maka-agent 0.2.0-dev.26.20260909 → 0.2.0-dev.27.20260910
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli-core.js +21 -0
- package/dist/runtime-host-cli.js +43 -3
- package/dist/runtime-host-handoff-surface.js +10 -8
- package/dist/runtime-host-lifecycle-transaction.js +28 -3
- package/dist/runtime-host-local-source-retirement.js +1 -1
- package/dist/runtime-host-setup-command.js +29 -6
- package/dist/runtime-host-update-command.js +49 -5
- package/dist/session-export-command.js +72 -0
- package/native/runtime-host-windows-task-launcher/prebuilds/win32-x64/maka-runtime-host-task-launcher.exe +0 -0
- package/node_modules/@maka/core/dist/usage-stats/types.js +2 -0
- package/node_modules/@maka/core/dist/workhub-routing.js +126 -0
- package/node_modules/@maka/core/package.json +2 -1
- package/node_modules/@maka/runtime/dist/ai-sdk-turn.js +7 -3
- package/node_modules/@maka/runtime/dist/builtin-tools.js +21 -2
- package/node_modules/@maka/runtime/dist/plugin-agent-service.js +131 -0
- package/node_modules/@maka/runtime/dist/plugin-approval-service.js +33 -0
- package/node_modules/@maka/runtime/dist/plugin-attachment-service.js +53 -0
- package/node_modules/@maka/runtime/dist/plugin-command-service.js +100 -0
- package/node_modules/@maka/runtime/dist/plugin-data-services.js +332 -0
- package/node_modules/@maka/runtime/dist/plugin-fs-service.js +62 -0
- package/node_modules/@maka/runtime/dist/plugin-goal-service.js +61 -0
- package/node_modules/@maka/runtime/dist/plugin-invocation-signal.js +24 -0
- package/node_modules/@maka/runtime/dist/plugin-llm-service.js +85 -0
- package/node_modules/@maka/runtime/dist/plugin-lsp-service.js +94 -0
- package/node_modules/@maka/runtime/dist/plugin-scope-registry.js +91 -0
- package/node_modules/@maka/runtime/dist/plugin-session-query-service.js +71 -0
- package/node_modules/@maka/runtime/dist/plugin-shell-env-service.js +87 -0
- package/node_modules/@maka/runtime/dist/plugin-shell-service.js +74 -0
- package/node_modules/@maka/runtime/dist/plugin-skill-service.js +93 -0
- package/node_modules/@maka/runtime/dist/plugin-system-prompt-service.js +346 -0
- package/node_modules/@maka/runtime/dist/plugin-tool-service.js +18 -52
- package/node_modules/@maka/runtime/dist/plugin-user-question-service.js +43 -0
- package/node_modules/@maka/runtime/dist/plugin-web-service.js +69 -0
- package/node_modules/@maka/runtime/dist/session-export.js +177 -0
- package/node_modules/@maka/runtime/package.json +18 -0
- package/node_modules/@maka/runtime-host/dist/client/host-handoff-copy.js +67 -18
- package/node_modules/@maka/runtime-host/dist/client/host-handoff.js +46 -12
- package/node_modules/@maka/runtime-host/dist/operator/setup-frame.js +31 -21
- package/node_modules/@maka/runtime-host/dist/protocol/index.js +9 -1
- package/node_modules/@maka/runtime-host/dist/protocol/plugin-platform.js +30 -5
- package/node_modules/@maka/runtime-host/dist/protocol/workhub-coordination.js +25 -23
- package/node_modules/@maka/runtime-host/dist/server/client-capability-coordinator.js +62 -4
- package/node_modules/@maka/runtime-host/dist/server/execution-composition.js +452 -7
- package/node_modules/@maka/runtime-host/dist/server/execution-model-authority.js +74 -0
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-recovery.js +2 -2
- package/node_modules/@maka/runtime-host/dist/server/hosted-execution-tool-profile.js +30 -0
- package/node_modules/@maka/runtime-host/dist/server/interactive-run-composer.js +79 -16
- package/node_modules/@maka/runtime-host/dist/server/message-coordinator.js +25 -4
- package/node_modules/@maka/runtime-host/dist/server/plugin-data-runtime.js +234 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform-coordinator.js +6 -0
- package/node_modules/@maka/runtime-host/dist/server/plugin-platform.js +12 -0
- package/node_modules/@maka/runtime-host/dist/server/root-turn-coordinator.js +189 -92
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-action-gate.js +44 -35
- package/node_modules/@maka/runtime-host/dist/server/workhub-coordination-coordinator.js +92 -10
- package/node_modules/@maka/storage/dist/agent-run-store.js +54 -10
- package/node_modules/@maka/storage/dist/context-offload-snapshot.js +13 -6
- package/node_modules/@maka/storage/dist/execution-stores.js +1 -1
- package/node_modules/@maka/storage/dist/session-bundle-policy.js +333 -30
- package/node_modules/@maka/storage/dist/session-store.js +2 -2
- package/node_modules/@maka/storage/dist/sqlite-session-metadata-store.js +12 -5
- package/node_modules/@maka/storage/package.json +2 -0
- package/package.json +1 -1
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import { copyWorkHubAttachmentsToTarget } from './workhub-message-attachments.js';
|
|
20
20
|
import { createHash, randomUUID } from 'node:crypto';
|
|
21
|
-
import { MAX_READ_IMAGE_BYTES } from '@maka/core/attachments';
|
|
21
|
+
import { attachmentKindFromMimeType, MAX_READ_IMAGE_BYTES } from '@maka/core/attachments';
|
|
22
22
|
import { messageContentDigest, normalizeMessageContent } from '@maka/core/events';
|
|
23
23
|
import { NO_REAL_CONNECTION_CODE } from '@maka/core/connection-error-copy';
|
|
24
24
|
import { generalizedErrorMessage } from '@maka/core/redaction';
|
|
@@ -31,6 +31,7 @@ import { AgentGraphSupervisorWakeCoordinator } from '@maka/runtime/agent-graph-s
|
|
|
31
31
|
import { BackendRegistry, SessionManager, workHubDirectStopAbortSource, } from '@maka/runtime/session-manager';
|
|
32
32
|
import { buildToolsForAgentDefinition } from '@maka/runtime/agent-catalog';
|
|
33
33
|
import { buildHistoryTools } from '@maka/runtime/history-tools';
|
|
34
|
+
import { buildBuiltinTools } from '@maka/runtime/builtin-tools';
|
|
34
35
|
import { createLocalContinuationSafetyInspector } from '@maka/runtime/continuation-safety';
|
|
35
36
|
import { createConfiguredSubagentCatalog } from '@maka/runtime/configured-subagent-catalog';
|
|
36
37
|
import { buildHostCapabilitiesFromBinding } from '@maka/runtime/skills';
|
|
@@ -45,8 +46,24 @@ import { SessionActivityRegistry } from '@maka/runtime/goal-turn-lifecycle';
|
|
|
45
46
|
import { ShellRunProcessManager } from '@maka/runtime/shell-run-manager';
|
|
46
47
|
import { resolveShellPlan, resolveTurnShellPlan, validateShellPreference, } from '@maka/runtime/shell-detect';
|
|
47
48
|
import { Context } from '@maka/runtime/plugin-kernel';
|
|
49
|
+
import { PluginAgentService } from '@maka/runtime/plugin-agent-service';
|
|
50
|
+
import { PluginAttachmentService } from '@maka/runtime/plugin-attachment-service';
|
|
51
|
+
import { PluginApprovalService } from '@maka/runtime/plugin-approval-service';
|
|
52
|
+
import { PluginFilesystemService } from '@maka/runtime/plugin-fs-service';
|
|
53
|
+
import { PluginLlmService } from '@maka/runtime/plugin-llm-service';
|
|
54
|
+
import { PluginShellService } from '@maka/runtime/plugin-shell-service';
|
|
55
|
+
import { PluginUserQuestionService } from '@maka/runtime/plugin-user-question-service';
|
|
56
|
+
import { PluginWebService } from '@maka/runtime/plugin-web-service';
|
|
48
57
|
import { MakaCompositionLoader } from '@maka/runtime/plugin-composition-loader';
|
|
49
58
|
import { PluginToolService } from '@maka/runtime/plugin-tool-service';
|
|
59
|
+
import { PluginSystemPromptService } from '@maka/runtime/plugin-system-prompt-service';
|
|
60
|
+
import { PluginCommandService } from '@maka/runtime/plugin-command-service';
|
|
61
|
+
import { PluginAuthorizationService, PluginCredentialService, PluginSettingsService, PluginStorageService, } from '@maka/runtime/plugin-data-services';
|
|
62
|
+
import { PluginGoalService } from '@maka/runtime/plugin-goal-service';
|
|
63
|
+
import { PluginLspService } from '@maka/runtime/plugin-lsp-service';
|
|
64
|
+
import { PluginSessionQueryService } from '@maka/runtime/plugin-session-query-service';
|
|
65
|
+
import { PluginShellEnvService } from '@maka/runtime/plugin-shell-env-service';
|
|
66
|
+
import { PluginSkillService } from '@maka/runtime/plugin-skill-service';
|
|
50
67
|
import { isHostedExecutionTerminal } from './hosted-execution-authority.js';
|
|
51
68
|
import { createAgentGraphControlStore } from '@maka/storage/agent-graph-control-store';
|
|
52
69
|
import { createArtifactAttachmentResourceReader } from '@maka/storage/artifact-stores';
|
|
@@ -59,6 +76,7 @@ import { createInteractiveContextOffloadReader } from '@maka/storage/context-off
|
|
|
59
76
|
import { openStorageWriterComposition } from '@maka/storage/storage-writer-composition';
|
|
60
77
|
import { resolveWorkspaceIdentity } from '@maka/storage/workspace-identity';
|
|
61
78
|
import { CanonicalSessionProjectionReader } from './canonical-session-projection.js';
|
|
79
|
+
import { HostPluginDataRuntime } from './plugin-data-runtime.js';
|
|
62
80
|
import { bindHostChildAgentBackend, createHostChildAgentToolComposition, } from './child-agent-composition.js';
|
|
63
81
|
import { HostCanonicalPermissionOutcomeReader } from './canonical-permission-outcome-reader.js';
|
|
64
82
|
import { HostArtifactCoordinator } from './artifact-coordinator.js';
|
|
@@ -75,7 +93,7 @@ import { HostDeepResearchCoordinator } from './deep-research-coordinator.js';
|
|
|
75
93
|
import { HostDailyReviewCoordinator } from './daily-review-coordinator.js';
|
|
76
94
|
import { prepareHostAiSdkBackend } from './execution-model-composition.js';
|
|
77
95
|
import { createInteractiveRunComposer, createInteractiveRunComposerFactory, routeInteractiveRunToolSurface, } from './interactive-run-composer.js';
|
|
78
|
-
import { createHostGoalEvaluator, createHostDailyReviewModel, createHostMemoryExtractionModel, createHostSessionEffectModel, } from './execution-model-authority.js';
|
|
96
|
+
import { createHostGoalEvaluator, createHostDailyReviewModel, createHostMemoryExtractionModel, createHostPluginModel, createHostSessionEffectModel, } from './execution-model-authority.js';
|
|
79
97
|
import { HostExecutionInspectCoordinator } from './execution-inspect-coordinator.js';
|
|
80
98
|
import { HostExternalSessionCoordinator } from './external-session-coordinator.js';
|
|
81
99
|
import { HostGoalCoordinator } from './goal-coordinator.js';
|
|
@@ -88,7 +106,7 @@ import { HostInteractionCoordinator } from './interaction-coordinator.js';
|
|
|
88
106
|
import { HostInteractiveTurnCoordinator } from './interactive-turn-coordinator.js';
|
|
89
107
|
import { SessionTurnAccessRequestCoordinator } from './session-turn-access-request-coordinator.js';
|
|
90
108
|
import { ensureBootstrapRuntimePolicy } from './bootstrap-runtime-policy.js';
|
|
91
|
-
import { hostedExecutionRunProfile } from './hosted-execution-tool-profile.js';
|
|
109
|
+
import { bindWorkHubRoutingDecisionPrompt, hostedExecutionRunProfile, } from './hosted-execution-tool-profile.js';
|
|
92
110
|
import { HostMemoryCoordinator } from './memory-coordinator.js';
|
|
93
111
|
import { HostMemoryExtractionCoordinator } from './memory-extraction-coordinator.js';
|
|
94
112
|
import { MemoryExtractionSessionLane } from './memory-extraction-session-lane.js';
|
|
@@ -177,10 +195,35 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
177
195
|
let archiveEvidence;
|
|
178
196
|
try {
|
|
179
197
|
const pluginRoot = new Context();
|
|
180
|
-
const
|
|
198
|
+
const pluginAgents = new PluginAgentService(pluginRoot);
|
|
199
|
+
const pluginAttachments = new PluginAttachmentService(pluginRoot, pluginAgents);
|
|
200
|
+
new PluginApprovalService(pluginRoot, pluginAgents);
|
|
201
|
+
new PluginUserQuestionService(pluginRoot, pluginAgents);
|
|
202
|
+
const pluginFilesystem = new PluginFilesystemService(pluginRoot, pluginAgents);
|
|
203
|
+
const pluginLlm = new PluginLlmService(pluginRoot, pluginAgents);
|
|
204
|
+
const pluginShellEnv = new PluginShellEnvService(pluginRoot);
|
|
205
|
+
const pluginShell = new PluginShellService(pluginRoot, pluginAgents, pluginShellEnv);
|
|
206
|
+
const pluginWeb = new PluginWebService(pluginRoot, pluginAgents);
|
|
207
|
+
const pluginSessionQuery = new PluginSessionQueryService(pluginRoot, pluginAgents);
|
|
208
|
+
const pluginGoals = new PluginGoalService(pluginRoot, pluginAgents);
|
|
209
|
+
const pluginSkills = new PluginSkillService(pluginRoot);
|
|
210
|
+
const pluginCommands = new PluginCommandService(pluginRoot);
|
|
211
|
+
new PluginLspService(pluginRoot);
|
|
212
|
+
const pluginSettings = new PluginSettingsService(pluginRoot);
|
|
213
|
+
const pluginStorage = new PluginStorageService(pluginRoot);
|
|
214
|
+
const pluginCredentials = new PluginCredentialService(pluginRoot);
|
|
215
|
+
new PluginAuthorizationService(pluginRoot, pluginCredentials);
|
|
216
|
+
const pluginData = new HostPluginDataRuntime(context.owner.controlDirectory);
|
|
217
|
+
pluginSettings.bindRuntime(pluginData);
|
|
218
|
+
pluginStorage.bindRuntime(pluginData);
|
|
219
|
+
pluginCredentials.bindRuntime(pluginData);
|
|
220
|
+
const pluginTools = new PluginToolService(pluginRoot, { agents: pluginAgents });
|
|
221
|
+
const pluginSystemPrompt = new PluginSystemPromptService(pluginRoot);
|
|
181
222
|
pluginPlatform = new HostPluginPlatform(context.owner.controlDirectory, {
|
|
182
223
|
composition: new MakaCompositionLoader({ root: pluginRoot }),
|
|
183
224
|
tools: pluginTools,
|
|
225
|
+
systemPrompt: pluginSystemPrompt,
|
|
226
|
+
commands: pluginCommands,
|
|
184
227
|
});
|
|
185
228
|
const pluginPlatformCoordinator = new HostPluginPlatformCoordinator(pluginPlatform);
|
|
186
229
|
const openedProjectCatalog = storage.projectCatalog;
|
|
@@ -323,12 +366,94 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
323
366
|
...(sandboxManager ? { sandboxManager } : {}),
|
|
324
367
|
...(filesystemWorker ? { filesystemWorker } : {}),
|
|
325
368
|
};
|
|
369
|
+
const invokeBuiltin = async (name, args, invocation, shellEnvironment) => {
|
|
370
|
+
if (!invocation.toolContext)
|
|
371
|
+
throw new Error(`${name} requires an active Tool invocation`);
|
|
372
|
+
const policy = await runtimePolicyStores.runtimePolicy.getSnapshot();
|
|
373
|
+
const tool = buildBuiltinTools({
|
|
374
|
+
...builtinTools,
|
|
375
|
+
shell: resolveTurnShellPlan(policy.policy.shell),
|
|
376
|
+
...(shellEnvironment ? { shellEnvironment } : {}),
|
|
377
|
+
}).find((candidate) => candidate.name === name);
|
|
378
|
+
if (!tool)
|
|
379
|
+
throw new Error(`Builtin capability is unavailable: ${name}`);
|
|
380
|
+
return tool.impl(args, invocation.toolContext);
|
|
381
|
+
};
|
|
382
|
+
pluginFilesystem.bindRuntime({
|
|
383
|
+
execute: (operation, invocation) => {
|
|
384
|
+
switch (operation.kind) {
|
|
385
|
+
case 'read':
|
|
386
|
+
return invokeBuiltin('Read', operation, invocation);
|
|
387
|
+
case 'write':
|
|
388
|
+
return invokeBuiltin('Write', operation, invocation);
|
|
389
|
+
case 'edit':
|
|
390
|
+
return invokeBuiltin('Edit', {
|
|
391
|
+
path: operation.path,
|
|
392
|
+
old_string: operation.oldString,
|
|
393
|
+
new_string: operation.newString,
|
|
394
|
+
}, invocation);
|
|
395
|
+
case 'glob':
|
|
396
|
+
return invokeBuiltin('Glob', { pattern: operation.pattern, cwd: operation.path }, invocation);
|
|
397
|
+
case 'grep':
|
|
398
|
+
return invokeBuiltin('Grep', { pattern: operation.pattern, path: operation.path, glob: operation.glob }, invocation);
|
|
399
|
+
case 'apply_patch':
|
|
400
|
+
return invokeBuiltin('apply_patch', operation.patch, invocation);
|
|
401
|
+
}
|
|
402
|
+
},
|
|
403
|
+
});
|
|
404
|
+
pluginShell.bindRuntime({
|
|
405
|
+
run: (options, invocation) => invokeBuiltin('Bash', {
|
|
406
|
+
command: options.command,
|
|
407
|
+
timeout_ms: options.timeoutMs,
|
|
408
|
+
run_in_background: options.background,
|
|
409
|
+
pty: options.pty,
|
|
410
|
+
}, invocation, options.environment),
|
|
411
|
+
read: (ref, invocation) => runtimeResources.readRuntimeResource(invocation.sessionId, ref, invocation.abortSignal),
|
|
412
|
+
write: (ref, input, invocation) => runtimeResources.writeStdin({
|
|
413
|
+
sessionId: invocation.sessionId,
|
|
414
|
+
ref,
|
|
415
|
+
input,
|
|
416
|
+
abortSignal: invocation.abortSignal,
|
|
417
|
+
caller: 'model',
|
|
418
|
+
}),
|
|
419
|
+
stop: (ref, invocation) => runtimeResources.stopBackgroundTask(invocation.sessionId, ref, invocation.abortSignal),
|
|
420
|
+
});
|
|
421
|
+
pluginAttachments.bindRuntime({
|
|
422
|
+
create: async (input, invocation) => {
|
|
423
|
+
const record = await openedArtifactStore.create({
|
|
424
|
+
sessionId: invocation.sessionId,
|
|
425
|
+
turnId: invocation.turnId,
|
|
426
|
+
name: input.name,
|
|
427
|
+
kind: pluginAttachmentArtifactKind(input.mimeType, input.name),
|
|
428
|
+
content: input.content,
|
|
429
|
+
mimeType: input.mimeType,
|
|
430
|
+
source: 'tool_result',
|
|
431
|
+
...(input.summary ? { summary: input.summary } : {}),
|
|
432
|
+
});
|
|
433
|
+
return pluginAttachmentRef(record);
|
|
434
|
+
},
|
|
435
|
+
read: async (attachment, invocation) => {
|
|
436
|
+
if (attachment.ref.kind !== 'session_file' ||
|
|
437
|
+
attachment.ref.sessionId !== invocation.sessionId) {
|
|
438
|
+
throw new Error('Attachment is outside the current Session');
|
|
439
|
+
}
|
|
440
|
+
const result = await openedArtifactStore.readBinaryInSession(invocation.sessionId, attachment.ref.relativePath);
|
|
441
|
+
if (!result.ok)
|
|
442
|
+
throw new Error(`Attachment read failed: ${result.reason}`);
|
|
443
|
+
return Uint8Array.from(Buffer.from(result.base64, 'base64'));
|
|
444
|
+
},
|
|
445
|
+
list: async (invocation) => (await openedArtifactStore.listTurnArtifacts(invocation.sessionId, invocation.turnId)).map(pluginAttachmentRef),
|
|
446
|
+
});
|
|
326
447
|
const webSearchService = createHostWebSearchService({
|
|
327
448
|
policy: runtimePolicyStores.operations,
|
|
328
449
|
});
|
|
329
450
|
const webFetchService = createHostWebFetchService({
|
|
330
451
|
policy: runtimePolicyStores.operations,
|
|
331
452
|
});
|
|
453
|
+
pluginWeb.bindRuntime({
|
|
454
|
+
search: ({ query, limit, abortSignal }) => webSearchService.search({ query, limit, ...(abortSignal ? { abortSignal } : {}) }),
|
|
455
|
+
fetch: (input) => webFetchService.fetch(input),
|
|
456
|
+
});
|
|
332
457
|
const historyTools = buildHistoryTools({
|
|
333
458
|
listSessions: () => requireSessionManager(manager).listSessions(),
|
|
334
459
|
readMessages: async (sessionId, abortSignal) => {
|
|
@@ -394,6 +519,7 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
394
519
|
publish: (sessionId) => hostChanges.publishSessionCatalog(sessionId),
|
|
395
520
|
}, projectMembership, context.requestDrain, new HostProjectDirectoryAuthority(options.projectDirectoryRoots));
|
|
396
521
|
let rootCoordinator;
|
|
522
|
+
let workHubCoordination;
|
|
397
523
|
let canonicalProjection;
|
|
398
524
|
let memory;
|
|
399
525
|
let clientCapabilities;
|
|
@@ -473,6 +599,7 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
473
599
|
let recoveryTask;
|
|
474
600
|
let rootCloseTask;
|
|
475
601
|
let rootRecoveryCompleted = false;
|
|
602
|
+
let clientBoundRecovery = Promise.resolve();
|
|
476
603
|
let closeTask;
|
|
477
604
|
let backendInvalidationPoisoned = false;
|
|
478
605
|
let domainModules;
|
|
@@ -539,6 +666,7 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
539
666
|
oauthCredentials,
|
|
540
667
|
createRunComposer: createInteractiveRunComposerFactory({
|
|
541
668
|
skills,
|
|
669
|
+
pluginSkills,
|
|
542
670
|
memory: requireMemory(memory),
|
|
543
671
|
sessionTodo,
|
|
544
672
|
clientCapabilities: requireClientCapabilities(clientCapabilities),
|
|
@@ -551,9 +679,29 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
551
679
|
hostTools,
|
|
552
680
|
resolveRootTools: (sessionId) => requireGraphCoordinator(graphCoordinator).toolsForSession(sessionId),
|
|
553
681
|
resolvePluginTools: (sessionId, coreTools) => pluginTools.resolveContributions(sessionId, coreTools),
|
|
682
|
+
resolvePluginSystemPrompt: async (sessionId, promptContext, baseText) => {
|
|
683
|
+
const assembly = await pluginSystemPrompt.assemble({
|
|
684
|
+
sessionId,
|
|
685
|
+
turnId: promptContext.turnId,
|
|
686
|
+
cwd: promptContext.cwd,
|
|
687
|
+
}, baseText);
|
|
688
|
+
return {
|
|
689
|
+
text: assembly.text,
|
|
690
|
+
contexts: assembly.contexts,
|
|
691
|
+
sourceRevisions: assembly.sourceRevision ? [assembly.sourceRevision] : [],
|
|
692
|
+
};
|
|
693
|
+
},
|
|
554
694
|
parentAgentTools: childAgentTools.parentTools,
|
|
555
695
|
childTools: childAgentTools.childTools,
|
|
556
696
|
worktreePatchWriteBackAvailable: true,
|
|
697
|
+
resolveProfileSystemPrompt: async (promptContext, basePrompt) => {
|
|
698
|
+
if (promptContext.sessionId !== WORKHUB_COORDINATION_SESSION_ID)
|
|
699
|
+
return basePrompt;
|
|
700
|
+
const admission = await stores.agentRunStore.readRootTurnAdmission(promptContext.sessionId, promptContext.turnId);
|
|
701
|
+
return bindWorkHubRoutingDecisionPrompt(basePrompt, admission?.execution.kind === 'workhub_coordination'
|
|
702
|
+
? admission.execution.routingDecision
|
|
703
|
+
: undefined);
|
|
704
|
+
},
|
|
557
705
|
}),
|
|
558
706
|
...(hostedExecutionRunProfile(backendContext.header.toolProfile)?.memoryExtraction === false
|
|
559
707
|
? {}
|
|
@@ -927,8 +1075,229 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
927
1075
|
}, {
|
|
928
1076
|
currentGraphId: (rootSessionId) => requireGraphCoordinator(graphCoordinator).currentGraphId(rootSessionId),
|
|
929
1077
|
beginNextGraphEpoch: async (rootSessionId) => (await requireGraphCoordinator(graphCoordinator).beginNextGraphEpoch(rootSessionId, (operation) => requireGraphSupervisorWake(graphSupervisorWake).runWithSessionWakesSuppressed(rootSessionId, operation, 'agent_graph_epoch_advanced'))).graphId,
|
|
930
|
-
}, (input) => sessionEffectCoordinator.nameSessionFromRootMessage(input), context.owner.capability.rootId
|
|
1078
|
+
}, (input) => sessionEffectCoordinator.nameSessionFromRootMessage(input), context.owner.capability.rootId, dependencies.workHubRoutingModel
|
|
1079
|
+
? (input) => workHubCoordination.prepareRoutingDecision(input)
|
|
1080
|
+
: undefined);
|
|
931
1081
|
const coordinator = rootCoordinator;
|
|
1082
|
+
const pluginModel = createHostPluginModel({
|
|
1083
|
+
runtimePolicy: runtimePolicyStores,
|
|
1084
|
+
oauthCredentials,
|
|
1085
|
+
usage: openedUsageStores,
|
|
1086
|
+
requestDrain: context.requestDrain,
|
|
1087
|
+
readSessionHeader: (sessionId) => stores.sessionStore.readHeaderSnapshot(sessionId),
|
|
1088
|
+
});
|
|
1089
|
+
pluginLlm.bindRuntime({
|
|
1090
|
+
generate: (input, invocation) => pluginModel.generate({
|
|
1091
|
+
sessionId: invocation.sessionId,
|
|
1092
|
+
prompt: input.prompt,
|
|
1093
|
+
...(input.system ? { system: input.system } : {}),
|
|
1094
|
+
...(input.maxOutputTokens ? { maxOutputTokens: input.maxOutputTokens } : {}),
|
|
1095
|
+
abortSignal: input.signal ?? invocation.abortSignal,
|
|
1096
|
+
}),
|
|
1097
|
+
});
|
|
1098
|
+
const visibleAgentSessions = async (initiator) => {
|
|
1099
|
+
const sessions = await manager.listSessions();
|
|
1100
|
+
if (!initiator)
|
|
1101
|
+
return [];
|
|
1102
|
+
const visible = new Set([initiator.sessionId]);
|
|
1103
|
+
let changed = true;
|
|
1104
|
+
while (changed) {
|
|
1105
|
+
changed = false;
|
|
1106
|
+
for (const session of sessions) {
|
|
1107
|
+
if (!session.parentSessionId ||
|
|
1108
|
+
!visible.has(session.parentSessionId) ||
|
|
1109
|
+
visible.has(session.id))
|
|
1110
|
+
continue;
|
|
1111
|
+
visible.add(session.id);
|
|
1112
|
+
changed = true;
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
return sessions.filter((session) => visible.has(session.id));
|
|
1116
|
+
};
|
|
1117
|
+
const pluginSessionSummary = (session) => Object.freeze({
|
|
1118
|
+
id: session.id,
|
|
1119
|
+
...(session.name ? { title: session.name } : {}),
|
|
1120
|
+
...(session.cwd ? { cwd: session.cwd } : {}),
|
|
1121
|
+
...(session.status ? { status: session.status } : {}),
|
|
1122
|
+
...(session.parentSessionId ? { parentSessionId: session.parentSessionId } : {}),
|
|
1123
|
+
...(session.statusUpdatedAt || session.lastMessageAt
|
|
1124
|
+
? { updatedAt: session.statusUpdatedAt ?? session.lastMessageAt }
|
|
1125
|
+
: {}),
|
|
1126
|
+
});
|
|
1127
|
+
const sessionQueryInitiator = (caller) => caller.invocation ??
|
|
1128
|
+
(caller.scopeSessionId ? Object.freeze({ sessionId: caller.scopeSessionId }) : undefined);
|
|
1129
|
+
pluginSessionQuery.bindRuntime({
|
|
1130
|
+
list: async (caller) => Object.freeze((await visibleAgentSessions(sessionQueryInitiator(caller))).map(pluginSessionSummary)),
|
|
1131
|
+
read: async (sessionId, caller) => {
|
|
1132
|
+
const session = (await visibleAgentSessions(sessionQueryInitiator(caller))).find(({ id }) => id === sessionId);
|
|
1133
|
+
if (!session)
|
|
1134
|
+
return undefined;
|
|
1135
|
+
return Object.freeze({
|
|
1136
|
+
session: pluginSessionSummary(session),
|
|
1137
|
+
messages: Object.freeze([
|
|
1138
|
+
...(await requireSessionManager(manager).getMessages(sessionId)),
|
|
1139
|
+
]),
|
|
1140
|
+
});
|
|
1141
|
+
},
|
|
1142
|
+
search: async (request, caller) => {
|
|
1143
|
+
const query = request.query.toLocaleLowerCase();
|
|
1144
|
+
const sessions = await visibleAgentSessions(sessionQueryInitiator(caller));
|
|
1145
|
+
const matches = [];
|
|
1146
|
+
for (const session of sessions) {
|
|
1147
|
+
const headerText = `${session.name}\n${session.cwd ?? ''}`.toLocaleLowerCase();
|
|
1148
|
+
if (headerText.includes(query)) {
|
|
1149
|
+
matches.push(session);
|
|
1150
|
+
continue;
|
|
1151
|
+
}
|
|
1152
|
+
const messages = await requireSessionManager(manager).getMessages(session.id);
|
|
1153
|
+
if (messages.some((message) => JSON.stringify(message).toLocaleLowerCase().includes(query))) {
|
|
1154
|
+
matches.push(session);
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
const offset = request.cursor ? Number.parseInt(request.cursor, 10) : 0;
|
|
1158
|
+
if (!Number.isSafeInteger(offset) || offset < 0)
|
|
1159
|
+
throw new TypeError('Invalid Session query cursor');
|
|
1160
|
+
const limit = request.limit ?? 20;
|
|
1161
|
+
const page = matches.slice(offset, offset + limit);
|
|
1162
|
+
return Object.freeze({
|
|
1163
|
+
items: Object.freeze(page.map(pluginSessionSummary)),
|
|
1164
|
+
...(offset + page.length < matches.length
|
|
1165
|
+
? { cursor: String(offset + page.length) }
|
|
1166
|
+
: {}),
|
|
1167
|
+
});
|
|
1168
|
+
},
|
|
1169
|
+
});
|
|
1170
|
+
const describeAgent = (session) => ({
|
|
1171
|
+
id: session.id,
|
|
1172
|
+
sessionId: session.id,
|
|
1173
|
+
root: !session.parentSessionId,
|
|
1174
|
+
status: session.runningTurnIds?.length ? 'running' : session.status,
|
|
1175
|
+
...(session.parentSessionId ? { ownerId: session.parentSessionId } : {}),
|
|
1176
|
+
});
|
|
1177
|
+
const submitAgentMessage = async (id, message, placement, initiator) => {
|
|
1178
|
+
if (!(await visibleAgentSessions(initiator)).some((session) => session.id === id)) {
|
|
1179
|
+
throw new Error('Agent is outside the current ownership tree');
|
|
1180
|
+
}
|
|
1181
|
+
const content = normalizeMessageContent(typeof message === 'string' ? { text: message } : message);
|
|
1182
|
+
const result = await messages.handlers['turn.message.submit']({
|
|
1183
|
+
originHostEpoch: context.hostEpoch,
|
|
1184
|
+
sessionId: id,
|
|
1185
|
+
messageId: randomUUID(),
|
|
1186
|
+
content,
|
|
1187
|
+
placement,
|
|
1188
|
+
}, {
|
|
1189
|
+
hostEpoch: context.hostEpoch,
|
|
1190
|
+
connectionId: 'plugin-agent',
|
|
1191
|
+
principal: 'runtime_host',
|
|
1192
|
+
acquireResidency: () => context.acquireResidency('plugin-agent'),
|
|
1193
|
+
});
|
|
1194
|
+
if (!result.ok)
|
|
1195
|
+
throw new Error(result.error.message);
|
|
1196
|
+
return result.result;
|
|
1197
|
+
};
|
|
1198
|
+
pluginAgents.bindRuntime({
|
|
1199
|
+
create: async (options, initiator) => {
|
|
1200
|
+
const spawn = initiator.toolContext?.spawnChildSession;
|
|
1201
|
+
if (!spawn)
|
|
1202
|
+
throw new Error('Agent creation requires an active Tool invocation');
|
|
1203
|
+
if (!options.prompt?.trim())
|
|
1204
|
+
throw new Error('Agent creation requires a prompt');
|
|
1205
|
+
return new Promise((resolve, reject) => {
|
|
1206
|
+
void spawn({
|
|
1207
|
+
agentProfile: options.agentProfile ?? 'implementation',
|
|
1208
|
+
prompt: options.prompt,
|
|
1209
|
+
...(options.signal ? { abortSignal: options.signal } : {}),
|
|
1210
|
+
onReady: (ready) => resolve({
|
|
1211
|
+
id: ready.childSessionId,
|
|
1212
|
+
sessionId: ready.childSessionId,
|
|
1213
|
+
root: false,
|
|
1214
|
+
status: 'running',
|
|
1215
|
+
ownerId: initiator.sessionId,
|
|
1216
|
+
}),
|
|
1217
|
+
}).catch(reject);
|
|
1218
|
+
});
|
|
1219
|
+
},
|
|
1220
|
+
resume: async (options, initiator) => {
|
|
1221
|
+
if (options.prompt)
|
|
1222
|
+
await submitAgentMessage(options.sessionId, options.prompt, 'next_turn', initiator);
|
|
1223
|
+
const session = (await visibleAgentSessions(initiator)).find((item) => item.id === options.sessionId);
|
|
1224
|
+
if (!session)
|
|
1225
|
+
throw new Error('Agent was not found');
|
|
1226
|
+
return describeAgent(session);
|
|
1227
|
+
},
|
|
1228
|
+
get: async (id, initiator) => {
|
|
1229
|
+
const session = (await visibleAgentSessions(initiator)).find((item) => item.id === id);
|
|
1230
|
+
return session ? describeAgent(session) : undefined;
|
|
1231
|
+
},
|
|
1232
|
+
list: async (initiator) => (await visibleAgentSessions(initiator)).map(describeAgent),
|
|
1233
|
+
roots: async (initiator) => (await visibleAgentSessions(initiator))
|
|
1234
|
+
.filter((session) => !session.parentSessionId)
|
|
1235
|
+
.map(describeAgent),
|
|
1236
|
+
followup: (id, message, initiator) => submitAgentMessage(id, message, 'next_turn', initiator),
|
|
1237
|
+
steer: (id, message, initiator) => submitAgentMessage(id, message, 'current_turn', initiator),
|
|
1238
|
+
inject: (id, message, initiator) => submitAgentMessage(id, message, 'current_turn', initiator),
|
|
1239
|
+
cancel: async (id, initiator) => {
|
|
1240
|
+
if (!(await visibleAgentSessions(initiator)).some((session) => session.id === id)) {
|
|
1241
|
+
throw new Error('Agent is outside the current ownership tree');
|
|
1242
|
+
}
|
|
1243
|
+
await coordinator.stopSession(id, { source: 'stop_button' });
|
|
1244
|
+
},
|
|
1245
|
+
whenIdle: async (id, signal, initiator) => {
|
|
1246
|
+
if (!(await visibleAgentSessions(initiator)).some((session) => session.id === id)) {
|
|
1247
|
+
throw new Error('Agent is outside the current ownership tree');
|
|
1248
|
+
}
|
|
1249
|
+
const wait = coordinator.whenIdle(id);
|
|
1250
|
+
if (!wait)
|
|
1251
|
+
return;
|
|
1252
|
+
if (!signal)
|
|
1253
|
+
return wait;
|
|
1254
|
+
if (signal.aborted)
|
|
1255
|
+
throw signal.reason;
|
|
1256
|
+
let rejectAbort;
|
|
1257
|
+
const aborted = new Promise((_resolve, reject) => {
|
|
1258
|
+
rejectAbort = reject;
|
|
1259
|
+
});
|
|
1260
|
+
const onAbort = () => rejectAbort?.(signal.reason);
|
|
1261
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
1262
|
+
try {
|
|
1263
|
+
await Promise.race([wait, aborted]);
|
|
1264
|
+
}
|
|
1265
|
+
finally {
|
|
1266
|
+
signal.removeEventListener('abort', onAbort);
|
|
1267
|
+
}
|
|
1268
|
+
},
|
|
1269
|
+
snapshot: async (id, initiator) => {
|
|
1270
|
+
const session = (await visibleAgentSessions(initiator)).find((item) => item.id === id);
|
|
1271
|
+
if (!session)
|
|
1272
|
+
throw new Error('Agent was not found');
|
|
1273
|
+
return { agent: describeAgent(session), root: coordinator.readRootState(id) };
|
|
1274
|
+
},
|
|
1275
|
+
inbox: async (id, initiator) => {
|
|
1276
|
+
if (!(await visibleAgentSessions(initiator)).some((session) => session.id === id))
|
|
1277
|
+
throw new Error('Agent was not found');
|
|
1278
|
+
return coordinator.readRootState(id);
|
|
1279
|
+
},
|
|
1280
|
+
result: async (id, initiator) => {
|
|
1281
|
+
if (!(await visibleAgentSessions(initiator)).some((session) => session.id === id))
|
|
1282
|
+
throw new Error('Agent was not found');
|
|
1283
|
+
return (await manager.getMessages(id)).at(-1);
|
|
1284
|
+
},
|
|
1285
|
+
artifacts: async (id, initiator) => {
|
|
1286
|
+
if (!(await visibleAgentSessions(initiator)).some((session) => session.id === id))
|
|
1287
|
+
throw new Error('Agent was not found');
|
|
1288
|
+
return (await openedArtifactStore.listPage(id, { offset: 0, limit: 100 })).records;
|
|
1289
|
+
},
|
|
1290
|
+
transcript: async (id, initiator) => {
|
|
1291
|
+
if (!(await visibleAgentSessions(initiator)).some((session) => session.id === id))
|
|
1292
|
+
throw new Error('Agent was not found');
|
|
1293
|
+
return manager.getMessages(id);
|
|
1294
|
+
},
|
|
1295
|
+
dispose: async (id, initiator) => {
|
|
1296
|
+
if (!(await visibleAgentSessions(initiator)).some((session) => session.id === id))
|
|
1297
|
+
throw new Error('Agent was not found');
|
|
1298
|
+
await coordinator.stopSession(id, { source: 'stop_button' });
|
|
1299
|
+
},
|
|
1300
|
+
});
|
|
932
1301
|
const contextOperations = new HostContextCoordinator({
|
|
933
1302
|
runtime: manager,
|
|
934
1303
|
executions: coordinator,
|
|
@@ -1032,6 +1401,34 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
1032
1401
|
onProjectionChanged: (sessionId) => continuityCoordinator.enqueueCanonicalRefresh(sessionId),
|
|
1033
1402
|
requestDrain: context.requestDrain,
|
|
1034
1403
|
});
|
|
1404
|
+
pluginGoals.bindRuntime({
|
|
1405
|
+
execute: async (operation, invocation) => {
|
|
1406
|
+
const coordinator = requireGoal(goal);
|
|
1407
|
+
if (operation.kind === 'get')
|
|
1408
|
+
return coordinator.readProjection(invocation.sessionId);
|
|
1409
|
+
if (!invocation.toolContext)
|
|
1410
|
+
throw new Error('Goal mutation requires an active Tool invocation');
|
|
1411
|
+
const toolName = operation.kind === 'create'
|
|
1412
|
+
? 'GoalSet'
|
|
1413
|
+
: operation.kind === 'clear'
|
|
1414
|
+
? 'GoalClear'
|
|
1415
|
+
: operation.kind === 'pause'
|
|
1416
|
+
? 'GoalPause'
|
|
1417
|
+
: 'GoalResume';
|
|
1418
|
+
const tool = coordinator.tools.find(({ name }) => name === toolName);
|
|
1419
|
+
if (!tool)
|
|
1420
|
+
throw new Error(`Goal capability is unavailable: ${toolName}`);
|
|
1421
|
+
const args = operation.kind === 'create'
|
|
1422
|
+
? {
|
|
1423
|
+
condition: operation.objective,
|
|
1424
|
+
...(operation.maxIterations ? { max_iterations: operation.maxIterations } : {}),
|
|
1425
|
+
...(operation.blockCap ? { block_cap: operation.blockCap } : {}),
|
|
1426
|
+
...(operation.tokenBudget ? { token_budget: operation.tokenBudget } : {}),
|
|
1427
|
+
}
|
|
1428
|
+
: {};
|
|
1429
|
+
return await tool.impl(args, invocation.toolContext);
|
|
1430
|
+
},
|
|
1431
|
+
});
|
|
1035
1432
|
async function applyRuntimePolicyMutationEffects() {
|
|
1036
1433
|
try {
|
|
1037
1434
|
await requireMemory(memory).refreshAfterPolicyMutation();
|
|
@@ -1061,7 +1458,8 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
1061
1458
|
? { sessionAccessAuthority: context.sessionAccessAuthority }
|
|
1062
1459
|
: {}),
|
|
1063
1460
|
});
|
|
1064
|
-
|
|
1461
|
+
workHubCoordination = new HostWorkHubCoordinationCoordinator({
|
|
1462
|
+
routingModel: dependencies.workHubRoutingModel,
|
|
1065
1463
|
configureModel: (input) => sessionCatalog.configureWorkHubModel(input),
|
|
1066
1464
|
transitionConfiguration: (input) => requireSessionManager(manager).transitionSessionConfiguration(WORKHUB_COORDINATION_SESSION_ID, input),
|
|
1067
1465
|
stateRoot: context.owner.capability.canonicalPath,
|
|
@@ -1556,7 +1954,35 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
1556
1954
|
}),
|
|
1557
1955
|
createRuntimeHostDomainModule({
|
|
1558
1956
|
id: 'client-capability',
|
|
1559
|
-
handlers: [
|
|
1957
|
+
handlers: [
|
|
1958
|
+
{
|
|
1959
|
+
...clientCapabilities.handlers,
|
|
1960
|
+
'client.capability.replace': async (input, operationContext) => {
|
|
1961
|
+
const outcome = await clientCapabilities.handlers['client.capability.replace'](input, operationContext);
|
|
1962
|
+
if (outcome.ok && rootRecoveryCompleted && !draining) {
|
|
1963
|
+
// Registration completes outside the policy mutation gate before
|
|
1964
|
+
// recovery selects bindings or composes a backend. Serialize
|
|
1965
|
+
// reconnects and retain the task for the shutdown barrier.
|
|
1966
|
+
clientBoundRecovery = clientBoundRecovery.then(async () => {
|
|
1967
|
+
if (draining)
|
|
1968
|
+
return;
|
|
1969
|
+
await coordinator.recover();
|
|
1970
|
+
await messages.consumePendingAdmissions(recoverySessions
|
|
1971
|
+
.filter((session) => session.toolProfile === 'workhub-coordination-v2')
|
|
1972
|
+
.map((session) => session.id));
|
|
1973
|
+
});
|
|
1974
|
+
try {
|
|
1975
|
+
await clientBoundRecovery;
|
|
1976
|
+
}
|
|
1977
|
+
catch (error) {
|
|
1978
|
+
context.requestDrain();
|
|
1979
|
+
throw error;
|
|
1980
|
+
}
|
|
1981
|
+
}
|
|
1982
|
+
return outcome;
|
|
1983
|
+
},
|
|
1984
|
+
},
|
|
1985
|
+
],
|
|
1560
1986
|
recovery: {
|
|
1561
1987
|
resources: async () => {
|
|
1562
1988
|
await recoverClientCapabilityOutcomes(stores.runtimeEventStore, recoverySessions.map((session) => session.id));
|
|
@@ -1630,6 +2056,7 @@ export async function createExecutionRuntimeHostComposition(context, options = {
|
|
|
1630
2056
|
async () => {
|
|
1631
2057
|
if (!rootRecoveryCompleted || poisonFailure)
|
|
1632
2058
|
return;
|
|
2059
|
+
await clientBoundRecovery.catch(() => undefined);
|
|
1633
2060
|
rootCloseTask ??= coordinator.close();
|
|
1634
2061
|
await rootCloseTask;
|
|
1635
2062
|
},
|
|
@@ -2028,6 +2455,24 @@ function requireGoal(coordinator) {
|
|
|
2028
2455
|
throw new Error('Runtime Host Goal coordinator is not composed');
|
|
2029
2456
|
return coordinator;
|
|
2030
2457
|
}
|
|
2458
|
+
function pluginAttachmentArtifactKind(mimeType, name) {
|
|
2459
|
+
const kind = attachmentKindFromMimeType(mimeType, name);
|
|
2460
|
+
return kind === 'image' || kind === 'pdf' ? kind : 'file';
|
|
2461
|
+
}
|
|
2462
|
+
function pluginAttachmentRef(record) {
|
|
2463
|
+
const mimeType = record.mimeType ?? 'application/octet-stream';
|
|
2464
|
+
return {
|
|
2465
|
+
kind: attachmentKindFromMimeType(mimeType, record.name),
|
|
2466
|
+
name: record.name,
|
|
2467
|
+
mimeType,
|
|
2468
|
+
bytes: record.sizeBytes,
|
|
2469
|
+
ref: {
|
|
2470
|
+
kind: 'session_file',
|
|
2471
|
+
sessionId: record.sessionId,
|
|
2472
|
+
relativePath: record.relativePath,
|
|
2473
|
+
},
|
|
2474
|
+
};
|
|
2475
|
+
}
|
|
2031
2476
|
/** Every run this Session has opened, named by the event spine that defines it. */
|
|
2032
2477
|
async function sessionRunIds(runtimeEventStore, sessionId) {
|
|
2033
2478
|
return (await runtimeEventStore.listSessionInvocations(sessionId)).map((invocation) => invocation.runId);
|