@botbotgo/agent-harness 0.0.298 → 0.0.300

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 (166) hide show
  1. package/README.md +78 -38
  2. package/README.zh.md +80 -31
  3. package/dist/acp.d.ts +3 -0
  4. package/dist/acp.js +10 -2
  5. package/dist/api.d.ts +14 -2
  6. package/dist/api.js +19 -3
  7. package/dist/cli.d.ts +18 -1
  8. package/dist/cli.js +1408 -319
  9. package/dist/client/acp.d.ts +9 -3
  10. package/dist/client/acp.js +55 -1
  11. package/dist/client/in-process.d.ts +5 -2
  12. package/dist/client/in-process.js +4 -6
  13. package/dist/client/index.d.ts +1 -1
  14. package/dist/client/types.d.ts +6 -5
  15. package/dist/config/agents/direct.yaml +7 -17
  16. package/dist/config/agents/orchestra.yaml +9 -65
  17. package/dist/config/catalogs/embedding-models.yaml +1 -1
  18. package/dist/config/catalogs/stores.yaml +1 -1
  19. package/dist/config/knowledge/knowledge-runtime.yaml +36 -2
  20. package/dist/config/knowledge/procedural-memory-runtime.yaml +78 -0
  21. package/dist/config/{catalogs/models.yaml → models.yaml} +2 -2
  22. package/dist/config/prompts/direct-system.md +16 -0
  23. package/dist/config/prompts/orchestra-system.md +62 -0
  24. package/dist/config/prompts/routing-system.md +14 -0
  25. package/dist/config/runtime/runtime-memory.yaml +39 -5
  26. package/dist/config/runtime/workspace.yaml +7 -16
  27. package/dist/contracts/runtime.d.ts +242 -1
  28. package/dist/contracts/workspace.d.ts +2 -0
  29. package/dist/index.d.ts +5 -3
  30. package/dist/index.js +2 -1
  31. package/dist/init-project.js +178 -33
  32. package/dist/knowledge/contracts.d.ts +5 -0
  33. package/dist/knowledge/module.d.ts +5 -0
  34. package/dist/knowledge/module.js +340 -18
  35. package/dist/package-version.d.ts +1 -1
  36. package/dist/package-version.js +1 -1
  37. package/dist/persistence/file-store.d.ts +5 -1
  38. package/dist/persistence/file-store.js +16 -0
  39. package/dist/persistence/sqlite-store.d.ts +4 -1
  40. package/dist/persistence/sqlite-store.js +88 -14
  41. package/dist/persistence/types.d.ts +4 -1
  42. package/dist/procedural/config.d.ts +63 -0
  43. package/dist/procedural/config.js +125 -0
  44. package/dist/procedural/index.d.ts +2 -0
  45. package/dist/procedural/index.js +1 -0
  46. package/dist/protocol/ag-ui/http.d.ts +3 -0
  47. package/dist/protocol/ag-ui/http.js +10 -0
  48. package/dist/request-events.d.ts +63 -0
  49. package/dist/request-events.js +400 -0
  50. package/dist/resource/isolation.js +11 -0
  51. package/dist/resource/resource-impl.d.ts +1 -0
  52. package/dist/resource/resource-impl.js +103 -12
  53. package/dist/resources/init-templates/agent-context/deep-research.md +5 -0
  54. package/dist/resources/init-templates/prompts/research-analyst-basic.md +1 -0
  55. package/dist/resources/init-templates/prompts/research-analyst-web-search.md +1 -0
  56. package/dist/resources/init-templates/prompts/research-host-deep-research-basic.md +1 -0
  57. package/dist/resources/init-templates/prompts/research-host-deep-research-web-search.md +1 -0
  58. package/dist/resources/init-templates/prompts/research-host-single-agent-basic.md +1 -0
  59. package/dist/resources/init-templates/prompts/research-host-single-agent-web-search.md +1 -0
  60. package/dist/resources/prompts/runtime/browser-capability-disclaimer-recovery.md +1 -0
  61. package/dist/resources/prompts/runtime/default-subagent.md +2 -0
  62. package/dist/resources/prompts/runtime/durable-memory-context.md +7 -0
  63. package/dist/resources/prompts/runtime/execution-with-tool-evidence-retry.md +1 -0
  64. package/dist/resources/prompts/runtime/execution-with-tool-evidence.md +1 -0
  65. package/dist/resources/prompts/runtime/invalid-tool-selection-recovery.md +1 -0
  66. package/dist/resources/prompts/runtime/memory-manager.md +31 -0
  67. package/dist/resources/prompts/runtime/memory-mutation-reconciliation.md +22 -0
  68. package/dist/resources/prompts/runtime/slash-command-skill.md +6 -0
  69. package/dist/resources/prompts/runtime/strict-tool-json.md +1 -0
  70. package/dist/resources/prompts/runtime/workspace-boundary-guidance.md +3 -0
  71. package/dist/resources/prompts/runtime/workspace-relative-path.md +1 -0
  72. package/dist/resources/prompts/runtime/write-todos-descriptive-content.md +1 -0
  73. package/dist/resources/prompts/runtime/write-todos-full-entry.md +1 -0
  74. package/dist/resources/prompts/runtime/write-todos-non-empty-initial-list.md +1 -0
  75. package/dist/resources/tools/_runtime_tool_helpers.mjs +152 -0
  76. package/dist/resources/tools/cancel_request.mjs +21 -0
  77. package/dist/resources/tools/fetch_url.mjs +23 -0
  78. package/dist/resources/tools/http_request.mjs +30 -0
  79. package/dist/resources/tools/inspect_approvals.mjs +27 -0
  80. package/dist/resources/tools/inspect_artifacts.mjs +21 -0
  81. package/dist/resources/tools/inspect_events.mjs +21 -0
  82. package/dist/resources/tools/inspect_requests.mjs +27 -0
  83. package/dist/resources/tools/inspect_sessions.mjs +21 -0
  84. package/dist/resources/tools/list_files.mjs +27 -0
  85. package/dist/resources/tools/read_artifact.mjs +22 -0
  86. package/dist/resources/tools/request_approval.mjs +27 -0
  87. package/dist/resources/tools/run_command.mjs +21 -0
  88. package/dist/resources/tools/schedule_task.mjs +76 -0
  89. package/dist/resources/tools/search_files.mjs +47 -0
  90. package/dist/resources/tools/send_message.mjs +23 -0
  91. package/dist/runtime/adapter/direct-builtin-utility.d.ts +1 -0
  92. package/dist/runtime/adapter/direct-builtin-utility.js +90 -0
  93. package/dist/runtime/adapter/flow/execution-context.d.ts +1 -1
  94. package/dist/runtime/adapter/flow/execution-context.js +1 -1
  95. package/dist/runtime/adapter/flow/invocation-flow.d.ts +1 -0
  96. package/dist/runtime/adapter/flow/invocation-flow.js +9 -1
  97. package/dist/runtime/adapter/flow/invoke-runtime.d.ts +1 -1
  98. package/dist/runtime/adapter/flow/stream-runtime.d.ts +5 -1
  99. package/dist/runtime/adapter/flow/stream-runtime.js +556 -35
  100. package/dist/runtime/adapter/invocation-result.js +3 -2
  101. package/dist/runtime/adapter/local-tool-invocation.d.ts +1 -1
  102. package/dist/runtime/adapter/local-tool-invocation.js +28 -4
  103. package/dist/runtime/adapter/middleware-assembly.js +3 -1
  104. package/dist/runtime/adapter/model/invocation-request.d.ts +4 -1
  105. package/dist/runtime/adapter/model/invocation-request.js +138 -16
  106. package/dist/runtime/adapter/model/message-assembly.js +2 -6
  107. package/dist/runtime/adapter/model/model-providers.js +103 -5
  108. package/dist/runtime/adapter/resilience.js +17 -2
  109. package/dist/runtime/adapter/runtime-adapter-support.d.ts +11 -7
  110. package/dist/runtime/adapter/runtime-adapter-support.js +39 -5
  111. package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +63 -1
  112. package/dist/runtime/adapter/tool/builtin-middleware-tools.js +193 -21
  113. package/dist/runtime/adapter/tool/tool-arguments.d.ts +3 -1
  114. package/dist/runtime/adapter/tool/tool-arguments.js +52 -17
  115. package/dist/runtime/adapter/tool-resolution.d.ts +1 -0
  116. package/dist/runtime/adapter/tool-resolution.js +4 -2
  117. package/dist/runtime/agent-runtime-adapter.d.ts +27 -0
  118. package/dist/runtime/agent-runtime-adapter.js +163 -11
  119. package/dist/runtime/harness/events/event-bus.d.ts +1 -0
  120. package/dist/runtime/harness/events/event-bus.js +3 -0
  121. package/dist/runtime/harness/events/event-sink.d.ts +3 -0
  122. package/dist/runtime/harness/events/event-sink.js +16 -7
  123. package/dist/runtime/harness/events/streaming.d.ts +18 -1
  124. package/dist/runtime/harness/events/streaming.js +23 -10
  125. package/dist/runtime/harness/run/inspection.js +26 -5
  126. package/dist/runtime/harness/run/stream-run.d.ts +13 -4
  127. package/dist/runtime/harness/run/stream-run.js +448 -4
  128. package/dist/runtime/harness/run/surface-semantics.js +7 -34
  129. package/dist/runtime/harness/system/runtime-memory-manager.d.ts +3 -0
  130. package/dist/runtime/harness/system/runtime-memory-manager.js +384 -69
  131. package/dist/runtime/harness/system/runtime-memory-policy.d.ts +20 -1
  132. package/dist/runtime/harness/system/runtime-memory-policy.js +65 -17
  133. package/dist/runtime/harness/system/runtime-memory-records.js +100 -0
  134. package/dist/runtime/harness/system/runtime-memory-sync.js +2 -2
  135. package/dist/runtime/harness/system/store.d.ts +4 -0
  136. package/dist/runtime/harness/system/store.js +153 -0
  137. package/dist/runtime/harness.d.ts +9 -1
  138. package/dist/runtime/harness.js +141 -7
  139. package/dist/runtime/maintenance/sqlite-checkpoint-saver.d.ts +8 -3
  140. package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +152 -53
  141. package/dist/runtime/parsing/output-parsing.d.ts +10 -2
  142. package/dist/runtime/parsing/output-parsing.js +223 -16
  143. package/dist/runtime/parsing/stream-event-parsing.d.ts +7 -0
  144. package/dist/runtime/parsing/stream-event-parsing.js +51 -1
  145. package/dist/runtime/scheduling/system-schedule-manager.d.ts +41 -0
  146. package/dist/runtime/scheduling/system-schedule-manager.js +532 -0
  147. package/dist/runtime/support/embedding-models.d.ts +1 -1
  148. package/dist/runtime/support/embedding-models.js +5 -2
  149. package/dist/runtime/support/runtime-factories.js +1 -1
  150. package/dist/runtime/support/runtime-layout.d.ts +3 -0
  151. package/dist/runtime/support/runtime-layout.js +10 -1
  152. package/dist/runtime/support/runtime-prompts.d.ts +30 -0
  153. package/dist/runtime/support/runtime-prompts.js +55 -0
  154. package/dist/runtime/support/vector-stores.d.ts +1 -1
  155. package/dist/runtime/support/vector-stores.js +5 -2
  156. package/dist/upstream-events.js +8 -7
  157. package/dist/utils/bundled-text.d.ts +3 -0
  158. package/dist/utils/bundled-text.js +25 -0
  159. package/dist/utils/id.js +3 -2
  160. package/dist/workspace/agent-binding-compiler.js +53 -13
  161. package/dist/workspace/object-loader.js +64 -2
  162. package/dist/workspace/support/workspace-ref-utils.d.ts +2 -1
  163. package/dist/workspace/support/workspace-ref-utils.js +24 -5
  164. package/dist/workspace/yaml-object-reader.d.ts +1 -0
  165. package/dist/workspace/yaml-object-reader.js +95 -17
  166. package/package.json +11 -5
