@sema-agent/server 1.310.0 → 1.312.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 (72) hide show
  1. package/dist/auth-keys.d.ts +14 -0
  2. package/dist/auth-keys.js +31 -0
  3. package/dist/brain.d.ts +1 -1
  4. package/dist/capabilities/center-prompts.d.ts +3 -28
  5. package/dist/capabilities/center-prompts.js +2 -107
  6. package/dist/capabilities/select-environment-tool.d.ts +1 -1
  7. package/dist/config-lkg.js +1 -1
  8. package/dist/config-types.d.ts +306 -0
  9. package/dist/config-types.js +2 -0
  10. package/dist/config.d.ts +4 -305
  11. package/dist/config.js +1 -1
  12. package/dist/env-facts.d.ts +1 -1
  13. package/dist/hooks/hook-llm.d.ts +1 -1
  14. package/dist/http/server.d.ts +5 -85
  15. package/dist/http/wire-types.d.ts +84 -0
  16. package/dist/http/wire-types.js +2 -0
  17. package/dist/images/manifest.d.ts +1 -1
  18. package/dist/index.d.ts +2 -1
  19. package/dist/index.js +1 -1
  20. package/dist/main.js +134 -143
  21. package/dist/per-task-image.d.ts +2 -2
  22. package/dist/plugins/file-run-store.d.ts +1 -1
  23. package/dist/plugins/local-session-store.d.ts +2 -2
  24. package/dist/plugins/local-session-store.js +1 -1
  25. package/dist/plugins/memory-run-store.d.ts +1 -1
  26. package/dist/plugins/pg-approval-store.js +1 -27
  27. package/dist/plugins/pg-checkpoint-store.js +1 -5
  28. package/dist/plugins/pg-image-bake.d.ts +2 -2
  29. package/dist/plugins/pg-image-bake.js +2 -54
  30. package/dist/plugins/pg-image-index.d.ts +2 -2
  31. package/dist/plugins/pg-image-index.js +1 -44
  32. package/dist/plugins/pg-pool.d.ts +1 -1
  33. package/dist/plugins/pg-run-store.d.ts +1 -1
  34. package/dist/plugins/pg-run-store.js +2 -16
  35. package/dist/plugins/pg-session-storage.d.ts +2 -2
  36. package/dist/plugins/pg-session-storage.js +3 -7
  37. package/dist/plugins/pg-tool-result-store.js +1 -1
  38. package/dist/plugins/session-store.d.ts +1 -1
  39. package/dist/plugins/sql-escape.d.ts +2 -0
  40. package/dist/plugins/sql-escape.js +4 -0
  41. package/dist/plugins/sql-row-helpers.d.ts +7 -0
  42. package/dist/plugins/sql-row-helpers.js +43 -0
  43. package/dist/plugins/store-backend.d.ts +1 -1
  44. package/dist/plugins/store-contracts.d.ts +205 -0
  45. package/dist/plugins/store-contracts.js +61 -0
  46. package/dist/plugins/tidb-approval-store.d.ts +1 -0
  47. package/dist/plugins/tidb-approval-store.js +2 -11
  48. package/dist/plugins/tidb-checkpoint-store.js +1 -5
  49. package/dist/plugins/tidb-image-bake.d.ts +3 -64
  50. package/dist/plugins/tidb-image-bake.js +3 -54
  51. package/dist/plugins/tidb-image-index.d.ts +3 -52
  52. package/dist/plugins/tidb-image-index.js +2 -43
  53. package/dist/plugins/tidb-pool.d.ts +1 -1
  54. package/dist/plugins/tidb-run-store.d.ts +2 -32
  55. package/dist/plugins/tidb-run-store.js +2 -16
  56. package/dist/plugins/tidb-session-storage.js +1 -5
  57. package/dist/plugins/tidb-session-store.d.ts +2 -2
  58. package/dist/plugins/tidb-session-store.js +2 -2
  59. package/dist/plugins/tidb-tool-result-store.d.ts +1 -1
  60. package/dist/plugins/tidb-tool-result-store.js +2 -3
  61. package/dist/prompts-domain-validate.d.ts +29 -0
  62. package/dist/prompts-domain-validate.js +109 -0
  63. package/dist/security.d.ts +6 -16
  64. package/dist/security.js +1 -30
  65. package/dist/sema-registry.d.ts +1 -1
  66. package/dist/session-sync-kernel.d.ts +47 -0
  67. package/dist/session-sync-kernel.js +47 -0
  68. package/dist/session-sync.d.ts +3 -45
  69. package/dist/session-sync.js +2 -46
  70. package/dist/trace/artifacts.d.ts +1 -1
  71. package/dist/trace/project.d.ts +1 -1
  72. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -988,31 +988,80 @@ async function main() {
988
988
  requirePrincipal: config.requirePrincipal,
989
989
  warn: (msg, fields) => logger.warn(msg, fields),
990
990
  });
