eidolon-ai-runtime-host-contract 0.0.0-stage → 0.3.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.
Files changed (42) hide show
  1. package/package.json +20 -4
  2. package/src/ActorManagement.ts +22 -0
  3. package/src/AgentAdapters.ts +171 -0
  4. package/src/AgentAdaptersWire.ts +61 -0
  5. package/src/Attachment.ts +15 -0
  6. package/src/Command.ts +110 -0
  7. package/src/ContentRead.ts +20 -0
  8. package/src/Conversation.ts +18 -0
  9. package/src/Daemon.ts +63 -0
  10. package/src/Effects.ts +61 -0
  11. package/src/ExecutionEnvironment.ts +28 -0
  12. package/src/GlobalTaskSpace.ts +116 -0
  13. package/src/Goal.ts +29 -0
  14. package/src/HostInteractions.ts +190 -0
  15. package/src/HostPort.ts +144 -0
  16. package/src/Observation.ts +128 -0
  17. package/src/Organization.ts +14 -0
  18. package/src/Participant.ts +93 -0
  19. package/src/Schedule.ts +79 -0
  20. package/src/Schema.ts +598 -0
  21. package/src/SessionImport.ts +38 -0
  22. package/src/SessionManagement.ts +23 -0
  23. package/src/SessionProject.ts +9 -0
  24. package/src/Statistics.ts +24 -0
  25. package/src/Workflow.ts +207 -0
  26. package/src/WorkflowAuthoring.ts +76 -0
  27. package/src/WorkflowConversationOwner.ts +164 -0
  28. package/src/WorkflowExecutionCatalog.ts +48 -0
  29. package/src/WorkflowHumanReview.ts +26 -0
  30. package/src/WorkflowHumanReviewSchema.ts +90 -0
  31. package/src/WorkflowLaunch.ts +47 -0
  32. package/src/WorkflowLaunchMaterials.ts +43 -0
  33. package/src/WorkflowLaunchMaterialsSchema.ts +166 -0
  34. package/src/WorkflowLaunchParameters.ts +63 -0
  35. package/src/WorkflowLaunchReview.ts +90 -0
  36. package/src/WorkflowLaunchSchema.ts +181 -0
  37. package/src/WorkflowPresentation.ts +67 -0
  38. package/src/WorkflowSchema.ts +199 -0
  39. package/src/WorkflowSessionCall.ts +47 -0
  40. package/src/WorkflowTaskTree.ts +46 -0
  41. package/src/index.ts +89 -0
  42. package/README.md +0 -3
