Promote AgentCompany-New to the repository root and retire the old app
The legacy application - its src, tests, landing site, promo assets, docs, release tooling, CI workflows, and root configs - leaves the tree; it stays reachable in history. Everything under AgentCompany-New moves up unchanged: same package name, so the production userData/database path is untouched, and e2e/build scripts already resolved paths relative to the project. The developer cred.txt stays gitignored at its new location. Full verify:ci passes from the new root.
This commit is contained in:
1 parent
2350f744e3
commit
07d0b4587d
1904 files changed
+1133
-282075
No files matched your search
@@ -1,140 +0,0 @@
|
||||
export interface ApprovalDocumentReference {
|
||||
id: string
|
||||
title?: string
|
||||
type?: string
|
||||
}
|
||||
|
||||
export type ApprovalPayloadInspection =
|
||||
| { kind: "empty" }
|
||||
| { kind: "ok"; payload: Record<string, unknown> }
|
||||
| { kind: "malformed"; reason: string }
|
||||
|
||||
/**
|
||||
* Inspect an approval payloadJson and classify it. Unlike the tolerant
|
||||
* extractors (which collapse malformed rows to "no attachments"), this
|
||||
* returns an explicit "malformed" signal so the inspector can surface a
|
||||
* dignified error card instead of rendering as if nothing was attached.
|
||||
*
|
||||
* The HTTP route + file_approval tool both reject malformed payloads at
|
||||
* write time via mergeApprovalAttachments. This detector exists for the
|
||||
* read path, where a legacy row with a broken payload could otherwise
|
||||
* silently render as empty.
|
||||
*/
|
||||
export function inspectApprovalPayload(payloadJson: string | null | undefined): ApprovalPayloadInspection {
|
||||
if (payloadJson == null || payloadJson.length === 0) return { kind: "empty" }
|
||||
let parsed: unknown
|
||||
try {
|
||||
parsed = JSON.parse(payloadJson)
|
||||
} catch (error) {
|
||||
const detail = error instanceof Error ? error.message : String(error)
|
||||
return { kind: "malformed", reason: `payloadJson is not valid JSON (${detail})` }
|
||||
}
|
||||
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
||||
const actual = Array.isArray(parsed) ? "array" : parsed === null ? "null" : typeof parsed
|
||||
return { kind: "malformed", reason: `payloadJson must be a JSON object (got ${actual})` }
|
||||
}
|
||||
return { kind: "ok", payload: parsed as Record<string, unknown> }
|
||||
}
|
||||
|
||||
function parsePayload(payloadJson: string | null): Record<string, unknown> | null {
|
||||
if (!payloadJson) return null
|
||||
try {
|
||||
const parsed = JSON.parse(payloadJson)
|
||||
return parsed && typeof parsed === "object" && !Array.isArray(parsed)
|
||||
? parsed as Record<string, unknown>
|
||||
: null
|
||||
} catch {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract document references from an approval's persisted payloadJson.
|
||||
*
|
||||
* Priority order (canonical → legacy), with later sources providing
|
||||
* enrichment only for ids introduced by earlier sources:
|
||||
* 1. payload.documentIds — canonical schema top-level field (written by
|
||||
* mergeApprovalAttachments). This is the authoritative id set.
|
||||
* 2. payload.documentId / documentTitle / documentType — singular legacy
|
||||
* shape; kept for back-compat with old rows.
|
||||
* 3. payload.documents[] — legacy rich shape; used to enrich title/type
|
||||
* metadata on ids already present from the canonical list, and to
|
||||
* contribute ids that pre-date the canonical field.
|
||||
*/
|
||||
export function extractApprovalDocumentReferences(payloadJson: string | null): ApprovalDocumentReference[] {
|
||||
const payload = parsePayload(payloadJson)
|
||||
if (!payload) return []
|
||||
|
||||
const refs = new Map<string, ApprovalDocumentReference>()
|
||||
const addId = (id: unknown) => {
|
||||
if (typeof id !== "string" || id.length === 0) return
|
||||
if (!refs.has(id)) refs.set(id, { id })
|
||||
}
|
||||
const enrich = (id: unknown, title?: unknown, type?: unknown) => {
|
||||
if (typeof id !== "string" || id.length === 0) return
|
||||
const prior = refs.get(id) ?? { id }
|
||||
refs.set(id, {
|
||||
id,
|
||||
title: prior.title ?? (typeof title === "string" && title.length > 0 ? title : undefined),
|
||||
type: prior.type ?? (typeof type === "string" && type.length > 0 ? type : undefined),
|
||||
})
|
||||
}
|
||||
|
||||
// 1. Canonical top-level list first — establishes the authoritative ids.
|
||||
const documentIds = payload.documentIds
|
||||
if (Array.isArray(documentIds)) {
|
||||
for (const entry of documentIds) addId(entry)
|
||||
}
|
||||
|
||||
// 2. Legacy singular shape.
|
||||
enrich(payload.documentId, payload.documentTitle, payload.documentType)
|
||||
|
||||
// 3. Legacy rich shape — enriches metadata on canonical ids and adds
|
||||
// ids that only ever lived in the legacy form.
|
||||
const documents = payload.documents
|
||||
if (Array.isArray(documents)) {
|
||||
for (const entry of documents) {
|
||||
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue
|
||||
const record = entry as Record<string, unknown>
|
||||
enrich(record.id, record.title, record.type)
|
||||
}
|
||||
}
|
||||
|
||||
return [...refs.values()]
|
||||
}
|
||||
|
||||
export function extractApprovalDocumentIds(payloadJson: string | null): string[] {
|
||||
return extractApprovalDocumentReferences(payloadJson).map((entry) => entry.id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirror of extractApprovalDocumentReferences for work products. Work products
|
||||
* are filesystem-backed (or URL-backed) artifacts — the board inspector opens
|
||||
* them via the OS default handler rather than editing them inline.
|
||||
*
|
||||
* Canonical source is payload.workProductIds (schema top-level, folded in by
|
||||
* mergeApprovalAttachments). Legacy payload.workProducts[] is still read for
|
||||
* back-compat but new callers must not write it.
|
||||
*/
|
||||
export function extractApprovalWorkProductIds(payloadJson: string | null): string[] {
|
||||
const payload = parsePayload(payloadJson)
|
||||
if (!payload) return []
|
||||
const out = new Set<string>()
|
||||
// Canonical first.
|
||||
const workProductIds = payload.workProductIds
|
||||
if (Array.isArray(workProductIds)) {
|
||||
for (const entry of workProductIds) {
|
||||
if (typeof entry === "string" && entry.length > 0) out.add(entry)
|
||||
}
|
||||
}
|
||||
// Legacy rich shape; back-compat only.
|
||||
const workProducts = payload.workProducts
|
||||
if (Array.isArray(workProducts)) {
|
||||
for (const entry of workProducts) {
|
||||
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue
|
||||
const record = entry as Record<string, unknown>
|
||||
if (typeof record.id === "string" && record.id.length > 0) out.add(record.id)
|
||||
}
|
||||
}
|
||||
return [...out]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
export interface AuditReplayRunRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
threadId: string;
|
||||
eventCount: number;
|
||||
eventDigest: string;
|
||||
replayJson: string;
|
||||
createdByEmployeeId: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
export const CHAT_THREAD_BOARD_STATE = {
|
||||
OPEN: "open",
|
||||
FROZEN: "frozen",
|
||||
TAKEOVER: "takeover",
|
||||
} as const;
|
||||
|
||||
export const BOARD_INTERVENTION_MODE = {
|
||||
OBSERVE: "observe",
|
||||
INTERVENE: "intervene",
|
||||
TAKEOVER: "takeover",
|
||||
} as const;
|
||||
|
||||
export const BOARD_INTERVENTION_ACTION = {
|
||||
DECISION: "decision",
|
||||
FREEZE: "freeze",
|
||||
TAKEOVER: "takeover",
|
||||
ROLLBACK: "rollback",
|
||||
FORCE_APPROVAL: "force_approval",
|
||||
} as const;
|
||||
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export type ChatThreadBoardState = ValueOf<typeof CHAT_THREAD_BOARD_STATE>;
|
||||
export type BoardInterventionMode = ValueOf<typeof BOARD_INTERVENTION_MODE>;
|
||||
export type BoardInterventionAction = ValueOf<typeof BOARD_INTERVENTION_ACTION>;
|
||||
|
||||
export interface BoardInterventionRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
threadId: string;
|
||||
messageId: string;
|
||||
mode: BoardInterventionMode;
|
||||
action: BoardInterventionAction;
|
||||
details: string;
|
||||
targetType: "employee" | "agent" | "board" | null;
|
||||
targetId: string | null;
|
||||
approvalId: string | null;
|
||||
createdByType: "employee" | "agent" | "board" | "system";
|
||||
createdById: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import type { ChatThreadBoardState } from "./board-domain";
|
||||
|
||||
export interface ChatSpaceRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
spaceType: string;
|
||||
name: string;
|
||||
topic: string;
|
||||
visibility: string;
|
||||
retentionPolicy: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface ChatMessageRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
spaceId: string;
|
||||
threadId: string | null;
|
||||
senderType: "employee" | "agent" | "board" | "system";
|
||||
senderId: string | null;
|
||||
bodyMd: string;
|
||||
bodyStructuredJson: string;
|
||||
deliveryState: string;
|
||||
createdAt: string;
|
||||
editedAt: string | null;
|
||||
deletedAt: string | null;
|
||||
}
|
||||
|
||||
export interface ChatMembershipRecord {
|
||||
spaceId: string;
|
||||
principalType: "employee" | "agent";
|
||||
principalId: string;
|
||||
role: string;
|
||||
muteState: string;
|
||||
}
|
||||
|
||||
export interface ChatThreadRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
spaceId: string;
|
||||
rootMessageId: string | null;
|
||||
title: string;
|
||||
state: string;
|
||||
boardState: ChatThreadBoardState;
|
||||
controlledByType: "employee" | "agent" | "board" | null;
|
||||
controlledById: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ChatAttachmentRecord {
|
||||
messageId: string;
|
||||
fileId: string;
|
||||
transferType: string;
|
||||
checksum: string;
|
||||
previewKey: string | null;
|
||||
}
|
||||
|
||||
export interface ChatMentionRecord {
|
||||
messageId: string;
|
||||
targetType: "employee" | "agent" | "board" | "org_group";
|
||||
targetId: string;
|
||||
offsetStart: number;
|
||||
offsetEnd: number;
|
||||
wakeState: "none" | "woken" | "failed";
|
||||
}
|
||||
|
||||
export interface ChatSlashInvocationRecord {
|
||||
id: string;
|
||||
messageId: string;
|
||||
command: string;
|
||||
argsJson: string;
|
||||
resultRef: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface ChatPresenceRecord {
|
||||
principalType: string;
|
||||
principalId: string;
|
||||
status: string;
|
||||
statusText: string;
|
||||
lastSeenAt: string;
|
||||
}
|
||||
|
||||
export interface ChatReadStateRecord {
|
||||
orgId: string;
|
||||
employeeId: string;
|
||||
spaceId: string;
|
||||
lastReadMessageId: string | null;
|
||||
lastReadAt: string;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
export interface SendMessageInput {
|
||||
orgId: string;
|
||||
spaceId: string;
|
||||
threadId: string | null;
|
||||
senderType: "employee" | "agent" | "board" | "system";
|
||||
senderId: string | null;
|
||||
bodyMd: string;
|
||||
attachmentFileIds?: string[];
|
||||
}
|
||||
|
||||
export interface EditMessageInput {
|
||||
orgId: string;
|
||||
messageId: string;
|
||||
actorType: SendMessageInput["senderType"];
|
||||
actorId: string | null;
|
||||
bodyMd: string;
|
||||
}
|
||||
|
||||
export interface DeleteMessageInput {
|
||||
orgId: string;
|
||||
messageId: string;
|
||||
actorType: SendMessageInput["senderType"];
|
||||
actorId: string | null;
|
||||
}
|
||||
|
||||
export interface CreateChatSpaceInput {
|
||||
orgId: string;
|
||||
spaceType: "company" | "division" | "department" | "project" | "pod" | "ad_hoc" | "direct";
|
||||
name: string;
|
||||
topic: string;
|
||||
visibility: "workspace" | "restricted";
|
||||
retentionPolicy?: "standard_365d" | "restricted_365d";
|
||||
memberEmployeeIds?: string[];
|
||||
memberAgentIds?: string[];
|
||||
}
|
||||
|
||||
export interface MarkChatSpaceReadInput {
|
||||
orgId: string;
|
||||
employeeId: string;
|
||||
spaceId: string;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
export interface CreateDocumentInput {
|
||||
orgId: string;
|
||||
title: string;
|
||||
docType: string;
|
||||
content: string;
|
||||
authorAgentId: string | null;
|
||||
reviewerAgentId: string | null;
|
||||
projectId: string | null;
|
||||
goalId: string | null;
|
||||
taskId: string | null;
|
||||
}
|
||||
|
||||
export interface UpdateDocumentInput {
|
||||
orgId: string;
|
||||
documentId: string;
|
||||
title: string;
|
||||
content: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface DeleteDocumentInput {
|
||||
orgId: string;
|
||||
documentId: string;
|
||||
}
|
||||
|
||||
export interface CreateKnowledgeEntryInput {
|
||||
orgId: string;
|
||||
topic: string;
|
||||
category: string;
|
||||
content: string;
|
||||
importance: string;
|
||||
sourceType: string;
|
||||
sourceId: string | null;
|
||||
}
|
||||
|
||||
export interface DeleteKnowledgeEntryInput {
|
||||
orgId: string;
|
||||
entryId: string;
|
||||
}
|
||||
|
||||
export interface CreateAutomationRuleInput {
|
||||
orgId: string;
|
||||
name: string;
|
||||
triggerEvent: string;
|
||||
conditions: Record<string, unknown>;
|
||||
actionType: string;
|
||||
actionConfig: Record<string, unknown>;
|
||||
priority: number;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface UpdateAutomationRuleInput {
|
||||
orgId: string;
|
||||
ruleId: string;
|
||||
name: string;
|
||||
triggerEvent: string;
|
||||
conditions: Record<string, unknown>;
|
||||
actionType: string;
|
||||
actionConfig: Record<string, unknown>;
|
||||
priority: number;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface DeleteAutomationRuleInput {
|
||||
orgId: string;
|
||||
ruleId: string;
|
||||
}
|
||||
|
||||
export interface CreateMeetingInput {
|
||||
orgId: string;
|
||||
title: string;
|
||||
meetingType: string;
|
||||
scheduledAt: string | null;
|
||||
durationMinutes: number;
|
||||
agenda: string;
|
||||
}
|
||||
|
||||
export interface DeleteMeetingInput {
|
||||
orgId: string;
|
||||
meetingId: string;
|
||||
}
|
||||
|
||||
export interface CreateSprintInput {
|
||||
orgId: string;
|
||||
name: string;
|
||||
goal: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
}
|
||||
|
||||
export interface DeleteSprintInput {
|
||||
orgId: string;
|
||||
sprintId: string;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
export interface SaveComposioSettingsInput {
|
||||
orgId: string;
|
||||
apiKey: string;
|
||||
toolkits: string[];
|
||||
}
|
||||
|
||||
export interface ComposioToolkitSummaryDto {
|
||||
slug: string;
|
||||
name: string;
|
||||
description: string;
|
||||
logo: string | null;
|
||||
categories: string[];
|
||||
authSchemes: string[];
|
||||
noAuth: boolean;
|
||||
toolsCount: number;
|
||||
}
|
||||
|
||||
export interface ListComposioToolkitsInput {
|
||||
orgId: string;
|
||||
}
|
||||
|
||||
export interface ConnectComposioToolkitInput {
|
||||
orgId: string;
|
||||
toolkitSlug: string;
|
||||
toolkitName: string;
|
||||
}
|
||||
|
||||
export interface ConnectComposioToolkitResult {
|
||||
accountId: string;
|
||||
status: string;
|
||||
redirectUrl: string | null;
|
||||
}
|
||||
|
||||
export interface RefreshComposioAccountsInput {
|
||||
orgId: string;
|
||||
}
|
||||
|
||||
export interface ConnectorGrantInput {
|
||||
orgId: string;
|
||||
agentId: string;
|
||||
toolkitSlug: string;
|
||||
employeeId: string;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
export interface ImportFileInput {
|
||||
orgId: string;
|
||||
}
|
||||
|
||||
export interface OpenFileInput {
|
||||
orgId: string;
|
||||
fileId: string;
|
||||
}
|
||||
|
||||
export interface SetFilePinnedInput {
|
||||
orgId: string;
|
||||
fileId: string;
|
||||
pinned: boolean;
|
||||
}
|
||||
|
||||
export interface NativeDialogResult {
|
||||
canceled: boolean;
|
||||
filePaths: string[];
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
import type {
|
||||
ComplianceExportType,
|
||||
ComplianceSubjectType,
|
||||
LegalHoldEntityType,
|
||||
RetentionFreezeScopeType,
|
||||
SdlcReviewTargetType,
|
||||
} from "../domain";
|
||||
|
||||
export interface CreateMigrationReportInput {
|
||||
orgId: string;
|
||||
sourceDatabasePath: string;
|
||||
}
|
||||
|
||||
export interface CreateRollbackSnapshotInput {
|
||||
orgId: string;
|
||||
migrationReportId: string;
|
||||
createdByEmployeeId: string;
|
||||
}
|
||||
|
||||
export interface SetRollbackSnapshotActiveInput {
|
||||
orgId: string;
|
||||
snapshotId: string;
|
||||
active: boolean;
|
||||
employeeId: string;
|
||||
}
|
||||
|
||||
export interface ResolveMigrationReconciliationInput {
|
||||
orgId: string;
|
||||
reconciliationItemId: string;
|
||||
employeeId: string;
|
||||
}
|
||||
|
||||
export interface CreateComplianceExportInput {
|
||||
orgId: string;
|
||||
subjectType: ComplianceSubjectType;
|
||||
subjectId: string;
|
||||
exportType: ComplianceExportType;
|
||||
requestedByEmployeeId: string;
|
||||
}
|
||||
|
||||
export interface CreateAuditReplayInput {
|
||||
orgId: string;
|
||||
threadId: string;
|
||||
createdByEmployeeId: string;
|
||||
}
|
||||
|
||||
export interface CreateLegalHoldInput {
|
||||
orgId: string;
|
||||
entityType: LegalHoldEntityType;
|
||||
entityId: string;
|
||||
reason: string;
|
||||
createdByEmployeeId: string;
|
||||
}
|
||||
|
||||
export interface SetLegalHoldStateInput {
|
||||
orgId: string;
|
||||
legalHoldId: string;
|
||||
active: boolean;
|
||||
employeeId: string;
|
||||
}
|
||||
|
||||
export interface CreateRetentionFreezeInput {
|
||||
orgId: string;
|
||||
scopeType: RetentionFreezeScopeType;
|
||||
scopeId: string;
|
||||
reason: string;
|
||||
createdByEmployeeId: string;
|
||||
}
|
||||
|
||||
export interface SetRetentionFreezeStateInput {
|
||||
orgId: string;
|
||||
retentionFreezeId: string;
|
||||
active: boolean;
|
||||
employeeId: string;
|
||||
}
|
||||
|
||||
export interface SetFeatureFlagInput {
|
||||
orgId: string;
|
||||
flagId: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface RunChaosDrillInput {
|
||||
orgId: string;
|
||||
drillId: string;
|
||||
}
|
||||
|
||||
export interface RunSdlcReviewInput {
|
||||
orgId: string;
|
||||
reviewAgentId: string;
|
||||
targetType: SdlcReviewTargetType;
|
||||
targetRef: string;
|
||||
}
|
||||
|
||||
export interface RunEvalSuiteInput {
|
||||
orgId: string;
|
||||
suiteId: string;
|
||||
}
|
||||
|
||||
export interface SetPrBotGateInput {
|
||||
orgId: string;
|
||||
gateId: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
export * from "./organization";
|
||||
export * from "./chat";
|
||||
export * from "./provider";
|
||||
export * from "./skills";
|
||||
export * from "./social";
|
||||
export * from "./files";
|
||||
export * from "./governance";
|
||||
export * from "./collaboration";
|
||||
export * from "./onboarding";
|
||||
export * from "./composio";
|
||||
@@ -0,0 +1,36 @@
|
||||
import type { SearchEntityType } from "../domain";
|
||||
|
||||
export interface BootstrapOnboardingInput {
|
||||
companyName: string;
|
||||
companyDescription: string;
|
||||
employeeName: string;
|
||||
workspacePath: string;
|
||||
executionMode: "ai_ceo" | "ai_cofounder";
|
||||
autoApproveHires: boolean;
|
||||
reviewDeliverables: boolean;
|
||||
goalTitle: string;
|
||||
goalDescription: string;
|
||||
providerKey: string;
|
||||
providerSecret: string;
|
||||
providerModel: string;
|
||||
}
|
||||
|
||||
export interface BootstrapOnboardingSummary {
|
||||
orgId: string;
|
||||
employeeId: string;
|
||||
ceoAgentId: string;
|
||||
workspaceId: string | null;
|
||||
goalId: string;
|
||||
projectId: string;
|
||||
taskId: string;
|
||||
runId: string;
|
||||
providerId: string;
|
||||
}
|
||||
|
||||
export interface SearchInput {
|
||||
orgId: string;
|
||||
employeeId: string;
|
||||
query: string;
|
||||
entityTypes?: SearchEntityType[];
|
||||
limit?: number;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
import type { ApprovalState, IdentitySource, PrincipalType, RiskLevel, RoleKey, TaskPriority, TaskStatus } from "../domain";
|
||||
|
||||
export interface SetActiveOrganizationInput {
|
||||
orgId: string;
|
||||
}
|
||||
|
||||
export interface DeleteOrganizationInput {
|
||||
orgId: string;
|
||||
}
|
||||
|
||||
export interface CreateOrganizationInput {
|
||||
organizationName: string;
|
||||
description?: string;
|
||||
mission: string;
|
||||
goal: string;
|
||||
employeeName: string;
|
||||
executionMode?: "ai_ceo" | "ai_cofounder";
|
||||
autoApproveHires?: boolean;
|
||||
reviewDeliverables?: boolean;
|
||||
}
|
||||
|
||||
export interface UpdateAgentInput {
|
||||
orgId: string;
|
||||
agentId: string;
|
||||
role: string;
|
||||
title: string;
|
||||
roleLevel: string;
|
||||
department: string;
|
||||
budgetCents: number;
|
||||
modelProviderId: string | null;
|
||||
modelId: string | null;
|
||||
}
|
||||
|
||||
export interface CreateAgentInput {
|
||||
orgId: string;
|
||||
name: string;
|
||||
role: string;
|
||||
department: string;
|
||||
modelProviderId: string | null;
|
||||
modelId: string | null;
|
||||
budgetCents: number;
|
||||
managerAgentId: string | null;
|
||||
title?: string;
|
||||
roleLevel?: string;
|
||||
modelStrategy?: string;
|
||||
workspaceId?: string | null;
|
||||
heartbeatEnabled?: boolean;
|
||||
heartbeatIntervalSec?: number;
|
||||
}
|
||||
|
||||
export interface CreateTaskInput {
|
||||
orgId: string;
|
||||
title: string;
|
||||
description: string;
|
||||
status: TaskStatus;
|
||||
assigneeAgentId: string | null;
|
||||
risk: RiskLevel;
|
||||
projectId: string | null;
|
||||
goalId: string | null;
|
||||
workspaceId: string | null;
|
||||
priority: TaskPriority;
|
||||
requiresFilesystem: boolean;
|
||||
}
|
||||
|
||||
export interface UpdateTaskStatusInput {
|
||||
orgId: string;
|
||||
taskId: string;
|
||||
status: TaskStatus;
|
||||
}
|
||||
|
||||
export interface RunTaskInput {
|
||||
orgId: string;
|
||||
taskId: string;
|
||||
}
|
||||
|
||||
export interface UpdateTaskInput {
|
||||
orgId: string;
|
||||
taskId: string;
|
||||
title: string;
|
||||
description: string;
|
||||
assigneeAgentId: string | null;
|
||||
risk: RiskLevel;
|
||||
priority: TaskPriority;
|
||||
parentTaskId: string | null;
|
||||
}
|
||||
|
||||
export interface DeleteTaskInput {
|
||||
orgId: string;
|
||||
taskId: string;
|
||||
}
|
||||
|
||||
export interface CreateGoalInput {
|
||||
orgId: string;
|
||||
title: string;
|
||||
description: string;
|
||||
ownerAgentId: string | null;
|
||||
}
|
||||
|
||||
export interface CreateProjectInput {
|
||||
orgId: string;
|
||||
goalId: string | null;
|
||||
name: string;
|
||||
description: string;
|
||||
leadAgentId: string | null;
|
||||
}
|
||||
|
||||
export interface CreateWorkspaceInput {
|
||||
orgId: string;
|
||||
name: string;
|
||||
localPath: string;
|
||||
projectId: string | null;
|
||||
}
|
||||
|
||||
export interface CreateApprovalInput {
|
||||
orgId: string;
|
||||
kind: string;
|
||||
title: string;
|
||||
details: string;
|
||||
risk: RiskLevel;
|
||||
requestedByType: "employee" | "agent" | "system";
|
||||
requestedById: string | null;
|
||||
}
|
||||
|
||||
export interface DecideApprovalInput {
|
||||
orgId: string;
|
||||
approvalId: string;
|
||||
state: Extract<ApprovalState, "approved" | "declined">;
|
||||
decidedByEmployeeId: string;
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
export interface SyncEmployeeIdentityInput {
|
||||
orgId: string;
|
||||
employeeId: string;
|
||||
source: IdentitySource;
|
||||
externalSubject: string;
|
||||
email: string | null;
|
||||
}
|
||||
|
||||
export interface GrantRoleInput {
|
||||
orgId: string;
|
||||
principalType: PrincipalType;
|
||||
principalId: string;
|
||||
roleKey: RoleKey;
|
||||
scopeType: "organization" | "workspace" | "project" | "department";
|
||||
scopeId: string;
|
||||
grantedByEmployeeId: string;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
import type { ProviderDataPolicy, ProviderExecutionMode } from "../domain";
|
||||
|
||||
export interface SaveProviderCredentialInput {
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
secret: string;
|
||||
model: string | null;
|
||||
employeeId?: string | null;
|
||||
}
|
||||
|
||||
export interface RevokeProviderCredentialInput {
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
}
|
||||
|
||||
export interface LaunchProviderSignInInput {
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
employeeId: string;
|
||||
}
|
||||
|
||||
export interface StartProviderOAuthInput {
|
||||
providerKey: string;
|
||||
enterpriseDomain?: string | null;
|
||||
/** Present when connecting an existing org's provider (Settings); absent
|
||||
* during onboarding, where the obtained credential is returned to the caller. */
|
||||
orgId?: string;
|
||||
providerId?: string;
|
||||
employeeId?: string;
|
||||
model?: string | null;
|
||||
}
|
||||
|
||||
export interface StartProviderOAuthResult {
|
||||
/** The obtained credential JSON when no org context was supplied, else null
|
||||
* (the credential was already stored). */
|
||||
secret: string | null;
|
||||
}
|
||||
|
||||
export interface CancelProviderOAuthInput {
|
||||
providerKey: string;
|
||||
}
|
||||
|
||||
export interface CheckProviderHealthInput {
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
}
|
||||
|
||||
export interface ListProviderModelsInput {
|
||||
providerKey: string;
|
||||
/** A just-typed/authorized credential (onboarding or the connect-new dialog). */
|
||||
secret?: string;
|
||||
/** A stored provider whose secret is decrypted server-side (settings refresh). */
|
||||
orgId?: string;
|
||||
providerId?: string;
|
||||
}
|
||||
|
||||
export interface UpdateProviderPolicyInput {
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
dataPolicy: ProviderDataPolicy;
|
||||
backgroundEnabled: boolean;
|
||||
monthlyRequestLimit: number;
|
||||
workspaceScope: "organization" | "workspace";
|
||||
}
|
||||
|
||||
export interface CreateProviderResponseInput {
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
workspaceId?: string | null;
|
||||
prompt: string;
|
||||
instructions: string | null;
|
||||
executionMode?: ProviderExecutionMode;
|
||||
}
|
||||
|
||||
export type StreamProviderResponseInput = CreateProviderResponseInput;
|
||||
|
||||
export interface CancelProviderResponseInput {
|
||||
orgId: string;
|
||||
requestId: string;
|
||||
providerResponseId?: string;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
export interface ImportSkillDirectoryInput {
|
||||
orgId: string;
|
||||
directoryPath: string;
|
||||
versionSemver: string;
|
||||
}
|
||||
|
||||
export interface BindSkillInput {
|
||||
orgId: string;
|
||||
agentId: string;
|
||||
skillId: string;
|
||||
revisionId: string;
|
||||
}
|
||||
|
||||
export interface ResolveAgentSkillsInput {
|
||||
orgId: string;
|
||||
agentId: string;
|
||||
runId: string;
|
||||
}
|
||||
|
||||
export interface RunSkillTestsInput {
|
||||
orgId: string;
|
||||
revisionId: string;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import type { SocialPlatform } from "../domain";
|
||||
|
||||
export interface CreateSocialAccountInput {
|
||||
orgId: string;
|
||||
platform: SocialPlatform;
|
||||
handle: string;
|
||||
displayName: string;
|
||||
createdByEmployeeId: string;
|
||||
authorizedEmployeeId: string | null;
|
||||
}
|
||||
|
||||
export interface LaunchSocialLoginInput {
|
||||
orgId: string;
|
||||
socialAccountId: string;
|
||||
employeeId: string;
|
||||
}
|
||||
|
||||
export interface CreateScheduledPostInput {
|
||||
orgId: string;
|
||||
socialAccountId: string;
|
||||
bodyMd: string;
|
||||
scheduledFor: string;
|
||||
createdByEmployeeId: string;
|
||||
}
|
||||
|
||||
export interface SetScheduledPostStateInput {
|
||||
orgId: string;
|
||||
scheduledPostId: string;
|
||||
state: "draft" | "scheduled" | "published" | "cancelled";
|
||||
employeeId: string;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
export const COMPLIANCE_EXPORT_TYPE = {
|
||||
GDPR_EXPORT: "gdpr_export",
|
||||
GDPR_DELETE: "gdpr_delete",
|
||||
} as const;
|
||||
|
||||
export const COMPLIANCE_EXPORT_STATE = {
|
||||
COMPLETED: "completed",
|
||||
} as const;
|
||||
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export type ComplianceExportType = ValueOf<typeof COMPLIANCE_EXPORT_TYPE>;
|
||||
export type ComplianceExportState = ValueOf<typeof COMPLIANCE_EXPORT_STATE>;
|
||||
export type ComplianceSubjectType = "employee" | "agent";
|
||||
export type LegalHoldEntityType = "organization" | "employee" | "agent" | "chat_thread" | "file_object";
|
||||
export type RetentionFreezeScopeType = "organization" | "chat_space" | "file_object";
|
||||
|
||||
export interface ComplianceExportRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
subjectType: ComplianceSubjectType;
|
||||
subjectId: string;
|
||||
exportType: ComplianceExportType;
|
||||
state: ComplianceExportState;
|
||||
payloadJson: string;
|
||||
requestedByEmployeeId: string | null;
|
||||
createdAt: string;
|
||||
completedAt: string | null;
|
||||
}
|
||||
|
||||
export interface LegalHoldRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
entityType: LegalHoldEntityType;
|
||||
entityId: string;
|
||||
reason: string;
|
||||
createdByEmployeeId: string | null;
|
||||
active: boolean;
|
||||
createdAt: string;
|
||||
releasedAt: string | null;
|
||||
}
|
||||
|
||||
export interface RetentionFreezeRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
scopeType: RetentionFreezeScopeType;
|
||||
scopeId: string;
|
||||
reason: string;
|
||||
createdByEmployeeId: string | null;
|
||||
active: boolean;
|
||||
createdAt: string;
|
||||
releasedAt: string | null;
|
||||
}
|
||||
@@ -1,312 +0,0 @@
|
||||
/**
|
||||
* Renderer-visible pi-mono connector catalog.
|
||||
*
|
||||
* Mirrors the authoritative definitions in `src/main/connector-definitions*.ts`
|
||||
* so the renderer can drive UI from the same 26-entry list without importing
|
||||
* Node/main-process modules. Keep this file in strict lockstep with the main
|
||||
* catalog when new connectors are added.
|
||||
*/
|
||||
|
||||
import type { ConnectorId } from "./types/enums";
|
||||
|
||||
export type PiOAuthProviderId =
|
||||
| "anthropic"
|
||||
| "openai-codex"
|
||||
| "github-copilot"
|
||||
| "google-gemini-cli"
|
||||
| "google-antigravity";
|
||||
|
||||
export type ConnectorAuthKind = "oauth" | "api_key" | "aws" | "azure" | "gcp_adc" | "local";
|
||||
|
||||
export interface ConnectorAuthOAuth { type: "oauth"; oauthId: PiOAuthProviderId }
|
||||
export interface ConnectorAuthApiKey { type: "api_key"; envKey: string }
|
||||
export interface ConnectorAuthAws { type: "aws" }
|
||||
export interface ConnectorAuthAzure { type: "azure" }
|
||||
export interface ConnectorAuthGcpAdc { type: "gcp_adc" }
|
||||
export interface ConnectorAuthLocal { type: "local"; defaultBaseUrl: string }
|
||||
|
||||
export type ConnectorAuth =
|
||||
| ConnectorAuthOAuth
|
||||
| ConnectorAuthApiKey
|
||||
| ConnectorAuthAws
|
||||
| ConnectorAuthAzure
|
||||
| ConnectorAuthGcpAdc
|
||||
| ConnectorAuthLocal;
|
||||
|
||||
export interface ConnectorCatalogEntry {
|
||||
id: ConnectorId;
|
||||
provider: string;
|
||||
label: string;
|
||||
description: string;
|
||||
defaultModel: string;
|
||||
auth: ConnectorAuth;
|
||||
onboardingFeatured?: boolean;
|
||||
notes?: string;
|
||||
}
|
||||
|
||||
const OAUTH_ENTRIES: ConnectorCatalogEntry[] = [
|
||||
{
|
||||
id: "claude-pro",
|
||||
provider: "anthropic",
|
||||
label: "Claude Pro/Max",
|
||||
description: "Anthropic Claude via Claude Pro / Max subscription OAuth.",
|
||||
defaultModel: "claude-sonnet-4-5",
|
||||
auth: { type: "oauth", oauthId: "anthropic" },
|
||||
onboardingFeatured: true,
|
||||
notes: "Requires an active Claude Pro or Max subscription. Tokens refresh automatically.",
|
||||
},
|
||||
{
|
||||
id: "openai-codex",
|
||||
provider: "openai-codex",
|
||||
label: "ChatGPT Plus/Pro (Codex)",
|
||||
description: "OpenAI Codex via a ChatGPT Plus or Pro subscription.",
|
||||
defaultModel: "gpt-5.3-codex",
|
||||
auth: { type: "oauth", oauthId: "openai-codex" },
|
||||
onboardingFeatured: true,
|
||||
notes: "Personal use only; requires ChatGPT Plus or Pro.",
|
||||
},
|
||||
{
|
||||
id: "github-copilot",
|
||||
provider: "github-copilot",
|
||||
label: "GitHub Copilot",
|
||||
description: "Models exposed through a GitHub Copilot subscription.",
|
||||
defaultModel: "claude-opus-4.5",
|
||||
auth: { type: "oauth", oauthId: "github-copilot" },
|
||||
notes: "Supports github.com and GitHub Enterprise Server.",
|
||||
},
|
||||
{
|
||||
id: "gemini-cli",
|
||||
provider: "google-gemini-cli",
|
||||
label: "Google Gemini CLI",
|
||||
description: "Google Gemini models via Cloud Code Assist OAuth. Free tier works with any Google account.",
|
||||
defaultModel: "gemini-2.5-pro",
|
||||
auth: { type: "oauth", oauthId: "google-gemini-cli" },
|
||||
notes: "For paid Cloud Code Assist, set GOOGLE_CLOUD_PROJECT.",
|
||||
},
|
||||
{
|
||||
id: "antigravity",
|
||||
provider: "google-antigravity",
|
||||
label: "Google Antigravity",
|
||||
description: "Google Antigravity sandbox with Gemini 3, Claude, and GPT-OSS models.",
|
||||
defaultModel: "claude-sonnet-4-5",
|
||||
auth: { type: "oauth", oauthId: "google-antigravity" },
|
||||
notes: "Free with any Google account.",
|
||||
},
|
||||
];
|
||||
|
||||
const API_KEY_ENTRIES: ConnectorCatalogEntry[] = [
|
||||
{
|
||||
id: "anthropic",
|
||||
provider: "anthropic",
|
||||
label: "Anthropic API",
|
||||
description: "Direct Anthropic Messages API for production workloads.",
|
||||
defaultModel: "claude-sonnet-4-5",
|
||||
auth: { type: "api_key", envKey: "ANTHROPIC_API_KEY" },
|
||||
onboardingFeatured: true,
|
||||
},
|
||||
{
|
||||
id: "openai",
|
||||
provider: "openai",
|
||||
label: "OpenAI API",
|
||||
description: "OpenAI Responses + Chat Completions endpoints. GPT-5 family and Codex deployments.",
|
||||
defaultModel: "gpt-5.4",
|
||||
auth: { type: "api_key", envKey: "OPENAI_API_KEY" },
|
||||
onboardingFeatured: true,
|
||||
},
|
||||
{
|
||||
id: "google",
|
||||
provider: "google",
|
||||
label: "Google Gemini API",
|
||||
description: "Google Gemini Generative Language API using the standard GEMINI_API_KEY variable.",
|
||||
defaultModel: "gemini-2.5-pro",
|
||||
auth: { type: "api_key", envKey: "GEMINI_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "mistral",
|
||||
provider: "mistral",
|
||||
label: "Mistral",
|
||||
description: "Mistral La Plateforme — Codestral, Devstral, Mistral Medium/Large families.",
|
||||
defaultModel: "mistral-medium-latest",
|
||||
auth: { type: "api_key", envKey: "MISTRAL_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "groq",
|
||||
provider: "groq",
|
||||
label: "Groq",
|
||||
description: "Groq LPU cloud. High-throughput inference for Llama 3, Qwen, DeepSeek, Groq Compound.",
|
||||
defaultModel: "groq/compound",
|
||||
auth: { type: "api_key", envKey: "GROQ_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "cerebras",
|
||||
provider: "cerebras",
|
||||
label: "Cerebras",
|
||||
description: "Cerebras Inference cloud — wafer-scale hardware for Qwen, Llama, GPT-OSS.",
|
||||
defaultModel: "qwen-3-235b-a22b-instruct-2507",
|
||||
auth: { type: "api_key", envKey: "CEREBRAS_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "xai",
|
||||
provider: "xai",
|
||||
label: "xAI",
|
||||
description: "xAI Grok API including Grok 4 Fast and Grok Code Fast.",
|
||||
defaultModel: "grok-4-fast",
|
||||
auth: { type: "api_key", envKey: "XAI_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "openrouter",
|
||||
provider: "openrouter",
|
||||
label: "OpenRouter",
|
||||
description: "OpenRouter aggregator — Anthropic, OpenAI, Google, open-weights through one key.",
|
||||
defaultModel: "anthropic/claude-sonnet-4.5",
|
||||
auth: { type: "api_key", envKey: "OPENROUTER_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "vercel-ai-gateway",
|
||||
provider: "vercel-ai-gateway",
|
||||
label: "Vercel AI Gateway",
|
||||
description: "Vercel multi-provider proxy using provider/model slugs on one billing profile.",
|
||||
defaultModel: "anthropic/claude-sonnet-4.5",
|
||||
auth: { type: "api_key", envKey: "AI_GATEWAY_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "zai",
|
||||
provider: "zai",
|
||||
label: "Z.AI",
|
||||
description: "Z.AI GLM-4.5/4.6 family — coding-tuned Chinese models with tool use.",
|
||||
defaultModel: "glm-4.6",
|
||||
auth: { type: "api_key", envKey: "ZAI_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "opencode",
|
||||
provider: "opencode",
|
||||
label: "OpenCode Zen",
|
||||
description: "OpenCode Zen managed endpoint. Shares OPENCODE_API_KEY with OpenCode Go.",
|
||||
defaultModel: "claude-sonnet-4.5",
|
||||
auth: { type: "api_key", envKey: "OPENCODE_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "opencode-go",
|
||||
provider: "opencode-go",
|
||||
label: "OpenCode Go",
|
||||
description: "OpenCode Go managed endpoint. Shares OPENCODE_API_KEY with OpenCode Zen.",
|
||||
defaultModel: "kimi-k2.5",
|
||||
auth: { type: "api_key", envKey: "OPENCODE_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "huggingface",
|
||||
provider: "huggingface",
|
||||
label: "Hugging Face",
|
||||
description: "Hugging Face Inference Endpoints — Kimi K2, GLM, DeepSeek, MiniMax, open-weights.",
|
||||
defaultModel: "moonshotai/Kimi-K2.5",
|
||||
auth: { type: "api_key", envKey: "HF_TOKEN" },
|
||||
},
|
||||
{
|
||||
id: "kimi-coding",
|
||||
provider: "kimi-coding",
|
||||
label: "Kimi For Coding",
|
||||
description: "Moonshot AI Kimi For Coding endpoint — tuned for agentic coding workloads.",
|
||||
defaultModel: "kimi-for-coding",
|
||||
auth: { type: "api_key", envKey: "KIMI_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "minimax",
|
||||
provider: "minimax",
|
||||
label: "MiniMax",
|
||||
description: "MiniMax international endpoint for M2 coding models.",
|
||||
defaultModel: "MiniMax-M2.7",
|
||||
auth: { type: "api_key", envKey: "MINIMAX_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "minimax-cn",
|
||||
provider: "minimax-cn",
|
||||
label: "MiniMax (China)",
|
||||
description: "MiniMax mainland China endpoint. Separate key from the international tier.",
|
||||
defaultModel: "MiniMax-M2.7",
|
||||
auth: { type: "api_key", envKey: "MINIMAX_CN_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "fireworks",
|
||||
provider: "fireworks",
|
||||
label: "Fireworks AI",
|
||||
description: "Fireworks inference cloud — Kimi K2.5 Turbo and more.",
|
||||
defaultModel: "accounts/fireworks/models/kimi-k2.5-turbo",
|
||||
auth: { type: "api_key", envKey: "FIREWORKS_API_KEY" },
|
||||
},
|
||||
{
|
||||
id: "fireworks-firepass",
|
||||
provider: "fireworks-firepass",
|
||||
label: "Fireworks Fire Pass",
|
||||
description: "Fireworks Fire Pass — subscription bundle. Same FIREWORKS_API_KEY.",
|
||||
defaultModel: "accounts/fireworks/routers/kimi-k2p6-turbo",
|
||||
auth: { type: "api_key", envKey: "FIREWORKS_API_KEY" },
|
||||
notes: "Fire Pass uses the dedicated router id accounts/fireworks/routers/kimi-k2p6-turbo documented at docs.fireworks.ai/firepass.",
|
||||
},
|
||||
];
|
||||
|
||||
const LOCAL_ENTRIES: ConnectorCatalogEntry[] = [
|
||||
{
|
||||
id: "ollama",
|
||||
provider: "ollama",
|
||||
label: "Ollama",
|
||||
description: "Local Ollama server — open-weights models on your own machine via the OpenAI-compatible endpoint.",
|
||||
defaultModel: "llama3.2",
|
||||
auth: { type: "local", defaultBaseUrl: "http://localhost:11434/v1" },
|
||||
notes: "Default port 11434. Override with a loopback or private-network address.",
|
||||
},
|
||||
{
|
||||
id: "lm-studio",
|
||||
provider: "lm-studio",
|
||||
label: "LM Studio",
|
||||
description: "Local LM Studio server — host any loaded model via the OpenAI-compatible endpoint.",
|
||||
defaultModel: "local-model",
|
||||
auth: { type: "local", defaultBaseUrl: "http://localhost:1234/v1" },
|
||||
notes: "Enable LM Studio's local server from the Developer tab. Use a loopback or private-network address.",
|
||||
},
|
||||
];
|
||||
|
||||
const CLOUD_ENTRIES: ConnectorCatalogEntry[] = [
|
||||
{
|
||||
id: "amazon-bedrock",
|
||||
provider: "amazon-bedrock",
|
||||
label: "AWS Bedrock",
|
||||
description: "Anthropic, Amazon Nova, and Llama models served through AWS Bedrock.",
|
||||
defaultModel: "us.anthropic.claude-sonnet-4-20250514-v1:0",
|
||||
auth: { type: "aws" },
|
||||
onboardingFeatured: true,
|
||||
notes: "Honours standard AWS credential discovery. Region defaults to us-east-1.",
|
||||
},
|
||||
{
|
||||
id: "azure-openai",
|
||||
provider: "azure-openai-responses",
|
||||
label: "Azure OpenAI",
|
||||
description: "Azure-hosted OpenAI deployments via the Responses API.",
|
||||
defaultModel: "gpt-5.4",
|
||||
auth: { type: "azure" },
|
||||
notes: "Provide AZURE_OPENAI_API_KEY plus AZURE_OPENAI_BASE_URL or AZURE_OPENAI_RESOURCE_NAME.",
|
||||
},
|
||||
{
|
||||
id: "google-vertex",
|
||||
provider: "google-vertex",
|
||||
label: "Google Vertex AI",
|
||||
description: "Gemini, Claude, and third-party models on Google Vertex AI using ADC.",
|
||||
defaultModel: "gemini-2.5-pro",
|
||||
auth: { type: "gcp_adc" },
|
||||
notes: "Set GOOGLE_CLOUD_PROJECT and GOOGLE_CLOUD_LOCATION.",
|
||||
},
|
||||
];
|
||||
|
||||
export const CONNECTOR_CATALOG: ConnectorCatalogEntry[] = [
|
||||
...OAUTH_ENTRIES,
|
||||
...API_KEY_ENTRIES,
|
||||
...CLOUD_ENTRIES,
|
||||
...LOCAL_ENTRIES,
|
||||
];
|
||||
|
||||
export function findConnectorCatalogEntry(id: string): ConnectorCatalogEntry | undefined {
|
||||
return CONNECTOR_CATALOG.find((entry) => entry.id === id);
|
||||
}
|
||||
|
||||
export function listFeaturedOnboardingConnectors(): ConnectorCatalogEntry[] {
|
||||
return CONNECTOR_CATALOG.filter((entry) => entry.onboardingFeatured === true);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
export interface ConnectorModelEntry {
|
||||
id: string;
|
||||
label: string;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
function dedupeById(entries: Array<{ id: string; label: string; enabled: boolean }>) {
|
||||
const seen = new Map<string, ConnectorModelEntry>();
|
||||
for (const entry of entries) {
|
||||
if (!entry.id.trim()) continue;
|
||||
const existing = seen.get(entry.id);
|
||||
if (!existing) {
|
||||
seen.set(entry.id, { ...entry, id: entry.id.trim() });
|
||||
continue;
|
||||
}
|
||||
seen.set(entry.id, {
|
||||
...existing,
|
||||
label: existing.label || entry.label,
|
||||
enabled: existing.enabled || entry.enabled,
|
||||
});
|
||||
}
|
||||
return Array.from(seen.values());
|
||||
}
|
||||
|
||||
export function mergeConnectorModelEntries(
|
||||
enabledModels: Array<{ id: string; label: string }>,
|
||||
disabledModels: Array<{ id: string; label: string }>,
|
||||
): ConnectorModelEntry[] {
|
||||
return dedupeById([
|
||||
...enabledModels.map((entry) => ({ ...entry, enabled: true })),
|
||||
...disabledModels.map((entry) => ({ ...entry, enabled: false })),
|
||||
]).sort((a, b) => {
|
||||
if (a.enabled !== b.enabled) return a.enabled ? -1 : 1;
|
||||
return a.label.localeCompare(b.label);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import type { ConnectorRecord } from "./types";
|
||||
|
||||
type ConnectorExecutionCandidate = Pick<ConnectorRecord, "status" | "capabilityMatrix"> & Partial<Pick<ConnectorRecord, "label">>;
|
||||
|
||||
export function isConnectorExecutionReady(connector: ConnectorExecutionCandidate) {
|
||||
return connector.status === "ready";
|
||||
}
|
||||
|
||||
export function getConnectorExecutionReadinessIssue(connector: ConnectorExecutionCandidate) {
|
||||
const label = connector.label ?? "Connector";
|
||||
if (connector.status === "ready") {
|
||||
return null;
|
||||
}
|
||||
if (connector.status === "not_installed") {
|
||||
return `${label} is not installed.`;
|
||||
}
|
||||
if (connector.status === "auth_required") {
|
||||
return `${label} requires authentication. Run the CLI login command first.`;
|
||||
}
|
||||
return `${label} is ${connector.status.replaceAll("_", " ")} and cannot be used for autonomous execution.`;
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
import type { DepartmentId } from "./types";
|
||||
|
||||
export const DEPARTMENT_LABELS: Record<DepartmentId, string> = {
|
||||
executive: "Executive Suite",
|
||||
engineering: "Engineering",
|
||||
product: "Product & Design",
|
||||
marketing: "Marketing",
|
||||
sales: "Sales & BD",
|
||||
hr: "People & Culture",
|
||||
finance: "Finance & Legal",
|
||||
legal: "Legal",
|
||||
operations: "Operations",
|
||||
customer_support: "Customer Success",
|
||||
research: "Research",
|
||||
design: "Design",
|
||||
};
|
||||
|
||||
export const DEPARTMENT_OPTIONS: Array<{ value: DepartmentId | ""; label: string }> = [
|
||||
{ value: "", label: "Any department" },
|
||||
...(Object.entries(DEPARTMENT_LABELS) as [DepartmentId, string][]).map(([value, label]) => ({ value, label })),
|
||||
];
|
||||
|
||||
export const DEPARTMENT_COLORS: Record<DepartmentId, string> = {
|
||||
executive: "var(--primary)",
|
||||
engineering: "var(--kami-ink)",
|
||||
product: "var(--kami-dark-warm)",
|
||||
marketing: "var(--kami-olive)",
|
||||
sales: "var(--kami-olive)",
|
||||
hr: "var(--kami-charcoal)",
|
||||
finance: "var(--kami-charcoal)",
|
||||
legal: "var(--kami-stone)",
|
||||
operations: "var(--kami-dark-warm)",
|
||||
customer_support: "var(--kami-stone)",
|
||||
research: "var(--kami-ink)",
|
||||
design: "var(--primary)",
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
export * from "./contracts/channels";
|
||||
export * from "./contracts/helpers";
|
||||
export * from "./contracts/json-fields";
|
||||
export * from "./contracts/schemas-company";
|
||||
export * from "./contracts/schemas-agents";
|
||||
export * from "./contracts/schemas-tasks";
|
||||
export * from "./contracts/schemas-approvals";
|
||||
export * from "./contracts/schemas-messages";
|
||||
export * from "./contracts/schemas-execution";
|
||||
export * from "./contracts/schemas-misc";
|
||||
export * from "./contracts/schemas-work-products";
|
||||
export * from "./contracts/desktop-api";
|
||||
export * from "./contracts/preload-forwarders";
|
||||
@@ -1,111 +0,0 @@
|
||||
export const IPC_CHANNELS = {
|
||||
loadSnapshot: "agent-company:load-snapshot",
|
||||
pickDirectory: "agent-company:pick-directory",
|
||||
openPath: "agent-company:open-path",
|
||||
openWorkProduct: "agent-company:open-work-product",
|
||||
saveCompany: "agent-company:save-company",
|
||||
setCurrentCompany: "agent-company:set-current-company",
|
||||
saveConnector: "agent-company:save-connector",
|
||||
testConnector: "agent-company:test-connector",
|
||||
saveWorkspace: "agent-company:save-workspace",
|
||||
saveAgent: "agent-company:save-agent",
|
||||
requestHire: "agent-company:request-hire",
|
||||
saveGoal: "agent-company:save-goal",
|
||||
saveProject: "agent-company:save-project",
|
||||
saveTask: "agent-company:save-task",
|
||||
requestApproval: "agent-company:request-approval",
|
||||
decideApproval: "agent-company:decide-approval",
|
||||
startTaskRun: "agent-company:start-task-run",
|
||||
cancelRun: "agent-company:cancel-run",
|
||||
getRunLog: "agent-company:get-run-log",
|
||||
getRunLogChunk: "agent-company:get-run-log-chunk",
|
||||
backupProfile: "agent-company:backup-profile",
|
||||
restoreProfile: "agent-company:restore-profile",
|
||||
updateSettings: "agent-company:update-settings",
|
||||
checkForUpdates: "agent-company:check-for-updates",
|
||||
deleteCompany: "agent-company:delete-company",
|
||||
deleteAgent: "agent-company:delete-agent",
|
||||
deleteTask: "agent-company:delete-task",
|
||||
deleteGoal: "agent-company:delete-goal",
|
||||
deleteProject: "agent-company:delete-project",
|
||||
deleteWorkspace: "agent-company:delete-workspace",
|
||||
deleteApproval: "agent-company:delete-approval",
|
||||
deleteSecret: "agent-company:delete-secret",
|
||||
listConnectorModels: "agent-company:list-connector-models",
|
||||
addComment: "agent-company:add-comment",
|
||||
setHeartbeat: "agent-company:set-heartbeat",
|
||||
triggerHeartbeat: "agent-company:trigger-heartbeat",
|
||||
rendererEvent: "agent-company:event",
|
||||
getCompanyMetrics: "agent-company:get-company-metrics",
|
||||
getStandupReport: "agent-company:get-standup-report",
|
||||
bootstrapOnboarding: "agent-company:bootstrap-onboarding",
|
||||
checkNodeInstalled: "agent-company:check-node-installed",
|
||||
openTerminalCommand: "agent-company:open-terminal-command",
|
||||
saveSocialAccount: "agent-company:save-social-account",
|
||||
deleteSocialAccount: "agent-company:delete-social-account",
|
||||
listBrowserActions: "agent-company:list-browser-actions",
|
||||
cancelBrowserAction: "agent-company:cancel-browser-action",
|
||||
triggerBrowserLogin: "agent-company:trigger-browser-login",
|
||||
saveMeeting: "agent-company:save-meeting",
|
||||
deleteMeeting: "agent-company:delete-meeting",
|
||||
saveDocument: "agent-company:save-document",
|
||||
deleteDocument: "agent-company:delete-document",
|
||||
saveKnowledgeEntry: "agent-company:save-knowledge-entry",
|
||||
deleteKnowledgeEntry: "agent-company:delete-knowledge-entry",
|
||||
saveSprint: "agent-company:save-sprint",
|
||||
deleteSprint: "agent-company:delete-sprint",
|
||||
saveAutomationRule: "agent-company:save-automation-rule",
|
||||
deleteAutomationRule: "agent-company:delete-automation-rule",
|
||||
toggleAutomationRule: "agent-company:toggle-automation-rule",
|
||||
getAutomationLog: "agent-company:get-automation-log",
|
||||
sendAgentMessage: "agent-company:send-agent-message",
|
||||
markMessageRead: "agent-company:mark-message-read",
|
||||
saveWorkflow: "agent-company:save-workflow",
|
||||
deleteWorkflow: "agent-company:delete-workflow",
|
||||
runWorkflow: "agent-company:run-workflow",
|
||||
searchMessages: "agent-company:search-messages",
|
||||
importSkill: "agent-company:import-skill",
|
||||
listSkills: "agent-company:list-skills",
|
||||
getSkillDetail: "agent-company:get-skill-detail",
|
||||
getSkillMarkdown: "agent-company:get-skill-markdown",
|
||||
deleteSkill: "agent-company:delete-skill",
|
||||
assignSkillToAgent: "agent-company:assign-skill-to-agent",
|
||||
removeSkillFromAgent: "agent-company:remove-skill-from-agent",
|
||||
checkSkillUpdate: "agent-company:check-skill-update",
|
||||
listSkillAgents: "agent-company:list-skill-agents",
|
||||
listAgentSkills: "agent-company:list-agent-skills",
|
||||
saveBudgetPolicy: "agent-company:save-budget-policy",
|
||||
deleteBudgetPolicy: "agent-company:delete-budget-policy",
|
||||
listBudgetPolicies: "agent-company:list-budget-policies",
|
||||
listBudgetIncidents: "agent-company:list-budget-incidents",
|
||||
resolveBudgetIncident: "agent-company:resolve-budget-incident",
|
||||
getBudgetStatus: "agent-company:get-budget-status",
|
||||
getTask: "agent-company:get-task",
|
||||
getAgent: "agent-company:get-agent",
|
||||
getRun: "agent-company:get-run",
|
||||
getApproval: "agent-company:get-approval",
|
||||
getConnectorDisabledModels: "agent-company:get-connector-disabled-models",
|
||||
setConnectorDisabledModels: "agent-company:set-connector-disabled-models",
|
||||
// Recovery
|
||||
recoveryRetry: "recovery:retry",
|
||||
recoveryFail: "recovery:fail",
|
||||
// Thread runtime (read-only — writes happen inside the backend)
|
||||
getThread: "agent-company:get-thread",
|
||||
listThreadEvents: "agent-company:list-thread-events",
|
||||
listThreadWaitStates: "agent-company:list-thread-wait-states",
|
||||
listThreadParticipants: "agent-company:list-thread-participants",
|
||||
windowMinimize: "window:minimize",
|
||||
windowMaximize: "window:maximize",
|
||||
windowClose: "window:close",
|
||||
windowIsMaximized: "window:isMaximized",
|
||||
// Credentials (pi-mono)
|
||||
credentialsList: "credentials:list",
|
||||
credentialsSave: "credentials:save",
|
||||
credentialsRemove: "credentials:remove",
|
||||
credentialsTest: "credentials:test",
|
||||
// OAuth (pi-mono)
|
||||
oauthStart: "oauth:start",
|
||||
oauthCancel: "oauth:cancel",
|
||||
oauthPromptResponse: "oauth:submit-prompt",
|
||||
oauthManualCodeResponse: "oauth:submit-manual-code",
|
||||
} as const;
|
||||
@@ -1,52 +0,0 @@
|
||||
// DesktopApi composition. Flat shape is preserved via intersection of sub-APIs;
|
||||
// external `window.agentCompany` callers stay unchanged. Per-domain declarations
|
||||
// live in `./desktop-api/*.ts`.
|
||||
|
||||
import type { AgentsApi } from "./desktop-api/agents";
|
||||
import type { ApprovalsApi } from "./desktop-api/approvals";
|
||||
import type { AutomationApi } from "./desktop-api/automation";
|
||||
import type { BudgetApi } from "./desktop-api/budget";
|
||||
import type { CommunicationApi } from "./desktop-api/communication";
|
||||
import type { CompaniesApi } from "./desktop-api/companies";
|
||||
import type { CredentialsApi } from "./desktop-api/credentials";
|
||||
import type { RunsApi } from "./desktop-api/runs";
|
||||
import type { SkillsApi } from "./desktop-api/skills";
|
||||
import type { TasksApi } from "./desktop-api/tasks";
|
||||
import type { ThreadsApi } from "./desktop-api/threads";
|
||||
import type { WindowApi } from "./desktop-api/window";
|
||||
|
||||
export type {
|
||||
DesktopResult,
|
||||
SaveTaskResult,
|
||||
RunEventRecord,
|
||||
HeartbeatPolicy,
|
||||
} from "./desktop-api/common";
|
||||
|
||||
export type {
|
||||
AgentsApi,
|
||||
ApprovalsApi,
|
||||
AutomationApi,
|
||||
BudgetApi,
|
||||
CommunicationApi,
|
||||
CompaniesApi,
|
||||
CredentialsApi,
|
||||
RunsApi,
|
||||
SkillsApi,
|
||||
TasksApi,
|
||||
ThreadsApi,
|
||||
WindowApi,
|
||||
};
|
||||
|
||||
export type DesktopApi =
|
||||
& CompaniesApi
|
||||
& AgentsApi
|
||||
& TasksApi
|
||||
& RunsApi
|
||||
& ApprovalsApi
|
||||
& CommunicationApi
|
||||
& ThreadsApi
|
||||
& CredentialsApi
|
||||
& SkillsApi
|
||||
& BudgetApi
|
||||
& AutomationApi
|
||||
& WindowApi;
|
||||
@@ -1,15 +0,0 @@
|
||||
import type { z } from "zod";
|
||||
import type { AgentRecord } from "../../types";
|
||||
import type { agentInputSchema, heartbeatSettingsSchema, hireRequestSchema, triggerHeartbeatSchema } from "../schemas-agents";
|
||||
import type { entityGetterSchema } from "../schemas-badges";
|
||||
import type { deleteEntitySchema } from "../schemas-badges";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type AgentsApi = {
|
||||
saveAgent: (input: z.infer<typeof agentInputSchema>) => Promise<DesktopResult<string>>;
|
||||
requestHire: (input: z.infer<typeof hireRequestSchema>) => Promise<DesktopResult<{ agentId: string; approvalId: string; autoApproved: boolean }>>;
|
||||
deleteAgent: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
getAgent: (input: z.infer<typeof entityGetterSchema>) => Promise<DesktopResult<AgentRecord>>;
|
||||
setHeartbeat: (input: z.infer<typeof heartbeatSettingsSchema>) => Promise<DesktopResult<boolean>>;
|
||||
triggerHeartbeat: (input: z.infer<typeof triggerHeartbeatSchema>) => Promise<DesktopResult<string>>;
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
import type { z } from "zod";
|
||||
import type { ApprovalRecord } from "../../types";
|
||||
import type { approvalDecisionSchema, approvalInputSchema } from "../schemas-approvals";
|
||||
import type { deleteEntitySchema, entityGetterSchema } from "../schemas-badges";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type ApprovalsApi = {
|
||||
requestApproval: (input: z.infer<typeof approvalInputSchema>) => Promise<DesktopResult<string>>;
|
||||
decideApproval: (input: z.infer<typeof approvalDecisionSchema>) => Promise<DesktopResult<boolean>>;
|
||||
deleteApproval: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
getApproval: (input: z.infer<typeof entityGetterSchema>) => Promise<DesktopResult<ApprovalRecord>>;
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
import type { z } from "zod";
|
||||
import type { BrowserActionRecord } from "../../types";
|
||||
import type { automationRuleInputSchema, toggleAutomationRuleSchema } from "../schemas-automation";
|
||||
import type { browserActionQuerySchema, cancelBrowserActionSchema, openTerminalCommandSchema, runWorkflowSchema, triggerBrowserLoginSchema, workflowInputSchema } from "../schemas-execution";
|
||||
import type { socialAccountInputSchema } from "../schemas-company";
|
||||
import type { deleteEntitySchema } from "../schemas-badges";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type AutomationApi = {
|
||||
saveAutomationRule: (input: z.infer<typeof automationRuleInputSchema>) => Promise<DesktopResult<string>>;
|
||||
deleteAutomationRule: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
toggleAutomationRule: (input: z.infer<typeof toggleAutomationRuleSchema>) => Promise<DesktopResult<boolean>>;
|
||||
getAutomationLog: (companyId: string) => Promise<DesktopResult<Array<{ ruleId: string; ruleName: string; trigger: string; action: string; executedAt: string }>>>;
|
||||
saveWorkflow: (input: z.infer<typeof workflowInputSchema>) => Promise<DesktopResult<string>>;
|
||||
deleteWorkflow: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
runWorkflow: (input: z.infer<typeof runWorkflowSchema>) => Promise<DesktopResult<boolean>>;
|
||||
saveSocialAccount: (input: z.infer<typeof socialAccountInputSchema>) => Promise<DesktopResult<string>>;
|
||||
deleteSocialAccount: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
listBrowserActions: (input: z.infer<typeof browserActionQuerySchema>) => Promise<DesktopResult<BrowserActionRecord[]>>;
|
||||
cancelBrowserAction: (input: z.infer<typeof cancelBrowserActionSchema>) => Promise<DesktopResult<boolean>>;
|
||||
triggerBrowserLogin: (input: z.infer<typeof triggerBrowserLoginSchema>) => Promise<DesktopResult<boolean>>;
|
||||
openTerminalCommand: (input: z.infer<typeof openTerminalCommandSchema>) => Promise<DesktopResult<boolean>>;
|
||||
};
|
||||
@@ -1,13 +0,0 @@
|
||||
import type { z } from "zod";
|
||||
import type { BudgetIncidentRecord, BudgetPolicyRecord, BudgetStatusSummary } from "../../types";
|
||||
import type { budgetPolicyInputSchema, deleteBudgetPolicySchema, listBudgetIncidentsSchema, resolveBudgetIncidentSchema } from "../schemas-budget";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type BudgetApi = {
|
||||
saveBudgetPolicy: (input: z.infer<typeof budgetPolicyInputSchema>) => Promise<DesktopResult<string>>;
|
||||
deleteBudgetPolicy: (input: z.infer<typeof deleteBudgetPolicySchema>) => Promise<DesktopResult<boolean>>;
|
||||
listBudgetPolicies: (companyId: string) => Promise<DesktopResult<BudgetPolicyRecord[]>>;
|
||||
listBudgetIncidents: (input: z.infer<typeof listBudgetIncidentsSchema>) => Promise<DesktopResult<BudgetIncidentRecord[]>>;
|
||||
resolveBudgetIncident: (input: z.infer<typeof resolveBudgetIncidentSchema>) => Promise<DesktopResult<boolean>>;
|
||||
getBudgetStatus: (companyId: string) => Promise<DesktopResult<BudgetStatusSummary>>;
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
export type DesktopResult<T> =
|
||||
| { ok: true; data: T }
|
||||
| { ok: false; error: { code: string; message: string } };
|
||||
|
||||
export interface SaveTaskResult {
|
||||
id: string;
|
||||
capabilityWarning?: string;
|
||||
}
|
||||
|
||||
export interface RunEventRecord {
|
||||
id: number;
|
||||
runId: string;
|
||||
agentId: string;
|
||||
seq: number;
|
||||
eventType: string;
|
||||
stream: string | null;
|
||||
level: string | null;
|
||||
message: string | null;
|
||||
payload: Record<string, unknown> | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface HeartbeatPolicy {
|
||||
enabled: boolean;
|
||||
intervalSec: number;
|
||||
cooldownSec: number;
|
||||
maxConcurrentRuns: number;
|
||||
wakeOnDemand: boolean;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import type { z } from "zod";
|
||||
import type { AgentMessageRecord, DocumentRecord, KnowledgeEntryRecord } from "../../types";
|
||||
import type { agentMessageInputSchema, commentInputSchema, documentInputSchema, knowledgeEntryInputSchema, markMessageReadSchema, meetingInputSchema, searchMessagesSchema } from "../schemas-messages";
|
||||
import type { deleteEntitySchema } from "../schemas-badges";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type CommunicationApi = {
|
||||
addComment: (input: z.infer<typeof commentInputSchema>) => Promise<DesktopResult<string>>;
|
||||
saveMeeting: (input: z.infer<typeof meetingInputSchema>) => Promise<DesktopResult<string>>;
|
||||
deleteMeeting: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
saveDocument: (input: z.infer<typeof documentInputSchema>) => Promise<DesktopResult<string>>;
|
||||
deleteDocument: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
saveKnowledgeEntry: (input: z.infer<typeof knowledgeEntryInputSchema>) => Promise<DesktopResult<string>>;
|
||||
deleteKnowledgeEntry: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
sendAgentMessage: (input: z.infer<typeof agentMessageInputSchema>) => Promise<DesktopResult<import("@shared/types").SendMessageResult>>;
|
||||
markMessageRead: (input: z.infer<typeof markMessageReadSchema>) => Promise<DesktopResult<boolean>>;
|
||||
searchMessages: (input: z.infer<typeof searchMessagesSchema>) => Promise<DesktopResult<AgentMessageRecord[]>>;
|
||||
// Keep reference to silence unused-import checker for DocumentRecord/KnowledgeEntryRecord — consumers infer via schemas.
|
||||
_recordsAnchor?: never & { _d?: DocumentRecord; _k?: KnowledgeEntryRecord };
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
import type { z } from "zod";
|
||||
import type { CompanyMetrics, OnboardingBootstrapResult, ProfileSnapshot, StandupReport } from "../../types";
|
||||
import type { bootstrapOnboardingSchema, companyInputSchema, connectorDisabledModelsSchema, connectorInputSchema, managedPathInputSchema, settingsSchema } from "../schemas-company";
|
||||
import type { entityGetterSchema, metricsQuerySchema } from "../schemas-badges";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type CompaniesApi = {
|
||||
loadSnapshot: () => Promise<DesktopResult<ProfileSnapshot>>;
|
||||
pickDirectory: () => Promise<DesktopResult<string | null>>;
|
||||
openPath: (input: z.infer<typeof managedPathInputSchema>) => Promise<DesktopResult<boolean>>;
|
||||
openWorkProduct: (input: z.infer<typeof entityGetterSchema>) => Promise<DesktopResult<boolean>>;
|
||||
saveCompany: (input: z.infer<typeof companyInputSchema>) => Promise<DesktopResult<string>>;
|
||||
setCurrentCompany: (companyId: string) => Promise<DesktopResult<boolean>>;
|
||||
saveConnector: (input: z.infer<typeof connectorInputSchema>) => Promise<DesktopResult<boolean>>;
|
||||
testConnector: (id: z.infer<typeof connectorInputSchema.shape.id>) => Promise<DesktopResult<boolean>>;
|
||||
updateSettings: (input: z.infer<typeof settingsSchema>) => Promise<DesktopResult<boolean>>;
|
||||
checkForUpdates: () => Promise<DesktopResult<boolean>>;
|
||||
deleteCompany: (companyId: string) => Promise<DesktopResult<boolean>>;
|
||||
listConnectorModels: (connectorId: string) => Promise<DesktopResult<Array<{ id: string; label: string }>>>;
|
||||
getConnectorDisabledModels: (connectorId: string) => Promise<DesktopResult<Array<{ id: string; label: string }>>>;
|
||||
setConnectorDisabledModels: (input: z.infer<typeof connectorDisabledModelsSchema>) => Promise<DesktopResult<boolean>>;
|
||||
getCompanyMetrics: (input: z.infer<typeof metricsQuerySchema>) => Promise<DesktopResult<CompanyMetrics>>;
|
||||
getStandupReport: (companyId: string) => Promise<DesktopResult<StandupReport>>;
|
||||
bootstrapOnboarding: (input: z.infer<typeof bootstrapOnboardingSchema>) => Promise<DesktopResult<OnboardingBootstrapResult>>;
|
||||
checkNodeInstalled: () => Promise<DesktopResult<{ installed: boolean; version: string | null }>>;
|
||||
backupProfile: () => Promise<DesktopResult<string | null>>;
|
||||
restoreProfile: () => Promise<DesktopResult<boolean>>;
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
import type { deleteEntitySchema } from "../schemas-badges";
|
||||
import type { z } from "zod";
|
||||
import type {
|
||||
CredentialSummary,
|
||||
SaveCredentialInput,
|
||||
} from "../schemas-credentials";
|
||||
import type {
|
||||
OAuthStartInput,
|
||||
OAuthPromptResponseInput,
|
||||
OAuthManualCodeResponseInput,
|
||||
} from "../schemas-oauth";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type CredentialsApi = {
|
||||
deleteSecret: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
// pi-mono credentials
|
||||
listCredentials: () => Promise<DesktopResult<CredentialSummary[]>>;
|
||||
saveCredential: (input: SaveCredentialInput) => Promise<DesktopResult<CredentialSummary>>;
|
||||
removeCredential: (input: { connectorId: string }) => Promise<DesktopResult<boolean>>;
|
||||
testCredential: (input: { connectorId: string }) => Promise<DesktopResult<{ ok: boolean; message: string }>>;
|
||||
// pi-mono OAuth
|
||||
startOAuth: (input: OAuthStartInput) => Promise<DesktopResult<boolean>>;
|
||||
cancelOAuth: (input: { connectorId: string }) => Promise<DesktopResult<boolean>>;
|
||||
submitOAuthPrompt: (input: OAuthPromptResponseInput) => Promise<DesktopResult<boolean>>;
|
||||
submitOAuthManualCode: (input: OAuthManualCodeResponseInput) => Promise<DesktopResult<boolean>>;
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import type { z } from "zod";
|
||||
import type { RunLogChunk, RunRecord } from "../../types";
|
||||
import type { cancelRunSchema, runLogChunkSchema, runLogSchema, startRunSchema } from "../schemas-execution";
|
||||
import type { entityGetterSchema } from "../schemas-badges";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type RunsApi = {
|
||||
startTaskRun: (input: z.infer<typeof startRunSchema>) => Promise<DesktopResult<string>>;
|
||||
cancelRun: (input: z.infer<typeof cancelRunSchema>) => Promise<DesktopResult<boolean>>;
|
||||
getRunLog: (input: z.infer<typeof runLogSchema>) => Promise<DesktopResult<string>>;
|
||||
getRunLogChunk: (input: z.infer<typeof runLogChunkSchema>) => Promise<DesktopResult<RunLogChunk>>;
|
||||
getRun: (input: z.infer<typeof entityGetterSchema>) => Promise<DesktopResult<RunRecord>>;
|
||||
recoveryRetry: (taskId: string, agentId: string, companyId: string) => Promise<DesktopResult<null>>;
|
||||
recoveryFail: (taskId: string, companyId: string) => Promise<DesktopResult<null>>;
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
import type { SkillImportResult, SkillRecord, SkillUpdateStatus } from "../../types";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type SkillsApi = {
|
||||
importSkill: (companyId: string, source: string) => Promise<DesktopResult<SkillImportResult[]>>;
|
||||
listSkills: (companyId: string) => Promise<DesktopResult<SkillRecord[]>>;
|
||||
getSkillDetail: (companyId: string, skillId: string) => Promise<DesktopResult<SkillRecord>>;
|
||||
getSkillMarkdown: (companyId: string, slug: string) => Promise<DesktopResult<string>>;
|
||||
deleteSkill: (companyId: string, skillId: string) => Promise<DesktopResult<void>>;
|
||||
assignSkillToAgent: (companyId: string, agentId: string, skillId: string) => Promise<DesktopResult<void>>;
|
||||
removeSkillFromAgent: (companyId: string, agentId: string, skillId: string) => Promise<DesktopResult<void>>;
|
||||
checkSkillUpdate: (companyId: string, skillId: string) => Promise<DesktopResult<SkillUpdateStatus>>;
|
||||
listSkillAgents: (companyId: string, skillId: string) => Promise<DesktopResult<string[]>>;
|
||||
listAgentSkills: (companyId: string, agentId: string) => Promise<DesktopResult<string[]>>;
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
import type { z } from "zod";
|
||||
import type { TaskRecord } from "../../types";
|
||||
import type { goalInputSchema, projectInputSchema, sprintInputSchema, taskInputSchema } from "../schemas-tasks";
|
||||
import type { workspaceInputSchema } from "../schemas-company";
|
||||
import type { deleteEntitySchema, entityGetterSchema } from "../schemas-badges";
|
||||
import type { DesktopResult, SaveTaskResult } from "./common";
|
||||
|
||||
export type TasksApi = {
|
||||
saveWorkspace: (input: z.infer<typeof workspaceInputSchema>) => Promise<DesktopResult<string>>;
|
||||
saveGoal: (input: z.infer<typeof goalInputSchema>) => Promise<DesktopResult<string>>;
|
||||
saveProject: (input: z.infer<typeof projectInputSchema>) => Promise<DesktopResult<string>>;
|
||||
saveTask: (input: z.infer<typeof taskInputSchema>) => Promise<DesktopResult<SaveTaskResult>>;
|
||||
saveSprint: (input: z.infer<typeof sprintInputSchema>) => Promise<DesktopResult<string>>;
|
||||
deleteTask: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
deleteGoal: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
deleteProject: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
deleteWorkspace: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
deleteSprint: (input: z.infer<typeof deleteEntitySchema>) => Promise<DesktopResult<boolean>>;
|
||||
getTask: (input: z.infer<typeof entityGetterSchema>) => Promise<DesktopResult<TaskRecord>>;
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
import type { z } from "zod";
|
||||
import type { ConversationEventRecord, ConversationParticipantRecord, ConversationThreadRecord, ThreadWaitStateRecord } from "../../types";
|
||||
import type { listThreadEventsSchema, listThreadParticipantsSchema, listThreadWaitStatesSchema, threadGetterSchema } from "../schemas-threads";
|
||||
import type { DesktopResult } from "./common";
|
||||
|
||||
export type ThreadsApi = {
|
||||
getThread: (input: z.infer<typeof threadGetterSchema>) => Promise<DesktopResult<ConversationThreadRecord>>;
|
||||
listThreadEvents: (input: z.infer<typeof listThreadEventsSchema>) => Promise<DesktopResult<ConversationEventRecord[]>>;
|
||||
listThreadWaitStates: (input: z.infer<typeof listThreadWaitStatesSchema>) => Promise<DesktopResult<ThreadWaitStateRecord[]>>;
|
||||
listThreadParticipants: (input: z.infer<typeof listThreadParticipantsSchema>) => Promise<DesktopResult<ConversationParticipantRecord[]>>;
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
import type { DesktopEvent } from "../../types";
|
||||
|
||||
export type WindowApi = {
|
||||
subscribe: (callback: (event: DesktopEvent) => void) => () => void;
|
||||
platform: "win32" | "darwin" | "linux";
|
||||
windowMinimize: () => Promise<void>;
|
||||
windowMaximize: () => Promise<void>;
|
||||
windowClose: () => Promise<void>;
|
||||
windowIsMaximized: () => Promise<boolean>;
|
||||
};
|
||||
@@ -1,31 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const optionalId = z.preprocess(
|
||||
(value) => (value === "" ? null : value),
|
||||
z.string().uuid().nullable().optional(),
|
||||
);
|
||||
|
||||
/** Canonical department identifiers shared across agent and automation schemas. */
|
||||
export const DEPARTMENT_IDS = z.enum([
|
||||
"executive", "engineering", "product", "marketing", "sales",
|
||||
"hr", "finance", "legal", "operations", "customer_support", "research", "design",
|
||||
]);
|
||||
|
||||
/** Canonical message channel types shared across messaging schemas. */
|
||||
export const MESSAGE_CHANNELS = z.enum([
|
||||
"direct", "department", "company", "project", "incident",
|
||||
]);
|
||||
|
||||
/**
|
||||
* Canonical automation trigger enum shared by `automationRuleInputSchema` and
|
||||
* `workflowInputSchema`. Single source of truth: the TS `AutomationTrigger`
|
||||
* alias in `types/enums.ts` derives from this enum.
|
||||
*/
|
||||
export const automationTriggerEnum = z.enum([
|
||||
"task_status_changed", "task_created", "task_blocked", "task_reassigned",
|
||||
"run_completed", "run_failed", "approval_created", "approval_resolved",
|
||||
"budget_threshold", "agent_idle", "comment_posted", "document_created",
|
||||
"schedule", "hire_approved", "sprint_started", "sprint_ended",
|
||||
]);
|
||||
|
||||
export type AutomationTrigger = z.infer<typeof automationTriggerEnum>;
|
||||
@@ -1,80 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export type JsonValue =
|
||||
| null
|
||||
| boolean
|
||||
| number
|
||||
| string
|
||||
| JsonValue[]
|
||||
| { [key: string]: JsonValue };
|
||||
|
||||
export const jsonValueSchema: z.ZodType<JsonValue> = z.lazy(() => z.union([
|
||||
z.null(),
|
||||
z.boolean(),
|
||||
z.number(),
|
||||
z.string(),
|
||||
z.array(jsonValueSchema),
|
||||
z.record(z.string(), jsonValueSchema),
|
||||
]));
|
||||
|
||||
export const jsonStringArraySchema = z.array(z.string());
|
||||
export const jsonArraySchema = z.array(jsonValueSchema);
|
||||
|
||||
export const meetingActionItemArraySchema = z.array(z.object({
|
||||
title: z.string().optional(),
|
||||
assigneeAgentId: z.string().optional(),
|
||||
description: z.string().optional(),
|
||||
}).catchall(jsonValueSchema));
|
||||
|
||||
export function canonicalizeJsonString<T>(value: string | null | undefined, schema: z.ZodType<T>, fallback: T): string {
|
||||
const raw = value ?? JSON.stringify(fallback);
|
||||
const parsed = JSON.parse(raw);
|
||||
return JSON.stringify(schema.parse(parsed));
|
||||
}
|
||||
|
||||
export function canonicalJsonString<T>(schema: z.ZodType<T>, fallback: T) {
|
||||
const fallbackJson = JSON.stringify(fallback);
|
||||
return z.string().default(fallbackJson).superRefine((value, ctx) => {
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(value);
|
||||
} catch {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "Must be valid JSON.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const result = schema.safeParse(parsed);
|
||||
if (!result.success) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "JSON value does not match the expected shape.",
|
||||
});
|
||||
}
|
||||
}).transform((value) => canonicalizeJsonString(value, schema, fallback));
|
||||
}
|
||||
|
||||
export function canonicalOptionalJsonString<T>(schema: z.ZodType<T>) {
|
||||
return z.string().superRefine((value, ctx) => {
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(value);
|
||||
} catch {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "Must be valid JSON.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const result = schema.safeParse(parsed);
|
||||
if (!result.success) {
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "JSON value does not match the expected shape.",
|
||||
});
|
||||
}
|
||||
}).transform((value) => JSON.stringify(schema.parse(JSON.parse(value))));
|
||||
}
|
||||
@@ -1,312 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { IPC_CHANNELS } from "./channels";
|
||||
import type { DesktopApi } from "./desktop-api";
|
||||
import {
|
||||
agentInputSchema,
|
||||
heartbeatSettingsSchema,
|
||||
hireRequestSchema,
|
||||
triggerHeartbeatSchema,
|
||||
} from "./schemas-agents";
|
||||
import {
|
||||
approvalDecisionSchema,
|
||||
approvalInputSchema,
|
||||
} from "./schemas-approvals";
|
||||
import {
|
||||
automationRuleInputSchema,
|
||||
toggleAutomationRuleSchema,
|
||||
} from "./schemas-automation";
|
||||
import {
|
||||
deleteEntitySchema,
|
||||
entityGetterSchema,
|
||||
} from "./schemas-badges";
|
||||
import {
|
||||
budgetPolicyInputSchema,
|
||||
deleteBudgetPolicySchema,
|
||||
resolveBudgetIncidentSchema,
|
||||
} from "./schemas-budget";
|
||||
import {
|
||||
bootstrapOnboardingSchema,
|
||||
companyIdSchema,
|
||||
companyInputSchema,
|
||||
connectorDisabledModelsSchema,
|
||||
connectorInputSchema,
|
||||
managedPathInputSchema,
|
||||
socialAccountInputSchema,
|
||||
settingsSchema,
|
||||
workspaceInputSchema,
|
||||
} from "./schemas-company";
|
||||
import {
|
||||
removeCredentialInputSchema,
|
||||
saveCredentialInputSchema,
|
||||
testCredentialInputSchema,
|
||||
} from "./schemas-credentials";
|
||||
import {
|
||||
assignSkillToAgentSchema,
|
||||
cancelBrowserActionSchema,
|
||||
cancelRunSchema,
|
||||
checkSkillUpdateSchema,
|
||||
deleteSkillSchema,
|
||||
importSkillSchema,
|
||||
openTerminalCommandSchema,
|
||||
recoveryRetrySchema,
|
||||
recoveryTaskSchema,
|
||||
removeSkillFromAgentSchema,
|
||||
runWorkflowSchema,
|
||||
startRunSchema,
|
||||
triggerBrowserLoginSchema,
|
||||
workflowInputSchema,
|
||||
} from "./schemas-execution";
|
||||
import {
|
||||
agentMessageInputSchema,
|
||||
commentInputSchema,
|
||||
documentInputSchema,
|
||||
knowledgeEntryInputSchema,
|
||||
markMessageReadSchema,
|
||||
meetingInputSchema,
|
||||
} from "./schemas-messages";
|
||||
import {
|
||||
oauthCancelInputSchema,
|
||||
oauthManualCodeResponseSchema,
|
||||
oauthPromptResponseSchema,
|
||||
oauthStartInputSchema,
|
||||
} from "./schemas-oauth";
|
||||
import {
|
||||
goalInputSchema,
|
||||
projectInputSchema,
|
||||
sprintInputSchema,
|
||||
taskInputSchema,
|
||||
} from "./schemas-tasks";
|
||||
|
||||
type DesktopFunctionKey = {
|
||||
[Key in keyof DesktopApi]: DesktopApi[Key] extends (...args: infer _Args) => unknown ? Key : never;
|
||||
}[keyof DesktopApi];
|
||||
|
||||
type IpcChannelKey = keyof typeof IPC_CHANNELS;
|
||||
|
||||
export type PreloadPayloadSpec =
|
||||
| Readonly<{ kind: "none" }>
|
||||
| Readonly<{ kind: "single" }>
|
||||
| Readonly<{ kind: "object"; keys: readonly string[] }>;
|
||||
|
||||
export type PreloadForwarder = Readonly<{
|
||||
api: DesktopFunctionKey;
|
||||
channel: IpcChannelKey;
|
||||
payload: PreloadPayloadSpec;
|
||||
}>;
|
||||
|
||||
const noPayload = { kind: "none" } as const;
|
||||
const singlePayload = { kind: "single" } as const;
|
||||
const objectPayload = <const Keys extends readonly string[]>(...keys: Keys) =>
|
||||
({ kind: "object", keys } as const);
|
||||
const forwardSame = <const Api extends Extract<DesktopFunctionKey, IpcChannelKey>>(
|
||||
api: Api,
|
||||
payload: PreloadPayloadSpec,
|
||||
) => ({ api, channel: api, payload } as const);
|
||||
const forwardAlias = <const Api extends DesktopFunctionKey, const Channel extends IpcChannelKey>(
|
||||
api: Api,
|
||||
channel: Channel,
|
||||
payload: PreloadPayloadSpec,
|
||||
) => ({ api, channel, payload } as const);
|
||||
|
||||
export const PRELOAD_FORWARDERS = [
|
||||
forwardSame("loadSnapshot", noPayload),
|
||||
forwardSame("pickDirectory", noPayload),
|
||||
forwardSame("openPath", singlePayload),
|
||||
forwardSame("openWorkProduct", singlePayload),
|
||||
forwardSame("saveCompany", singlePayload),
|
||||
forwardSame("setCurrentCompany", singlePayload),
|
||||
forwardSame("saveConnector", singlePayload),
|
||||
forwardSame("testConnector", singlePayload),
|
||||
forwardSame("saveWorkspace", singlePayload),
|
||||
forwardSame("saveAgent", singlePayload),
|
||||
forwardSame("requestHire", singlePayload),
|
||||
forwardSame("saveGoal", singlePayload),
|
||||
forwardSame("saveProject", singlePayload),
|
||||
forwardSame("saveTask", singlePayload),
|
||||
forwardSame("requestApproval", singlePayload),
|
||||
forwardSame("decideApproval", singlePayload),
|
||||
forwardSame("startTaskRun", singlePayload),
|
||||
forwardSame("cancelRun", singlePayload),
|
||||
forwardSame("getRunLog", singlePayload),
|
||||
forwardSame("getRunLogChunk", singlePayload),
|
||||
forwardSame("backupProfile", noPayload),
|
||||
forwardSame("restoreProfile", noPayload),
|
||||
forwardSame("updateSettings", singlePayload),
|
||||
forwardSame("checkForUpdates", noPayload),
|
||||
forwardSame("deleteCompany", singlePayload),
|
||||
forwardSame("deleteAgent", singlePayload),
|
||||
forwardSame("deleteTask", singlePayload),
|
||||
forwardSame("deleteGoal", singlePayload),
|
||||
forwardSame("deleteProject", singlePayload),
|
||||
forwardSame("deleteWorkspace", singlePayload),
|
||||
forwardSame("deleteApproval", singlePayload),
|
||||
forwardSame("deleteSecret", singlePayload),
|
||||
forwardSame("listConnectorModels", singlePayload),
|
||||
forwardSame("getConnectorDisabledModels", singlePayload),
|
||||
forwardSame("setConnectorDisabledModels", singlePayload),
|
||||
forwardSame("addComment", singlePayload),
|
||||
forwardSame("setHeartbeat", singlePayload),
|
||||
forwardSame("triggerHeartbeat", singlePayload),
|
||||
forwardSame("getCompanyMetrics", singlePayload),
|
||||
forwardSame("getStandupReport", singlePayload),
|
||||
forwardSame("bootstrapOnboarding", singlePayload),
|
||||
forwardSame("checkNodeInstalled", noPayload),
|
||||
forwardSame("openTerminalCommand", singlePayload),
|
||||
forwardSame("saveSocialAccount", singlePayload),
|
||||
forwardSame("deleteSocialAccount", singlePayload),
|
||||
forwardSame("listBrowserActions", singlePayload),
|
||||
forwardSame("cancelBrowserAction", singlePayload),
|
||||
forwardSame("triggerBrowserLogin", singlePayload),
|
||||
forwardSame("saveMeeting", singlePayload),
|
||||
forwardSame("deleteMeeting", singlePayload),
|
||||
forwardSame("saveDocument", singlePayload),
|
||||
forwardSame("deleteDocument", singlePayload),
|
||||
forwardSame("saveKnowledgeEntry", singlePayload),
|
||||
forwardSame("deleteKnowledgeEntry", singlePayload),
|
||||
forwardSame("saveSprint", singlePayload),
|
||||
forwardSame("deleteSprint", singlePayload),
|
||||
forwardSame("saveAutomationRule", singlePayload),
|
||||
forwardSame("deleteAutomationRule", singlePayload),
|
||||
forwardSame("toggleAutomationRule", singlePayload),
|
||||
forwardSame("getAutomationLog", singlePayload),
|
||||
forwardSame("sendAgentMessage", singlePayload),
|
||||
forwardSame("searchMessages", singlePayload),
|
||||
forwardSame("markMessageRead", singlePayload),
|
||||
forwardSame("saveWorkflow", singlePayload),
|
||||
forwardSame("deleteWorkflow", singlePayload),
|
||||
forwardSame("runWorkflow", singlePayload),
|
||||
forwardSame("importSkill", objectPayload("companyId", "source")),
|
||||
forwardSame("listSkills", objectPayload("companyId")),
|
||||
forwardSame("getSkillDetail", objectPayload("companyId", "skillId")),
|
||||
forwardSame("getSkillMarkdown", objectPayload("companyId", "slug")),
|
||||
forwardSame("deleteSkill", objectPayload("companyId", "skillId")),
|
||||
forwardSame("assignSkillToAgent", objectPayload("companyId", "agentId", "skillId")),
|
||||
forwardSame("removeSkillFromAgent", objectPayload("companyId", "agentId", "skillId")),
|
||||
forwardSame("checkSkillUpdate", objectPayload("companyId", "skillId")),
|
||||
forwardSame("listSkillAgents", objectPayload("companyId", "skillId")),
|
||||
forwardSame("listAgentSkills", objectPayload("companyId", "agentId")),
|
||||
forwardSame("saveBudgetPolicy", singlePayload),
|
||||
forwardSame("deleteBudgetPolicy", singlePayload),
|
||||
forwardSame("listBudgetPolicies", objectPayload("companyId")),
|
||||
forwardSame("listBudgetIncidents", singlePayload),
|
||||
forwardSame("resolveBudgetIncident", singlePayload),
|
||||
forwardSame("getBudgetStatus", objectPayload("companyId")),
|
||||
forwardSame("recoveryRetry", objectPayload("taskId", "agentId", "companyId")),
|
||||
forwardSame("recoveryFail", objectPayload("taskId", "companyId")),
|
||||
forwardSame("getTask", singlePayload),
|
||||
forwardSame("getAgent", singlePayload),
|
||||
forwardSame("getRun", singlePayload),
|
||||
forwardSame("getApproval", singlePayload),
|
||||
forwardSame("getThread", singlePayload),
|
||||
forwardSame("listThreadEvents", singlePayload),
|
||||
forwardSame("listThreadWaitStates", singlePayload),
|
||||
forwardSame("listThreadParticipants", singlePayload),
|
||||
forwardAlias("listCredentials", "credentialsList", noPayload),
|
||||
forwardAlias("saveCredential", "credentialsSave", singlePayload),
|
||||
forwardAlias("removeCredential", "credentialsRemove", singlePayload),
|
||||
forwardAlias("testCredential", "credentialsTest", singlePayload),
|
||||
forwardAlias("startOAuth", "oauthStart", singlePayload),
|
||||
forwardAlias("cancelOAuth", "oauthCancel", singlePayload),
|
||||
forwardAlias("submitOAuthPrompt", "oauthPromptResponse", singlePayload),
|
||||
forwardAlias("submitOAuthManualCode", "oauthManualCodeResponse", singlePayload),
|
||||
] as const satisfies readonly PreloadForwarder[];
|
||||
|
||||
export type PreloadForwardedMethod = (typeof PRELOAD_FORWARDERS)[number]["api"];
|
||||
export type PreloadForwardedApi = Pick<DesktopApi, PreloadForwardedMethod>;
|
||||
|
||||
export const PRELOAD_INPUT_SCHEMAS: Partial<Record<PreloadForwardedMethod, z.ZodType<unknown>>> = {
|
||||
openPath: managedPathInputSchema,
|
||||
openWorkProduct: entityGetterSchema,
|
||||
saveCompany: companyInputSchema,
|
||||
setCurrentCompany: companyIdSchema,
|
||||
saveConnector: connectorInputSchema,
|
||||
testConnector: connectorInputSchema.shape.id,
|
||||
saveWorkspace: workspaceInputSchema,
|
||||
saveAgent: agentInputSchema,
|
||||
requestHire: hireRequestSchema,
|
||||
saveGoal: goalInputSchema,
|
||||
saveProject: projectInputSchema,
|
||||
saveTask: taskInputSchema,
|
||||
requestApproval: approvalInputSchema,
|
||||
decideApproval: approvalDecisionSchema,
|
||||
startTaskRun: startRunSchema,
|
||||
cancelRun: cancelRunSchema,
|
||||
updateSettings: settingsSchema,
|
||||
deleteCompany: companyIdSchema,
|
||||
deleteAgent: deleteEntitySchema,
|
||||
deleteTask: deleteEntitySchema,
|
||||
deleteGoal: deleteEntitySchema,
|
||||
deleteProject: deleteEntitySchema,
|
||||
deleteWorkspace: deleteEntitySchema,
|
||||
deleteApproval: deleteEntitySchema,
|
||||
deleteSecret: deleteEntitySchema,
|
||||
setConnectorDisabledModels: connectorDisabledModelsSchema,
|
||||
addComment: commentInputSchema,
|
||||
setHeartbeat: heartbeatSettingsSchema,
|
||||
triggerHeartbeat: triggerHeartbeatSchema,
|
||||
bootstrapOnboarding: bootstrapOnboardingSchema,
|
||||
openTerminalCommand: openTerminalCommandSchema,
|
||||
saveSocialAccount: socialAccountInputSchema,
|
||||
deleteSocialAccount: deleteEntitySchema,
|
||||
cancelBrowserAction: cancelBrowserActionSchema,
|
||||
triggerBrowserLogin: triggerBrowserLoginSchema,
|
||||
saveMeeting: meetingInputSchema,
|
||||
deleteMeeting: deleteEntitySchema,
|
||||
saveDocument: documentInputSchema,
|
||||
deleteDocument: deleteEntitySchema,
|
||||
saveKnowledgeEntry: knowledgeEntryInputSchema,
|
||||
deleteKnowledgeEntry: deleteEntitySchema,
|
||||
saveSprint: sprintInputSchema,
|
||||
deleteSprint: deleteEntitySchema,
|
||||
saveAutomationRule: automationRuleInputSchema,
|
||||
deleteAutomationRule: deleteEntitySchema,
|
||||
toggleAutomationRule: toggleAutomationRuleSchema,
|
||||
sendAgentMessage: agentMessageInputSchema,
|
||||
markMessageRead: markMessageReadSchema,
|
||||
saveWorkflow: workflowInputSchema,
|
||||
deleteWorkflow: deleteEntitySchema,
|
||||
runWorkflow: runWorkflowSchema,
|
||||
importSkill: importSkillSchema,
|
||||
deleteSkill: deleteSkillSchema,
|
||||
assignSkillToAgent: assignSkillToAgentSchema,
|
||||
removeSkillFromAgent: removeSkillFromAgentSchema,
|
||||
checkSkillUpdate: checkSkillUpdateSchema,
|
||||
saveBudgetPolicy: budgetPolicyInputSchema,
|
||||
deleteBudgetPolicy: deleteBudgetPolicySchema,
|
||||
resolveBudgetIncident: resolveBudgetIncidentSchema,
|
||||
recoveryRetry: recoveryRetrySchema,
|
||||
recoveryFail: recoveryTaskSchema,
|
||||
saveCredential: saveCredentialInputSchema,
|
||||
removeCredential: removeCredentialInputSchema,
|
||||
testCredential: testCredentialInputSchema,
|
||||
startOAuth: oauthStartInputSchema,
|
||||
cancelOAuth: oauthCancelInputSchema,
|
||||
submitOAuthPrompt: oauthPromptResponseSchema,
|
||||
submitOAuthManualCode: oauthManualCodeResponseSchema,
|
||||
};
|
||||
|
||||
export function mapPreloadInvokeArgs(
|
||||
payload: PreloadPayloadSpec,
|
||||
args: readonly unknown[],
|
||||
schema?: z.ZodType<unknown>,
|
||||
): readonly unknown[] {
|
||||
if (payload.kind === "none") {
|
||||
assertArgCount(payload.kind, args.length, 0);
|
||||
return [];
|
||||
}
|
||||
|
||||
if (payload.kind === "single") {
|
||||
assertArgCount(payload.kind, args.length, 1);
|
||||
return [schema ? schema.parse(args[0]) : args[0]];
|
||||
}
|
||||
|
||||
assertArgCount(payload.kind, args.length, payload.keys.length);
|
||||
const objectPayload = Object.fromEntries(payload.keys.map((key, index) => [key, args[index]]));
|
||||
return [schema ? schema.parse(objectPayload) : objectPayload];
|
||||
}
|
||||
|
||||
function assertArgCount(kind: PreloadPayloadSpec["kind"], actual: number, expected: number): void {
|
||||
if (actual !== expected) {
|
||||
throw new Error(`Invalid preload ${kind} argument count: expected ${expected}, received ${actual}`);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
/**
|
||||
* The renderer-bound `agent-event` push payload.
|
||||
*
|
||||
* The `event` payload is pi's AgentEvent (discriminated by `type`). We do not
|
||||
* mirror pi's type system in Zod (it would couple the renderer to pi's
|
||||
* internals); we validate the envelope and pass the event through opaquely.
|
||||
*/
|
||||
export const agentEventPushSchema = z.object({
|
||||
runId: z.string(),
|
||||
agentId: z.string(),
|
||||
companyId: z.string(),
|
||||
taskId: z.string().nullable(),
|
||||
emittedAt: z.string(),
|
||||
event: z.object({
|
||||
type: z.string(),
|
||||
}).passthrough(),
|
||||
});
|
||||
@@ -1,53 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { DEPARTMENT_IDS, optionalId } from "./helpers";
|
||||
import { connectorInputSchema } from "./schemas-company";
|
||||
|
||||
const agentNameSchema = z.string().trim().min(2).max(80);
|
||||
const agentRoleSchema = z.string().trim().min(2).max(80);
|
||||
const agentTitleSchema = z.string().trim().max(80).default("");
|
||||
|
||||
export const agentInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
name: agentNameSchema,
|
||||
role: agentRoleSchema,
|
||||
title: agentTitleSchema,
|
||||
department: DEPARTMENT_IDS.nullable().optional(),
|
||||
reportsTo: optionalId,
|
||||
connectorId: connectorInputSchema.shape.id,
|
||||
workspaceId: optionalId,
|
||||
model: z.string().nullable().optional(),
|
||||
metadataJson: z.string().default("{}").optional(),
|
||||
capabilities: z.string().default(""),
|
||||
budgetMonthlyUsd: z.number().min(0).default(0),
|
||||
status: z.enum(["idle", "active", "running", "paused", "error", "pending_approval", "terminated"]).default("idle"),
|
||||
});
|
||||
|
||||
export const hireRequestSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
requestedByAgentId: optionalId,
|
||||
name: agentNameSchema,
|
||||
role: agentRoleSchema,
|
||||
title: agentTitleSchema,
|
||||
department: DEPARTMENT_IDS.nullable().optional(),
|
||||
reportsTo: optionalId,
|
||||
connectorId: connectorInputSchema.shape.id,
|
||||
workspaceId: optionalId,
|
||||
model: z.string().nullable().optional(),
|
||||
metadataJson: z.string().default("{}").optional(),
|
||||
capabilities: z.string().default(""),
|
||||
budgetMonthlyUsd: z.number().min(0).default(0),
|
||||
});
|
||||
|
||||
export const heartbeatSettingsSchema = z.object({
|
||||
agentId: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
enabled: z.boolean(),
|
||||
intervalSec: z.number().int().min(30).max(86400).default(120),
|
||||
});
|
||||
|
||||
export const triggerHeartbeatSchema = z.object({
|
||||
agentId: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
trigger: z.enum(["manual", "timer", "assignment", "goal_activated", "approval_resolved", "subtask_completed", "task_review_requested", "comment", "report_blocked", "report_failed", "recovery", "message", "peer_request", "task_continuation"]).default("manual"),
|
||||
});
|
||||
@@ -1,85 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { optionalId } from "./helpers";
|
||||
|
||||
// Schema-typed attachment pointers. Agents used to jam everything into the
|
||||
// free-form `payloadJson` string, which meant the board UI had to parse JSON
|
||||
// blind and hope the keys matched. documentIds / workProductIds make the
|
||||
// attachment contract schema-visible: validators see them, the HTTP route
|
||||
// folds them back into payloadJson for persistence, and the inspector renders
|
||||
// them deterministically in the "linked documents" panel on the first screen.
|
||||
// payloadJson remains as the escape hatch for type-specific structured
|
||||
// fields (social post drafts, hire proposals, etc.).
|
||||
export const approvalInputSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
relatedTaskId: optionalId,
|
||||
requestedByAgentId: optionalId,
|
||||
relatedAgentId: optionalId,
|
||||
type: z.enum(["hire_agent", "approve_ceo_strategy", "dangerous_command", "secret_access", "budget_request", "promotion", "termination", "vendor_approval", "document_review", "production_deploy", "incident_escalation", "social_post", "deliverable_review", "budget_override", "plan_review", "scope_review", "draft_review", "strategy_review", "exception_review"]),
|
||||
payloadSummary: z.string().min(2).max(280),
|
||||
impactSummary: z.string().min(2).max(400),
|
||||
// payloadJson: type-specific structured fields only (social draft, hire
|
||||
// proposal, etc). DEPRECATED: embedding `documentIds` / `workProductIds` /
|
||||
// `documents[]` / `workProducts[]` here. Use the top-level schema fields
|
||||
// below — they are the canonical source of truth for attachment pointers.
|
||||
// Legacy embedded mirrors are still read for back-compat but new callers
|
||||
// must not write them.
|
||||
payloadJson: z.string().nullable().optional(),
|
||||
// CANONICAL attachment pointers. mergeApprovalAttachments folds these into
|
||||
// payloadJson at persist time so on-disk rows have a single readable shape,
|
||||
// but the schema top-level is the authoritative contract.
|
||||
documentIds: z.array(z.string().uuid()).optional(),
|
||||
workProductIds: z.array(z.string().uuid()).optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Merge canonical documentIds / workProductIds (schema top-level) into
|
||||
* payloadJson so downstream readers (ApprovalDocumentsPanel,
|
||||
* extractApprovalDocumentReferences) see a single source of truth.
|
||||
*
|
||||
* Throws if payloadJson is non-empty but not valid JSON-object: the previous
|
||||
* behavior stuffed the opaque string under `rawPayload` which hid producer
|
||||
* bugs (an agent passing a stringified-twice JSON, or a literal "undefined")
|
||||
* and silently broke attachment rendering. Let it crash at the boundary.
|
||||
*/
|
||||
export function mergeApprovalAttachments(
|
||||
payloadJson: string | null | undefined,
|
||||
documentIds: string[] | undefined,
|
||||
workProductIds: string[] | undefined,
|
||||
): string | null {
|
||||
const hasDocs = Array.isArray(documentIds) && documentIds.length > 0;
|
||||
const hasProducts = Array.isArray(workProductIds) && workProductIds.length > 0;
|
||||
if (!hasDocs && !hasProducts) return payloadJson ?? null;
|
||||
|
||||
let base: Record<string, unknown> = {};
|
||||
if (payloadJson) {
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(payloadJson);
|
||||
} catch (error) {
|
||||
const detail = error instanceof Error ? error.message : String(error);
|
||||
throw new Error(
|
||||
`mergeApprovalAttachments: payloadJson is not valid JSON (${detail}). ` +
|
||||
`payloadJson must be a JSON object or null; free-text payloads are not supported.`,
|
||||
);
|
||||
}
|
||||
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
||||
throw new Error(
|
||||
`mergeApprovalAttachments: payloadJson must be a JSON object (got ${
|
||||
Array.isArray(parsed) ? "array" : parsed === null ? "null" : typeof parsed
|
||||
}).`,
|
||||
);
|
||||
}
|
||||
base = parsed as Record<string, unknown>;
|
||||
}
|
||||
|
||||
if (hasDocs) base.documentIds = documentIds;
|
||||
if (hasProducts) base.workProductIds = workProductIds;
|
||||
return JSON.stringify(base);
|
||||
}
|
||||
|
||||
export const approvalDecisionSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
approvalId: z.string().uuid(),
|
||||
state: z.enum(["approved", "rejected", "revision_requested"]),
|
||||
decisionNote: z.string().max(400).default(""),
|
||||
});
|
||||
@@ -1,28 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { DEPARTMENT_IDS, automationTriggerEnum } from "./helpers";
|
||||
|
||||
export const automationRuleInputSchema = z.object({
|
||||
id: z.preprocess((v) => (v === "" ? null : v), z.string().uuid().nullable().optional()),
|
||||
companyId: z.string().uuid(),
|
||||
name: z.string().min(2).max(120),
|
||||
description: z.string().max(500).default(""),
|
||||
trigger: automationTriggerEnum,
|
||||
conditionsJson: z.string().default("{}"),
|
||||
action: z.enum([
|
||||
"assign_task", "create_task", "notify_agent", "send_message",
|
||||
"trigger_heartbeat", "create_approval", "update_task_status",
|
||||
"escalate_to_manager", "cross_department_notify", "schedule_meeting",
|
||||
"create_document", "auto_approve", "reassign_task", "run_task",
|
||||
]),
|
||||
actionConfigJson: z.string().default("{}"),
|
||||
sourceDepartment: DEPARTMENT_IDS.nullable().optional(),
|
||||
targetDepartment: DEPARTMENT_IDS.nullable().optional(),
|
||||
priority: z.number().int().min(0).max(100).default(50),
|
||||
status: z.enum(["active", "paused", "disabled", "error"]).default("active"),
|
||||
});
|
||||
|
||||
export const toggleAutomationRuleSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
status: z.enum(["active", "paused"]),
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const deleteEntitySchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const entityGetterSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
id: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const metricsQuerySchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
agentId: z.string().uuid().optional(),
|
||||
days: z.number().int().min(1).max(90).default(30),
|
||||
});
|
||||
|
||||
// `SidebarBadges` and its Zod schema used to live here as an IPC
|
||||
// response type. Sidebar badges are now derived in the renderer from
|
||||
// `ProfileSnapshot` (see `src/shared/sidebar-badges.ts`), so no wire
|
||||
// contract is needed — `deriveSidebarBadges(snapshot)` is the only
|
||||
// path that produces a `SidebarBadges` value.
|
||||
@@ -1,39 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { optionalId } from "./helpers";
|
||||
|
||||
export const budgetPolicyInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
scopeType: z.enum(["company", "agent", "project"]),
|
||||
scopeId: z.string().uuid(),
|
||||
metric: z.literal("billed_cents").default("billed_cents"),
|
||||
windowKind: z.literal("calendar_month_utc").default("calendar_month_utc"),
|
||||
amount: z.number().int().min(1),
|
||||
warnPercent: z.number().int().min(1).max(100).default(80),
|
||||
hardStopEnabled: z.boolean().default(true),
|
||||
notifyEnabled: z.boolean().default(true),
|
||||
isActive: z.boolean().default(true),
|
||||
});
|
||||
|
||||
export const listBudgetPoliciesSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const deleteBudgetPolicySchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
policyId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const listBudgetIncidentsSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
status: z.enum(["open", "resolved", "auto_resolved_limit_increase", "auto_closed", "all"]).default("all"),
|
||||
});
|
||||
|
||||
export const resolveBudgetIncidentSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
incidentId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const getBudgetStatusSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
});
|
||||
@@ -1,143 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { optionalId } from "./helpers";
|
||||
|
||||
export const companyIdSchema = z.string().uuid();
|
||||
|
||||
export const managedPathInputSchema = z.object({
|
||||
companyId: companyIdSchema,
|
||||
path: z.string().min(1),
|
||||
});
|
||||
|
||||
export const companyInputSchema = z.object({
|
||||
id: optionalId,
|
||||
name: z.string().min(2).max(80),
|
||||
description: z.string().max(500).default(""),
|
||||
status: z.enum(["active", "paused", "archived"]).default("active"),
|
||||
autoApproveHires: z.boolean().default(false),
|
||||
reviewDeliverables: z.boolean().default(false),
|
||||
executionMode: z.enum(["ai_ceo", "ai_cofounder"]).default("ai_ceo"),
|
||||
});
|
||||
|
||||
/**
|
||||
* Pure pi-mono connector catalog ids. Single source of truth: this zod enum.
|
||||
* The TS `ConnectorId` alias (`shared/types/enums.ts`) and the catalog
|
||||
* (`shared/connector-catalog.ts`) both derive from it. Adding a connector
|
||||
* requires editing this list only.
|
||||
*/
|
||||
export const connectorIdEnum = z.enum([
|
||||
// OAuth (5)
|
||||
"claude-pro",
|
||||
"openai-codex",
|
||||
"github-copilot",
|
||||
"gemini-cli",
|
||||
"antigravity",
|
||||
// API key (18)
|
||||
"anthropic",
|
||||
"openai",
|
||||
"google",
|
||||
"mistral",
|
||||
"groq",
|
||||
"cerebras",
|
||||
"xai",
|
||||
"openrouter",
|
||||
"vercel-ai-gateway",
|
||||
"zai",
|
||||
"opencode",
|
||||
"opencode-go",
|
||||
"huggingface",
|
||||
"kimi-coding",
|
||||
"minimax",
|
||||
"minimax-cn",
|
||||
"fireworks",
|
||||
"fireworks-firepass",
|
||||
// Cloud (3)
|
||||
"amazon-bedrock",
|
||||
"azure-openai",
|
||||
"google-vertex",
|
||||
// Local (2)
|
||||
"ollama",
|
||||
"lm-studio",
|
||||
]);
|
||||
|
||||
export type ConnectorId = z.infer<typeof connectorIdEnum>;
|
||||
|
||||
export const connectorInputSchema = z.object({
|
||||
id: connectorIdEnum,
|
||||
model: z.string().nullable().optional(),
|
||||
envBindingText: z.string().default(""),
|
||||
notes: z.string().default(""),
|
||||
});
|
||||
|
||||
export const connectorDisabledModelsSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
connectorId: connectorInputSchema.shape.id,
|
||||
disabledModels: z.array(z.object({ id: z.string(), label: z.string() })),
|
||||
});
|
||||
|
||||
export const connectorModelPoolQuerySchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
connectorId: connectorInputSchema.shape.id,
|
||||
});
|
||||
|
||||
export const workspaceInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
name: z.string().min(2).max(80),
|
||||
localPath: z.string().min(1),
|
||||
repoUrl: z.string().default(""),
|
||||
repoRef: z.string().default(""),
|
||||
projectId: optionalId,
|
||||
isPrimary: z.boolean().default(false),
|
||||
});
|
||||
|
||||
export const settingsSchema = z.object({
|
||||
theme: z.enum(["system", "light", "dark"]).optional(),
|
||||
locale: z.enum(["en", "zh"]).optional(),
|
||||
updatesEnabled: z.boolean().optional(),
|
||||
logRetentionDays: z.number().int().min(1).max(365).optional(),
|
||||
});
|
||||
|
||||
export const bootstrapOnboardingSchema = z.object({
|
||||
companyName: z.string().min(2).max(80),
|
||||
companyDescription: z.string().max(500).default(""),
|
||||
workspacePath: z.string().default(""),
|
||||
autoApproveHires: z.boolean().default(true),
|
||||
reviewDeliverables: z.boolean().default(false),
|
||||
executionMode: z.enum(["ai_ceo", "ai_cofounder"]).default("ai_ceo"),
|
||||
goalTitle: z.string().default(""),
|
||||
goalDescription: z.string().default(""),
|
||||
connectorId: connectorInputSchema.shape.id.optional(),
|
||||
connectorModel: z.string().default(""),
|
||||
// Per-connector disabled-model selections gathered during onboarding.
|
||||
// Persisted against the new company's id once it is created, so they
|
||||
// are scoped correctly from the first moment the company exists.
|
||||
connectorPoolSelections: z
|
||||
.array(
|
||||
z.object({
|
||||
connectorId: connectorInputSchema.shape.id,
|
||||
disabledModels: z.array(z.object({ id: z.string(), label: z.string() })),
|
||||
}),
|
||||
)
|
||||
.default([]),
|
||||
});
|
||||
|
||||
export const socialAccountInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
platform: z.enum(["twitter", "linkedin", "instagram", "facebook", "reddit", "youtube", "tiktok", "bluesky", "discord", "threads", "pinterest", "telegram", "whatsapp", "wechat", "weibo", "xiaohongshu", "douyin", "bilibili", "zhihu", "other"]),
|
||||
accountName: z.string().min(1).max(120),
|
||||
displayName: z.string().max(120).default(""),
|
||||
profileUrl: z.string().max(500).default(""),
|
||||
credentialSecretId: optionalId,
|
||||
status: z.enum(["active", "logged_in", "login_required", "suspended", "paused"]).default("login_required"),
|
||||
requireApproval: z.boolean().default(true),
|
||||
metadataJson: z.string().default("{}"),
|
||||
});
|
||||
|
||||
export const secretInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
name: z.string().min(2).max(80),
|
||||
description: z.string().default(""),
|
||||
value: z.string().min(1).max(2000),
|
||||
});
|
||||
@@ -1,200 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const credentialKindSchema = z.enum([
|
||||
"oauth",
|
||||
"api_key",
|
||||
"aws",
|
||||
"azure",
|
||||
"gcp_adc",
|
||||
"local",
|
||||
]);
|
||||
|
||||
export const credentialStatusSchema = z.enum([
|
||||
"active",
|
||||
"expired",
|
||||
"revoked",
|
||||
"error",
|
||||
"not_configured",
|
||||
]);
|
||||
|
||||
export const apiKeyValueSchema = z.object({
|
||||
source: z.enum(["literal", "env"]),
|
||||
value: z.string().min(1),
|
||||
});
|
||||
|
||||
const AWS_REGION_SEGMENT = "[a-z]{2}(?:-gov)?-[a-z]+-\\d";
|
||||
const AWS_BEDROCK_RUNTIME_HOSTNAME = new RegExp(
|
||||
`^bedrock-runtime(?:-fips)?\\.${AWS_REGION_SEGMENT}\\.amazonaws\\.com(?:\\.cn)?$`,
|
||||
);
|
||||
const AWS_BEDROCK_VPCE_HOSTNAME = new RegExp(
|
||||
`^vpce-[a-z0-9-]+\\.bedrock-runtime(?:-fips)?\\.${AWS_REGION_SEGMENT}\\.vpce\\.amazonaws\\.com(?:\\.cn)?$`,
|
||||
);
|
||||
|
||||
export const azureCredentialSchema = z.object({
|
||||
apiKey: z.string().min(1),
|
||||
baseUrl: z.string().url().optional().or(z.literal("")),
|
||||
resourceName: z.string().optional().or(z.literal("")),
|
||||
apiVersion: z.string().optional().or(z.literal("")),
|
||||
deploymentMap: z.record(z.string(), z.string()).optional(),
|
||||
});
|
||||
|
||||
export const awsEndpointUrlSchema = z
|
||||
.string()
|
||||
.url()
|
||||
.refine(
|
||||
isAwsBedrockEndpointUrl,
|
||||
"AWS Bedrock endpointUrl must be an HTTPS AWS Bedrock runtime endpoint or a private endpoint.",
|
||||
);
|
||||
|
||||
export const awsCredentialSchema = z.object({
|
||||
authMode: z.enum(["profile", "iam", "bearer"]),
|
||||
region: z.string().min(1).default("us-east-1"),
|
||||
awsProfile: z.string().optional(),
|
||||
accessKeyId: z.string().optional(),
|
||||
secretAccessKey: z.string().optional(),
|
||||
sessionToken: z.string().optional(),
|
||||
bearerToken: z.string().optional(),
|
||||
forceCache: z.boolean().optional(),
|
||||
endpointUrl: awsEndpointUrlSchema.optional(),
|
||||
skipAuth: z.boolean().optional(),
|
||||
forceHttp1: z.boolean().optional(),
|
||||
});
|
||||
|
||||
export const gcpAdcCredentialSchema = z.object({
|
||||
project: z.string().min(1),
|
||||
location: z.string().min(1),
|
||||
credentialsPath: z.string().optional(),
|
||||
});
|
||||
|
||||
function normalizeUrlHostname(hostname: string): string {
|
||||
const trimmed = hostname.trim().toLowerCase();
|
||||
return trimmed.startsWith("[") && trimmed.endsWith("]")
|
||||
? trimmed.slice(1, -1)
|
||||
: trimmed;
|
||||
}
|
||||
|
||||
function parseIpv4(hostname: string): [number, number, number, number] | null {
|
||||
const parts = hostname.split(".");
|
||||
if (parts.length !== 4) return null;
|
||||
const octets = parts.map((part) => {
|
||||
if (!/^\d+$/.test(part)) return null;
|
||||
const value = Number(part);
|
||||
return Number.isInteger(value) && value >= 0 && value <= 255 ? value : null;
|
||||
});
|
||||
if (octets.some((part) => part === null)) return null;
|
||||
return octets as [number, number, number, number];
|
||||
}
|
||||
|
||||
function isPrivateIpv4(hostname: string): boolean {
|
||||
const octets = parseIpv4(hostname);
|
||||
if (!octets) return false;
|
||||
const [first, second] = octets;
|
||||
return first === 10
|
||||
|| first === 127
|
||||
|| (first === 172 && second >= 16 && second <= 31)
|
||||
|| (first === 192 && second === 168)
|
||||
|| (first === 169 && second === 254);
|
||||
}
|
||||
|
||||
function isPrivateIpv6(hostname: string): boolean {
|
||||
if (hostname === "::1") return true;
|
||||
return /^f[cd][0-9a-f]{2}:/i.test(hostname) || /^fe80:/i.test(hostname);
|
||||
}
|
||||
|
||||
function isPrivateNetworkHostname(hostname: string): boolean {
|
||||
return hostname === "localhost" || isPrivateIpv4(hostname) || isPrivateIpv6(hostname);
|
||||
}
|
||||
|
||||
function hasOnlyRootUrlPath(value: string): boolean {
|
||||
const trimmed = value.trim();
|
||||
if (trimmed.includes("?") || trimmed.includes("#")) return false;
|
||||
const schemeSeparator = trimmed.indexOf("://");
|
||||
if (schemeSeparator < 0) return false;
|
||||
const authorityAndPath = trimmed.slice(schemeSeparator + 3);
|
||||
const pathStart = authorityAndPath.indexOf("/");
|
||||
if (pathStart < 0) return true;
|
||||
return authorityAndPath.slice(pathStart) === "/";
|
||||
}
|
||||
|
||||
export function isLocalConnectorBaseUrl(value: string): boolean {
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(value);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
if (url.protocol !== "http:" && url.protocol !== "https:") return false;
|
||||
if (url.username || url.password) return false;
|
||||
const hostname = normalizeUrlHostname(url.hostname);
|
||||
return isPrivateNetworkHostname(hostname);
|
||||
}
|
||||
|
||||
export const localBaseUrlSchema = z
|
||||
.string()
|
||||
.url()
|
||||
.refine(
|
||||
isLocalConnectorBaseUrl,
|
||||
"Local connector baseUrl must use HTTP(S) with localhost, loopback, or a private IP host.",
|
||||
);
|
||||
|
||||
export const localCredentialSchema = z.object({
|
||||
baseUrl: localBaseUrlSchema,
|
||||
});
|
||||
|
||||
function isAwsBedrockHostname(hostname: string): boolean {
|
||||
return AWS_BEDROCK_RUNTIME_HOSTNAME.test(hostname) || AWS_BEDROCK_VPCE_HOSTNAME.test(hostname);
|
||||
}
|
||||
|
||||
export function isAwsBedrockEndpointUrl(value: string): boolean {
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(value);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
if (url.protocol !== "https:") return false;
|
||||
if (url.username || url.password) return false;
|
||||
if (!hasOnlyRootUrlPath(value)) return false;
|
||||
const hostname = normalizeUrlHostname(url.hostname);
|
||||
return isAwsBedrockHostname(hostname) || isPrivateNetworkHostname(hostname);
|
||||
}
|
||||
|
||||
export const credentialPayloadSchema = z.discriminatedUnion("kind", [
|
||||
z.object({ kind: z.literal("api_key"), value: apiKeyValueSchema }),
|
||||
z.object({ kind: z.literal("azure"), value: azureCredentialSchema }),
|
||||
z.object({ kind: z.literal("aws"), value: awsCredentialSchema }),
|
||||
z.object({ kind: z.literal("gcp_adc"), value: gcpAdcCredentialSchema }),
|
||||
z.object({ kind: z.literal("local"), value: localCredentialSchema }),
|
||||
]);
|
||||
|
||||
export const saveCredentialInputSchema = z.object({
|
||||
connectorId: z.string().min(1),
|
||||
payload: credentialPayloadSchema,
|
||||
});
|
||||
|
||||
export const removeCredentialInputSchema = z.object({
|
||||
connectorId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const testCredentialInputSchema = z.object({
|
||||
connectorId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const credentialSummarySchema = z.object({
|
||||
connectorId: z.string(),
|
||||
kind: credentialKindSchema,
|
||||
displayHint: z.string(),
|
||||
status: credentialStatusSchema,
|
||||
expiresAt: z.string().nullable(),
|
||||
lastRefreshedAt: z.string().nullable(),
|
||||
lastError: z.string().nullable(),
|
||||
updatedAt: z.string().nullable(),
|
||||
});
|
||||
|
||||
export type CredentialSummary = z.infer<typeof credentialSummarySchema>;
|
||||
export type SaveCredentialInput = z.infer<typeof saveCredentialInputSchema>;
|
||||
export type AwsCredential = z.infer<typeof awsCredentialSchema>;
|
||||
export type AzureCredential = z.infer<typeof azureCredentialSchema>;
|
||||
export type GcpAdcCredential = z.infer<typeof gcpAdcCredentialSchema>;
|
||||
export type LocalCredential = z.infer<typeof localCredentialSchema>;
|
||||
export type ApiKeyValue = z.infer<typeof apiKeyValueSchema>;
|
||||
@@ -1,135 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { automationTriggerEnum } from "./helpers";
|
||||
|
||||
export const startRunSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
taskId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const cancelRunSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
runId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const recoveryRetrySchema = z.object({
|
||||
taskId: z.string().uuid(),
|
||||
agentId: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const recoveryTaskSchema = z.object({
|
||||
taskId: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const runLogSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
runId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const runLogChunkSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
runId: z.string().uuid(),
|
||||
offset: z.number().int().min(0).default(0),
|
||||
limit: z.number().int().min(1024).max(262_144).default(65_536),
|
||||
});
|
||||
|
||||
export const triggerBrowserLoginSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
socialAccountId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const browserActionQuerySchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
socialAccountId: z.string().uuid().optional(),
|
||||
status: z.string().optional(),
|
||||
limit: z.number().int().min(1).max(100).default(50),
|
||||
});
|
||||
|
||||
export const cancelBrowserActionSchema = z.object({
|
||||
actionId: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const workflowInputSchema = z.object({
|
||||
id: z.preprocess((v) => (v === "" ? null : v), z.string().uuid().nullable().optional()),
|
||||
companyId: z.string().uuid(),
|
||||
name: z.string().min(2).max(120),
|
||||
description: z.string().max(500).default(""),
|
||||
stepsJson: z.string().default("[]"),
|
||||
triggerType: automationTriggerEnum,
|
||||
triggerConfigJson: z.string().default("{}"),
|
||||
status: z.enum(["draft", "active", "paused", "completed", "failed"]).default("draft"),
|
||||
});
|
||||
|
||||
export const runWorkflowSchema = z.object({
|
||||
id: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const importSkillSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
source: z.string().min(1),
|
||||
});
|
||||
|
||||
export const listSkillsSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const getSkillDetailSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
skillId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const getSkillMarkdownSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
slug: z.string().min(1),
|
||||
});
|
||||
|
||||
export const deleteSkillSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
skillId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const assignSkillToAgentSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
agentId: z.string().min(1),
|
||||
skillId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const removeSkillFromAgentSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
agentId: z.string().min(1),
|
||||
skillId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const checkSkillUpdateSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
skillId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const listSkillAgentsSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
skillId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const listAgentSkillsSchema = z.object({
|
||||
companyId: z.string().min(1),
|
||||
agentId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const terminalCommandKeys = [
|
||||
"install_node_darwin",
|
||||
"install_node_win32",
|
||||
"install_node_linux",
|
||||
"install_claude_unix",
|
||||
"install_claude_win32",
|
||||
"install_codex",
|
||||
"install_gemini",
|
||||
] as const;
|
||||
|
||||
export type TerminalCommandKey = (typeof terminalCommandKeys)[number];
|
||||
|
||||
export const openTerminalCommandSchema = z.object({
|
||||
commandKey: z.enum(terminalCommandKeys),
|
||||
});
|
||||
@@ -1,140 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { canonicalJsonString, jsonArraySchema, jsonStringArraySchema, meetingActionItemArraySchema } from "./json-fields";
|
||||
import { MESSAGE_CHANNELS, optionalId } from "./helpers";
|
||||
|
||||
export const agentMessageInputSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
fromAgentId: z.union([z.string().uuid(), z.literal("__board__")]),
|
||||
toAgentId: z.preprocess(
|
||||
(v) => (v === "" ? null : v),
|
||||
z.union([z.string().uuid(), z.literal("__board__")]).nullable().optional(),
|
||||
),
|
||||
channel: MESSAGE_CHANNELS.default("direct"),
|
||||
channelTargetId: z.string().nullable().optional(),
|
||||
subject: z.preprocess((v) => (v === "" ? "(no subject)" : v), z.string().min(1).max(200)),
|
||||
body: z.string().min(1).max(8000),
|
||||
priority: z.enum(["urgent", "normal", "low"]).default("normal"),
|
||||
parentMessageId: z.preprocess((v) => (v === "" ? null : v), z.string().uuid().nullable().optional()),
|
||||
attachmentsJson: z.string().default("[]"),
|
||||
threadId: z.preprocess((v) => (v === "" ? null : v), z.string().uuid().nullable().optional()),
|
||||
waitStateId: z.preprocess((v) => (v === "" ? null : v), z.string().uuid().nullable().optional()),
|
||||
}).superRefine((value, ctx) => {
|
||||
if (value.channel === "direct" && !value.toAgentId) {
|
||||
ctx.addIssue({
|
||||
path: ["toAgentId"],
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "Direct messages require toAgentId.",
|
||||
});
|
||||
}
|
||||
|
||||
if ((value.channel === "department" || value.channel === "project") && !value.channelTargetId) {
|
||||
ctx.addIssue({
|
||||
path: ["channelTargetId"],
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: `${value.channel} messages require channelTargetId.`,
|
||||
});
|
||||
}
|
||||
|
||||
if (value.channel !== "direct" && value.toAgentId) {
|
||||
ctx.addIssue({
|
||||
path: ["toAgentId"],
|
||||
code: z.ZodIssueCode.custom,
|
||||
message: "Only direct messages may set toAgentId.",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
export const messageQuerySchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
agentId: z.string().uuid().optional(),
|
||||
channel: MESSAGE_CHANNELS.optional(),
|
||||
channelTargetId: z.string().nullable().optional(),
|
||||
unreadOnly: z.boolean().optional(),
|
||||
limit: z.number().int().min(1).max(500).default(200),
|
||||
});
|
||||
|
||||
export const searchMessagesSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
query: z.string().min(1).max(200),
|
||||
channel: MESSAGE_CHANNELS.optional(),
|
||||
channelTargetId: z.string().nullable().optional(),
|
||||
limit: z.number().int().min(1).max(100).default(50),
|
||||
});
|
||||
|
||||
export const commentInputSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
taskId: z.string().uuid(),
|
||||
authorAgentId: optionalId,
|
||||
authorName: z.string().min(1).max(80),
|
||||
body: z.string().min(1).max(4000),
|
||||
});
|
||||
|
||||
export const listCommentsSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
taskId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const documentInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
type: z.enum(["prd", "technical_spec", "design_doc", "test_plan", "post_mortem", "meeting_notes", "budget_proposal", "hiring_requisition", "performance_review_doc", "sop", "knowledge_article", "project_brief", "sprint_report", "incident_report", "onboarding_guide", "architecture_decision", "status_report", "contract", "proposal"]),
|
||||
title: z.string().min(2).max(200),
|
||||
content: z.string().default(""),
|
||||
authorAgentId: optionalId,
|
||||
reviewerAgentId: optionalId,
|
||||
projectId: optionalId,
|
||||
goalId: optionalId,
|
||||
parentDocId: optionalId,
|
||||
version: z.number().int().min(1).default(1),
|
||||
status: z.enum(["draft", "in_review", "approved", "archived", "superseded"]).default("draft"),
|
||||
tagsJson: canonicalJsonString(jsonStringArraySchema, []),
|
||||
});
|
||||
|
||||
export const knowledgeEntryInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
category: z.enum(["lesson_learned", "best_practice", "decision", "process", "technical", "business", "onboarding", "incident"]),
|
||||
topic: z.string().min(2).max(200),
|
||||
content: z.string().min(1),
|
||||
authorAgentId: optionalId,
|
||||
importance: z.enum(["critical", "high", "medium", "low"]).default("medium"),
|
||||
tagsJson: canonicalJsonString(jsonStringArraySchema, []),
|
||||
referencedEntityType: z.enum([
|
||||
"agents",
|
||||
"goals",
|
||||
"projects",
|
||||
"tasks",
|
||||
"approvals",
|
||||
"runs",
|
||||
"secrets",
|
||||
"meetings",
|
||||
"documents",
|
||||
"knowledge_base",
|
||||
"sprints",
|
||||
"automation_rules",
|
||||
"workflow_pipelines",
|
||||
]).nullable().optional(),
|
||||
referencedEntityId: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
export const meetingInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
type: z.enum(["standup", "sprint_planning", "sprint_review", "retrospective", "one_on_one", "all_hands", "department_sync", "incident_review", "hiring_committee", "budget_review", "design_review", "architecture_review"]),
|
||||
title: z.string().min(2).max(160),
|
||||
organizerAgentId: optionalId,
|
||||
participantAgentIds: canonicalJsonString(jsonStringArraySchema, []),
|
||||
scheduledAt: z.string(),
|
||||
durationMinutes: z.number().int().min(5).max(480).default(30),
|
||||
agendaJson: canonicalJsonString(jsonArraySchema, []),
|
||||
notesJson: canonicalJsonString(jsonArraySchema, []),
|
||||
decisionsJson: canonicalJsonString(jsonArraySchema, []),
|
||||
actionItemsJson: canonicalJsonString(meetingActionItemArraySchema, []),
|
||||
status: z.enum(["scheduled", "in_progress", "completed", "cancelled"]).default("scheduled"),
|
||||
});
|
||||
|
||||
export const markMessageReadSchema = z.object({
|
||||
messageId: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
readerAgentId: optionalId,
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
// Barrel re-export. Canonical domain files live alongside.
|
||||
// New code should import directly from the domain file.
|
||||
export * from "./schemas-badges";
|
||||
export * from "./schemas-automation";
|
||||
export * from "./schemas-budget";
|
||||
export * from "./schemas-threads";
|
||||
@@ -1,31 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const oauthStartInputSchema = z.object({
|
||||
connectorId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const oauthCancelInputSchema = z.object({
|
||||
connectorId: z.string().min(1),
|
||||
});
|
||||
|
||||
export const oauthPromptResponseSchema = z.object({
|
||||
connectorId: z.string().min(1),
|
||||
requestId: z.string().min(1),
|
||||
value: z.string(),
|
||||
});
|
||||
|
||||
export const oauthManualCodeResponseSchema = z.object({
|
||||
connectorId: z.string().min(1),
|
||||
requestId: z.string().min(1),
|
||||
code: z.string().min(1),
|
||||
});
|
||||
|
||||
// Event shapes (OAuthStatusEvent, OAuthAuthUrlEvent, OAuthProgressEvent,
|
||||
// OAuthPromptRequestEvent, OAuthManualCodeRequestEvent) live in
|
||||
// `shared/types/events.ts` — that's the runtime shape emitted by
|
||||
// `oauth-login-service` and consumed by the renderer via `DesktopEvent`.
|
||||
// This module only owns the renderer→main request schemas.
|
||||
|
||||
export type OAuthStartInput = z.infer<typeof oauthStartInputSchema>;
|
||||
export type OAuthPromptResponseInput = z.infer<typeof oauthPromptResponseSchema>;
|
||||
export type OAuthManualCodeResponseInput = z.infer<typeof oauthManualCodeResponseSchema>;
|
||||
@@ -1,56 +0,0 @@
|
||||
import { z } from "zod";
|
||||
import { optionalId } from "./helpers";
|
||||
|
||||
export const goalInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
title: z.string().min(2).max(120),
|
||||
description: z.string().default(""),
|
||||
parentId: optionalId,
|
||||
ownerAgentId: optionalId,
|
||||
status: z.enum(["planned", "active", "achieved", "cancelled"]).default("planned"),
|
||||
});
|
||||
|
||||
export const projectInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
goalId: optionalId,
|
||||
name: z.string().min(2).max(120),
|
||||
description: z.string().default(""),
|
||||
leadAgentId: optionalId,
|
||||
targetDate: z.string().nullable().optional(),
|
||||
status: z.enum(["backlog", "planned", "in_progress", "completed", "cancelled"]).default("planned"),
|
||||
});
|
||||
|
||||
export const taskInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
projectId: optionalId,
|
||||
goalId: optionalId,
|
||||
parentId: optionalId,
|
||||
title: z.string().min(2).max(160),
|
||||
description: z.string().default(""),
|
||||
assigneeAgentId: optionalId,
|
||||
workspaceId: optionalId,
|
||||
requiresFilesystem: z.boolean().default(false),
|
||||
priority: z.enum(["critical", "high", "medium", "low"]).default("medium"),
|
||||
status: z.enum(["backlog", "todo", "in_progress", "in_review", "done", "blocked", "cancelled"]).default("todo"),
|
||||
});
|
||||
|
||||
export const sprintInputSchema = z.object({
|
||||
id: optionalId,
|
||||
companyId: z.string().uuid(),
|
||||
name: z.string().min(2).max(120),
|
||||
goal: z.string().default(""),
|
||||
startDate: z.string(),
|
||||
endDate: z.string(),
|
||||
status: z.enum(["planning", "active", "review", "completed", "cancelled"]).default("planning"),
|
||||
retrospectiveNotes: z.string().default(""),
|
||||
velocityPoints: z.number().int().min(0).default(0),
|
||||
completedPoints: z.number().int().min(0).default(0),
|
||||
});
|
||||
|
||||
export const autoAssignSchema = z.object({
|
||||
taskId: z.string().uuid(),
|
||||
companyId: z.string().uuid(),
|
||||
});
|
||||
@@ -1,23 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const threadGetterSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
threadId: z.string().uuid(),
|
||||
});
|
||||
|
||||
export const listThreadEventsSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
threadId: z.string().uuid(),
|
||||
limit: z.number().int().min(1).max(100).default(50),
|
||||
offset: z.number().int().min(0).default(0),
|
||||
});
|
||||
|
||||
export const listThreadWaitStatesSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
resolvedOnly: z.boolean().default(false),
|
||||
});
|
||||
|
||||
export const listThreadParticipantsSchema = z.object({
|
||||
companyId: z.string().uuid(),
|
||||
threadId: z.string().uuid(),
|
||||
});
|
||||
@@ -1,45 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export const workProductTypeEnum = z.enum([
|
||||
"file",
|
||||
"link",
|
||||
"pull_request",
|
||||
"branch",
|
||||
"commit",
|
||||
"artifact",
|
||||
"document",
|
||||
"preview_url",
|
||||
"runtime_service",
|
||||
]);
|
||||
|
||||
export const workProductProviderEnum = z.enum([
|
||||
"filesystem",
|
||||
"external",
|
||||
"agentcompany",
|
||||
"github",
|
||||
"custom",
|
||||
]);
|
||||
|
||||
export const workProductStatusEnum = z.enum([
|
||||
"active",
|
||||
"ready_for_review",
|
||||
"approved",
|
||||
"merged",
|
||||
"closed",
|
||||
"failed",
|
||||
"draft",
|
||||
"archived",
|
||||
]);
|
||||
|
||||
export const workProductReviewStateEnum = z.enum([
|
||||
"none",
|
||||
"needs_board_review",
|
||||
"approved",
|
||||
"changes_requested",
|
||||
]);
|
||||
|
||||
export type WorkProductType = z.infer<typeof workProductTypeEnum>;
|
||||
export type WorkProductProvider = z.infer<typeof workProductProviderEnum>;
|
||||
export type WorkProductStatus = z.infer<typeof workProductStatusEnum>;
|
||||
export type WorkProductReviewState = z.infer<typeof workProductReviewStateEnum>;
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
import type { DesktopResult } from "./result";
|
||||
import type { AppSnapshot, SearchResultRecord } from "./domain";
|
||||
import type { ProviderModelEntry } from "./provider-models";
|
||||
import type {
|
||||
BindSkillInput,
|
||||
BootstrapOnboardingInput,
|
||||
BootstrapOnboardingSummary,
|
||||
CancelProviderResponseInput,
|
||||
CreateAgentInput,
|
||||
UpdateAgentInput,
|
||||
CreateApprovalInput,
|
||||
CreateAutomationRuleInput,
|
||||
CreateDocumentInput,
|
||||
CreateGoalInput,
|
||||
CreateMeetingInput,
|
||||
CreateSprintInput,
|
||||
DeleteMeetingInput,
|
||||
DeleteSprintInput,
|
||||
CreateKnowledgeEntryInput,
|
||||
CreateProjectInput,
|
||||
CreateWorkspaceInput,
|
||||
DeleteAutomationRuleInput,
|
||||
DeleteDocumentInput,
|
||||
DeleteTaskInput,
|
||||
DeleteKnowledgeEntryInput,
|
||||
UpdateAutomationRuleInput,
|
||||
UpdateDocumentInput,
|
||||
UpdateTaskInput,
|
||||
CreateAuditReplayInput,
|
||||
CreateChatSpaceInput,
|
||||
CreateComplianceExportInput,
|
||||
CreateLegalHoldInput,
|
||||
CreateMigrationReportInput,
|
||||
CheckProviderHealthInput,
|
||||
ListProviderModelsInput,
|
||||
StartProviderOAuthInput,
|
||||
StartProviderOAuthResult,
|
||||
CancelProviderOAuthInput,
|
||||
MarkChatSpaceReadInput,
|
||||
CreateOrganizationInput,
|
||||
CreateProviderResponseInput,
|
||||
CreateRetentionFreezeInput,
|
||||
CreateRollbackSnapshotInput,
|
||||
CreateScheduledPostInput,
|
||||
CreateSocialAccountInput,
|
||||
CreateTaskInput,
|
||||
DecideApprovalInput,
|
||||
DeleteMessageInput,
|
||||
DeleteOrganizationInput,
|
||||
EditMessageInput,
|
||||
ImportFileInput,
|
||||
OpenFileInput,
|
||||
ImportSkillDirectoryInput,
|
||||
GrantRoleInput,
|
||||
LaunchProviderSignInInput,
|
||||
LaunchSocialLoginInput,
|
||||
ResolveAgentSkillsInput,
|
||||
ResolveMigrationReconciliationInput,
|
||||
RunChaosDrillInput,
|
||||
RunEvalSuiteInput,
|
||||
RunSdlcReviewInput,
|
||||
RunSkillTestsInput,
|
||||
RunTaskInput,
|
||||
RevokeProviderCredentialInput,
|
||||
SaveProviderCredentialInput,
|
||||
SaveComposioSettingsInput,
|
||||
ComposioToolkitSummaryDto,
|
||||
ConnectComposioToolkitInput,
|
||||
ConnectComposioToolkitResult,
|
||||
ConnectorGrantInput,
|
||||
ListComposioToolkitsInput,
|
||||
RefreshComposioAccountsInput,
|
||||
SearchInput,
|
||||
SendMessageInput,
|
||||
SetActiveOrganizationInput,
|
||||
SetFilePinnedInput,
|
||||
SetFeatureFlagInput,
|
||||
SetLegalHoldStateInput,
|
||||
SetPrBotGateInput,
|
||||
SetRollbackSnapshotActiveInput,
|
||||
SetRetentionFreezeStateInput,
|
||||
SetScheduledPostStateInput,
|
||||
StreamProviderResponseInput,
|
||||
SyncEmployeeIdentityInput,
|
||||
UpdateProviderPolicyInput,
|
||||
UpdateTaskStatusInput,
|
||||
} from "./commands";
|
||||
import type { ProviderStreamRendererEvent } from "./provider-request-domain";
|
||||
|
||||
export type ProviderOAuthPhase = "authorize" | "progress" | "active" | "error" | "cancelled";
|
||||
|
||||
export interface ProviderOAuthEvent {
|
||||
type: "provider-oauth";
|
||||
providerKey: string;
|
||||
phase: ProviderOAuthPhase;
|
||||
url?: string;
|
||||
instructions?: string;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export type RendererEvent =
|
||||
| { type: "snapshot-changed" }
|
||||
| { type: "provider-response-stream"; event: ProviderStreamRendererEvent }
|
||||
| ProviderOAuthEvent;
|
||||
|
||||
export interface DesktopApi {
|
||||
loadSnapshot(): Promise<DesktopResult<AppSnapshot>>;
|
||||
bootstrapOnboarding(input: BootstrapOnboardingInput): Promise<DesktopResult<BootstrapOnboardingSummary>>;
|
||||
setActiveOrganization(input: SetActiveOrganizationInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
deleteOrganization(input: DeleteOrganizationInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createOrganization(input: CreateOrganizationInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createAgent(input: CreateAgentInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
updateAgent(input: UpdateAgentInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createTask(input: CreateTaskInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
updateTask(input: UpdateTaskInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
deleteTask(input: DeleteTaskInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
updateTaskStatus(input: UpdateTaskStatusInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
runTask(input: RunTaskInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createGoal(input: CreateGoalInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createProject(input: CreateProjectInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createWorkspace(input: CreateWorkspaceInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createDocument(input: CreateDocumentInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
updateDocument(input: UpdateDocumentInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
deleteDocument(input: DeleteDocumentInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createKnowledgeEntry(input: CreateKnowledgeEntryInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
deleteKnowledgeEntry(input: DeleteKnowledgeEntryInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createAutomationRule(input: CreateAutomationRuleInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
updateAutomationRule(input: UpdateAutomationRuleInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
deleteAutomationRule(input: DeleteAutomationRuleInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createMeeting(input: CreateMeetingInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
deleteMeeting(input: DeleteMeetingInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createSprint(input: CreateSprintInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
deleteSprint(input: DeleteSprintInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createApproval(input: CreateApprovalInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
decideApproval(input: DecideApprovalInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
syncEmployeeIdentity(input: SyncEmployeeIdentityInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
grantRole(input: GrantRoleInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createChatSpace(input: CreateChatSpaceInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
sendMessage(input: SendMessageInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
editMessage(input: EditMessageInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
deleteMessage(input: DeleteMessageInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
markChatSpaceRead(input: MarkChatSpaceReadInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
saveProviderCredential(input: SaveProviderCredentialInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
revokeProviderCredential(input: RevokeProviderCredentialInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
launchProviderSignIn(input: LaunchProviderSignInInput): Promise<DesktopResult<null>>;
|
||||
startProviderOAuth(input: StartProviderOAuthInput): Promise<DesktopResult<StartProviderOAuthResult>>;
|
||||
cancelProviderOAuth(input: CancelProviderOAuthInput): Promise<DesktopResult<null>>;
|
||||
checkProviderHealth(input: CheckProviderHealthInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
listProviderModels(input: ListProviderModelsInput): Promise<DesktopResult<ProviderModelEntry[]>>;
|
||||
updateProviderPolicy(input: UpdateProviderPolicyInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
openExternalUrl(url: string): Promise<DesktopResult<null>>;
|
||||
createProviderResponse(input: CreateProviderResponseInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
streamProviderResponse(input: StreamProviderResponseInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
cancelProviderResponse(input: CancelProviderResponseInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
importSkillDirectory(input: ImportSkillDirectoryInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
bindSkill(input: BindSkillInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
resolveAgentSkills(input: ResolveAgentSkillsInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
runSkillTests(input: RunSkillTestsInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createSocialAccount(input: CreateSocialAccountInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
launchSocialLogin(input: LaunchSocialLoginInput): Promise<DesktopResult<null>>;
|
||||
createScheduledPost(input: CreateScheduledPostInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
setScheduledPostState(input: SetScheduledPostStateInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
importFile(input: ImportFileInput): Promise<DesktopResult<string | null>>;
|
||||
openFile(input: OpenFileInput): Promise<DesktopResult<null>>;
|
||||
pickDirectory(): Promise<DesktopResult<string | null>>;
|
||||
setFilePinned(input: SetFilePinnedInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createMigrationReport(input: CreateMigrationReportInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createRollbackSnapshot(input: CreateRollbackSnapshotInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
setRollbackSnapshotActive(input: SetRollbackSnapshotActiveInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
resolveMigrationReconciliation(input: ResolveMigrationReconciliationInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
setFeatureFlag(input: SetFeatureFlagInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
runChaosDrill(input: RunChaosDrillInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
runSdlcReview(input: RunSdlcReviewInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
runEvalSuite(input: RunEvalSuiteInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
setPrBotGate(input: SetPrBotGateInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createComplianceExport(input: CreateComplianceExportInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createAuditReplay(input: CreateAuditReplayInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createLegalHold(input: CreateLegalHoldInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
setLegalHoldState(input: SetLegalHoldStateInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
createRetentionFreeze(input: CreateRetentionFreezeInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
setRetentionFreezeState(input: SetRetentionFreezeStateInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
saveComposioSettings(input: SaveComposioSettingsInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
listComposioToolkits(input: ListComposioToolkitsInput): Promise<DesktopResult<ComposioToolkitSummaryDto[]>>;
|
||||
connectComposioToolkit(input: ConnectComposioToolkitInput): Promise<DesktopResult<ConnectComposioToolkitResult>>;
|
||||
refreshComposioAccounts(input: RefreshComposioAccountsInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
grantConnector(input: ConnectorGrantInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
revokeConnector(input: ConnectorGrantInput): Promise<DesktopResult<AppSnapshot>>;
|
||||
search(input: SearchInput): Promise<DesktopResult<SearchResultRecord[]>>;
|
||||
subscribe(callback: (event: RendererEvent) => void): () => void;
|
||||
platform: "win32" | "darwin" | "linux";
|
||||
windowMinimize(): Promise<void>;
|
||||
windowMaximize(): Promise<void>;
|
||||
windowClose(): Promise<void>;
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/**
|
||||
* Document type categories shared between db, route handlers, and clients.
|
||||
*
|
||||
* IMPORTANT_DOC_TYPES are the document types that trigger deliverable-review
|
||||
* approvals (PRDs, specs, design docs, contracts, etc.). The ordering matters
|
||||
* for some lookup queries; keep this in sync with database/documents.ts.
|
||||
*/
|
||||
export const IMPORTANT_DOC_TYPES = [
|
||||
"prd",
|
||||
"technical_spec",
|
||||
"design_doc",
|
||||
"project_brief",
|
||||
"proposal",
|
||||
"budget_proposal",
|
||||
"architecture_decision",
|
||||
"contract",
|
||||
"sop",
|
||||
] as const;
|
||||
|
||||
export const IMPORTANT_DOC_TYPE_SET: ReadonlySet<string> = new Set(IMPORTANT_DOC_TYPES);
|
||||
@@ -0,0 +1,449 @@
|
||||
import type { ProviderDataPolicy } from "./provider-policy-domain";
|
||||
export { BOARD_INTERVENTION_ACTION, BOARD_INTERVENTION_MODE, CHAT_THREAD_BOARD_STATE, type BoardInterventionAction, type BoardInterventionMode, type BoardInterventionRecord, type ChatThreadBoardState } from "./board-domain";
|
||||
export type { ChatSpaceRecord, ChatMessageRecord, ChatMembershipRecord, ChatThreadRecord, ChatAttachmentRecord, ChatMentionRecord, ChatSlashInvocationRecord, ChatPresenceRecord, ChatReadStateRecord } from "./chat-domain";
|
||||
export type { AuditReplayRunRecord } from "./audit-domain";
|
||||
export { COMPLIANCE_EXPORT_STATE, COMPLIANCE_EXPORT_TYPE, type ComplianceExportRecord, type ComplianceExportState, type ComplianceExportType, type ComplianceSubjectType, type LegalHoldEntityType, type LegalHoldRecord, type RetentionFreezeRecord, type RetentionFreezeScopeType } from "./compliance-domain";
|
||||
export { ACCESS_DECISION, IDENTITY_SOURCE, ROLE_KEY, type AccessDecision, type AccessDecisionRecord, type EmployeeIdentityRecord, type IdentitySource, type PrincipalType, type RoleGrantRecord, type RoleKey, type ServiceIdentityRecord } from "./identity-domain";
|
||||
export { ROUTE_TO_TYPE, type ApprovalAssignmentRecord, type ApprovalRoutingRuleRecord, type HiringPolicyRecord, type OrgDepartmentRecord, type RouteToType } from "./org-governance-domain";
|
||||
export { CHAOS_DRILL_SCENARIO, CHAOS_DRILL_STATE, FEATURE_FLAG_KEY, SLO_SIGNAL_KEY, type ChaosDrillRecord, type ChaosDrillRunRecord, type ChaosDrillScenario, type ChaosDrillState, type FeatureFlagKey, type FeatureFlagRecord, type OperationalEventRecord, type SloSignalKey, type SloTargetRecord } from "./operations-domain";
|
||||
export type { ProviderAuthProfileRecord, ProviderAuthSessionRecord } from "./provider-auth-domain";
|
||||
export { PROVIDER_DATA_POLICY, PROVIDER_EXECUTION_MODE, type ProviderDataPolicy, type ProviderExecutionMode } from "./provider-policy-domain";
|
||||
export { PROVIDER_REQUEST_STATE, type ProviderRequestRecord, type ProviderRequestState, type ProviderStreamRendererEvent } from "./provider-request-domain";
|
||||
export type { ProviderRateLimitObservationRecord, ProviderRateLimitStateRecord } from "./provider-runtime-domain";
|
||||
export type { MigrationCutoverEventRecord, MigrationReconciliationItemRecord, RollbackSnapshotRecord } from "./rollback-domain";
|
||||
export { EVAL_SUITE_KEY, PR_BOT_GATE_KEY, SDLC_REVIEW_AGENT_KEY, SDLC_REVIEW_TARGET_TYPE, SDLC_RUN_STATE, type EvalCaseRecord, type EvalRunRecord, type EvalSuiteKey, type EvalSuiteRecord, type PrBotGateKey, type PrBotGateRecord, type SdlcReviewAgentKey, type SdlcReviewAgentRecord, type SdlcReviewRunRecord, type SdlcReviewTargetType, type SdlcRunState } from "./sdlc-domain";
|
||||
export { SEARCH_ENTITY_TYPES, type SearchEntityType, type SearchResultRecord } from "./search-domain";
|
||||
export type { BrowserActionPolicyRecord, BrowserActionRecord, BrowserSessionContainerRecord, SocialAccountGrantRecord, SocialAccountRecord, SocialApprovalRouteRecord, SocialAuditRecord } from "./social-domain";
|
||||
export type { AppSnapshot } from "./snapshot-domain";
|
||||
export const TASK_STATUS = { BACKLOG: "backlog", IN_PROGRESS: "in_progress", REVIEW: "review", DONE: "done" } as const;
|
||||
export const APPROVAL_STATE = { PENDING: "pending", APPROVED: "approved", DECLINED: "declined" } as const;
|
||||
export const RISK_LEVEL = { LOW: "low", MEDIUM: "medium", HIGH: "high" } as const;
|
||||
export const TASK_PRIORITY = { LOW: "low", NORMAL: "normal", HIGH: "high" } as const;
|
||||
export const PROVIDER_AUTH_TYPE = { API_KEY: "api_key", OAUTH_PKCE: "oauth_pkce", ACCOUNT_SUBSCRIPTION: "account_subscription", CLOUD: "cloud" } as const;
|
||||
export const SOCIAL_PLATFORM = { X: "x", LINKEDIN: "linkedin", YOUTUBE: "youtube", INSTAGRAM: "instagram" } as const;
|
||||
export const FILE_SCAN_STATE = { APPROVED: "approved", BLOCKED: "blocked" } as const;
|
||||
|
||||
export type ValueOf<T> = T[keyof T];
|
||||
export type TaskStatus = ValueOf<typeof TASK_STATUS>;
|
||||
export type ApprovalState = ValueOf<typeof APPROVAL_STATE>;
|
||||
export type RiskLevel = ValueOf<typeof RISK_LEVEL>;
|
||||
export type TaskPriority = ValueOf<typeof TASK_PRIORITY>;
|
||||
export type ProviderAuthType = ValueOf<typeof PROVIDER_AUTH_TYPE>;
|
||||
export type SocialPlatform = ValueOf<typeof SOCIAL_PLATFORM>;
|
||||
export type FileScanState = ValueOf<typeof FILE_SCAN_STATE>;
|
||||
|
||||
export interface OrganizationRecord {
|
||||
id: string;
|
||||
name: string;
|
||||
mission: string;
|
||||
goal: string;
|
||||
description: string;
|
||||
executionMode: string;
|
||||
autoApproveHires: boolean;
|
||||
reviewDeliverables: boolean;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface EmployeeRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
displayName: string;
|
||||
role: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface AgentRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
name: string;
|
||||
role: string;
|
||||
department: string;
|
||||
modelProviderId: string | null;
|
||||
modelId: string | null;
|
||||
budgetCents: number;
|
||||
managerAgentId: string | null;
|
||||
title: string;
|
||||
roleLevel: string;
|
||||
modelStrategy: string;
|
||||
workspaceId: string | null;
|
||||
heartbeatEnabled: boolean;
|
||||
heartbeatIntervalSec: number;
|
||||
lifecycle: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface TaskRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
title: string;
|
||||
description: string;
|
||||
status: TaskStatus;
|
||||
assigneeAgentId: string | null;
|
||||
risk: RiskLevel;
|
||||
projectId: string | null;
|
||||
goalId: string | null;
|
||||
workspaceId: string | null;
|
||||
priority: TaskPriority;
|
||||
parentTaskId: string | null;
|
||||
requiresFilesystem: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface WorkspaceRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
name: string;
|
||||
localPath: string;
|
||||
repoUrl: string;
|
||||
repoRef: string;
|
||||
projectId: string | null;
|
||||
isPrimary: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface GoalRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
title: string;
|
||||
description: string;
|
||||
status: string;
|
||||
ownerAgentId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ProjectRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
goalId: string | null;
|
||||
name: string;
|
||||
description: string;
|
||||
leadAgentId: string | null;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface TaskRunRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
taskId: string;
|
||||
agentId: string | null;
|
||||
providerId: string | null;
|
||||
providerRequestId: string | null;
|
||||
executionContextId: string | null;
|
||||
serviceIdentityId: string | null;
|
||||
workspaceMountJson: string;
|
||||
secretScopeJson: string;
|
||||
trigger: string;
|
||||
state: string;
|
||||
createdAt: string;
|
||||
startedAt: string | null;
|
||||
completedAt: string | null;
|
||||
errorMessage: string | null;
|
||||
}
|
||||
|
||||
export interface ApprovalRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
kind: string;
|
||||
title: string;
|
||||
details: string;
|
||||
risk: RiskLevel;
|
||||
requestedByType: "employee" | "agent" | "system";
|
||||
requestedById: string | null;
|
||||
sourceEntityType: string | null;
|
||||
sourceEntityId: string | null;
|
||||
state: ApprovalState;
|
||||
decisionNotes: string | null;
|
||||
decidedByEmployeeId: string | null;
|
||||
createdAt: string;
|
||||
decidedAt: string | null;
|
||||
}
|
||||
|
||||
export interface MeetingRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
title: string;
|
||||
meetingType: string;
|
||||
status: string;
|
||||
scheduledAt: string | null;
|
||||
durationMinutes: number;
|
||||
agenda: string;
|
||||
notes: string;
|
||||
decisions: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SprintRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
name: string;
|
||||
goal: string;
|
||||
status: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
velocityPoints: number;
|
||||
completedPoints: number;
|
||||
retrospective: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface FileObjectRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
name: string;
|
||||
kind: string;
|
||||
sizeBytes: number;
|
||||
sha256: string;
|
||||
storagePath: string;
|
||||
ownerType: "employee" | "agent" | "system";
|
||||
ownerId: string | null;
|
||||
spaceId: string | null;
|
||||
pinned: boolean;
|
||||
scanState: FileScanState;
|
||||
scanLabelsJson: string;
|
||||
scannedAt: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string | null;
|
||||
}
|
||||
|
||||
export interface FileAccessGrantRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
fileId: string;
|
||||
grantedToType: "employee" | "agent" | "board" | "org_group";
|
||||
grantedToId: string;
|
||||
grantedByType: "employee" | "agent" | "board" | "system";
|
||||
grantedById: string | null;
|
||||
sourceMessageId: string | null;
|
||||
sourceThreadId: string | null;
|
||||
accessLevel: "read" | "manage";
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface FileHandoffRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
messageId: string;
|
||||
fileId: string;
|
||||
sourcePrincipalType: "employee" | "agent" | "board" | "system";
|
||||
sourcePrincipalId: string | null;
|
||||
targetPrincipalType: "employee" | "agent" | "board" | "org_group";
|
||||
targetPrincipalId: string;
|
||||
transferType: string;
|
||||
checksum: string;
|
||||
scanState: FileScanState;
|
||||
scanLabelsJson: string;
|
||||
policyDecision: "approved_for_handoff" | "blocked_by_scan";
|
||||
objectRef: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface ScheduledPostRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
socialAccountId: string;
|
||||
bodyMd: string;
|
||||
scheduledFor: string;
|
||||
state: "draft" | "scheduled" | "published" | "cancelled";
|
||||
approvalId: string | null;
|
||||
createdByEmployeeId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ProviderRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
providerKey: string;
|
||||
label: string;
|
||||
authType: ProviderAuthType;
|
||||
model: string | null;
|
||||
credentialId: string | null;
|
||||
enabled: boolean;
|
||||
authState: string;
|
||||
healthState: string;
|
||||
lastCheckedAt: string | null;
|
||||
lastError: string | null;
|
||||
dataPolicy: ProviderDataPolicy;
|
||||
backgroundEnabled: boolean;
|
||||
monthlyRequestLimit: number;
|
||||
workspaceScope: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface ProviderCatalogModel {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface ProviderCatalogEntry {
|
||||
key: string;
|
||||
label: string;
|
||||
authType: ProviderAuthType;
|
||||
defaultModel: string | null;
|
||||
capabilityTags: string[];
|
||||
signInUrl: string | null;
|
||||
credentialHelp: string;
|
||||
models: ProviderCatalogModel[];
|
||||
/** True when the provider exposes a real models endpoint we can fetch from.
|
||||
* When false (e.g. the Codex subscription, which has no enumerable list), the
|
||||
* UI offers a free-text model id instead of a fixed dropdown. */
|
||||
supportsLiveModels: boolean;
|
||||
/** Set for user-configured OpenAI/Anthropic-compatible endpoints: the UI
|
||||
* collects a base URL + API key + model instead of a fixed provider form. */
|
||||
customEndpoint?: "openai" | "anthropic";
|
||||
}
|
||||
|
||||
export interface SkillDefinitionRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
ownerType: string;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SkillRevisionRecord {
|
||||
id: string;
|
||||
skillId: string;
|
||||
versionSemver: string;
|
||||
manifestJson: string;
|
||||
sourceType: string;
|
||||
sourceRef: string;
|
||||
publishedAt: string;
|
||||
immutableChecksum: string;
|
||||
}
|
||||
|
||||
export interface SkillBindingRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
agentId: string;
|
||||
skillId: string;
|
||||
pinnedRevisionId: string;
|
||||
bindingMode: string;
|
||||
priority: number;
|
||||
enabled: boolean;
|
||||
}
|
||||
|
||||
export interface SkillRuntimeSnapshotRecord {
|
||||
id: string;
|
||||
agentId: string;
|
||||
runId: string;
|
||||
compiledPrompt: string;
|
||||
toolsManifest: string;
|
||||
sourceRevisionIds: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SkillTestRecord {
|
||||
id: string;
|
||||
revisionId: string;
|
||||
testType: string;
|
||||
expectedOutputRef: string;
|
||||
lastResult: string | null;
|
||||
lastRunAt: string | null;
|
||||
}
|
||||
|
||||
export interface AuditEventRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
entityType: string;
|
||||
entityId: string;
|
||||
actorType: string;
|
||||
actorId: string | null;
|
||||
action: string;
|
||||
payloadJson: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface PolicyRuleRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
subjectType: string;
|
||||
subjectId: string | null;
|
||||
action: string;
|
||||
effect: string;
|
||||
riskCeiling: RiskLevel;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface MigrationReportRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
sourceRef: string;
|
||||
reportJson: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface DocumentRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
title: string;
|
||||
docType: string;
|
||||
content: string;
|
||||
status: string;
|
||||
authorAgentId: string | null;
|
||||
reviewerAgentId: string | null;
|
||||
projectId: string | null;
|
||||
goalId: string | null;
|
||||
taskId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface KnowledgeEntryRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
topic: string;
|
||||
category: string;
|
||||
content: string;
|
||||
importance: string;
|
||||
sourceType: string;
|
||||
sourceId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ConnectorAccountRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
toolkitSlug: string;
|
||||
toolkitName: string;
|
||||
authConfigId: string;
|
||||
status: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ConnectorGrantRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
agentId: string;
|
||||
toolkitSlug: string;
|
||||
grantedByType: string;
|
||||
grantedById: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface AutomationRuleRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
name: string;
|
||||
triggerEvent: string;
|
||||
conditionJson: string;
|
||||
actionType: string;
|
||||
actionConfigJson: string;
|
||||
priority: number;
|
||||
enabled: boolean;
|
||||
lastFiredAt: string | null;
|
||||
fireCount: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export const IDENTITY_SOURCE = { BOOTSTRAP: "bootstrap", SSO: "sso", SCIM: "scim" } as const;
|
||||
export const ROLE_KEY = {
|
||||
ORG_ADMIN: "org_admin",
|
||||
APPROVAL_DECIDER: "approval_decider",
|
||||
HIRING_MANAGER: "hiring_manager",
|
||||
SCOPED_AGENT: "scoped_agent",
|
||||
} as const;
|
||||
export const ACCESS_DECISION = { ALLOW: "allow", DENY: "deny" } as const;
|
||||
|
||||
export type IdentitySource = ValueOf<typeof IDENTITY_SOURCE>;
|
||||
export type RoleKey = ValueOf<typeof ROLE_KEY>;
|
||||
export type AccessDecision = ValueOf<typeof ACCESS_DECISION>;
|
||||
export type PrincipalType = "employee" | "agent" | "service_identity";
|
||||
|
||||
export interface EmployeeIdentityRecord {
|
||||
id: string; orgId: string; employeeId: string; source: IdentitySource; externalSubject: string;
|
||||
email: string | null; active: boolean; createdAt: string; lastSeenAt: string | null;
|
||||
}
|
||||
|
||||
export interface ServiceIdentityRecord {
|
||||
id: string; orgId: string; agentId: string; name: string; scopeJson: string; createdAt: string;
|
||||
}
|
||||
|
||||
export interface RoleGrantRecord {
|
||||
id: string; orgId: string; principalType: PrincipalType; principalId: string; roleKey: RoleKey;
|
||||
scopeType: string; scopeId: string; grantedByEmployeeId: string | null; createdAt: string;
|
||||
}
|
||||
|
||||
export interface AccessDecisionRecord {
|
||||
id: string; orgId: string; principalType: PrincipalType; principalId: string; action: string;
|
||||
resourceType: string; resourceId: string; decision: AccessDecision; reason: string; createdAt: string;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
export type EntityId = string;
|
||||
|
||||
export function createId(prefix: string): EntityId {
|
||||
return `${prefix}_${crypto.randomUUID().replaceAll("-", "")}`;
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
import type { InboxItem, ProfileSnapshot } from "./types";
|
||||
|
||||
/**
|
||||
* Inbox items, derived purely from `ProfileSnapshot`.
|
||||
*
|
||||
* Mirrors the single-source-of-truth pattern used for sidebar badges
|
||||
* (`sidebar-badges.ts`). The renderer already holds every row the
|
||||
* inbox would aggregate — approvals, runs, tasks, agents, messages —
|
||||
* so the old `getInbox` IPC was a second aggregation path that could
|
||||
* drift. Deriving on the client from the snapshot removes the drift
|
||||
* class and the round-trip.
|
||||
*
|
||||
* Parity note: the five item categories (`pending_approval`,
|
||||
* `failed_run`, `budget_warning`, `blocked_task` / `review_needed`,
|
||||
* `agent_message`) match what the old `buildDocumentMethods::getInbox`
|
||||
* produced. One behavioural drop: the old SQL limited failed-run
|
||||
* items to the last 24 hours; we preserve that window here using the
|
||||
* snapshot's `createdAt` strings and the caller's "now".
|
||||
*/
|
||||
|
||||
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
|
||||
const BUDGET_WARNING_RATIO = 0.8;
|
||||
const URGENT_CHANNELS: ReadonlyArray<string> = ["company", "incident"];
|
||||
|
||||
const SEVERITY_ORDER: Record<InboxItem["severity"], number> = {
|
||||
critical: 0,
|
||||
high: 1,
|
||||
medium: 2,
|
||||
low: 3,
|
||||
};
|
||||
|
||||
/** Build the inbox list from the current snapshot for the given company. */
|
||||
export function deriveInboxItems(
|
||||
snapshot: ProfileSnapshot,
|
||||
companyId: string | null,
|
||||
now: Date = new Date(),
|
||||
): InboxItem[] {
|
||||
if (!companyId) return [];
|
||||
const agentNameMap = new Map<string, string>();
|
||||
for (const agent of snapshot.agents) {
|
||||
if (agent.companyId === companyId) agentNameMap.set(agent.id, agent.name);
|
||||
}
|
||||
|
||||
const items: InboxItem[] = [];
|
||||
const oneDayAgoIso = new Date(now.getTime() - ONE_DAY_MS).toISOString();
|
||||
|
||||
for (const approval of snapshot.approvals) {
|
||||
if (approval.companyId !== companyId) continue;
|
||||
if (approval.state !== "pending") continue;
|
||||
const requesterName = approval.requestedByAgentId
|
||||
? agentNameMap.get(approval.requestedByAgentId) ?? null
|
||||
: null;
|
||||
items.push({
|
||||
id: `approval-${approval.id}`,
|
||||
type: "pending_approval",
|
||||
title: approval.payloadSummary,
|
||||
subtitle: `${approval.type.replaceAll("_", " ")} — requested by ${requesterName ?? "Unknown"}`,
|
||||
severity: approval.type === "dangerous_command" ? "critical" : "high",
|
||||
entityType: "approval",
|
||||
entityId: approval.id,
|
||||
agentId: approval.requestedByAgentId,
|
||||
agentName: requesterName,
|
||||
createdAt: approval.createdAt,
|
||||
});
|
||||
}
|
||||
|
||||
for (const run of snapshot.runs) {
|
||||
if (run.companyId !== companyId) continue;
|
||||
if (run.status !== "failed" && run.status !== "timed_out") continue;
|
||||
if (run.createdAt <= oneDayAgoIso) continue;
|
||||
const agentName = agentNameMap.get(run.agentId) ?? null;
|
||||
items.push({
|
||||
id: `run-${run.id}`,
|
||||
type: "failed_run",
|
||||
title: run.summary || "Run failed",
|
||||
subtitle: `${agentName ?? "Unknown agent"} — ${run.errorMessage?.slice(0, 100) ?? "Unknown error"}`,
|
||||
severity: "high",
|
||||
entityType: "run",
|
||||
entityId: run.id,
|
||||
agentId: run.agentId,
|
||||
agentName,
|
||||
createdAt: run.createdAt,
|
||||
});
|
||||
}
|
||||
|
||||
for (const agent of snapshot.agents) {
|
||||
if (agent.companyId !== companyId) continue;
|
||||
if (agent.budgetMonthlyUsd <= 0) continue;
|
||||
const ratio = agent.spentMonthlyUsd / agent.budgetMonthlyUsd;
|
||||
if (ratio <= BUDGET_WARNING_RATIO) continue;
|
||||
const pct = Math.round(ratio * 100);
|
||||
items.push({
|
||||
id: `budget-${agent.id}`,
|
||||
type: "budget_warning",
|
||||
title: `${agent.name} at ${pct}% budget`,
|
||||
subtitle: `$${agent.spentMonthlyUsd.toFixed(2)} of $${agent.budgetMonthlyUsd.toFixed(2)} monthly limit`,
|
||||
severity: pct >= 100 ? "critical" : "high",
|
||||
entityType: "agent",
|
||||
entityId: agent.id,
|
||||
agentId: agent.id,
|
||||
agentName: agent.name,
|
||||
createdAt: agent.updatedAt,
|
||||
});
|
||||
}
|
||||
|
||||
for (const task of snapshot.tasks) {
|
||||
if (task.companyId !== companyId) continue;
|
||||
if (task.status !== "blocked" && task.status !== "in_review") continue;
|
||||
const assigneeName = task.assigneeAgentId ? agentNameMap.get(task.assigneeAgentId) ?? null : null;
|
||||
if (task.status === "blocked") {
|
||||
items.push({
|
||||
id: `blocked-${task.id}`,
|
||||
type: "blocked_task",
|
||||
title: task.title,
|
||||
subtitle: `Assigned to ${assigneeName ?? "Unassigned"} — blocked`,
|
||||
severity: task.priority === "critical" ? "critical" : "medium",
|
||||
entityType: "task",
|
||||
entityId: task.id,
|
||||
agentId: task.assigneeAgentId,
|
||||
agentName: assigneeName,
|
||||
createdAt: task.updatedAt,
|
||||
});
|
||||
} else {
|
||||
items.push({
|
||||
id: `review-${task.id}`,
|
||||
type: "review_needed",
|
||||
title: task.title,
|
||||
subtitle: `Submitted by ${assigneeName ?? "Unknown"} — awaiting review`,
|
||||
severity: task.priority === "critical" ? "high" : "medium",
|
||||
entityType: "task",
|
||||
entityId: task.id,
|
||||
agentId: task.assigneeAgentId,
|
||||
agentName: assigneeName,
|
||||
createdAt: task.updatedAt,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const message of snapshot.agentMessages) {
|
||||
if (message.companyId !== companyId) continue;
|
||||
if (message.readAt) continue;
|
||||
const visible =
|
||||
URGENT_CHANNELS.includes(message.channel) || message.priority === "urgent";
|
||||
if (!visible) continue;
|
||||
const senderName = agentNameMap.get(message.fromAgentId) ?? null;
|
||||
const urgencyTag = message.priority === "urgent" ? " (urgent)" : "";
|
||||
items.push({
|
||||
id: `message-${message.id}`,
|
||||
type: "agent_message",
|
||||
title: message.subject,
|
||||
subtitle: `${senderName ?? "Unknown"} — ${message.channel === "incident" ? "INCIDENT" : message.channel}${urgencyTag}`,
|
||||
severity: message.priority === "urgent" || message.channel === "incident" ? "critical" : "medium",
|
||||
entityType: "message",
|
||||
entityId: message.id,
|
||||
agentId: message.fromAgentId,
|
||||
agentName: senderName,
|
||||
createdAt: message.createdAt,
|
||||
});
|
||||
}
|
||||
|
||||
items.sort(
|
||||
(a, b) =>
|
||||
SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity] ||
|
||||
new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime(),
|
||||
);
|
||||
return items;
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
export const IPC_CHANNELS = {
|
||||
loadSnapshot: "agentcompany:load-snapshot",
|
||||
bootstrapOnboarding: "agentcompany:bootstrap-onboarding",
|
||||
setActiveOrganization: "agentcompany:set-active-organization",
|
||||
deleteOrganization: "agentcompany:delete-organization",
|
||||
createOrganization: "agentcompany:create-organization",
|
||||
createAgent: "agentcompany:create-agent",
|
||||
updateAgent: "agentcompany:update-agent",
|
||||
createTask: "agentcompany:create-task",
|
||||
updateTask: "agentcompany:update-task",
|
||||
deleteTask: "agentcompany:delete-task",
|
||||
updateTaskStatus: "agentcompany:update-task-status",
|
||||
runTask: "agentcompany:run-task",
|
||||
createApproval: "agentcompany:create-approval",
|
||||
decideApproval: "agentcompany:decide-approval",
|
||||
syncEmployeeIdentity: "agentcompany:sync-employee-identity",
|
||||
grantRole: "agentcompany:grant-role",
|
||||
createChatSpace: "agentcompany:create-chat-space",
|
||||
sendMessage: "agentcompany:send-message",
|
||||
editMessage: "agentcompany:edit-message",
|
||||
deleteMessage: "agentcompany:delete-message",
|
||||
markChatSpaceRead: "agentcompany:mark-chat-space-read",
|
||||
saveProviderCredential: "agentcompany:save-provider-credential",
|
||||
revokeProviderCredential: "agentcompany:revoke-provider-credential",
|
||||
launchProviderSignIn: "agentcompany:launch-provider-sign-in",
|
||||
startProviderOAuth: "agentcompany:start-provider-oauth",
|
||||
cancelProviderOAuth: "agentcompany:cancel-provider-oauth",
|
||||
checkProviderHealth: "agentcompany:check-provider-health",
|
||||
listProviderModels: "agentcompany:list-provider-models",
|
||||
updateProviderPolicy: "agentcompany:update-provider-policy",
|
||||
openExternalUrl: "agentcompany:open-external-url",
|
||||
createProviderResponse: "agentcompany:create-provider-response",
|
||||
streamProviderResponse: "agentcompany:stream-provider-response",
|
||||
cancelProviderResponse: "agentcompany:cancel-provider-response",
|
||||
importSkillDirectory: "agentcompany:import-skill-directory",
|
||||
bindSkill: "agentcompany:bind-skill",
|
||||
resolveAgentSkills: "agentcompany:resolve-agent-skills",
|
||||
runSkillTests: "agentcompany:run-skill-tests",
|
||||
createSocialAccount: "agentcompany:create-social-account",
|
||||
launchSocialLogin: "agentcompany:launch-social-login",
|
||||
createScheduledPost: "agentcompany:create-scheduled-post",
|
||||
setScheduledPostState: "agentcompany:set-scheduled-post-state",
|
||||
importFile: "agentcompany:import-file",
|
||||
openFile: "agentcompany:open-file",
|
||||
pickDirectory: "agentcompany:pick-directory",
|
||||
setFilePinned: "agentcompany:set-file-pinned",
|
||||
createMigrationReport: "agentcompany:create-migration-report",
|
||||
createRollbackSnapshot: "agentcompany:create-rollback-snapshot",
|
||||
setRollbackSnapshotActive: "agentcompany:set-rollback-snapshot-active",
|
||||
resolveMigrationReconciliation: "agentcompany:resolve-migration-reconciliation",
|
||||
setFeatureFlag: "agentcompany:set-feature-flag",
|
||||
runChaosDrill: "agentcompany:run-chaos-drill",
|
||||
runSdlcReview: "agentcompany:run-sdlc-review",
|
||||
runEvalSuite: "agentcompany:run-eval-suite",
|
||||
setPrBotGate: "agentcompany:set-pr-bot-gate",
|
||||
createComplianceExport: "agentcompany:create-compliance-export",
|
||||
createAuditReplay: "agentcompany:create-audit-replay",
|
||||
createLegalHold: "agentcompany:create-legal-hold",
|
||||
setLegalHoldState: "agentcompany:set-legal-hold-state",
|
||||
createRetentionFreeze: "agentcompany:create-retention-freeze",
|
||||
setRetentionFreezeState: "agentcompany:set-retention-freeze-state",
|
||||
createGoal: "agentcompany:create-goal",
|
||||
createProject: "agentcompany:create-project",
|
||||
createWorkspace: "agentcompany:create-workspace",
|
||||
createDocument: "agentcompany:create-document",
|
||||
updateDocument: "agentcompany:update-document",
|
||||
deleteDocument: "agentcompany:delete-document",
|
||||
createKnowledgeEntry: "agentcompany:create-knowledge-entry",
|
||||
deleteKnowledgeEntry: "agentcompany:delete-knowledge-entry",
|
||||
createAutomationRule: "agentcompany:create-automation-rule",
|
||||
updateAutomationRule: "agentcompany:update-automation-rule",
|
||||
deleteAutomationRule: "agentcompany:delete-automation-rule",
|
||||
createMeeting: "agentcompany:create-meeting",
|
||||
deleteMeeting: "agentcompany:delete-meeting",
|
||||
createSprint: "agentcompany:create-sprint",
|
||||
deleteSprint: "agentcompany:delete-sprint",
|
||||
saveComposioSettings: "agentcompany:save-composio-settings",
|
||||
listComposioToolkits: "agentcompany:list-composio-toolkits",
|
||||
connectComposioToolkit: "agentcompany:connect-composio-toolkit",
|
||||
refreshComposioAccounts: "agentcompany:refresh-composio-accounts",
|
||||
grantConnector: "agentcompany:grant-connector",
|
||||
revokeConnector: "agentcompany:revoke-connector",
|
||||
search: "agentcompany:search",
|
||||
rendererEvent: "agentcompany:renderer-event",
|
||||
windowMinimize: "agentcompany:window-minimize",
|
||||
windowMaximize: "agentcompany:window-maximize",
|
||||
windowClose: "agentcompany:window-close",
|
||||
} as const;
|
||||
@@ -1,4 +0,0 @@
|
||||
export type AppLocale = "en" | "zh";
|
||||
export const APP_LOCALES: readonly AppLocale[] = ["en", "zh"] as const;
|
||||
export const LOCALE_LABELS: Record<AppLocale, string> = { en: "English", zh: "中文" };
|
||||
export const DEFAULT_LOCALE: AppLocale = "en";
|
||||
@@ -1,12 +0,0 @@
|
||||
const ACTUAL_LINE_BREAKS = /\r\n?/g;
|
||||
const ESCAPED_CRLF = /\\r\\n/g;
|
||||
const ESCAPED_LF = /\\n/g;
|
||||
const ESCAPED_CR = /\\r/g;
|
||||
|
||||
export function normalizeMarkdownText(text: string): string {
|
||||
return text
|
||||
.replace(ACTUAL_LINE_BREAKS, "\n")
|
||||
.replace(ESCAPED_CRLF, "\n")
|
||||
.replace(ESCAPED_LF, "\n")
|
||||
.replace(ESCAPED_CR, "\n");
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
export const RESERVED_MENTION_HANDLES = new Set(["board", "oncall"]);
|
||||
|
||||
export function canonicalMentionHandle(value: string): string {
|
||||
return value.toLowerCase().replace(/[^a-z0-9]/g, "");
|
||||
}
|
||||
|
||||
export function assertUsableMentionName(value: string): void {
|
||||
if (RESERVED_MENTION_HANDLES.has(canonicalMentionHandle(value))) {
|
||||
throw new Error("Mention handle is reserved.");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export const FEATURE_FLAG_KEY = {
|
||||
PROVIDER_BACKGROUND_EXECUTION: "provider_background_execution",
|
||||
SOCIAL_PUBLISH_APPROVAL: "social_publish_approval",
|
||||
BOARD_INTERVENTION: "board_intervention",
|
||||
CHAOS_DRILLS: "chaos_drills",
|
||||
} as const;
|
||||
|
||||
export const SLO_SIGNAL_KEY = {
|
||||
PROVIDER_REQUEST_SUCCESS: "provider_request_success",
|
||||
APPROVAL_ROUTE_COVERAGE: "approval_route_coverage",
|
||||
BROWSER_SESSION_BOUNDARY: "browser_session_boundary",
|
||||
SKILL_RESOLVE_SUCCESS: "skill_resolve_success",
|
||||
MIGRATION_VALIDATION_SUCCESS: "migration_validation_success",
|
||||
} as const;
|
||||
|
||||
export const CHAOS_DRILL_SCENARIO = {
|
||||
PROVIDER_OUTAGE_POLICY_GATE: "provider_outage_policy_gate",
|
||||
APPROVAL_BACKLOG_GATE: "approval_backlog_gate",
|
||||
BROWSER_SESSION_BOUNDARY: "browser_session_boundary",
|
||||
MIGRATION_ROLLBACK_PACK: "migration_rollback_pack",
|
||||
} as const;
|
||||
|
||||
export const CHAOS_DRILL_STATE = { PASSED: "passed", FAILED: "failed" } as const;
|
||||
|
||||
export type FeatureFlagKey = ValueOf<typeof FEATURE_FLAG_KEY>;
|
||||
export type SloSignalKey = ValueOf<typeof SLO_SIGNAL_KEY>;
|
||||
export type ChaosDrillScenario = ValueOf<typeof CHAOS_DRILL_SCENARIO>;
|
||||
export type ChaosDrillState = ValueOf<typeof CHAOS_DRILL_STATE>;
|
||||
|
||||
export interface FeatureFlagRecord {
|
||||
id: string; orgId: string; key: FeatureFlagKey; label: string; enabled: boolean; createdAt: string; updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SloTargetRecord {
|
||||
id: string; orgId: string; signalKey: SloSignalKey; label: string; targetBasisPoints: number; windowMinutes: number; createdAt: string; updatedAt: string;
|
||||
}
|
||||
|
||||
export interface OperationalEventRecord {
|
||||
id: string; orgId: string; signalKey: SloSignalKey; source: string; success: boolean; durationMs: number | null; detailJson: string; createdAt: string;
|
||||
}
|
||||
|
||||
export interface ChaosDrillRecord {
|
||||
id: string; orgId: string; key: string; label: string; scenarioKey: ChaosDrillScenario; enabled: boolean; createdAt: string; updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ChaosDrillRunRecord {
|
||||
id: string; orgId: string; drillId: string; state: ChaosDrillState; resultJson: string; startedAt: string; completedAt: string;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export const ROUTE_TO_TYPE = { EMPLOYEE: "employee", AGENT: "agent", BOARD: "board" } as const;
|
||||
export type RouteToType = ValueOf<typeof ROUTE_TO_TYPE>;
|
||||
|
||||
export interface OrgDepartmentRecord {
|
||||
id: string; orgId: string; name: string; leadAgentId: string | null;
|
||||
headcountLimit: number; monthlyBudgetLimitCents: number; createdAt: string; updatedAt: string;
|
||||
}
|
||||
|
||||
export interface HiringPolicyRecord {
|
||||
id: string; orgId: string; departmentName: string; maxHeadcount: number;
|
||||
monthlyBudgetLimitCents: number; requireApprovalAboveCents: number; createdAt: string; updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ApprovalRoutingRuleRecord {
|
||||
id: string; orgId: string; kind: string; minimumRisk: string;
|
||||
routeToType: RouteToType; routeToId: string; createdAt: string;
|
||||
}
|
||||
|
||||
export interface ApprovalAssignmentRecord {
|
||||
id: string; orgId: string; approvalId: string; assigneeType: RouteToType;
|
||||
assigneeId: string; routingRuleId: string | null; createdAt: string;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import type { ProviderAuthType } from "./domain";
|
||||
|
||||
export interface ProviderAuthProfileRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
credentialId: string;
|
||||
providerKey: string;
|
||||
authType: ProviderAuthType;
|
||||
profileKind: string;
|
||||
displayHint: string;
|
||||
sourceType: string;
|
||||
sourceRef: string | null;
|
||||
capabilityJson: string;
|
||||
active: boolean;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface ProviderAuthSessionRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
providerKey: string;
|
||||
employeeId: string;
|
||||
state: string;
|
||||
nonce: string;
|
||||
codeVerifierSha256: string;
|
||||
redirectUri: string;
|
||||
signInUrl: string;
|
||||
partition: string;
|
||||
createdAt: string;
|
||||
expiresAt: string;
|
||||
completedAt: string | null;
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
import { PROVIDER_AUTH_TYPE, type ProviderCatalogEntry } from "./domain";
|
||||
import { listProviderModels } from "./provider-models";
|
||||
|
||||
const RAW_CATALOG: Omit<ProviderCatalogEntry, "models" | "supportsLiveModels">[] = [
|
||||
{
|
||||
key: "openai",
|
||||
label: "OpenAI",
|
||||
authType: PROVIDER_AUTH_TYPE.API_KEY,
|
||||
defaultModel: "gpt-5.4",
|
||||
capabilityTags: ["responses", "tools", "background"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Generate an API key at platform.openai.com → API keys.",
|
||||
},
|
||||
{
|
||||
key: "anthropic",
|
||||
label: "Anthropic",
|
||||
authType: PROVIDER_AUTH_TYPE.API_KEY,
|
||||
defaultModel: "claude-sonnet-4-5",
|
||||
capabilityTags: ["messages", "tool-use", "token-bucket"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Generate an API key at console.anthropic.com → API keys.",
|
||||
},
|
||||
{
|
||||
key: "claude-pro",
|
||||
label: "Claude Pro/Max",
|
||||
authType: PROVIDER_AUTH_TYPE.OAUTH_PKCE,
|
||||
defaultModel: "claude-sonnet-4-5",
|
||||
capabilityTags: ["account", "subscription"],
|
||||
signInUrl: "https://claude.ai/login",
|
||||
credentialHelp: "Sign in with your Claude Pro or Max account in the browser; AgentCompany finishes the handshake.",
|
||||
},
|
||||
{
|
||||
key: "xai",
|
||||
label: "xAI Grok",
|
||||
authType: PROVIDER_AUTH_TYPE.API_KEY,
|
||||
defaultModel: "grok-4",
|
||||
capabilityTags: ["chat", "reasoning"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Generate an API key at console.x.ai → API keys.",
|
||||
},
|
||||
{
|
||||
key: "groq",
|
||||
label: "Groq",
|
||||
authType: PROVIDER_AUTH_TYPE.API_KEY,
|
||||
defaultModel: "groq/compound",
|
||||
capabilityTags: ["inference", "low-latency"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Generate an API key at console.groq.com → API keys.",
|
||||
},
|
||||
{
|
||||
key: "mistral",
|
||||
label: "Mistral",
|
||||
authType: PROVIDER_AUTH_TYPE.API_KEY,
|
||||
defaultModel: "mistral-large-latest",
|
||||
capabilityTags: ["chat", "reasoning"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Generate an API key at console.mistral.ai → API keys.",
|
||||
},
|
||||
{
|
||||
key: "cerebras",
|
||||
label: "Cerebras",
|
||||
authType: PROVIDER_AUTH_TYPE.API_KEY,
|
||||
defaultModel: "qwen-3-235b-a22b-instruct-2507",
|
||||
capabilityTags: ["inference", "fast"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Generate an API key at cloud.cerebras.ai → API keys.",
|
||||
},
|
||||
{
|
||||
key: "openrouter",
|
||||
label: "OpenRouter",
|
||||
authType: PROVIDER_AUTH_TYPE.API_KEY,
|
||||
defaultModel: "anthropic/claude-sonnet-4.5",
|
||||
capabilityTags: ["router", "multi-model"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Generate an API key at openrouter.ai → Keys.",
|
||||
},
|
||||
{
|
||||
key: "github-copilot",
|
||||
label: "GitHub Copilot",
|
||||
authType: PROVIDER_AUTH_TYPE.OAUTH_PKCE,
|
||||
defaultModel: "claude-opus-4-5",
|
||||
capabilityTags: ["account", "coding"],
|
||||
signInUrl: "https://github.com/login/device",
|
||||
credentialHelp: "Sign in with the GitHub device code shown here — no token to copy.",
|
||||
},
|
||||
{
|
||||
key: "google-antigravity",
|
||||
label: "Google Antigravity",
|
||||
authType: PROVIDER_AUTH_TYPE.OAUTH_PKCE,
|
||||
defaultModel: "claude-sonnet-4-5",
|
||||
capabilityTags: ["account", "coding"],
|
||||
signInUrl: "https://antigravity.google/",
|
||||
credentialHelp: "Sign in with your Google account in the browser; AgentCompany finishes the handshake.",
|
||||
},
|
||||
{
|
||||
key: "gpt-account",
|
||||
label: "GPT account",
|
||||
authType: PROVIDER_AUTH_TYPE.ACCOUNT_SUBSCRIPTION,
|
||||
defaultModel: "gpt-5.3-codex",
|
||||
capabilityTags: ["codex", "subscription"],
|
||||
signInUrl: "https://chatgpt.com/codex",
|
||||
credentialHelp: "Sign in to ChatGPT Plus/Pro in the browser; AgentCompany finishes the handshake.",
|
||||
},
|
||||
{
|
||||
key: "azure-openai",
|
||||
label: "Azure OpenAI",
|
||||
authType: PROVIDER_AUTH_TYPE.CLOUD,
|
||||
defaultModel: "gpt-5.4",
|
||||
capabilityTags: ["enterprise", "regional"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Set base URL (e.g. https://<resource>.openai.azure.com), deployment name, and the api-key from Azure portal.",
|
||||
},
|
||||
{
|
||||
key: "aws-bedrock",
|
||||
label: "AWS Bedrock",
|
||||
authType: PROVIDER_AUTH_TYPE.CLOUD,
|
||||
defaultModel: "anthropic.claude-sonnet-4-5",
|
||||
capabilityTags: ["enterprise", "multi-model"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Provide AWS region plus an access key + secret access key with bedrock:InvokeModel permission.",
|
||||
},
|
||||
{
|
||||
key: "vertex-ai",
|
||||
label: "Vertex AI",
|
||||
authType: PROVIDER_AUTH_TYPE.CLOUD,
|
||||
defaultModel: "gemini-2.5-pro",
|
||||
capabilityTags: ["enterprise", "regional"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Provide GCP project id, region, and a service-account JSON key with aiplatform.user role.",
|
||||
},
|
||||
{
|
||||
key: "custom-openai",
|
||||
label: "Custom OpenAI-compatible",
|
||||
authType: PROVIDER_AUTH_TYPE.CLOUD,
|
||||
defaultModel: null,
|
||||
capabilityTags: ["custom", "openai-compatible"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Set the base URL (ending in /v1) and an API key for any OpenAI Chat Completions–compatible endpoint, then enter the model id.",
|
||||
customEndpoint: "openai",
|
||||
},
|
||||
{
|
||||
key: "custom-anthropic",
|
||||
label: "Custom Anthropic-compatible",
|
||||
authType: PROVIDER_AUTH_TYPE.CLOUD,
|
||||
defaultModel: null,
|
||||
capabilityTags: ["custom", "anthropic-compatible"],
|
||||
signInUrl: null,
|
||||
credentialHelp: "Set the base URL and an API key for any Anthropic Messages–compatible endpoint, then enter the model id.",
|
||||
customEndpoint: "anthropic",
|
||||
},
|
||||
];
|
||||
|
||||
// Providers with no enumerable models endpoint: the Codex subscription, the
|
||||
// browser-token / cloud connectors, and user-configured custom endpoints whose
|
||||
// model id is entered by hand. The UI offers a fixed dropdown (when a curated
|
||||
// list exists) or a free-text model id instead of a live fetch.
|
||||
const CURATED_MODEL_PROVIDERS = new Set([
|
||||
"github-copilot",
|
||||
"google-antigravity",
|
||||
"gpt-account",
|
||||
"azure-openai",
|
||||
"aws-bedrock",
|
||||
"vertex-ai",
|
||||
"custom-openai",
|
||||
"custom-anthropic",
|
||||
]);
|
||||
|
||||
export const PROVIDER_CATALOG: ProviderCatalogEntry[] = RAW_CATALOG.map((entry) => ({
|
||||
...entry,
|
||||
models: listProviderModels(entry.key),
|
||||
supportsLiveModels: !CURATED_MODEL_PROVIDERS.has(entry.key),
|
||||
}));
|
||||
@@ -0,0 +1,237 @@
|
||||
export interface ProviderModelEntry {
|
||||
id: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
const ANTHROPIC_MODELS: ProviderModelEntry[] = [
|
||||
{ id: "claude-opus-4-7", name: "Claude Opus 4.7" },
|
||||
{ id: "claude-opus-4-6", name: "Claude Opus 4.6" },
|
||||
{ id: "claude-opus-4-5", name: "Claude Opus 4.5 (latest)" },
|
||||
{ id: "claude-opus-4-1", name: "Claude Opus 4.1 (latest)" },
|
||||
{ id: "claude-opus-4-0", name: "Claude Opus 4 (latest)" },
|
||||
{ id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6" },
|
||||
{ id: "claude-sonnet-4-5", name: "Claude Sonnet 4.5 (latest)" },
|
||||
{ id: "claude-sonnet-4-0", name: "Claude Sonnet 4 (latest)" },
|
||||
{ id: "claude-haiku-4-5", name: "Claude Haiku 4.5 (latest)" },
|
||||
{ id: "claude-3-7-sonnet-20250219", name: "Claude Sonnet 3.7" },
|
||||
{ id: "claude-3-5-sonnet-20241022", name: "Claude Sonnet 3.5 v2" },
|
||||
{ id: "claude-3-5-sonnet-20240620", name: "Claude Sonnet 3.5" },
|
||||
{ id: "claude-3-5-haiku-latest", name: "Claude Haiku 3.5 (latest)" },
|
||||
{ id: "claude-3-5-haiku-20241022", name: "Claude Haiku 3.5" },
|
||||
{ id: "claude-3-haiku-20240307", name: "Claude Haiku 3" },
|
||||
{ id: "claude-3-sonnet-20240229", name: "Claude Sonnet 3" },
|
||||
{ id: "claude-3-opus-20240229", name: "Claude Opus 3" },
|
||||
];
|
||||
|
||||
export const PROVIDER_MODELS: Record<string, ProviderModelEntry[]> = {
|
||||
openai: [
|
||||
{ id: "gpt-5.5", name: "GPT-5.5" },
|
||||
{ id: "gpt-5.4-pro", name: "GPT-5.4 Pro" },
|
||||
{ id: "gpt-5.4", name: "GPT-5.4" },
|
||||
{ id: "gpt-5.4-mini", name: "GPT-5.4 mini" },
|
||||
{ id: "gpt-5.4-nano", name: "GPT-5.4 nano" },
|
||||
{ id: "gpt-5.3-codex", name: "GPT-5.3 Codex" },
|
||||
{ id: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark" },
|
||||
{ id: "gpt-5.3-chat-latest", name: "GPT-5.3 Chat" },
|
||||
{ id: "gpt-5.2-pro", name: "GPT-5.2 Pro" },
|
||||
{ id: "gpt-5.2", name: "GPT-5.2" },
|
||||
{ id: "gpt-5.2-codex", name: "GPT-5.2 Codex" },
|
||||
{ id: "gpt-5.2-chat-latest", name: "GPT-5.2 Chat" },
|
||||
{ id: "gpt-5.1", name: "GPT-5.1" },
|
||||
{ id: "gpt-5.1-codex", name: "GPT-5.1 Codex" },
|
||||
{ id: "gpt-5.1-codex-max", name: "GPT-5.1 Codex Max" },
|
||||
{ id: "gpt-5.1-codex-mini", name: "GPT-5.1 Codex mini" },
|
||||
{ id: "gpt-5.1-chat-latest", name: "GPT-5.1 Chat" },
|
||||
{ id: "gpt-5-pro", name: "GPT-5 Pro" },
|
||||
{ id: "gpt-5", name: "GPT-5" },
|
||||
{ id: "gpt-5-codex", name: "GPT-5 Codex" },
|
||||
{ id: "gpt-5-mini", name: "GPT-5 mini" },
|
||||
{ id: "gpt-5-nano", name: "GPT-5 nano" },
|
||||
{ id: "gpt-5-chat-latest", name: "GPT-5 Chat" },
|
||||
{ id: "o4-mini", name: "o4-mini" },
|
||||
{ id: "o4-mini-deep-research", name: "o4-mini deep research" },
|
||||
{ id: "o3", name: "o3" },
|
||||
{ id: "o3-pro", name: "o3-pro" },
|
||||
{ id: "o3-mini", name: "o3-mini" },
|
||||
{ id: "o3-deep-research", name: "o3 deep research" },
|
||||
{ id: "o1", name: "o1" },
|
||||
{ id: "o1-pro", name: "o1-pro" },
|
||||
{ id: "gpt-4.1", name: "GPT-4.1" },
|
||||
{ id: "gpt-4.1-mini", name: "GPT-4.1 mini" },
|
||||
{ id: "gpt-4.1-nano", name: "GPT-4.1 nano" },
|
||||
{ id: "gpt-4o", name: "GPT-4o" },
|
||||
{ id: "gpt-4o-mini", name: "GPT-4o mini" },
|
||||
{ id: "gpt-4-turbo", name: "GPT-4 Turbo" },
|
||||
{ id: "gpt-4", name: "GPT-4" },
|
||||
],
|
||||
anthropic: ANTHROPIC_MODELS,
|
||||
"claude-pro": ANTHROPIC_MODELS,
|
||||
xai: [
|
||||
{ id: "grok-4", name: "Grok 4" },
|
||||
{ id: "grok-4-fast", name: "Grok 4 Fast" },
|
||||
{ id: "grok-4-fast-non-reasoning", name: "Grok 4 Fast (Non-Reasoning)" },
|
||||
{ id: "grok-4-1-fast", name: "Grok 4.1 Fast" },
|
||||
{ id: "grok-4-1-fast-non-reasoning", name: "Grok 4.1 Fast (Non-Reasoning)" },
|
||||
{ id: "grok-4.20-0309-reasoning", name: "Grok 4.20 (Reasoning)" },
|
||||
{ id: "grok-4.20-0309-non-reasoning", name: "Grok 4.20 (Non-Reasoning)" },
|
||||
{ id: "grok-code-fast-1", name: "Grok Code Fast 1" },
|
||||
{ id: "grok-3", name: "Grok 3" },
|
||||
{ id: "grok-3-fast", name: "Grok 3 Fast" },
|
||||
{ id: "grok-3-mini", name: "Grok 3 Mini" },
|
||||
{ id: "grok-3-mini-fast", name: "Grok 3 Mini Fast" },
|
||||
{ id: "grok-2", name: "Grok 2" },
|
||||
{ id: "grok-2-vision", name: "Grok 2 Vision" },
|
||||
{ id: "grok-beta", name: "Grok Beta" },
|
||||
{ id: "grok-vision-beta", name: "Grok Vision Beta" },
|
||||
],
|
||||
groq: [
|
||||
{ id: "groq/compound", name: "Compound" },
|
||||
{ id: "groq/compound-mini", name: "Compound Mini" },
|
||||
{ id: "moonshotai/kimi-k2-instruct-0905", name: "Kimi K2 Instruct 0905" },
|
||||
{ id: "moonshotai/kimi-k2-instruct", name: "Kimi K2 Instruct" },
|
||||
{ id: "openai/gpt-oss-120b", name: "GPT OSS 120B" },
|
||||
{ id: "openai/gpt-oss-20b", name: "GPT OSS 20B" },
|
||||
{ id: "openai/gpt-oss-safeguard-20b", name: "Safety GPT OSS 20B" },
|
||||
{ id: "llama-3.3-70b-versatile", name: "Llama 3.3 70B Versatile" },
|
||||
{ id: "llama-3.1-8b-instant", name: "Llama 3.1 8B Instant" },
|
||||
{ id: "meta-llama/llama-4-maverick-17b-128e-instruct", name: "Llama 4 Maverick 17B" },
|
||||
{ id: "meta-llama/llama-4-scout-17b-16e-instruct", name: "Llama 4 Scout 17B" },
|
||||
{ id: "qwen-qwq-32b", name: "Qwen QwQ 32B" },
|
||||
{ id: "qwen/qwen3-32b", name: "Qwen3 32B" },
|
||||
{ id: "mistral-saba-24b", name: "Mistral Saba 24B" },
|
||||
{ id: "deepseek-r1-distill-llama-70b", name: "DeepSeek R1 Distill Llama 70B" },
|
||||
{ id: "gemma2-9b-it", name: "Gemma 2 9B" },
|
||||
],
|
||||
"github-copilot": [
|
||||
{ id: "claude-opus-4.7", name: "Claude Opus 4.7" },
|
||||
{ id: "claude-opus-4.6", name: "Claude Opus 4.6" },
|
||||
{ id: "claude-opus-4.5", name: "Claude Opus 4.5" },
|
||||
{ id: "claude-sonnet-4.6", name: "Claude Sonnet 4.6" },
|
||||
{ id: "claude-sonnet-4.5", name: "Claude Sonnet 4.5" },
|
||||
{ id: "claude-sonnet-4", name: "Claude Sonnet 4" },
|
||||
{ id: "claude-haiku-4.5", name: "Claude Haiku 4.5" },
|
||||
{ id: "gpt-5.5", name: "GPT-5.5" },
|
||||
{ id: "gpt-5.4", name: "GPT-5.4" },
|
||||
{ id: "gpt-5.4-mini", name: "GPT-5.4 mini" },
|
||||
{ id: "gpt-5.3-codex", name: "GPT-5.3 Codex" },
|
||||
{ id: "gpt-5.2", name: "GPT-5.2" },
|
||||
{ id: "gpt-5.2-codex", name: "GPT-5.2 Codex" },
|
||||
{ id: "gpt-5.1", name: "GPT-5.1" },
|
||||
{ id: "gpt-5.1-codex", name: "GPT-5.1 Codex" },
|
||||
{ id: "gpt-5.1-codex-max", name: "GPT-5.1 Codex Max" },
|
||||
{ id: "gpt-5.1-codex-mini", name: "GPT-5.1 Codex Mini" },
|
||||
{ id: "gpt-5", name: "GPT-5" },
|
||||
{ id: "gpt-5-mini", name: "GPT-5 mini" },
|
||||
{ id: "gpt-4.1", name: "GPT-4.1" },
|
||||
{ id: "gpt-4o", name: "GPT-4o" },
|
||||
{ id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro Preview" },
|
||||
{ id: "gemini-3-pro-preview", name: "Gemini 3 Pro Preview" },
|
||||
{ id: "gemini-3-flash-preview", name: "Gemini 3 Flash" },
|
||||
{ id: "gemini-2.5-pro", name: "Gemini 2.5 Pro" },
|
||||
{ id: "grok-code-fast-1", name: "Grok Code Fast 1" },
|
||||
],
|
||||
"google-antigravity": [
|
||||
{ id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6 (Antigravity)" },
|
||||
{ id: "claude-sonnet-4-5", name: "Claude Sonnet 4.5 (Antigravity)" },
|
||||
{ id: "claude-sonnet-4-5-thinking", name: "Claude Sonnet 4.5 Thinking" },
|
||||
{ id: "claude-opus-4-6-thinking", name: "Claude Opus 4.6 Thinking" },
|
||||
{ id: "claude-opus-4-5-thinking", name: "Claude Opus 4.5 Thinking" },
|
||||
{ id: "gemini-3.1-pro-high", name: "Gemini 3.1 Pro High" },
|
||||
{ id: "gemini-3.1-pro-low", name: "Gemini 3.1 Pro Low" },
|
||||
{ id: "gemini-3-flash", name: "Gemini 3 Flash" },
|
||||
{ id: "gpt-oss-120b-medium", name: "GPT-OSS 120B Medium" },
|
||||
],
|
||||
"gpt-account": [
|
||||
{ id: "gpt-5.5", name: "GPT-5.5" },
|
||||
{ id: "gpt-5.4", name: "GPT-5.4" },
|
||||
{ id: "gpt-5.4-mini", name: "GPT-5.4 Mini" },
|
||||
{ id: "gpt-5.3-codex", name: "GPT-5.3 Codex" },
|
||||
{ id: "gpt-5.3-codex-spark", name: "GPT-5.3 Codex Spark" },
|
||||
{ id: "gpt-5.2", name: "GPT-5.2" },
|
||||
{ id: "gpt-5.2-codex", name: "GPT-5.2 Codex" },
|
||||
{ id: "gpt-5.1", name: "GPT-5.1" },
|
||||
{ id: "gpt-5.1-codex-max", name: "GPT-5.1 Codex Max" },
|
||||
{ id: "gpt-5.1-codex-mini", name: "GPT-5.1 Codex Mini" },
|
||||
],
|
||||
"azure-openai": [
|
||||
{ id: "gpt-5.5", name: "GPT-5.5" },
|
||||
{ id: "gpt-5.4", name: "GPT-5.4" },
|
||||
{ id: "gpt-5.4-mini", name: "GPT-5.4 mini" },
|
||||
{ id: "gpt-5.3-codex", name: "GPT-5.3 Codex" },
|
||||
{ id: "gpt-5.2", name: "GPT-5.2" },
|
||||
{ id: "gpt-5.1", name: "GPT-5.1" },
|
||||
{ id: "gpt-5", name: "GPT-5" },
|
||||
{ id: "gpt-5-codex", name: "GPT-5 Codex" },
|
||||
{ id: "gpt-4.1", name: "GPT-4.1" },
|
||||
{ id: "gpt-4o", name: "GPT-4o" },
|
||||
{ id: "o4-mini", name: "o4-mini" },
|
||||
{ id: "o3", name: "o3" },
|
||||
],
|
||||
"aws-bedrock": [
|
||||
{ id: "anthropic.claude-opus-4-7", name: "Claude Opus 4.7" },
|
||||
{ id: "anthropic.claude-opus-4-6-v1", name: "Claude Opus 4.6" },
|
||||
{ id: "anthropic.claude-opus-4-5-20251101-v1:0", name: "Claude Opus 4.5" },
|
||||
{ id: "anthropic.claude-sonnet-4-6", name: "Claude Sonnet 4.6" },
|
||||
{ id: "anthropic.claude-sonnet-4-5-20250929-v1:0", name: "Claude Sonnet 4.5" },
|
||||
{ id: "anthropic.claude-haiku-4-5-20251001-v1:0", name: "Claude Haiku 4.5" },
|
||||
{ id: "amazon.nova-2-lite-v1:0", name: "Nova 2 Lite" },
|
||||
{ id: "amazon.nova-premier-v1:0", name: "Nova Premier" },
|
||||
{ id: "amazon.nova-pro-v1:0", name: "Nova Pro" },
|
||||
{ id: "deepseek.v3.2", name: "DeepSeek V3.2" },
|
||||
{ id: "meta.llama3-3-70b-instruct-v1:0", name: "Llama 3.3 70B" },
|
||||
{ id: "moonshotai.kimi-k2.5", name: "Kimi K2.5" },
|
||||
],
|
||||
"vertex-ai": [
|
||||
{ id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro Preview" },
|
||||
{ id: "gemini-3-pro-preview", name: "Gemini 3 Pro Preview" },
|
||||
{ id: "gemini-3-flash-preview", name: "Gemini 3 Flash Preview" },
|
||||
{ id: "gemini-2.5-pro", name: "Gemini 2.5 Pro" },
|
||||
{ id: "gemini-2.5-flash", name: "Gemini 2.5 Flash" },
|
||||
{ id: "gemini-2.5-flash-lite", name: "Gemini 2.5 Flash Lite" },
|
||||
{ id: "gemini-2.0-flash", name: "Gemini 2.0 Flash" },
|
||||
{ id: "gemini-2.0-flash-lite", name: "Gemini 2.0 Flash Lite" },
|
||||
{ id: "gemini-1.5-pro", name: "Gemini 1.5 Pro" },
|
||||
{ id: "gemini-1.5-flash", name: "Gemini 1.5 Flash" },
|
||||
],
|
||||
mistral: [
|
||||
{ id: "mistral-large-latest", name: "Mistral Large (latest)" },
|
||||
{ id: "mistral-large-2512", name: "Mistral Large 3" },
|
||||
{ id: "mistral-medium-latest", name: "Mistral Medium (latest)" },
|
||||
{ id: "mistral-medium-2508", name: "Mistral Medium 3.1" },
|
||||
{ id: "mistral-small-latest", name: "Mistral Small (latest)" },
|
||||
{ id: "mistral-small-2603", name: "Mistral Small 4" },
|
||||
{ id: "magistral-medium-latest", name: "Magistral Medium (latest)" },
|
||||
{ id: "magistral-small", name: "Magistral Small" },
|
||||
{ id: "codestral-latest", name: "Codestral (latest)" },
|
||||
{ id: "devstral-medium-latest", name: "Devstral Medium (latest)" },
|
||||
{ id: "devstral-small-2507", name: "Devstral Small" },
|
||||
{ id: "ministral-8b-latest", name: "Ministral 8B (latest)" },
|
||||
{ id: "ministral-3b-latest", name: "Ministral 3B (latest)" },
|
||||
{ id: "pixtral-large-latest", name: "Pixtral Large (latest)" },
|
||||
{ id: "open-mistral-nemo", name: "Mistral Nemo" },
|
||||
],
|
||||
cerebras: [
|
||||
{ id: "qwen-3-235b-a22b-instruct-2507", name: "Qwen 3 235B Instruct" },
|
||||
{ id: "gpt-oss-120b", name: "GPT OSS 120B" },
|
||||
{ id: "zai-glm-4.7", name: "Z.AI GLM-4.7" },
|
||||
{ id: "llama3.1-8b", name: "Llama 3.1 8B" },
|
||||
],
|
||||
openrouter: [
|
||||
{ id: "anthropic/claude-sonnet-4.5", name: "Anthropic: Claude Sonnet 4.5" },
|
||||
{ id: "anthropic/claude-opus-4.5", name: "Anthropic: Claude Opus 4.5" },
|
||||
{ id: "anthropic/claude-haiku-4.5", name: "Anthropic: Claude Haiku 4.5" },
|
||||
{ id: "openai/gpt-5.2", name: "OpenAI: GPT-5.2" },
|
||||
{ id: "openai/gpt-5.1", name: "OpenAI: GPT-5.1" },
|
||||
{ id: "google/gemini-3-pro-preview", name: "Google: Gemini 3 Pro Preview" },
|
||||
{ id: "google/gemini-2.5-pro", name: "Google: Gemini 2.5 Pro" },
|
||||
{ id: "google/gemini-2.5-flash", name: "Google: Gemini 2.5 Flash" },
|
||||
{ id: "x-ai/grok-4", name: "xAI: Grok 4" },
|
||||
{ id: "deepseek/deepseek-chat", name: "DeepSeek: DeepSeek Chat" },
|
||||
{ id: "meta-llama/llama-4-maverick", name: "Meta: Llama 4 Maverick" },
|
||||
{ id: "qwen/qwen3-235b-a22b", name: "Qwen: Qwen3 235B A22B" },
|
||||
],
|
||||
};
|
||||
|
||||
export function listProviderModels(providerKey: string): ProviderModelEntry[] {
|
||||
return PROVIDER_MODELS[providerKey] ?? [];
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export const PROVIDER_DATA_POLICY = {
|
||||
STANDARD: "standard",
|
||||
ZERO_DATA_RETENTION: "zero_data_retention",
|
||||
} as const;
|
||||
|
||||
export const PROVIDER_EXECUTION_MODE = {
|
||||
FOREGROUND: "foreground",
|
||||
BACKGROUND: "background",
|
||||
} as const;
|
||||
|
||||
export type ProviderDataPolicy = ValueOf<typeof PROVIDER_DATA_POLICY>;
|
||||
export type ProviderExecutionMode = ValueOf<typeof PROVIDER_EXECUTION_MODE>;
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { ProviderExecutionMode } from "./provider-policy-domain";
|
||||
|
||||
export const PROVIDER_REQUEST_STATE = {
|
||||
PENDING: "pending",
|
||||
STREAMING: "streaming",
|
||||
SUCCEEDED: "succeeded",
|
||||
FAILED: "failed",
|
||||
CANCELLED: "cancelled",
|
||||
} as const;
|
||||
|
||||
export type ProviderRequestState = typeof PROVIDER_REQUEST_STATE[keyof typeof PROVIDER_REQUEST_STATE];
|
||||
|
||||
export interface ProviderRequestRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
providerKey: string;
|
||||
workspaceId: string | null;
|
||||
model: string;
|
||||
promptSha256: string;
|
||||
responseText: string | null;
|
||||
rawResponseJson: string | null;
|
||||
state: ProviderRequestState;
|
||||
errorMessage: string | null;
|
||||
inputCharCount: number;
|
||||
outputCharCount: number;
|
||||
executionMode: ProviderExecutionMode;
|
||||
policyDecision: string;
|
||||
externalResponseId: string | null;
|
||||
streamEventCount: number;
|
||||
cancelledAt: string | null;
|
||||
createdAt: string;
|
||||
completedAt: string | null;
|
||||
}
|
||||
|
||||
export interface ProviderStreamRendererEvent {
|
||||
requestId: string;
|
||||
providerId: string;
|
||||
providerKey: string;
|
||||
model: string;
|
||||
streamEventType: "message_start" | "text_delta" | "message_stop" | "error";
|
||||
textDelta: string | null;
|
||||
responseText: string;
|
||||
providerResponseId: string | null;
|
||||
rawEventJson: string;
|
||||
streamEventCount: number;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
export interface ProviderRateLimitStateRecord {
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
providerKey: string;
|
||||
windowStart: string;
|
||||
windowEnd: string;
|
||||
monthlyRequestLimit: number;
|
||||
requestCount: number;
|
||||
inputCharCount: number;
|
||||
outputCharCount: number;
|
||||
remainingRequestCount: number;
|
||||
exhausted: boolean;
|
||||
}
|
||||
|
||||
export interface ProviderObservedRateLimitState {
|
||||
requestLimit: number | null;
|
||||
remainingRequests: number | null;
|
||||
resetAt: string | null;
|
||||
retryAfterMs: number | null;
|
||||
rawStateJson: string;
|
||||
}
|
||||
|
||||
export interface ProviderRateLimitObservationRecord extends ProviderObservedRateLimitState {
|
||||
id: string;
|
||||
orgId: string;
|
||||
providerId: string;
|
||||
providerKey: string;
|
||||
model: string | null;
|
||||
observedAt: string;
|
||||
}
|
||||
|
||||
export function currentProviderUsageWindow(now = new Date()): { start: string; end: string } {
|
||||
const start = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), 1));
|
||||
const end = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth() + 1, 1));
|
||||
return { start: start.toISOString(), end: end.toISOString() };
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
export interface DesktopError {
|
||||
code: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export type DesktopResult<T> =
|
||||
| { ok: true; data: T }
|
||||
| { ok: false; error: DesktopError };
|
||||
|
||||
export function ok<T>(data: T): DesktopResult<T> {
|
||||
return { ok: true, data };
|
||||
}
|
||||
|
||||
export function fail(code: string, message: string): DesktopResult<never> {
|
||||
return { ok: false, error: { code, message } };
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
export interface RollbackSnapshotRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
migrationReportId: string;
|
||||
sourceDatabasePath: string;
|
||||
sourceFingerprint: string;
|
||||
sourceDatabaseSha256: string;
|
||||
workspaceManifestJson: string;
|
||||
workspaceManifestSha256: string;
|
||||
deltaJournalJson: string;
|
||||
restorePlanJson: string;
|
||||
active: boolean;
|
||||
createdByEmployeeId: string | null;
|
||||
createdAt: string;
|
||||
activatedAt: string | null;
|
||||
}
|
||||
|
||||
export interface MigrationCutoverEventRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
migrationReportId: string;
|
||||
rollbackSnapshotId: string | null;
|
||||
eventType: string;
|
||||
actorType: string;
|
||||
actorId: string | null;
|
||||
payloadJson: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface MigrationReconciliationItemRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
migrationReportId: string;
|
||||
rollbackSnapshotId: string | null;
|
||||
sourceEventId: string;
|
||||
targetType: string;
|
||||
targetId: string;
|
||||
reason: string;
|
||||
state: string;
|
||||
payloadJson: string;
|
||||
createdAt: string;
|
||||
resolvedAt: string | null;
|
||||
resolvedByEmployeeId: string | null;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
type ValueOf<T> = T[keyof T];
|
||||
|
||||
export const SDLC_REVIEW_AGENT_KEY = {
|
||||
CODE_REVIEWER: "code_reviewer",
|
||||
MIGRATION_REVIEWER: "migration_reviewer",
|
||||
POLICY_REVIEWER: "policy_reviewer",
|
||||
} as const;
|
||||
|
||||
export const SDLC_REVIEW_TARGET_TYPE = { WORKSPACE: "workspace", MIGRATION: "migration", POLICY: "policy" } as const;
|
||||
export const EVAL_SUITE_KEY = { CONTRACT: "contract", INTEGRATION: "integration", REPLAY: "replay" } as const;
|
||||
export const SDLC_RUN_STATE = { PASSED: "passed", FAILED: "failed" } as const;
|
||||
export const PR_BOT_GATE_KEY = {
|
||||
STATIC_CHECKS: "static_checks",
|
||||
MIGRATION_DIFF: "migration_diff",
|
||||
POLICY_DIFF: "policy_diff",
|
||||
HUMAN_APPROVAL: "human_approval",
|
||||
} as const;
|
||||
|
||||
export type SdlcReviewAgentKey = ValueOf<typeof SDLC_REVIEW_AGENT_KEY>;
|
||||
export type SdlcReviewTargetType = ValueOf<typeof SDLC_REVIEW_TARGET_TYPE>;
|
||||
export type EvalSuiteKey = ValueOf<typeof EVAL_SUITE_KEY>;
|
||||
export type SdlcRunState = ValueOf<typeof SDLC_RUN_STATE>;
|
||||
export type PrBotGateKey = ValueOf<typeof PR_BOT_GATE_KEY>;
|
||||
|
||||
export interface SdlcReviewAgentRecord {
|
||||
id: string; orgId: string; key: SdlcReviewAgentKey; label: string; specialty: string; enabled: boolean; createdAt: string; updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SdlcReviewRunRecord {
|
||||
id: string; orgId: string; reviewAgentId: string; targetType: SdlcReviewTargetType; targetRef: string;
|
||||
state: SdlcRunState; resultJson: string; createdAt: string; completedAt: string;
|
||||
}
|
||||
|
||||
export interface EvalSuiteRecord {
|
||||
id: string; orgId: string; key: EvalSuiteKey; label: string; scope: string; createdAt: string; updatedAt: string;
|
||||
}
|
||||
|
||||
export interface EvalCaseRecord {
|
||||
id: string; orgId: string; suiteId: string; title: string; sourceType: string; sourceRef: string; expectedSignal: string; createdAt: string;
|
||||
}
|
||||
|
||||
export interface EvalRunRecord {
|
||||
id: string; orgId: string; suiteId: string; state: SdlcRunState; passedCount: number; failedCount: number; resultJson: string; createdAt: string; completedAt: string;
|
||||
}
|
||||
|
||||
export interface PrBotGateRecord {
|
||||
id: string; orgId: string; key: PrBotGateKey; label: string; gateType: string; enabled: boolean; createdAt: string; updatedAt: string;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
export const SEARCH_ENTITY_TYPES = [
|
||||
"employee",
|
||||
"agent",
|
||||
"task",
|
||||
"goal",
|
||||
"project",
|
||||
"workspace",
|
||||
"approval",
|
||||
"chat_space",
|
||||
"chat_message",
|
||||
"file",
|
||||
"provider",
|
||||
"social_account",
|
||||
"scheduled_post",
|
||||
] as const;
|
||||
|
||||
export type SearchEntityType = (typeof SEARCH_ENTITY_TYPES)[number];
|
||||
|
||||
export interface SearchResultRecord {
|
||||
entityType: SearchEntityType;
|
||||
entityId: string;
|
||||
title: string;
|
||||
preview: string;
|
||||
facets: Record<string, string>;
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
import type { ProfileSnapshot } from "./types";
|
||||
|
||||
/**
|
||||
* Sidebar badge counters, derived purely from `ProfileSnapshot`.
|
||||
*
|
||||
* This is a local-first desktop app: every row the badges would want
|
||||
* to count is already in memory via `ProfileSnapshot` (which is scoped
|
||||
* to the current company and refreshed as an atomic unit). Running a
|
||||
* second server-side aggregation — as the old `getSidebarBadges` IPC
|
||||
* did — created two parallel data paths for the same answer, and the
|
||||
* two drifted whenever one side's data was mutated between refreshes
|
||||
* (e.g. a message being marked read in Communication). The resulting
|
||||
* "badge = 1, inbox = empty" mismatch was the visible symptom.
|
||||
*
|
||||
* Derivation eliminates the class. Same snapshot in, same badge out.
|
||||
* No IPC, no state, no drift.
|
||||
*/
|
||||
export interface SidebarBadges {
|
||||
pendingApprovals: number;
|
||||
activeRuns: number;
|
||||
failedRuns: number;
|
||||
todoTasks: number;
|
||||
budgetWarnings: number;
|
||||
unreadMessages: number;
|
||||
}
|
||||
|
||||
const FAILED_RUN_STATUSES: ReadonlyArray<string> = ["failed", "timed_out", "interrupted"];
|
||||
const ACTIVE_RUN_STATUSES: ReadonlyArray<string> = ["queued", "running"];
|
||||
const OPEN_TASK_STATUSES: ReadonlyArray<string> = ["todo", "in_progress", "in_review"];
|
||||
const BUDGET_WARNING_RATIO = 0.8;
|
||||
|
||||
/**
|
||||
* Derive the sidebar badge counts for the current snapshot. Call this
|
||||
* from the renderer whenever the snapshot changes; it is cheap
|
||||
* (O(n) linear filters over arrays that never exceed the snapshot's
|
||||
* per-company caps).
|
||||
*
|
||||
* `snapshot.agentMessages[i].readAt` already reflects the board
|
||||
* reader's read timestamp (the snapshot query joins
|
||||
* `agent_message_reads` with `agent_id = BOARD_READER_ID` and projects
|
||||
* that value into the `readAt` field — see
|
||||
* `src/main/database/snapshot.ts`). So the unread filter here is just
|
||||
* "no board read receipt" plus the same channel/priority scope the
|
||||
* old server query used.
|
||||
*/
|
||||
export function deriveSidebarBadges(snapshot: ProfileSnapshot, companyId: string | null): SidebarBadges {
|
||||
// The snapshot query is already company-scoped when `currentCompanyId`
|
||||
// is non-null (see `listRendererSnapshot` → `listSnapshot`). The extra
|
||||
// `companyId` filter here is defensive: on the rare path where the
|
||||
// caller passes an un-scoped snapshot (e.g., cross-company testing),
|
||||
// we still count the right company's rows rather than the union.
|
||||
const matchesCompany = <T extends { companyId: string }>(row: T): boolean =>
|
||||
companyId === null || row.companyId === companyId;
|
||||
|
||||
let pendingApprovals = 0;
|
||||
for (const approval of snapshot.approvals) {
|
||||
if (matchesCompany(approval) && approval.state === "pending") pendingApprovals += 1;
|
||||
}
|
||||
|
||||
let activeRuns = 0;
|
||||
let failedRuns = 0;
|
||||
for (const run of snapshot.runs) {
|
||||
if (!matchesCompany(run)) continue;
|
||||
if (ACTIVE_RUN_STATUSES.includes(run.status)) activeRuns += 1;
|
||||
else if (FAILED_RUN_STATUSES.includes(run.status)) failedRuns += 1;
|
||||
}
|
||||
|
||||
let todoTasks = 0;
|
||||
for (const task of snapshot.tasks) {
|
||||
if (matchesCompany(task) && OPEN_TASK_STATUSES.includes(task.status)) todoTasks += 1;
|
||||
}
|
||||
|
||||
let budgetWarnings = 0;
|
||||
for (const agent of snapshot.agents) {
|
||||
if (!matchesCompany(agent)) continue;
|
||||
if (agent.budgetMonthlyUsd > 0 && agent.spentMonthlyUsd / agent.budgetMonthlyUsd >= BUDGET_WARNING_RATIO) {
|
||||
budgetWarnings += 1;
|
||||
}
|
||||
}
|
||||
|
||||
let unreadMessages = 0;
|
||||
for (const message of snapshot.agentMessages) {
|
||||
if (!matchesCompany(message)) continue;
|
||||
if (message.readAt) continue;
|
||||
if (
|
||||
message.channel === "company" ||
|
||||
message.channel === "incident" ||
|
||||
message.priority === "urgent"
|
||||
) {
|
||||
unreadMessages += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
pendingApprovals,
|
||||
activeRuns,
|
||||
failedRuns,
|
||||
todoTasks,
|
||||
budgetWarnings,
|
||||
unreadMessages,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
import type { AuditReplayRunRecord } from "./audit-domain";
|
||||
import type { BoardInterventionRecord as BoardInterventionRecordModel } from "./board-domain";
|
||||
import type {
|
||||
ChatAttachmentRecord,
|
||||
ChatMembershipRecord,
|
||||
ChatMentionRecord,
|
||||
ChatMessageRecord,
|
||||
ChatPresenceRecord,
|
||||
ChatReadStateRecord,
|
||||
ChatSlashInvocationRecord,
|
||||
ChatSpaceRecord,
|
||||
ChatThreadRecord,
|
||||
} from "./chat-domain";
|
||||
import type { ComplianceExportRecord, LegalHoldRecord, RetentionFreezeRecord } from "./compliance-domain";
|
||||
import type {
|
||||
AgentRecord,
|
||||
ApprovalRecord,
|
||||
AuditEventRecord,
|
||||
AutomationRuleRecord,
|
||||
ConnectorAccountRecord,
|
||||
ConnectorGrantRecord,
|
||||
DocumentRecord,
|
||||
EmployeeRecord,
|
||||
FileAccessGrantRecord,
|
||||
FileHandoffRecord,
|
||||
FileObjectRecord,
|
||||
GoalRecord,
|
||||
KnowledgeEntryRecord,
|
||||
MeetingRecord,
|
||||
MigrationReportRecord,
|
||||
OrganizationRecord,
|
||||
PolicyRuleRecord,
|
||||
ProjectRecord,
|
||||
ProviderCatalogEntry,
|
||||
ProviderRecord,
|
||||
ScheduledPostRecord,
|
||||
SkillBindingRecord,
|
||||
SkillDefinitionRecord,
|
||||
SkillRevisionRecord,
|
||||
SkillRuntimeSnapshotRecord,
|
||||
SkillTestRecord,
|
||||
SprintRecord,
|
||||
TaskRecord,
|
||||
TaskRunRecord,
|
||||
WorkspaceRecord,
|
||||
} from "./domain";
|
||||
import type { AccessDecisionRecord, EmployeeIdentityRecord, RoleGrantRecord, ServiceIdentityRecord } from "./identity-domain";
|
||||
import type { ApprovalAssignmentRecord, ApprovalRoutingRuleRecord, HiringPolicyRecord, OrgDepartmentRecord } from "./org-governance-domain";
|
||||
import type { ChaosDrillRecord, ChaosDrillRunRecord, FeatureFlagRecord, OperationalEventRecord, SloTargetRecord } from "./operations-domain";
|
||||
import type { ProviderAuthProfileRecord, ProviderAuthSessionRecord } from "./provider-auth-domain";
|
||||
import type { ProviderRequestRecord } from "./provider-request-domain";
|
||||
import type { ProviderRateLimitObservationRecord, ProviderRateLimitStateRecord } from "./provider-runtime-domain";
|
||||
import type { MigrationCutoverEventRecord, MigrationReconciliationItemRecord, RollbackSnapshotRecord } from "./rollback-domain";
|
||||
import type { EvalCaseRecord, EvalRunRecord, EvalSuiteRecord, PrBotGateRecord, SdlcReviewAgentRecord, SdlcReviewRunRecord } from "./sdlc-domain";
|
||||
import type {
|
||||
BrowserActionPolicyRecord,
|
||||
BrowserActionRecord,
|
||||
BrowserSessionContainerRecord,
|
||||
SocialAccountGrantRecord,
|
||||
SocialAccountRecord,
|
||||
SocialApprovalRouteRecord,
|
||||
SocialAuditRecord,
|
||||
} from "./social-domain";
|
||||
|
||||
export interface AppSnapshot {
|
||||
activeOrgId: string | null;
|
||||
organizations: OrganizationRecord[];
|
||||
employees: EmployeeRecord[];
|
||||
agents: AgentRecord[];
|
||||
tasks: TaskRecord[];
|
||||
workspaces: WorkspaceRecord[];
|
||||
goals: GoalRecord[];
|
||||
projects: ProjectRecord[];
|
||||
taskRuns: TaskRunRecord[];
|
||||
approvals: ApprovalRecord[];
|
||||
chatSpaces: ChatSpaceRecord[];
|
||||
chatMemberships: ChatMembershipRecord[];
|
||||
chatMessages: ChatMessageRecord[];
|
||||
chatThreads: ChatThreadRecord[];
|
||||
chatAttachments: ChatAttachmentRecord[];
|
||||
chatMentions: ChatMentionRecord[];
|
||||
chatSlashInvocations: ChatSlashInvocationRecord[];
|
||||
boardInterventions: BoardInterventionRecordModel[];
|
||||
chatPresence: ChatPresenceRecord[];
|
||||
chatReadStates: ChatReadStateRecord[];
|
||||
files: FileObjectRecord[];
|
||||
fileAccessGrants: FileAccessGrantRecord[];
|
||||
fileHandoffRecords: FileHandoffRecord[];
|
||||
scheduledPosts: ScheduledPostRecord[];
|
||||
providers: ProviderRecord[];
|
||||
providerAuthProfiles: ProviderAuthProfileRecord[];
|
||||
providerAuthSessions: ProviderAuthSessionRecord[];
|
||||
providerCatalog: ProviderCatalogEntry[];
|
||||
providerRequests: ProviderRequestRecord[];
|
||||
providerRateLimits: ProviderRateLimitStateRecord[];
|
||||
providerRateLimitObservations: ProviderRateLimitObservationRecord[];
|
||||
skillDefinitions: SkillDefinitionRecord[];
|
||||
skillRevisions: SkillRevisionRecord[];
|
||||
skillBindings: SkillBindingRecord[];
|
||||
skillRuntimeSnapshots: SkillRuntimeSnapshotRecord[];
|
||||
skillTests: SkillTestRecord[];
|
||||
socialAccounts: SocialAccountRecord[];
|
||||
socialAccountGrants: SocialAccountGrantRecord[];
|
||||
browserSessionContainers: BrowserSessionContainerRecord[];
|
||||
browserActionPolicies: BrowserActionPolicyRecord[];
|
||||
socialApprovalRoutes: SocialApprovalRouteRecord[];
|
||||
browserActions: BrowserActionRecord[];
|
||||
socialAuditRecords: SocialAuditRecord[];
|
||||
policyRules: PolicyRuleRecord[];
|
||||
migrationReports: MigrationReportRecord[];
|
||||
rollbackSnapshots: RollbackSnapshotRecord[];
|
||||
migrationCutoverEvents: MigrationCutoverEventRecord[];
|
||||
migrationReconciliationItems: MigrationReconciliationItemRecord[];
|
||||
complianceExports: ComplianceExportRecord[];
|
||||
legalHolds: LegalHoldRecord[];
|
||||
retentionFreezes: RetentionFreezeRecord[];
|
||||
employeeIdentities: EmployeeIdentityRecord[];
|
||||
serviceIdentities: ServiceIdentityRecord[];
|
||||
roleGrants: RoleGrantRecord[];
|
||||
accessDecisions: AccessDecisionRecord[];
|
||||
orgDepartments: OrgDepartmentRecord[];
|
||||
hiringPolicies: HiringPolicyRecord[];
|
||||
approvalRoutingRules: ApprovalRoutingRuleRecord[];
|
||||
approvalAssignments: ApprovalAssignmentRecord[];
|
||||
featureFlags: FeatureFlagRecord[];
|
||||
sloTargets: SloTargetRecord[];
|
||||
operationalEvents: OperationalEventRecord[];
|
||||
chaosDrills: ChaosDrillRecord[];
|
||||
chaosDrillRuns: ChaosDrillRunRecord[];
|
||||
sdlcReviewAgents: SdlcReviewAgentRecord[];
|
||||
sdlcReviewRuns: SdlcReviewRunRecord[];
|
||||
evalSuites: EvalSuiteRecord[];
|
||||
evalCases: EvalCaseRecord[];
|
||||
evalRuns: EvalRunRecord[];
|
||||
prBotGates: PrBotGateRecord[];
|
||||
auditReplayRuns: AuditReplayRunRecord[];
|
||||
auditEvents: AuditEventRecord[];
|
||||
documents: DocumentRecord[];
|
||||
knowledgeEntries: KnowledgeEntryRecord[];
|
||||
automationRules: AutomationRuleRecord[];
|
||||
meetings: MeetingRecord[];
|
||||
sprints: SprintRecord[];
|
||||
composioSettings: ComposioSettingRecord[];
|
||||
connectorAccounts: ConnectorAccountRecord[];
|
||||
connectorGrants: ConnectorGrantRecord[];
|
||||
}
|
||||
|
||||
export interface ComposioSettingRecord {
|
||||
orgId: string;
|
||||
key: string;
|
||||
value: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
import type { SocialPlatform } from "./domain";
|
||||
|
||||
export interface SocialAccountRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
platform: SocialPlatform;
|
||||
handle: string;
|
||||
displayName: string;
|
||||
authorizedEmployeeId: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SocialAccountGrantRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
socialAccountId: string;
|
||||
employeeId: string;
|
||||
role: string;
|
||||
scopeJson: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface BrowserSessionContainerRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
socialAccountId: string;
|
||||
platform: SocialPlatform;
|
||||
partitionKey: string;
|
||||
hostAllowlistJson: string;
|
||||
permissionPolicy: string;
|
||||
sandboxEnabled: boolean;
|
||||
createdAt: string;
|
||||
lastUsedAt: string | null;
|
||||
}
|
||||
|
||||
export interface BrowserActionPolicyRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
socialAccountId: string;
|
||||
actionType: string;
|
||||
contentCategory: string;
|
||||
riskLevel: string;
|
||||
approvalRequired: boolean;
|
||||
approvalKind: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SocialApprovalRouteRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
socialAccountId: string;
|
||||
actionType: string;
|
||||
riskLevel: string;
|
||||
approvalKind: string;
|
||||
routeToType: string;
|
||||
routeToId: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface BrowserActionRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
socialAccountId: string;
|
||||
actionType: string;
|
||||
policyDecision: string;
|
||||
evidenceFileId: string | null;
|
||||
metadataJson: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SocialAuditRecord {
|
||||
id: string;
|
||||
orgId: string;
|
||||
socialAccountId: string | null;
|
||||
sourceType: string;
|
||||
sourceId: string | null;
|
||||
eventType: string;
|
||||
actorType: string;
|
||||
actorId: string | null;
|
||||
policyDecision: string;
|
||||
evidenceFileId: string | null;
|
||||
metadataJson: string;
|
||||
createdAt: string;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export * from "./types/enums";
|
||||
export * from "./types/records";
|
||||
export * from "./types/events";
|
||||
export * from "./types/snapshot";
|
||||
@@ -1,300 +0,0 @@
|
||||
import { z } from "zod";
|
||||
|
||||
export type SectionId =
|
||||
| "overview"
|
||||
| "inbox"
|
||||
| "standup"
|
||||
| "performance"
|
||||
| "runs"
|
||||
| "connectors"
|
||||
| "agents"
|
||||
| "hiring"
|
||||
| "goals"
|
||||
| "projects"
|
||||
| "tasks"
|
||||
| "approvals"
|
||||
| "costs"
|
||||
| "activity"
|
||||
| "workspaces"
|
||||
| "social"
|
||||
| "skills"
|
||||
| "automation"
|
||||
| "communication"
|
||||
| "documents"
|
||||
| "knowledge"
|
||||
| "meetings"
|
||||
| "sprints"
|
||||
| "settings";
|
||||
|
||||
/**
|
||||
* Pure pi-mono connector catalog ids. Five OAuth, eighteen API-key, three
|
||||
* cloud — see `src/main/connector-definitions.ts`. The id is what the UI, the
|
||||
* database `connectors` table, and the worker resolver all key on.
|
||||
*
|
||||
* Single source of truth: derived from the `connectorIdEnum` zod enum in
|
||||
* `contracts/schemas-company.ts`. Adding a connector requires editing the zod
|
||||
* enum only; the TS union updates automatically.
|
||||
*/
|
||||
export type { ConnectorId } from "../contracts/schemas-company";
|
||||
|
||||
export type ConnectorStatus =
|
||||
| "not_installed"
|
||||
| "detected"
|
||||
| "auth_required"
|
||||
| "ready"
|
||||
| "degraded"
|
||||
| "error";
|
||||
|
||||
export type TaskType = "code" | "research" | "content" | "management" | "general";
|
||||
|
||||
export type WorkspaceState = "ready" | "busy" | "blocked" | "missing" | "error";
|
||||
export type CompanyStatus = "active" | "paused" | "archived";
|
||||
export type ExecutionMode = "ai_ceo" | "ai_cofounder";
|
||||
export type AgentStatus =
|
||||
| "idle"
|
||||
| "active"
|
||||
| "running"
|
||||
| "paused"
|
||||
| "error"
|
||||
| "pending_approval"
|
||||
| "terminated";
|
||||
|
||||
/**
|
||||
* Hierarchical role seniority. Used by prompt generation, skill auto-assign,
|
||||
* and other "am I a manager?" decisions to avoid substring-matching English
|
||||
* role strings like "chief" / "vp" / "manager". `role` remains a free-text
|
||||
* field that users can edit in the UI.
|
||||
*/
|
||||
export type AgentRoleLevel = "ic" | "lead" | "manager" | "director" | "vp" | "c_suite";
|
||||
|
||||
export const AGENT_ROLE_LEVELS: readonly AgentRoleLevel[] = [
|
||||
"ic", "lead", "manager", "director", "vp", "c_suite",
|
||||
] as const;
|
||||
|
||||
/** Levels that grant leadership-style prompts and cross-team visibility. */
|
||||
export const LEADERSHIP_LEVELS: readonly AgentRoleLevel[] = [
|
||||
"lead", "manager", "director", "vp", "c_suite",
|
||||
] as const;
|
||||
|
||||
export function isLeadershipLevel(level: AgentRoleLevel | null | undefined): boolean {
|
||||
return level != null && level !== "ic";
|
||||
}
|
||||
|
||||
/**
|
||||
* Three-dimensional capability axes used by the model dispatcher. We compress
|
||||
* the marketing five ("architecture / coding / writing / math / research")
|
||||
* into three because the first, fourth and fifth collapse into a single
|
||||
* reasoning axis empirically — a model that can design an RFC, do the math,
|
||||
* and read a paper is the same model. Writing and coding stay separate
|
||||
* because the rankings between top providers diverge there.
|
||||
*/
|
||||
export type TaskDomain = "reasoning" | "coding" | "writing";
|
||||
|
||||
/**
|
||||
* Difficulty tier. Agents whose work is routine tagging, formatting, or
|
||||
* summarization are `trivial` and should burn the cheapest model that
|
||||
* clears the domain threshold. `hard` is for architecture/audit/research —
|
||||
* send the strongest model the user has enabled.
|
||||
*/
|
||||
export type TaskTier = "trivial" | "standard" | "hard";
|
||||
|
||||
/**
|
||||
* Run-time model routing for an agent.
|
||||
* - `explicit`: use the agent.connectorId + agent.model pair the user
|
||||
* saved. This was the pre-v39 behavior; existing rows stay
|
||||
* here on migration so nothing silently re-routes.
|
||||
* - `auto`: ignore agent.connectorId/model; the dispatcher picks the
|
||||
* cheapest enabled model that clears the agent's inferred
|
||||
* task profile. Default for newly created agents.
|
||||
*/
|
||||
export type AgentModelStrategy = "explicit" | "auto";
|
||||
|
||||
export type GoalStatus = "planned" | "active" | "achieved" | "cancelled";
|
||||
export type ProjectStatus = "backlog" | "planned" | "in_progress" | "completed" | "cancelled";
|
||||
export type TaskStatus = "backlog" | "todo" | "in_progress" | "in_review" | "done" | "blocked" | "cancelled";
|
||||
export type ApprovalState = "pending" | "approved" | "rejected" | "revision_requested";
|
||||
export const approvalTypeEnum = z.enum([
|
||||
"hire_agent",
|
||||
"approve_ceo_strategy",
|
||||
"dangerous_command",
|
||||
"secret_access",
|
||||
"budget_request",
|
||||
"promotion",
|
||||
"termination",
|
||||
"vendor_approval",
|
||||
"document_review",
|
||||
"production_deploy",
|
||||
"incident_escalation",
|
||||
"social_post",
|
||||
"deliverable_review",
|
||||
"budget_override",
|
||||
"plan_review",
|
||||
"scope_review",
|
||||
"draft_review",
|
||||
"strategy_review",
|
||||
"exception_review",
|
||||
]);
|
||||
|
||||
export type ApprovalType = z.infer<typeof approvalTypeEnum>;
|
||||
export type RunStatus =
|
||||
| "queued"
|
||||
| "running"
|
||||
| "succeeded"
|
||||
| "failed"
|
||||
| "cancelled"
|
||||
| "timed_out"
|
||||
| "interrupted";
|
||||
|
||||
export const RUN_USAGE_STATUSES = [
|
||||
"ok",
|
||||
"pre_first_message",
|
||||
"error_stop",
|
||||
"aborted_before_usage",
|
||||
] as const;
|
||||
|
||||
export type RunUsageStatus = (typeof RUN_USAGE_STATUSES)[number];
|
||||
|
||||
export type DepartmentId =
|
||||
| "executive"
|
||||
| "engineering"
|
||||
| "product"
|
||||
| "marketing"
|
||||
| "sales"
|
||||
| "hr"
|
||||
| "finance"
|
||||
| "legal"
|
||||
| "operations"
|
||||
| "customer_support"
|
||||
| "research"
|
||||
| "design";
|
||||
|
||||
export type SkillSourceType = "github" | "local_path" | "url" | "skills_sh" | "managed";
|
||||
export type TrustLevel = "markdown_only" | "assets" | "scripts_executables";
|
||||
|
||||
export type SocialPlatform =
|
||||
| "twitter"
|
||||
| "linkedin"
|
||||
| "instagram"
|
||||
| "facebook"
|
||||
| "reddit"
|
||||
| "youtube"
|
||||
| "tiktok"
|
||||
| "bluesky"
|
||||
| "discord"
|
||||
| "threads"
|
||||
| "pinterest"
|
||||
| "telegram"
|
||||
| "whatsapp"
|
||||
| "wechat"
|
||||
| "weibo"
|
||||
| "xiaohongshu"
|
||||
| "douyin"
|
||||
| "bilibili"
|
||||
| "zhihu"
|
||||
| "other";
|
||||
export type SocialAccountStatus = "active" | "logged_in" | "login_required" | "suspended" | "paused";
|
||||
export type BrowserActionType = "post" | "reply" | "like" | "follow" | "browse_feed" | "screenshot" | "navigate" | "search";
|
||||
export type BrowserActionStatus = "queued" | "running" | "succeeded" | "failed" | "cancelled" | "approval_required";
|
||||
|
||||
export type MeetingType =
|
||||
| "standup"
|
||||
| "sprint_planning"
|
||||
| "sprint_review"
|
||||
| "retrospective"
|
||||
| "one_on_one"
|
||||
| "all_hands"
|
||||
| "department_sync"
|
||||
| "incident_review"
|
||||
| "hiring_committee"
|
||||
| "budget_review"
|
||||
| "design_review"
|
||||
| "architecture_review";
|
||||
|
||||
export type MeetingStatus = "scheduled" | "in_progress" | "completed" | "cancelled";
|
||||
|
||||
export type DocumentType =
|
||||
| "prd"
|
||||
| "technical_spec"
|
||||
| "design_doc"
|
||||
| "test_plan"
|
||||
| "post_mortem"
|
||||
| "meeting_notes"
|
||||
| "budget_proposal"
|
||||
| "hiring_requisition"
|
||||
| "performance_review_doc"
|
||||
| "sop"
|
||||
| "knowledge_article"
|
||||
| "project_brief"
|
||||
| "sprint_report"
|
||||
| "incident_report"
|
||||
| "onboarding_guide"
|
||||
| "architecture_decision"
|
||||
| "status_report"
|
||||
| "contract"
|
||||
| "proposal";
|
||||
|
||||
export type DocumentStatus = "draft" | "in_review" | "approved" | "archived" | "superseded";
|
||||
|
||||
export type {
|
||||
WorkProductType,
|
||||
WorkProductProvider,
|
||||
WorkProductStatus,
|
||||
WorkProductReviewState,
|
||||
} from "../contracts/schemas-work-products";
|
||||
|
||||
export type KnowledgeCategory =
|
||||
| "lesson_learned"
|
||||
| "best_practice"
|
||||
| "decision"
|
||||
| "process"
|
||||
| "technical"
|
||||
| "business"
|
||||
| "onboarding"
|
||||
| "incident";
|
||||
|
||||
export type SprintStatus = "planning" | "active" | "review" | "completed" | "cancelled";
|
||||
|
||||
/**
|
||||
* Single source of truth: `automationTriggerEnum` in `contracts/helpers.ts`.
|
||||
* Shared by `automationRuleInputSchema` and `workflowInputSchema`.
|
||||
*/
|
||||
export type { AutomationTrigger } from "../contracts/helpers";
|
||||
|
||||
export type AutomationAction =
|
||||
| "assign_task"
|
||||
| "create_task"
|
||||
| "notify_agent"
|
||||
| "send_message"
|
||||
| "trigger_heartbeat"
|
||||
| "create_approval"
|
||||
| "update_task_status"
|
||||
| "escalate_to_manager"
|
||||
| "cross_department_notify"
|
||||
| "schedule_meeting"
|
||||
| "create_document"
|
||||
| "auto_approve"
|
||||
| "reassign_task"
|
||||
| "run_task";
|
||||
|
||||
export type AutomationStatus = "active" | "paused" | "disabled" | "error";
|
||||
|
||||
export type MessageChannel = "direct" | "department" | "company" | "project" | "incident";
|
||||
export type MessagePriority = "urgent" | "normal" | "low";
|
||||
|
||||
export type WorkflowStatus = "draft" | "active" | "paused" | "completed" | "failed";
|
||||
|
||||
|
||||
export type InboxItemType = "pending_approval" | "failed_run" | "budget_warning" | "blocked_task" | "review_needed" | "agent_message";
|
||||
|
||||
export type ThreadType = "task" | "approval" | "general" | "announcement";
|
||||
export type ThreadEventType =
|
||||
| "message"
|
||||
| "status_change"
|
||||
| "approval_request"
|
||||
| "approval_decision"
|
||||
| "file_attachment"
|
||||
| "system_note";
|
||||
export type ThreadActorType = "agent" | "user" | "system";
|
||||
export type ThreadParticipantRole = "owner" | "member" | "observer";
|
||||
export type ThreadWaitingFor = "user_review" | "user_approval" | "user_reply";
|
||||
export type ThreadNotifyOn = "all" | "mentions" | "none";
|
||||
@@ -1,191 +0,0 @@
|
||||
import type { RunStatus, SectionId, AutomationTrigger, AutomationAction } from "./enums";
|
||||
import type { CommentRecord } from "./records-core";
|
||||
import type { AgentMessageRecord } from "./records-extended";
|
||||
|
||||
export interface LogChunkEvent {
|
||||
type: "run-log";
|
||||
runId: string;
|
||||
stream: "stdout" | "stderr";
|
||||
chunk: string;
|
||||
}
|
||||
|
||||
export interface DomainChangedEvent {
|
||||
type: "domain-changed";
|
||||
}
|
||||
|
||||
export interface ShortcutEvent {
|
||||
type: "shortcut";
|
||||
action: "toggle-command-palette" | "refresh";
|
||||
}
|
||||
|
||||
export interface RunStatusEvent {
|
||||
type: "run-status";
|
||||
runId: string;
|
||||
status: RunStatus;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface HeartbeatStatusEvent {
|
||||
type: "heartbeat-status";
|
||||
agentId: string;
|
||||
enabled: boolean;
|
||||
nextWakeAt: string | null;
|
||||
}
|
||||
|
||||
export interface AgentMessageEvent {
|
||||
type: "agent-message";
|
||||
taskId: string;
|
||||
comment: CommentRecord;
|
||||
}
|
||||
|
||||
export interface AutomationFiredEvent {
|
||||
type: "automation-fired";
|
||||
ruleId: string;
|
||||
ruleName: string;
|
||||
trigger: AutomationTrigger;
|
||||
action: AutomationAction;
|
||||
}
|
||||
|
||||
export interface NewMessageEvent {
|
||||
type: "new-message";
|
||||
message: AgentMessageRecord;
|
||||
}
|
||||
|
||||
export interface NotificationClickEvent {
|
||||
type: "notification-click";
|
||||
section: SectionId;
|
||||
entityId?: string;
|
||||
}
|
||||
|
||||
export interface TaskUpdatedEvent {
|
||||
type: "task-updated";
|
||||
taskId: string;
|
||||
action: "created" | "updated" | "deleted";
|
||||
}
|
||||
|
||||
export interface RunUpdatedEvent {
|
||||
type: "run-updated";
|
||||
runId: string;
|
||||
action: "created" | "status_changed" | "completed";
|
||||
}
|
||||
|
||||
export interface ApprovalUpdatedEvent {
|
||||
type: "approval-updated";
|
||||
approvalId: string;
|
||||
action: "created" | "decided" | "deleted";
|
||||
}
|
||||
|
||||
export interface AgentUpdatedEvent {
|
||||
type: "agent-updated";
|
||||
agentId: string;
|
||||
action: "updated" | "paused";
|
||||
}
|
||||
|
||||
export interface BudgetChangedEvent {
|
||||
type: "budget-changed";
|
||||
companyId: string;
|
||||
}
|
||||
|
||||
export interface ThreadWaitStateUpdatedEvent {
|
||||
type: "thread-wait-state-updated";
|
||||
threadId: string;
|
||||
companyId: string;
|
||||
waitStateId: string;
|
||||
action: "created" | "resolved";
|
||||
}
|
||||
|
||||
export interface RecoveryNeededEvent {
|
||||
type: "recovery-needed";
|
||||
interruptedRuns: Array<{
|
||||
runId: string; taskId: string; taskTitle: string; agentId: string;
|
||||
agentName: string; companyId: string; connectorId: string; interruptedAt: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
// ─── pi-mono credentials / OAuth events ────────────────────────────────────
|
||||
|
||||
export type OAuthStatusValue =
|
||||
| "pending"
|
||||
| "in_progress"
|
||||
| "active"
|
||||
| "error"
|
||||
| "cancelled"
|
||||
| "completed";
|
||||
|
||||
export interface OAuthStatusEvent {
|
||||
type: "oauth:status";
|
||||
connectorId: string;
|
||||
status: OAuthStatusValue;
|
||||
message?: string;
|
||||
errorMessage?: string;
|
||||
}
|
||||
|
||||
export interface OAuthAuthUrlEvent {
|
||||
type: "oauth:auth-url";
|
||||
connectorId: string;
|
||||
url: string;
|
||||
instructions?: string;
|
||||
}
|
||||
|
||||
export interface OAuthProgressEvent {
|
||||
type: "oauth:progress";
|
||||
connectorId: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface OAuthPromptRequestEvent {
|
||||
type: "oauth:prompt-request";
|
||||
connectorId: string;
|
||||
requestId: string;
|
||||
message: string;
|
||||
placeholder?: string;
|
||||
allowEmpty?: boolean;
|
||||
}
|
||||
|
||||
export interface OAuthManualCodeRequestEvent {
|
||||
type: "oauth:manual-code-request";
|
||||
connectorId: string;
|
||||
requestId: string;
|
||||
authUrl?: string;
|
||||
instructions?: string;
|
||||
}
|
||||
|
||||
export interface CredentialsChangedEvent {
|
||||
type: "credentials-changed";
|
||||
connectorId?: string;
|
||||
}
|
||||
|
||||
export interface AgentEvent {
|
||||
type: "agent-event";
|
||||
runId: string;
|
||||
agentId: string;
|
||||
companyId: string;
|
||||
taskId: string | null;
|
||||
emittedAt: string;
|
||||
event: { type: string } & Record<string, unknown>;
|
||||
}
|
||||
|
||||
export type DesktopEvent =
|
||||
| LogChunkEvent
|
||||
| DomainChangedEvent
|
||||
| ShortcutEvent
|
||||
| RunStatusEvent
|
||||
| HeartbeatStatusEvent
|
||||
| AgentMessageEvent
|
||||
| AutomationFiredEvent
|
||||
| NewMessageEvent
|
||||
| NotificationClickEvent
|
||||
| TaskUpdatedEvent
|
||||
| RunUpdatedEvent
|
||||
| ApprovalUpdatedEvent
|
||||
| AgentUpdatedEvent
|
||||
| BudgetChangedEvent
|
||||
| ThreadWaitStateUpdatedEvent
|
||||
| RecoveryNeededEvent
|
||||
| OAuthStatusEvent
|
||||
| OAuthAuthUrlEvent
|
||||
| OAuthProgressEvent
|
||||
| OAuthPromptRequestEvent
|
||||
| OAuthManualCodeRequestEvent
|
||||
| CredentialsChangedEvent
|
||||
| AgentEvent;
|
||||
@@ -1,397 +0,0 @@
|
||||
import type {
|
||||
ConnectorId,
|
||||
ConnectorStatus,
|
||||
CompanyStatus,
|
||||
ExecutionMode,
|
||||
WorkspaceState,
|
||||
DepartmentId,
|
||||
AgentStatus,
|
||||
AgentRoleLevel,
|
||||
AgentModelStrategy,
|
||||
GoalStatus,
|
||||
ProjectStatus,
|
||||
TaskStatus,
|
||||
ApprovalState,
|
||||
ApprovalType,
|
||||
RunStatus,
|
||||
RunUsageStatus,
|
||||
SkillSourceType,
|
||||
TrustLevel,
|
||||
} from "./enums";
|
||||
|
||||
export interface CapabilityMatrix {
|
||||
sessionResume: boolean;
|
||||
gracefulCancel: boolean;
|
||||
modelDiscovery: boolean;
|
||||
structuredTranscript: boolean;
|
||||
costAttribution: boolean;
|
||||
}
|
||||
|
||||
export interface CompanyRecord {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
status: CompanyStatus;
|
||||
autoApproveHires: boolean;
|
||||
reviewDeliverables: boolean;
|
||||
executionMode: ExecutionMode;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ConnectorRecord {
|
||||
id: ConnectorId;
|
||||
label: string;
|
||||
description: string;
|
||||
status: ConnectorStatus;
|
||||
version: string | null;
|
||||
authState: "unknown" | "ok" | "required" | "error";
|
||||
lastCheckedAt: string | null;
|
||||
lastError: string | null;
|
||||
model: string | null;
|
||||
envBindingText: string;
|
||||
notes: string;
|
||||
configurationDoc: string;
|
||||
capabilityMatrix: CapabilityMatrix;
|
||||
}
|
||||
|
||||
export interface WorkspaceRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
name: string;
|
||||
localPath: string;
|
||||
repoUrl: string;
|
||||
repoRef: string;
|
||||
projectId: string | null;
|
||||
state: WorkspaceState;
|
||||
isPrimary: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface AgentRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
name: string;
|
||||
role: string;
|
||||
title: string;
|
||||
/**
|
||||
* Seniority enum used for leadership detection; free-text `role` remains
|
||||
* UI-editable. Optional on the read model because the DB column has a
|
||||
* `DEFAULT 'ic'` and no write path (agent-form / saveAgent / hireRequest)
|
||||
* currently accepts it. Consumers use `agentIsLeader()` which handles the
|
||||
* null/undefined case via keyword fallback.
|
||||
*/
|
||||
roleLevel?: AgentRoleLevel | null;
|
||||
department: DepartmentId | null;
|
||||
status: AgentStatus;
|
||||
reportsTo: string | null;
|
||||
connectorId: ConnectorId;
|
||||
workspaceId: string | null;
|
||||
model: string | null;
|
||||
/**
|
||||
* Model routing strategy (v39+). See AgentModelStrategy in enums.ts.
|
||||
* Optional on the read model because the DB column has a schema-level
|
||||
* default of 'explicit' for existing rows and legacy AgentRecord literals
|
||||
* in tests predate this field.
|
||||
*/
|
||||
modelStrategy?: AgentModelStrategy | null;
|
||||
capabilities: string;
|
||||
budgetMonthlyUsd: number;
|
||||
spentMonthlyUsd: number;
|
||||
metadataJson: string;
|
||||
heartbeatEnabled: boolean;
|
||||
heartbeatIntervalSec: number;
|
||||
lastHeartbeatAt: string | null;
|
||||
/**
|
||||
* Agent-scoped active session id. One active session per agent (per
|
||||
* company) — switching tasks appends a "now work on X" user turn to the
|
||||
* agent's ongoing transcript rather than starting a fresh session.
|
||||
* Optional on the read model for the same reason `roleLevel` is: existing
|
||||
* callers constructing an AgentRecord literally (tests, fixtures) do not
|
||||
* need to set it, and pre-migration rows legitimately have NULL.
|
||||
*/
|
||||
sessionId?: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface GoalRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
title: string;
|
||||
description: string;
|
||||
parentId: string | null;
|
||||
ownerAgentId: string | null;
|
||||
status: GoalStatus;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ProjectRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
goalId: string | null;
|
||||
name: string;
|
||||
description: string;
|
||||
leadAgentId: string | null;
|
||||
status: ProjectStatus;
|
||||
targetDate: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface TaskRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
projectId: string | null;
|
||||
goalId: string | null;
|
||||
parentId: string | null;
|
||||
title: string;
|
||||
description: string;
|
||||
assigneeAgentId: string | null;
|
||||
workspaceId: string | null;
|
||||
status: TaskStatus;
|
||||
priority: "critical" | "high" | "medium" | "low";
|
||||
activeRunId: string | null;
|
||||
costUsd: number;
|
||||
taskType: string | null;
|
||||
requiresUserReview: boolean;
|
||||
/**
|
||||
* Per-task filesystem lock policy (v52+). `true` makes the
|
||||
* orchestrator resolve a workspace and hold it exclusively for
|
||||
* the duration of the run. `false` lets a task with no explicit
|
||||
* workspace binding execute with `lockMode='none'`.
|
||||
*/
|
||||
requiresFilesystem: boolean;
|
||||
startedAt: string | null;
|
||||
completedAt: string | null;
|
||||
cancelledAt: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ApprovalRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
relatedTaskId: string | null;
|
||||
relatedAgentId: string | null;
|
||||
requestedByAgentId: string | null;
|
||||
type: ApprovalType;
|
||||
payloadSummary: string;
|
||||
impactSummary: string;
|
||||
payloadJson: string | null;
|
||||
decisionNote: string;
|
||||
state: ApprovalState;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface RunRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
taskId: string | null;
|
||||
agentId: string;
|
||||
workspaceId: string | null;
|
||||
connectorId: ConnectorId;
|
||||
status: RunStatus;
|
||||
summary: string;
|
||||
errorMessage: string | null;
|
||||
exitCode: number | null;
|
||||
signal: string | null;
|
||||
model: string | null;
|
||||
costUsd: number | null;
|
||||
unattributedCost: boolean;
|
||||
usageStatus: RunUsageStatus;
|
||||
startedAt: string | null;
|
||||
finishedAt: string | null;
|
||||
logPath: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface RunLogChunk {
|
||||
content: string;
|
||||
offset: number;
|
||||
nextOffset: number;
|
||||
totalBytes: number;
|
||||
eof: boolean;
|
||||
}
|
||||
|
||||
export interface CostRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
runId: string;
|
||||
taskId: string | null;
|
||||
agentId: string | null;
|
||||
connectorId: ConnectorId;
|
||||
amountUsd: number | null;
|
||||
unattributed: boolean;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface BudgetPolicyRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
scopeType: "company" | "agent" | "project";
|
||||
scopeId: string;
|
||||
metric: string;
|
||||
windowKind: string;
|
||||
amount: number; // INTEGER cents
|
||||
warnPercent: number;
|
||||
hardStopEnabled: boolean;
|
||||
notifyEnabled: boolean;
|
||||
isActive: boolean;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface BudgetIncidentRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
policyId: string;
|
||||
scopeType: string;
|
||||
scopeId: string;
|
||||
metric: string;
|
||||
windowKind: string;
|
||||
windowStart: string;
|
||||
windowEnd: string;
|
||||
thresholdType: "warn_threshold" | "hard_stop";
|
||||
amountLimit: number;
|
||||
amountObserved: number;
|
||||
status: "open" | "resolved" | "auto_resolved_limit_increase" | "auto_closed";
|
||||
resolvedAt: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface BudgetStatusSummary {
|
||||
policies: Array<{
|
||||
policyId: string;
|
||||
scopeType: string;
|
||||
scopeId: string;
|
||||
amount: number;
|
||||
spent: number;
|
||||
warnPercent: number;
|
||||
hardStopEnabled: boolean;
|
||||
hasOpenIncident: boolean;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface TaskSessionRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
agentId: string;
|
||||
adapterType: string;
|
||||
lastRunId: string | null;
|
||||
lastError: string | null;
|
||||
runCount: number;
|
||||
totalInputTokens: number;
|
||||
totalOutputTokens: number;
|
||||
rotatedAt: string | null;
|
||||
rotationReason: string | null;
|
||||
handoffMarkdown: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ActivityRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
actor: string;
|
||||
action: string;
|
||||
entityType: string;
|
||||
entityId: string;
|
||||
detail: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface SecretRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
name: string;
|
||||
description: string;
|
||||
backend: "safe_storage" | "vault";
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface CommentRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
taskId: string;
|
||||
authorAgentId: string | null;
|
||||
authorName: string;
|
||||
body: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface FileInventoryEntry {
|
||||
path: string;
|
||||
kind: "skill" | "reference" | "script" | "asset" | "markdown" | "other";
|
||||
}
|
||||
|
||||
export interface SkillRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
key: string;
|
||||
slug: string;
|
||||
name: string;
|
||||
description: string | null;
|
||||
sourceType: SkillSourceType;
|
||||
sourceLocator: string | null;
|
||||
sourceRef: string | null;
|
||||
trustLevel: TrustLevel;
|
||||
compatibility: string;
|
||||
fileInventory: FileInventoryEntry[];
|
||||
metadata: Record<string, unknown> | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SkillImportResult {
|
||||
skillId: string;
|
||||
key: string;
|
||||
name: string;
|
||||
isUpdate: boolean;
|
||||
}
|
||||
|
||||
export interface SkillUpdateStatus {
|
||||
skillId: string;
|
||||
key: string;
|
||||
currentRef: string | null;
|
||||
latestRef: string | null;
|
||||
hasUpdate: boolean;
|
||||
}
|
||||
|
||||
export type MentionOutcome = "woken" | "queued" | "busy" | "not_found";
|
||||
|
||||
export interface MentionResult {
|
||||
agentId: string;
|
||||
agentName: string;
|
||||
outcome: MentionOutcome;
|
||||
}
|
||||
|
||||
export interface SendMessageResult {
|
||||
id: string;
|
||||
mentionResults: MentionResult[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Row in `model_capabilities`. Scores are 1..5 integer ratings per domain,
|
||||
* tier is the hard lower bound the dispatcher clears before considering
|
||||
* `costPerMtokOut` to pick the cheapest qualifying model.
|
||||
*
|
||||
* Composite primary key `(provider, modelId)` — the same modelId can
|
||||
* legitimately ship under multiple providers (e.g. an Anthropic-compatible
|
||||
* endpoint that serves Claude via a Fireworks proxy).
|
||||
*/
|
||||
export interface ModelCapability {
|
||||
provider: string;
|
||||
modelId: string;
|
||||
reasoning: number;
|
||||
coding: number;
|
||||
writing: number;
|
||||
tier: "trivial" | "standard" | "hard";
|
||||
costPerMtokOut: number;
|
||||
updatedAt: string;
|
||||
}
|
||||
@@ -1,359 +0,0 @@
|
||||
import type { AgentStatus, RunStatus, InboxItemType } from "./enums";
|
||||
import type {
|
||||
SocialPlatform,
|
||||
SocialAccountStatus,
|
||||
BrowserActionType,
|
||||
BrowserActionStatus,
|
||||
MeetingType,
|
||||
MeetingStatus,
|
||||
DocumentType,
|
||||
DocumentStatus,
|
||||
KnowledgeCategory,
|
||||
SprintStatus,
|
||||
AutomationTrigger,
|
||||
AutomationAction,
|
||||
AutomationStatus,
|
||||
MessageChannel,
|
||||
MessagePriority,
|
||||
WorkflowStatus,
|
||||
ThreadType,
|
||||
ThreadActorType,
|
||||
ThreadEventType,
|
||||
ThreadParticipantRole,
|
||||
ThreadWaitingFor,
|
||||
ThreadNotifyOn,
|
||||
DepartmentId,
|
||||
WorkProductType,
|
||||
WorkProductProvider,
|
||||
WorkProductStatus,
|
||||
WorkProductReviewState,
|
||||
} from "./enums";
|
||||
|
||||
export interface SocialAccountRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
platform: SocialPlatform;
|
||||
accountName: string;
|
||||
displayName: string;
|
||||
profileUrl: string;
|
||||
credentialSecretId: string | null;
|
||||
status: SocialAccountStatus;
|
||||
requireApproval: boolean;
|
||||
metadataJson: string;
|
||||
lastUsedAt: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface BrowserActionRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
socialAccountId: string;
|
||||
agentId: string;
|
||||
taskId: string | null;
|
||||
actionType: BrowserActionType;
|
||||
payloadJson: string;
|
||||
status: BrowserActionStatus;
|
||||
resultSummary: string;
|
||||
screenshotPath: string | null;
|
||||
approvalId: string | null;
|
||||
errorMessage: string | null;
|
||||
startedAt: string | null;
|
||||
finishedAt: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface MeetingRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
type: MeetingType;
|
||||
title: string;
|
||||
organizerAgentId: string | null;
|
||||
participantAgentIds: string; // JSON array of agent IDs
|
||||
scheduledAt: string;
|
||||
durationMinutes: number;
|
||||
agendaJson: string;
|
||||
notesJson: string;
|
||||
decisionsJson: string;
|
||||
actionItemsJson: string;
|
||||
status: MeetingStatus;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface DocumentRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
type: DocumentType;
|
||||
title: string;
|
||||
content: string;
|
||||
authorAgentId: string | null;
|
||||
reviewerAgentId: string | null;
|
||||
projectId: string | null;
|
||||
goalId: string | null;
|
||||
parentDocId: string | null;
|
||||
version: number;
|
||||
status: DocumentStatus;
|
||||
tagsJson: string;
|
||||
latestRevisionId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface WorkProductRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
projectId: string | null;
|
||||
taskId: string | null;
|
||||
workspaceId: string | null;
|
||||
type: WorkProductType;
|
||||
provider: WorkProductProvider;
|
||||
externalId: string | null;
|
||||
title: string;
|
||||
url: string | null;
|
||||
status: WorkProductStatus;
|
||||
reviewState: WorkProductReviewState;
|
||||
isPrimary: boolean;
|
||||
summary: string | null;
|
||||
metadataJson: string | null;
|
||||
createdByRunId: string | null;
|
||||
lastTouchedByRunId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface KnowledgeEntryRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
category: KnowledgeCategory;
|
||||
topic: string;
|
||||
content: string;
|
||||
authorAgentId: string | null;
|
||||
importance: "critical" | "high" | "medium" | "low";
|
||||
tagsJson: string;
|
||||
referencedEntityType:
|
||||
| "agents"
|
||||
| "goals"
|
||||
| "projects"
|
||||
| "tasks"
|
||||
| "approvals"
|
||||
| "runs"
|
||||
| "secrets"
|
||||
| "meetings"
|
||||
| "documents"
|
||||
| "knowledge_base"
|
||||
| "sprints"
|
||||
| "automation_rules"
|
||||
| "workflow_pipelines"
|
||||
| null;
|
||||
referencedEntityId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface SprintRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
name: string;
|
||||
goal: string;
|
||||
startDate: string;
|
||||
endDate: string;
|
||||
status: SprintStatus;
|
||||
retrospectiveNotes: string;
|
||||
velocityPoints: number;
|
||||
completedPoints: number;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface AutomationRuleRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
name: string;
|
||||
description: string;
|
||||
trigger: AutomationTrigger;
|
||||
conditionsJson: string;
|
||||
action: AutomationAction;
|
||||
actionConfigJson: string;
|
||||
sourceDepartment: DepartmentId | null;
|
||||
targetDepartment: DepartmentId | null;
|
||||
priority: number;
|
||||
status: AutomationStatus;
|
||||
executionCount: number;
|
||||
lastExecutedAt: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface AgentMessageRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
fromAgentId: string;
|
||||
toAgentId: string | null;
|
||||
senderKind: "agent" | "human" | "system";
|
||||
channel: MessageChannel;
|
||||
channelTargetId: string | null;
|
||||
subject: string;
|
||||
body: string;
|
||||
priority: MessagePriority;
|
||||
readAt: string | null;
|
||||
parentMessageId: string | null;
|
||||
attachmentsJson: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface WorkflowPipelineRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
name: string;
|
||||
description: string;
|
||||
stepsJson: string;
|
||||
triggerType: AutomationTrigger;
|
||||
triggerConfigJson: string;
|
||||
status: WorkflowStatus;
|
||||
currentStepIndex: number;
|
||||
runCount: number;
|
||||
lastRunAt: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface WorkflowStep {
|
||||
id: string;
|
||||
name: string;
|
||||
action: AutomationAction;
|
||||
configJson: string;
|
||||
assigneeDepartment: DepartmentId | null;
|
||||
assigneeAgentId: string | null;
|
||||
requiresApproval: boolean;
|
||||
timeoutSec: number;
|
||||
status: "pending" | "running" | "completed" | "failed" | "skipped";
|
||||
}
|
||||
|
||||
export interface ConversationThreadRecord {
|
||||
id: string;
|
||||
companyId: string;
|
||||
title: string;
|
||||
type: ThreadType;
|
||||
relatedEntityType: string | null;
|
||||
relatedEntityId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface ConversationEventRecord {
|
||||
id: string;
|
||||
threadId: string;
|
||||
actorId: string;
|
||||
actorType: ThreadActorType;
|
||||
eventType: ThreadEventType;
|
||||
body: string;
|
||||
metadataJson: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface ConversationParticipantRecord {
|
||||
threadId: string;
|
||||
participantId: string;
|
||||
participantType: ThreadActorType;
|
||||
role: ThreadParticipantRole;
|
||||
joinedAt: string;
|
||||
}
|
||||
|
||||
export interface ThreadSubscriptionRecord {
|
||||
threadId: string;
|
||||
subscriberId: string;
|
||||
subscriberType: ThreadActorType;
|
||||
notifyOn: ThreadNotifyOn;
|
||||
subscribedAt: string;
|
||||
}
|
||||
|
||||
export interface ThreadWaitStateRecord {
|
||||
id: string;
|
||||
threadId: string;
|
||||
companyId: string;
|
||||
waitingFor: ThreadWaitingFor;
|
||||
relatedApprovalId: string | null;
|
||||
reason: string;
|
||||
createdAt: string;
|
||||
resolvedAt: string | null;
|
||||
}
|
||||
|
||||
export interface InboxItem {
|
||||
id: string;
|
||||
type: InboxItemType;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
severity: "critical" | "high" | "medium" | "low";
|
||||
entityType: string;
|
||||
entityId: string;
|
||||
agentId: string | null;
|
||||
agentName: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface AgentMetrics {
|
||||
agentId: string;
|
||||
agentName: string;
|
||||
tasksCompleted: number;
|
||||
tasksAssigned: number;
|
||||
tasksFailed: number;
|
||||
successRate: number;
|
||||
avgRunDurationSec: number;
|
||||
totalCostUsd: number;
|
||||
runsTotal: number;
|
||||
runsSucceeded: number;
|
||||
runsFailed: number;
|
||||
reviewCycles: number;
|
||||
lastActiveAt: string | null;
|
||||
}
|
||||
|
||||
export interface CompanyMetrics {
|
||||
totalAgents: number;
|
||||
activeAgents: number;
|
||||
totalTasks: number;
|
||||
completedTasks: number;
|
||||
blockedTasks: number;
|
||||
totalRuns: number;
|
||||
successfulRuns: number;
|
||||
failedRuns: number;
|
||||
overallSuccessRate: number;
|
||||
totalCostUsd: number;
|
||||
avgCostPerTask: number;
|
||||
throughputTasksPerDay: number;
|
||||
agentMetrics: AgentMetrics[];
|
||||
}
|
||||
|
||||
export interface OnboardingBootstrapResult {
|
||||
companyId: string;
|
||||
companyName: string;
|
||||
workspaceId: string | null;
|
||||
leadAgentId: string | null;
|
||||
projectId: string | null;
|
||||
taskId: string | null;
|
||||
runId: string | null;
|
||||
}
|
||||
|
||||
export interface StandupReport {
|
||||
companyId: string;
|
||||
generatedAt: string;
|
||||
summary: string;
|
||||
agentReports: Array<{
|
||||
agentId: string;
|
||||
agentName: string;
|
||||
role: string;
|
||||
status: AgentStatus;
|
||||
tasksInProgress: number;
|
||||
tasksCompleted24h: number;
|
||||
tasksBlocked: number;
|
||||
lastRunStatus: RunStatus | null;
|
||||
lastRunAt: string | null;
|
||||
costLast24h: number;
|
||||
highlights: string[];
|
||||
}>;
|
||||
companyHighlights: string[];
|
||||
blockers: string[];
|
||||
pendingApprovals: number;
|
||||
budgetUtilization: number;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from "./records-core";
|
||||
export * from "./records-extended";
|
||||
@@ -1,101 +0,0 @@
|
||||
import type {
|
||||
CompanyRecord,
|
||||
ConnectorRecord,
|
||||
WorkspaceRecord,
|
||||
AgentRecord,
|
||||
GoalRecord,
|
||||
ProjectRecord,
|
||||
TaskRecord,
|
||||
ApprovalRecord,
|
||||
RunRecord,
|
||||
CostRecord,
|
||||
ActivityRecord,
|
||||
SecretRecord,
|
||||
CommentRecord,
|
||||
} from "./records-core";
|
||||
import type {
|
||||
SocialAccountRecord,
|
||||
MeetingRecord,
|
||||
DocumentRecord,
|
||||
KnowledgeEntryRecord,
|
||||
SprintRecord,
|
||||
AutomationRuleRecord,
|
||||
AgentMessageRecord,
|
||||
WorkflowPipelineRecord,
|
||||
WorkProductRecord,
|
||||
} from "./records-extended";
|
||||
|
||||
export interface ProfileSnapshot {
|
||||
// ─── Profile-level (shared across all companies) ─────────────────────────
|
||||
currentCompanyId: string | null;
|
||||
profilePath: string;
|
||||
updatesEnabled: boolean;
|
||||
theme: "system" | "light" | "dark";
|
||||
locale: "en" | "zh";
|
||||
backend: {
|
||||
secretBackend: string;
|
||||
};
|
||||
companies: CompanyRecord[];
|
||||
connectors: ConnectorRecord[];
|
||||
// ─── Company-scoped collections (current company only) ───────────────────
|
||||
workspaces: WorkspaceRecord[];
|
||||
agents: AgentRecord[];
|
||||
goals: GoalRecord[];
|
||||
projects: ProjectRecord[];
|
||||
tasks: TaskRecord[];
|
||||
approvals: ApprovalRecord[];
|
||||
runs: RunRecord[];
|
||||
costs: CostRecord[];
|
||||
activity: ActivityRecord[];
|
||||
secrets: SecretRecord[];
|
||||
comments: CommentRecord[];
|
||||
socialAccounts: SocialAccountRecord[];
|
||||
meetings: MeetingRecord[];
|
||||
documents: DocumentRecord[];
|
||||
workProducts: WorkProductRecord[];
|
||||
knowledgeBase: KnowledgeEntryRecord[];
|
||||
sprints: SprintRecord[];
|
||||
automationRules: AutomationRuleRecord[];
|
||||
agentMessages: AgentMessageRecord[];
|
||||
workflows: WorkflowPipelineRecord[];
|
||||
}
|
||||
|
||||
/** Fields that are shared across companies and loaded regardless of currentCompanyId. */
|
||||
export const PROFILE_LEVEL_KEYS = [
|
||||
"currentCompanyId",
|
||||
"profilePath",
|
||||
"updatesEnabled",
|
||||
"theme",
|
||||
"locale",
|
||||
"backend",
|
||||
"companies",
|
||||
"connectors",
|
||||
] as const satisfies ReadonlyArray<keyof ProfileSnapshot>;
|
||||
|
||||
/** Fields that are filtered to the current company; switching companies reloads these. */
|
||||
export const COMPANY_SCOPED_KEYS = [
|
||||
"workspaces",
|
||||
"agents",
|
||||
"goals",
|
||||
"projects",
|
||||
"tasks",
|
||||
"approvals",
|
||||
"runs",
|
||||
"costs",
|
||||
"activity",
|
||||
"secrets",
|
||||
"comments",
|
||||
"socialAccounts",
|
||||
"meetings",
|
||||
"documents",
|
||||
"workProducts",
|
||||
"knowledgeBase",
|
||||
"sprints",
|
||||
"automationRules",
|
||||
"agentMessages",
|
||||
"workflows",
|
||||
] as const satisfies ReadonlyArray<keyof ProfileSnapshot>;
|
||||
|
||||
export type ProfileLevelKey = typeof PROFILE_LEVEL_KEYS[number];
|
||||
export type CompanyScopedKey = typeof COMPANY_SCOPED_KEYS[number];
|
||||
|
||||
Reference in new issue
Block a user