@@ -8,6 +8,16 @@ function asString(value) {
8
8
  function asPositiveInteger(value) {
9
9
  return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : undefined;
10
10
  }
11
+ function asStringArray(value) {
12
+ if (!Array.isArray(value)) {
13
+ return undefined;
14
+ }
15
+ const items = value
16
+ .filter((item) => typeof item === "string")
17
+ .map((item) => item.trim())
18
+ .filter((item) => item.length > 0);
19
+ return items.length > 0 ? Array.from(new Set(items)) : undefined;
20
+ }
11
21
  export function normalizeLangMemMemoryKind(kind) {
12
22
  const normalized = kind?.trim().toLowerCase();
13
23
  if (!normalized) {
@@ -26,14 +36,23 @@ export function readRuntimeMemoryPolicyConfig(runtimeMemory, workspaceRoot) {
26
36
  return undefined;
27
37
  }
28
38
  const retrieval = asRecord(runtimeMemory.retrieval);
39
+ const writePolicy = asRecord(runtimeMemory.writePolicy);
29
40
  const namespaces = asRecord(runtimeMemory.namespaces);
30
41
  const workspaceId = path.basename(workspaceRoot) || "default";
42
+ const writePolicyMode = writePolicy?.mode === "all" || writePolicy?.mode === "selective" || writePolicy?.mode === "disabled"
43
+ ? writePolicy.mode
44
+ : "all";
31
45
  return {
32
46
  enabled: true,
33
47
  retrieval: {
34
48
  defaultTopK: asPositiveInteger(retrieval?.defaultTopK) ?? 5,
35
49
  maxPromptMemories: asPositiveInteger(retrieval?.maxPromptMemories) ?? 8,
36
50
  },
51
+ writePolicy: {
52
+ mode: writePolicyMode,
53
+ allow: asStringArray(writePolicy?.allow) ?? [],
54
+ deny: asStringArray(writePolicy?.deny) ?? [],
55
+ },
37
56
  namespaces: {
38
57
  session: asString(namespaces?.sessions) ?? "memories/sessions/{sessionId}",
39
58
  workspace: asString(namespaces?.workspaces) ?? `memories/workspaces/${workspaceId}`,
@@ -65,24 +84,53 @@ export function resolveMemoryNamespace(template, values) {
65
84
  .map((part) => part.trim())
66
85
  .filter((part) => part.length > 0);
67
86
  }
68
- function tokenize(text) {
69
- return text
70
- .toLowerCase()
71
- .split(/[^a-z0-9_]+/i)
72
- .map((token) => token.trim())
73
- .filter((token) => token.length > 2);
87
+ export function hasExplicitResourceReference(text) {
88
+ const normalized = text.trim();
89
+ if (!normalized) {
90
+ return false;
91
+ }
92
+ return /(https?:\/\/|www\.)/iu.test(normalized);
93
+ }
94
+ export function extractExplicitResourceReferences(text) {
95
+ const normalized = text.trim();
96
+ if (!normalized) {
97
+ return [];
98
+ }
99
+ const matches = normalized.match(/https?:\/\/\S+/giu) ?? [];
100
+ return Array.from(new Set(matches.map((item) => item.trim().replace(/[),.;:!?]+$/u, ""))))
101
+ .filter((item) => item.length > 0);
102
+ }
103
+ export function shouldRecallDurableMemory(text) {
104
+ const normalized = text.trim();
105
+ if (!normalized) {
106
+ return false;
107
+ }
108
+ return !hasExplicitResourceReference(normalized);
109
+ }
110
+ function normalizePolicyLabel(value) {
111
+ return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
112
+ }
113
+ export function collectMemoryCandidateLabels(candidate) {
114
+ return Array.from(new Set([
115
+ ...(candidate.kind ? [normalizePolicyLabel(candidate.kind)] : []),
116
+ ...(candidate.scope ? [normalizePolicyLabel(candidate.scope)] : []),
117
+ ...(candidate.sourceType ? [normalizePolicyLabel(candidate.sourceType)] : []),
118
+ ...((candidate.tags ?? []).map((tag) => normalizePolicyLabel(tag))),
119
+ ]));
74
120
  }
75
- export function scoreMemoryText(query, content, scopeBoost = 0) {
76
- const queryTokens = new Set(tokenize(query));
77
- if (queryTokens.size === 0) {
78
- return scopeBoost;
121
+ export function shouldStoreMemoryCandidate(policy, candidate) {
122
+ if (!policy || policy.writePolicy.mode === "all") {
123
+ return true;
124
+ }
125
+ if (policy.writePolicy.mode === "disabled") {
126
+ return false;
127
+ }
128
+ const labels = new Set(collectMemoryCandidateLabels(candidate));
129
+ if (policy.writePolicy.deny.some((label) => labels.has(normalizePolicyLabel(label)))) {
130
+ return false;
79
131
  }
80
- const contentTokens = tokenize(content);
81
- let overlap = 0;
82
- for (const token of contentTokens) {
83
- if (queryTokens.has(token)) {
84
- overlap += 1;
85
- }
132
+ if (policy.writePolicy.allow.length === 0) {
133
+ return true;
86
134
  }
87
- return overlap + scopeBoost;
135
+ return policy.writePolicy.allow.some((label) => labels.has(normalizePolicyLabel(label)));
88
136
  }
@@ -23,7 +23,57 @@ function normalizeConfidence(value) {
23
23
  function normalizeSourceRef(value) {
24
24
  return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
25
25
  }
26
+ function normalizeOperationalRule(rule) {
27
+ if (!rule) {
28
+ return undefined;
29
+ }
30
+ const trigger = typeof rule.trigger === "string" ? rule.trigger.trim() : "";
31
+ const action = typeof rule.action === "string" ? rule.action.trim() : "";
32
+ const target = typeof rule.target === "string" ? rule.target.trim() : "";
33
+ if (!trigger || !action || !target) {
34
+ return undefined;
35
+ }
36
+ return {
37
+ trigger,
38
+ action,
39
+ target,
40
+ ...(rule.effect === "apply" || rule.effect === "invalidate" ? { effect: rule.effect } : {}),
41
+ };
42
+ }
43
+ function normalizeKnowledgeMutation(mutation) {
44
+ if (!mutation || typeof mutation !== "object") {
45
+ return undefined;
46
+ }
47
+ const identity = typeof mutation.identity === "string" ? mutation.identity.trim() : "";
48
+ if (!identity) {
49
+ return undefined;
50
+ }
51
+ const operation = mutation.operation === "update" || mutation.operation === "delete" ? mutation.operation : "create";
52
+ return { identity, operation };
53
+ }
54
+ function inferKnowledgeMutation(candidate) {
55
+ const explicit = normalizeKnowledgeMutation(candidate.knowledgeMutation);
56
+ if (explicit) {
57
+ return explicit;
58
+ }
59
+ const operationalRule = normalizeOperationalRule(candidate.operationalRule);
60
+ if (operationalRule) {
61
+ return {
62
+ identity: `rule:${createFingerprint([operationalRule.trigger, operationalRule.action, operationalRule.target].join("\n"))}`,
63
+ operation: operationalRule.effect === "invalidate" ? "delete" : "create",
64
+ };
65
+ }
66
+ return undefined;
67
+ }
26
68
  function createCanonicalKey(candidate, kind, scope) {
69
+ const knowledgeMutation = normalizeKnowledgeMutation(candidate.knowledgeMutation);
70
+ if (knowledgeMutation) {
71
+ return `${kind}:${scope}:knowledge:${createFingerprint(knowledgeMutation.identity)}`;
72
+ }
73
+ const operationalRule = normalizeOperationalRule(candidate.operationalRule);
74
+ if (operationalRule) {
75
+ return `${kind}:${scope}:rule:${createFingerprint([operationalRule.trigger, operationalRule.action, operationalRule.target].join("\n"))}`;
76
+ }
27
77
  const sourceRef = normalizeSourceRef(candidate.sourceRef);
28
78
  if (sourceRef) {
29
79
  return `${kind}:${scope}:source:${createFingerprint(sourceRef)}`;
@@ -105,6 +155,8 @@ function createMemoryRecord(candidate, options) {
105
155
  options.recordedAt,
106
156
  ].join("\n"));
107
157
  const sourceRef = normalizeSourceRef(candidate.sourceRef);
158
+ const operationalRule = normalizeOperationalRule(candidate.operationalRule);
159
+ const knowledgeMutation = inferKnowledgeMutation(candidate);
108
160
  return {
109
161
  id,
110
162
  canonicalKey,
@@ -120,6 +172,13 @@ function createMemoryRecord(candidate, options) {
120
172
  sourceType: candidate.sourceType?.trim() || "tool-output",
121
173
  sourceRefs: sourceRef ? [sourceRef] : [],
122
174
  tags: candidate.tags ?? [],
175
+ ...(knowledgeMutation
176
+ ? {
177
+ knowledgeIdentity: knowledgeMutation.identity,
178
+ knowledgeOperation: knowledgeMutation.operation,
179
+ }
180
+ : {}),
181
+ ...(operationalRule ? { operationalRule } : {}),
123
182
  provenance: {
124
183
  sessionId: options.sessionId,
125
184
  requestId: options.requestId,
@@ -191,6 +250,15 @@ function createReviewRecord(existing, incoming, recordedAt) {
191
250
  lastConfirmedAt: recordedAt,
192
251
  };
193
252
  }
253
+ function archiveRecord(record, incomingRecordId, recordedAt) {
254
+ return {
255
+ ...record,
256
+ status: "archived",
257
+ lastConfirmedAt: recordedAt,
258
+ supersedes: mergeUniqueStrings(record.supersedes, [incomingRecordId]),
259
+ revision: record.revision + 1,
260
+ };
261
+ }
194
262
  async function listStoredRecords(store, scope) {
195
263
  const scopes = scope ? [scope] : MEMORY_SCOPES;
196
264
  const docs = await Promise.all(scopes.map((currentScope) => store.search(buildScopeNamespace(currentScope))));
@@ -247,6 +315,31 @@ function evaluateDecision(existing, incoming, recordedAt) {
247
315
  }
248
316
  if (existing.canonicalKey === incoming.canonicalKey ||
249
317
  incoming.sourceRefs.some((sourceRef) => existing.sourceRefs.includes(sourceRef))) {
318
+ if (existing.knowledgeIdentity && incoming.knowledgeIdentity && existing.knowledgeIdentity === incoming.knowledgeIdentity) {
319
+ const existingOperation = existing.knowledgeOperation ?? "create";
320
+ const incomingOperation = incoming.knowledgeOperation ?? "create";
321
+ if (existingOperation !== incomingOperation || !isSameRecordContent(existing, incoming)) {
322
+ const archivedExisting = archiveRecord(existing, incoming.id, recordedAt);
323
+ const activeIncoming = {
324
+ ...incoming,
325
+ supersedes: mergeUniqueStrings(incoming.supersedes, [existing.id]),
326
+ };
327
+ return {
328
+ decision: {
329
+ action: "supersede",
330
+ reason: "Stored a newer knowledge mutation that supersedes the previous active state.",
331
+ recordId: activeIncoming.id,
332
+ kind: activeIncoming.kind,
333
+ scope: activeIncoming.scope,
334
+ confidence: activeIncoming.confidence,
335
+ maintenance: "merge",
336
+ reviewRequired: false,
337
+ },
338
+ primaryRecord: archivedExisting,
339
+ additionalRecords: [activeIncoming],
340
+ };
341
+ }
342
+ }
250
343
  if (hasNegationSignal(existing.content) !== hasNegationSignal(incoming.content)) {
251
344
  const conflictedExisting = markConflicted(existing, incoming.id, recordedAt);
252
345
  const pendingReview = createReviewRecord(conflictedExisting, incoming, recordedAt);
@@ -348,6 +441,13 @@ export function renderMemoryRecordsMarkdown(title, records) {
348
441
  lines.push(`- scope: ${record.scope}`);
349
442
  lines.push(`- status: ${record.status}`);
350
443
  lines.push(`- confidence: ${record.confidence.toFixed(2)}`);
444
+ if (record.knowledgeIdentity) {
445
+ lines.push(`- knowledge_identity: ${record.knowledgeIdentity}`);
446
+ lines.push(`- knowledge_operation: ${record.knowledgeOperation ?? "create"}`);
447
+ }
448
+ if (record.operationalRule) {
449
+ lines.push(`- operational_rule: ${record.operationalRule.trigger} -> ${record.operationalRule.action}(${record.operationalRule.target}) [${record.operationalRule.effect ?? "apply"}]`);
450
+ }
351
451
  if (record.tags.length > 0) {
352
452
  lines.push(`- tags: ${record.tags.join(", ")}`);
353
453
  }
@@ -88,8 +88,8 @@ export function readRuntimeMemorySyncConfig(runtimeMemory) {
88
88
  return undefined;
89
89
  }
90
90
  const ingestion = asRecord(runtimeMemory.ingestion);
91
- const writeOnApprovalResolution = asBoolean(ingestion?.writeOnApprovalResolution) ?? true;
92
- const writeOnRequestCompletion = asBoolean(ingestion?.writeOnRequestCompletion) ?? true;
91
+ const writeOnApprovalResolution = asBoolean(ingestion?.writeOnApprovalResolution) ?? false;
92
+ const writeOnRequestCompletion = asBoolean(ingestion?.writeOnRequestCompletion) ?? false;
93
93
  if (!writeOnApprovalResolution && !writeOnRequestCompletion) {
94
94
  return undefined;
95
95
  }
@@ -57,6 +57,10 @@ export declare class SqliteBackedStore {
57
57
  constructor(filePath: string);
58
58
  private getClient;
59
59
  private ensureInitialized;
60
+ private ensureKnowledgeRecordEntryColumns;
61
+ private backfillKnowledgeRecordEntries;
62
+ private upsertKnowledgeRecordEntry;
63
+ private deleteKnowledgeRecordEntry;
60
64
  private selectAll;
61
65
  batch(operations: Array<Record<string, unknown>>): Promise<readonly unknown[]>;
62
66
  get(namespace: string[], key: string): Promise<{
@@ -65,6 +65,45 @@ function parseRow(row) {
65
65
  updatedAt: new Date(row.updated_at),
66
66
  };
67
67
  }
68
+ function isKnowledgeRecordNamespace(namespace) {
69
+ return namespace.length === 3 && namespace[0] === "memories" && namespace[1] === "records";
70
+ }
71
+ function extractKnowledgeRecordEntry(namespace, key, value, createdAt, updatedAt) {
72
+ if (!isKnowledgeRecordNamespace(namespace) || typeof value !== "object" || value === null || Array.isArray(value)) {
73
+ return null;
74
+ }
75
+ const typed = value;
76
+ const recordId = typeof typed.id === "string" ? typed.id : undefined;
77
+ const scope = typeof typed.scope === "string" ? typed.scope : undefined;
78
+ const kind = typeof typed.kind === "string" ? typed.kind : undefined;
79
+ const status = typeof typed.status === "string" ? typed.status : undefined;
80
+ const canonicalKey = typeof typed.canonicalKey === "string" ? typed.canonicalKey : undefined;
81
+ const sourceType = typeof typed.sourceType === "string" ? typed.sourceType : undefined;
82
+ const summary = typeof typed.summary === "string" ? typed.summary : undefined;
83
+ const content = typeof typed.content === "string" ? typed.content : undefined;
84
+ if (!recordId || !scope || !kind || !status || !canonicalKey || !sourceType || !summary || !content) {
85
+ return null;
86
+ }
87
+ return {
88
+ namespace: serializeNamespace(namespace),
89
+ key,
90
+ record_id: recordId,
91
+ scope,
92
+ kind,
93
+ status,
94
+ canonical_key: canonicalKey,
95
+ source_type: sourceType,
96
+ knowledge_identity: typeof typed.knowledgeIdentity === "string" ? typed.knowledgeIdentity : null,
97
+ knowledge_operation: typeof typed.knowledgeOperation === "string" ? typed.knowledgeOperation : null,
98
+ summary_text: summary,
99
+ content_text: content,
100
+ confidence: typeof typed.confidence === "number" ? typed.confidence : null,
101
+ observed_at: typeof typed.observedAt === "string" ? typed.observedAt : null,
102
+ last_confirmed_at: typeof typed.lastConfirmedAt === "string" ? typed.lastConfirmedAt : null,
103
+ created_at: createdAt,
104
+ updated_at: updatedAt,
105
+ };
106
+ }
68
107
  export class FileBackedStore {
69
108
  filePath;
70
109
  delegate = new InMemoryStore();
@@ -186,11 +225,117 @@ export class SqliteBackedStore {
186
225
  )
187
226
  `);
188
227
  await client.execute("CREATE INDEX IF NOT EXISTS idx_store_entries_namespace ON store_entries(namespace)");
228
+ await client.execute(`
229
+ CREATE TABLE IF NOT EXISTS knowledge_record_entries (
230
+ namespace TEXT NOT NULL,
231
+ key TEXT NOT NULL,
232
+ record_id TEXT NOT NULL,
233
+ scope TEXT NOT NULL,
234
+ kind TEXT NOT NULL,
235
+ status TEXT NOT NULL,
236
+ canonical_key TEXT NOT NULL,
237
+ source_type TEXT NOT NULL,
238
+ knowledge_identity TEXT,
239
+ knowledge_operation TEXT,
240
+ summary_text TEXT NOT NULL,
241
+ content_text TEXT NOT NULL,
242
+ confidence REAL,
243
+ observed_at TEXT,
244
+ last_confirmed_at TEXT,
245
+ created_at TEXT NOT NULL,
246
+ updated_at TEXT NOT NULL,
247
+ PRIMARY KEY (namespace, key)
248
+ )
249
+ `);
250
+ await this.ensureKnowledgeRecordEntryColumns(client);
251
+ await client.execute("CREATE INDEX IF NOT EXISTS idx_knowledge_record_entries_scope_status ON knowledge_record_entries(scope, status)");
252
+ await client.execute("CREATE INDEX IF NOT EXISTS idx_knowledge_record_entries_canonical_key ON knowledge_record_entries(canonical_key)");
253
+ await client.execute("CREATE INDEX IF NOT EXISTS idx_knowledge_record_entries_knowledge_identity ON knowledge_record_entries(knowledge_identity)");
254
+ await client.execute("CREATE INDEX IF NOT EXISTS idx_knowledge_record_entries_record_id ON knowledge_record_entries(record_id)");
255
+ await this.backfillKnowledgeRecordEntries(client);
189
256
  this.initialized = true;
190
257
  this.initialization = null;
191
258
  })();
192
259
  await this.initialization;
193
260
  }
261
+ async ensureKnowledgeRecordEntryColumns(client) {
262
+ const result = await client.execute("PRAGMA table_info(knowledge_record_entries)");
263
+ const existing = new Set(result.rows.map((row) => String(row.name ?? "")));
264
+ if (!existing.has("knowledge_identity")) {
265
+ await client.execute("ALTER TABLE knowledge_record_entries ADD COLUMN knowledge_identity TEXT");
266
+ }
267
+ if (!existing.has("knowledge_operation")) {
268
+ await client.execute("ALTER TABLE knowledge_record_entries ADD COLUMN knowledge_operation TEXT");
269
+ }
270
+ }
271
+ async backfillKnowledgeRecordEntries(client) {
272
+ const countResult = await client.execute("SELECT COUNT(*) AS count FROM knowledge_record_entries");
273
+ const count = Number(countResult.rows?.[0]?.count ?? 0);
274
+ if (count > 0) {
275
+ return;
276
+ }
277
+ const result = await client.execute({
278
+ sql: `SELECT namespace, namespace_json, key, value_json, created_at, updated_at
279
+ FROM store_entries
280
+ WHERE namespace LIKE ?`,
281
+ args: [`memories${NAMESPACE_SEPARATOR}records${NAMESPACE_SEPARATOR}%`],
282
+ });
283
+ for (const row of result.rows) {
284
+ const namespace = JSON.parse(row.namespace_json);
285
+ const entry = extractKnowledgeRecordEntry(namespace, row.key, decodeValue(JSON.parse(row.value_json)), row.created_at, row.updated_at);
286
+ if (entry) {
287
+ await this.upsertKnowledgeRecordEntry(client, entry);
288
+ }
289
+ }
290
+ }
291
+ async upsertKnowledgeRecordEntry(client, entry) {
292
+ await client.execute({
293
+ sql: `INSERT INTO knowledge_record_entries (
294
+ namespace, key, record_id, scope, kind, status, canonical_key, source_type,
295
+ knowledge_identity, knowledge_operation, summary_text, content_text, confidence, observed_at, last_confirmed_at, created_at, updated_at
296
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
297
+ ON CONFLICT(namespace, key) DO UPDATE SET
298
+ record_id = excluded.record_id,
299
+ scope = excluded.scope,
300
+ kind = excluded.kind,
301
+ status = excluded.status,
302
+ canonical_key = excluded.canonical_key,
303
+ source_type = excluded.source_type,
304
+ knowledge_identity = excluded.knowledge_identity,
305
+ knowledge_operation = excluded.knowledge_operation,
306
+ summary_text = excluded.summary_text,
307
+ content_text = excluded.content_text,
308
+ confidence = excluded.confidence,
309
+ observed_at = excluded.observed_at,
310
+ last_confirmed_at = excluded.last_confirmed_at,
311
+ updated_at = excluded.updated_at`,
312
+ args: [
313
+ entry.namespace,
314
+ entry.key,
315
+ entry.record_id,
316
+ entry.scope,
317
+ entry.kind,
318
+ entry.status,
319
+ entry.canonical_key,
320
+ entry.source_type,
321
+ entry.knowledge_identity,
322
+ entry.knowledge_operation,
323
+ entry.summary_text,
324
+ entry.content_text,
325
+ entry.confidence,
326
+ entry.observed_at,
327
+ entry.last_confirmed_at,
328
+ entry.created_at,
329
+ entry.updated_at,
330
+ ],
331
+ });
332
+ }
333
+ async deleteKnowledgeRecordEntry(client, namespace, key) {
334
+ await client.execute({
335
+ sql: `DELETE FROM knowledge_record_entries WHERE namespace = ? AND key = ?`,
336
+ args: [serializeNamespace(namespace), key],
337
+ });
338
+ }
194
339
  async selectAll(sql, args = []) {
195
340
  await this.ensureInitialized();
196
341
  const client = await this.getClient();
@@ -246,6 +391,13 @@ export class SqliteBackedStore {
246
391
  updated_at = excluded.updated_at`,
247
392
  args: [serializedNamespace, JSON.stringify(namespace), key, encodedValue, now, now],
248
393
  });
394
+ const knowledgeEntry = extractKnowledgeRecordEntry(namespace, key, value, now, now);
395
+ if (knowledgeEntry) {
396
+ await this.upsertKnowledgeRecordEntry(client, knowledgeEntry);
397
+ }
398
+ else {
399
+ await this.deleteKnowledgeRecordEntry(client, namespace, key);
400
+ }
249
401
  }
250
402
  async delete(namespace, key) {
251
403
  await this.ensureInitialized();
@@ -254,6 +406,7 @@ export class SqliteBackedStore {
254
406
  sql: `DELETE FROM store_entries WHERE namespace = ? AND key = ?`,
255
407
  args: [serializeNamespace(namespace), key],
256
408
  });
409
+ await this.deleteKnowledgeRecordEntry(client, namespace, key);
257
410
  }
258
411
  async listNamespaces() {
259
412
  const rows = await this.selectAll(`SELECT DISTINCT namespace_json
@@ -1,7 +1,8 @@
1
- import type { ApprovalRecord, ArtifactListing, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, RuntimeOperatorOverview, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RequestOptions, RequestRecord, RequestResult, RequestSummary, RequestStartOptions, RestartConversationOptions, RuntimeAdapterOptions, RuntimeArtifactWriteInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRequestPackage, RuntimeRequestPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, ResumeOptions, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, SessionSummary, SessionRecord, SessionListSummary, WorkspaceBundle } from "../contracts/types.js";
1
+ import type { ApprovalRecord, ArtifactListing, CancelOptions, HarnessEvent, HarnessStreamItem, RuntimeHealthSnapshot, RuntimeOperatorOverview, ListMemoriesInput, ListMemoriesResult, MessageContent, RemoveMemoryInput, RequestPlanState, RequestOptions, RequestRecord, RequestResult, RequestSummary, RequestStartOptions, RestartConversationOptions, RuntimeAdapterOptions, RuntimeArtifactWriteInput, RuntimeEvaluationExport, RuntimeEvaluationExportInput, RuntimeEvaluationReplayInput, RuntimeEvaluationReplayResult, RuntimeRequestPackage, RuntimeRequestPackageInput, RuntimeSessionPackage, RuntimeSessionPackageInput, ResumeOptions, MemoryRecord, MemorizeInput, MemorizeResult, RecallInput, RecallResult, UpdateMemoryInput, SessionSummary, SessionRecord, SessionListSummary, WorkspaceBundle } from "../contracts/types.js";
2
2
  import { type RuntimeMcpServerOptions, type ToolMcpServerOptions } from "../mcp.js";
3
3
  import { type InventoryAgentRecord, type InventorySkillRecord } from "./harness/system/inventory.js";
4
4
  import type { RequirementAssessmentOptions } from "./harness/system/skill-requirements.js";
5
+ import { SystemScheduleManager } from "./scheduling/system-schedule-manager.js";
5
6
  export declare class AgentHarnessRuntime {
6
7
  private readonly workspace;
7
8
  private readonly runtimeAdapterOptions;
@@ -36,6 +37,7 @@ export declare class AgentHarnessRuntime {
36
37
  private readonly runtimeMemoryFormationSync;
37
38
  private readonly unregisterRuntimeMemoryFormationSync;
38
39
  private readonly resolvedRuntimeAdapterOptions;
40
+ private readonly scheduleManager;
39
41
  private readonly healthMonitor;
40
42
  private readonly recoveryConfig;
41
43
  private readonly concurrencyConfig;
@@ -54,7 +56,11 @@ export declare class AgentHarnessRuntime {
54
56
  private getDefaultRuntimeEntryAgentId;
55
57
  private resolveSelectedAgentId;
56
58
  private createPrepareRunStartRuntime;
59
+ private buildFunctionToolContext;
57
60
  constructor(workspace: WorkspaceBundle, runtimeAdapterOptions?: RuntimeAdapterOptions);
61
+ manageSchedule(input: Parameters<SystemScheduleManager["manageSchedule"]>[0]): Promise<import("../contracts/runtime.js").RuntimeScheduleManageResult>;
62
+ getSchedule(scheduleId: string): Promise<import("../contracts/runtime.js").RuntimeScheduleRecord | null>;
63
+ runScheduledTask(scheduleId: string): Promise<RequestResult>;
58
64
  private createHealthMonitor;
59
65
  private recordLlmSuccess;
60
66
  private recordLlmFailure;
@@ -81,6 +87,7 @@ export declare class AgentHarnessRuntime {
81
87
  updateMemory(input: UpdateMemoryInput): Promise<MemoryRecord>;
82
88
  removeMemory(input: RemoveMemoryInput): Promise<MemoryRecord>;
83
89
  getRequest(requestId: string): Promise<RequestRecord | null>;
90
+ getRequestPlanState(sessionId: string, requestId: string): Promise<RequestPlanState | null>;
84
91
  private getSessionSummary;
85
92
  private getSessionSummaryRecord;
86
93
  getSession(sessionId: string): Promise<SessionRecord | null>;
@@ -128,6 +135,7 @@ export declare class AgentHarnessRuntime {
128
135
  private getWorkspaceId;
129
136
  private buildRuntimeMemoryContext;
130
137
  private persistRuntimeMemoryCandidates;
138
+ private persistRequestPlanState;
131
139
  private resolvePersistedRequestPriority;
132
140
  private enqueuePendingRequestSlot;
133
141
  private executeQueuedRequest;