@botbotgo/agent-harness 0.0.298 → 0.0.299
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -37
- package/README.zh.md +79 -30
- package/dist/acp.d.ts +3 -0
- package/dist/acp.js +10 -2
- package/dist/api.d.ts +14 -2
- package/dist/api.js +19 -3
- package/dist/cli.d.ts +18 -1
- package/dist/cli.js +1408 -319
- package/dist/client/acp.d.ts +9 -3
- package/dist/client/acp.js +55 -1
- package/dist/client/in-process.d.ts +5 -2
- package/dist/client/in-process.js +4 -6
- package/dist/client/index.d.ts +1 -1
- package/dist/client/types.d.ts +6 -5
- package/dist/config/agents/direct.yaml +7 -17
- package/dist/config/agents/orchestra.yaml +9 -65
- package/dist/config/catalogs/embedding-models.yaml +1 -1
- package/dist/config/catalogs/stores.yaml +1 -1
- package/dist/config/knowledge/knowledge-runtime.yaml +36 -2
- package/dist/config/knowledge/procedural-memory-runtime.yaml +78 -0
- package/dist/config/{catalogs/models.yaml → models.yaml} +2 -2
- package/dist/config/prompts/direct-system.md +16 -0
- package/dist/config/prompts/orchestra-system.md +62 -0
- package/dist/config/prompts/routing-system.md +14 -0
- package/dist/config/runtime/runtime-memory.yaml +39 -5
- package/dist/config/runtime/workspace.yaml +7 -16
- package/dist/contracts/runtime.d.ts +242 -1
- package/dist/contracts/workspace.d.ts +2 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +2 -1
- package/dist/init-project.js +178 -33
- package/dist/knowledge/contracts.d.ts +5 -0
- package/dist/knowledge/module.d.ts +5 -0
- package/dist/knowledge/module.js +340 -18
- package/dist/package-version.d.ts +1 -1
- package/dist/package-version.js +1 -1
- package/dist/persistence/file-store.d.ts +5 -1
- package/dist/persistence/file-store.js +16 -0
- package/dist/persistence/sqlite-store.d.ts +4 -1
- package/dist/persistence/sqlite-store.js +88 -14
- package/dist/persistence/types.d.ts +4 -1
- package/dist/procedural/config.d.ts +63 -0
- package/dist/procedural/config.js +125 -0
- package/dist/procedural/index.d.ts +2 -0
- package/dist/procedural/index.js +1 -0
- package/dist/protocol/ag-ui/http.d.ts +3 -0
- package/dist/protocol/ag-ui/http.js +10 -0
- package/dist/request-events.d.ts +63 -0
- package/dist/request-events.js +400 -0
- package/dist/resource/isolation.js +11 -0
- package/dist/resource/resource-impl.d.ts +1 -0
- package/dist/resource/resource-impl.js +103 -12
- package/dist/resources/init-templates/agent-context/deep-research.md +5 -0
- package/dist/resources/init-templates/prompts/research-analyst-basic.md +1 -0
- package/dist/resources/init-templates/prompts/research-analyst-web-search.md +1 -0
- package/dist/resources/init-templates/prompts/research-host-deep-research-basic.md +1 -0
- package/dist/resources/init-templates/prompts/research-host-deep-research-web-search.md +1 -0
- package/dist/resources/init-templates/prompts/research-host-single-agent-basic.md +1 -0
- package/dist/resources/init-templates/prompts/research-host-single-agent-web-search.md +1 -0
- package/dist/resources/prompts/runtime/browser-capability-disclaimer-recovery.md +1 -0
- package/dist/resources/prompts/runtime/default-subagent.md +2 -0
- package/dist/resources/prompts/runtime/durable-memory-context.md +7 -0
- package/dist/resources/prompts/runtime/execution-with-tool-evidence-retry.md +1 -0
- package/dist/resources/prompts/runtime/execution-with-tool-evidence.md +1 -0
- package/dist/resources/prompts/runtime/invalid-tool-selection-recovery.md +1 -0
- package/dist/resources/prompts/runtime/memory-manager.md +31 -0
- package/dist/resources/prompts/runtime/memory-mutation-reconciliation.md +22 -0
- package/dist/resources/prompts/runtime/slash-command-skill.md +6 -0
- package/dist/resources/prompts/runtime/strict-tool-json.md +1 -0
- package/dist/resources/prompts/runtime/workspace-boundary-guidance.md +3 -0
- package/dist/resources/prompts/runtime/workspace-relative-path.md +1 -0
- package/dist/resources/prompts/runtime/write-todos-descriptive-content.md +1 -0
- package/dist/resources/prompts/runtime/write-todos-full-entry.md +1 -0
- package/dist/resources/prompts/runtime/write-todos-non-empty-initial-list.md +1 -0
- package/dist/resources/tools/_runtime_tool_helpers.mjs +152 -0
- package/dist/resources/tools/cancel_request.mjs +21 -0
- package/dist/resources/tools/fetch_url.mjs +23 -0
- package/dist/resources/tools/http_request.mjs +30 -0
- package/dist/resources/tools/inspect_approvals.mjs +27 -0
- package/dist/resources/tools/inspect_artifacts.mjs +21 -0
- package/dist/resources/tools/inspect_events.mjs +21 -0
- package/dist/resources/tools/inspect_requests.mjs +27 -0
- package/dist/resources/tools/inspect_sessions.mjs +21 -0
- package/dist/resources/tools/list_files.mjs +27 -0
- package/dist/resources/tools/read_artifact.mjs +22 -0
- package/dist/resources/tools/request_approval.mjs +27 -0
- package/dist/resources/tools/run_command.mjs +21 -0
- package/dist/resources/tools/schedule_task.mjs +76 -0
- package/dist/resources/tools/search_files.mjs +47 -0
- package/dist/resources/tools/send_message.mjs +23 -0
- package/dist/runtime/adapter/direct-builtin-utility.d.ts +1 -0
- package/dist/runtime/adapter/direct-builtin-utility.js +90 -0
- package/dist/runtime/adapter/flow/execution-context.d.ts +1 -1
- package/dist/runtime/adapter/flow/execution-context.js +1 -1
- package/dist/runtime/adapter/flow/invocation-flow.d.ts +1 -0
- package/dist/runtime/adapter/flow/invocation-flow.js +9 -1
- package/dist/runtime/adapter/flow/invoke-runtime.d.ts +1 -1
- package/dist/runtime/adapter/flow/stream-runtime.d.ts +5 -1
- package/dist/runtime/adapter/flow/stream-runtime.js +556 -35
- package/dist/runtime/adapter/invocation-result.js +3 -2
- package/dist/runtime/adapter/local-tool-invocation.d.ts +1 -1
- package/dist/runtime/adapter/local-tool-invocation.js +28 -4
- package/dist/runtime/adapter/middleware-assembly.js +3 -1
- package/dist/runtime/adapter/model/invocation-request.d.ts +4 -1
- package/dist/runtime/adapter/model/invocation-request.js +138 -16
- package/dist/runtime/adapter/model/message-assembly.js +2 -6
- package/dist/runtime/adapter/model/model-providers.js +103 -5
- package/dist/runtime/adapter/resilience.js +17 -2
- package/dist/runtime/adapter/runtime-adapter-support.d.ts +11 -7
- package/dist/runtime/adapter/runtime-adapter-support.js +39 -5
- package/dist/runtime/adapter/tool/builtin-middleware-tools.d.ts +63 -1
- package/dist/runtime/adapter/tool/builtin-middleware-tools.js +193 -21
- package/dist/runtime/adapter/tool/tool-arguments.d.ts +3 -1
- package/dist/runtime/adapter/tool/tool-arguments.js +52 -17
- package/dist/runtime/adapter/tool-resolution.d.ts +1 -0
- package/dist/runtime/adapter/tool-resolution.js +4 -2
- package/dist/runtime/agent-runtime-adapter.d.ts +27 -0
- package/dist/runtime/agent-runtime-adapter.js +163 -11
- package/dist/runtime/harness/events/event-bus.d.ts +1 -0
- package/dist/runtime/harness/events/event-bus.js +3 -0
- package/dist/runtime/harness/events/event-sink.d.ts +3 -0
- package/dist/runtime/harness/events/event-sink.js +16 -7
- package/dist/runtime/harness/events/streaming.d.ts +18 -1
- package/dist/runtime/harness/events/streaming.js +23 -10
- package/dist/runtime/harness/run/inspection.js +26 -5
- package/dist/runtime/harness/run/stream-run.d.ts +13 -4
- package/dist/runtime/harness/run/stream-run.js +448 -4
- package/dist/runtime/harness/run/surface-semantics.js +7 -34
- package/dist/runtime/harness/system/runtime-memory-manager.d.ts +3 -0
- package/dist/runtime/harness/system/runtime-memory-manager.js +384 -69
- package/dist/runtime/harness/system/runtime-memory-policy.d.ts +20 -1
- package/dist/runtime/harness/system/runtime-memory-policy.js +65 -17
- package/dist/runtime/harness/system/runtime-memory-records.js +100 -0
- package/dist/runtime/harness/system/runtime-memory-sync.js +2 -2
- package/dist/runtime/harness/system/store.d.ts +4 -0
- package/dist/runtime/harness/system/store.js +153 -0
- package/dist/runtime/harness.d.ts +9 -1
- package/dist/runtime/harness.js +141 -7
- package/dist/runtime/maintenance/sqlite-checkpoint-saver.d.ts +8 -3
- package/dist/runtime/maintenance/sqlite-checkpoint-saver.js +152 -53
- package/dist/runtime/parsing/output-parsing.d.ts +10 -2
- package/dist/runtime/parsing/output-parsing.js +223 -16
- package/dist/runtime/parsing/stream-event-parsing.d.ts +7 -0
- package/dist/runtime/parsing/stream-event-parsing.js +51 -1
- package/dist/runtime/scheduling/system-schedule-manager.d.ts +41 -0
- package/dist/runtime/scheduling/system-schedule-manager.js +532 -0
- package/dist/runtime/support/embedding-models.d.ts +1 -1
- package/dist/runtime/support/embedding-models.js +5 -2
- package/dist/runtime/support/runtime-factories.js +1 -1
- package/dist/runtime/support/runtime-layout.d.ts +3 -0
- package/dist/runtime/support/runtime-layout.js +10 -1
- package/dist/runtime/support/runtime-prompts.d.ts +30 -0
- package/dist/runtime/support/runtime-prompts.js +55 -0
- package/dist/runtime/support/vector-stores.d.ts +1 -1
- package/dist/runtime/support/vector-stores.js +5 -2
- package/dist/upstream-events.js +8 -7
- package/dist/utils/bundled-text.d.ts +3 -0
- package/dist/utils/bundled-text.js +25 -0
- package/dist/utils/id.js +3 -2
- package/dist/workspace/agent-binding-compiler.js +53 -13
- package/dist/workspace/object-loader.js +64 -2
- package/dist/workspace/support/workspace-ref-utils.d.ts +2 -1
- package/dist/workspace/support/workspace-ref-utils.js +24 -5
- package/dist/workspace/yaml-object-reader.d.ts +1 -0
- package/dist/workspace/yaml-object-reader.js +95 -17
- 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
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
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
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
-
|
|
81
|
-
|
|
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
|
|
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) ??
|
|
92
|
-
const writeOnRequestCompletion = asBoolean(ingestion?.writeOnRequestCompletion) ??
|
|
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;
|