package/package.json CHANGED
@@ -1,6 +1,22 @@
1
1
  {
2
2
  "name": "eidolon-ai-runtime-host-contract",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.3.0",
4
+ "type": "module",
5
+ "main": "./src/index.ts",
6
+ "types": "./src/index.ts",
7
+ "exports": {
8
+ ".": "./src/index.ts"
9
+ },
10
+ "files": [
11
+ "src"
12
+ ],
13
+ "description": "Serializable runtime host protocol and injected effects shared by local and remote shells.",
14
+ "dependencies": {
15
+ "holarchy-eidolon-adapter": "0.2.2"
16
+ },
17
+ "publishConfig": {
18
+ "access": "public",
19
+ "registry": "https://registry.npmjs.com/"
20
+ },
21
+ "private": false
22
+ }
@@ -0,0 +1,22 @@
1
+ /** Original Actor lifecycle, distinct from closing a browser pane or deleting files. */
2
+ export type ActorLifecycle = Readonly<{
3
+ state: 'active' | 'archived' | 'tombstoned';
4
+ revision: number;
5
+ changedAt?: number;
6
+ }>;
7
+ export type ActorManagementCommand = Readonly<{
8
+ commandId: string;
9
+ kind: 'archive_actor' | 'delete_actor';
10
+ expectedServerInstanceId: string;
11
+ expectedEpoch: string;
12
+ expectedLifecycleRevision: number;
13
+ }>;
14
+ /** Principal-scoped durable proof; a historical receipt does not overwrite the current lifecycle. */
15
+ export type ActorManagementResult = Readonly<{
16
+ sessionId: string;
17
+ actorId: string;
18
+ commandId: string;
19
+ kind: ActorManagementCommand['kind'];
20
+ submittedEpoch: string;
21
+ lifecycle: Readonly<{state: 'archived' | 'tombstoned'; revision: number; changedAt: number}>;
22
+ }>;
@@ -0,0 +1,171 @@
1
+ import type { ExecutionEnvironmentRef, ExecutionEnvironmentContext } from './ExecutionEnvironment';
2
+ import type { HostRequest } from './HostPort';
3
+ import type { ParticipantContextCut } from './Participant';
4
+ /** Original external runtimes keep their own handles; these are never Native TaskSpace IDs. */
5
+ export type AgentAdapterKind = 'codex' | 'claude' | 'grok';
6
+ export type AgentAdapterSourceRef = Readonly<{
7
+ kind: 'agent-adapter';
8
+ daemonId: string;
9
+ adapterId: string;
10
+ revision: number;
11
+ }>;
12
+ export type AgentAdapterConfiguration = Readonly<{
13
+ provider: AgentAdapterKind;
14
+ name: string;
15
+ model: string;
16
+ environment: ExecutionEnvironmentRef;
17
+ enabled: boolean;
18
+ }>;
19
+ export type AgentAdapterRegistration = Readonly<{
20
+ source: AgentAdapterSourceRef;
21
+ configuration: AgentAdapterConfiguration;
22
+ }>;
23
+ export type AgentAdapterCapabilities = Readonly<{
24
+ submit: boolean;
25
+ interrupt: boolean;
26
+ observeOriginal: boolean;
27
+ nativeTaskSpace: false;
28
+ nativeActorHistory: false;
29
+ attachments: false;
30
+ artifacts: false;
31
+ tools: 'chat-only' | 'read-only';
32
+ context: 'retained' | 'explicit-cut';
33
+ }>;
34
+ export type AgentAdapterView = AgentAdapterRegistration & Readonly<{
35
+ canSubmit: boolean;
36
+ unavailableReason?: string;
37
+ installedVersion?: string;
38
+ access: 'unverified' | 'observed';
39
+ capabilities: AgentAdapterCapabilities;
40
+ }>;
41
+ export type AgentAdapterDirectory = Readonly<{
42
+ daemonId: string;
43
+ adapters: readonly AgentAdapterView[];
44
+ }>;
45
+ export type AgentExecutionHandle = Readonly<{
46
+ kind: 'agent-execution';
47
+ source: AgentAdapterSourceRef;
48
+ provider: AgentAdapterKind;
49
+ sessionId: string;
50
+ turnId?: string;
51
+ }>;
52
+ export type AgentExecutionState = 'queued' | 'sending' | 'running' | 'completed' | 'failed' | 'cancelled' | 'unknown';
53
+ export type AgentAdapterSendCommand = Readonly<{
54
+ source: AgentAdapterSourceRef;
55
+ bindingKey: string;
56
+ commandId: string;
57
+ text: string;
58
+ contextCut: ParticipantContextCut;
59
+ }>;
60
+ export type AgentExecutionSnapshot = Readonly<{
61
+ source: AgentAdapterSourceRef;
62
+ bindingKey: string;
63
+ commandId: string;
64
+ fingerprint: string;
65
+ revision: number;
66
+ state: AgentExecutionState;
67
+ handle?: AgentExecutionHandle;
68
+ result?: string;
69
+ errorCode?: string;
70
+ canInterrupt: boolean;
71
+ }>;
72
+ export type AgentAdapterConfigureCommand = Readonly<{
73
+ commandId: string;
74
+ adapterId: string;
75
+ expectedRevision: number;
76
+ configuration: AgentAdapterConfiguration;
77
+ }>;
78
+ export type AgentAdapterConfigureReceipt = Readonly<{
79
+ commandId: string;
80
+ adapterId: string;
81
+ revision: number;
82
+ fingerprint: string;
83
+ }>;
84
+ export type AgentAdapterSelector = Readonly<{
85
+ source: AgentAdapterSourceRef;
86
+ bindingKey: string;
87
+ commandId: string;
88
+ }>;
89
+ export type AgentAdapterInterruptCommand = AgentAdapterSelector & Readonly<{
90
+ controlId: string;
91
+ expectedRevision: number;
92
+ }>;
93
+ export type AgentDriverEvent = Readonly<{
94
+ kind: 'session';
95
+ sessionId: string;
96
+ }> | Readonly<{
97
+ kind: 'handle';
98
+ handle: AgentExecutionHandle;
99
+ }> | Readonly<{
100
+ kind: 'sending';
101
+ }> | Readonly<{
102
+ kind: 'running';
103
+ }>;
104
+ export type AgentDriverResult = Readonly<{
105
+ state: 'completed';
106
+ handle: AgentExecutionHandle;
107
+ text: string;
108
+ }> | Readonly<{
109
+ state: 'failed' | 'cancelled' | 'unknown';
110
+ handle?: AgentExecutionHandle;
111
+ errorCode: string;
112
+ }>;
113
+ export type AgentDriverInput = Readonly<{
114
+ command: AgentAdapterSendCommand;
115
+ configuration: AgentAdapterConfiguration;
116
+ environment: ExecutionEnvironmentContext;
117
+ sessionId?: string;
118
+ }>;
119
+ export type AgentDriver = Readonly<{
120
+ probe(provider: AgentAdapterKind): Promise<Readonly<{
121
+ installed: boolean;
122
+ version?: string;
123
+ capabilities: AgentAdapterCapabilities;
124
+ }>>;
125
+ start(input: AgentDriverInput, onEvent: (event: AgentDriverEvent) => Promise<void>): Readonly<{
126
+ result: Promise<AgentDriverResult>;
127
+ interrupt(): Promise<void>;
128
+ close(): Promise<void>;
129
+ }>;
130
+ }>;
131
+ export type AgentAdapterHost = Readonly<{
132
+ directory(request: HostRequest): Promise<AgentAdapterDirectory>;
133
+ configure(request: HostRequest, command: AgentAdapterConfigureCommand): Promise<AgentAdapterConfigureReceipt>;
134
+ configurationResult(request: HostRequest, commandId: string): Promise<AgentAdapterConfigureReceipt>;
135
+ send(request: HostRequest, command: AgentAdapterSendCommand): Promise<AgentExecutionSnapshot>;
136
+ observe(request: HostRequest, selector: AgentAdapterSelector): Promise<AgentExecutionSnapshot>;
137
+ interrupt(request: HostRequest, command: AgentAdapterInterruptCommand): Promise<AgentExecutionSnapshot>;
138
+ busy(workspaceKey: string): boolean;
139
+ close(): Promise<void>;
140
+ }>;
141
+ export type AgentAdapterBinding = Readonly<{
142
+ source: AgentAdapterSourceRef;
143
+ bindingKey: string;
144
+ sessionId?: string;
145
+ }>;
146
+ export type AgentAdapterExecutionRecord = Readonly<{
147
+ command: AgentAdapterSendCommand;
148
+ configuration: AgentAdapterConfiguration;
149
+ snapshot: AgentExecutionSnapshot;
150
+ }>;
151
+ export type AgentAdapterState = Readonly<{
152
+ version: 1;
153
+ revision: number;
154
+ registrations: readonly AgentAdapterRegistration[];
155
+ receipts: readonly AgentAdapterConfigureReceipt[];
156
+ bindings: readonly AgentAdapterBinding[];
157
+ executions: readonly AgentAdapterExecutionRecord[];
158
+ controls: readonly Readonly<{
159
+ controlId: string;
160
+ fingerprint: string;
161
+ source: AgentAdapterSourceRef;
162
+ bindingKey: string;
163
+ commandId: string;
164
+ state: 'sending' | 'accepted' | 'unknown';
165
+ }>[];
166
+ }>;
167
+ export type AgentAdapterStore = Readonly<{
168
+ read(): AgentAdapterState;
169
+ commit(expectedRevision: number, state: AgentAdapterState): void;
170
+ close(): void;
171
+ }>;
@@ -0,0 +1,61 @@
1
+ import type { AgentAdapterConfigureCommand, AgentAdapterConfigureReceipt, AgentAdapterDirectory, AgentAdapterSourceRef, AgentAdapterSendCommand, AgentAdapterSelector, AgentAdapterInterruptCommand, AgentExecutionHandle, AgentExecutionSnapshot, AgentAdapterConfiguration } from './AgentAdapters';
2
+ import { parseExecutionEnvironmentRef, parseHostParticipantSendCommand, WireSchemaError } from './Schema';
3
+ function object(value: unknown, keys: readonly string[]): Record<string, any> { if (!value || typeof value !== 'object' || Array.isArray(value) || Object.keys(value).some(k => !keys.includes(k)))
4
+ throw new WireSchemaError('agent_adapter'); return value as Record<string, any>; }
5
+ function text(value: unknown, max = 256): asserts value is string { if (typeof value !== 'string' || !value || value.length > max)
6
+ throw new WireSchemaError('agent_adapter_text'); }
7
+ function id(value: unknown): asserts value is string { text(value, 128); if (!/^[A-Za-z0-9_-]+$/.test(value))
8
+ throw new WireSchemaError('agent_adapter_id'); }
9
+ function integer(value: unknown, min = 0): asserts value is number { if (!Number.isSafeInteger(value) || (value as number) < min)
10
+ throw new WireSchemaError('agent_adapter_revision'); }
11
+ function flag(value: unknown): asserts value is boolean { if (typeof value !== 'boolean')
12
+ throw new WireSchemaError('agent_adapter_flag'); }
13
+ function provider(value: unknown) { if (!['codex', 'claude', 'grok'].includes(String(value)))
14
+ throw new WireSchemaError('agent_adapter_provider'); }
15
+ export function parseAgentAdapterSourceRef(value: unknown): AgentAdapterSourceRef { const v = object(value, ['kind', 'daemonId', 'adapterId', 'revision']); if (v.kind !== 'agent-adapter')
16
+ throw new WireSchemaError('agent_adapter_source'); id(v.daemonId); id(v.adapterId); integer(v.revision, 1); return value as AgentAdapterSourceRef; }
17
+ export function parseAgentAdapterConfiguration(value: unknown): AgentAdapterConfiguration { const v = object(value, ['provider', 'name', 'model', 'environment', 'enabled']); provider(v.provider); text(v.name, 120); text(v.model); if (!/^[A-Za-z0-9][A-Za-z0-9_.:/-]*$/.test(v.model))
18
+ throw new WireSchemaError('agent_adapter_model'); parseExecutionEnvironmentRef(v.environment); flag(v.enabled); return value as AgentAdapterConfiguration; }
19
+ export function parseAgentAdapterConfigureCommand(value: unknown): AgentAdapterConfigureCommand { const v = object(value, ['commandId', 'adapterId', 'expectedRevision', 'configuration']); id(v.commandId); id(v.adapterId); integer(v.expectedRevision); parseAgentAdapterConfiguration(v.configuration); return value as AgentAdapterConfigureCommand; }
20
+ export function parseAgentAdapterConfigureReceipt(value: unknown): AgentAdapterConfigureReceipt { const v = object(value, ['commandId', 'adapterId', 'revision', 'fingerprint']); id(v.commandId); id(v.adapterId); integer(v.revision, 1); text(v.fingerprint); return value as AgentAdapterConfigureReceipt; }
21
+ export function parseAgentAdapterSelector(value: unknown): AgentAdapterSelector { const v = object(value, ['source', 'bindingKey', 'commandId']); parseAgentAdapterSourceRef(v.source); text(v.bindingKey); id(v.commandId); return value as AgentAdapterSelector; }
22
+ export function parseAgentAdapterInterruptCommand(value: unknown): AgentAdapterInterruptCommand { const v = object(value, ['source', 'bindingKey', 'commandId', 'controlId', 'expectedRevision']); parseAgentAdapterSelector({ source: v.source, bindingKey: v.bindingKey, commandId: v.commandId }); id(v.controlId); integer(v.expectedRevision, 1); return value as AgentAdapterInterruptCommand; }
23
+ export function parseAgentAdapterSendCommand(value: unknown): AgentAdapterSendCommand { const v = object(value, ['source', 'bindingKey', 'commandId', 'text', 'contextCut']); parseAgentAdapterSourceRef(v.source); text(v.bindingKey); id(v.commandId); text(v.text, 65536); parseHostParticipantSendCommand({ bindingKey: v.bindingKey, commandId: v.commandId, text: v.text, contextCut: v.contextCut, recipient: { kind: 'member', ref: 'adapter-wire-validation', ownerScopeRef: 'adapter-wire-validation', bindingRef: 'validation', bindingDigest: 'validation', admissionRef: 'validation' } }); return value as AgentAdapterSendCommand; }
24
+ export function parseAgentExecutionHandle(value: unknown): AgentExecutionHandle { const v = object(value, ['kind', 'source', 'provider', 'sessionId', 'turnId']); if (v.kind !== 'agent-execution')
25
+ throw new WireSchemaError('agent_execution_handle'); parseAgentAdapterSourceRef(v.source); provider(v.provider); text(v.sessionId); if (v.turnId !== undefined)
26
+ text(v.turnId); if (v.provider === 'codex' && !v.turnId)
27
+ throw new WireSchemaError('agent_execution_turn'); return value as AgentExecutionHandle; }
28
+ export function parseAgentExecutionSnapshot(value: unknown): AgentExecutionSnapshot { const v = object(value, ['source', 'bindingKey', 'commandId', 'fingerprint', 'revision', 'state', 'handle', 'result', 'errorCode', 'canInterrupt']); parseAgentAdapterSelector({ source: v.source, bindingKey: v.bindingKey, commandId: v.commandId }); text(v.fingerprint); integer(v.revision, 1); flag(v.canInterrupt); if (!['queued', 'sending', 'running', 'completed', 'failed', 'cancelled', 'unknown'].includes(v.state))
29
+ throw new WireSchemaError('agent_execution_state'); if (v.handle !== undefined) {
30
+ const handle = parseAgentExecutionHandle(v.handle);
31
+ if (['kind', 'daemonId', 'adapterId', 'revision'].some(k => (handle.source as any)[k] !== v.source[k]))
32
+ throw new WireSchemaError('agent_execution_source');
33
+ } if (v.state === 'completed' && (!v.handle || typeof v.result !== 'string'))
34
+ throw new WireSchemaError('agent_execution_result'); if (v.result !== undefined && (v.state !== 'completed' || typeof v.result !== 'string' || new TextEncoder().encode(v.result).byteLength > 8 * 1024 * 1024))
35
+ throw new WireSchemaError('agent_execution_result'); if (v.errorCode !== undefined)
36
+ text(v.errorCode); return value as AgentExecutionSnapshot; }
37
+ export function parseAgentAdapterDirectory(value: unknown): AgentAdapterDirectory { const v = object(value, ['daemonId', 'adapters']); id(v.daemonId); if (!Array.isArray(v.adapters) || v.adapters.length > 128)
38
+ throw new WireSchemaError('agent_adapter_directory'); for (const row of v.adapters) {
39
+ const a = object(row, ['source', 'configuration', 'canSubmit', 'unavailableReason', 'installedVersion', 'access', 'capabilities']);
40
+ const ref = parseAgentAdapterSourceRef(a.source);
41
+ if (ref.daemonId !== v.daemonId)
42
+ throw new WireSchemaError('agent_adapter_source');
43
+ parseAgentAdapterConfiguration(a.configuration);
44
+ flag(a.canSubmit);
45
+ if (a.unavailableReason !== undefined)
46
+ text(a.unavailableReason);
47
+ if (a.installedVersion !== undefined)
48
+ text(a.installedVersion, 512);
49
+ if (!['unverified', 'observed'].includes(a.access))
50
+ throw new WireSchemaError('agent_adapter_access');
51
+ const c = object(a.capabilities, ['submit', 'interrupt', 'observeOriginal', 'nativeTaskSpace', 'nativeActorHistory', 'attachments', 'artifacts', 'tools', 'context']);
52
+ for (const key of ['submit', 'interrupt', 'observeOriginal'])
53
+ flag(c[key]);
54
+ for (const key of ['nativeTaskSpace', 'nativeActorHistory', 'attachments', 'artifacts'])
55
+ if (c[key] !== false)
56
+ throw new WireSchemaError('agent_adapter_capability');
57
+ if (!['retained', 'explicit-cut'].includes(c.context))
58
+ throw new WireSchemaError('agent_adapter_context');
59
+ if (!['chat-only', 'read-only'].includes(c.tools))
60
+ throw new WireSchemaError('agent_adapter_tools');
61
+ } return value as AgentAdapterDirectory; }
@@ -0,0 +1,15 @@
1
+ export type AttachmentMime = "text/plain" | "image/png" | "image/jpeg" | "image/webp"
2
+ export type HostInputPart = Readonly<
3
+ | { type: "text"; text: string; filename?: string }
4
+ | { type: "image"; mime: Exclude<AttachmentMime, "text/plain">; dataUrl: string; filename?: string }
5
+ | { type: "attachment"; attachmentId: string }
6
+ >
7
+ export type AttachmentOperation = Readonly<
8
+ | { kind: "begin"; expectedEpoch: string; uploadId: string; filename: string; mime: AttachmentMime; totalBytes: number; digest: string }
9
+ | { kind: "append"; expectedEpoch: string; attachmentId: string; offsetBytes: number; data: string }
10
+ | { kind: "release"; expectedEpoch: string; attachmentId: string }
11
+ >
12
+ export type AttachmentSummary = Readonly<{
13
+ attachmentId: string; epoch: string; state: "uploading" | "ready" | "released" | "expired" | "failed"
14
+ filename: string; mime: AttachmentMime; uploadedBytes: number; totalBytes: number; expiresAt: number; digest?: string
15
+ }>
package/src/Command.ts ADDED
@@ -0,0 +1,110 @@
1
+ import type { HostInputPart } from "./Attachment"
2
+ import type { ConversationOperation } from "./Conversation"
3
+ import type { GoalControl, GoalControlReceipt, SessionGoalView } from "./Goal"
4
+ export type ActorAction = "host_interaction" | "observe" | "read_history" | "send_text" | "cancel_turn" | "answer_question" | "set_model" | "compact" | "send_input" | "upload_attachment" | "set_work_mode" | "fork_conversation" | "rewind_conversation" | "set_goal" | "continue_goal" | "archive_actor" | "delete_actor"
5
+ export type ActorExecutionKind = "primary" | "interactive" | "delegate" | "detached"
6
+ export type TurnState = "queued" | "running" | "waiting_input" | "succeeded" | "failed" | "cancelled" | "interrupted"
7
+
8
+ export type ProtocolError = Readonly<{
9
+ code: string
10
+ requestId: string
11
+ retryable: boolean
12
+ message?: string
13
+ currentEpoch?: string
14
+ state?: "unknown"
15
+ }>
16
+
17
+ export type CommandPayloads = {
18
+ host_interaction: { actorId: string; operationJson: string }
19
+ send_text: { actorId: string; text: string }
20
+ send_input: { actorId: string; parts: readonly HostInputPart[] }
21
+ cancel_turn: { actorId: string; turnId: string }
22
+ answer_question: { actorId: string; turnId: string; questionnaireId: string; responseText: string }
23
+ create_actor: { profileId: string; displayName?: string; modelRef?: string }
24
+ set_model: { actorId: string; modelRef: string }
25
+ compact: { actorId: string; expectedHistoryRevision: string }
26
+ set_work_mode: { actorId: string; workMode: "build" | "plan" }
27
+ set_goal: GoalControl
28
+ continue_goal: { actorId: string; goalId: string }
29
+ fork_conversation: { actorId: string; expectedHistoryRevision: string; selector: { kind: "current_head" } | { kind: "through_committed_message"; messageId: string } }
30
+ rewind_conversation: { actorId: string; expectedHistoryRevision: string; selector: { kind: "through_committed_message"; messageId: string } }
31
+ }
32
+
33
+ export type CommandEnvelope = {
34
+ [K in keyof CommandPayloads]: Readonly<{
35
+ commandId: string
36
+ surfaceId: string
37
+ expectedEpoch: string
38
+ kind: K
39
+ payload: Readonly<CommandPayloads[K]>
40
+ }>
41
+ }[keyof CommandPayloads]
42
+
43
+ export type AssociatedTurn = Readonly<{
44
+ actorId: string
45
+ turnId: string
46
+ state: TurnState
47
+ canCancel: boolean
48
+ pendingQuestionIds: readonly string[]
49
+ source?: "goal"
50
+ goalId?: string
51
+ }>
52
+
53
+ export type CommandReceipt = Readonly<{
54
+ commandId: string
55
+ epoch: string
56
+ status: "accepted"
57
+ turnId?: string
58
+ acceptedAt: string
59
+ }>
60
+
61
+ export type CommandStatus = Readonly<{
62
+ commandId: string
63
+ epoch: string
64
+ turnId?: string
65
+ state: "accepted" | "applied" | "rejected" | "unknown"
66
+ associatedTurn?: AssociatedTurn
67
+ result?: { actorId?: string; compact?: Readonly<{ compacted: boolean; tokensBefore: number; messagesAfter: number; historyRevision: string }>; workMode?: "build" | "plan"; conversation?: ConversationOperation; goal?: GoalControlReceipt }
68
+ error?: ProtocolError
69
+ }>
70
+
71
+ export type ExistingControl = Readonly<{
72
+ status: "existing_control"
73
+ epoch: string
74
+ requestedCommandId: string
75
+ existingControlId: string
76
+ actorId: string
77
+ turnId: string
78
+ questionnaireId?: string
79
+ }>
80
+
81
+ export type AlreadyTerminal = Readonly<{
82
+ status: "already_terminal"
83
+ epoch: string
84
+ requestedCommandId: string
85
+ associatedTurn: AssociatedTurn
86
+ }>
87
+
88
+ export type CommandAdmission = CommandReceipt | ExistingControl | AlreadyTerminal
89
+
90
+ export type ActorSummary = Readonly<{
91
+ actorId: string
92
+ lifecycle?: import('./ActorManagement').ActorLifecycle
93
+ /** Stable identity within this session, only for fixed foreground actors. */
94
+ memberId?: string
95
+ displayName: string
96
+ executionKind: ActorExecutionKind
97
+ runtimeState: "idle" | "running" | "waiting_input" | "stopped" | "failed"
98
+ allowedActions: readonly ActorAction[]
99
+ capabilities: Readonly<{ textInput: boolean; cancelTurn: boolean; questionnaireAnswer: boolean }>
100
+ disabledReasons?: Readonly<Record<string, string>>
101
+ modelRef?: string
102
+ workContext?: Readonly<{ workMode: "build" | "plan"; taskPhase: "normal" | "answer"; workModeUpdatedAt: string; taskPhaseUpdatedAt: string }>
103
+ threadGoal?: SessionGoalView
104
+ }>
105
+
106
+ export type CreateSessionCommand = Readonly<{
107
+ commandId: string
108
+ profileId: string
109
+ expectedServerInstanceId: string
110
+ }>
@@ -0,0 +1,20 @@
1
+ import type { MessagePreview } from "./Observation"
2
+
3
+ export type HistoryPage = Readonly<{
4
+ actorId: string
5
+ epoch: string
6
+ historyRevision: string
7
+ messages: readonly MessagePreview[]
8
+ nextCursor?: string
9
+ }>
10
+
11
+ export type MessageContentChunk = Readonly<{
12
+ codec: "public-message-json-v1"
13
+ encoding: "base64"
14
+ messageId: string
15
+ historyRevision: string
16
+ offsetBytes: number
17
+ totalBytes: number
18
+ data: string
19
+ nextCursor?: string
20
+ }>
@@ -0,0 +1,18 @@
1
+ /** Public publication facts, separate from execution replay and private proof. */
2
+ export type ConversationOperationResult =
3
+ | Readonly<{ kind: "fork"; targetSessionId: string; targetActorId: string; cutoffMessageId?: string; transactionId: string }>
4
+ | Readonly<{ kind: "rewind"; retainedMessageCount: number; removedMessageCount: number; cutoffMessageId: string; historyRevision: string; transactionId: string }>
5
+
6
+ export type ConversationOperation = Readonly<{
7
+ operationId: string
8
+ sessionId: string
9
+ actorId: string
10
+ commandId: string
11
+ epoch: string
12
+ submittedEpoch: string
13
+ kind: "fork" | "rewind"
14
+ state: "pending" | "unknown" | "applied" | "rejected"
15
+ result?: ConversationOperationResult
16
+ errorCode?: string
17
+ }>
18
+ export type ConversationOperationList = Readonly<{ epoch: string; operations: readonly ConversationOperation[] }>
package/src/Daemon.ts ADDED
@@ -0,0 +1,63 @@
1
+ import type { HostCapabilities, RuntimeHostPort } from './HostPort'
2
+ import type { ResourceEffectKind } from './Effects'
3
+ import type {HostRequest} from './HostPort'
4
+ import type {WorkflowTaskTreeRelayIntent,WorkflowTaskTreeTrustedContext,WorkflowTaskTreeOwnerCall} from './WorkflowTaskTree'
5
+
6
+ export type WorkspaceRegistration = Readonly<{
7
+ workspaceKey: string; workspaceId: string; workDir: string; revision: number; placement: 'workspace' | 'independent'
8
+ }>
9
+ export type DaemonCapabilities = Readonly<{
10
+ protocolVersion: '1'; mode: 'daemon'; daemonId: string; daemonInstanceId: string
11
+ globalWorkspaceKey: string; limits: { workspaces: number; workers: number; requests: number; subscriptions: number; sessionsPerWorkspace: number }
12
+ }>
13
+ export type WorkspaceView = WorkspaceRegistration & Readonly<{
14
+ state: 'registered' | 'opening' | 'ready' | 'closing' | 'failed'; serverInstanceId?: string; error?: string
15
+ }>
16
+ export const hostOperations = ['organizationWorkbench','organizationDirectory','previewOrganization','commandOrganization','organizationResult','hostInteractions','executionEnvironmentBusy','workflowDefinitions','workflowRuns','workflowRun','workflowEvents','commandWorkflow','workflowCommandResult','workflowMaterial','globalTaskCreateResult','globalTaskRootPlan','globalTaskDetail','globalTaskArtifact','globalTaskSpaces','globalTaskSpace','commandGlobalTaskSpace','globalTaskSpaceResult','participantDirectory', 'openParticipant', 'submitExecution', 'executionOutputPage', 'participantWork','controlParticipant','executionArtifact','participantAttachment', 'sessions', 'createSession', 'sessionMetadata', 'manageSession', 'sessionManagementResult',
17
+ 'workflowMaterialFiles', 'workflowLaunchMaterials', 'workflowLaunch','workflowLaunchParameters','workflowAuthoring','workflowHumanReview','workflowSessionCall','workflowExecutionCatalog','workflowConversationOwner',
18
+ 'actors', 'statistics', 'conversationOperations', 'conversationOperation', 'command', 'attachment',
19
+ 'commandStatus', 'history', 'content', 'subscribe', 'isBusy'] as const
20
+ export type HostOperation = typeof hostOperations[number]
21
+ export type WorkerConfig = Readonly<{
22
+ workspace: WorkspaceRegistration; globalRoot: string; principalId: string; grantsVersion: string
23
+ globalAuthority?: Readonly<{daemonId:string;globalWorkspaceKey:string}>;
24
+ daemonAuthority?: Readonly<{daemonId:string;globalWorkspaceKey:string}>;
25
+ taskTreeEnabled?:boolean;
26
+ executionEnvironmentsEnabled?:boolean;
27
+ sessionLimit?: number
28
+ runtimeConfig?: { adapter?: string; model?: string; mcp?: boolean; metadata?: Record<string,unknown>; captureProviderRequests?: boolean; approvalMode?: 'default' | 'full-auto' | 'dangerous' }
29
+ }>
30
+ export type WorkerRequest =
31
+ | { kind: 'init'; config: WorkerConfig }
32
+ | { kind: 'call'; id: string; operation: HostOperation; args: unknown[] }
33
+ | { kind: 'pull' | 'unsubscribe'; id: string; subscriptionId: string }
34
+ | { kind: 'close'; id: string }
35
+ | { kind: 'prepare-close'; id: string }
36
+ | { kind: 'lease-result'; id: string; leaseId?: string; error?: string }
37
+ | { kind:'tasktree-owner-call';id:string;request:HostRequest;context:WorkflowTaskTreeTrustedContext;intent:WorkflowTaskTreeRelayIntent }
38
+ | { kind:'tasktree-relay-result';id:string;value?:unknown;error?:{status:number;code:string;state?:string} }
39
+ | {kind:'execution-environment-result';id:string;value?:import('./ExecutionEnvironment').ExecutionEnvironmentContext;error?:{status:number;code:string}}
40
+ export type WorkerReply =
41
+ | { kind: 'ready'; capabilities: HostCapabilities }
42
+ | { kind: 'result'; id: string; value?: unknown; error?: { status: number; code: string; currentEpoch?: string; state?: string } }
43
+ | { kind: 'lease'; id: string; effect: ResourceEffectKind; targets?: readonly string[];workflowTaskTree?:import('./WorkflowTaskTree').WorkflowTaskTreeOrigin;executionEnvironment?:import('./ExecutionEnvironment').ExecutionEnvironmentRef;workflowMaterialRead?:import('./Effects').WorkflowMaterialReadOrigin;authorizationRead?:import('./Effects').HostAuthorizationReadOrigin }
44
+ | { kind: 'lease-cancel'; id: string }
45
+ | { kind: 'release' | 'invalidate'; leaseId: string }
46
+ | { kind:'tasktree-relay';id:string;request:HostRequest;intent:WorkflowTaskTreeRelayIntent }
47
+ | {kind:'execution-environment-resolve';id:string;request:HostRequest;ref:import('./ExecutionEnvironment').ExecutionEnvironmentRef;action:'read'|'execute'}
48
+ export type WorkspaceWorker = Readonly<{
49
+ port: RuntimeHostPort; capabilities: HostCapabilities; exited: Promise<unknown>; close(force?: boolean): Promise<void>
50
+ taskTreeCall?:WorkflowTaskTreeOwnerCall;
51
+ }>
52
+ export type WorkspaceRegistryStore = Readonly<{
53
+ daemonId: string; list(): readonly WorkspaceRegistration[]
54
+ register(workDir: string, placement?: 'workspace' | 'independent'): Promise<WorkspaceRegistration>
55
+ remove(key: string): void; close(): void
56
+ resources: Readonly<{ uncertain(): readonly string[]; acquire(id: string, key: string): void; release(id: string): void; invalidate(key: string): void }>
57
+ }>
58
+ export type DaemonEffects = Readonly<{
59
+ registry: WorkspaceRegistryStore
60
+ canonicalDirectory(path: string): Promise<string>
61
+ createWorker(config: WorkerConfig): Promise<WorkspaceWorker>
62
+ newId(): string
63
+ }>
package/src/Effects.ts ADDED
@@ -0,0 +1,61 @@
1
+ import type { ActorAction } from "./Command"
2
+ import type { ObservationFrame } from "./Observation"
3
+
4
+ export type Principal = Readonly<{ principalId: string; grantsVersion: string }>
5
+ export type AuthorizationTarget =
6
+ | Readonly<{kind:'workflow-materials';action:'read';path:string}>
7
+ | Readonly<{kind:'agent-adapters';action:'discover'|'configure'}>
8
+ | Readonly<{kind:'agent-adapter';adapterId:string;action:'observe'|'execute'|'interrupt'}>
9
+ | Readonly<{kind:'execution-environments';action:'discover'}>
10
+ | Readonly<{kind:'execution-environment';workspaceKey:string;action:'read'|'execute'}>
11
+ | Readonly<{kind:'daemon-schedules';action:'read'|'manage'|'execute';scheduleId?:string}>
12
+ | Readonly<{kind:'workflows';action:'discover'|'read'|'start'|'resume';runId?:string}>
13
+ | Readonly<{kind:'global-taskspaces';action:'list'|'create'}>
14
+ | Readonly<{kind:'global-taskspace';taskSpaceId:string;action:'read'|'edit'|'execute'|'control'}>
15
+ | Readonly<{ kind: "server"; action: "list_sessions" | "create_session" | "discover_sessions" | "manage_workspaces" | "stop_daemon" | "register_workflow_conversation_owner" }>
16
+ | Readonly<{ kind: "session"; sessionId: string; action: "open" | "import_session" | "create_actor" | "read_statistics" | "rename" | "archive" }>
17
+ | Readonly<{ kind: "actor"; sessionId: string; actorId: string; action: ActorAction }>
18
+
19
+ export type HostAuthorizationEffects = Readonly<{
20
+ permits: (principal: Principal, target: AuthorizationTarget) => boolean
21
+ currentGrantsVersion: (principalId: string) => string | undefined
22
+ }>
23
+
24
+ export type HostIdentityEffects = Readonly<{
25
+ newId: () => string
26
+ now: () => number
27
+ }>
28
+
29
+ export type ResourceEffectKind = "read_only" | "workspace_mutation" | "unclassified"
30
+ export type ResourceLease = Readonly<{ release: () => void; invalidate?: () => void }>
31
+ export type WorkflowMaterialReadOrigin = Readonly<{ request: import('./HostPort').HostRequest; path: string }>
32
+ export type HostAuthorizationReadOrigin = Readonly<{request:import('./HostPort').HostRequest;target:AuthorizationTarget}>
33
+ export type HostResourceEffects = Readonly<{
34
+ acquire: (input: Readonly<{ workDir: string; kind: ResourceEffectKind; targets?: readonly string[]; signal?: AbortSignal;workflowTaskTree?:import('./WorkflowTaskTree').WorkflowTaskTreeOrigin;executionEnvironment?:import('./ExecutionEnvironment').ExecutionEnvironmentRef;workflowMaterialRead?:WorkflowMaterialReadOrigin;authorizationRead?:HostAuthorizationReadOrigin }>) => Promise<ResourceLease>
35
+ }>
36
+
37
+ export type SessionWriterLeaseEffects = Readonly<{
38
+ acquire: (sessionStorageKey: string) => Promise<ResourceLease>
39
+ }>
40
+
41
+ export type ObservationCursorBinding = Readonly<{
42
+ epoch: string
43
+ principalId: string
44
+ grantsVersion: string
45
+ actors: readonly string[]
46
+ }>
47
+ export type ObservationCursorEffects = Readonly<{
48
+ issue: (binding: ObservationCursorBinding, seq: number) => string
49
+ read: (binding: ObservationCursorBinding, cursor: string) => number | undefined
50
+ }>
51
+
52
+ export type ObservationQueue = Readonly<{
53
+ frames: AsyncIterable<ObservationFrame>
54
+ push: (frame: ObservationFrame, lane: "bootstrap" | "live") => boolean
55
+ close: () => void
56
+ isClosed: () => boolean
57
+ }>
58
+ export type ObservationQueueEffects = Readonly<{
59
+ create: (onClose: () => void) => ObservationQueue
60
+ frameBytes: (frame: ObservationFrame) => number
61
+ }>
@@ -0,0 +1,28 @@
1
+ import type { WorkspaceRegistration } from './Daemon';
2
+ /** A reference to parent-owned registration, never a caller-provided filesystem path. */
3
+ export type ExecutionEnvironmentRef = Readonly<{
4
+ kind: 'daemon-workspace';
5
+ daemonId: string;
6
+ workspaceKey: string;
7
+ revision: number;
8
+ }>;
9
+ export type ExecutionEnvironmentView = Readonly<{
10
+ ref: ExecutionEnvironmentRef;
11
+ name: string;
12
+ workDir: string;
13
+ state: 'registered' | 'opening' | 'ready' | 'closing' | 'failed';
14
+ canExecute: boolean;
15
+ unavailableReason?: string;
16
+ }>;
17
+ export type ExecutionEnvironmentDirectory = Readonly<{
18
+ daemonId: string;
19
+ environments: readonly ExecutionEnvironmentView[];
20
+ }>;
21
+ /** Trusted composition result: public input cannot create this context or replace its path. */
22
+ export type ExecutionEnvironmentContext = Readonly<{
23
+ ref: ExecutionEnvironmentRef;
24
+ workspace: WorkspaceRegistration;
25
+ }>;
26
+ export type ExecutionEnvironmentEffects = Readonly<{
27
+ resolve(request: import('./HostPort').HostRequest, ref: ExecutionEnvironmentRef, action: 'read' | 'execute'): Promise<ExecutionEnvironmentContext>;
28
+ }>;