@borgee/agents-host 0.2.26 → 0.2.29
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/README.md +27 -4
- package/dist/agents-host.d.ts +25 -0
- package/dist/agents-host.js +627 -14
- package/dist/compatibility-gates.d.ts +8 -1
- package/dist/compatibility-gates.js +43 -3
- package/dist/config.js +3 -3
- package/dist/context/attention.d.ts +12 -0
- package/dist/context/attention.js +137 -0
- package/dist/context/collaboration-capabilities-diagnostics.d.ts +3 -0
- package/dist/context/collaboration-capabilities-diagnostics.js +18 -0
- package/dist/context/collaboration-outcome.d.ts +2 -0
- package/dist/context/collaboration-outcome.js +26 -0
- package/dist/context/injection.d.ts +26 -1
- package/dist/context/injection.js +7 -2
- package/dist/context/prompt.js +61 -0
- package/dist/context/task-thread-collaboration.d.ts +6 -0
- package/dist/context/task-thread-collaboration.js +31 -0
- package/dist/context/turn-preparation.js +30 -1
- package/dist/managed-daemon.js +183 -47
- package/dist/providers/awaiting-user.js +46 -5
- package/dist/providers/codex/project-doc.js +24 -0
- package/dist/state-paths.d.ts +1 -0
- package/dist/state-paths.js +3 -0
- package/dist/types.d.ts +97 -4
- package/package.json +1 -1
package/dist/managed-daemon.js
CHANGED
|
@@ -5,7 +5,7 @@ import { createConnection, createServer } from 'node:net';
|
|
|
5
5
|
import { dirname, join, resolve } from 'node:path';
|
|
6
6
|
import { fileURLToPath } from 'node:url';
|
|
7
7
|
import { AgentsHostSupervisor } from './agents-host-supervisor.js';
|
|
8
|
-
import { COMPATIBILITY_GATES_ENV, createManagedRuntimeSettingsFingerprint, INTERNAL_POLICY_MODE_ENV, INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV, MANAGED_RUNTIME_CONVERGENCE_COMPATIBILITY_GATE, MANAGED_RUNTIME_SETTINGS_SCHEMA_VERSION, resolveManagedRuntimeSettingsSnapshot, normalizeInternalProviderImplementationOverrides, } from './compatibility-gates.js';
|
|
8
|
+
import { COMPATIBILITY_GATES_ENV, createManagedRuntimeSettingsFingerprint, INTERNAL_DISABLED_COMPATIBILITY_GATES_ENV, INTERNAL_POLICY_MODE_ENV, INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV, MANAGED_RUNTIME_CONVERGENCE_COMPATIBILITY_GATE, MANAGED_RUNTIME_SETTINGS_SCHEMA_VERSION, resolveDisabledDefaultCompatibilityGates, resolveManagedRuntimeSettingsSnapshot, normalizeInternalProviderImplementationOverrides, } from './compatibility-gates.js';
|
|
9
9
|
import { loadConfigFromEnv } from './config.js';
|
|
10
10
|
import { loadLocalConfigGenerateSpec, materializeLocalConfig, parseGenerateConfigSpec, resolveLocalConfigLayout, } from './local-config.js';
|
|
11
11
|
import { normalizeManagedRuntimeKey, resolveManagedBootstrapLockPath, resolveManagedDaemonLogPath, resolveManagedDaemonSocketPath, resolveManagedRuntimeRoot, resolveManagedRuntimeSettingsPath, } from './state-paths.js';
|
|
@@ -222,15 +222,45 @@ function buildManagedRuntimeSettingsEnv(baseEnv, snapshot) {
|
|
|
222
222
|
return {
|
|
223
223
|
...baseEnv,
|
|
224
224
|
[COMPATIBILITY_GATES_ENV]: snapshot.compatibilityGates.join(','),
|
|
225
|
+
[INTERNAL_DISABLED_COMPATIBILITY_GATES_ENV]: resolveDisabledDefaultCompatibilityGates(snapshot.compatibilityGates).join(','),
|
|
225
226
|
[INTERNAL_PROVIDER_IMPLEMENTATIONS_ENV]: snapshot.providerImplementationOverrides.join(','),
|
|
226
227
|
[INTERNAL_POLICY_MODE_ENV]: snapshot.internalPolicyMode,
|
|
227
228
|
};
|
|
228
229
|
}
|
|
229
|
-
function
|
|
230
|
-
|
|
231
|
-
|
|
230
|
+
function buildDesiredManagedRuntimeSettingsFromSnapshot(snapshot) {
|
|
231
|
+
return {
|
|
232
|
+
snapshot,
|
|
233
|
+
fingerprint: createManagedRuntimeSettingsFingerprint(snapshot),
|
|
234
|
+
convergenceEnabled: snapshot.compatibilityGates.includes(MANAGED_RUNTIME_CONVERGENCE_COMPATIBILITY_GATE),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
async function getManagedRuntimeFingerprintMismatch(rootPath, status, desiredSettings) {
|
|
238
|
+
if (status.managedRuntimeFingerprint != null) {
|
|
239
|
+
return status.managedRuntimeFingerprint !== desiredSettings.fingerprint;
|
|
240
|
+
}
|
|
241
|
+
if (desiredSettings.convergenceEnabled) {
|
|
242
|
+
return true;
|
|
243
|
+
}
|
|
244
|
+
const persistedSettingsSnapshot = await loadManagedRuntimeSettingsSnapshot(rootPath);
|
|
245
|
+
if (!persistedSettingsSnapshot) {
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
return createManagedRuntimeSettingsFingerprint(persistedSettingsSnapshot) !== desiredSettings.fingerprint;
|
|
249
|
+
}
|
|
250
|
+
async function resolveAuthoritativeManagedRuntimeSettings(rootPath, effectiveProcessEnv) {
|
|
251
|
+
const persistedSettingsSnapshot = await loadManagedRuntimeSettingsSnapshot(rootPath);
|
|
252
|
+
if (!persistedSettingsSnapshot) {
|
|
253
|
+
return {
|
|
254
|
+
desiredSettings: resolveDesiredManagedRuntimeSettings(effectiveProcessEnv),
|
|
255
|
+
processEnv: effectiveProcessEnv,
|
|
256
|
+
persistedSettingsSnapshot: null,
|
|
257
|
+
};
|
|
232
258
|
}
|
|
233
|
-
return
|
|
259
|
+
return {
|
|
260
|
+
desiredSettings: buildDesiredManagedRuntimeSettingsFromSnapshot(persistedSettingsSnapshot),
|
|
261
|
+
processEnv: buildManagedRuntimeSettingsEnv(effectiveProcessEnv, persistedSettingsSnapshot),
|
|
262
|
+
persistedSettingsSnapshot,
|
|
263
|
+
};
|
|
234
264
|
}
|
|
235
265
|
function cloneLocalAgentConfig(agent) {
|
|
236
266
|
return {
|
|
@@ -311,6 +341,57 @@ export function buildManagedLocalAgentConfig(options) {
|
|
|
311
341
|
},
|
|
312
342
|
};
|
|
313
343
|
}
|
|
344
|
+
function mergeManagedLocalAgentConfig(existingAgent, generatedAgent, envOverrides) {
|
|
345
|
+
const overrides = envOverrides ?? {};
|
|
346
|
+
const hasOverride = (key) => Object.prototype.hasOwnProperty.call(overrides, key);
|
|
347
|
+
return {
|
|
348
|
+
...cloneLocalAgentConfig(existingAgent),
|
|
349
|
+
key: generatedAgent.key,
|
|
350
|
+
apiKey: generatedAgent.apiKey,
|
|
351
|
+
enabled: true,
|
|
352
|
+
name: hasOverride('BORGEE_AGENT_NAME') ? generatedAgent.name : existingAgent.name,
|
|
353
|
+
provider: hasOverride('RUNTIME_PROVIDER') ? generatedAgent.provider : existingAgent.provider,
|
|
354
|
+
claudeCommand: hasOverride('CLAUDE_COMMAND') ? generatedAgent.claudeCommand : existingAgent.claudeCommand,
|
|
355
|
+
claudeArgs: hasOverride('CLAUDE_ARGS')
|
|
356
|
+
? [...(generatedAgent.claudeArgs ?? [])]
|
|
357
|
+
: [...(existingAgent.claudeArgs ?? [])],
|
|
358
|
+
codexCommand: hasOverride('CODEX_COMMAND') ? generatedAgent.codexCommand : existingAgent.codexCommand,
|
|
359
|
+
codexArgs: hasOverride('CODEX_ARGS')
|
|
360
|
+
? [...(generatedAgent.codexArgs ?? [])]
|
|
361
|
+
: [...(existingAgent.codexArgs ?? [])],
|
|
362
|
+
copilotCommand: hasOverride('COPILOT_COMMAND')
|
|
363
|
+
? generatedAgent.copilotCommand
|
|
364
|
+
: existingAgent.copilotCommand,
|
|
365
|
+
copilotArgs: hasOverride('COPILOT_ARGS')
|
|
366
|
+
? [...(generatedAgent.copilotArgs ?? [])]
|
|
367
|
+
: [...(existingAgent.copilotArgs ?? [])],
|
|
368
|
+
copilotSessionTtlMinutes: hasOverride('COPILOT_SESSION_TTL_MINUTES')
|
|
369
|
+
? generatedAgent.copilotSessionTtlMinutes
|
|
370
|
+
: existingAgent.copilotSessionTtlMinutes,
|
|
371
|
+
};
|
|
372
|
+
}
|
|
373
|
+
function collectExplicitManagedAgentEnvOverrides(processEnv, optionEnv) {
|
|
374
|
+
const explicitOverrides = {};
|
|
375
|
+
for (const key of [
|
|
376
|
+
'BORGEE_AGENT_NAME',
|
|
377
|
+
'RUNTIME_PROVIDER',
|
|
378
|
+
'CLAUDE_COMMAND',
|
|
379
|
+
'CLAUDE_ARGS',
|
|
380
|
+
'CODEX_COMMAND',
|
|
381
|
+
'CODEX_ARGS',
|
|
382
|
+
'COPILOT_COMMAND',
|
|
383
|
+
'COPILOT_ARGS',
|
|
384
|
+
'COPILOT_SESSION_TTL_MINUTES',
|
|
385
|
+
]) {
|
|
386
|
+
if (processEnv[key] !== undefined) {
|
|
387
|
+
explicitOverrides[key] = processEnv[key];
|
|
388
|
+
}
|
|
389
|
+
if (optionEnv && Object.prototype.hasOwnProperty.call(optionEnv, key)) {
|
|
390
|
+
explicitOverrides[key] = optionEnv[key];
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
return explicitOverrides;
|
|
394
|
+
}
|
|
314
395
|
function resolveManagedRuntimeLayoutForServerUrl(serverUrl, processEnv = process.env) {
|
|
315
396
|
const rootPath = resolveManagedRuntimeRoot(serverUrl, processEnv);
|
|
316
397
|
return {
|
|
@@ -884,8 +965,6 @@ export async function bootstrapManagedDaemonStart(options, deps = {}) {
|
|
|
884
965
|
...(options.processEnv ?? process.env),
|
|
885
966
|
...options.env,
|
|
886
967
|
};
|
|
887
|
-
const loadSpec = deps.loadSpec
|
|
888
|
-
?? ((hostConfigPath) => loadLocalConfigGenerateSpec(hostConfigPath, { env: effectiveProcessEnv }));
|
|
889
968
|
const materialize = deps.materialize ?? materializeLocalConfig;
|
|
890
969
|
const sendRequest = deps.sendRequest ?? sendManagedDaemonRequest;
|
|
891
970
|
const spawnDaemonProcess = deps.spawnDaemon ?? spawnManagedDaemonProcess;
|
|
@@ -895,19 +974,51 @@ export async function bootstrapManagedDaemonStart(options, deps = {}) {
|
|
|
895
974
|
?? (async (rootPath) => {
|
|
896
975
|
await waitForManagedDaemonShutdown(rootPath, canConnectToSocket);
|
|
897
976
|
});
|
|
898
|
-
const
|
|
899
|
-
const
|
|
900
|
-
const resolved = resolvedManagedAgent ??
|
|
901
|
-
resolveManagedRuntimeLayoutForServerUrl(options.serverUrl, options.processEnv);
|
|
977
|
+
const requestedSettings = resolveDesiredManagedRuntimeSettings(effectiveProcessEnv);
|
|
978
|
+
const resolved = resolveManagedRuntimeLayoutForServerUrl(options.serverUrl, options.processEnv);
|
|
902
979
|
const releaseBootstrapLock = await acquireLock(resolved.rootPath);
|
|
903
980
|
try {
|
|
981
|
+
const currentRuntimeSettings = await resolveAuthoritativeManagedRuntimeSettings(resolved.rootPath, effectiveProcessEnv);
|
|
982
|
+
const loadManagedSpecWithCurrentRuntimeEnv = (hostConfigPath) => deps.loadSpec
|
|
983
|
+
? deps.loadSpec(hostConfigPath)
|
|
984
|
+
: loadLocalConfigGenerateSpec(hostConfigPath, {
|
|
985
|
+
env: currentRuntimeSettings.processEnv,
|
|
986
|
+
});
|
|
987
|
+
if (options.apiKey !== undefined
|
|
988
|
+
&& currentRuntimeSettings.persistedSettingsSnapshot == null
|
|
989
|
+
&& await fs.access(resolved.hostConfigPath).then(() => true).catch(() => false)) {
|
|
990
|
+
throw new Error(`Managed runtime root ${resolved.rootPath} predates managed-runtime-settings.json; run \`agents-host start-managed ${options.serverUrl}\` once to migrate it before updating an individual agent`);
|
|
991
|
+
}
|
|
992
|
+
const explicitManagedAgentOverrides = collectExplicitManagedAgentEnvOverrides(options.processEnv ?? process.env, options.env);
|
|
993
|
+
const currentManagedSpec = options.apiKey === undefined
|
|
994
|
+
? undefined
|
|
995
|
+
: await loadManagedSpecOrUndefined(resolved.hostConfigPath, loadManagedSpecWithCurrentRuntimeEnv);
|
|
996
|
+
const resolvedManagedAgent = options.apiKey === undefined
|
|
997
|
+
? null
|
|
998
|
+
: (() => {
|
|
999
|
+
const generatedManagedAgent = buildManagedLocalAgentConfig({
|
|
1000
|
+
...options,
|
|
1001
|
+
processEnv: currentRuntimeSettings.processEnv,
|
|
1002
|
+
env: options.env,
|
|
1003
|
+
});
|
|
1004
|
+
const existingAgent = currentManagedSpec?.agents.find((agent) => agent.key === generatedManagedAgent.agent.key);
|
|
1005
|
+
return existingAgent
|
|
1006
|
+
? {
|
|
1007
|
+
...generatedManagedAgent,
|
|
1008
|
+
agent: mergeManagedLocalAgentConfig(existingAgent, generatedManagedAgent.agent, explicitManagedAgentOverrides),
|
|
1009
|
+
}
|
|
1010
|
+
: generatedManagedAgent;
|
|
1011
|
+
})();
|
|
1012
|
+
const desiredBootstrapSettings = options.apiKey === undefined ? requestedSettings : currentRuntimeSettings.desiredSettings;
|
|
1013
|
+
const desiredBootstrapProcessEnv = options.apiKey === undefined ? effectiveProcessEnv : currentRuntimeSettings.processEnv;
|
|
904
1014
|
let statusResponse = await readReadyManagedDaemonStatus(resolved.rootPath, sendRequest);
|
|
905
|
-
if (statusResponse
|
|
1015
|
+
if (statusResponse
|
|
1016
|
+
&& await getManagedRuntimeFingerprintMismatch(resolved.rootPath, statusResponse, desiredBootstrapSettings)) {
|
|
906
1017
|
await recycleManagedDaemonWithDesiredSettings({
|
|
907
1018
|
rootPath: resolved.rootPath,
|
|
908
1019
|
debug: options.debug === true,
|
|
909
|
-
processEnv:
|
|
910
|
-
desiredSettings,
|
|
1020
|
+
processEnv: desiredBootstrapProcessEnv,
|
|
1021
|
+
desiredSettings: desiredBootstrapSettings,
|
|
911
1022
|
sendRequest,
|
|
912
1023
|
waitForShutdown,
|
|
913
1024
|
spawnDaemonProcess,
|
|
@@ -917,11 +1028,17 @@ export async function bootstrapManagedDaemonStart(options, deps = {}) {
|
|
|
917
1028
|
}
|
|
918
1029
|
if (!statusResponse) {
|
|
919
1030
|
if (options.apiKey === undefined) {
|
|
920
|
-
await ensurePersistedManagedAgentsExist(options.serverUrl, resolved.hostConfigPath,
|
|
1031
|
+
await ensurePersistedManagedAgentsExist(options.serverUrl, resolved.hostConfigPath, (hostConfigPath) => options.apiKey === undefined
|
|
1032
|
+
? (deps.loadSpec
|
|
1033
|
+
? deps.loadSpec(hostConfigPath)
|
|
1034
|
+
: loadLocalConfigGenerateSpec(hostConfigPath, {
|
|
1035
|
+
env: desiredBootstrapProcessEnv,
|
|
1036
|
+
}))
|
|
1037
|
+
: loadManagedSpecWithCurrentRuntimeEnv(hostConfigPath));
|
|
921
1038
|
}
|
|
922
1039
|
else {
|
|
923
1040
|
try {
|
|
924
|
-
await
|
|
1041
|
+
await loadManagedSpecWithCurrentRuntimeEnv(resolved.hostConfigPath);
|
|
925
1042
|
}
|
|
926
1043
|
catch (error) {
|
|
927
1044
|
if (isNotFoundError(error)) {
|
|
@@ -938,8 +1055,8 @@ export async function bootstrapManagedDaemonStart(options, deps = {}) {
|
|
|
938
1055
|
await startManagedDaemonWithPersistedSettings({
|
|
939
1056
|
rootPath: resolved.rootPath,
|
|
940
1057
|
debug: options.debug === true,
|
|
941
|
-
processEnv:
|
|
942
|
-
desiredSettings,
|
|
1058
|
+
processEnv: desiredBootstrapProcessEnv,
|
|
1059
|
+
desiredSettings: desiredBootstrapSettings,
|
|
943
1060
|
spawnDaemonProcess,
|
|
944
1061
|
waitForDaemon,
|
|
945
1062
|
sendRequest,
|
|
@@ -948,7 +1065,11 @@ export async function bootstrapManagedDaemonStart(options, deps = {}) {
|
|
|
948
1065
|
}
|
|
949
1066
|
if (options.apiKey === undefined) {
|
|
950
1067
|
if (!statusResponse) {
|
|
951
|
-
await ensurePersistedManagedAgentsExist(options.serverUrl, resolved.hostConfigPath, loadSpec
|
|
1068
|
+
await ensurePersistedManagedAgentsExist(options.serverUrl, resolved.hostConfigPath, (hostConfigPath) => deps.loadSpec
|
|
1069
|
+
? deps.loadSpec(hostConfigPath)
|
|
1070
|
+
: loadLocalConfigGenerateSpec(hostConfigPath, {
|
|
1071
|
+
env: desiredBootstrapProcessEnv,
|
|
1072
|
+
}));
|
|
952
1073
|
}
|
|
953
1074
|
else {
|
|
954
1075
|
assertManagedRuntimeBinding(statusResponse.borgeeBaseUrl, options.serverUrl);
|
|
@@ -1079,10 +1200,11 @@ async function terminateChildProcessAndWait(child) {
|
|
|
1079
1200
|
}
|
|
1080
1201
|
await waitForChildExit(child, DAEMON_FORCE_KILL_WAIT_MS);
|
|
1081
1202
|
}
|
|
1082
|
-
async function rollbackManagedApplyFailure(rootPath, previousSpec, materialize, clearRuntimeImpl, applyError) {
|
|
1203
|
+
async function rollbackManagedApplyFailure(rootPath, previousSpec, previousSettingsSnapshot, materialize, clearRuntimeImpl, applyError) {
|
|
1083
1204
|
const original = toManagedErrorPayload(applyError, 'MANAGED_RELOAD_FAILED');
|
|
1084
1205
|
try {
|
|
1085
1206
|
if (previousSpec) {
|
|
1207
|
+
await restoreManagedRuntimeSettingsSnapshot(rootPath, previousSettingsSnapshot);
|
|
1086
1208
|
await materialize(rootPath, cloneLocalConfigGenerateSpec(previousSpec));
|
|
1087
1209
|
}
|
|
1088
1210
|
else {
|
|
@@ -1139,8 +1261,6 @@ function validateDaemonUpsertAgentInput(currentSpec, serverUrl, agent, env = pro
|
|
|
1139
1261
|
}
|
|
1140
1262
|
export async function describeManagedSpec(options, deps = {}) {
|
|
1141
1263
|
const effectiveProcessEnv = options.processEnv ?? process.env;
|
|
1142
|
-
const loadSpec = deps.loadSpec
|
|
1143
|
-
?? ((hostConfigPath) => loadLocalConfigGenerateSpec(hostConfigPath, { env: effectiveProcessEnv }));
|
|
1144
1264
|
const sendRequest = deps.sendRequest ?? sendManagedDaemonRequest;
|
|
1145
1265
|
const resolved = resolveManagedRuntimeLayoutForServerUrl(options.serverUrl, options.processEnv);
|
|
1146
1266
|
try {
|
|
@@ -1167,7 +1287,12 @@ export async function describeManagedSpec(options, deps = {}) {
|
|
|
1167
1287
|
}
|
|
1168
1288
|
}
|
|
1169
1289
|
try {
|
|
1170
|
-
const
|
|
1290
|
+
const currentRuntimeSettings = await resolveAuthoritativeManagedRuntimeSettings(resolved.rootPath, effectiveProcessEnv);
|
|
1291
|
+
const persistedSpec = await loadManagedSpecOrUndefined(resolved.hostConfigPath, (hostConfigPath) => deps.loadSpec
|
|
1292
|
+
? deps.loadSpec(hostConfigPath)
|
|
1293
|
+
: loadLocalConfigGenerateSpec(hostConfigPath, {
|
|
1294
|
+
env: currentRuntimeSettings.processEnv,
|
|
1295
|
+
}));
|
|
1171
1296
|
if (!persistedSpec) {
|
|
1172
1297
|
return { ok: true, present: false };
|
|
1173
1298
|
}
|
|
@@ -1207,27 +1332,13 @@ async function applySpecToRunningManagedDaemon(rootPath, borgeeBaseUrl, spec, se
|
|
|
1207
1332
|
}
|
|
1208
1333
|
export async function applyManagedSpec(options, deps = {}) {
|
|
1209
1334
|
const effectiveProcessEnv = options.processEnv ?? process.env;
|
|
1210
|
-
const
|
|
1211
|
-
?? ((hostConfigPath) => loadLocalConfigGenerateSpec(hostConfigPath, { env: effectiveProcessEnv }));
|
|
1212
|
-
const materialize = deps.materialize
|
|
1213
|
-
?? ((rootPath, spec) => materializeLocalConfig(rootPath, spec, { env: effectiveProcessEnv }));
|
|
1335
|
+
const desiredSettings = resolveDesiredManagedRuntimeSettings(effectiveProcessEnv);
|
|
1214
1336
|
const sendRequest = deps.sendRequest ?? sendManagedDaemonRequest;
|
|
1215
1337
|
const spawnDaemonProcess = deps.spawnDaemon ?? spawnManagedDaemonProcess;
|
|
1216
1338
|
const waitForDaemon = deps.waitForDaemonReady ?? waitForManagedDaemonReady;
|
|
1217
1339
|
const acquireLock = deps.acquireBootstrapLock ?? acquireBootstrapLock;
|
|
1218
1340
|
const clearManagedRuntimeImpl = deps.clearManagedRuntime ?? clearManagedRuntime;
|
|
1219
1341
|
const resolved = resolveManagedRuntimeLayoutForServerUrl(options.serverUrl, options.processEnv);
|
|
1220
|
-
let spec;
|
|
1221
|
-
try {
|
|
1222
|
-
spec = validateApplyManagedInput(options.spec, options.serverUrl, effectiveProcessEnv);
|
|
1223
|
-
}
|
|
1224
|
-
catch (error) {
|
|
1225
|
-
if (isManagedOperationError(error)) {
|
|
1226
|
-
return toManagedErrorResponse(error);
|
|
1227
|
-
}
|
|
1228
|
-
return toManagedErrorResponse(managedOperationError('MANAGED_SPEC_INVALID', `Invalid managed spec: ${toErrorMessage(error)}`));
|
|
1229
|
-
}
|
|
1230
|
-
const desiredSettings = resolveDesiredManagedRuntimeSettings(effectiveProcessEnv);
|
|
1231
1342
|
const waitForShutdown = deps.waitForShutdown
|
|
1232
1343
|
?? (async (rootPath) => {
|
|
1233
1344
|
await waitForManagedDaemonShutdown(rootPath, canConnectToSocket);
|
|
@@ -1240,6 +1351,32 @@ export async function applyManagedSpec(options, deps = {}) {
|
|
|
1240
1351
|
return toApplyManagedColdStartErrorResponse(error);
|
|
1241
1352
|
}
|
|
1242
1353
|
try {
|
|
1354
|
+
const currentRuntimeSettings = await resolveAuthoritativeManagedRuntimeSettings(resolved.rootPath, effectiveProcessEnv);
|
|
1355
|
+
const loadSpecWithCurrentRuntimeEnv = (hostConfigPath) => deps.loadSpec
|
|
1356
|
+
? deps.loadSpec(hostConfigPath)
|
|
1357
|
+
: loadLocalConfigGenerateSpec(hostConfigPath, {
|
|
1358
|
+
env: currentRuntimeSettings.processEnv,
|
|
1359
|
+
});
|
|
1360
|
+
const materializeWithDesiredEnv = (rootPath, nextSpec) => deps.materialize
|
|
1361
|
+
? deps.materialize(rootPath, nextSpec)
|
|
1362
|
+
: materializeLocalConfig(rootPath, nextSpec, {
|
|
1363
|
+
env: effectiveProcessEnv,
|
|
1364
|
+
});
|
|
1365
|
+
const materializeWithCurrentRuntimeEnv = (rootPath, nextSpec) => deps.materialize
|
|
1366
|
+
? deps.materialize(rootPath, nextSpec)
|
|
1367
|
+
: materializeLocalConfig(rootPath, nextSpec, {
|
|
1368
|
+
env: currentRuntimeSettings.processEnv,
|
|
1369
|
+
});
|
|
1370
|
+
let spec;
|
|
1371
|
+
try {
|
|
1372
|
+
spec = validateApplyManagedInput(options.spec, options.serverUrl, effectiveProcessEnv);
|
|
1373
|
+
}
|
|
1374
|
+
catch (error) {
|
|
1375
|
+
if (isManagedOperationError(error)) {
|
|
1376
|
+
return toManagedErrorResponse(error);
|
|
1377
|
+
}
|
|
1378
|
+
return toManagedErrorResponse(managedOperationError('MANAGED_SPEC_INVALID', `Invalid managed spec: ${toErrorMessage(error)}`));
|
|
1379
|
+
}
|
|
1243
1380
|
let statusResponse;
|
|
1244
1381
|
try {
|
|
1245
1382
|
statusResponse = await readReadyManagedDaemonStatus(resolved.rootPath, sendRequest);
|
|
@@ -1250,7 +1387,8 @@ export async function applyManagedSpec(options, deps = {}) {
|
|
|
1250
1387
|
}
|
|
1251
1388
|
throw error;
|
|
1252
1389
|
}
|
|
1253
|
-
if (statusResponse
|
|
1390
|
+
if (statusResponse
|
|
1391
|
+
&& await getManagedRuntimeFingerprintMismatch(resolved.rootPath, statusResponse, desiredSettings)) {
|
|
1254
1392
|
try {
|
|
1255
1393
|
await recycleManagedDaemonWithDesiredSettings({
|
|
1256
1394
|
rootPath: resolved.rootPath,
|
|
@@ -1273,7 +1411,7 @@ export async function applyManagedSpec(options, deps = {}) {
|
|
|
1273
1411
|
}
|
|
1274
1412
|
let previousSpec;
|
|
1275
1413
|
try {
|
|
1276
|
-
previousSpec = await loadManagedSpecOrUndefined(resolved.hostConfigPath,
|
|
1414
|
+
previousSpec = await loadManagedSpecOrUndefined(resolved.hostConfigPath, loadSpecWithCurrentRuntimeEnv);
|
|
1277
1415
|
if (previousSpec) {
|
|
1278
1416
|
assertManagedSpecBinding(previousSpec, options.serverUrl);
|
|
1279
1417
|
}
|
|
@@ -1282,10 +1420,10 @@ export async function applyManagedSpec(options, deps = {}) {
|
|
|
1282
1420
|
return toApplyManagedColdStartErrorResponse(error);
|
|
1283
1421
|
}
|
|
1284
1422
|
try {
|
|
1285
|
-
await
|
|
1423
|
+
await materializeWithDesiredEnv(resolved.rootPath, cloneLocalConfigGenerateSpec(spec));
|
|
1286
1424
|
}
|
|
1287
1425
|
catch (error) {
|
|
1288
|
-
return rollbackManagedApplyFailure(resolved.rootPath, previousSpec,
|
|
1426
|
+
return rollbackManagedApplyFailure(resolved.rootPath, previousSpec, currentRuntimeSettings.persistedSettingsSnapshot ?? undefined, materializeWithCurrentRuntimeEnv, clearManagedRuntimeImpl, error);
|
|
1289
1427
|
}
|
|
1290
1428
|
try {
|
|
1291
1429
|
await startManagedDaemonWithPersistedSettings({
|
|
@@ -1300,7 +1438,7 @@ export async function applyManagedSpec(options, deps = {}) {
|
|
|
1300
1438
|
const status = await sendRequest(resolved.rootPath, { type: 'status' });
|
|
1301
1439
|
if (!status.ok) {
|
|
1302
1440
|
const managedError = getManagedErrorPayload(status);
|
|
1303
|
-
return rollbackManagedApplyFailure(resolved.rootPath, previousSpec,
|
|
1441
|
+
return rollbackManagedApplyFailure(resolved.rootPath, previousSpec, currentRuntimeSettings.persistedSettingsSnapshot ?? undefined, materializeWithCurrentRuntimeEnv, clearManagedRuntimeImpl, managedOperationError(managedError.code, managedError.message));
|
|
1304
1442
|
}
|
|
1305
1443
|
if (status.type !== 'status') {
|
|
1306
1444
|
throw new Error('Unexpected managed daemon response for status');
|
|
@@ -1314,7 +1452,7 @@ export async function applyManagedSpec(options, deps = {}) {
|
|
|
1314
1452
|
};
|
|
1315
1453
|
}
|
|
1316
1454
|
catch (error) {
|
|
1317
|
-
return rollbackManagedApplyFailure(resolved.rootPath, previousSpec,
|
|
1455
|
+
return rollbackManagedApplyFailure(resolved.rootPath, previousSpec, currentRuntimeSettings.persistedSettingsSnapshot ?? undefined, materializeWithCurrentRuntimeEnv, clearManagedRuntimeImpl, error);
|
|
1318
1456
|
}
|
|
1319
1457
|
}
|
|
1320
1458
|
finally {
|
|
@@ -1350,9 +1488,7 @@ export class ManagedAgentsHostDaemon {
|
|
|
1350
1488
|
this.loadSpec = deps.loadSpec ?? loadLocalConfigGenerateSpec;
|
|
1351
1489
|
this.materialize = deps.materialize ?? materializeLocalConfig;
|
|
1352
1490
|
const managedRuntimeSettings = resolveDesiredManagedRuntimeSettings(process.env);
|
|
1353
|
-
this.managedRuntimeFingerprint = managedRuntimeSettings.
|
|
1354
|
-
? managedRuntimeSettings.fingerprint
|
|
1355
|
-
: null;
|
|
1491
|
+
this.managedRuntimeFingerprint = managedRuntimeSettings.fingerprint;
|
|
1356
1492
|
this.logger = deps.logger ?? console;
|
|
1357
1493
|
this.logPath = deps.logPath ?? null;
|
|
1358
1494
|
this.server = createServer((socket) => {
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
export const HOST_CONTROL_PREFIX = '[[BORGEE_CONTROL]] ';
|
|
2
2
|
export const AWAITING_USER_CONTROL_PREFIX = HOST_CONTROL_PREFIX;
|
|
3
|
+
const VALID_ATTENTION_UPDATES = new Set([
|
|
4
|
+
'follow-channel',
|
|
5
|
+
'unfollow-channel',
|
|
6
|
+
'mute-channel',
|
|
7
|
+
'claim-channel',
|
|
8
|
+
'claim-task-thread',
|
|
9
|
+
'unclaim-channel',
|
|
10
|
+
'unclaim-task-thread',
|
|
11
|
+
]);
|
|
12
|
+
function isProviderAttentionUpdate(value) {
|
|
13
|
+
return typeof value === 'string' && VALID_ATTENTION_UPDATES.has(value);
|
|
14
|
+
}
|
|
3
15
|
function hasVisibleText(value) {
|
|
4
16
|
return value.trim().length > 0;
|
|
5
17
|
}
|
|
@@ -50,13 +62,26 @@ function parseControlPayload(payload) {
|
|
|
50
62
|
if (typeof record.kind !== 'string') {
|
|
51
63
|
return null;
|
|
52
64
|
}
|
|
65
|
+
const attentionUpdate = (() => {
|
|
66
|
+
if (record.attentionUpdate === undefined) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
return isProviderAttentionUpdate(record.attentionUpdate) ? record.attentionUpdate : null;
|
|
70
|
+
})();
|
|
71
|
+
if (attentionUpdate === null) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
53
74
|
if (record.kind === 'continue-to-peer' || record.kind === 'conclude-locally') {
|
|
54
|
-
return Object.keys(record).
|
|
55
|
-
? {
|
|
75
|
+
return Object.keys(record).every((key) => key === 'kind' || key === 'attentionUpdate')
|
|
76
|
+
? {
|
|
77
|
+
kind: record.kind,
|
|
78
|
+
...(attentionUpdate ? { attentionUpdate } : {}),
|
|
79
|
+
}
|
|
56
80
|
: null;
|
|
57
81
|
}
|
|
58
82
|
if (record.kind === 'start-protocol') {
|
|
59
|
-
return
|
|
83
|
+
return attentionUpdate === undefined
|
|
84
|
+
&& Object.keys(record).length === 2
|
|
60
85
|
&& typeof record.rounds === 'number'
|
|
61
86
|
&& Number.isInteger(record.rounds)
|
|
62
87
|
&& record.rounds > 0
|
|
@@ -68,7 +93,7 @@ function parseControlPayload(payload) {
|
|
|
68
93
|
}
|
|
69
94
|
if (record.kind === 'awaiting-user') {
|
|
70
95
|
const keys = Object.keys(record);
|
|
71
|
-
if (keys.some((key) => key !== 'kind' && key !== 'question' && key !== 'reason')) {
|
|
96
|
+
if (keys.some((key) => key !== 'kind' && key !== 'question' && key !== 'reason' && key !== 'attentionUpdate')) {
|
|
72
97
|
return null;
|
|
73
98
|
}
|
|
74
99
|
if (typeof record.question !== 'string' || record.question.trim().length === 0) {
|
|
@@ -82,8 +107,17 @@ function parseControlPayload(payload) {
|
|
|
82
107
|
kind: 'awaiting-user',
|
|
83
108
|
question: record.question.trim(),
|
|
84
109
|
...(typeof record.reason === 'string' ? { reason: record.reason.trim() } : {}),
|
|
110
|
+
...(attentionUpdate ? { attentionUpdate } : {}),
|
|
85
111
|
};
|
|
86
112
|
}
|
|
113
|
+
if (record.kind === 'attention-only') {
|
|
114
|
+
return Object.keys(record).length === 2 && attentionUpdate
|
|
115
|
+
? {
|
|
116
|
+
kind: 'attention-only',
|
|
117
|
+
attentionUpdate,
|
|
118
|
+
}
|
|
119
|
+
: null;
|
|
120
|
+
}
|
|
87
121
|
return null;
|
|
88
122
|
}
|
|
89
123
|
export function parseProviderReply(text) {
|
|
@@ -98,8 +132,15 @@ export function parseProviderReply(text) {
|
|
|
98
132
|
controlMalformed: true,
|
|
99
133
|
};
|
|
100
134
|
}
|
|
135
|
+
const textWithoutFooter = stripTrailingCarriageReturn(match.analyzedText.slice(0, match.removalStart));
|
|
136
|
+
if (control.kind === 'attention-only' && !hasVisibleText(textWithoutFooter)) {
|
|
137
|
+
return {
|
|
138
|
+
text: textWithoutFooter,
|
|
139
|
+
controlMalformed: true,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
101
142
|
return {
|
|
102
|
-
text:
|
|
143
|
+
text: textWithoutFooter,
|
|
103
144
|
control,
|
|
104
145
|
...(control.kind === 'awaiting-user'
|
|
105
146
|
? {
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { basename } from 'node:path';
|
|
2
|
+
import { buildAttentionSummaryLines } from '../../context/attention.js';
|
|
3
|
+
import { buildCollaborationCapabilityDeclarationSummaryLines, buildMissedCollaborationDiagnosticSummaryLines, } from '../../context/collaboration-capabilities-diagnostics.js';
|
|
4
|
+
import { buildCollaborationOutcomeSummaryLines } from '../../context/collaboration-outcome.js';
|
|
5
|
+
import { buildTaskThreadCollaborationSummaryLines } from '../../context/task-thread-collaboration.js';
|
|
2
6
|
const PROJECT_DOC_MAX_BYTES = 32 * 1024;
|
|
3
7
|
function buildSkillRuntimeLines(context) {
|
|
4
8
|
if (!context?.skillRuntime || !context.channelContextPayloadPath) {
|
|
@@ -47,6 +51,26 @@ export function buildCodexProjectDocument(context) {
|
|
|
47
51
|
'That writable task workspace is local to agents-host for the current task thread and does not imply that the target repository has already been checked out there.',
|
|
48
52
|
]
|
|
49
53
|
: []),
|
|
54
|
+
...(() => {
|
|
55
|
+
const collaborationOutcomeLines = buildCollaborationOutcomeSummaryLines(context?.collaborationOutcome);
|
|
56
|
+
return collaborationOutcomeLines.length > 0 ? ['', ...collaborationOutcomeLines] : [];
|
|
57
|
+
})(),
|
|
58
|
+
...(() => {
|
|
59
|
+
const attentionLines = buildAttentionSummaryLines(context?.attentionSnapshot);
|
|
60
|
+
return attentionLines.length > 0 ? ['', ...attentionLines] : [];
|
|
61
|
+
})(),
|
|
62
|
+
...(() => {
|
|
63
|
+
const capabilityLines = buildCollaborationCapabilityDeclarationSummaryLines(context?.collaborationCapabilities);
|
|
64
|
+
return capabilityLines.length > 0 ? ['', ...capabilityLines] : [];
|
|
65
|
+
})(),
|
|
66
|
+
...(() => {
|
|
67
|
+
const diagnosticLines = buildMissedCollaborationDiagnosticSummaryLines(context?.missedCollaborationDiagnostic);
|
|
68
|
+
return diagnosticLines.length > 0 ? ['', ...diagnosticLines] : [];
|
|
69
|
+
})(),
|
|
70
|
+
...(() => {
|
|
71
|
+
const taskThreadLines = buildTaskThreadCollaborationSummaryLines(context?.taskThreadCollaborationContract);
|
|
72
|
+
return taskThreadLines.length > 0 ? ['', ...taskThreadLines] : [];
|
|
73
|
+
})(),
|
|
50
74
|
...(() => {
|
|
51
75
|
const skillRuntimeLines = buildSkillRuntimeLines(context);
|
|
52
76
|
return skillRuntimeLines.length > 0 ? ['', ...skillRuntimeLines] : [];
|
package/dist/state-paths.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export declare function resolveAgentCursorPath(stateRootDir: string, agentId: st
|
|
|
11
11
|
export declare function resolveSharedProtocolKickoffDecisionPath(stateRootDir: string, channelId: string, anchorMessageId: string): string;
|
|
12
12
|
export declare function resolveSharedProtocolStatusPath(stateRootDir: string, channelId: string, anchorMessageId: string): string;
|
|
13
13
|
export declare function resolveConnectionsStatePath(stateRootDir: string): string;
|
|
14
|
+
export declare function resolveAttentionStatePath(stateRootDir: string, channelId: string): string;
|
|
14
15
|
export declare function resolveAuthorizationAuditPath(stateRootDir: string): string;
|
|
15
16
|
export declare function resolvePreviousAuthorizationAuditPath(stateRootDir: string): string;
|
|
16
17
|
export declare function resolveClaudeSessionMapPath(stateRootDir: string, agentId: string): string;
|
package/dist/state-paths.js
CHANGED
|
@@ -110,6 +110,9 @@ export function resolveSharedProtocolStatusPath(stateRootDir, channelId, anchorM
|
|
|
110
110
|
export function resolveConnectionsStatePath(stateRootDir) {
|
|
111
111
|
return join(stateRootDir, 'connections-state.sqlite');
|
|
112
112
|
}
|
|
113
|
+
export function resolveAttentionStatePath(stateRootDir, channelId) {
|
|
114
|
+
return join(stateRootDir, 'attention-state', `${encodeSegment(channelId)}.json`);
|
|
115
|
+
}
|
|
113
116
|
export function resolveAuthorizationAuditPath(stateRootDir) {
|
|
114
117
|
return join(stateRootDir, 'authorization-audit.jsonl');
|
|
115
118
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -140,6 +140,83 @@ export interface CollaborationDraftSnapshot {
|
|
|
140
140
|
finalMessageId?: string;
|
|
141
141
|
}
|
|
142
142
|
export type ProviderCollaborationTurnMode = 'ordinary' | 'silent-kickoff' | 'protocol-managed';
|
|
143
|
+
export type CollaborationOutcomeResponseState = 'responded' | 'blocked' | 'superseded' | 'failed';
|
|
144
|
+
export type CollaborationOutcomeDeliveryState = 'posted' | 'draft-finalized' | 'not-delivered' | 'delivery-failed';
|
|
145
|
+
export type CollaborationOutcomeWakeState = 'waiting' | 'suppressed-agent' | 'resumed-human';
|
|
146
|
+
export interface CollaborationOutcomeBlockedDetails {
|
|
147
|
+
question: string;
|
|
148
|
+
reason?: string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Shared host-side projection only. This is the latest host-observed snapshot
|
|
152
|
+
* that adapters may surface back to providers; it is not provider-authoritative
|
|
153
|
+
* truth about collaboration state or recovery.
|
|
154
|
+
*/
|
|
155
|
+
export interface CollaborationOutcomeSnapshot {
|
|
156
|
+
source: 'host-observed';
|
|
157
|
+
responseState: CollaborationOutcomeResponseState;
|
|
158
|
+
deliveryState: CollaborationOutcomeDeliveryState;
|
|
159
|
+
wakeState?: CollaborationOutcomeWakeState;
|
|
160
|
+
blockedDetails?: CollaborationOutcomeBlockedDetails;
|
|
161
|
+
observedAt: number;
|
|
162
|
+
turnExecutionId?: string;
|
|
163
|
+
}
|
|
164
|
+
export type AttentionDeliveryMode = 'default' | 'follow' | 'muted';
|
|
165
|
+
export type AttentionClaimState = 'unclaimed' | 'claimed';
|
|
166
|
+
export type AttentionClaimActivation = 'inactive' | 'active' | 'dormant';
|
|
167
|
+
export type AttentionWakeMode = 'current-policy' | 'follow-visible-human' | 'mute-non-mention';
|
|
168
|
+
export type ProviderAttentionUpdate = 'follow-channel' | 'unfollow-channel' | 'mute-channel' | 'claim-channel' | 'claim-task-thread' | 'unclaim-channel' | 'unclaim-task-thread';
|
|
169
|
+
export interface AttentionClaimContext {
|
|
170
|
+
scope: 'channel' | 'task-thread';
|
|
171
|
+
taskId: string;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Shared host-side projection only. This is the latest host-observed snapshot
|
|
175
|
+
* that adapters may surface back to providers; it is not server-authoritative
|
|
176
|
+
* truth about delivery policy, fanout, or ownership.
|
|
177
|
+
*/
|
|
178
|
+
export interface AttentionSnapshot {
|
|
179
|
+
source: 'host-observed';
|
|
180
|
+
deliveryMode: AttentionDeliveryMode;
|
|
181
|
+
claimState: AttentionClaimState;
|
|
182
|
+
claimActivation: AttentionClaimActivation;
|
|
183
|
+
wakeMode: AttentionWakeMode;
|
|
184
|
+
observedAt: number;
|
|
185
|
+
turnExecutionId?: string;
|
|
186
|
+
claimContext?: AttentionClaimContext;
|
|
187
|
+
}
|
|
188
|
+
export type TaskThreadCollaborationTurnRole = 'assignment' | 'continuation';
|
|
189
|
+
export type TaskThreadMainResultContract = 'ordinary-final-reply-in-thread';
|
|
190
|
+
export type TaskThreadAuxiliaryRouteContract = 'optional-auxiliary-send-or-escalation-only';
|
|
191
|
+
export type TaskThreadCheckInContract = 'status-update-intent-only';
|
|
192
|
+
export type TaskThreadBlockedWorkContract = 'in-thread-disclosure-only';
|
|
193
|
+
/**
|
|
194
|
+
* Shared host-side projection only. This is a narrow adapter-facing summary of
|
|
195
|
+
* task-thread collaboration meaning; it is not runtime-authoritative truth
|
|
196
|
+
* about task ownership, task routes, heartbeat execution, or blocked state.
|
|
197
|
+
*/
|
|
198
|
+
export interface TaskThreadCollaborationContract {
|
|
199
|
+
source: 'host-projected';
|
|
200
|
+
turnRole: TaskThreadCollaborationTurnRole;
|
|
201
|
+
taskThreadContextActive: true;
|
|
202
|
+
mainResult: TaskThreadMainResultContract;
|
|
203
|
+
auxiliaryRoute: TaskThreadAuxiliaryRouteContract;
|
|
204
|
+
checkIn: TaskThreadCheckInContract;
|
|
205
|
+
blockedWork: TaskThreadBlockedWorkContract;
|
|
206
|
+
}
|
|
207
|
+
export interface CollaborationCapabilityDeclaration {
|
|
208
|
+
collaborationOutcome?: true;
|
|
209
|
+
attentionSnapshot?: true;
|
|
210
|
+
taskThreadCollaborationContract?: true;
|
|
211
|
+
missedCollaborationDiagnostic?: true;
|
|
212
|
+
recoveryExplanation?: 'runtime-local-only';
|
|
213
|
+
}
|
|
214
|
+
export type MissedCollaborationDiagnosticStage = 'delivery' | 'wake' | 'response';
|
|
215
|
+
export type MissedCollaborationDiagnosticReason = 'delivery-failed' | 'not-delivered' | 'wake-suppressed-attention-policy' | 'blocked-awaiting-user';
|
|
216
|
+
export interface MissedCollaborationDiagnostic {
|
|
217
|
+
stage: MissedCollaborationDiagnosticStage;
|
|
218
|
+
reason: MissedCollaborationDiagnosticReason;
|
|
219
|
+
}
|
|
143
220
|
export interface ProviderCollaborationContext {
|
|
144
221
|
enabled: boolean;
|
|
145
222
|
turnExecutionId?: string;
|
|
@@ -158,6 +235,11 @@ export interface ProviderInput {
|
|
|
158
235
|
incomingEventKind?: string;
|
|
159
236
|
incomingMessageType?: string;
|
|
160
237
|
collaboration?: ProviderCollaborationContext;
|
|
238
|
+
collaborationOutcome?: CollaborationOutcomeSnapshot;
|
|
239
|
+
attentionSnapshot?: AttentionSnapshot;
|
|
240
|
+
taskThreadCollaborationContract?: TaskThreadCollaborationContract;
|
|
241
|
+
collaborationCapabilities?: CollaborationCapabilityDeclaration;
|
|
242
|
+
missedCollaborationDiagnostic?: MissedCollaborationDiagnostic;
|
|
161
243
|
}
|
|
162
244
|
export interface ProviderProtocolContext {
|
|
163
245
|
anchorMessageId: string;
|
|
@@ -210,6 +292,11 @@ export interface PreparedPromptContext {
|
|
|
210
292
|
gatewayAuthPath?: string;
|
|
211
293
|
collaborationTurnExecutionId?: string;
|
|
212
294
|
collaborationTurnMode?: ProviderCollaborationTurnMode;
|
|
295
|
+
collaborationOutcome?: CollaborationOutcomeSnapshot;
|
|
296
|
+
attentionSnapshot?: AttentionSnapshot;
|
|
297
|
+
taskThreadCollaborationContract?: TaskThreadCollaborationContract;
|
|
298
|
+
collaborationCapabilities?: CollaborationCapabilityDeclaration;
|
|
299
|
+
missedCollaborationDiagnostic?: MissedCollaborationDiagnostic;
|
|
213
300
|
kickoff?: ProviderProtocolKickoffContext;
|
|
214
301
|
protocol?: ProviderProtocolContext;
|
|
215
302
|
grounding?: ProviderTurnGroundingContext;
|
|
@@ -234,16 +321,22 @@ export interface ProviderAwaitingUser {
|
|
|
234
321
|
question: string;
|
|
235
322
|
reason?: string;
|
|
236
323
|
}
|
|
237
|
-
export
|
|
324
|
+
export interface ProviderTurnControlBase {
|
|
325
|
+
attentionUpdate?: ProviderAttentionUpdate;
|
|
326
|
+
}
|
|
327
|
+
export type ProviderTurnControl = ({
|
|
238
328
|
kind: 'continue-to-peer';
|
|
239
|
-
} | {
|
|
329
|
+
} & ProviderTurnControlBase) | ({
|
|
240
330
|
kind: 'conclude-locally';
|
|
241
|
-
} | {
|
|
331
|
+
} & ProviderTurnControlBase) | {
|
|
242
332
|
kind: 'start-protocol';
|
|
243
333
|
rounds: number;
|
|
244
334
|
} | ({
|
|
245
335
|
kind: 'awaiting-user';
|
|
246
|
-
} & ProviderAwaitingUser)
|
|
336
|
+
} & ProviderAwaitingUser & ProviderTurnControlBase) | ({
|
|
337
|
+
kind: 'attention-only';
|
|
338
|
+
attentionUpdate: ProviderAttentionUpdate;
|
|
339
|
+
} & ProviderTurnControlBase);
|
|
247
340
|
export interface ProviderReply {
|
|
248
341
|
text: string;
|
|
249
342
|
awaitingUser?: ProviderAwaitingUser;
|