991
+ const workflowModelAllowlist = workflowModelAllowlistFor(config);
992
+ const selfOrchestrationDeps = config.selfOrchestrationEnabled
993
+ ? {
994
+ workflowScriptRunner: config.selfOrchestrationWorkerIsolation
995
+ ? createWorkerHardenedVmRunner()
996
+ : createHardenedVmRunner(),
997
+ workflowRunStore: workflowRunStore ? workflowRunStore : undefined,
998
+ workflowJournalStore: workflowJournalStore ? workflowJournalStore : undefined,
999
+ workflowScriptStore: (() => {
1000
+ const fileStore = createFileWorkflowScriptStore(join(config.localDataRoot ?? localRoot, "workflow-scripts"));
1001
+ return {
1002
+ scopePartitioned: true,
1003
+ persist: fileStore.persist.bind(fileStore),
1004
+ load: fileStore.load.bind(fileStore),
1005
+ resolveName: (name) => resolveCollabWorkflow(name) ?? fileStore.resolveName?.(name),
1006
+ list: () => listCollabWorkflows(),
1007
+ };
1008
+ })(),
1009
+ onWorkflowAgentSpawn: workflowAgentRegistry
1010
+ ? (handle) => {
1011
+ const unregister = workflowAgentRegistry.register(handle);
1012
+ void Promise.resolve(handle.result()).then(unregister, unregister);
1013
+ }
1014
+ : undefined,
1015
+ workflowLimits: config.workflowSizeGuideline ? { sizeGuideline: config.workflowSizeGuideline } : undefined,
1016
+ workflowGovernanceBaseline: {
1017
+ base: config.workflowAgentsReadOnly ? { handsReadOnly: true } : {},
1018
+ worktreeBase: config.workflowAgentsReadOnly ? { handsReadOnly: false } : undefined,
1019
+ workflowModelAllowlist: workflowModelAllowlist ? workflowModelAllowlist : undefined,
1020
+ },
1021
+ workflowCompletionNotifier: {
1022
+ ...(workflowNotifyGate
1023
+ ? workflowNotifyGate.buildNotifier()
1024
+ : { notify: (input) => deliverWorkflowCompletion(input) }),
1025
+ ackServed: async (input) => {
1026
+ if (!workflowCompletionInbox)
1027
+ return;
1028
+ try {
1029
+ const sid = await resolveServedSession(input, runStore ? (id) => runStore.getRun(id) : undefined);
1030
+ if (sid) {
1031
+ await workflowCompletionInbox.markTerminalServed(sid, input.runId);
1032
+ logger.info("workflow_complete_ack_served", { route: "poll-served", sessionId: sid, runId: input.runId });
1033
+ }
1034
+ }
1035
+ catch (err) {
1036
+ logger.warn("workflow_ack_served_failed", { runId: input.runId, err: String(err) });
1037
+ }
1038
+ },
1039
+ },
1040
+ }
1041
+ : {};
991
1042
  const runnerDeps = {
992
1043
  promptSource,
993
- ...(rosterStore ? { rosterStore } : {}),
994
- ...(backgroundAgentStore ? { backgroundAgentStore } : {}),
995
- ...(mailboxStore ? { mailboxStore } : {}),
1044
+ rosterStore: rosterStore ? rosterStore : undefined,
1045
+ backgroundAgentStore: backgroundAgentStore ? backgroundAgentStore : undefined,
1046
+ mailboxStore: mailboxStore ? mailboxStore : undefined,
996
1047
  brain,
997
1048
  models: config.models,
998
1049
  roles: config.roles,
999
1050
  tiers: config.tiers,
1000
1051
  pricing,
1001
1052
  tracer,
1002
- ...(config.configProvider === "local" ? { hands: { commitCoAuthor: "Sema <noreply@vivi-ai.com>" } } : {}),
1003
- ...(outcomeSink
1004
- ? {
1005
- onTaskOutcome: (o) => {
1006
- metrics.inc("task_outcomes_total", { status: o.status, green: String(o.oracle?.green ?? "unknown") });
1007
- void outcomeSink.recordCore(o).catch((err) => logger.warn("task_outcome_record_failed", { runId: o.runId, err: String(err) }));
1008
- },
1009
- }
1010
- : {}),
1011
- ...(elicitation ? { onElicit: elicitation.elicit } : {}),
1012
- ...(question ? { onQuestion: question.question } : {}),
1013
- ...(toolApproval
1014
- ? { onAsk: (req, signal) => toolApproval.ask(req, signal) }
1015
- : {}),
1053
+ hands: config.configProvider === "local" ? { commitCoAuthor: "Sema <noreply@vivi-ai.com>" } : undefined,
1054
+ onTaskOutcome: outcomeSink
1055
+ ? (o) => {
1056
+ metrics.inc("task_outcomes_total", { status: o.status, green: String(o.oracle?.green ?? "unknown") });
1057
+ void outcomeSink.recordCore(o).catch((err) => logger.warn("task_outcome_record_failed", { runId: o.runId, err: String(err) }));
1058
+ }
1059
+ : undefined,
1060
+ onElicit: elicitation ? elicitation.elicit : undefined,
1061
+ onQuestion: question ? question.question : undefined,
1062
+ onAsk: toolApproval
1063
+ ? (req, signal) => toolApproval.ask(req, signal)
1064
+ : undefined,
1016
1065
  autoMode: {
1017
1066
  onBreakerOpen: (info) => {
1018
1067
  metrics.inc("auto_mode_breaker_open_total");
@@ -1020,84 +1069,32 @@ async function main() {
1020
1069
  },
1021
1070
  },
1022
1071
  sessionStore,
1023
- ...(memoryEngine ? { memoryBackend: memoryEngine.backend, memoryEngineDir: memoryEngine.root } : {}),
1024
- ...(memoryEngine
1025
- ? {
1026
- onMemoryHarvestReport: (report, info) => {
1027
- metrics.inc("memory_harvest_total", { ok: String(report.ok), phase: info.phase, incident: report.incident?.kind ?? "none" });
1028
- if (report.patches)
1029
- metrics.inc("memory_harvest_patches_total", { phase: info.phase }, (report.patches.add ?? 0) + (report.patches.update ?? 0));
1030
- if (report.incident)
1031
- logger.warn("memory_harvest_incident", { kind: report.incident.kind, phase: info.phase });
1032
- if (memorySyncRunner && report.ok && (report.patches?.add ?? 0) + (report.patches?.update ?? 0) > 0)
1033
- memorySyncRunner.trigger("harvest");
1034
- },
1035
- }
1036
- : {}),
1072
+ memoryBackend: memoryEngine ? memoryEngine.backend : undefined,
1073
+ memoryEngineDir: memoryEngine ? memoryEngine.root : undefined,
1074
+ onMemoryHarvestReport: memoryEngine
1075
+ ? (report, info) => {
1076
+ metrics.inc("memory_harvest_total", { ok: String(report.ok), phase: info.phase, incident: report.incident?.kind ?? "none" });
1077
+ if (report.patches)
1078
+ metrics.inc("memory_harvest_patches_total", { phase: info.phase }, (report.patches.add ?? 0) + (report.patches.update ?? 0));
1079
+ if (report.incident)
1080
+ logger.warn("memory_harvest_incident", { kind: report.incident.kind, phase: info.phase });
1081
+ if (memorySyncRunner && report.ok && (report.patches?.add ?? 0) + (report.patches?.update ?? 0) > 0)
1082
+ memorySyncRunner.trigger("harvest");
1083
+ }
1084
+ : undefined,
1037
1085
  toolResultStore,
1038
- ...(sessionPolicyStore ? { sessionPolicyStore } : {}),
1039
- ...(runtimeCapsResolver ? { runtimeCapsResolver } : {}),
1040
- ...(fileSnapshotStore ? { fileSnapshotStore } : {}),
1041
- ...(executionEnvFactory ? { executionEnvFactory } : {}),
1042
- ...(lspManager ? { lspManager } : {}),
1086
+ sessionPolicyStore: sessionPolicyStore ? sessionPolicyStore : undefined,
1087
+ runtimeCapsResolver: runtimeCapsResolver ? runtimeCapsResolver : undefined,
1088
+ fileSnapshotStore: fileSnapshotStore ? fileSnapshotStore : undefined,
1089
+ executionEnvFactory: executionEnvFactory ? executionEnvFactory : undefined,
1090
+ lspManager: lspManager ? lspManager : undefined,
1043
1091
  onBackgroundChildEvent: fleetBackgroundChildPublisher(fleetBus, (msg, fields) => logger.info(msg, fields)),
1044
- ...(config.requirePrincipal !== true && !config.projectMemoryDisabled ? { loadProjectMemory: makeLoadProjectMemory({ logger }) } : {}),
1045
- ...(config.remoteExec?.provider === "host" && config.requirePrincipal !== true && !config.projectMemoryDisabled
1046
- ? { probeInstructionSources: makeProbeInstructionSources() }
1047
- : {}),
1092
+ loadProjectMemory: config.requirePrincipal !== true && !config.projectMemoryDisabled ? makeLoadProjectMemory({ logger }) : undefined,
1093
+ probeInstructionSources: config.remoteExec?.provider === "host" && config.requirePrincipal !== true && !config.projectMemoryDisabled
1094
+ ? makeProbeInstructionSources()
1095
+ : undefined,
1048
1096
  hooks: deploymentHooks,
1049
- ...(config.selfOrchestrationEnabled
1050
- ? {
1051
- workflowScriptRunner: config.selfOrchestrationWorkerIsolation
1052
- ? createWorkerHardenedVmRunner()
1053
- : createHardenedVmRunner(),
1054
- ...(workflowRunStore ? { workflowRunStore } : {}),
1055
- ...(workflowJournalStore ? { workflowJournalStore } : {}),
1056
- workflowScriptStore: (() => {
1057
- const fileStore = createFileWorkflowScriptStore(join(config.localDataRoot ?? localRoot, "workflow-scripts"));
1058
- return {
1059
- scopePartitioned: true,
1060
- persist: fileStore.persist.bind(fileStore),
1061
- load: fileStore.load.bind(fileStore),
1062
- resolveName: (name) => resolveCollabWorkflow(name) ?? fileStore.resolveName?.(name),
1063
- list: () => listCollabWorkflows(),
1064
- };
1065
- })(),
1066
- ...(workflowAgentRegistry
1067
- ? {
1068
- onWorkflowAgentSpawn: (handle) => {
1069
- const unregister = workflowAgentRegistry.register(handle);
1070
- void Promise.resolve(handle.result()).then(unregister, unregister);
1071
- },
1072
- }
1073
- : {}),
1074
- ...(config.workflowSizeGuideline ? { workflowLimits: { sizeGuideline: config.workflowSizeGuideline } } : {}),
1075
- workflowGovernanceBaseline: {
1076
- base: config.workflowAgentsReadOnly ? { handsReadOnly: true } : {},
1077
- ...(config.workflowAgentsReadOnly ? { worktreeBase: { handsReadOnly: false } } : {}),
1078
- ...((wl) => (wl ? { workflowModelAllowlist: wl } : {}))(workflowModelAllowlistFor(config)),
1079
- },
1080
- workflowCompletionNotifier: {
1081
- ...(workflowNotifyGate
1082
- ? workflowNotifyGate.buildNotifier()
1083
- : { notify: (input) => deliverWorkflowCompletion(input) }),
1084
- ackServed: async (input) => {
1085
- if (!workflowCompletionInbox)
1086
- return;
1087
- try {
1088
- const sid = await resolveServedSession(input, runStore ? (id) => runStore.getRun(id) : undefined);
1089
- if (sid) {
1090
- await workflowCompletionInbox.markTerminalServed(sid, input.runId);
1091
- logger.info("workflow_complete_ack_served", { route: "poll-served", sessionId: sid, runId: input.runId });
1092
- }
1093
- }
1094
- catch (err) {
1095
- logger.warn("workflow_ack_served_failed", { runId: input.runId, err: String(err) });
1096
- }
1097
- },
1098
- },
1099
- }
1100
- : {}),
1097
+ ...selfOrchestrationDeps,
1101
1098
  onError: (err, ctx) => {
1102
1099
  if (ctx.phase === "degraded") {
1103
1100
  logger.warn("task_degraded", { sessionId: ctx.sessionId, info: String(err) });
@@ -1335,20 +1332,18 @@ async function main() {
1335
1332
  };
1336
1333
  const scenarioDeps = {
1337
1334
  runner, subRunner, model: "default", skills, repoClient, requirePrincipal: config.requirePrincipal,
1338
- ...(webSearch ? { webSearch } : {}), metrics, logger, webFetchSummarize,
1339
- ...(backgroundAgentStore ? { backgroundAgentStore } : {}),
1340
- ...(checkpointStore ? { checkpointStore } : {}),
1341
- ...(ensureChildSessionDurable ? { ensureChildSessionDurable } : {}),
1335
+ webSearch: webSearch ? webSearch : undefined, metrics, logger, webFetchSummarize,
1336
+ backgroundAgentStore: backgroundAgentStore ? backgroundAgentStore : undefined,
1337
+ checkpointStore: checkpointStore ? checkpointStore : undefined,
1338
+ ensureChildSessionDurable: ensureChildSessionDurable ? ensureChildSessionDurable : undefined,
1342
1339
  oaApiBaseUrl: config.oaApiBaseUrl, oaServiceToken: config.oaServiceToken, oaIssue: config.oaIssue,
1343
1340
  brandIdentity: config.configProvider === "local",
1344
- ...(sendUserFileToolSpec
1345
- ? {
1346
- subagentExtraTools: subagentSendUserFileExtraTools({
1347
- spec: sendUserFileToolSpec,
1348
- approvalGate: () => ({ deny: config.approvalDeny, require: config.approvalRequire, neverAuto: config.approvalNeverAuto }),
1349
- }),
1350
- }
1351
- : {}),
1341
+ subagentExtraTools: sendUserFileToolSpec
1342
+ ? subagentSendUserFileExtraTools({
1343
+ spec: sendUserFileToolSpec,
1344
+ approvalGate: () => ({ deny: config.approvalDeny, require: config.approvalRequire, neverAuto: config.approvalNeverAuto }),
1345
+ })
1346
+ : undefined,
1352
1347
  };
1353
1348
  const scenarios = buildScenarios(scenarioDeps);
1354
1349
  const parkedReviveTool = checkpointStore && backgroundAgentStore ? scenarios.default?.({})?.tools.find((t) => t.name === "Agent") : undefined;
@@ -1844,72 +1839,68 @@ async function main() {
1844
1839
  config,
1845
1840
  authorize,
1846
1841
  sessionStoreLabel: config.sessionBackend === "tidb" && backend ? `durable(${backend.kind})` : config.sessionBackend,
1847
- ...(taskAttachmentStore ? { taskAttachmentStore } : {}),
1848
- ...(backend && backend.kind !== "local" && !config.snapshotBlobStore
1849
- ? ((cap) => (cap !== undefined ? { snapshotBlobSqlCapBytes: cap } : {}))(config.snapshotBlobSqlMaxBytes ?? (backend.kind === "mysql" ? SQL_BLOB_DEFAULT_MAX_BYTES : undefined))
1850
- : {}),
1842
+ taskAttachmentStore: taskAttachmentStore ? taskAttachmentStore : undefined,
1843
+ snapshotBlobSqlCapBytes: backend && backend.kind !== "local" && !config.snapshotBlobStore
1844
+ ? (config.snapshotBlobSqlMaxBytes ?? (backend.kind === "mysql" ? SQL_BLOB_DEFAULT_MAX_BYTES : undefined))
1845
+ : undefined,
1851
1846
  modelReady: () => modelReadyState.ready,
1852
1847
  scenarioDetails,
1853
- ...(registryJwtVerifier ? { registryJwtVerifier } : {}),
1848
+ registryJwtVerifier: registryJwtVerifier ? registryJwtVerifier : undefined,
1854
1849
  hookWakeBus,
1855
1850
  runStore,
1856
1851
  fleetBus,
1857
1852
  workflowsCapable,
1858
- ...(resumeAnchorStore ? { resumeAnchorStore } : {}),
1859
- ...(approvalExemptionStore ? { approvalExemptionStore } : {}),
1860
- ...(sessionTitler ? { sessionTitler } : {}),
1861
- ...(sessionPolicyStore ? { sessionPolicyStore } : {}),
1862
- ...(fileSnapshotStore ? { fileSnapshotStore } : {}),
1863
- ...(backend ? { backend } : {}),
1864
- ...(principalCaps
1865
- ? { sessionMirrorRuling: async (p) => (await principalCaps.executionRuling(p))?.sessionMirror }
1866
- : {}),
1853
+ resumeAnchorStore: resumeAnchorStore ? resumeAnchorStore : undefined,
1854
+ approvalExemptionStore: approvalExemptionStore ? approvalExemptionStore : undefined,
1855
+ sessionTitler: sessionTitler ? sessionTitler : undefined,
1856
+ sessionPolicyStore: sessionPolicyStore ? sessionPolicyStore : undefined,
1857
+ fileSnapshotStore: fileSnapshotStore ? fileSnapshotStore : undefined,
1858
+ backend: backend ? backend : undefined,
1859
+ sessionMirrorRuling: principalCaps
1860
+ ? async (p) => (await principalCaps.executionRuling(p))?.sessionMirror
1861
+ : undefined,
1867
1862
  approvalStore,
1868
1863
  checkpointStore,
1869
- ...(backgroundAgentStore ? { backgroundAgentStore } : {}),
1870
- ...(parkedReviveTool ? { parkedReviveTool } : {}),
1871
- ...(parkedReviveInheritedGate ? { parkedReviveInheritedGate } : {}),
1864
+ backgroundAgentStore: backgroundAgentStore ? backgroundAgentStore : undefined,
1865
+ parkedReviveTool: parkedReviveTool ? parkedReviveTool : undefined,
1866
+ parkedReviveInheritedGate: parkedReviveInheritedGate ? parkedReviveInheritedGate : undefined,
1872
1867
  imageIndex,
1873
1868
  imageBakes,
1874
1869
  leaderEndpoint,
1875
- ...(workflowRunStore ? { workflowRunStore } : {}),
1876
- ...(workflowJournalStore ? { workflowJournalStore } : {}),
1877
- ...(workflowAgentRegistry ? { workflowAgentRegistry } : {}),
1870
+ workflowRunStore: workflowRunStore ? workflowRunStore : undefined,
1871
+ workflowJournalStore: workflowJournalStore ? workflowJournalStore : undefined,
1872
+ workflowAgentRegistry: workflowAgentRegistry ? workflowAgentRegistry : undefined,
1878
1873
  subagentSteerRegistry,
1879
1874
  subagentTaskOutput: (handle, access) => backgroundAgentOutput(defaultTaskRegistry, handle, access, backgroundAgentStore),
1880
1875
  taskHandleOutput: (handle, access) => taskHandleOutput(defaultTaskRegistry, handle, access, backgroundAgentStore),
1881
1876
  taskHandleStop: (handle, access) => taskHandleStop(defaultTaskRegistry, handle, access, backgroundAgentStore),
1882
- ...(workflowCompletionInbox ? { workflowCompletionInbox } : {}),
1877
+ workflowCompletionInbox: workflowCompletionInbox ? workflowCompletionInbox : undefined,
1883
1878
  sessionAudit,
1884
1879
  sessionStorage: ownerAware,
1885
- ...(sessionWatchRegistry
1886
- ? {
1887
- sessionWatch: sessionWatchRegistry,
1888
- sessionEventsMaxConnections: posIntEnv(process.env.SESSION_EVENTS_MAX_CONNS, 256, 100_000),
1889
- }
1890
- : {}),
1891
- ...(purgeSession ? { purgeSession } : {}),
1880
+ sessionWatch: sessionWatchRegistry ? sessionWatchRegistry : undefined,
1881
+ sessionEventsMaxConnections: sessionWatchRegistry ? posIntEnv(process.env.SESSION_EVENTS_MAX_CONNS, 256, 100_000) : undefined,
1882
+ purgeSession: purgeSession ? purgeSession : undefined,
1892
1883
  instrumentDegenerate,
1893
1884
  planCacheProbe,
1894
1885
  modelUsage: modelUsageTracker,
1895
1886
  promptManifests: promptManifestTracker,
1896
- ...(elicitation ? { elicitation } : {}),
1897
- ...(question ? { question } : {}),
1898
- ...(toolApproval ? { toolApproval } : {}),
1899
- ...(sendUserFileEmitter ? { sendUserFile: sendUserFileEmitter } : {}),
1900
- ...(sendFileLedger ? { sendFileLedger } : {}),
1887
+ elicitation: elicitation ? elicitation : undefined,
1888
+ question: question ? question : undefined,
1889
+ toolApproval: toolApproval ? toolApproval : undefined,
1890
+ sendUserFile: sendUserFileEmitter ? sendUserFileEmitter : undefined,
1891
+ sendFileLedger: sendFileLedger ? sendFileLedger : undefined,
1901
1892
  instanceId,
1902
1893
  logger,
1903
1894
  metrics,
1904
1895
  rateLimiter,
1905
1896
  costQuota,
1906
- ...(fleetLease ? { fleetLease } : {}),
1897
+ fleetLease: fleetLease ? fleetLease : undefined,
1907
1898
  sideQueryAccounting,
1908
- ...(outcomeSink ? { outcomeSink } : {}),
1909
- ...(memoryExportBackend ? { memoryExport: (scope) => exportMemoryScope(memoryExportBackend, scope) } : {}),
1910
- ...(memoryExportBackend && memorySyncCursors
1911
- ? { memorySync: (scope, syncReq) => performMemorySync(memoryExportBackend, memorySyncCursors, scope, syncReq) }
1912
- : {}),
1899
+ outcomeSink: outcomeSink ? outcomeSink : undefined,
1900
+ memoryExport: memoryExportBackend ? (scope) => exportMemoryScope(memoryExportBackend, scope) : undefined,
1901
+ memorySync: memoryExportBackend && memorySyncCursors
1902
+ ? (scope, syncReq) => performMemorySync(memoryExportBackend, memorySyncCursors, scope, syncReq)
1903
+ : undefined,
1913
1904
  capabilities: {
1914
1905
  version: serviceVersion(),
1915
1906
  scenarios: Object.keys(scenarios),
@@ -1,11 +1,11 @@
1
- import type { ImageViewer, ImageIndexEntry } from "./plugins/tidb-image-index.js";
1
+ import type { ImageViewer, ImageIndexEntry } from "./plugins/store-contracts.js";
2
2
  export interface SandboxImageResolver {
3
3
  latestPublished(profile: string, viewer: ImageViewer): Promise<Pick<ImageIndexEntry, "repo" | "digest" | "capabilities"> | null>;
4
4
  }
5
5
  export type SandboxImageResolution = {
6
6
  ok: true;
7
7
  ref: string;
8
- capabilities?: import("./plugins/tidb-image-index.js").ImageCapabilities;
8
+ capabilities?: import("./plugins/store-contracts.js").ImageCapabilities;
9
9
  } | {
10
10
  ok: false;
11
11
  status: number;
@@ -1,6 +1,6 @@
1
1
  import { type UsageRow } from "../usage-analytics.js";
2
2
  import type { TaskResult, TaskStatus } from "@sema-agent/core";
3
- import type { RunRecord, SessionSummary, RunEvent } from "./tidb-run-store.js";
3
+ import type { RunRecord, SessionSummary, RunEvent } from "./store-contracts.js";
4
4
  import type { RunStoreCheckpointProbe } from "./memory-run-store.js";
5
5
  export declare class FileRunStore {
6
6
  private readonly runsDir;
@@ -1,6 +1,6 @@
1
1
  import { type AcquiredSession, type SessionStore, type SessionRepo, type SessionTreeEntry } from "@sema-agent/core";
2
- import type { SessionSummary } from "./tidb-run-store.js";
3
- import { type StagingHandle } from "../session-sync.js";
2
+ import type { SessionSummary } from "./store-contracts.js";
3
+ import { type StagingHandle } from "../session-sync-kernel.js";
4
4
  export declare class LocalSessionStore implements SessionStore {
5
5
  private readonly repo;
6
6
  private readonly pending;
@@ -2,7 +2,7 @@ import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
2
2
  import { join, resolve } from "node:path";
3
3
  import { SessionError, validateEntriesForImport } from "@sema-agent/core";
4
4
  import { identicalIdsAlsoIdenticalContent } from "../session-sync-content.js";
5
- import { classifySyncRelationshipByIds, SyncConflictError, stagingIdFor, } from "../session-sync.js";
5
+ import { classifySyncRelationshipByIds, SyncConflictError, stagingIdFor, } from "../session-sync-kernel.js";
6
6
  const ownerEq = (a, b) => (a ?? null) === (b ?? null);
7
7
  const isNotFound = (e) => e instanceof SessionError && e.code === "not_found";
8
8
  function userText(entry) {
@@ -1,6 +1,6 @@
1
1
  import { type UsageRow } from "../usage-analytics.js";
2
2
  import type { TaskResult, TaskStatus } from "@sema-agent/core";
3
- import type { RunRecord, SessionSummary, RunEvent } from "./tidb-run-store.js";
3
+ import type { RunRecord, SessionSummary, RunEvent } from "./store-contracts.js";
4
4
  export interface RunStoreCheckpointProbe {
5
5
  hasPending(sessionId: string): Promise<boolean>;
6
6
  hasExpired(sessionId: string): Promise<boolean>;
@@ -1,4 +1,4 @@
1
- import {} from "./tidb-approval-store.js";
1
+ import { mapRow } from "./tidb-approval-store.js";
2
2
  import { pgProtocolJsonStringify } from "./pg-safe-json.js";
3
3
  export const PG_APPROVAL_SCHEMA = [
4
4
  `CREATE TABLE IF NOT EXISTS approval (
@@ -27,16 +27,6 @@ export async function ensureSchema(pool) {
27
27
  for (const stmt of PG_APPROVAL_SCHEMA)
28
28
  await pool.query(stmt);
29
29
  }
30
- function parseJson(v) {
31
- if (v == null)
32
- return null;
33
- return (typeof v === "string" ? JSON.parse(v) : v);
34
- }
35
- function iso(v) {
36
- if (v == null)
37
- return null;
38
- return v instanceof Date ? v.toISOString() : String(v);
39
- }
40
30
  export class PgApprovalStore {
41
31
  pool;
42
32
  constructor(pool) {
@@ -91,20 +81,4 @@ export class PgApprovalStore {
91
81
  return res.rowCount ?? 0;
92
82
  }
93
83
  }
94
- function mapRow(r) {
95
- return {
96
- id: String(r.id),
97
- taskId: r.task_id ?? null,
98
- sessionId: r.session_id ?? null,
99
- owner: r.owner ?? null,
100
- scope: r.scope ?? null,
101
- toolName: String(r.tool_name),
102
- args: parseJson(r.args),
103
- status: r.status,
104
- reason: r.reason ?? null,
105
- decidedBy: r.decided_by ?? null,
106
- createdAt: iso(r.created_at),
107
- decidedAt: iso(r.decided_at),
108
- };
109
- }
110
84
  //# sourceMappingURL=pg-approval-store.js.map
@@ -2,15 +2,11 @@ import { CheckpointError, validatePendingSteer, checkpointVersionOf, winnerFromO
2
2
  import { redactDeep } from "../trace/redact.js";
3
3
  import { tokenFingerprint } from "./tidb-checkpoint-store.js";
4
4
  import { pgProtocolJsonStringify } from "./pg-safe-json.js";
5
+ import { parseJsonStrict as parseJson } from "./sql-row-helpers.js";
5
6
  const MAX_TOOL_INPUT_CHARS = 8192;
6
7
  const TERMINAL_BACKSTOP_MS = Math.max(60_000, Number(process.env.APPROVAL_TERMINAL_BACKSTOP_MS) || 30 * 86_400_000);
7
8
  const TERMINAL_GRACE_MS = 3_600_000;
8
9
  const PG_UNIQUE_VIOLATION = "23505";
9
- function parseJson(v) {
10
- if (v == null)
11
- return null;
12
- return (typeof v === "string" ? JSON.parse(v) : v);
13
- }
14
10
  function boundedToolInput(args) {
15
11
  if (args === undefined)
16
12
  return null;
@@ -1,6 +1,6 @@
1
1
  import type { Pool, PoolClient } from "pg";
2
- import type { BakeStatus, BakeState, BakeRecord, BakeEvent, CreateBakeInput, BakeTerminal } from "./tidb-image-bake.js";
3
- export type { BakeStatus, BakeState, BakeErrorCode, BakeRecord, BakeEvent, CreateBakeInput, BakeTerminal, } from "./tidb-image-bake.js";
2
+ import type { BakeStatus, BakeState, BakeRecord, BakeEvent, CreateBakeInput, BakeTerminal } from "./store-contracts.js";
3
+ export type { BakeStatus, BakeState, BakeErrorCode, BakeRecord, BakeEvent, CreateBakeInput, BakeTerminal, } from "./store-contracts.js";
4
4
  export declare const PG_IMAGE_BAKE_SCHEMA: string[];
5
5
  export declare function ensureSchema(pool: Pool | PoolClient, poolName?: string): Promise<void>;
6
6
  export declare class PgImageBake {
@@ -1,6 +1,8 @@
1
1
  import { uuidv7 } from "@sema-agent/core";
2
2
  import { randomBytes } from "node:crypto";
3
3
  import { pgSanitizeText, pgSafeJsonStringify, pgHasUnstorable } from "./pg-safe-json.js";
4
+ import { parseJsonOr as parseJson, toIso as iso } from "./sql-row-helpers.js";
5
+ import { mapBakeRow as mapRow, BAKE_SELECT_COLS as SELECT_COLS } from "./store-contracts.js";
4
6
  export const PG_IMAGE_BAKE_SCHEMA = [
5
7
  `CREATE TABLE IF NOT EXISTS image_bake (
6
8
  bake_id VARCHAR(64) NOT NULL,
@@ -74,60 +76,6 @@ function dupKeyName(err) {
74
76
  return "primary";
75
77
  return "other";
76
78
  }
77
- function iso(v) {
78
- return v instanceof Date ? v.toISOString() : String(v);
79
- }
80
- function isoOrNull(v) {
81
- if (v == null)
82
- return null;
83
- return v instanceof Date ? v.toISOString() : new Date(v).toISOString();
84
- }
85
- function parseJson(v, fallback) {
86
- if (v == null)
87
- return fallback;
88
- if (typeof v !== "string")
89
- return v;
90
- try {
91
- return JSON.parse(v);
92
- }
93
- catch {
94
- return fallback;
95
- }
96
- }
97
- function mapRow(r) {
98
- return {
99
- bakeId: r.bake_id,
100
- profile: r.profile,
101
- bands: r.bands == null ? null : parseJson(r.bands, []),
102
- baseRef: r.base_ref,
103
- push: !!r.push,
104
- dryRun: !!r.dry_run,
105
- logs: !!r.logs,
106
- argv: parseJson(r.argv, []),
107
- status: r.status,
108
- state: r.state ?? null,
109
- digest: r.digest,
110
- repo: r.repo,
111
- ref: r.ref,
112
- indexId: r.index_id,
113
- exitCode: r.exit_code === null ? null : Number(r.exit_code),
114
- error: r.error,
115
- errorCode: r.error_code ?? null,
116
- manifestSha: r.manifest_sha,
117
- tag: r.tag,
118
- idemKey: r.idem_key,
119
- ingestSecret: r.ingest_secret,
120
- runnerId: r.runner_id,
121
- leaseUntil: isoOrNull(r.lease_until),
122
- cancelRequested: !!r.cancel_requested,
123
- requestedBy: r.requested_by,
124
- createdAt: iso(r.created_at),
125
- updatedAt: iso(r.updated_at),
126
- };
127
- }
128
- const SELECT_COLS = "bake_id, profile, bands, base_ref, push, dry_run, logs, argv, status, state, digest, repo, ref, index_id, " +
129
- "exit_code, error, error_code, manifest_sha, tag, idem_key, ingest_secret, runner_id, lease_until, " +
130
- "cancel_requested, requested_by, created_at, updated_at";
131
79
  export class PgImageBake {
132
80
  pool;
133
81
  poolName;
@@ -1,6 +1,6 @@
1
1
  import type { Pool, PoolClient } from "pg";
2
- import { type ImageStatus, type ImageIndexEntry, type ImageIndexUpsert, type ImageViewer, type ImageListFilter } from "./tidb-image-index.js";
3
- export type { ImageNestedBuildMode, ImageCapabilities, ImagePodContract, ImageStatus, ImageVisibility, ImageIndexEntry, ImageIndexUpsert, ImageViewer, ImageListFilter, } from "./tidb-image-index.js";
2
+ import { type ImageStatus, type ImageIndexEntry, type ImageIndexUpsert, type ImageViewer, type ImageListFilter } from "./store-contracts.js";
3
+ export type { ImageNestedBuildMode, ImageCapabilities, ImagePodContract, ImageStatus, ImageVisibility, ImageIndexEntry, ImageIndexUpsert, ImageViewer, ImageListFilter, } from "./store-contracts.js";
4
4
  export declare const PG_IMAGE_INDEX_SCHEMA: string[];
5
5
  export declare function ensureSchema(pool: Pool | PoolClient): Promise<void>;
6
6
  export declare class PgImageIndex {
@@ -1,6 +1,6 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { pgSafeJsonStringify, pgSanitizeText, pgHasUnstorable, PgUnstorableError } from "./pg-safe-json.js";
3
- import {} from "./tidb-image-index.js";
3
+ import { mapImageRow as mapRow, } from "./store-contracts.js";
4
4
  export const PG_IMAGE_INDEX_SCHEMA = [
5
5
  `CREATE TABLE IF NOT EXISTS sandbox_image_index (
6
6
  id VARCHAR(64) NOT NULL,
@@ -37,49 +37,6 @@ export async function ensureSchema(pool) {
37
37
  }
38
38
  const MAX_LIMIT = 200;
39
39
  const DEFAULT_LIMIT = 50;
40
- function asJson(v, fallback) {
41
- if (v === null || v === undefined)
42
- return fallback;
43
- if (typeof v === "string") {
44
- try {
45
- return JSON.parse(v);
46
- }
47
- catch {
48
- return fallback;
49
- }
50
- }
51
- return v;
52
- }
53
- function iso(v) {
54
- if (v === null || v === undefined)
55
- return null;
56
- return v instanceof Date ? v.toISOString() : new Date(v).toISOString();
57
- }
58
- function mapRow(r) {
59
- return {
60
- id: r.id,
61
- profile: r.profile,
62
- bands: asJson(r.bands, []),
63
- repo: r.repo,
64
- tag: r.tag,
65
- digest: r.digest,
66
- toolchainVersions: asJson(r.toolchain_versions, {}),
67
- capabilities: asJson(r.capabilities, {}),
68
- podContract: asJson(r.pod_contract, {}),
69
- sizeBytes: r.size_bytes === null ? null : Number(r.size_bytes),
70
- status: r.status,
71
- visibility: r.visibility,
72
- tenantId: r.tenant_id,
73
- manifestSha: r.manifest_sha,
74
- recipeGitSha: r.recipe_git_sha,
75
- generatorVersion: r.generator_version,
76
- buildDate: iso(r.build_date),
77
- supersedes: r.supersedes,
78
- signed: !!r.signed,
79
- createdAt: iso(r.created_at) ?? new Date(0).toISOString(),
80
- updatedAt: iso(r.updated_at) ?? new Date(0).toISOString(),
81
- };
82
- }
83
40
  function visibilityClause(viewer, startIdx) {
84
41
  if (viewer.operator)
85
42
  return { sql: "1=1", params: [], nextIdx: startIdx };
@@ -1,5 +1,5 @@
1
1
  import pg from "pg";
2
- import type { ServiceConfig } from "../config.js";
2
+ import type { ServiceConfig } from "../config-types.js";
3
3
  export declare const PG_SCHEMA_STATEMENTS: readonly string[];
4
4
  export declare function pgPoolOptions(pgCfg: NonNullable<ServiceConfig["pg"]>, dbQueryTimeoutMs?: number): pg.PoolConfig;
5
5
  export declare function createPgPool(opts: string | pg.PoolConfig): pg.Pool;
@@ -1,7 +1,7 @@
1
1
  import type { TaskResult, TaskStatus } from "@sema-agent/core";
2
2
  import { type UsageRow } from "../usage-analytics.js";
3
3
  import type { Pool } from "pg";
4
- import type { RunRecord, RunEvent, SessionSummary } from "./tidb-run-store.js";
4
+ import type { RunRecord, RunEvent, SessionSummary } from "./store-contracts.js";
5
5
  export declare class PgRunStore {
6
6
  private readonly pool;
7
7
  constructor(pool: Pool);