@xenosystem/agent-interface-host 0.1.6 → 0.1.8
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/acp/AcpAgentTurnExecutionAdapter.d.ts.map +1 -1
- package/dist/acp/AcpAgentTurnExecutionAdapter.js +11 -0
- package/dist/acp/AcpAgentTurnExecutionAdapter.js.map +1 -1
- package/dist/acp/AcpNativeProviderLauncherResolver.d.ts +26 -0
- package/dist/acp/AcpNativeProviderLauncherResolver.d.ts.map +1 -0
- package/dist/acp/AcpNativeProviderLauncherResolver.js +145 -0
- package/dist/acp/AcpNativeProviderLauncherResolver.js.map +1 -0
- package/dist/acp/AcpProcessSupervisor.d.ts.map +1 -1
- package/dist/acp/AcpProcessSupervisor.js +4 -1
- package/dist/acp/AcpProcessSupervisor.js.map +1 -1
- package/dist/acp/AcpProviderModelService.d.ts +1 -0
- package/dist/acp/AcpProviderModelService.d.ts.map +1 -1
- package/dist/acp/AcpProviderModelService.js +2 -2
- package/dist/acp/AcpProviderModelService.js.map +1 -1
- package/dist/acp/AcpSessionService.d.ts.map +1 -1
- package/dist/acp/AcpSessionService.js +40 -2
- package/dist/acp/AcpSessionService.js.map +1 -1
- package/dist/acp/acpTypes.d.ts +3 -0
- package/dist/acp/acpTypes.d.ts.map +1 -1
- package/dist/cloud/XenoCloudAgentTurnExecutionAdapter.d.ts.map +1 -1
- package/dist/cloud/XenoCloudAgentTurnExecutionAdapter.js +4 -0
- package/dist/cloud/XenoCloudAgentTurnExecutionAdapter.js.map +1 -1
- package/dist/index.d.ts +41 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +138 -10
- package/dist/index.js.map +1 -1
- package/dist/lease/ProcessLivenessProber.d.ts +30 -0
- package/dist/lease/ProcessLivenessProber.d.ts.map +1 -0
- package/dist/lease/ProcessLivenessProber.js +95 -0
- package/dist/lease/ProcessLivenessProber.js.map +1 -0
- package/dist/lease/ProviderWriterLeaseService.d.ts +43 -0
- package/dist/lease/ProviderWriterLeaseService.d.ts.map +1 -0
- package/dist/lease/ProviderWriterLeaseService.js +148 -0
- package/dist/lease/ProviderWriterLeaseService.js.map +1 -0
- package/dist/node.d.ts +8 -0
- package/dist/node.d.ts.map +1 -1
- package/dist/node.js +8 -0
- package/dist/node.js.map +1 -1
- package/dist/provider/ProviderLaneService.d.ts +71 -0
- package/dist/provider/ProviderLaneService.d.ts.map +1 -0
- package/dist/provider/ProviderLaneService.js +892 -0
- package/dist/provider/ProviderLaneService.js.map +1 -0
- package/dist/provider/ProviderTransitionOutboxDispatcher.d.ts +22 -0
- package/dist/provider/ProviderTransitionOutboxDispatcher.d.ts.map +1 -0
- package/dist/provider/ProviderTransitionOutboxDispatcher.js +60 -0
- package/dist/provider/ProviderTransitionOutboxDispatcher.js.map +1 -0
- package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.d.ts +4 -1
- package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.d.ts.map +1 -1
- package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.js +37 -1
- package/dist/sdk/SdkNativeAgentTurnExecutionAdapter.js.map +1 -1
- package/dist/state/ProviderLaneSqliteStore.d.ts +64 -0
- package/dist/state/ProviderLaneSqliteStore.d.ts.map +1 -0
- package/dist/state/ProviderLaneSqliteStore.js +728 -0
- package/dist/state/ProviderLaneSqliteStore.js.map +1 -0
- package/dist/state/SqliteAgentStateRepository.d.ts +9 -0
- package/dist/state/SqliteAgentStateRepository.d.ts.map +1 -1
- package/dist/state/SqliteAgentStateRepository.js +171 -17
- package/dist/state/SqliteAgentStateRepository.js.map +1 -1
- package/dist/state/createAgentStateRepository.d.ts.map +1 -1
- package/dist/state/createAgentStateRepository.js +4 -2
- package/dist/state/createAgentStateRepository.js.map +1 -1
- package/dist/state/providerLaneSchema.d.ts +13 -0
- package/dist/state/providerLaneSchema.d.ts.map +1 -0
- package/dist/state/providerLaneSchema.js +129 -0
- package/dist/state/providerLaneSchema.js.map +1 -0
- package/dist/state/providerLaneTypes.d.ts +122 -0
- package/dist/state/providerLaneTypes.d.ts.map +1 -0
- package/dist/state/providerLaneTypes.js +28 -0
- package/dist/state/providerLaneTypes.js.map +1 -0
- package/dist/state/sdkProtectedStateCipher.d.ts +30 -0
- package/dist/state/sdkProtectedStateCipher.d.ts.map +1 -0
- package/dist/state/sdkProtectedStateCipher.js +50 -0
- package/dist/state/sdkProtectedStateCipher.js.map +1 -0
- package/dist/workspace/WorkspaceHostService.d.ts +31 -1
- package/dist/workspace/WorkspaceHostService.d.ts.map +1 -1
- package/dist/workspace/WorkspaceHostService.js +89 -12
- package/dist/workspace/WorkspaceHostService.js.map +1 -1
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -86,6 +86,7 @@ export class AgentHostCoordinator {
|
|
|
86
86
|
*/
|
|
87
87
|
subagentRuns;
|
|
88
88
|
resolveRunId;
|
|
89
|
+
providerLaneService;
|
|
89
90
|
connectedClients = new Map();
|
|
90
91
|
/** What each connected client declared it can do, keyed the same way. */
|
|
91
92
|
clientCapabilities = new Map();
|
|
@@ -130,7 +131,7 @@ export class AgentHostCoordinator {
|
|
|
130
131
|
providerCatalogFingerprint = '';
|
|
131
132
|
providerCatalogRefresh = null;
|
|
132
133
|
constructor(options) {
|
|
133
|
-
const { providers, providerCatalogLoader, runtimeEvents, runtimeEventRepository, stateRepository, workspaceService, interactionService, permissionPolicyService, interruptedTurnStore, turnAdmissionPolicy, turnAbandonGraceMs, sdkControlService, engineeringControlService, turnExecutionAdapters, coordinationService, runObservationService, runIsolationService, runObservationBinder, sessionService, nativeTuiLane, acpAgentRegistry, intakeService, knowledgeService, acpApprovalService, subagentRuns, resolveRunId, ...hostOptions } = options;
|
|
134
|
+
const { providers, providerCatalogLoader, runtimeEvents, runtimeEventRepository, stateRepository, workspaceService, interactionService, permissionPolicyService, interruptedTurnStore, turnAdmissionPolicy, turnAbandonGraceMs, sdkControlService, engineeringControlService, providerLaneService, turnExecutionAdapters, coordinationService, runObservationService, runIsolationService, runObservationBinder, sessionService, nativeTuiLane, acpAgentRegistry, intakeService, knowledgeService, acpApprovalService, subagentRuns, resolveRunId, ...hostOptions } = options;
|
|
134
135
|
if (runtimeEventRepository && runtimeEvents && runtimeEvents.length > 0) {
|
|
135
136
|
throw new Error('Seeded runtimeEvents cannot be combined with a durable runtimeEventRepository.');
|
|
136
137
|
}
|
|
@@ -146,6 +147,9 @@ export class AgentHostCoordinator {
|
|
|
146
147
|
this.turnAbandonGraceMs = turnAbandonGraceMs ?? DEFAULT_TURN_ABANDON_GRACE_MS;
|
|
147
148
|
this.sdkControlService = sdkControlService;
|
|
148
149
|
this.engineeringControlService = engineeringControlService;
|
|
150
|
+
this.providerLaneService = providerLaneService;
|
|
151
|
+
this.providerLaneService?.setEventSink?.((type, payload) => this.publish(type, payload));
|
|
152
|
+
this.providerLaneService?.start?.();
|
|
149
153
|
this.coordinationService = coordinationService;
|
|
150
154
|
// A turn's run identity, if the request carries one. `subagentRunId` first:
|
|
151
155
|
// a subagent IS a distinct run with its own claims, so folding it into its
|
|
@@ -153,7 +157,11 @@ export class AgentHostCoordinator {
|
|
|
153
157
|
// 🔴 `defaultRunIdOf`, not a hand-written `??` — a session filters runtime
|
|
154
158
|
// EVENTS by the same rule, and the two must not drift. See its doc.
|
|
155
159
|
this.resolveRunId = resolveRunId ?? ((request) => defaultRunIdOf(request));
|
|
156
|
-
this.workspaceService?.setEventSink((type, payload) =>
|
|
160
|
+
this.workspaceService?.setEventSink((type, payload) => {
|
|
161
|
+
if (type === 'workspace.pty.exit')
|
|
162
|
+
this.providerLaneService?.handleWorkspacePtyExit?.(payload);
|
|
163
|
+
this.publish(type, payload);
|
|
164
|
+
});
|
|
157
165
|
// Coordination reaches surfaces through the event feed and nothing else.
|
|
158
166
|
// Published as `redactionState: 'safe'` like every host event — which holds
|
|
159
167
|
// because a coordination event carries ids, scopes and outcomes, never
|
|
@@ -1519,6 +1527,64 @@ export class AgentHostCoordinator {
|
|
|
1519
1527
|
this.assertWorkspaceClient(input);
|
|
1520
1528
|
return await this.requireWorkspaceService().stopPty(input);
|
|
1521
1529
|
}
|
|
1530
|
+
if (method === 'conversation.open') {
|
|
1531
|
+
const request = input;
|
|
1532
|
+
this.assertConnectedClient(request.command.client, 'using provider conversations');
|
|
1533
|
+
return await this.requireProviderLaneService().openConversation(request);
|
|
1534
|
+
}
|
|
1535
|
+
if (method === 'conversation.resume') {
|
|
1536
|
+
const request = input;
|
|
1537
|
+
this.assertConnectedClient(request.command.client, 'using provider conversations');
|
|
1538
|
+
return await this.requireProviderLaneService().resumeConversation(request);
|
|
1539
|
+
}
|
|
1540
|
+
if (method === 'provider.lanes.list') {
|
|
1541
|
+
const request = input;
|
|
1542
|
+
this.assertConnectedClient(request.client, 'listing provider lanes');
|
|
1543
|
+
return await this.requireProviderLaneService().listLanes(request);
|
|
1544
|
+
}
|
|
1545
|
+
if (method === 'provider.lanes.get') {
|
|
1546
|
+
const request = input;
|
|
1547
|
+
this.assertConnectedClient(request.client, 'reading provider lanes');
|
|
1548
|
+
return await this.requireProviderLaneService().getLane(request);
|
|
1549
|
+
}
|
|
1550
|
+
if (method === 'provider.lanes.select') {
|
|
1551
|
+
const request = input;
|
|
1552
|
+
this.assertConnectedClient(request.command.client, 'selecting provider lanes');
|
|
1553
|
+
await this.refreshProviderCatalog();
|
|
1554
|
+
return await this.requireProviderLaneService().selectLane(request);
|
|
1555
|
+
}
|
|
1556
|
+
if (method === 'provider.native.attach') {
|
|
1557
|
+
const request = input;
|
|
1558
|
+
this.assertConnectedClient(request.command.client, 'attaching a native provider TUI');
|
|
1559
|
+
if ([...this.activeTurns.values()].some((active) => active.request.conversationId === request.conversationId)) {
|
|
1560
|
+
return {
|
|
1561
|
+
success: false,
|
|
1562
|
+
code: 'LANE_WRITER_ACTIVE',
|
|
1563
|
+
error: 'A structured provider turn is active for this conversation.',
|
|
1564
|
+
};
|
|
1565
|
+
}
|
|
1566
|
+
return await this.requireProviderLaneService().attachNative(request);
|
|
1567
|
+
}
|
|
1568
|
+
if (method === 'provider.native.detach') {
|
|
1569
|
+
const request = input;
|
|
1570
|
+
this.assertConnectedClient(request.command.client, 'detaching a native provider TUI');
|
|
1571
|
+
return await this.requireProviderLaneService().detachNative(request);
|
|
1572
|
+
}
|
|
1573
|
+
if (method === 'provider.native.reattach') {
|
|
1574
|
+
const request = input;
|
|
1575
|
+
this.assertConnectedClient(request.command.client, 'reattaching a native provider TUI');
|
|
1576
|
+
return await this.requireProviderLaneService().reattachNative(request);
|
|
1577
|
+
}
|
|
1578
|
+
if (method === 'provider.native.stop') {
|
|
1579
|
+
const request = input;
|
|
1580
|
+
this.assertConnectedClient(request.command.client, 'stopping a native provider TUI');
|
|
1581
|
+
return await this.requireProviderLaneService().stopNative(request);
|
|
1582
|
+
}
|
|
1583
|
+
if (method === 'provider.reconcile') {
|
|
1584
|
+
const request = input;
|
|
1585
|
+
this.assertConnectedClient(request.command.client, 'reconciling a provider lane');
|
|
1586
|
+
return await this.requireProviderLaneService().reconcile(request);
|
|
1587
|
+
}
|
|
1522
1588
|
if (method === 'turn.start') {
|
|
1523
1589
|
return await this.startTurn(input);
|
|
1524
1590
|
}
|
|
@@ -1759,6 +1825,7 @@ export class AgentHostCoordinator {
|
|
|
1759
1825
|
}));
|
|
1760
1826
|
await this.sdkControlService?.close?.();
|
|
1761
1827
|
await this.engineeringControlService?.close?.();
|
|
1828
|
+
await this.providerLaneService?.close?.();
|
|
1762
1829
|
await this.workspaceService?.close?.();
|
|
1763
1830
|
await this.stateRepository?.close?.();
|
|
1764
1831
|
// Before the listeners go: each session's protocol channel is subscribed to
|
|
@@ -2008,13 +2075,26 @@ export class AgentHostCoordinator {
|
|
|
2008
2075
|
this.trackTurnTimer(activeKey, timer);
|
|
2009
2076
|
}
|
|
2010
2077
|
async startTurn(input) {
|
|
2011
|
-
|
|
2078
|
+
let invalidReason = validateTurnStartRequest(input);
|
|
2012
2079
|
if (invalidReason) {
|
|
2013
2080
|
return turnStartFailure('invalid_request', invalidReason, input);
|
|
2014
2081
|
}
|
|
2015
2082
|
if (!this.isConnectedClient(input.command.client)) {
|
|
2016
2083
|
return turnStartFailure('client_not_connected', 'The requesting surface must complete the host handshake before starting a turn.', input);
|
|
2017
2084
|
}
|
|
2085
|
+
if (this.providerLaneService?.prepareTurn) {
|
|
2086
|
+
try {
|
|
2087
|
+
input = await this.providerLaneService.prepareTurn(structuredClone(input));
|
|
2088
|
+
}
|
|
2089
|
+
catch (error) {
|
|
2090
|
+
return turnStartFailure('invalid_request', error instanceof Error && error.message.trim()
|
|
2091
|
+
? error.message.slice(0, 1_000)
|
|
2092
|
+
: 'The active provider lane rejected this turn.', input);
|
|
2093
|
+
}
|
|
2094
|
+
invalidReason = validateTurnStartRequest(input);
|
|
2095
|
+
if (invalidReason)
|
|
2096
|
+
return turnStartFailure('invalid_request', invalidReason, input);
|
|
2097
|
+
}
|
|
2018
2098
|
const commandKey = this.commandKey('turn.start', input.command);
|
|
2019
2099
|
const fingerprint = commandFingerprint(input);
|
|
2020
2100
|
const prior = this.commandResults.get(commandKey);
|
|
@@ -2111,6 +2191,16 @@ export class AgentHostCoordinator {
|
|
|
2111
2191
|
return turnStartFailure('concurrency_limit_reached', admission.safeError, input);
|
|
2112
2192
|
}
|
|
2113
2193
|
const request = structuredClone(input);
|
|
2194
|
+
if (this.providerLaneService?.beginStructuredTurn) {
|
|
2195
|
+
try {
|
|
2196
|
+
await this.providerLaneService.beginStructuredTurn(request);
|
|
2197
|
+
}
|
|
2198
|
+
catch (error) {
|
|
2199
|
+
return this.rememberTurnStartFailure(commandKey, fingerprint, turnStartFailure('request_already_active', error instanceof Error && error.message.trim()
|
|
2200
|
+
? error.message.slice(0, 1_000)
|
|
2201
|
+
: 'The provider lane writer could not be acquired.', request));
|
|
2202
|
+
}
|
|
2203
|
+
}
|
|
2114
2204
|
// Recorded BEFORE execution, so a coordination event arriving in the first
|
|
2115
2205
|
// moments of a turn still finds its conversation.
|
|
2116
2206
|
const contextRunId = this.resolveRunId(request);
|
|
@@ -2202,10 +2292,25 @@ export class AgentHostCoordinator {
|
|
|
2202
2292
|
// §5.2b's `message` primitive is a PUSH, and this is the push. Without
|
|
2203
2293
|
// it a run could send and no run could ever receive.
|
|
2204
2294
|
.then(() => this.deliverCoordinationMessages(request))
|
|
2205
|
-
.then(() =>
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2295
|
+
.then(async () => {
|
|
2296
|
+
const hostBinding = await this.providerLaneService?.getHostBinding?.(request.conversationId);
|
|
2297
|
+
return adapter.execute(request, provider, resolved.selection, {
|
|
2298
|
+
signal: controller.signal,
|
|
2299
|
+
...(hostBinding ? { hostBinding: structuredClone(hostBinding) } : {}),
|
|
2300
|
+
publishPersistedRuntimeEvent: (event) => this.publishPersistedRuntimeEvent(event),
|
|
2301
|
+
commitProviderContinuation: async (continuation) => {
|
|
2302
|
+
if (!this.providerLaneService?.commitTurnContinuation)
|
|
2303
|
+
return;
|
|
2304
|
+
const result = await this.providerLaneService.commitTurnContinuation({
|
|
2305
|
+
conversationId: request.conversationId,
|
|
2306
|
+
requestId: request.requestId,
|
|
2307
|
+
continuation: structuredClone(continuation),
|
|
2308
|
+
});
|
|
2309
|
+
if (!result.success)
|
|
2310
|
+
throw new Error(result.error || 'Provider continuation could not be committed.');
|
|
2311
|
+
},
|
|
2312
|
+
});
|
|
2313
|
+
})
|
|
2209
2314
|
.then(() => {
|
|
2210
2315
|
// The turn ended WELL. Published here rather than inferred by each surface from
|
|
2211
2316
|
// provider-specific runtime event strings — see the note on the event type itself.
|
|
@@ -2217,6 +2322,15 @@ export class AgentHostCoordinator {
|
|
|
2217
2322
|
// what the host already told every surface. Late is not the same as successful.
|
|
2218
2323
|
if (this.activeTurns.get(activeKey)?.controller !== controller)
|
|
2219
2324
|
return;
|
|
2325
|
+
if (controller.signal.aborted) {
|
|
2326
|
+
this.publish('turn.execution.abandoned', {
|
|
2327
|
+
conversationId: request.conversationId,
|
|
2328
|
+
requestId: request.requestId,
|
|
2329
|
+
adapterId: adapter.id,
|
|
2330
|
+
reason: 'The turn was cancelled before completion.',
|
|
2331
|
+
});
|
|
2332
|
+
return;
|
|
2333
|
+
}
|
|
2220
2334
|
this.publish('turn.execution.completed', {
|
|
2221
2335
|
conversationId: request.conversationId,
|
|
2222
2336
|
requestId: request.requestId,
|
|
@@ -2228,14 +2342,17 @@ export class AgentHostCoordinator {
|
|
|
2228
2342
|
// second terminal event either.
|
|
2229
2343
|
if (this.activeTurns.get(activeKey)?.controller !== controller)
|
|
2230
2344
|
return;
|
|
2231
|
-
this.publish('turn.execution.failed', {
|
|
2345
|
+
this.publish(controller.signal.aborted ? 'turn.execution.abandoned' : 'turn.execution.failed', {
|
|
2232
2346
|
conversationId: request.conversationId,
|
|
2233
2347
|
requestId: request.requestId,
|
|
2234
2348
|
adapterId: adapter.id,
|
|
2235
|
-
|
|
2349
|
+
...(controller.signal.aborted
|
|
2350
|
+
? { reason: 'The turn was cancelled before completion.' }
|
|
2351
|
+
: { safeError: 'The selected runtime adapter failed to execute the turn.' }),
|
|
2236
2352
|
});
|
|
2237
2353
|
})
|
|
2238
|
-
.finally(() => {
|
|
2354
|
+
.finally(async () => {
|
|
2355
|
+
await this.providerLaneService?.finishStructuredTurn?.(request.conversationId, request.requestId);
|
|
2239
2356
|
const active = this.activeTurns.get(activeKey);
|
|
2240
2357
|
if (active?.controller === controller)
|
|
2241
2358
|
this.activeTurns.delete(activeKey);
|
|
@@ -3034,6 +3151,17 @@ export class AgentHostCoordinator {
|
|
|
3034
3151
|
}
|
|
3035
3152
|
return this.engineeringControlService;
|
|
3036
3153
|
}
|
|
3154
|
+
requireProviderLaneService() {
|
|
3155
|
+
if (!this.providerLaneService) {
|
|
3156
|
+
throw new AgentHostProtocolError('invalid_response', 'Host-owned provider lane services are unavailable.');
|
|
3157
|
+
}
|
|
3158
|
+
return this.providerLaneService;
|
|
3159
|
+
}
|
|
3160
|
+
assertConnectedClient(identity, operation) {
|
|
3161
|
+
if (!isAgentHostClientIdentity(identity) || !this.isConnectedClient(identity)) {
|
|
3162
|
+
throw new AgentHostProtocolError('invalid_response', `The requesting surface must complete the host handshake before ${operation}.`);
|
|
3163
|
+
}
|
|
3164
|
+
}
|
|
3037
3165
|
assertWorkspaceClient(input) {
|
|
3038
3166
|
if (!isRecord(input) || !isAgentHostClientIdentity(input.client) || !this.isConnectedClient(input.client)) {
|
|
3039
3167
|
throw new AgentHostProtocolError('invalid_response', 'The requesting surface must complete the host handshake before using workspace services.');
|