@elevasis/sdk 1.24.0 → 1.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +1178 -1039
- package/dist/index.d.ts +4760 -4567
- package/dist/index.js +989 -2332
- package/dist/node/index.d.ts +660 -1323
- package/dist/node/index.js +1 -1
- package/dist/test-utils/index.d.ts +4101 -4115
- package/dist/test-utils/index.js +1724 -3471
- package/dist/types/worker/index.d.ts +3 -2
- package/dist/types/worker/platform.d.ts +2 -2
- package/dist/worker/index.js +394 -2448
- package/package.json +2 -2
- package/reference/cli.mdx +1107 -808
- package/reference/scaffold/recipes/customize-crm-actions.md +45 -46
- package/reference/scaffold/recipes/extend-crm.md +253 -255
- package/reference/scaffold/recipes/index.md +43 -44
- package/reference/scaffold/reference/contracts.md +976 -1063
package/dist/node/index.d.ts
CHANGED
|
@@ -1388,668 +1388,108 @@ declare const OntologyScopeSchema: z.ZodDefault<z.ZodObject<{
|
|
|
1388
1388
|
}, z.core.$strip>>;
|
|
1389
1389
|
type OntologyScope = z.infer<typeof OntologyScopeSchema>;
|
|
1390
1390
|
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1391
|
+
type JsonPrimitive = string | number | boolean | null;
|
|
1392
|
+
type JsonValue = JsonPrimitive | JsonValue[] | {
|
|
1393
|
+
[key: string]: JsonValue;
|
|
1394
|
+
};
|
|
1395
|
+
/** Explicit interface needed to annotate the recursive SystemEntrySchema. */
|
|
1396
|
+
interface SystemEntry {
|
|
1397
|
+
id: string;
|
|
1398
|
+
label?: string;
|
|
1399
|
+
title?: string;
|
|
1400
|
+
description?: string;
|
|
1401
|
+
kind?: 'product' | 'operational' | 'platform' | 'diagnostic';
|
|
1402
|
+
parentSystemId?: string;
|
|
1403
|
+
ui?: {
|
|
1404
|
+
path: string;
|
|
1405
|
+
surfaces: string[];
|
|
1406
|
+
icon?: string;
|
|
1407
|
+
order?: number;
|
|
1408
|
+
};
|
|
1409
|
+
lifecycle?: 'draft' | 'beta' | 'active' | 'deprecated' | 'archived';
|
|
1410
|
+
responsibleRoleId?: string;
|
|
1411
|
+
governedByKnowledge?: string[];
|
|
1412
|
+
actions?: {
|
|
1413
|
+
actionId: string;
|
|
1414
|
+
intent: 'exposes' | 'consumes';
|
|
1415
|
+
invocation?: unknown;
|
|
1416
|
+
}[];
|
|
1417
|
+
policies?: string[];
|
|
1418
|
+
drivesGoals?: string[];
|
|
1419
|
+
/** @deprecated Use lifecycle. Accepted for one publish cycle. */
|
|
1420
|
+
status?: 'active' | 'deprecated' | 'archived';
|
|
1421
|
+
path?: string;
|
|
1422
|
+
icon?: string;
|
|
1423
|
+
color?: string;
|
|
1424
|
+
uiPosition?: 'sidebar-primary' | 'sidebar-bottom';
|
|
1425
|
+
enabled?: boolean;
|
|
1426
|
+
devOnly?: boolean;
|
|
1427
|
+
requiresAdmin?: boolean;
|
|
1428
|
+
order: number;
|
|
1429
|
+
config?: Record<string, JsonValue>;
|
|
1430
|
+
ontology?: OntologyScope;
|
|
1431
|
+
systems?: Record<string, SystemEntry>;
|
|
1432
|
+
subsystems?: Record<string, SystemEntry>;
|
|
1411
1433
|
}
|
|
1412
1434
|
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
iteration: number;
|
|
1427
|
-
actionsPlanned?: string[];
|
|
1428
|
-
sessionId?: string;
|
|
1429
|
-
turnNumber?: number;
|
|
1430
|
-
}
|
|
1431
|
-
interface AgentCompletionContext {
|
|
1432
|
-
type: 'agent-completion';
|
|
1433
|
-
attempt: 1 | 2;
|
|
1434
|
-
validationFailed?: boolean;
|
|
1435
|
-
sessionId?: string;
|
|
1436
|
-
turnNumber?: number;
|
|
1437
|
-
}
|
|
1438
|
-
interface WorkflowStepContext {
|
|
1439
|
-
type: 'workflow-step';
|
|
1440
|
-
stepId: string;
|
|
1441
|
-
stepName?: string;
|
|
1442
|
-
stepSequence?: number;
|
|
1443
|
-
}
|
|
1444
|
-
interface ToolCallContext {
|
|
1445
|
-
type: 'tool';
|
|
1446
|
-
toolName: string;
|
|
1447
|
-
parentIteration?: number;
|
|
1448
|
-
parentStepId?: string;
|
|
1449
|
-
}
|
|
1450
|
-
interface OtherCallContext {
|
|
1451
|
-
type: 'other';
|
|
1435
|
+
declare const SurfaceTypeSchema: z.ZodEnum<{
|
|
1436
|
+
dashboard: "dashboard";
|
|
1437
|
+
settings: "settings";
|
|
1438
|
+
graph: "graph";
|
|
1439
|
+
list: "list";
|
|
1440
|
+
page: "page";
|
|
1441
|
+
detail: "detail";
|
|
1442
|
+
}>;
|
|
1443
|
+
interface SidebarSurfaceNode {
|
|
1444
|
+
type: 'surface';
|
|
1445
|
+
label: string;
|
|
1446
|
+
path: string;
|
|
1447
|
+
surfaceType: z.infer<typeof SurfaceTypeSchema>;
|
|
1452
1448
|
description?: string;
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
outputTokens: number;
|
|
1464
|
-
latencyMs: number;
|
|
1465
|
-
/** Actual cost from provider in USD (when available, e.g., OpenRouter) */
|
|
1466
|
-
cost?: number;
|
|
1467
|
-
}
|
|
1468
|
-
interface AIUsageSummary {
|
|
1469
|
-
model: LLMModel;
|
|
1470
|
-
totalInputTokens: number;
|
|
1471
|
-
totalOutputTokens: number;
|
|
1472
|
-
totalTokens: number;
|
|
1473
|
-
totalCostUsd: number;
|
|
1474
|
-
callCount: number;
|
|
1475
|
-
calls: AICallRecord[];
|
|
1476
|
-
}
|
|
1477
|
-
interface ExecutionMetricsSummary {
|
|
1478
|
-
durationMs?: number;
|
|
1479
|
-
automationSavingsUsd?: number;
|
|
1480
|
-
}
|
|
1481
|
-
interface ResourceMetricsConfig {
|
|
1482
|
-
estimatedManualMinutes: number;
|
|
1483
|
-
hourlyLaborRateUsd: number;
|
|
1484
|
-
confidenceLevel?: 'low' | 'medium' | 'high';
|
|
1485
|
-
notes?: string;
|
|
1449
|
+
icon?: string;
|
|
1450
|
+
order?: number;
|
|
1451
|
+
targets?: {
|
|
1452
|
+
systems?: string[];
|
|
1453
|
+
entities?: string[];
|
|
1454
|
+
resources?: string[];
|
|
1455
|
+
actions?: string[];
|
|
1456
|
+
};
|
|
1457
|
+
devOnly?: boolean;
|
|
1458
|
+
requiresAdmin?: boolean;
|
|
1486
1459
|
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
private calls;
|
|
1495
|
-
private callSequence;
|
|
1496
|
-
/**
|
|
1497
|
-
* Record a single AI call with usage metrics
|
|
1498
|
-
*
|
|
1499
|
-
* @param usage - Token usage and latency data from LLM adapter
|
|
1500
|
-
* @param callType - Type discriminator (agent-reasoning, tool, etc.)
|
|
1501
|
-
* @param context - Optional typed context specific to callType
|
|
1502
|
-
*/
|
|
1503
|
-
record(usage: LLMUsageData, callType?: BaseAICall['callType'], context?: AICallContext): void;
|
|
1504
|
-
/**
|
|
1505
|
-
* Get aggregated summary of all AI calls
|
|
1506
|
-
*/
|
|
1507
|
-
getSummary(): AIUsageSummary;
|
|
1508
|
-
/**
|
|
1509
|
-
* Check if any usage has been recorded
|
|
1510
|
-
*/
|
|
1511
|
-
hasUsage(): boolean;
|
|
1460
|
+
interface SidebarGroupNode {
|
|
1461
|
+
type: 'group';
|
|
1462
|
+
label: string;
|
|
1463
|
+
description?: string;
|
|
1464
|
+
icon?: string;
|
|
1465
|
+
order?: number;
|
|
1466
|
+
children: Record<string, SidebarNode>;
|
|
1512
1467
|
}
|
|
1468
|
+
type SidebarNode = SidebarSurfaceNode | SidebarGroupNode;
|
|
1513
1469
|
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
/**
|
|
1538
|
-
* Structured action metadata attached to assistant messages.
|
|
1539
|
-
* Frontend reads this instead of parsing text prefixes.
|
|
1540
|
-
*/
|
|
1541
|
-
type AssistantAction = {
|
|
1542
|
-
kind: 'navigate';
|
|
1543
|
-
path: string;
|
|
1544
|
-
reason: string;
|
|
1545
|
-
} | {
|
|
1546
|
-
kind: 'update_filters';
|
|
1547
|
-
timeRange: string | null;
|
|
1548
|
-
statusFilter: string | null;
|
|
1549
|
-
searchQuery: string | null;
|
|
1550
|
-
};
|
|
1551
|
-
type MessageEvent = {
|
|
1552
|
-
type: 'user_message';
|
|
1553
|
-
text: string;
|
|
1554
|
-
} | {
|
|
1555
|
-
type: 'assistant_message';
|
|
1556
|
-
text: string;
|
|
1557
|
-
_action?: AssistantAction;
|
|
1558
|
-
} | {
|
|
1559
|
-
type: 'agent:started';
|
|
1560
|
-
} | {
|
|
1561
|
-
type: 'agent:completed';
|
|
1562
|
-
} | {
|
|
1563
|
-
type: 'agent:error';
|
|
1564
|
-
error: string;
|
|
1565
|
-
} | {
|
|
1566
|
-
type: 'agent:reasoning';
|
|
1567
|
-
iteration: number;
|
|
1568
|
-
reasoning: string;
|
|
1569
|
-
} | {
|
|
1570
|
-
type: 'agent:tool_call';
|
|
1571
|
-
toolName: string;
|
|
1572
|
-
args: Record<string, unknown>;
|
|
1573
|
-
} | {
|
|
1574
|
-
type: 'agent:tool_result';
|
|
1575
|
-
toolName: string;
|
|
1576
|
-
success: boolean;
|
|
1577
|
-
result?: unknown;
|
|
1578
|
-
error?: string;
|
|
1579
|
-
};
|
|
1580
|
-
/**
|
|
1581
|
-
* Execution context for all resources
|
|
1582
|
-
* Unified callback replaces SessionTurnMessages (removed)
|
|
1583
|
-
*/
|
|
1584
|
-
interface ExecutionContext extends ExecutionMetadata {
|
|
1585
|
-
logger: IExecutionLogger;
|
|
1586
|
-
signal?: AbortSignal;
|
|
1587
|
-
onMessageEvent?: (event: MessageEvent) => Promise<void>;
|
|
1588
|
-
/** Called per iteration to write heartbeat + check stall status. Non-fatal if it throws. */
|
|
1589
|
-
onHeartbeat?: () => Promise<void>;
|
|
1590
|
-
aiUsageCollector?: AIUsageCollector;
|
|
1591
|
-
metricsCollector?: MetricsCollector;
|
|
1592
|
-
parentExecutionId?: string;
|
|
1593
|
-
executionDepth: number;
|
|
1594
|
-
credentialName?: string;
|
|
1595
|
-
store: Map<string, unknown>;
|
|
1596
|
-
}
|
|
1597
|
-
interface Contract {
|
|
1598
|
-
inputSchema: z.ZodSchema;
|
|
1599
|
-
outputSchema?: z.ZodSchema;
|
|
1600
|
-
}
|
|
1601
|
-
|
|
1602
|
-
/**
|
|
1603
|
-
* Tool definitions
|
|
1604
|
-
*
|
|
1605
|
-
* Tool interface used by agents and workflows.
|
|
1606
|
-
* Provides a universal interface for AI systems to interact with tools.
|
|
1607
|
-
*/
|
|
1608
|
-
|
|
1609
|
-
/**
|
|
1610
|
-
* Options for tool execution
|
|
1611
|
-
* Provides named parameters for better API clarity and extensibility
|
|
1612
|
-
*/
|
|
1613
|
-
interface ToolExecutionOptions {
|
|
1614
|
-
/** Tool input (validated against inputSchema before execution) */
|
|
1615
|
-
input: unknown;
|
|
1616
|
-
/** Execution context with multi-tenant isolation and observability (optional for simple tools, required for platform/integration tools) */
|
|
1617
|
-
executionContext?: ExecutionContext;
|
|
1618
|
-
/** Full iteration context for advanced tools (provides access to memoryManager, toolRegistry, logger, etc.) */
|
|
1619
|
-
iterationContext?: IterationContext;
|
|
1620
|
-
/** Abort signal for timeout/cancellation -- forward to fetch() calls for clean cancellation */
|
|
1621
|
-
signal?: AbortSignal;
|
|
1622
|
-
}
|
|
1623
|
-
/**
|
|
1624
|
-
* Tool interface for AI systems
|
|
1625
|
-
*
|
|
1626
|
-
* Used by:
|
|
1627
|
-
* - Agents: For agentic tool use (reasoning loop selects and executes tools)
|
|
1628
|
-
* - Workflows: For workflow step tool invocation (future)
|
|
1629
|
-
* - Platform tools: createApprovalTool(), createSchedulerTool()
|
|
1630
|
-
* - Integration tools: External API calls (Gmail, Slack, etc.)
|
|
1631
|
-
*/
|
|
1632
|
-
interface Tool {
|
|
1633
|
-
name: string;
|
|
1634
|
-
description: string;
|
|
1635
|
-
inputSchema: z.ZodSchema;
|
|
1636
|
-
outputSchema: z.ZodSchema;
|
|
1637
|
-
execute: (options: ToolExecutionOptions) => Promise<unknown>;
|
|
1638
|
-
timeout?: number;
|
|
1639
|
-
}
|
|
1640
|
-
|
|
1641
|
-
/**
|
|
1642
|
-
* Supported integration types
|
|
1643
|
-
*
|
|
1644
|
-
* These represent the available integration adapters that can be used with tools.
|
|
1645
|
-
* Each integration type corresponds to an adapter implementation.
|
|
1646
|
-
*
|
|
1647
|
-
* Note: Concrete adapter implementations are deferred until needed.
|
|
1648
|
-
* This type provides compile-time safety and auto-completion for tool definitions.
|
|
1649
|
-
*/
|
|
1650
|
-
type IntegrationType = 'gmail' | 'google-sheets' | 'slack' | 'github' | 'linear' | 'attio' | 'airtable' | 'salesforce' | 'hubspot' | 'stripe' | 'twilio' | 'sendgrid' | 'mailgun' | 'zapier' | 'webhook' | 'apify' | 'instantly' | 'resend' | 'signature-api' | 'dropbox' | 'anymailfinder' | 'tomba' | 'millionverifier';
|
|
1651
|
-
|
|
1652
|
-
type JsonPrimitive = string | number | boolean | null;
|
|
1653
|
-
type JsonValue = JsonPrimitive | JsonValue[] | {
|
|
1654
|
-
[key: string]: JsonValue;
|
|
1655
|
-
};
|
|
1656
|
-
/** Explicit interface needed to annotate the recursive SystemEntrySchema. */
|
|
1657
|
-
interface SystemEntry {
|
|
1658
|
-
id: string;
|
|
1659
|
-
label?: string;
|
|
1660
|
-
title?: string;
|
|
1661
|
-
description?: string;
|
|
1662
|
-
kind?: 'product' | 'operational' | 'platform' | 'diagnostic';
|
|
1663
|
-
parentSystemId?: string;
|
|
1664
|
-
ui?: {
|
|
1665
|
-
path: string;
|
|
1666
|
-
surfaces: string[];
|
|
1667
|
-
icon?: string;
|
|
1668
|
-
order?: number;
|
|
1669
|
-
};
|
|
1670
|
-
lifecycle?: 'draft' | 'beta' | 'active' | 'deprecated' | 'archived';
|
|
1671
|
-
responsibleRoleId?: string;
|
|
1672
|
-
governedByKnowledge?: string[];
|
|
1673
|
-
actions?: {
|
|
1674
|
-
actionId: string;
|
|
1675
|
-
intent: 'exposes' | 'consumes';
|
|
1676
|
-
invocation?: unknown;
|
|
1677
|
-
}[];
|
|
1678
|
-
policies?: string[];
|
|
1679
|
-
drivesGoals?: string[];
|
|
1680
|
-
/** @deprecated Use lifecycle. Accepted for one publish cycle. */
|
|
1681
|
-
status?: 'active' | 'deprecated' | 'archived';
|
|
1682
|
-
path?: string;
|
|
1683
|
-
icon?: string;
|
|
1684
|
-
color?: string;
|
|
1685
|
-
uiPosition?: 'sidebar-primary' | 'sidebar-bottom';
|
|
1686
|
-
enabled?: boolean;
|
|
1687
|
-
devOnly?: boolean;
|
|
1688
|
-
requiresAdmin?: boolean;
|
|
1689
|
-
order: number;
|
|
1690
|
-
config?: Record<string, JsonValue>;
|
|
1691
|
-
ontology?: OntologyScope;
|
|
1692
|
-
systems?: Record<string, SystemEntry>;
|
|
1693
|
-
subsystems?: Record<string, SystemEntry>;
|
|
1694
|
-
}
|
|
1695
|
-
|
|
1696
|
-
/**
|
|
1697
|
-
* Resource Registry type definitions
|
|
1698
|
-
*/
|
|
1699
|
-
|
|
1700
|
-
/**
|
|
1701
|
-
* Environment/deployment status for resources
|
|
1702
|
-
*/
|
|
1703
|
-
type ResourceStatus = 'dev' | 'prod';
|
|
1704
|
-
/**
|
|
1705
|
-
* All resource types in the platform
|
|
1706
|
-
* Used as the discriminator field in ResourceDefinition
|
|
1707
|
-
*/
|
|
1708
|
-
type ResourceType = 'agent' | 'workflow' | 'trigger' | 'integration' | 'external' | 'human';
|
|
1709
|
-
type ResourceSystemSummary = Pick<SystemEntry, 'id' | 'title' | 'description' | 'kind' | 'lifecycle'>;
|
|
1710
|
-
/**
|
|
1711
|
-
* Base interface for ALL platform resources
|
|
1712
|
-
* Shared by both executable (agents, workflows) and non-executable (triggers, integrations, etc.) resources
|
|
1713
|
-
*/
|
|
1714
|
-
interface ResourceDefinition {
|
|
1715
|
-
/** Unique resource identifier */
|
|
1716
|
-
resourceId: string;
|
|
1717
|
-
/** Display name */
|
|
1718
|
-
name: string;
|
|
1719
|
-
/** Purpose and functionality description */
|
|
1720
|
-
description: string;
|
|
1721
|
-
/** Version for change tracking and evolution */
|
|
1722
|
-
version: string;
|
|
1723
|
-
/** Resource type discriminator */
|
|
1724
|
-
type: ResourceType;
|
|
1725
|
-
/** Environment/deployment status */
|
|
1726
|
-
status: ResourceStatus;
|
|
1727
|
-
/** Graph links to Organization Model nodes */
|
|
1728
|
-
links?: ResourceLink[];
|
|
1729
|
-
/** Infrastructure category for filtering */
|
|
1730
|
-
category?: ResourceCategory;
|
|
1731
|
-
/** Whether the agent supports multi-turn sessions (agents only) */
|
|
1732
|
-
sessionCapable?: boolean;
|
|
1733
|
-
/** Whether the resource is local (monorepo) or remote (externally deployed) */
|
|
1734
|
-
origin?: 'local' | 'remote';
|
|
1735
|
-
/** OM System membership — dot-separated system path (e.g. "sys.lead-gen"), when backed by a Resource descriptor */
|
|
1736
|
-
systemPath?: string;
|
|
1737
|
-
/** Display metadata for the owning OM System */
|
|
1738
|
-
system?: ResourceSystemSummary;
|
|
1739
|
-
/** Governance lifecycle status from the OM Resource descriptor */
|
|
1740
|
-
governanceStatus?: ResourceGovernanceStatus;
|
|
1741
|
-
/** Whether this resource is archived and should be excluded from registration and deployment */
|
|
1742
|
-
archived?: boolean;
|
|
1743
|
-
}
|
|
1744
|
-
/** Webhook provider identifiers */
|
|
1745
|
-
type WebhookProviderType = 'cal-com' | 'stripe' | 'signature-api' | 'instantly' | 'apify' | 'test';
|
|
1746
|
-
/** Webhook trigger configuration */
|
|
1747
|
-
interface WebhookTriggerConfig {
|
|
1748
|
-
/** Provider identifier */
|
|
1749
|
-
provider: WebhookProviderType;
|
|
1750
|
-
/** Event type for documentation (not used for matching - workflow handles routing) */
|
|
1751
|
-
event?: string;
|
|
1752
|
-
/** Optional filtering (e.g., specific form ID for Fillout) */
|
|
1753
|
-
filter?: Record<string, string>;
|
|
1754
|
-
/** References credential in credentials table for per-org webhook secrets */
|
|
1755
|
-
credentialName?: string;
|
|
1756
|
-
}
|
|
1757
|
-
/** Schedule trigger configuration */
|
|
1758
|
-
interface ScheduleTriggerConfig {
|
|
1759
|
-
/** Cron expression (e.g., '0 6 * * *') */
|
|
1760
|
-
cron: string;
|
|
1761
|
-
/** Optional timezone (default: UTC) */
|
|
1762
|
-
timezone?: string;
|
|
1763
|
-
}
|
|
1764
|
-
/** Event trigger configuration */
|
|
1765
|
-
interface EventTriggerConfig {
|
|
1766
|
-
/** Internal event type */
|
|
1767
|
-
eventType: string;
|
|
1768
|
-
/** Event source */
|
|
1769
|
-
source?: string;
|
|
1770
|
-
}
|
|
1771
|
-
/** Union of all trigger configs */
|
|
1772
|
-
type TriggerConfig = WebhookTriggerConfig | ScheduleTriggerConfig | EventTriggerConfig;
|
|
1773
|
-
/**
|
|
1774
|
-
* Trigger metadata - entry points that initiate resource execution
|
|
1775
|
-
*
|
|
1776
|
-
* Triggers represent how executions start: webhooks from external services,
|
|
1777
|
-
* scheduled cron jobs, platform events, or manual user actions.
|
|
1778
|
-
*
|
|
1779
|
-
* BREAKING CHANGES (2025-11-30):
|
|
1780
|
-
* - Now extends ResourceDefinition (inherits: resourceId, name, description, version, type, status, links, category)
|
|
1781
|
-
* - Field renames: `id` -> `resourceId` (inherited), `type` -> `triggerType`
|
|
1782
|
-
* - Relationship rename: `invokes` -> `triggers` (unified vocabulary)
|
|
1783
|
-
* - New required fields: `version` (inherited), `type: 'trigger'` (inherited)
|
|
1784
|
-
* - triggers object now includes `externalResources` option
|
|
1785
|
-
*
|
|
1786
|
-
* @example
|
|
1787
|
-
* // TriggerDefinition - metadata only
|
|
1788
|
-
* {
|
|
1789
|
-
* resourceId: 'trigger-new-order',
|
|
1790
|
-
* type: 'trigger',
|
|
1791
|
-
* triggerType: 'webhook',
|
|
1792
|
-
* name: 'New Order',
|
|
1793
|
-
* description: 'Webhook from Shopify on new orders',
|
|
1794
|
-
* version: '1.0.0',
|
|
1795
|
-
* status: 'prod',
|
|
1796
|
-
* webhookPath: '/webhooks/shopify/orders'
|
|
1797
|
-
* }
|
|
1798
|
-
*
|
|
1799
|
-
* // Relationships declared in ResourceRelationships (not on TriggerDefinition):
|
|
1800
|
-
* // relationships: {
|
|
1801
|
-
* // 'trigger-new-order': { triggers: { workflows: ['order-fulfillment-workflow'] } }
|
|
1802
|
-
* // }
|
|
1803
|
-
*/
|
|
1804
|
-
interface TriggerDefinition extends ResourceDefinition {
|
|
1805
|
-
/** Resource type discriminator (narrowed from base union) */
|
|
1806
|
-
type: 'trigger';
|
|
1807
|
-
/** Trigger mechanism type (renamed from 'type' to avoid collision with base type discriminator) */
|
|
1808
|
-
triggerType: 'webhook' | 'schedule' | 'manual' | 'event';
|
|
1809
|
-
/** Type-specific configuration */
|
|
1810
|
-
config?: TriggerConfig;
|
|
1811
|
-
/** For webhook triggers: path like '/webhooks/shopify/orders' */
|
|
1812
|
-
webhookPath?: string;
|
|
1813
|
-
/** For schedule triggers: cron expression like '0 6 * * *' */
|
|
1814
|
-
schedule?: string;
|
|
1815
|
-
/** For event triggers: event type like 'low-stock-alert' */
|
|
1816
|
-
eventType?: string;
|
|
1817
|
-
}
|
|
1818
|
-
/**
|
|
1819
|
-
* Integration metadata - external service connections
|
|
1820
|
-
*
|
|
1821
|
-
* References credentials table for actual connection. No connection status
|
|
1822
|
-
* stored here (queried at runtime from credentials table).
|
|
1823
|
-
*
|
|
1824
|
-
* BREAKING CHANGES (2025-11-30):
|
|
1825
|
-
* - Now extends ResourceDefinition (inherits: resourceId, name, description, version, type, status, links, category)
|
|
1826
|
-
* - Field renames: `id` -> `resourceId` (inherited)
|
|
1827
|
-
* - New required field: `status` (inherited) - organizations must add status to all integrations
|
|
1828
|
-
* - New required field: `version` (inherited) - organizations must add version to all integrations
|
|
1829
|
-
* - New required field: `type: 'integration'` (inherited) - resource type discriminator
|
|
1830
|
-
*
|
|
1831
|
-
* @example
|
|
1832
|
-
* {
|
|
1833
|
-
* resourceId: 'integration-shopify-prod',
|
|
1834
|
-
* type: 'integration',
|
|
1835
|
-
* provider: 'shopify',
|
|
1836
|
-
* credentialName: 'shopify-prod',
|
|
1837
|
-
* name: 'Shopify Production',
|
|
1838
|
-
* description: 'E-commerce platform',
|
|
1839
|
-
* version: '1.0.0',
|
|
1840
|
-
* status: 'prod'
|
|
1841
|
-
* }
|
|
1842
|
-
*/
|
|
1843
|
-
interface IntegrationDefinition extends ResourceDefinition {
|
|
1844
|
-
/** Resource type discriminator (narrowed from base union) */
|
|
1845
|
-
type: 'integration';
|
|
1846
|
-
/** OM descriptor that owns canonical identity and governance metadata. */
|
|
1847
|
-
resource?: Extract<ResourceEntry, {
|
|
1848
|
-
kind: 'integration';
|
|
1849
|
-
}>;
|
|
1850
|
-
/** Integration provider type */
|
|
1851
|
-
provider: IntegrationType;
|
|
1852
|
-
/** References credentials table (e.g., 'shopify-prod', 'zendesk-api') */
|
|
1853
|
-
credentialName: string;
|
|
1854
|
-
}
|
|
1855
|
-
/**
|
|
1856
|
-
* Explicit resource relationship declaration
|
|
1857
|
-
*
|
|
1858
|
-
* Single-direction only - Command View derives reverse relationships.
|
|
1859
|
-
* Agents/workflows declare what they trigger and use.
|
|
1860
|
-
*
|
|
1861
|
-
* @example
|
|
1862
|
-
* {
|
|
1863
|
-
* triggers: { workflows: ['order-fulfillment-workflow'] },
|
|
1864
|
-
* uses: { integrations: ['integration-shopify-prod', 'integration-postgres'] }
|
|
1865
|
-
* }
|
|
1866
|
-
*/
|
|
1867
|
-
interface RelationshipDeclaration {
|
|
1868
|
-
/** Resources this resource triggers */
|
|
1869
|
-
triggers?: {
|
|
1870
|
-
/** Agent resourceIds this resource triggers */
|
|
1871
|
-
agents?: string[];
|
|
1872
|
-
/** Workflow resourceIds this resource triggers */
|
|
1873
|
-
workflows?: string[];
|
|
1874
|
-
};
|
|
1875
|
-
/** Integrations this resource uses */
|
|
1876
|
-
uses?: {
|
|
1877
|
-
/** Integration IDs this resource uses */
|
|
1878
|
-
integrations?: string[];
|
|
1879
|
-
};
|
|
1880
|
-
}
|
|
1881
|
-
/**
|
|
1882
|
-
* Resource relationships map
|
|
1883
|
-
* Maps resourceId to its relationship declarations
|
|
1884
|
-
*
|
|
1885
|
-
* @example
|
|
1886
|
-
* {
|
|
1887
|
-
* 'order-processor-agent': {
|
|
1888
|
-
* triggers: { workflows: ['order-fulfillment-workflow'] },
|
|
1889
|
-
* uses: { integrations: ['integration-shopify-prod'] }
|
|
1890
|
-
* }
|
|
1891
|
-
* }
|
|
1892
|
-
*/
|
|
1893
|
-
type ResourceRelationships = Record<string, RelationshipDeclaration>;
|
|
1894
|
-
/**
|
|
1895
|
-
* External platform type
|
|
1896
|
-
* Supported third-party automation platforms
|
|
1897
|
-
*/
|
|
1898
|
-
type ExternalPlatform = 'n8n' | 'make' | 'zapier' | 'other';
|
|
1899
|
-
/**
|
|
1900
|
-
* External automation resource metadata
|
|
1901
|
-
*
|
|
1902
|
-
* Represents workflows/automations running on third-party platforms
|
|
1903
|
-
* (n8n, Make, Zapier, etc.) for visualization in Command View.
|
|
1904
|
-
*
|
|
1905
|
-
* NOTE: This is metadata ONLY for visualization. No execution logic,
|
|
1906
|
-
* no API integration with external platforms, no status syncing.
|
|
1907
|
-
*
|
|
1908
|
-
* BREAKING CHANGES (2025-11-30):
|
|
1909
|
-
* - Now extends ResourceDefinition (inherits: resourceId, name, description, version, type, status, links, category)
|
|
1910
|
-
* - Field renames: `id` -> `resourceId` (inherited)
|
|
1911
|
-
* - New required field: `version` (inherited) - organizations must add version to all external resources
|
|
1912
|
-
* - New required field: `type: 'external'` (inherited) - resource type discriminator
|
|
1913
|
-
* - REMOVED FIELD: `triggeredBy` - per relationship-consolidation design, all relationships are forward-only declarations
|
|
1914
|
-
*
|
|
1915
|
-
* @example
|
|
1916
|
-
* {
|
|
1917
|
-
* resourceId: 'external-n8n-order-sync',
|
|
1918
|
-
* type: 'external',
|
|
1919
|
-
* version: '1.0.0',
|
|
1920
|
-
* platform: 'n8n',
|
|
1921
|
-
* name: 'Shopify Order Sync',
|
|
1922
|
-
* description: 'Legacy n8n workflow for syncing Shopify orders',
|
|
1923
|
-
* status: 'prod',
|
|
1924
|
-
* platformUrl: 'https://n8n.client.com/workflow/123',
|
|
1925
|
-
* triggers: { workflows: ['order-fulfillment-workflow'] },
|
|
1926
|
-
* uses: { integrations: ['integration-shopify-prod'] }
|
|
1927
|
-
* }
|
|
1928
|
-
*/
|
|
1929
|
-
interface ExternalResourceDefinition extends ResourceDefinition {
|
|
1930
|
-
/** Resource type discriminator (narrowed from base union) */
|
|
1931
|
-
type: 'external';
|
|
1932
|
-
/** Platform type */
|
|
1933
|
-
platform: ExternalPlatform;
|
|
1934
|
-
/** Link to external platform (e.g., n8n workflow editor URL) */
|
|
1935
|
-
platformUrl?: string;
|
|
1936
|
-
/** Platform's internal ID/reference */
|
|
1937
|
-
externalId?: string;
|
|
1938
|
-
/** What this external resource triggers (external -> internal) */
|
|
1939
|
-
triggers?: {
|
|
1940
|
-
/** Elevasis workflow resourceIds this external automation triggers */
|
|
1941
|
-
workflows?: string[];
|
|
1942
|
-
/** Elevasis agent resourceIds this external automation triggers */
|
|
1943
|
-
agents?: string[];
|
|
1944
|
-
};
|
|
1945
|
-
/** Integrations this external resource uses (shared credentials) */
|
|
1946
|
-
uses?: {
|
|
1947
|
-
/** Integration IDs this external automation uses */
|
|
1948
|
-
integrations?: string[];
|
|
1949
|
-
};
|
|
1950
|
-
}
|
|
1951
|
-
/**
|
|
1952
|
-
* Human Checkpoint definition - human decision points in automation
|
|
1953
|
-
*
|
|
1954
|
-
* Represents where human judgment is deployed in the automation landscape.
|
|
1955
|
-
* Tasks with matching command_queue_group are routed to this checkpoint.
|
|
1956
|
-
*
|
|
1957
|
-
* BREAKING CHANGES (2025-11-30):
|
|
1958
|
-
* - Now extends ResourceDefinition (inherits: resourceId, name, description, version, type, status, links, category)
|
|
1959
|
-
* - Field renames: `id` -> `resourceId` (inherited)
|
|
1960
|
-
* - description is now REQUIRED (was optional) - organizations must add description to all human checkpoints
|
|
1961
|
-
* - New required field: `version` (inherited) - organizations must add version to all human checkpoints
|
|
1962
|
-
* - New required field: `type: 'human'` (inherited) - resource type discriminator
|
|
1963
|
-
*
|
|
1964
|
-
* @example
|
|
1965
|
-
* {
|
|
1966
|
-
* resourceId: 'sales-approval',
|
|
1967
|
-
* type: 'human',
|
|
1968
|
-
* name: 'Sales Approval Queue',
|
|
1969
|
-
* description: 'High-value order approvals for sales team',
|
|
1970
|
-
* version: '1.0.0',
|
|
1971
|
-
* status: 'prod',
|
|
1972
|
-
* requestedBy: { agents: ['order-processor-agent'] },
|
|
1973
|
-
* routesTo: { agents: ['order-fulfillment-agent'] }
|
|
1974
|
-
* }
|
|
1975
|
-
*/
|
|
1976
|
-
interface HumanCheckpointDefinition extends ResourceDefinition {
|
|
1977
|
-
/** Resource type discriminator (narrowed from base union) */
|
|
1978
|
-
type: 'human';
|
|
1979
|
-
/** Resources that create tasks for this checkpoint */
|
|
1980
|
-
requestedBy?: {
|
|
1981
|
-
/** Agent resourceIds that request approval here */
|
|
1982
|
-
agents?: string[];
|
|
1983
|
-
/** Workflow resourceIds that request approval here */
|
|
1984
|
-
workflows?: string[];
|
|
1985
|
-
};
|
|
1986
|
-
/** Resources that receive approved decisions */
|
|
1987
|
-
routesTo?: {
|
|
1988
|
-
/** Agent resourceIds that handle approved tasks */
|
|
1989
|
-
agents?: string[];
|
|
1990
|
-
/** Workflow resourceIds that handle approved tasks */
|
|
1991
|
-
workflows?: string[];
|
|
1992
|
-
};
|
|
1993
|
-
}
|
|
1994
|
-
|
|
1995
|
-
declare const SurfaceTypeSchema: z.ZodEnum<{
|
|
1996
|
-
dashboard: "dashboard";
|
|
1997
|
-
settings: "settings";
|
|
1998
|
-
graph: "graph";
|
|
1999
|
-
list: "list";
|
|
2000
|
-
page: "page";
|
|
2001
|
-
detail: "detail";
|
|
2002
|
-
}>;
|
|
2003
|
-
interface SidebarSurfaceNode {
|
|
2004
|
-
type: 'surface';
|
|
2005
|
-
label: string;
|
|
2006
|
-
path: string;
|
|
2007
|
-
surfaceType: z.infer<typeof SurfaceTypeSchema>;
|
|
2008
|
-
description?: string;
|
|
2009
|
-
icon?: string;
|
|
2010
|
-
order?: number;
|
|
2011
|
-
targets?: {
|
|
2012
|
-
systems?: string[];
|
|
2013
|
-
entities?: string[];
|
|
2014
|
-
resources?: string[];
|
|
2015
|
-
actions?: string[];
|
|
2016
|
-
};
|
|
2017
|
-
devOnly?: boolean;
|
|
2018
|
-
requiresAdmin?: boolean;
|
|
2019
|
-
}
|
|
2020
|
-
interface SidebarGroupNode {
|
|
2021
|
-
type: 'group';
|
|
2022
|
-
label: string;
|
|
2023
|
-
description?: string;
|
|
2024
|
-
icon?: string;
|
|
2025
|
-
order?: number;
|
|
2026
|
-
children: Record<string, SidebarNode>;
|
|
2027
|
-
}
|
|
2028
|
-
type SidebarNode = SidebarSurfaceNode | SidebarGroupNode;
|
|
2029
|
-
|
|
2030
|
-
declare const LinkSchema: z.ZodObject<{
|
|
2031
|
-
nodeId: z.ZodString;
|
|
2032
|
-
kind: z.ZodEnum<{
|
|
2033
|
-
links: "links";
|
|
2034
|
-
affects: "affects";
|
|
2035
|
-
effects: "effects";
|
|
2036
|
-
actions: "actions";
|
|
2037
|
-
reads: "reads";
|
|
2038
|
-
writes: "writes";
|
|
2039
|
-
emits: "emits";
|
|
2040
|
-
triggers: "triggers";
|
|
2041
|
-
uses: "uses";
|
|
2042
|
-
approval: "approval";
|
|
2043
|
-
contains: "contains";
|
|
2044
|
-
references: "references";
|
|
2045
|
-
maps_to: "maps_to";
|
|
2046
|
-
governs: "governs";
|
|
2047
|
-
originates_from: "originates_from";
|
|
2048
|
-
applies_to: "applies_to";
|
|
2049
|
-
uses_catalog: "uses_catalog";
|
|
2050
|
-
}>;
|
|
2051
|
-
}, z.core.$strip>;
|
|
2052
|
-
type Link = z.infer<typeof LinkSchema>;
|
|
1470
|
+
declare const LinkSchema: z.ZodObject<{
|
|
1471
|
+
nodeId: z.ZodString;
|
|
1472
|
+
kind: z.ZodEnum<{
|
|
1473
|
+
links: "links";
|
|
1474
|
+
affects: "affects";
|
|
1475
|
+
effects: "effects";
|
|
1476
|
+
actions: "actions";
|
|
1477
|
+
reads: "reads";
|
|
1478
|
+
writes: "writes";
|
|
1479
|
+
emits: "emits";
|
|
1480
|
+
triggers: "triggers";
|
|
1481
|
+
uses: "uses";
|
|
1482
|
+
approval: "approval";
|
|
1483
|
+
contains: "contains";
|
|
1484
|
+
references: "references";
|
|
1485
|
+
maps_to: "maps_to";
|
|
1486
|
+
governs: "governs";
|
|
1487
|
+
originates_from: "originates_from";
|
|
1488
|
+
applies_to: "applies_to";
|
|
1489
|
+
uses_catalog: "uses_catalog";
|
|
1490
|
+
}>;
|
|
1491
|
+
}, z.core.$strip>;
|
|
1492
|
+
type Link = z.infer<typeof LinkSchema>;
|
|
2053
1493
|
|
|
2054
1494
|
declare const OrganizationModelSchema$1: z.ZodObject<{
|
|
2055
1495
|
version: z.ZodDefault<z.ZodLiteral<1>>;
|
|
@@ -2225,7 +1665,7 @@ declare const OrganizationModelSchema$1: z.ZodObject<{
|
|
|
2225
1665
|
lastModified: string;
|
|
2226
1666
|
} | undefined;
|
|
2227
1667
|
}>>;
|
|
2228
|
-
branding: z.ZodObject<{
|
|
1668
|
+
branding: z.ZodDefault<z.ZodObject<{
|
|
2229
1669
|
organizationName: z.ZodString;
|
|
2230
1670
|
productName: z.ZodString;
|
|
2231
1671
|
shortName: z.ZodString;
|
|
@@ -2234,7 +1674,7 @@ declare const OrganizationModelSchema$1: z.ZodObject<{
|
|
|
2234
1674
|
light: z.ZodOptional<z.ZodString>;
|
|
2235
1675
|
dark: z.ZodOptional<z.ZodString>;
|
|
2236
1676
|
}, z.core.$strip>>;
|
|
2237
|
-
}, z.core.$strip
|
|
1677
|
+
}, z.core.$strip>>;
|
|
2238
1678
|
navigation: z.ZodDefault<z.ZodObject<{
|
|
2239
1679
|
sidebar: z.ZodDefault<z.ZodObject<{
|
|
2240
1680
|
primary: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodType<SidebarNode, unknown, z.core.$ZodTypeInternals<SidebarNode, unknown>>>>;
|
|
@@ -2962,7 +2402,567 @@ declare const OrganizationModelSchema$1: z.ZodObject<{
|
|
|
2962
2402
|
}, z.core.$strip>>>>;
|
|
2963
2403
|
}, z.core.$strip>;
|
|
2964
2404
|
|
|
2965
|
-
type OrganizationModel$1 = z.infer<typeof OrganizationModelSchema$1>;
|
|
2405
|
+
type OrganizationModel$1 = z.infer<typeof OrganizationModelSchema$1>;
|
|
2406
|
+
|
|
2407
|
+
/**
|
|
2408
|
+
* MetricsCollector
|
|
2409
|
+
* Tracks execution timing and ROI metrics
|
|
2410
|
+
*/
|
|
2411
|
+
declare class MetricsCollector {
|
|
2412
|
+
private timings;
|
|
2413
|
+
private durationMs?;
|
|
2414
|
+
/**
|
|
2415
|
+
* Start a timer with a label
|
|
2416
|
+
*/
|
|
2417
|
+
startTimer(label: string): void;
|
|
2418
|
+
/**
|
|
2419
|
+
* End a timer and calculate duration
|
|
2420
|
+
* If label is 'execution', stores duration for metrics summary
|
|
2421
|
+
*/
|
|
2422
|
+
endTimer(label: string): number | null;
|
|
2423
|
+
/**
|
|
2424
|
+
* Build execution metrics summary with optional ROI calculation
|
|
2425
|
+
*/
|
|
2426
|
+
buildExecutionMetrics(metricsConfig?: ResourceMetricsConfig): ExecutionMetricsSummary;
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
interface BaseAICall {
|
|
2430
|
+
callSequence: number;
|
|
2431
|
+
callType: 'agent-reasoning' | 'agent-completion' | 'workflow-step' | 'tool' | 'other';
|
|
2432
|
+
model: LLMModel;
|
|
2433
|
+
inputTokens: number;
|
|
2434
|
+
outputTokens: number;
|
|
2435
|
+
costUsd: number;
|
|
2436
|
+
latencyMs: number;
|
|
2437
|
+
context?: AICallContext;
|
|
2438
|
+
}
|
|
2439
|
+
type AICallContext = AgentReasoningContext | AgentCompletionContext | WorkflowStepContext | ToolCallContext | OtherCallContext;
|
|
2440
|
+
interface AgentReasoningContext {
|
|
2441
|
+
type: 'agent-reasoning';
|
|
2442
|
+
iteration: number;
|
|
2443
|
+
actionsPlanned?: string[];
|
|
2444
|
+
sessionId?: string;
|
|
2445
|
+
turnNumber?: number;
|
|
2446
|
+
}
|
|
2447
|
+
interface AgentCompletionContext {
|
|
2448
|
+
type: 'agent-completion';
|
|
2449
|
+
attempt: 1 | 2;
|
|
2450
|
+
validationFailed?: boolean;
|
|
2451
|
+
sessionId?: string;
|
|
2452
|
+
turnNumber?: number;
|
|
2453
|
+
}
|
|
2454
|
+
interface WorkflowStepContext {
|
|
2455
|
+
type: 'workflow-step';
|
|
2456
|
+
stepId: string;
|
|
2457
|
+
stepName?: string;
|
|
2458
|
+
stepSequence?: number;
|
|
2459
|
+
}
|
|
2460
|
+
interface ToolCallContext {
|
|
2461
|
+
type: 'tool';
|
|
2462
|
+
toolName: string;
|
|
2463
|
+
parentIteration?: number;
|
|
2464
|
+
parentStepId?: string;
|
|
2465
|
+
}
|
|
2466
|
+
interface OtherCallContext {
|
|
2467
|
+
type: 'other';
|
|
2468
|
+
description?: string;
|
|
2469
|
+
metadata?: Record<string, unknown>;
|
|
2470
|
+
}
|
|
2471
|
+
type AICallRecord = BaseAICall;
|
|
2472
|
+
/**
|
|
2473
|
+
* Raw LLM usage data returned by adapters
|
|
2474
|
+
* Used as input to AIUsageCollector.record()
|
|
2475
|
+
*/
|
|
2476
|
+
interface LLMUsageData {
|
|
2477
|
+
model: LLMModel;
|
|
2478
|
+
inputTokens: number;
|
|
2479
|
+
outputTokens: number;
|
|
2480
|
+
latencyMs: number;
|
|
2481
|
+
/** Actual cost from provider in USD (when available, e.g., OpenRouter) */
|
|
2482
|
+
cost?: number;
|
|
2483
|
+
}
|
|
2484
|
+
interface AIUsageSummary {
|
|
2485
|
+
model: LLMModel;
|
|
2486
|
+
totalInputTokens: number;
|
|
2487
|
+
totalOutputTokens: number;
|
|
2488
|
+
totalTokens: number;
|
|
2489
|
+
totalCostUsd: number;
|
|
2490
|
+
callCount: number;
|
|
2491
|
+
calls: AICallRecord[];
|
|
2492
|
+
}
|
|
2493
|
+
interface ExecutionMetricsSummary {
|
|
2494
|
+
durationMs?: number;
|
|
2495
|
+
automationSavingsUsd?: number;
|
|
2496
|
+
}
|
|
2497
|
+
interface ResourceMetricsConfig {
|
|
2498
|
+
estimatedManualMinutes: number;
|
|
2499
|
+
hourlyLaborRateUsd: number;
|
|
2500
|
+
confidenceLevel?: 'low' | 'medium' | 'high';
|
|
2501
|
+
notes?: string;
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
/**
|
|
2505
|
+
* AIUsageCollector
|
|
2506
|
+
* Centralized token tracking that aggregates usage across all LLM calls in an execution
|
|
2507
|
+
*/
|
|
2508
|
+
declare class AIUsageCollector {
|
|
2509
|
+
private model;
|
|
2510
|
+
private calls;
|
|
2511
|
+
private callSequence;
|
|
2512
|
+
/**
|
|
2513
|
+
* Record a single AI call with usage metrics
|
|
2514
|
+
*
|
|
2515
|
+
* @param usage - Token usage and latency data from LLM adapter
|
|
2516
|
+
* @param callType - Type discriminator (agent-reasoning, tool, etc.)
|
|
2517
|
+
* @param context - Optional typed context specific to callType
|
|
2518
|
+
*/
|
|
2519
|
+
record(usage: LLMUsageData, callType?: BaseAICall['callType'], context?: AICallContext): void;
|
|
2520
|
+
/**
|
|
2521
|
+
* Get aggregated summary of all AI calls
|
|
2522
|
+
*/
|
|
2523
|
+
getSummary(): AIUsageSummary;
|
|
2524
|
+
/**
|
|
2525
|
+
* Check if any usage has been recorded
|
|
2526
|
+
*/
|
|
2527
|
+
hasUsage(): boolean;
|
|
2528
|
+
}
|
|
2529
|
+
|
|
2530
|
+
/**
|
|
2531
|
+
* Base Execution Engine type definitions
|
|
2532
|
+
* Core types shared across all Execution Engine resources
|
|
2533
|
+
*/
|
|
2534
|
+
|
|
2535
|
+
/**
|
|
2536
|
+
* Immutable execution metadata
|
|
2537
|
+
* Represents complete execution identity (who, what, when, where)
|
|
2538
|
+
* Shared across ExecutionContext and ExecutionLoggerContext to eliminate field duplication
|
|
2539
|
+
*/
|
|
2540
|
+
interface ExecutionMetadata {
|
|
2541
|
+
executionId: string;
|
|
2542
|
+
organizationId: string;
|
|
2543
|
+
organizationName: string;
|
|
2544
|
+
resourceId: string;
|
|
2545
|
+
userId?: string;
|
|
2546
|
+
sessionId?: string;
|
|
2547
|
+
sessionTurnNumber?: number;
|
|
2548
|
+
}
|
|
2549
|
+
/**
|
|
2550
|
+
* Unified message event type - covers all message types in sessions
|
|
2551
|
+
* Replaces separate SessionTurnMessages and AgentActivityEvent mechanisms
|
|
2552
|
+
*/
|
|
2553
|
+
/**
|
|
2554
|
+
* Structured action metadata attached to assistant messages.
|
|
2555
|
+
* Frontend reads this instead of parsing text prefixes.
|
|
2556
|
+
*/
|
|
2557
|
+
type AssistantAction = {
|
|
2558
|
+
kind: 'navigate';
|
|
2559
|
+
path: string;
|
|
2560
|
+
reason: string;
|
|
2561
|
+
} | {
|
|
2562
|
+
kind: 'update_filters';
|
|
2563
|
+
timeRange: string | null;
|
|
2564
|
+
statusFilter: string | null;
|
|
2565
|
+
searchQuery: string | null;
|
|
2566
|
+
};
|
|
2567
|
+
type MessageEvent = {
|
|
2568
|
+
type: 'user_message';
|
|
2569
|
+
text: string;
|
|
2570
|
+
} | {
|
|
2571
|
+
type: 'assistant_message';
|
|
2572
|
+
text: string;
|
|
2573
|
+
_action?: AssistantAction;
|
|
2574
|
+
} | {
|
|
2575
|
+
type: 'agent:started';
|
|
2576
|
+
} | {
|
|
2577
|
+
type: 'agent:completed';
|
|
2578
|
+
} | {
|
|
2579
|
+
type: 'agent:error';
|
|
2580
|
+
error: string;
|
|
2581
|
+
} | {
|
|
2582
|
+
type: 'agent:reasoning';
|
|
2583
|
+
iteration: number;
|
|
2584
|
+
reasoning: string;
|
|
2585
|
+
} | {
|
|
2586
|
+
type: 'agent:tool_call';
|
|
2587
|
+
toolName: string;
|
|
2588
|
+
args: Record<string, unknown>;
|
|
2589
|
+
} | {
|
|
2590
|
+
type: 'agent:tool_result';
|
|
2591
|
+
toolName: string;
|
|
2592
|
+
success: boolean;
|
|
2593
|
+
result?: unknown;
|
|
2594
|
+
error?: string;
|
|
2595
|
+
};
|
|
2596
|
+
/**
|
|
2597
|
+
* Execution context for all resources
|
|
2598
|
+
* Unified callback replaces SessionTurnMessages (removed)
|
|
2599
|
+
*/
|
|
2600
|
+
interface ExecutionContext extends ExecutionMetadata {
|
|
2601
|
+
logger: IExecutionLogger;
|
|
2602
|
+
signal?: AbortSignal;
|
|
2603
|
+
onMessageEvent?: (event: MessageEvent) => Promise<void>;
|
|
2604
|
+
/** Called per iteration to write heartbeat + check stall status. Non-fatal if it throws. */
|
|
2605
|
+
onHeartbeat?: () => Promise<void>;
|
|
2606
|
+
aiUsageCollector?: AIUsageCollector;
|
|
2607
|
+
metricsCollector?: MetricsCollector;
|
|
2608
|
+
parentExecutionId?: string;
|
|
2609
|
+
executionDepth: number;
|
|
2610
|
+
credentialName?: string;
|
|
2611
|
+
store: Map<string, unknown>;
|
|
2612
|
+
}
|
|
2613
|
+
interface Contract {
|
|
2614
|
+
inputSchema: z.ZodSchema;
|
|
2615
|
+
outputSchema?: z.ZodSchema;
|
|
2616
|
+
}
|
|
2617
|
+
|
|
2618
|
+
/**
|
|
2619
|
+
* Tool definitions
|
|
2620
|
+
*
|
|
2621
|
+
* Tool interface used by agents and workflows.
|
|
2622
|
+
* Provides a universal interface for AI systems to interact with tools.
|
|
2623
|
+
*/
|
|
2624
|
+
|
|
2625
|
+
/**
|
|
2626
|
+
* Options for tool execution
|
|
2627
|
+
* Provides named parameters for better API clarity and extensibility
|
|
2628
|
+
*/
|
|
2629
|
+
interface ToolExecutionOptions {
|
|
2630
|
+
/** Tool input (validated against inputSchema before execution) */
|
|
2631
|
+
input: unknown;
|
|
2632
|
+
/** Execution context with multi-tenant isolation and observability (optional for simple tools, required for platform/integration tools) */
|
|
2633
|
+
executionContext?: ExecutionContext;
|
|
2634
|
+
/** Full iteration context for advanced tools (provides access to memoryManager, toolRegistry, logger, etc.) */
|
|
2635
|
+
iterationContext?: IterationContext;
|
|
2636
|
+
/** Abort signal for timeout/cancellation -- forward to fetch() calls for clean cancellation */
|
|
2637
|
+
signal?: AbortSignal;
|
|
2638
|
+
}
|
|
2639
|
+
/**
|
|
2640
|
+
* Tool interface for AI systems
|
|
2641
|
+
*
|
|
2642
|
+
* Used by:
|
|
2643
|
+
* - Agents: For agentic tool use (reasoning loop selects and executes tools)
|
|
2644
|
+
* - Workflows: For workflow step tool invocation (future)
|
|
2645
|
+
* - Platform tools: createApprovalTool(), createSchedulerTool()
|
|
2646
|
+
* - Integration tools: External API calls (Gmail, Slack, etc.)
|
|
2647
|
+
*/
|
|
2648
|
+
interface Tool {
|
|
2649
|
+
name: string;
|
|
2650
|
+
description: string;
|
|
2651
|
+
inputSchema: z.ZodSchema;
|
|
2652
|
+
outputSchema: z.ZodSchema;
|
|
2653
|
+
execute: (options: ToolExecutionOptions) => Promise<unknown>;
|
|
2654
|
+
timeout?: number;
|
|
2655
|
+
}
|
|
2656
|
+
|
|
2657
|
+
/**
|
|
2658
|
+
* Supported integration types
|
|
2659
|
+
*
|
|
2660
|
+
* These represent the available integration adapters that can be used with tools.
|
|
2661
|
+
* Each integration type corresponds to an adapter implementation.
|
|
2662
|
+
*
|
|
2663
|
+
* Note: Concrete adapter implementations are deferred until needed.
|
|
2664
|
+
* This type provides compile-time safety and auto-completion for tool definitions.
|
|
2665
|
+
*/
|
|
2666
|
+
type IntegrationType = 'gmail' | 'google-sheets' | 'slack' | 'github' | 'linear' | 'attio' | 'airtable' | 'salesforce' | 'hubspot' | 'stripe' | 'twilio' | 'sendgrid' | 'mailgun' | 'zapier' | 'webhook' | 'apify' | 'instantly' | 'resend' | 'signature-api' | 'dropbox' | 'anymailfinder' | 'tomba' | 'millionverifier';
|
|
2667
|
+
|
|
2668
|
+
/**
|
|
2669
|
+
* Resource Registry type definitions
|
|
2670
|
+
*/
|
|
2671
|
+
|
|
2672
|
+
/**
|
|
2673
|
+
* Environment/deployment status for resources
|
|
2674
|
+
*/
|
|
2675
|
+
type ResourceStatus = 'dev' | 'prod';
|
|
2676
|
+
/**
|
|
2677
|
+
* All resource types in the platform
|
|
2678
|
+
* Used as the discriminator field in ResourceDefinition
|
|
2679
|
+
*/
|
|
2680
|
+
type ResourceType = 'agent' | 'workflow' | 'trigger' | 'integration' | 'external' | 'human';
|
|
2681
|
+
type ResourceSystemSummary = Pick<SystemEntry, 'id' | 'title' | 'description' | 'kind' | 'lifecycle'>;
|
|
2682
|
+
/**
|
|
2683
|
+
* Base interface for ALL platform resources
|
|
2684
|
+
* Shared by both executable (agents, workflows) and non-executable (triggers, integrations, etc.) resources
|
|
2685
|
+
*/
|
|
2686
|
+
interface ResourceDefinition {
|
|
2687
|
+
/** Unique resource identifier */
|
|
2688
|
+
resourceId: string;
|
|
2689
|
+
/** Display name */
|
|
2690
|
+
name: string;
|
|
2691
|
+
/** Purpose and functionality description */
|
|
2692
|
+
description: string;
|
|
2693
|
+
/** Version for change tracking and evolution */
|
|
2694
|
+
version: string;
|
|
2695
|
+
/** Resource type discriminator */
|
|
2696
|
+
type: ResourceType;
|
|
2697
|
+
/** Environment/deployment status */
|
|
2698
|
+
status: ResourceStatus;
|
|
2699
|
+
/** Graph links to Organization Model nodes */
|
|
2700
|
+
links?: ResourceLink[];
|
|
2701
|
+
/** Infrastructure category for filtering */
|
|
2702
|
+
category?: ResourceCategory;
|
|
2703
|
+
/** Whether the agent supports multi-turn sessions (agents only) */
|
|
2704
|
+
sessionCapable?: boolean;
|
|
2705
|
+
/** Whether the resource is local (monorepo) or remote (externally deployed) */
|
|
2706
|
+
origin?: 'local' | 'remote';
|
|
2707
|
+
/** OM System membership — dot-separated system path (e.g. "sys.lead-gen"), when backed by a Resource descriptor */
|
|
2708
|
+
systemPath?: string;
|
|
2709
|
+
/** Display metadata for the owning OM System */
|
|
2710
|
+
system?: ResourceSystemSummary;
|
|
2711
|
+
/** Governance lifecycle status from the OM Resource descriptor */
|
|
2712
|
+
governanceStatus?: ResourceGovernanceStatus;
|
|
2713
|
+
/** Whether this resource is archived and should be excluded from registration and deployment */
|
|
2714
|
+
archived?: boolean;
|
|
2715
|
+
}
|
|
2716
|
+
/** Webhook provider identifiers */
|
|
2717
|
+
type WebhookProviderType = 'cal-com' | 'stripe' | 'signature-api' | 'instantly' | 'apify' | 'test';
|
|
2718
|
+
/** Webhook trigger configuration */
|
|
2719
|
+
interface WebhookTriggerConfig {
|
|
2720
|
+
/** Provider identifier */
|
|
2721
|
+
provider: WebhookProviderType;
|
|
2722
|
+
/** Event type for documentation (not used for matching - workflow handles routing) */
|
|
2723
|
+
event?: string;
|
|
2724
|
+
/** Optional filtering (e.g., specific form ID for Fillout) */
|
|
2725
|
+
filter?: Record<string, string>;
|
|
2726
|
+
/** References credential in credentials table for per-org webhook secrets */
|
|
2727
|
+
credentialName?: string;
|
|
2728
|
+
}
|
|
2729
|
+
/** Schedule trigger configuration */
|
|
2730
|
+
interface ScheduleTriggerConfig {
|
|
2731
|
+
/** Cron expression (e.g., '0 6 * * *') */
|
|
2732
|
+
cron: string;
|
|
2733
|
+
/** Optional timezone (default: UTC) */
|
|
2734
|
+
timezone?: string;
|
|
2735
|
+
}
|
|
2736
|
+
/** Event trigger configuration */
|
|
2737
|
+
interface EventTriggerConfig {
|
|
2738
|
+
/** Internal event type */
|
|
2739
|
+
eventType: string;
|
|
2740
|
+
/** Event source */
|
|
2741
|
+
source?: string;
|
|
2742
|
+
}
|
|
2743
|
+
/** Union of all trigger configs */
|
|
2744
|
+
type TriggerConfig = WebhookTriggerConfig | ScheduleTriggerConfig | EventTriggerConfig;
|
|
2745
|
+
/**
|
|
2746
|
+
* Trigger metadata - entry points that initiate resource execution
|
|
2747
|
+
*
|
|
2748
|
+
* Triggers represent how executions start: webhooks from external services,
|
|
2749
|
+
* scheduled cron jobs, platform events, or manual user actions.
|
|
2750
|
+
*
|
|
2751
|
+
* BREAKING CHANGES (2025-11-30):
|
|
2752
|
+
* - Now extends ResourceDefinition (inherits: resourceId, name, description, version, type, status, links, category)
|
|
2753
|
+
* - Field renames: `id` -> `resourceId` (inherited), `type` -> `triggerType`
|
|
2754
|
+
* - Relationship rename: `invokes` -> `triggers` (unified vocabulary)
|
|
2755
|
+
* - New required fields: `version` (inherited), `type: 'trigger'` (inherited)
|
|
2756
|
+
* - triggers object now includes `externalResources` option
|
|
2757
|
+
*
|
|
2758
|
+
* @example
|
|
2759
|
+
* // TriggerDefinition - metadata only
|
|
2760
|
+
* {
|
|
2761
|
+
* resourceId: 'trigger-new-order',
|
|
2762
|
+
* type: 'trigger',
|
|
2763
|
+
* triggerType: 'webhook',
|
|
2764
|
+
* name: 'New Order',
|
|
2765
|
+
* description: 'Webhook from Shopify on new orders',
|
|
2766
|
+
* version: '1.0.0',
|
|
2767
|
+
* status: 'prod',
|
|
2768
|
+
* webhookPath: '/webhooks/shopify/orders'
|
|
2769
|
+
* }
|
|
2770
|
+
*
|
|
2771
|
+
* // Relationships declared in ResourceRelationships (not on TriggerDefinition):
|
|
2772
|
+
* // relationships: {
|
|
2773
|
+
* // 'trigger-new-order': { triggers: { workflows: ['order-fulfillment-workflow'] } }
|
|
2774
|
+
* // }
|
|
2775
|
+
*/
|
|
2776
|
+
interface TriggerDefinition extends ResourceDefinition {
|
|
2777
|
+
/** Resource type discriminator (narrowed from base union) */
|
|
2778
|
+
type: 'trigger';
|
|
2779
|
+
/** Trigger mechanism type (renamed from 'type' to avoid collision with base type discriminator) */
|
|
2780
|
+
triggerType: 'webhook' | 'schedule' | 'manual' | 'event';
|
|
2781
|
+
/** Type-specific configuration */
|
|
2782
|
+
config?: TriggerConfig;
|
|
2783
|
+
/** For webhook triggers: path like '/webhooks/shopify/orders' */
|
|
2784
|
+
webhookPath?: string;
|
|
2785
|
+
/** For schedule triggers: cron expression like '0 6 * * *' */
|
|
2786
|
+
schedule?: string;
|
|
2787
|
+
/** For event triggers: event type like 'low-stock-alert' */
|
|
2788
|
+
eventType?: string;
|
|
2789
|
+
}
|
|
2790
|
+
/**
|
|
2791
|
+
* Integration metadata - external service connections
|
|
2792
|
+
*
|
|
2793
|
+
* References credentials table for actual connection. No connection status
|
|
2794
|
+
* stored here (queried at runtime from credentials table).
|
|
2795
|
+
*
|
|
2796
|
+
* BREAKING CHANGES (2025-11-30):
|
|
2797
|
+
* - Now extends ResourceDefinition (inherits: resourceId, name, description, version, type, status, links, category)
|
|
2798
|
+
* - Field renames: `id` -> `resourceId` (inherited)
|
|
2799
|
+
* - New required field: `status` (inherited) - organizations must add status to all integrations
|
|
2800
|
+
* - New required field: `version` (inherited) - organizations must add version to all integrations
|
|
2801
|
+
* - New required field: `type: 'integration'` (inherited) - resource type discriminator
|
|
2802
|
+
*
|
|
2803
|
+
* @example
|
|
2804
|
+
* {
|
|
2805
|
+
* resourceId: 'integration-shopify-prod',
|
|
2806
|
+
* type: 'integration',
|
|
2807
|
+
* provider: 'shopify',
|
|
2808
|
+
* credentialName: 'shopify-prod',
|
|
2809
|
+
* name: 'Shopify Production',
|
|
2810
|
+
* description: 'E-commerce platform',
|
|
2811
|
+
* version: '1.0.0',
|
|
2812
|
+
* status: 'prod'
|
|
2813
|
+
* }
|
|
2814
|
+
*/
|
|
2815
|
+
interface IntegrationDefinition extends ResourceDefinition {
|
|
2816
|
+
/** Resource type discriminator (narrowed from base union) */
|
|
2817
|
+
type: 'integration';
|
|
2818
|
+
/** OM descriptor that owns canonical identity and governance metadata. */
|
|
2819
|
+
resource?: Extract<ResourceEntry, {
|
|
2820
|
+
kind: 'integration';
|
|
2821
|
+
}>;
|
|
2822
|
+
/** Integration provider type */
|
|
2823
|
+
provider: IntegrationType;
|
|
2824
|
+
/** References credentials table (e.g., 'shopify-prod', 'zendesk-api') */
|
|
2825
|
+
credentialName: string;
|
|
2826
|
+
}
|
|
2827
|
+
/**
|
|
2828
|
+
* Explicit resource relationship declaration
|
|
2829
|
+
*
|
|
2830
|
+
* Single-direction only - Command View derives reverse relationships.
|
|
2831
|
+
* Agents/workflows declare what they trigger and use.
|
|
2832
|
+
*
|
|
2833
|
+
* @example
|
|
2834
|
+
* {
|
|
2835
|
+
* triggers: { workflows: ['order-fulfillment-workflow'] },
|
|
2836
|
+
* uses: { integrations: ['integration-shopify-prod', 'integration-postgres'] }
|
|
2837
|
+
* }
|
|
2838
|
+
*/
|
|
2839
|
+
interface RelationshipDeclaration {
|
|
2840
|
+
/** Resources this resource triggers */
|
|
2841
|
+
triggers?: {
|
|
2842
|
+
/** Agent resourceIds this resource triggers */
|
|
2843
|
+
agents?: string[];
|
|
2844
|
+
/** Workflow resourceIds this resource triggers */
|
|
2845
|
+
workflows?: string[];
|
|
2846
|
+
};
|
|
2847
|
+
/** Integrations this resource uses */
|
|
2848
|
+
uses?: {
|
|
2849
|
+
/** Integration IDs this resource uses */
|
|
2850
|
+
integrations?: string[];
|
|
2851
|
+
};
|
|
2852
|
+
}
|
|
2853
|
+
/**
|
|
2854
|
+
* Resource relationships map
|
|
2855
|
+
* Maps resourceId to its relationship declarations
|
|
2856
|
+
*
|
|
2857
|
+
* @example
|
|
2858
|
+
* {
|
|
2859
|
+
* 'order-processor-agent': {
|
|
2860
|
+
* triggers: { workflows: ['order-fulfillment-workflow'] },
|
|
2861
|
+
* uses: { integrations: ['integration-shopify-prod'] }
|
|
2862
|
+
* }
|
|
2863
|
+
* }
|
|
2864
|
+
*/
|
|
2865
|
+
type ResourceRelationships = Record<string, RelationshipDeclaration>;
|
|
2866
|
+
/**
|
|
2867
|
+
* External platform type
|
|
2868
|
+
* Supported third-party automation platforms
|
|
2869
|
+
*/
|
|
2870
|
+
type ExternalPlatform = 'n8n' | 'make' | 'zapier' | 'other';
|
|
2871
|
+
/**
|
|
2872
|
+
* External automation resource metadata
|
|
2873
|
+
*
|
|
2874
|
+
* Represents workflows/automations running on third-party platforms
|
|
2875
|
+
* (n8n, Make, Zapier, etc.) for visualization in Command View.
|
|
2876
|
+
*
|
|
2877
|
+
* NOTE: This is metadata ONLY for visualization. No execution logic,
|
|
2878
|
+
* no API integration with external platforms, no status syncing.
|
|
2879
|
+
*
|
|
2880
|
+
* BREAKING CHANGES (2025-11-30):
|
|
2881
|
+
* - Now extends ResourceDefinition (inherits: resourceId, name, description, version, type, status, links, category)
|
|
2882
|
+
* - Field renames: `id` -> `resourceId` (inherited)
|
|
2883
|
+
* - New required field: `version` (inherited) - organizations must add version to all external resources
|
|
2884
|
+
* - New required field: `type: 'external'` (inherited) - resource type discriminator
|
|
2885
|
+
* - REMOVED FIELD: `triggeredBy` - per relationship-consolidation design, all relationships are forward-only declarations
|
|
2886
|
+
*
|
|
2887
|
+
* @example
|
|
2888
|
+
* {
|
|
2889
|
+
* resourceId: 'external-n8n-order-sync',
|
|
2890
|
+
* type: 'external',
|
|
2891
|
+
* version: '1.0.0',
|
|
2892
|
+
* platform: 'n8n',
|
|
2893
|
+
* name: 'Shopify Order Sync',
|
|
2894
|
+
* description: 'Legacy n8n workflow for syncing Shopify orders',
|
|
2895
|
+
* status: 'prod',
|
|
2896
|
+
* platformUrl: 'https://n8n.client.com/workflow/123',
|
|
2897
|
+
* triggers: { workflows: ['order-fulfillment-workflow'] },
|
|
2898
|
+
* uses: { integrations: ['integration-shopify-prod'] }
|
|
2899
|
+
* }
|
|
2900
|
+
*/
|
|
2901
|
+
interface ExternalResourceDefinition extends ResourceDefinition {
|
|
2902
|
+
/** Resource type discriminator (narrowed from base union) */
|
|
2903
|
+
type: 'external';
|
|
2904
|
+
/** Platform type */
|
|
2905
|
+
platform: ExternalPlatform;
|
|
2906
|
+
/** Link to external platform (e.g., n8n workflow editor URL) */
|
|
2907
|
+
platformUrl?: string;
|
|
2908
|
+
/** Platform's internal ID/reference */
|
|
2909
|
+
externalId?: string;
|
|
2910
|
+
/** What this external resource triggers (external -> internal) */
|
|
2911
|
+
triggers?: {
|
|
2912
|
+
/** Elevasis workflow resourceIds this external automation triggers */
|
|
2913
|
+
workflows?: string[];
|
|
2914
|
+
/** Elevasis agent resourceIds this external automation triggers */
|
|
2915
|
+
agents?: string[];
|
|
2916
|
+
};
|
|
2917
|
+
/** Integrations this external resource uses (shared credentials) */
|
|
2918
|
+
uses?: {
|
|
2919
|
+
/** Integration IDs this external automation uses */
|
|
2920
|
+
integrations?: string[];
|
|
2921
|
+
};
|
|
2922
|
+
}
|
|
2923
|
+
/**
|
|
2924
|
+
* Human Checkpoint definition - human decision points in automation
|
|
2925
|
+
*
|
|
2926
|
+
* Represents where human judgment is deployed in the automation landscape.
|
|
2927
|
+
* Tasks with matching command_queue_group are routed to this checkpoint.
|
|
2928
|
+
*
|
|
2929
|
+
* BREAKING CHANGES (2025-11-30):
|
|
2930
|
+
* - Now extends ResourceDefinition (inherits: resourceId, name, description, version, type, status, links, category)
|
|
2931
|
+
* - Field renames: `id` -> `resourceId` (inherited)
|
|
2932
|
+
* - description is now REQUIRED (was optional) - organizations must add description to all human checkpoints
|
|
2933
|
+
* - New required field: `version` (inherited) - organizations must add version to all human checkpoints
|
|
2934
|
+
* - New required field: `type: 'human'` (inherited) - resource type discriminator
|
|
2935
|
+
*
|
|
2936
|
+
* @example
|
|
2937
|
+
* {
|
|
2938
|
+
* resourceId: 'sales-approval',
|
|
2939
|
+
* type: 'human',
|
|
2940
|
+
* name: 'Sales Approval Queue',
|
|
2941
|
+
* description: 'High-value order approvals for sales team',
|
|
2942
|
+
* version: '1.0.0',
|
|
2943
|
+
* status: 'prod',
|
|
2944
|
+
* requestedBy: { agents: ['order-processor-agent'] },
|
|
2945
|
+
* routesTo: { agents: ['order-fulfillment-agent'] }
|
|
2946
|
+
* }
|
|
2947
|
+
*/
|
|
2948
|
+
interface HumanCheckpointDefinition extends ResourceDefinition {
|
|
2949
|
+
/** Resource type discriminator (narrowed from base union) */
|
|
2950
|
+
type: 'human';
|
|
2951
|
+
/** Resources that create tasks for this checkpoint */
|
|
2952
|
+
requestedBy?: {
|
|
2953
|
+
/** Agent resourceIds that request approval here */
|
|
2954
|
+
agents?: string[];
|
|
2955
|
+
/** Workflow resourceIds that request approval here */
|
|
2956
|
+
workflows?: string[];
|
|
2957
|
+
};
|
|
2958
|
+
/** Resources that receive approved decisions */
|
|
2959
|
+
routesTo?: {
|
|
2960
|
+
/** Agent resourceIds that handle approved tasks */
|
|
2961
|
+
agents?: string[];
|
|
2962
|
+
/** Workflow resourceIds that handle approved tasks */
|
|
2963
|
+
workflows?: string[];
|
|
2964
|
+
};
|
|
2965
|
+
}
|
|
2966
2966
|
|
|
2967
2967
|
declare const ResourceCategorySchema: z.ZodEnum<{
|
|
2968
2968
|
diagnostic: "diagnostic";
|
|
@@ -3089,670 +3089,7 @@ declare const IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
|
3089
3089
|
provider: z.string().trim().min(1).max(100)
|
|
3090
3090
|
})
|
|
3091
3091
|
|
|
3092
|
-
declare const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine(
|
|
3093
|
-
// Collect ALL system entries recursively — top-level systems plus any nested subsystems.
|
|
3094
|
-
// Wave 2 canonical OM authors nested subsystems (e.g. sys → subsystems → 'lead-gen' with id
|
|
3095
|
-
// 'sys.lead-gen'). Resource systemPath cross-refs must resolve against the full flattened set.
|
|
3096
|
-
type SystemWithPath = { path: string; schemaPath: Array<string | number>; system: SystemEntry }
|
|
3097
|
-
|
|
3098
|
-
function collectAllSystems(
|
|
3099
|
-
systems: Record<string, SystemEntry>,
|
|
3100
|
-
prefix = '',
|
|
3101
|
-
schemaPath: Array<string | number> = ['systems']
|
|
3102
|
-
): SystemWithPath[] {
|
|
3103
|
-
const result: SystemWithPath[] = []
|
|
3104
|
-
for (const [key, system] of Object.entries(systems)) {
|
|
3105
|
-
const path = prefix ? `${prefix}.${key}` : key
|
|
3106
|
-
const currentSchemaPath = [...schemaPath, key]
|
|
3107
|
-
result.push({ path, schemaPath: currentSchemaPath, system })
|
|
3108
|
-
const childSystems = system.systems ?? system.subsystems
|
|
3109
|
-
if (childSystems !== undefined) {
|
|
3110
|
-
result.push(
|
|
3111
|
-
...collectAllSystems(childSystems, path, [
|
|
3112
|
-
...currentSchemaPath,
|
|
3113
|
-
system.systems !== undefined ? 'systems' : 'subsystems'
|
|
3114
|
-
])
|
|
3115
|
-
)
|
|
3116
|
-
}
|
|
3117
|
-
}
|
|
3118
|
-
return result
|
|
3119
|
-
}
|
|
3120
|
-
|
|
3121
|
-
const allSystems = collectAllSystems(model.systems)
|
|
3122
|
-
const systemsById = new Map<string, SystemEntry>()
|
|
3123
|
-
for (const { path, system } of allSystems) {
|
|
3124
|
-
systemsById.set(path, system)
|
|
3125
|
-
systemsById.set(system.id, system)
|
|
3126
|
-
}
|
|
3127
|
-
|
|
3128
|
-
const systemIdsByEffectivePath = new Map<string, string>()
|
|
3129
|
-
allSystems.forEach(({ path, schemaPath, system }) => {
|
|
3130
|
-
if (system.parentSystemId !== undefined && !systemsById.has(system.parentSystemId)) {
|
|
3131
|
-
addIssue(
|
|
3132
|
-
ctx,
|
|
3133
|
-
[...schemaPath, 'parentSystemId'],
|
|
3134
|
-
`System "${system.id}" references unknown parent "${system.parentSystemId}"`
|
|
3135
|
-
)
|
|
3136
|
-
}
|
|
3137
|
-
|
|
3138
|
-
const hasChildren =
|
|
3139
|
-
Object.keys(system.systems ?? system.subsystems ?? {}).length > 0 ||
|
|
3140
|
-
allSystems.some(
|
|
3141
|
-
(candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes('.')
|
|
3142
|
-
)
|
|
3143
|
-
const contributesRoutePath = system.ui?.path !== undefined || system.path !== undefined || !hasChildren
|
|
3144
|
-
if (contributesRoutePath) {
|
|
3145
|
-
const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path)
|
|
3146
|
-
const existingSystemId = systemIdsByEffectivePath.get(effectivePath)
|
|
3147
|
-
if (existingSystemId !== undefined) {
|
|
3148
|
-
addIssue(
|
|
3149
|
-
ctx,
|
|
3150
|
-
[...schemaPath, system.ui?.path !== undefined ? 'ui' : 'path'],
|
|
3151
|
-
`System "${path}" effective path "${effectivePath}" duplicates system "${existingSystemId}"`
|
|
3152
|
-
)
|
|
3153
|
-
} else {
|
|
3154
|
-
systemIdsByEffectivePath.set(effectivePath, path)
|
|
3155
|
-
}
|
|
3156
|
-
}
|
|
3157
|
-
|
|
3158
|
-
if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
|
|
3159
|
-
const hasEnabledDescendant =
|
|
3160
|
-
Object.values(system.systems ?? system.subsystems ?? {}).some((candidate) =>
|
|
3161
|
-
isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
|
|
3162
|
-
) ||
|
|
3163
|
-
allSystems.some(
|
|
3164
|
-
(candidate) =>
|
|
3165
|
-
candidate.path.startsWith(`${path}.`) &&
|
|
3166
|
-
!candidate.path.slice(path.length + 1).includes('.') &&
|
|
3167
|
-
isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
|
|
3168
|
-
)
|
|
3169
|
-
if (!hasEnabledDescendant) {
|
|
3170
|
-
addIssue(ctx, [...schemaPath, 'lifecycle'], `System "${path}" is active but has no active descendants`)
|
|
3171
|
-
}
|
|
3172
|
-
}
|
|
3173
|
-
})
|
|
3174
|
-
|
|
3175
|
-
allSystems.forEach(({ schemaPath, system }) => {
|
|
3176
|
-
const visited = new Set<string>()
|
|
3177
|
-
let currentParentId = system.parentSystemId
|
|
3178
|
-
|
|
3179
|
-
while (currentParentId !== undefined) {
|
|
3180
|
-
if (currentParentId === system.id || visited.has(currentParentId)) {
|
|
3181
|
-
addIssue(ctx, [...schemaPath, 'parentSystemId'], `System "${system.id}" has a parent cycle`)
|
|
3182
|
-
return
|
|
3183
|
-
}
|
|
3184
|
-
|
|
3185
|
-
visited.add(currentParentId)
|
|
3186
|
-
currentParentId = systemsById.get(currentParentId)?.parentSystemId
|
|
3187
|
-
}
|
|
3188
|
-
})
|
|
3189
|
-
|
|
3190
|
-
type CollectedSidebarSurface = {
|
|
3191
|
-
id: string
|
|
3192
|
-
node: Extract<SidebarNode, { type: 'surface' }>
|
|
3193
|
-
path: Array<string | number>
|
|
3194
|
-
}
|
|
3195
|
-
|
|
3196
|
-
function normalizeRoutePath(path: string): string {
|
|
3197
|
-
return path.length > 1 ? path.replace(/\/+$/, '') : path
|
|
3198
|
-
}
|
|
3199
|
-
|
|
3200
|
-
const sidebarNodeIds = new Map<string, Array<string | number>>()
|
|
3201
|
-
const sidebarSurfacePaths = new Map<string, string>()
|
|
3202
|
-
const sidebarSurfaces: CollectedSidebarSurface[] = []
|
|
3203
|
-
|
|
3204
|
-
function collectSidebarNodes(nodes: Record<string, SidebarNode>, schemaPath: Array<string | number>): void {
|
|
3205
|
-
Object.entries(nodes).forEach(([nodeId, node]) => {
|
|
3206
|
-
const nodePath = [...schemaPath, nodeId]
|
|
3207
|
-
const existingNodePath = sidebarNodeIds.get(nodeId)
|
|
3208
|
-
if (existingNodePath !== undefined) {
|
|
3209
|
-
addIssue(ctx, nodePath, `Sidebar node id "${nodeId}" duplicates another sidebar node`)
|
|
3210
|
-
} else {
|
|
3211
|
-
sidebarNodeIds.set(nodeId, nodePath)
|
|
3212
|
-
}
|
|
3213
|
-
|
|
3214
|
-
if (node.type === 'group') {
|
|
3215
|
-
collectSidebarNodes(node.children, [...nodePath, 'children'])
|
|
3216
|
-
return
|
|
3217
|
-
}
|
|
3218
|
-
|
|
3219
|
-
sidebarSurfaces.push({ id: nodeId, node, path: nodePath })
|
|
3220
|
-
const normalizedPath = normalizeRoutePath(node.path)
|
|
3221
|
-
const existingSurfaceId = sidebarSurfacePaths.get(normalizedPath)
|
|
3222
|
-
if (existingSurfaceId !== undefined) {
|
|
3223
|
-
addIssue(
|
|
3224
|
-
ctx,
|
|
3225
|
-
[...nodePath, 'path'],
|
|
3226
|
-
`Sidebar surface path "${node.path}" duplicates surface "${existingSurfaceId}"`
|
|
3227
|
-
)
|
|
3228
|
-
} else {
|
|
3229
|
-
sidebarSurfacePaths.set(normalizedPath, nodeId)
|
|
3230
|
-
}
|
|
3231
|
-
|
|
3232
|
-
node.targets?.systems?.forEach((systemId, systemIndex) => {
|
|
3233
|
-
if (!systemsById.has(systemId)) {
|
|
3234
|
-
addIssue(
|
|
3235
|
-
ctx,
|
|
3236
|
-
[...nodePath, 'targets', 'systems', systemIndex],
|
|
3237
|
-
`Sidebar surface "${nodeId}" references unknown system "${systemId}"`
|
|
3238
|
-
)
|
|
3239
|
-
}
|
|
3240
|
-
})
|
|
3241
|
-
})
|
|
3242
|
-
}
|
|
3243
|
-
|
|
3244
|
-
collectSidebarNodes(model.navigation.sidebar.primary, ['navigation', 'sidebar', 'primary'])
|
|
3245
|
-
collectSidebarNodes(model.navigation.sidebar.bottom, ['navigation', 'sidebar', 'bottom'])
|
|
3246
|
-
|
|
3247
|
-
// Offerings -> CustomerSegment cross-ref: targetSegmentIds must resolve
|
|
3248
|
-
const segmentsById = new Map(Object.entries(model.customers))
|
|
3249
|
-
Object.values(model.offerings).forEach((product) => {
|
|
3250
|
-
product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
|
|
3251
|
-
if (!segmentsById.has(segmentId)) {
|
|
3252
|
-
addIssue(
|
|
3253
|
-
ctx,
|
|
3254
|
-
['offerings', product.id, 'targetSegmentIds', segmentIndex],
|
|
3255
|
-
`Product "${product.id}" references unknown customer segment "${segmentId}"`
|
|
3256
|
-
)
|
|
3257
|
-
}
|
|
3258
|
-
})
|
|
3259
|
-
|
|
3260
|
-
// Offerings -> System cross-ref: deliveryFeatureId must resolve (when present)
|
|
3261
|
-
if (product.deliveryFeatureId !== undefined && !systemsById.has(product.deliveryFeatureId)) {
|
|
3262
|
-
addIssue(
|
|
3263
|
-
ctx,
|
|
3264
|
-
['offerings', product.id, 'deliveryFeatureId'],
|
|
3265
|
-
`Product "${product.id}" references unknown delivery system "${product.deliveryFeatureId}"`
|
|
3266
|
-
)
|
|
3267
|
-
}
|
|
3268
|
-
})
|
|
3269
|
-
|
|
3270
|
-
// Goals -> period-range validation: periodEnd must be strictly after periodStart
|
|
3271
|
-
Object.values(model.goals).forEach((objective) => {
|
|
3272
|
-
if (objective.periodEnd <= objective.periodStart) {
|
|
3273
|
-
addIssue(
|
|
3274
|
-
ctx,
|
|
3275
|
-
['goals', objective.id, 'periodEnd'],
|
|
3276
|
-
`Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
|
|
3277
|
-
)
|
|
3278
|
-
}
|
|
3279
|
-
})
|
|
3280
|
-
|
|
3281
|
-
const goalsById = new Map(Object.entries(model.goals))
|
|
3282
|
-
// Phase 4: knowledge is now a flat Record<id, OrgKnowledgeNode> — no .nodes array
|
|
3283
|
-
const knowledgeById = new Map(Object.entries(model.knowledge))
|
|
3284
|
-
const actionsById = new Map(Object.entries(model.actions))
|
|
3285
|
-
const entitiesById = new Map(Object.entries(model.entities))
|
|
3286
|
-
const policiesById = new Map(Object.entries(model.policies))
|
|
3287
|
-
|
|
3288
|
-
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
3289
|
-
node.targets?.entities?.forEach((entityId, entityIndex) => {
|
|
3290
|
-
if (!entitiesById.has(entityId)) {
|
|
3291
|
-
addIssue(
|
|
3292
|
-
ctx,
|
|
3293
|
-
[...path, 'targets', 'entities', entityIndex],
|
|
3294
|
-
`Sidebar surface "${id}" references unknown entity "${entityId}"`
|
|
3295
|
-
)
|
|
3296
|
-
}
|
|
3297
|
-
})
|
|
3298
|
-
|
|
3299
|
-
node.targets?.actions?.forEach((actionId, actionIndex) => {
|
|
3300
|
-
if (!actionsById.has(actionId)) {
|
|
3301
|
-
addIssue(
|
|
3302
|
-
ctx,
|
|
3303
|
-
[...path, 'targets', 'actions', actionIndex],
|
|
3304
|
-
`Sidebar surface "${id}" references unknown action "${actionId}"`
|
|
3305
|
-
)
|
|
3306
|
-
}
|
|
3307
|
-
})
|
|
3308
|
-
})
|
|
3309
|
-
|
|
3310
|
-
Object.values(model.entities).forEach((entity) => {
|
|
3311
|
-
if (!systemsById.has(entity.ownedBySystemId)) {
|
|
3312
|
-
addIssue(
|
|
3313
|
-
ctx,
|
|
3314
|
-
['entities', entity.id, 'ownedBySystemId'],
|
|
3315
|
-
`Entity "${entity.id}" references unknown ownedBySystemId "${entity.ownedBySystemId}"`
|
|
3316
|
-
)
|
|
3317
|
-
}
|
|
3318
|
-
|
|
3319
|
-
entity.links?.forEach((link, linkIndex) => {
|
|
3320
|
-
if (!entitiesById.has(link.toEntity)) {
|
|
3321
|
-
addIssue(
|
|
3322
|
-
ctx,
|
|
3323
|
-
['entities', entity.id, 'links', linkIndex, 'toEntity'],
|
|
3324
|
-
`Entity "${entity.id}" links to unknown entity "${link.toEntity}"`
|
|
3325
|
-
)
|
|
3326
|
-
}
|
|
3327
|
-
})
|
|
3328
|
-
})
|
|
3329
|
-
|
|
3330
|
-
// Roles -> reportsToId cross-ref: each reportsToId must resolve to another role in the same collection
|
|
3331
|
-
const rolesById = new Map(Object.entries(model.roles))
|
|
3332
|
-
Object.values(model.roles).forEach((role) => {
|
|
3333
|
-
if (role.reportsToId !== undefined && !rolesById.has(role.reportsToId)) {
|
|
3334
|
-
addIssue(
|
|
3335
|
-
ctx,
|
|
3336
|
-
['roles', role.id, 'reportsToId'],
|
|
3337
|
-
`Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
|
|
3338
|
-
)
|
|
3339
|
-
}
|
|
3340
|
-
})
|
|
3341
|
-
|
|
3342
|
-
Object.values(model.roles).forEach((role) => {
|
|
3343
|
-
const visited = new Set<string>()
|
|
3344
|
-
let currentReportsToId = role.reportsToId
|
|
3345
|
-
|
|
3346
|
-
while (currentReportsToId !== undefined) {
|
|
3347
|
-
if (currentReportsToId === role.id || visited.has(currentReportsToId)) {
|
|
3348
|
-
addIssue(ctx, ['roles', role.id, 'reportsToId'], `Role "${role.id}" has a reportsToId cycle`)
|
|
3349
|
-
return
|
|
3350
|
-
}
|
|
3351
|
-
|
|
3352
|
-
visited.add(currentReportsToId)
|
|
3353
|
-
currentReportsToId = rolesById.get(currentReportsToId)?.reportsToId
|
|
3354
|
-
}
|
|
3355
|
-
})
|
|
3356
|
-
|
|
3357
|
-
Object.values(model.roles).forEach((role) => {
|
|
3358
|
-
role.responsibleFor?.forEach((systemId, systemIndex) => {
|
|
3359
|
-
if (!systemsById.has(systemId)) {
|
|
3360
|
-
addIssue(
|
|
3361
|
-
ctx,
|
|
3362
|
-
['roles', role.id, 'responsibleFor', systemIndex],
|
|
3363
|
-
`Role "${role.id}" references unknown responsibleFor system "${systemId}"`
|
|
3364
|
-
)
|
|
3365
|
-
}
|
|
3366
|
-
})
|
|
3367
|
-
})
|
|
3368
|
-
|
|
3369
|
-
allSystems.forEach(({ schemaPath, system }) => {
|
|
3370
|
-
if (system.responsibleRoleId !== undefined && !rolesById.has(system.responsibleRoleId)) {
|
|
3371
|
-
addIssue(
|
|
3372
|
-
ctx,
|
|
3373
|
-
[...schemaPath, 'responsibleRoleId'],
|
|
3374
|
-
`System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
|
|
3375
|
-
)
|
|
3376
|
-
}
|
|
3377
|
-
|
|
3378
|
-
system.governedByKnowledge?.forEach((nodeId, nodeIndex) => {
|
|
3379
|
-
if (!knowledgeById.has(nodeId)) {
|
|
3380
|
-
addIssue(
|
|
3381
|
-
ctx,
|
|
3382
|
-
[...schemaPath, 'governedByKnowledge', nodeIndex],
|
|
3383
|
-
`System "${system.id}" references unknown knowledge node "${nodeId}"`
|
|
3384
|
-
)
|
|
3385
|
-
}
|
|
3386
|
-
})
|
|
3387
|
-
|
|
3388
|
-
system.drivesGoals?.forEach((goalId, goalIndex) => {
|
|
3389
|
-
if (!goalsById.has(goalId)) {
|
|
3390
|
-
addIssue(
|
|
3391
|
-
ctx,
|
|
3392
|
-
[...schemaPath, 'drivesGoals', goalIndex],
|
|
3393
|
-
`System "${system.id}" references unknown goal "${goalId}"`
|
|
3394
|
-
)
|
|
3395
|
-
}
|
|
3396
|
-
})
|
|
3397
|
-
|
|
3398
|
-
system.actions?.forEach((actionRef, actionIndex) => {
|
|
3399
|
-
if (!actionsById.has(actionRef.actionId)) {
|
|
3400
|
-
addIssue(
|
|
3401
|
-
ctx,
|
|
3402
|
-
[...schemaPath, 'actions', actionIndex, 'actionId'],
|
|
3403
|
-
`System "${system.id}" references unknown action "${actionRef.actionId}"`
|
|
3404
|
-
)
|
|
3405
|
-
}
|
|
3406
|
-
})
|
|
3407
|
-
|
|
3408
|
-
system.policies?.forEach((policyId, policyIndex) => {
|
|
3409
|
-
if (!policiesById.has(policyId)) {
|
|
3410
|
-
addIssue(
|
|
3411
|
-
ctx,
|
|
3412
|
-
[...schemaPath, 'policies', policyIndex],
|
|
3413
|
-
`System "${system.id}" references unknown policy "${policyId}"`
|
|
3414
|
-
)
|
|
3415
|
-
}
|
|
3416
|
-
})
|
|
3417
|
-
})
|
|
3418
|
-
|
|
3419
|
-
Object.values(model.actions).forEach((action) => {
|
|
3420
|
-
action.affects?.forEach((entityId, entityIndex) => {
|
|
3421
|
-
if (!entitiesById.has(entityId)) {
|
|
3422
|
-
addIssue(
|
|
3423
|
-
ctx,
|
|
3424
|
-
['actions', action.id, 'affects', entityIndex],
|
|
3425
|
-
`Action "${action.id}" affects unknown entity "${entityId}"`
|
|
3426
|
-
)
|
|
3427
|
-
}
|
|
3428
|
-
})
|
|
3429
|
-
})
|
|
3430
|
-
|
|
3431
|
-
// Phase 4: sales / prospecting / projects compound-domain entity cross-ref checks removed.
|
|
3432
|
-
// Those entity bindings now live in System.ontology catalog scopes.
|
|
3433
|
-
|
|
3434
|
-
const resourcesById = new Map(Object.entries(model.resources))
|
|
3435
|
-
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
3436
|
-
node.targets?.resources?.forEach((resourceId, resourceIndex) => {
|
|
3437
|
-
if (!resourcesById.has(resourceId)) {
|
|
3438
|
-
addIssue(
|
|
3439
|
-
ctx,
|
|
3440
|
-
[...path, 'targets', 'resources', resourceIndex],
|
|
3441
|
-
`Sidebar surface "${id}" references unknown resource "${resourceId}"`
|
|
3442
|
-
)
|
|
3443
|
-
}
|
|
3444
|
-
})
|
|
3445
|
-
})
|
|
3446
|
-
const actionIds = new Set(Object.keys(model.actions))
|
|
3447
|
-
const offeringsById = new Map(Object.entries(model.offerings))
|
|
3448
|
-
const ontologyCompilation = compileOrganizationOntology(model)
|
|
3449
|
-
const stageIds = new Set<string>()
|
|
3450
|
-
for (const catalog of Object.values(ontologyCompilation.ontology.catalogTypes)) {
|
|
3451
|
-
if (catalog.kind !== 'stage') continue
|
|
3452
|
-
for (const stageId of Object.keys(catalog.entries ?? {})) {
|
|
3453
|
-
stageIds.add(stageId)
|
|
3454
|
-
}
|
|
3455
|
-
}
|
|
3456
|
-
const ontologyIndexByKind = {
|
|
3457
|
-
object: ontologyCompilation.ontology.objectTypes,
|
|
3458
|
-
link: ontologyCompilation.ontology.linkTypes,
|
|
3459
|
-
action: ontologyCompilation.ontology.actionTypes,
|
|
3460
|
-
catalog: ontologyCompilation.ontology.catalogTypes,
|
|
3461
|
-
event: ontologyCompilation.ontology.eventTypes,
|
|
3462
|
-
interface: ontologyCompilation.ontology.interfaceTypes,
|
|
3463
|
-
'value-type': ontologyCompilation.ontology.valueTypes,
|
|
3464
|
-
property: ontologyCompilation.ontology.sharedProperties,
|
|
3465
|
-
group: ontologyCompilation.ontology.groups,
|
|
3466
|
-
surface: ontologyCompilation.ontology.surfaces
|
|
3467
|
-
} satisfies Record<OntologyKind, Record<string, unknown>>
|
|
3468
|
-
const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)))
|
|
3469
|
-
|
|
3470
|
-
function topologyTargetExists(ref: OmTopologyNodeRef): boolean {
|
|
3471
|
-
if (ref.kind === 'system') return systemsById.has(ref.id)
|
|
3472
|
-
if (ref.kind === 'resource') return resourcesById.has(ref.id)
|
|
3473
|
-
if (ref.kind === 'ontology') return ontologyIds.has(ref.id)
|
|
3474
|
-
if (ref.kind === 'policy') return policiesById.has(ref.id)
|
|
3475
|
-
if (ref.kind === 'role') return rolesById.has(ref.id)
|
|
3476
|
-
|
|
3477
|
-
// Trigger, human checkpoint, and external resource refs are projected
|
|
3478
|
-
// topology nodes during the bridge period; their owning runtime indexes are
|
|
3479
|
-
// validated by deployment projection in later waves.
|
|
3480
|
-
return true
|
|
3481
|
-
}
|
|
3482
|
-
|
|
3483
|
-
Object.entries(model.topology.relationships).forEach(([relationshipId, relationship]) => {
|
|
3484
|
-
;(['from', 'to'] as const).forEach((side) => {
|
|
3485
|
-
const ref = relationship[side]
|
|
3486
|
-
if (topologyTargetExists(ref)) return
|
|
3487
|
-
|
|
3488
|
-
addIssue(
|
|
3489
|
-
ctx,
|
|
3490
|
-
['topology', 'relationships', relationshipId, side],
|
|
3491
|
-
`Topology relationship "${relationshipId}" ${side} references unknown ${ref.kind} "${ref.id}"`
|
|
3492
|
-
)
|
|
3493
|
-
})
|
|
3494
|
-
})
|
|
3495
|
-
|
|
3496
|
-
const ontologyReferenceKeyKinds = {
|
|
3497
|
-
valueType: 'value-type',
|
|
3498
|
-
catalogType: 'catalog',
|
|
3499
|
-
objectType: 'object',
|
|
3500
|
-
eventType: 'event',
|
|
3501
|
-
actionType: 'action',
|
|
3502
|
-
linkType: 'link',
|
|
3503
|
-
interfaceType: 'interface',
|
|
3504
|
-
propertyType: 'property',
|
|
3505
|
-
groupType: 'group',
|
|
3506
|
-
surfaceType: 'surface',
|
|
3507
|
-
stepCatalog: 'catalog'
|
|
3508
|
-
} satisfies Record<string, OntologyKind>
|
|
3509
|
-
|
|
3510
|
-
function validateKnownOntologyReferences(
|
|
3511
|
-
ownerId: string,
|
|
3512
|
-
value: unknown,
|
|
3513
|
-
path: Array<string | number>,
|
|
3514
|
-
seen = new WeakSet<object>()
|
|
3515
|
-
): void {
|
|
3516
|
-
if (Array.isArray(value)) {
|
|
3517
|
-
value.forEach((entry, index) => validateKnownOntologyReferences(ownerId, entry, [...path, index], seen))
|
|
3518
|
-
return
|
|
3519
|
-
}
|
|
3520
|
-
|
|
3521
|
-
if (!isRecord(value)) return
|
|
3522
|
-
if (seen.has(value)) return
|
|
3523
|
-
seen.add(value)
|
|
3524
|
-
|
|
3525
|
-
Object.entries(value).forEach(([key, entry]) => {
|
|
3526
|
-
const expectedKind = ontologyReferenceKeyKinds[key as keyof typeof ontologyReferenceKeyKinds]
|
|
3527
|
-
if (expectedKind !== undefined) {
|
|
3528
|
-
if (typeof entry !== 'string') {
|
|
3529
|
-
addIssue(ctx, [...path, key], `Ontology record "${ownerId}" ${key} must be an ontology ID string`)
|
|
3530
|
-
} else if (ontologyIndexByKind[expectedKind][entry] === undefined) {
|
|
3531
|
-
addIssue(
|
|
3532
|
-
ctx,
|
|
3533
|
-
[...path, key],
|
|
3534
|
-
`Ontology record "${ownerId}" ${key} references unknown ${expectedKind} ontology ID "${entry}"`
|
|
3535
|
-
)
|
|
3536
|
-
}
|
|
3537
|
-
}
|
|
3538
|
-
|
|
3539
|
-
validateKnownOntologyReferences(ownerId, entry, [...path, key], seen)
|
|
3540
|
-
})
|
|
3541
|
-
}
|
|
3542
|
-
|
|
3543
|
-
for (const { id, record } of listResolvedOntologyRecords(ontologyCompilation.ontology)) {
|
|
3544
|
-
validateKnownOntologyReferences(id, record, record.origin.path)
|
|
3545
|
-
}
|
|
3546
|
-
|
|
3547
|
-
Object.values(model.policies).forEach((policy) => {
|
|
3548
|
-
policy.appliesTo.systemIds.forEach((systemId, systemIndex) => {
|
|
3549
|
-
if (!systemsById.has(systemId)) {
|
|
3550
|
-
addIssue(
|
|
3551
|
-
ctx,
|
|
3552
|
-
['policies', policy.id, 'appliesTo', 'systemIds', systemIndex],
|
|
3553
|
-
`Policy "${policy.id}" applies to unknown system "${systemId}"`
|
|
3554
|
-
)
|
|
3555
|
-
}
|
|
3556
|
-
})
|
|
3557
|
-
|
|
3558
|
-
policy.appliesTo.actionIds.forEach((actionId, actionIndex) => {
|
|
3559
|
-
if (!actionsById.has(actionId)) {
|
|
3560
|
-
addIssue(
|
|
3561
|
-
ctx,
|
|
3562
|
-
['policies', policy.id, 'appliesTo', 'actionIds', actionIndex],
|
|
3563
|
-
`Policy "${policy.id}" applies to unknown action "${actionId}"`
|
|
3564
|
-
)
|
|
3565
|
-
}
|
|
3566
|
-
})
|
|
3567
|
-
|
|
3568
|
-
policy.actions.forEach((action, actionIndex) => {
|
|
3569
|
-
if (action.kind === 'invoke-action' && !actionsById.has(action.actionId)) {
|
|
3570
|
-
addIssue(
|
|
3571
|
-
ctx,
|
|
3572
|
-
['policies', policy.id, 'actions', actionIndex, 'actionId'],
|
|
3573
|
-
`Policy "${policy.id}" invokes unknown action "${action.actionId}"`
|
|
3574
|
-
)
|
|
3575
|
-
}
|
|
3576
|
-
if (
|
|
3577
|
-
(action.kind === 'notify-role' || action.kind === 'require-approval') &&
|
|
3578
|
-
action.roleId !== undefined &&
|
|
3579
|
-
!rolesById.has(action.roleId)
|
|
3580
|
-
) {
|
|
3581
|
-
addIssue(
|
|
3582
|
-
ctx,
|
|
3583
|
-
['policies', policy.id, 'actions', actionIndex, 'roleId'],
|
|
3584
|
-
`Policy "${policy.id}" references unknown role "${action.roleId}"`
|
|
3585
|
-
)
|
|
3586
|
-
}
|
|
3587
|
-
})
|
|
3588
|
-
|
|
3589
|
-
if (policy.trigger.kind === 'action-invocation' && !actionsById.has(policy.trigger.actionId)) {
|
|
3590
|
-
addIssue(
|
|
3591
|
-
ctx,
|
|
3592
|
-
['policies', policy.id, 'trigger', 'actionId'],
|
|
3593
|
-
`Policy "${policy.id}" references unknown trigger action "${policy.trigger.actionId}"`
|
|
3594
|
-
)
|
|
3595
|
-
}
|
|
3596
|
-
})
|
|
3597
|
-
|
|
3598
|
-
function knowledgeTargetExists(kind: string, id: string): boolean {
|
|
3599
|
-
if (kind === 'system') return systemsById.has(id)
|
|
3600
|
-
if (kind === 'resource') return resourcesById.has(id)
|
|
3601
|
-
if (kind === 'knowledge') return knowledgeById.has(id)
|
|
3602
|
-
if (kind === 'stage') return stageIds.has(id)
|
|
3603
|
-
if (kind === 'action') return actionIds.has(id)
|
|
3604
|
-
if (kind === 'role') return rolesById.has(id)
|
|
3605
|
-
if (kind === 'goal') return goalsById.has(id)
|
|
3606
|
-
if (kind === 'customer-segment') return segmentsById.has(id)
|
|
3607
|
-
if (kind === 'offering') return offeringsById.has(id)
|
|
3608
|
-
if (kind === 'ontology') return ontologyIds.has(id)
|
|
3609
|
-
return false
|
|
3610
|
-
}
|
|
3611
|
-
|
|
3612
|
-
// Phase 4: model.knowledge is now Record<id, OrgKnowledgeNode> — iterate Object.values
|
|
3613
|
-
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
3614
|
-
node.links.forEach((link, linkIndex) => {
|
|
3615
|
-
if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
|
|
3616
|
-
addIssue(
|
|
3617
|
-
ctx,
|
|
3618
|
-
['knowledge', nodeId, 'links', linkIndex, 'target'],
|
|
3619
|
-
`Knowledge node "${node.id}" references unknown ${link.target.kind} target "${link.target.id}"`
|
|
3620
|
-
)
|
|
3621
|
-
}
|
|
3622
|
-
|
|
3623
|
-
if (!isKnowledgeKindCompatibleWithTarget(node.kind, link.target.kind)) {
|
|
3624
|
-
addIssue(
|
|
3625
|
-
ctx,
|
|
3626
|
-
['knowledge', nodeId, 'links', linkIndex, 'target', 'kind'],
|
|
3627
|
-
`Knowledge node "${node.id}" kind "${node.kind}" cannot govern ${link.target.kind} targets`
|
|
3628
|
-
)
|
|
3629
|
-
}
|
|
3630
|
-
|
|
3631
|
-
// `governedByKnowledge` is validated one-way on target nodes above. Knowledge
|
|
3632
|
-
// links may be authored first and remain valid as forward references.
|
|
3633
|
-
})
|
|
3634
|
-
})
|
|
3635
|
-
|
|
3636
|
-
Object.values(model.resources).forEach((resource) => {
|
|
3637
|
-
if (!systemsById.has(resource.systemPath)) {
|
|
3638
|
-
addIssue(
|
|
3639
|
-
ctx,
|
|
3640
|
-
['resources', resource.id, 'systemPath'],
|
|
3641
|
-
`Resource "${resource.id}" references unknown system path "${resource.systemPath}"`
|
|
3642
|
-
)
|
|
3643
|
-
}
|
|
3644
|
-
|
|
3645
|
-
if (resource.ownerRoleId !== undefined && !rolesById.has(resource.ownerRoleId)) {
|
|
3646
|
-
addIssue(
|
|
3647
|
-
ctx,
|
|
3648
|
-
['resources', resource.id, 'ownerRoleId'],
|
|
3649
|
-
`Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
|
|
3650
|
-
)
|
|
3651
|
-
}
|
|
3652
|
-
|
|
3653
|
-
if (resource.kind === 'agent' && resource.actsAsRoleId !== undefined && !rolesById.has(resource.actsAsRoleId)) {
|
|
3654
|
-
addIssue(
|
|
3655
|
-
ctx,
|
|
3656
|
-
['resources', resource.id, 'actsAsRoleId'],
|
|
3657
|
-
`Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
|
|
3658
|
-
)
|
|
3659
|
-
}
|
|
3660
|
-
})
|
|
3661
|
-
|
|
3662
|
-
function validateResourceOntologyBinding(
|
|
3663
|
-
resourceId: string,
|
|
3664
|
-
bindingKey: 'actions' | 'primaryAction' | 'reads' | 'writes' | 'usesCatalogs' | 'emits',
|
|
3665
|
-
expectedKind: OntologyKind,
|
|
3666
|
-
ids: string[] | string | undefined
|
|
3667
|
-
): void {
|
|
3668
|
-
const ontologyIds = ids === undefined ? [] : Array.isArray(ids) ? ids : [ids]
|
|
3669
|
-
|
|
3670
|
-
ontologyIds.forEach((ontologyId, ontologyIndex) => {
|
|
3671
|
-
if (ontologyIndexByKind[expectedKind][ontologyId] === undefined) {
|
|
3672
|
-
addIssue(
|
|
3673
|
-
ctx,
|
|
3674
|
-
['resources', resourceId, 'ontology', bindingKey, ...(Array.isArray(ids) ? [ontologyIndex] : [])],
|
|
3675
|
-
`Resource "${resourceId}" ontology binding "${bindingKey}" references unknown ${expectedKind} ontology ID "${ontologyId}"`
|
|
3676
|
-
)
|
|
3677
|
-
}
|
|
3678
|
-
})
|
|
3679
|
-
}
|
|
3680
|
-
|
|
3681
|
-
Object.values(model.resources).forEach((resource) => {
|
|
3682
|
-
const binding = resource.ontology
|
|
3683
|
-
if (binding === undefined) return
|
|
3684
|
-
|
|
3685
|
-
validateResourceOntologyBinding(resource.id, 'actions', 'action', binding.actions)
|
|
3686
|
-
validateResourceOntologyBinding(resource.id, 'primaryAction', 'action', binding.primaryAction)
|
|
3687
|
-
validateResourceOntologyBinding(resource.id, 'reads', 'object', binding.reads)
|
|
3688
|
-
validateResourceOntologyBinding(resource.id, 'writes', 'object', binding.writes)
|
|
3689
|
-
validateResourceOntologyBinding(resource.id, 'usesCatalogs', 'catalog', binding.usesCatalogs)
|
|
3690
|
-
validateResourceOntologyBinding(resource.id, 'emits', 'event', binding.emits)
|
|
3691
|
-
|
|
3692
|
-
// Tier-1: validate contract ref SHAPE only — no module resolution (browser-safe).
|
|
3693
|
-
// Tier-2 intra-package resolution runs in om:verify (packages/cli/src/knowledge/verify.ts).
|
|
3694
|
-
if (binding.contract !== undefined) {
|
|
3695
|
-
const contractEntries = [
|
|
3696
|
-
['input', binding.contract.input],
|
|
3697
|
-
['output', binding.contract.output]
|
|
3698
|
-
] as const
|
|
3699
|
-
for (const [side, ref] of contractEntries) {
|
|
3700
|
-
if (ref === undefined) continue
|
|
3701
|
-
const result = ContractRefSchema.safeParse(ref)
|
|
3702
|
-
if (!result.success) {
|
|
3703
|
-
addIssue(
|
|
3704
|
-
ctx,
|
|
3705
|
-
['resources', resource.id, 'ontology', 'contract', side],
|
|
3706
|
-
`Resource "${resource.id}" contract.${side} "${ref}" is not a valid ContractRef (expected "package/subpath#ExportName")`
|
|
3707
|
-
)
|
|
3708
|
-
}
|
|
3709
|
-
}
|
|
3710
|
-
}
|
|
3711
|
-
})
|
|
3712
|
-
|
|
3713
|
-
Object.values(model.roles).forEach((role) => {
|
|
3714
|
-
if (role.heldBy === undefined) return
|
|
3715
|
-
|
|
3716
|
-
asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
|
|
3717
|
-
if (holder.kind !== 'agent') return
|
|
3718
|
-
|
|
3719
|
-
const resource = resourcesById.get(holder.agentId)
|
|
3720
|
-
if (resource === undefined) {
|
|
3721
|
-
addIssue(
|
|
3722
|
-
ctx,
|
|
3723
|
-
['roles', role.id, 'heldBy', Array.isArray(role.heldBy) ? holderIndex : 'agentId'],
|
|
3724
|
-
`Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
|
|
3725
|
-
)
|
|
3726
|
-
return
|
|
3727
|
-
}
|
|
3728
|
-
|
|
3729
|
-
if (resource.kind !== 'agent') {
|
|
3730
|
-
addIssue(
|
|
3731
|
-
ctx,
|
|
3732
|
-
['roles', role.id, 'heldBy', Array.isArray(role.heldBy) ? holderIndex : 'agentId'],
|
|
3733
|
-
`Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
|
|
3734
|
-
)
|
|
3735
|
-
}
|
|
3736
|
-
})
|
|
3737
|
-
})
|
|
3738
|
-
|
|
3739
|
-
// Phase 4: model.knowledge is now Record<id, OrgKnowledgeNode>
|
|
3740
|
-
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
3741
|
-
node.ownerIds.forEach((roleId, ownerIndex) => {
|
|
3742
|
-
if (!rolesById.has(roleId)) {
|
|
3743
|
-
addIssue(
|
|
3744
|
-
ctx,
|
|
3745
|
-
['knowledge', nodeId, 'ownerIds', ownerIndex],
|
|
3746
|
-
`Knowledge node "${node.id}" references unknown owner role "${roleId}"`
|
|
3747
|
-
)
|
|
3748
|
-
}
|
|
3749
|
-
})
|
|
3750
|
-
})
|
|
3751
|
-
|
|
3752
|
-
for (const diagnostic of ontologyCompilation.diagnostics) {
|
|
3753
|
-
addIssue(ctx, diagnostic.path, diagnostic.message)
|
|
3754
|
-
}
|
|
3755
|
-
})
|
|
3092
|
+
declare const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine(refineOrganizationModel)
|
|
3756
3093
|
|
|
3757
3094
|
type OrganizationModel = z.infer<typeof OrganizationModelSchema>
|
|
3758
3095
|
type OrganizationModelResourceOntologyBinding = z.infer<typeof ResourceOntologyBindingSchema>
|