@sema-agent/server 1.313.0 → 1.315.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/dist/approval-hmac.d.ts +17 -0
  2. package/dist/approval-hmac.js +27 -0
  3. package/dist/auth-bridge.d.ts +3 -2
  4. package/dist/bench/s1/live-deps.js +2 -2
  5. package/dist/budget.d.ts +4 -76
  6. package/dist/budget.js +4 -83
  7. package/dist/capabilities/sandbox-file-send.d.ts +2 -1
  8. package/dist/config-center/apply-effective.d.ts +22 -0
  9. package/dist/config-center/apply-effective.js +283 -0
  10. package/dist/config-center/http-client.d.ts +23 -0
  11. package/dist/config-center/http-client.js +109 -0
  12. package/dist/config-center/restart-signal.d.ts +12 -0
  13. package/dist/config-center/restart-signal.js +70 -0
  14. package/dist/config-center/skills-mcp.d.ts +13 -0
  15. package/dist/config-center/skills-mcp.js +113 -0
  16. package/dist/config-center/types.d.ts +143 -0
  17. package/dist/config-center/types.js +2 -0
  18. package/dist/config-types.d.ts +1 -1
  19. package/dist/elicitation.d.ts +5 -3
  20. package/dist/elicitation.js +3 -2
  21. package/dist/fleet/fleet-bus.js +92 -83
  22. package/dist/fleet-lease.d.ts +1 -1
  23. package/dist/fleet-lease.js +1 -1
  24. package/dist/hooks/hook-llm.d.ts +5 -4
  25. package/dist/hooks/hook-runner.d.ts +1 -1
  26. package/dist/hooks/hook-runner.js +19 -10
  27. package/dist/http/server.d.ts +95 -69
  28. package/dist/http/server.js +75 -86
  29. package/dist/index.d.ts +1 -1
  30. package/dist/key-resolver.d.ts +1 -1
  31. package/dist/key-resolver.js +1 -1
  32. package/dist/leader/grader-env-factory.d.ts +1 -1
  33. package/dist/leader/grader-env-factory.js +2 -2
  34. package/dist/leader/leader.js +5 -2
  35. package/dist/leader/wire.d.ts +1 -1
  36. package/dist/leader/wire.js +170 -166
  37. package/dist/main.js +487 -476
  38. package/dist/memory-scope.d.ts +18 -0
  39. package/dist/memory-scope.js +38 -0
  40. package/dist/observability/cost-taxonomy.d.ts +34 -0
  41. package/dist/observability/cost-taxonomy.js +26 -0
  42. package/dist/observability/prompt-manifest.d.ts +75 -0
  43. package/dist/observability/prompt-manifest.js +82 -0
  44. package/dist/plugins/checkpoint-store-sql.d.ts +67 -0
  45. package/dist/plugins/checkpoint-store-sql.js +224 -0
  46. package/dist/plugins/image-bake-store-sql.d.ts +53 -0
  47. package/dist/plugins/image-bake-store-sql.js +463 -0
  48. package/dist/plugins/k8s-bg-scripts.d.ts +19 -0
  49. package/dist/plugins/k8s-bg-scripts.js +129 -0
  50. package/dist/plugins/k8s-exec-protocol.d.ts +20 -0
  51. package/dist/plugins/k8s-exec-protocol.js +87 -0
  52. package/dist/plugins/pg-checkpoint-store.d.ts +1 -33
  53. package/dist/plugins/pg-checkpoint-store.js +1 -189
  54. package/dist/plugins/pg-cost-quota.js +3 -143
  55. package/dist/plugins/pg-image-bake.d.ts +1 -40
  56. package/dist/plugins/pg-image-bake.js +1 -420
  57. package/dist/plugins/pg-rate-limiter.d.ts +2 -32
  58. package/dist/plugins/pg-rate-limiter.js +4 -147
  59. package/dist/plugins/remote-env-k8s.d.ts +5 -38
  60. package/dist/plugins/remote-env-k8s.js +7 -213
  61. package/dist/plugins/sql-driver.d.ts +25 -0
  62. package/dist/plugins/sql-driver.js +59 -0
  63. package/dist/plugins/tidb-checkpoint-store.d.ts +1 -49
  64. package/dist/plugins/tidb-checkpoint-store.js +1 -191
  65. package/dist/plugins/tidb-image-bake.d.ts +1 -38
  66. package/dist/plugins/tidb-image-bake.js +1 -348
  67. package/dist/plugins/web-search.d.ts +4 -3
  68. package/dist/plugins/write-behind-counter.d.ts +14 -3
  69. package/dist/plugins/write-behind-counter.js +39 -12
  70. package/dist/principal-jwt.d.ts +44 -0
  71. package/dist/principal-jwt.js +95 -0
  72. package/dist/question.d.ts +2 -1
  73. package/dist/question.js +3 -2
  74. package/dist/run-local.js +2 -2
  75. package/dist/runtime-caps-resolver.d.ts +7 -7
  76. package/dist/runtime-caps-resolver.js +3 -3
  77. package/dist/security.d.ts +4 -74
  78. package/dist/security.js +6 -155
  79. package/dist/sema-registry.d.ts +5 -200
  80. package/dist/sema-registry.js +4 -567
  81. package/dist/tool-approval.d.ts +2 -1
  82. package/dist/tool-approval.js +3 -2
  83. package/package.json +1 -1
@@ -262,94 +262,78 @@ export function fleetBackgroundChildPublisher(bus, log) {
262
262
  return u.tokens;
263
263
  return undefined;
264
264
  };
265
- return (e) => {
266
- if (e.kind === "spawn") {
267
- const tomb = meta.get(e.taskId);
268
- const inheritParent = !e.parentTaskId && !e.parentSessionId && tomb?.done === true;
269
- const m = {
270
- ...(e.parentTaskId ? { parentTaskId: e.parentTaskId } : {}),
271
- ...(!e.parentTaskId && e.parentSessionId ? { parentSessionLink: e.parentSessionId } : {}),
272
- ...(inheritParent && tomb?.parentTaskId !== undefined ? { parentTaskId: tomb.parentTaskId } : {}),
273
- ...(inheritParent && tomb?.parentSessionLink !== undefined ? { parentSessionLink: tomb.parentSessionLink } : {}),
274
- ...(inheritParent && tomb?.resolvedParentId !== undefined ? { resolvedParentId: tomb.resolvedParentId } : {}),
275
- ...(e.sessionScoped && e.owner ? { hostSessionId: e.rootSessionId ?? e.owner } : {}),
276
- tenantScope: e.scope ?? "default",
277
- sessionScoped: e.sessionScoped,
278
- spawnedAt: e.startedAt ?? Date.now(),
279
- ...(e.rootSessionId ? { rootSessionId: e.rootSessionId } : {}),
280
- ...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}),
281
- ...(e.sessionId ? { aliasUuid: e.sessionId } : {}),
282
- ...(e.workflowRunId ? { workflowRunId: e.workflowRunId } : {}),
283
- ...(e.workflowRunId && !(e.sessionScoped && e.owner)
284
- ? (() => {
285
- if (e.rootSessionId)
286
- return { hostSessionId: e.rootSessionId };
287
- if (e.parentSessionId)
288
- return { hostSessionId: e.parentSessionId };
289
- const host = e.parentTaskId ? bus.snapshot().tasks.find((r) => r.id === e.parentTaskId && r.scope === (e.scope ?? "default")) : undefined;
290
- return host?.sessionId ? { hostSessionId: host.sessionId } : {};
291
- })()
292
- : {}),
293
- ...(!(e.sessionScoped && e.owner) && !e.workflowRunId && (e.rootSessionId ?? e.parentSessionId)
294
- ? (() => {
295
- if (e.rootSessionId)
296
- return { hostSessionId: e.rootSessionId };
297
- const childScope = e.scope ?? "default";
298
- for (const pm of meta.values()) {
299
- if (pm.aliasUuid === e.parentSessionId && (pm.tenantScope ?? "default") === childScope) {
300
- return pm.hostSessionId ? { hostSessionId: pm.hostSessionId } : {};
301
- }
302
- }
265
+ const handleSpawn = (e) => {
266
+ const tomb = meta.get(e.taskId);
267
+ const inheritParent = !e.parentTaskId && !e.parentSessionId && tomb?.done === true;
268
+ const m = {
269
+ ...(e.parentTaskId ? { parentTaskId: e.parentTaskId } : {}),
270
+ ...(!e.parentTaskId && e.parentSessionId ? { parentSessionLink: e.parentSessionId } : {}),
271
+ ...(inheritParent && tomb?.parentTaskId !== undefined ? { parentTaskId: tomb.parentTaskId } : {}),
272
+ ...(inheritParent && tomb?.parentSessionLink !== undefined ? { parentSessionLink: tomb.parentSessionLink } : {}),
273
+ ...(inheritParent && tomb?.resolvedParentId !== undefined ? { resolvedParentId: tomb.resolvedParentId } : {}),
274
+ ...(e.sessionScoped && e.owner ? { hostSessionId: e.rootSessionId ?? e.owner } : {}),
275
+ tenantScope: e.scope ?? "default",
276
+ sessionScoped: e.sessionScoped,
277
+ spawnedAt: e.startedAt ?? Date.now(),
278
+ ...(e.rootSessionId ? { rootSessionId: e.rootSessionId } : {}),
279
+ ...(e.parentToolCallId ? { parentToolCallId: e.parentToolCallId } : {}),
280
+ ...(e.sessionId ? { aliasUuid: e.sessionId } : {}),
281
+ ...(e.workflowRunId ? { workflowRunId: e.workflowRunId } : {}),
282
+ ...(e.workflowRunId && !(e.sessionScoped && e.owner)
283
+ ? (() => {
284
+ if (e.rootSessionId)
285
+ return { hostSessionId: e.rootSessionId };
286
+ if (e.parentSessionId)
303
287
  return { hostSessionId: e.parentSessionId };
304
- })()
305
- : {}),
306
- };
307
- remember(e.taskId, m);
308
- bus.publishTask({ id: e.taskId, name: redactSecrets(e.description ?? e.name ?? e.taskId), ...(e.agentType ? { agentType: redactSecrets(e.agentType) } : {}), ...rowTags(m), status: "running", tokens: 0, ...(e.transcriptId ? { transcriptId: e.transcriptId } : {}) });
309
- dlog("bg_child_event", { kind: "spawn", taskId: e.taskId, sessionScoped: e.sessionScoped, scope: m.tenantScope, hostSessionId: m.hostSessionId ?? null, parentTaskId: m.parentTaskId ?? null });
310
- return;
311
- }
312
- const m = meta.get(e.taskId) ?? { sessionScoped: e.sessionScoped, tenantScope: "default", spawnedAt: Date.now() };
313
- if (!meta.has(e.taskId)) {
314
- remember(e.taskId, m);
315
- dlog("bg_child_event", { kind: `${e.kind}-lazy-mint`, taskId: e.taskId, sessionScoped: e.sessionScoped });
316
- }
317
- else {
318
- remember(e.taskId, m);
319
- }
320
- if (m.done) {
321
- dlog("bg_child_event", { kind: `${e.kind}-after-terminal-ignored`, taskId: e.taskId });
322
- return;
323
- }
324
- if (m.parentToolCallId === undefined && e.parentToolCallId)
325
- m.parentToolCallId = e.parentToolCallId;
326
- if (e.kind === "tick") {
327
- if (!m.suppressedTwin && e.progressTaskId && (!e.progressParentTaskId || e.progressParentTaskId === (m.parentTaskId ?? m.parentSessionLink))) {
328
- const tail = ` ${e.progressTaskId}`;
329
- for (const row of bus.snapshot().tasks) {
330
- if (row.id.endsWith(tail))
331
- bus.removeTask(row.id);
332
- }
333
- m.suppressedTwin = true;
334
- }
335
- if (m.aliasUuid === undefined && e.progressTaskId && (!e.progressParentTaskId || e.progressParentTaskId === (m.parentTaskId ?? m.parentSessionLink))) {
336
- m.aliasUuid = e.progressTaskId;
337
- for (const [cid, cm] of meta) {
338
- if ((cm.parentTaskId ?? cm.parentSessionLink) === m.aliasUuid && cm.resolvedParentId === undefined && !cm.done) {
339
- bus.publishTask({ id: cid, ...rowTags(cm) });
288
+ const host = e.parentTaskId ? bus.snapshot().tasks.find((r) => r.id === e.parentTaskId && r.scope === (e.scope ?? "default")) : undefined;
289
+ return host?.sessionId ? { hostSessionId: host.sessionId } : {};
290
+ })()
291
+ : {}),
292
+ ...(!(e.sessionScoped && e.owner) && !e.workflowRunId && (e.rootSessionId ?? e.parentSessionId)
293
+ ? (() => {
294
+ if (e.rootSessionId)
295
+ return { hostSessionId: e.rootSessionId };
296
+ const childScope = e.scope ?? "default";
297
+ for (const pm of meta.values()) {
298
+ if (pm.aliasUuid === e.parentSessionId && (pm.tenantScope ?? "default") === childScope) {
299
+ return pm.hostSessionId ? { hostSessionId: pm.hostSessionId } : {};
300
+ }
340
301
  }
302
+ return { hostSessionId: e.parentSessionId };
303
+ })()
304
+ : {}),
305
+ };
306
+ remember(e.taskId, m);
307
+ bus.publishTask({ id: e.taskId, name: redactSecrets(e.description ?? e.name ?? e.taskId), ...(e.agentType ? { agentType: redactSecrets(e.agentType) } : {}), ...rowTags(m), status: "running", tokens: 0, ...(e.transcriptId ? { transcriptId: e.transcriptId } : {}) });
308
+ dlog("bg_child_event", { kind: "spawn", taskId: e.taskId, sessionScoped: e.sessionScoped, scope: m.tenantScope, hostSessionId: m.hostSessionId ?? null, parentTaskId: m.parentTaskId ?? null });
309
+ };
310
+ const handleTick = (e, m) => {
311
+ if (!m.suppressedTwin && e.progressTaskId && (!e.progressParentTaskId || e.progressParentTaskId === (m.parentTaskId ?? m.parentSessionLink))) {
312
+ const tail = ` ${e.progressTaskId}`;
313
+ for (const row of bus.snapshot().tasks) {
314
+ if (row.id.endsWith(tail))
315
+ bus.removeTask(row.id);
316
+ }
317
+ m.suppressedTwin = true;
318
+ }
319
+ if (m.aliasUuid === undefined && e.progressTaskId && (!e.progressParentTaskId || e.progressParentTaskId === (m.parentTaskId ?? m.parentSessionLink))) {
320
+ m.aliasUuid = e.progressTaskId;
321
+ for (const [cid, cm] of meta) {
322
+ if ((cm.parentTaskId ?? cm.parentSessionLink) === m.aliasUuid && cm.resolvedParentId === undefined && !cm.done) {
323
+ bus.publishTask({ id: cid, ...rowTags(cm) });
341
324
  }
342
325
  }
343
- const tokens = sumUsage(e.usage);
344
- const name = e.name ? redactSecrets(e.name) : undefined;
345
- const agentType = e.agentType ? redactSecrets(e.agentType) : name;
346
- const currentAction = e.currentAction ? redactSecrets(e.currentAction) : undefined;
347
- const currentTool = e.currentTool
348
- ? { toolName: e.currentTool.toolName, ...(e.currentTool.target !== undefined ? { target: redactSecrets(e.currentTool.target).slice(0, 300) } : {}) }
349
- : undefined;
350
- bus.publishTask({ id: e.taskId, ...rowTags(m), status: "running", ...(tokens !== undefined ? { tokens } : {}), ...(name ? { name } : {}), ...(agentType ? { agentType } : {}), ...(currentAction ? { currentAction } : {}), ...(currentTool ? { currentTool } : {}), ...(e.usage?.toolUses !== undefined ? { toolUses: e.usage.toolUses } : {}), ...(e.transcriptId ? { transcriptId: e.transcriptId } : {}) });
351
- return;
352
326
  }
327
+ const tokens = sumUsage(e.usage);
328
+ const name = e.name ? redactSecrets(e.name) : undefined;
329
+ const agentType = e.agentType ? redactSecrets(e.agentType) : name;
330
+ const currentAction = e.currentAction ? redactSecrets(e.currentAction) : undefined;
331
+ const currentTool = e.currentTool
332
+ ? { toolName: e.currentTool.toolName, ...(e.currentTool.target !== undefined ? { target: redactSecrets(e.currentTool.target).slice(0, 300) } : {}) }
333
+ : undefined;
334
+ bus.publishTask({ id: e.taskId, ...rowTags(m), status: "running", ...(tokens !== undefined ? { tokens } : {}), ...(name ? { name } : {}), ...(agentType ? { agentType } : {}), ...(currentAction ? { currentAction } : {}), ...(currentTool ? { currentTool } : {}), ...(e.usage?.toolUses !== undefined ? { toolUses: e.usage.toolUses } : {}), ...(e.transcriptId ? { transcriptId: e.transcriptId } : {}) });
335
+ };
336
+ const handleTerminal = (e, m) => {
353
337
  const status = e.status === "completed" ? "completed" : e.status === "killed" ? "killed" : "failed";
354
338
  bus.publishTask({
355
339
  id: e.taskId, ...rowTags(m), status,
@@ -420,6 +404,31 @@ export function fleetBackgroundChildPublisher(bus, log) {
420
404
  m.done = true;
421
405
  m.suppressedTwin = true;
422
406
  };
407
+ return (e) => {
408
+ if (e.kind === "spawn") {
409
+ handleSpawn(e);
410
+ return;
411
+ }
412
+ const m = meta.get(e.taskId) ?? { sessionScoped: e.sessionScoped, tenantScope: "default", spawnedAt: Date.now() };
413
+ if (!meta.has(e.taskId)) {
414
+ remember(e.taskId, m);
415
+ dlog("bg_child_event", { kind: `${e.kind}-lazy-mint`, taskId: e.taskId, sessionScoped: e.sessionScoped });
416
+ }
417
+ else {
418
+ remember(e.taskId, m);
419
+ }
420
+ if (m.done) {
421
+ dlog("bg_child_event", { kind: `${e.kind}-after-terminal-ignored`, taskId: e.taskId });
422
+ return;
423
+ }
424
+ if (m.parentToolCallId === undefined && e.parentToolCallId)
425
+ m.parentToolCallId = e.parentToolCallId;
426
+ if (e.kind === "tick") {
427
+ handleTick(e, m);
428
+ return;
429
+ }
430
+ handleTerminal(e, m);
431
+ };
423
432
  }
424
433
  export function fleetRunLabels(objective) {
425
434
  const oneLine = redactSecrets((objective ?? "").replace(/\s+/g, " ")).trim();
@@ -65,7 +65,7 @@ export declare class FleetLeaseManager {
65
65
  private issueOrRenew;
66
66
  private issueOrRenewInner;
67
67
  }
68
- export declare function buildFleetLeaseFromEnv(cfg: {
68
+ export declare function createFleetLeaseFromEnv(cfg: {
69
69
  configCenter?: {
70
70
  baseUrl: string;
71
71
  token: string;
@@ -115,7 +115,7 @@ export class FleetLeaseManager {
115
115
  }
116
116
  }
117
117
  }
118
- export function buildFleetLeaseFromEnv(cfg, opts) {
118
+ export function createFleetLeaseFromEnv(cfg, opts) {
119
119
  const cc = cfg.configCenter;
120
120
  if (!cc?.baseUrl || !cc.token || !cc.worker)
121
121
  return undefined;
@@ -11,6 +11,10 @@ export type HookModelPick = {
11
11
  ok: false;
12
12
  error: string;
13
13
  };
14
+ export interface HookLlm {
15
+ hookModelFor: (requested?: string) => HookModelPick;
16
+ hookLlm: HookLlmCall;
17
+ }
14
18
  export declare function createHookLlm(deps: {
15
19
  config: ServiceConfig;
16
20
  getKeyResolver: () => ((model: Model) => Promise<{
@@ -20,8 +24,5 @@ export declare function createHookLlm(deps: {
20
24
  inc: (name: string, labels?: Record<string, string>) => void;
21
25
  };
22
26
  fetchImpl?: typeof fetch;
23
- }): {
24
- hookModelFor: (requested?: string) => HookModelPick;
25
- hookLlm: HookLlmCall;
26
- };
27
+ }): HookLlm;
27
28
  //# sourceMappingURL=hook-llm.d.ts.map
@@ -49,6 +49,6 @@ export interface LlmHookExtra {
49
49
  system: string;
50
50
  transcript: string;
51
51
  }
52
- export declare function buildTaskHooks(config: HooksConfig, ctx: HookRunnerContext): Hooks | undefined;
52
+ export declare function createTaskHooks(config: HooksConfig, ctx: HookRunnerContext): Hooks | undefined;
53
53
  export declare function composeHooks(deployment: Hooks | undefined, task: Hooks): Hooks;
54
54
  //# sourceMappingURL=hook-runner.d.ts.map
@@ -494,7 +494,7 @@ async function runObserveOnlyEvent(event, groups, matchValue, payload, ctx, once
494
494
  }
495
495
  }
496
496
  }
497
- export function buildTaskHooks(config, ctx) {
497
+ export function createTaskHooks(config, ctx) {
498
498
  const configured = Object.keys(config).filter((e) => (config[e]?.length ?? 0) > 0);
499
499
  const dark = configured.filter((e) => HOOK_EVENT_OWNER[e] === "engine" && !LIT_EVENTS.includes(e));
500
500
  if (dark.length > 0) {
@@ -523,7 +523,7 @@ export function buildTaskHooks(config, ctx) {
523
523
  const onceFired = new Set();
524
524
  const hooks = {};
525
525
  if (pre) {
526
- hooks.preToolUse = async (toolName, input, tctx) => {
526
+ const preToolUseHook = async (toolName, input, tctx) => {
527
527
  let currentInput = input;
528
528
  let rewritten = false;
529
529
  let asked;
@@ -608,9 +608,10 @@ export function buildTaskHooks(config, ctx) {
608
608
  }
609
609
  return undefined;
610
610
  };
611
+ hooks.preToolUse = preToolUseHook;
611
612
  }
612
613
  if (post) {
613
- hooks.postToolUse = async (toolName, input, output, tctx) => {
614
+ const postToolUseHook = async (toolName, input, output, tctx) => {
614
615
  const contexts = [];
615
616
  const responseText = output.content
616
617
  .map((c) => (c && typeof c === "object" && typeof c.text === "string" ? c.text : ""))
@@ -657,9 +658,10 @@ export function buildTaskHooks(config, ctx) {
657
658
  }
658
659
  return contexts.length > 0 ? { additionalContext: contexts.join("\n") } : undefined;
659
660
  };
661
+ hooks.postToolUse = postToolUseHook;
660
662
  }
661
663
  if (postFailure) {
662
- hooks.postToolUseFailure = async (toolName, input, f, tctx) => {
664
+ const postToolUseFailureHook = async (toolName, input, f, tctx) => {
663
665
  const contexts = [];
664
666
  const payload = {
665
667
  ...basePayload(ctx),
@@ -700,9 +702,10 @@ export function buildTaskHooks(config, ctx) {
700
702
  }
701
703
  return contexts.length > 0 ? { additionalContext: contexts.join("\n") } : undefined;
702
704
  };
705
+ hooks.postToolUseFailure = postToolUseFailureHook;
703
706
  }
704
707
  if (postBatch) {
705
- hooks.postToolBatch = async (calls) => {
708
+ const postToolBatchHook = async (calls) => {
706
709
  const contexts = [];
707
710
  const payload = {
708
711
  ...basePayload(ctx),
@@ -740,9 +743,10 @@ export function buildTaskHooks(config, ctx) {
740
743
  }
741
744
  return contexts.length > 0 ? { additionalContext: contexts.join("\n") } : undefined;
742
745
  };
746
+ hooks.postToolBatch = postToolBatchHook;
743
747
  }
744
748
  if (promptSubmit) {
745
- hooks.userPromptSubmit = async (prompt) => {
749
+ const userPromptSubmitHook = async (prompt) => {
746
750
  const contexts = [];
747
751
  const payload = { ...basePayload(ctx), hook_event_name: "UserPromptSubmit", prompt: clip(prompt, MAX_TOOL_INPUT_CHARS) };
748
752
  const singles = await runMatchingEntries("UserPromptSubmit", ignoreMatchers(promptSubmit), "", payload, ctx, onceFired, Date.now() + MAX_HOOK_EVENT_TOTAL_SECONDS * 1000);
@@ -777,9 +781,10 @@ export function buildTaskHooks(config, ctx) {
777
781
  }
778
782
  return contexts.length > 0 ? { additionalContext: contexts.join("\n") } : undefined;
779
783
  };
784
+ hooks.userPromptSubmit = userPromptSubmitHook;
780
785
  }
781
786
  if (stopEntries) {
782
- hooks.stop = async (sctx) => {
787
+ const stopHook = async (sctx) => {
783
788
  const payload = { ...basePayload(ctx), hook_event_name: "Stop", stop_hook_active: sctx.stopHookActive };
784
789
  let llmExtra;
785
790
  const wantsPrompt = stopEntries.some((g) => g.hooks.some((h) => h.type === "prompt"));
@@ -867,9 +872,10 @@ export function buildTaskHooks(config, ctx) {
867
872
  ...(contexts.length ? { additionalContext: contexts.join("\n") } : {}),
868
873
  };
869
874
  };
875
+ hooks.stop = stopHook;
870
876
  }
871
877
  if (stopFailureEntries) {
872
- hooks.stopFailure = async (fctx) => {
878
+ const stopFailureHook = async (fctx) => {
873
879
  const turnError = toAssistantTurnError(fctx.errorKind);
874
880
  const payload = {
875
881
  ...basePayload(ctx),
@@ -879,9 +885,10 @@ export function buildTaskHooks(config, ctx) {
879
885
  };
880
886
  await runObserveOnlyEvent("StopFailure", stopFailureEntries, turnError, payload, ctx, onceFired);
881
887
  };
888
+ hooks.stopFailure = stopFailureHook;
882
889
  }
883
890
  if (preCompactEntries) {
884
- hooks.preCompact = async (pctx) => {
891
+ const preCompactHook = async (pctx) => {
885
892
  const payload = {
886
893
  ...basePayload(ctx),
887
894
  hook_event_name: "PreCompact",
@@ -911,9 +918,10 @@ export function buildTaskHooks(config, ctx) {
911
918
  }
912
919
  return undefined;
913
920
  };
921
+ hooks.preCompact = preCompactHook;
914
922
  }
915
923
  if (postCompactEntries) {
916
- hooks.postCompact = async (cctx) => {
924
+ const postCompactHook = async (cctx) => {
917
925
  const payload = {
918
926
  ...basePayload(ctx),
919
927
  hook_event_name: "PostCompact",
@@ -922,6 +930,7 @@ export function buildTaskHooks(config, ctx) {
922
930
  };
923
931
  await runObserveOnlyEvent("PostCompact", postCompactEntries, cctx.trigger, payload, ctx, onceFired);
924
932
  };
933
+ hooks.postCompact = postCompactHook;
925
934
  }
926
935
  return hooks;
927
936
  }
@@ -30,58 +30,59 @@ export interface RequestAuth {
30
30
  memoryScope?: string;
31
31
  resolvedProjectId?: string;
32
32
  }
33
- export interface ServiceDeps {
33
+ export interface ServiceCoreDeps {
34
34
  runner: Runner;
35
35
  config: ServiceConfig;
36
- registryJwtVerifier?: {
37
- verify: (bearer: string) => Promise<import("../auth-bridge.js").VerifyOutcome>;
38
- };
39
- hookWakeBus?: {
40
- deliver?: (sessionId: string, text: string) => Promise<boolean>;
41
- };
42
- drainState?: {
43
- draining: boolean;
44
- since?: number;
45
- inflight?: () => number;
46
- lastActivityAt?: () => number;
47
- };
48
- storeDegraded?: boolean;
49
- sessionStoreLabel?: string;
50
- modelReady?: () => boolean;
51
- scenarioDetails?: Record<string, import("../capabilities/scenarios.js").ScenarioDetail>;
52
- authorize?: (ctx: {
53
- req: IncomingMessage;
54
- body: TaskRequestBody;
55
- }) => Promise<RequestAuth>;
56
36
  resolveSpec: (body: TaskRequestBody, req: IncomingMessage | undefined, auth?: RequestAuth, opts?: {
57
37
  leg?: "fresh" | "resume";
58
38
  }) => TaskSpec | Promise<TaskSpec>;
39
+ }
40
+ export interface ServiceStoreDeps {
59
41
  runStore?: RunStore;
60
42
  resumeAnchorStore?: ResumeAnchorStore;
61
- sessionTitler?: {
62
- maybeTitle(sessionId: string, objective: string): void;
63
- };
43
+ approvalStore?: ApprovalStore;
64
44
  approvalExemptionStore?: ApprovalExemptionStore;
45
+ checkpointStore?: CheckpointStoreFull;
65
46
  sessionPolicyStore?: ServiceSessionPolicyStore;
66
47
  fileSnapshotStore?: ServiceFileSnapshotStore;
67
- snapshotBlobSqlCapBytes?: number;
68
- backend?: StoreBackend;
69
- sessionMirrorRuling?: (principal: string | undefined) => Promise<SessionMirrorRuling | undefined>;
70
- approvalStore?: ApprovalStore;
71
- checkpointStore?: CheckpointStoreFull;
72
- backgroundAgentStore?: import("@sema-agent/core").BackgroundAgentStore;
73
- parkedReviveTool?: import("@sema-agent/core").ToolSpec;
74
- parkedKnownAgentTypes?: ReadonlySet<string>;
75
- parkedReviveInheritedGate?: (row: import("@sema-agent/core").BackgroundAgentRecord) => unknown;
76
48
  taskAttachmentStore?: TaskAttachmentStore;
77
- imageIndex?: ImageIndex;
78
- imageBakes?: ImageBake;
79
- leaderEndpoint?: LeaderEndpoint;
49
+ backgroundAgentStore?: import("@sema-agent/core").BackgroundAgentStore;
50
+ sessionStorage?: OwnerAwareSessionStore;
80
51
  workflowRunStore?: WorkflowRunStore;
81
52
  workflowJournalStore?: import("@sema-agent/core").WorkflowJournalStore;
82
- workflowsCapable?: boolean;
53
+ imageIndex?: ImageIndex;
54
+ imageBakes?: ImageBake;
55
+ outcomeSink?: import("../plugins/file-outcome-sink.js").OutcomeSink;
56
+ sendFileLedger?: import("../plugins/send-file-ledger.js").SendFileLedger;
57
+ backend?: StoreBackend;
58
+ }
59
+ export interface ServiceCoordinatorDeps {
60
+ elicitation?: ElicitationCoordinator;
61
+ question?: QuestionCoordinator;
62
+ toolApproval?: ToolApprovalCoordinator;
83
63
  workflowAgentRegistry?: WorkflowAgentRegistry;
84
64
  subagentSteerRegistry?: SubagentSteerRegistry;
65
+ workflowCompletionInbox?: WorkflowCompletionInbox;
66
+ fleetBus?: FleetEventBus;
67
+ sessionWatch?: import("../session-watch.js").SessionWatchRegistry;
68
+ hookWakeBus?: {
69
+ deliver?: (sessionId: string, text: string) => Promise<boolean>;
70
+ };
71
+ sendUserFile?: import("../capabilities/send-user-file-tool.js").SendUserFileEmitter;
72
+ leaderEndpoint?: LeaderEndpoint;
73
+ sessionTitler?: {
74
+ maybeTitle(sessionId: string, objective: string): void;
75
+ };
76
+ }
77
+ export interface ServiceSeamDeps {
78
+ sessionAudit?: (sessionId: string) => Promise<({
79
+ owner: string | null;
80
+ } & Record<string, unknown>) | undefined>;
81
+ purgeSession?: (sessionId: string, owner: string | null) => Promise<{
82
+ deleted: boolean;
83
+ } | {
84
+ active: string;
85
+ }>;
85
86
  subagentTaskOutput?: (handle: string, access: {
86
87
  owner: string;
87
88
  scope: string;
@@ -106,23 +107,10 @@ export interface ServiceDeps {
106
107
  content: string;
107
108
  details: unknown;
108
109
  }>;
109
- workflowCompletionInbox?: WorkflowCompletionInbox;
110
- fleetBus?: FleetEventBus;
111
- sessionAudit?: (sessionId: string) => Promise<({
112
- owner: string | null;
113
- } & Record<string, unknown>) | undefined>;
114
- sessionStorage?: OwnerAwareSessionStore;
115
- purgeSession?: (sessionId: string, owner: string | null) => Promise<{
116
- deleted: boolean;
117
- } | {
118
- active: string;
119
- }>;
120
- instanceId?: string;
121
- logger?: Logger;
122
- metrics?: Metrics;
123
- rateLimiter?: RateGate;
124
- costQuota?: QuotaTracker;
125
- fleetLease?: FleetLeaseManager;
110
+ memoryExport?: (scope: string) => Promise<MemoryEntry[]>;
111
+ memorySync?: (scope: string, syncReq: MemorySyncRequest) => Promise<MemorySyncResponse>;
112
+ sessionMirrorRuling?: (principal: string | undefined) => Promise<SessionMirrorRuling | undefined>;
113
+ instrumentDegenerate?: (result: TaskResult) => void;
126
114
  sideQueryAccounting?: (principal: string | undefined, r: {
127
115
  model: string;
128
116
  family?: "input-includes-cached" | "input-excludes-cached";
@@ -136,30 +124,68 @@ export interface ServiceDeps {
136
124
  };
137
125
  };
138
126
  }) => void;
139
- outcomeSink?: import("../plugins/file-outcome-sink.js").OutcomeSink;
140
- memoryExport?: (scope: string) => Promise<MemoryEntry[]>;
141
- memorySync?: (scope: string, syncReq: MemorySyncRequest) => Promise<MemorySyncResponse>;
142
- instrumentDegenerate?: (result: TaskResult) => void;
143
- planCacheProbe?: PlanCacheProbe;
127
+ parkedReviveTool?: import("@sema-agent/core").ToolSpec;
128
+ parkedKnownAgentTypes?: ReadonlySet<string>;
129
+ parkedReviveInheritedGate?: (row: import("@sema-agent/core").BackgroundAgentRecord) => unknown;
130
+ }
131
+ export interface ServiceObservabilityDeps {
132
+ logger?: Logger;
133
+ metrics?: Metrics;
144
134
  modelUsage?: ModelUsageTracker;
145
135
  promptManifests?: PromptManifestTracker;
146
- elicitation?: ElicitationCoordinator;
147
- question?: QuestionCoordinator;
148
- toolApproval?: ToolApprovalCoordinator;
149
- sendUserFile?: import("../capabilities/send-user-file-tool.js").SendUserFileEmitter;
150
- sendFileLedger?: import("../plugins/send-file-ledger.js").SendFileLedger;
151
- sessionWatch?: import("../session-watch.js").SessionWatchRegistry;
152
- sessionEventsMaxConnections?: number;
153
- sessionEventsHeartbeatMs?: number;
154
- sessionEventsStallMs?: number;
136
+ planCacheProbe?: PlanCacheProbe;
137
+ }
138
+ export interface ServiceGovernanceDeps {
139
+ authorize?: (ctx: {
140
+ req: IncomingMessage;
141
+ body: TaskRequestBody;
142
+ }) => Promise<RequestAuth>;
143
+ registryJwtVerifier?: {
144
+ verify: (bearer: string) => Promise<import("../auth-bridge.js").VerifyOutcome>;
145
+ };
146
+ rateLimiter?: RateGate;
147
+ costQuota?: QuotaTracker;
148
+ fleetLease?: FleetLeaseManager;
149
+ }
150
+ export interface ServiceDeploymentDeps {
151
+ instanceId?: string;
155
152
  capabilities?: Record<string, unknown>;
153
+ scenarioDetails?: Record<string, import("../capabilities/scenarios.js").ScenarioDetail>;
154
+ sessionStoreLabel?: string;
155
+ storeDegraded?: boolean;
156
+ drainState?: {
157
+ draining: boolean;
158
+ since?: number;
159
+ inflight?: () => number;
160
+ lastActivityAt?: () => number;
161
+ };
162
+ modelReady?: () => boolean;
156
163
  restartState?: () => RestartSignal | undefined;
157
164
  planeDeferredState?: () => {
158
165
  version: number;
159
166
  since: number;
160
167
  blocked?: string[];
161
168
  } | undefined;
169
+ workflowsCapable?: boolean;
170
+ }
171
+ export interface ServiceKnobDeps {
172
+ snapshotBlobSqlCapBytes?: number;
173
+ sessionEventsMaxConnections?: number;
174
+ sessionEventsHeartbeatMs?: number;
175
+ sessionEventsStallMs?: number;
176
+ }
177
+ export interface ServiceDepGroups {
178
+ stores?: ServiceStoreDeps;
179
+ coordinators?: ServiceCoordinatorDeps;
180
+ seams?: ServiceSeamDeps;
181
+ observability?: ServiceObservabilityDeps;
182
+ governance?: ServiceGovernanceDeps;
183
+ deployment?: ServiceDeploymentDeps;
184
+ knobs?: ServiceKnobDeps;
162
185
  }
186
+ export type FlatServiceDeps = ServiceCoreDeps & Partial<ServiceStoreDeps & ServiceCoordinatorDeps & ServiceSeamDeps & ServiceObservabilityDeps & ServiceGovernanceDeps & ServiceDeploymentDeps & ServiceKnobDeps>;
187
+ export type ServiceDeps = FlatServiceDeps & ServiceDepGroups;
188
+ export declare function flattenServiceDeps(deps: ServiceDeps): FlatServiceDeps;
163
189
  export type { TaskRequestBody } from "./wire-types.js";
164
190
  export declare const MAX_USER_SKILLS = 10;
165
191
  export declare const MAX_SKILL_CONTENT_CHARS = 1048576;
@@ -175,7 +201,7 @@ export declare function cascadeConfig(ladder: readonly string[], maxCostUsd?: nu
175
201
  export declare function clampVerifyRounds(v: unknown): number;
176
202
  export declare function scopedIdempotencyKey(raw: string | undefined, source: string | null, principal: string | undefined): string | undefined;
177
203
  export declare function isQuestionAnswer(v: unknown): v is QuestionAnswer;
178
- export declare function createHttpServer(deps: ServiceDeps): http.Server & {
204
+ export declare function createHttpServer(rawDeps: ServiceDeps): http.Server & {
179
205
  denyExpiredApprovals: (now: number) => Promise<void>;
180
206
  };
181
207
  export declare function streamApprovals(req: IncomingMessage, res: ServerResponse, cs: Pick<CheckpointStoreFull, "listPending">, scope: string | undefined, pollMs?: number): Promise<void>;