opencode-swarm 7.32.1 → 7.32.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +27 -3
- package/dist/config/schema.d.ts +14 -0
- package/dist/full-auto/critic-response-parser.d.ts +30 -0
- package/dist/full-auto/oversight.d.ts +2 -7
- package/dist/hooks/full-auto-intercept.d.ts +2 -7
- package/dist/index.js +253 -130
- package/dist/memory/config.d.ts +7 -0
- package/dist/memory/gateway.d.ts +3 -1
- package/dist/memory/index.d.ts +1 -1
- package/dist/memory/injector.d.ts +1 -1
- package/dist/memory/local-jsonl-provider.d.ts +5 -0
- package/dist/memory/prompt-block.d.ts +1 -0
- package/dist/memory/provider.d.ts +6 -0
- package/dist/memory/run-log.d.ts +1 -1
- package/dist/memory/scoring.d.ts +12 -0
- package/dist/memory/types.d.ts +19 -0
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -34,7 +34,7 @@ var package_default;
|
|
|
34
34
|
var init_package = __esm(() => {
|
|
35
35
|
package_default = {
|
|
36
36
|
name: "opencode-swarm",
|
|
37
|
-
version: "7.32.
|
|
37
|
+
version: "7.32.3",
|
|
38
38
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
39
39
|
main: "dist/index.js",
|
|
40
40
|
types: "dist/index.d.ts",
|
|
@@ -17331,8 +17331,32 @@ var init_schema = __esm(() => {
|
|
|
17331
17331
|
recall: exports_external.object({
|
|
17332
17332
|
defaultMaxItems: exports_external.number().int().min(1).max(20).default(8),
|
|
17333
17333
|
defaultTokenBudget: exports_external.number().int().min(100).max(5000).default(1200),
|
|
17334
|
-
minScore: exports_external.number().min(0).max(1).default(0.05)
|
|
17335
|
-
|
|
17334
|
+
minScore: exports_external.number().min(0).max(1).default(0.05),
|
|
17335
|
+
injection: exports_external.object({
|
|
17336
|
+
enabled: exports_external.boolean().default(true),
|
|
17337
|
+
minScore: exports_external.number().min(0).max(1).default(0.25),
|
|
17338
|
+
requireQuerySignal: exports_external.boolean().default(true),
|
|
17339
|
+
maxItems: exports_external.number().int().min(1).max(20).default(6),
|
|
17340
|
+
tokenBudget: exports_external.number().int().min(100).max(5000).default(1000)
|
|
17341
|
+
}).default({
|
|
17342
|
+
enabled: true,
|
|
17343
|
+
minScore: 0.25,
|
|
17344
|
+
requireQuerySignal: true,
|
|
17345
|
+
maxItems: 6,
|
|
17346
|
+
tokenBudget: 1000
|
|
17347
|
+
})
|
|
17348
|
+
}).default({
|
|
17349
|
+
defaultMaxItems: 8,
|
|
17350
|
+
defaultTokenBudget: 1200,
|
|
17351
|
+
minScore: 0.05,
|
|
17352
|
+
injection: {
|
|
17353
|
+
enabled: true,
|
|
17354
|
+
minScore: 0.25,
|
|
17355
|
+
requireQuerySignal: true,
|
|
17356
|
+
maxItems: 6,
|
|
17357
|
+
tokenBudget: 1000
|
|
17358
|
+
}
|
|
17359
|
+
}),
|
|
17336
17360
|
writes: exports_external.object({
|
|
17337
17361
|
mode: exports_external.literal("propose").default("propose")
|
|
17338
17362
|
}).default({ mode: "propose" }),
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -510,6 +510,13 @@ export declare const MemoryConfigSchema: z.ZodObject<{
|
|
|
510
510
|
defaultMaxItems: z.ZodDefault<z.ZodNumber>;
|
|
511
511
|
defaultTokenBudget: z.ZodDefault<z.ZodNumber>;
|
|
512
512
|
minScore: z.ZodDefault<z.ZodNumber>;
|
|
513
|
+
injection: z.ZodDefault<z.ZodObject<{
|
|
514
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
515
|
+
minScore: z.ZodDefault<z.ZodNumber>;
|
|
516
|
+
requireQuerySignal: z.ZodDefault<z.ZodBoolean>;
|
|
517
|
+
maxItems: z.ZodDefault<z.ZodNumber>;
|
|
518
|
+
tokenBudget: z.ZodDefault<z.ZodNumber>;
|
|
519
|
+
}, z.core.$strip>>;
|
|
513
520
|
}, z.core.$strip>>;
|
|
514
521
|
writes: z.ZodDefault<z.ZodObject<{
|
|
515
522
|
mode: z.ZodDefault<z.ZodLiteral<"propose">>;
|
|
@@ -1161,6 +1168,13 @@ export declare const PluginConfigSchema: z.ZodObject<{
|
|
|
1161
1168
|
defaultMaxItems: z.ZodDefault<z.ZodNumber>;
|
|
1162
1169
|
defaultTokenBudget: z.ZodDefault<z.ZodNumber>;
|
|
1163
1170
|
minScore: z.ZodDefault<z.ZodNumber>;
|
|
1171
|
+
injection: z.ZodDefault<z.ZodObject<{
|
|
1172
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
1173
|
+
minScore: z.ZodDefault<z.ZodNumber>;
|
|
1174
|
+
requireQuerySignal: z.ZodDefault<z.ZodBoolean>;
|
|
1175
|
+
maxItems: z.ZodDefault<z.ZodNumber>;
|
|
1176
|
+
tokenBudget: z.ZodDefault<z.ZodNumber>;
|
|
1177
|
+
}, z.core.$strip>>;
|
|
1164
1178
|
}, z.core.$strip>>;
|
|
1165
1179
|
writes: z.ZodDefault<z.ZodObject<{
|
|
1166
1180
|
mode: z.ZodDefault<z.ZodLiteral<"propose">>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface ParsedCriticResponse {
|
|
2
|
+
verdict: string;
|
|
3
|
+
reasoning: string;
|
|
4
|
+
evidenceChecked: string[];
|
|
5
|
+
antiPatternsDetected: string[];
|
|
6
|
+
escalationNeeded: boolean;
|
|
7
|
+
rawResponse: string;
|
|
8
|
+
}
|
|
9
|
+
interface ParseCriticResponseOptions {
|
|
10
|
+
validVerdicts?: readonly string[];
|
|
11
|
+
onUnknownVerdict?: (value: string) => void;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Parses a structured critic response into a `ParsedCriticResponse`.
|
|
15
|
+
*
|
|
16
|
+
* Expected format (one field per line, value may span multiple lines until the next field):
|
|
17
|
+
* VERDICT: <value>
|
|
18
|
+
* REASONING: <text>
|
|
19
|
+
* EVIDENCE_CHECKED: <comma-separated list or "none">
|
|
20
|
+
* ANTI_PATTERNS_DETECTED: <comma-separated list or "none">
|
|
21
|
+
* ESCALATION_NEEDED: YES | NO
|
|
22
|
+
*
|
|
23
|
+
* @param rawResponse - The raw text response from the critic agent.
|
|
24
|
+
* @param options.validVerdicts - Override the default verdict allowlist. Unknown verdicts
|
|
25
|
+
* (those not in this list) default to `NEEDS_REVISION` and trigger `onUnknownVerdict`.
|
|
26
|
+
* @param options.onUnknownVerdict - Called with the raw verdict string when it is not
|
|
27
|
+
* in `validVerdicts`. Use for logging or metrics. Does not affect parsing outcome.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseCriticResponseFields(rawResponse: string, options?: ParseCriticResponseOptions): ParsedCriticResponse;
|
|
30
|
+
export {};
|
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
reasoning: string;
|
|
4
|
-
evidenceChecked: string[];
|
|
5
|
-
antiPatternsDetected: string[];
|
|
6
|
-
escalationNeeded: boolean;
|
|
7
|
-
rawResponse: string;
|
|
1
|
+
import { type ParsedCriticResponse } from './critic-response-parser';
|
|
2
|
+
export interface FullAutoCriticResult extends ParsedCriticResponse {
|
|
8
3
|
}
|
|
9
4
|
export type FullAutoTriggerSource = 'text_pattern' | 'tool_action' | 'cadence' | 'subagent_return' | 'phase_boundary' | 'task_completion' | 'risk';
|
|
10
5
|
export interface FullAutoOversightEvent {
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* and injects the critic's autonomous oversight response when escalation is detected.
|
|
9
9
|
*/
|
|
10
10
|
import type { PluginConfig } from '../config';
|
|
11
|
+
import { type ParsedCriticResponse } from '../full-auto/critic-response-parser';
|
|
11
12
|
interface MessageWithParts {
|
|
12
13
|
info: {
|
|
13
14
|
role: string;
|
|
@@ -24,13 +25,7 @@ interface MessageWithParts {
|
|
|
24
25
|
/**
|
|
25
26
|
* Result from critic dispatch — used to inject verdict into message stream.
|
|
26
27
|
*/
|
|
27
|
-
interface CriticDispatchResult {
|
|
28
|
-
verdict: string;
|
|
29
|
-
reasoning: string;
|
|
30
|
-
evidenceChecked: string[];
|
|
31
|
-
antiPatternsDetected: string[];
|
|
32
|
-
escalationNeeded: boolean;
|
|
33
|
-
rawResponse: string;
|
|
28
|
+
interface CriticDispatchResult extends ParsedCriticResponse {
|
|
34
29
|
}
|
|
35
30
|
/**
|
|
36
31
|
* Parses the critic's structured text response into a CriticDispatchResult.
|
package/dist/index.js
CHANGED
|
@@ -48,7 +48,7 @@ var package_default;
|
|
|
48
48
|
var init_package = __esm(() => {
|
|
49
49
|
package_default = {
|
|
50
50
|
name: "opencode-swarm",
|
|
51
|
-
version: "7.32.
|
|
51
|
+
version: "7.32.3",
|
|
52
52
|
description: "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
53
53
|
main: "dist/index.js",
|
|
54
54
|
types: "dist/index.d.ts",
|
|
@@ -15544,8 +15544,32 @@ var init_schema = __esm(() => {
|
|
|
15544
15544
|
recall: exports_external.object({
|
|
15545
15545
|
defaultMaxItems: exports_external.number().int().min(1).max(20).default(8),
|
|
15546
15546
|
defaultTokenBudget: exports_external.number().int().min(100).max(5000).default(1200),
|
|
15547
|
-
minScore: exports_external.number().min(0).max(1).default(0.05)
|
|
15548
|
-
|
|
15547
|
+
minScore: exports_external.number().min(0).max(1).default(0.05),
|
|
15548
|
+
injection: exports_external.object({
|
|
15549
|
+
enabled: exports_external.boolean().default(true),
|
|
15550
|
+
minScore: exports_external.number().min(0).max(1).default(0.25),
|
|
15551
|
+
requireQuerySignal: exports_external.boolean().default(true),
|
|
15552
|
+
maxItems: exports_external.number().int().min(1).max(20).default(6),
|
|
15553
|
+
tokenBudget: exports_external.number().int().min(100).max(5000).default(1000)
|
|
15554
|
+
}).default({
|
|
15555
|
+
enabled: true,
|
|
15556
|
+
minScore: 0.25,
|
|
15557
|
+
requireQuerySignal: true,
|
|
15558
|
+
maxItems: 6,
|
|
15559
|
+
tokenBudget: 1000
|
|
15560
|
+
})
|
|
15561
|
+
}).default({
|
|
15562
|
+
defaultMaxItems: 8,
|
|
15563
|
+
defaultTokenBudget: 1200,
|
|
15564
|
+
minScore: 0.05,
|
|
15565
|
+
injection: {
|
|
15566
|
+
enabled: true,
|
|
15567
|
+
minScore: 0.25,
|
|
15568
|
+
requireQuerySignal: true,
|
|
15569
|
+
maxItems: 6,
|
|
15570
|
+
tokenBudget: 1000
|
|
15571
|
+
}
|
|
15572
|
+
}),
|
|
15549
15573
|
writes: exports_external.object({
|
|
15550
15574
|
mode: exports_external.literal("propose").default("propose")
|
|
15551
15575
|
}).default({ mode: "propose" }),
|
|
@@ -85071,11 +85095,18 @@ init_utils2();
|
|
|
85071
85095
|
init_file_locks();
|
|
85072
85096
|
init_state();
|
|
85073
85097
|
init_logger();
|
|
85074
|
-
init_state2();
|
|
85075
85098
|
import * as fs40 from "node:fs";
|
|
85076
85099
|
import * as path62 from "node:path";
|
|
85077
|
-
|
|
85078
|
-
|
|
85100
|
+
|
|
85101
|
+
// src/full-auto/critic-response-parser.ts
|
|
85102
|
+
var KNOWN_FIELDS = new Set([
|
|
85103
|
+
"VERDICT",
|
|
85104
|
+
"REASONING",
|
|
85105
|
+
"EVIDENCE_CHECKED",
|
|
85106
|
+
"ANTI_PATTERNS_DETECTED",
|
|
85107
|
+
"ESCALATION_NEEDED"
|
|
85108
|
+
]);
|
|
85109
|
+
var DEFAULT_VALID_VERDICTS = [
|
|
85079
85110
|
"APPROVED",
|
|
85080
85111
|
"NEEDS_REVISION",
|
|
85081
85112
|
"REJECTED",
|
|
@@ -85085,7 +85116,8 @@ var VALID_VERDICTS = [
|
|
|
85085
85116
|
"REPHRASE",
|
|
85086
85117
|
"PENDING"
|
|
85087
85118
|
];
|
|
85088
|
-
function
|
|
85119
|
+
function parseCriticResponseFields(rawResponse, options = {}) {
|
|
85120
|
+
const validVerdicts = options.validVerdicts ?? DEFAULT_VALID_VERDICTS;
|
|
85089
85121
|
const result = {
|
|
85090
85122
|
verdict: "NEEDS_REVISION",
|
|
85091
85123
|
reasoning: "",
|
|
@@ -85102,10 +85134,10 @@ function parseFullAutoCriticResponse(rawResponse) {
|
|
|
85102
85134
|
switch (key) {
|
|
85103
85135
|
case "VERDICT": {
|
|
85104
85136
|
const normalized = value.trim().toUpperCase().replace(/[`*]/g, "");
|
|
85105
|
-
if (
|
|
85137
|
+
if (validVerdicts.includes(normalized)) {
|
|
85106
85138
|
res.verdict = normalized;
|
|
85107
85139
|
} else {
|
|
85108
|
-
|
|
85140
|
+
options.onUnknownVerdict?.(value);
|
|
85109
85141
|
res.verdict = "NEEDS_REVISION";
|
|
85110
85142
|
}
|
|
85111
85143
|
break;
|
|
@@ -85132,13 +85164,7 @@ function parseFullAutoCriticResponse(rawResponse) {
|
|
|
85132
85164
|
const colonIndex = line.indexOf(":");
|
|
85133
85165
|
if (colonIndex !== -1) {
|
|
85134
85166
|
const key = line.slice(0, colonIndex).trim().toUpperCase();
|
|
85135
|
-
if (
|
|
85136
|
-
"VERDICT",
|
|
85137
|
-
"REASONING",
|
|
85138
|
-
"EVIDENCE_CHECKED",
|
|
85139
|
-
"ANTI_PATTERNS_DETECTED",
|
|
85140
|
-
"ESCALATION_NEEDED"
|
|
85141
|
-
].includes(key)) {
|
|
85167
|
+
if (KNOWN_FIELDS.has(key)) {
|
|
85142
85168
|
if (currentKey)
|
|
85143
85169
|
commitField(result, currentKey, currentValue);
|
|
85144
85170
|
currentKey = key;
|
|
@@ -85156,6 +85182,17 @@ ${line}`;
|
|
|
85156
85182
|
commitField(result, currentKey, currentValue);
|
|
85157
85183
|
return result;
|
|
85158
85184
|
}
|
|
85185
|
+
|
|
85186
|
+
// src/full-auto/oversight.ts
|
|
85187
|
+
init_state2();
|
|
85188
|
+
var oversightSequenceCounter = 0;
|
|
85189
|
+
function parseFullAutoCriticResponse(rawResponse) {
|
|
85190
|
+
return parseCriticResponseFields(rawResponse, {
|
|
85191
|
+
onUnknownVerdict: (value) => {
|
|
85192
|
+
warn(`[full-auto/oversight] Unknown verdict '${value}' — defaulting to NEEDS_REVISION`);
|
|
85193
|
+
}
|
|
85194
|
+
});
|
|
85195
|
+
}
|
|
85159
85196
|
function buildOversightPrompt(input) {
|
|
85160
85197
|
const {
|
|
85161
85198
|
trigger,
|
|
@@ -86674,88 +86711,11 @@ function extractMessageText3(message) {
|
|
|
86674
86711
|
`);
|
|
86675
86712
|
}
|
|
86676
86713
|
function parseCriticResponse(rawResponse) {
|
|
86677
|
-
|
|
86678
|
-
|
|
86679
|
-
|
|
86680
|
-
evidenceChecked: [],
|
|
86681
|
-
antiPatternsDetected: [],
|
|
86682
|
-
escalationNeeded: false,
|
|
86683
|
-
rawResponse
|
|
86684
|
-
};
|
|
86685
|
-
const lines = rawResponse.split(`
|
|
86686
|
-
`);
|
|
86687
|
-
let currentKey = "";
|
|
86688
|
-
let currentValue = "";
|
|
86689
|
-
const commitField = (res, key, value) => {
|
|
86690
|
-
switch (key) {
|
|
86691
|
-
case "VERDICT": {
|
|
86692
|
-
const validVerdicts = [
|
|
86693
|
-
"APPROVED",
|
|
86694
|
-
"NEEDS_REVISION",
|
|
86695
|
-
"REJECTED",
|
|
86696
|
-
"BLOCKED",
|
|
86697
|
-
"ANSWER",
|
|
86698
|
-
"ESCALATE_TO_HUMAN",
|
|
86699
|
-
"REPHRASE"
|
|
86700
|
-
];
|
|
86701
|
-
const normalized = value.trim().toUpperCase().replace(/[`*]/g, "");
|
|
86702
|
-
if (validVerdicts.includes(normalized)) {
|
|
86703
|
-
res.verdict = normalized;
|
|
86704
|
-
} else {
|
|
86705
|
-
warn(`[full-auto-intercept] Unknown verdict '${value}' — defaulting to NEEDS_REVISION`);
|
|
86706
|
-
res.verdict = "NEEDS_REVISION";
|
|
86707
|
-
}
|
|
86708
|
-
break;
|
|
86709
|
-
}
|
|
86710
|
-
case "REASONING":
|
|
86711
|
-
res.reasoning = value.trim();
|
|
86712
|
-
break;
|
|
86713
|
-
case "EVIDENCE_CHECKED":
|
|
86714
|
-
if (value && value !== "none" && value !== '"none"') {
|
|
86715
|
-
res.evidenceChecked = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
86716
|
-
}
|
|
86717
|
-
break;
|
|
86718
|
-
case "ANTI_PATTERNS_DETECTED":
|
|
86719
|
-
if (value && value !== "none" && value !== '"none"') {
|
|
86720
|
-
res.antiPatternsDetected = value.split(",").map((s) => s.trim()).filter(Boolean);
|
|
86721
|
-
}
|
|
86722
|
-
break;
|
|
86723
|
-
case "ESCALATION_NEEDED":
|
|
86724
|
-
res.escalationNeeded = value.trim().toUpperCase() === "YES";
|
|
86725
|
-
break;
|
|
86726
|
-
}
|
|
86727
|
-
};
|
|
86728
|
-
for (const line of lines) {
|
|
86729
|
-
const colonIndex = line.indexOf(":");
|
|
86730
|
-
if (colonIndex !== -1) {
|
|
86731
|
-
const key = line.slice(0, colonIndex).trim().toUpperCase();
|
|
86732
|
-
if ([
|
|
86733
|
-
"VERDICT",
|
|
86734
|
-
"REASONING",
|
|
86735
|
-
"EVIDENCE_CHECKED",
|
|
86736
|
-
"ANTI_PATTERNS_DETECTED",
|
|
86737
|
-
"ESCALATION_NEEDED"
|
|
86738
|
-
].includes(key)) {
|
|
86739
|
-
if (currentKey) {
|
|
86740
|
-
commitField(result, currentKey, currentValue);
|
|
86741
|
-
}
|
|
86742
|
-
currentKey = key;
|
|
86743
|
-
currentValue = line.slice(colonIndex + 1).trim();
|
|
86744
|
-
} else {
|
|
86745
|
-
currentValue += `
|
|
86746
|
-
${line}`;
|
|
86747
|
-
}
|
|
86748
|
-
} else {
|
|
86749
|
-
if (line.trim()) {
|
|
86750
|
-
currentValue += `
|
|
86751
|
-
${line}`;
|
|
86752
|
-
}
|
|
86714
|
+
return parseCriticResponseFields(rawResponse, {
|
|
86715
|
+
onUnknownVerdict: (value) => {
|
|
86716
|
+
warn(`[full-auto-intercept] Unknown verdict '${value}' — defaulting to NEEDS_REVISION`);
|
|
86753
86717
|
}
|
|
86754
|
-
}
|
|
86755
|
-
if (currentKey) {
|
|
86756
|
-
commitField(result, currentKey, currentValue);
|
|
86757
|
-
}
|
|
86758
|
-
return result;
|
|
86718
|
+
});
|
|
86759
86719
|
}
|
|
86760
86720
|
function escalationTypeToInteractionMode(escalationType) {
|
|
86761
86721
|
return escalationType === "phase_completion" ? "phase_completion" : "question_resolution";
|
|
@@ -86789,7 +86749,8 @@ async function writeAutoOversightEvent(directory, architectOutput, criticVerdict
|
|
|
86789
86749
|
fs43.appendFileSync(eventsPath, `${JSON.stringify(event)}
|
|
86790
86750
|
`, "utf-8");
|
|
86791
86751
|
} catch (writeError) {
|
|
86792
|
-
error48(`[full-auto-intercept]
|
|
86752
|
+
error48(`[full-auto-intercept] Failed to write auto_oversight event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
86753
|
+
throw writeError;
|
|
86793
86754
|
} finally {
|
|
86794
86755
|
if (lockResult?.acquired && lockResult.lock._release) {
|
|
86795
86756
|
try {
|
|
@@ -86974,11 +86935,7 @@ ESCALATION_NEEDED: NO`;
|
|
|
86974
86935
|
rawResponse: criticResponse
|
|
86975
86936
|
};
|
|
86976
86937
|
}
|
|
86977
|
-
|
|
86978
|
-
await writeAutoOversightEvent(directory, architectOutput, parsed.verdict, parsed.reasoning, parsed.evidenceChecked, interactionCount, deadlockCount, escalationType);
|
|
86979
|
-
} catch (writeError) {
|
|
86980
|
-
error48(`[full-auto-intercept] Failed to write auto_oversight event: ${writeError instanceof Error ? writeError.message : String(writeError)}`);
|
|
86981
|
-
}
|
|
86938
|
+
await writeAutoOversightEvent(directory, architectOutput, parsed.verdict, parsed.reasoning, parsed.evidenceChecked, interactionCount, deadlockCount, escalationType);
|
|
86982
86939
|
try {
|
|
86983
86940
|
await mirrorReactiveVerdictToV2({
|
|
86984
86941
|
directory,
|
|
@@ -93958,6 +93915,7 @@ async function writeDelegationEvent(directory, event) {
|
|
|
93958
93915
|
`, "utf-8");
|
|
93959
93916
|
} catch (error93) {
|
|
93960
93917
|
error48(`[full-auto/delegation] failed to write event: ${error93 instanceof Error ? error93.message : String(error93)}`);
|
|
93918
|
+
throw error93;
|
|
93961
93919
|
} finally {
|
|
93962
93920
|
if (lockResult?.acquired && lockResult.lock._release) {
|
|
93963
93921
|
try {
|
|
@@ -97640,7 +97598,14 @@ var DEFAULT_MEMORY_CONFIG = {
|
|
|
97640
97598
|
recall: {
|
|
97641
97599
|
defaultMaxItems: 8,
|
|
97642
97600
|
defaultTokenBudget: 1200,
|
|
97643
|
-
minScore: 0.05
|
|
97601
|
+
minScore: 0.05,
|
|
97602
|
+
injection: {
|
|
97603
|
+
enabled: true,
|
|
97604
|
+
minScore: 0.25,
|
|
97605
|
+
requireQuerySignal: true,
|
|
97606
|
+
maxItems: 6,
|
|
97607
|
+
tokenBudget: 1000
|
|
97608
|
+
}
|
|
97644
97609
|
},
|
|
97645
97610
|
writes: {
|
|
97646
97611
|
mode: "propose"
|
|
@@ -97671,7 +97636,11 @@ function resolveMemoryConfig(input) {
|
|
|
97671
97636
|
...input ?? {},
|
|
97672
97637
|
recall: {
|
|
97673
97638
|
...DEFAULT_MEMORY_CONFIG.recall,
|
|
97674
|
-
...input?.recall ?? {}
|
|
97639
|
+
...input?.recall ?? {},
|
|
97640
|
+
injection: {
|
|
97641
|
+
...DEFAULT_MEMORY_CONFIG.recall.injection,
|
|
97642
|
+
...input?.recall?.injection ?? {}
|
|
97643
|
+
}
|
|
97675
97644
|
},
|
|
97676
97645
|
writes: {
|
|
97677
97646
|
...DEFAULT_MEMORY_CONFIG.writes,
|
|
@@ -97953,6 +97922,24 @@ function validateMemoryProposal(proposal) {
|
|
|
97953
97922
|
function tokenize(text) {
|
|
97954
97923
|
return new Set(text.toLowerCase().replace(/[^\w\s-]/g, " ").split(/\s+/).map((token) => token.trim()).filter(Boolean));
|
|
97955
97924
|
}
|
|
97925
|
+
function normalizeKindText(kind) {
|
|
97926
|
+
return kind.replace(/_/g, " ");
|
|
97927
|
+
}
|
|
97928
|
+
function collectMetadataStrings(metadata2, keys) {
|
|
97929
|
+
const values = [];
|
|
97930
|
+
for (const key of keys) {
|
|
97931
|
+
const value = metadata2[key];
|
|
97932
|
+
if (typeof value === "string")
|
|
97933
|
+
values.push(value);
|
|
97934
|
+
if (Array.isArray(value)) {
|
|
97935
|
+
for (const item of value) {
|
|
97936
|
+
if (typeof item === "string")
|
|
97937
|
+
values.push(item);
|
|
97938
|
+
}
|
|
97939
|
+
}
|
|
97940
|
+
}
|
|
97941
|
+
return values;
|
|
97942
|
+
}
|
|
97956
97943
|
function overlap(a, b) {
|
|
97957
97944
|
if (a.size === 0 || b.size === 0)
|
|
97958
97945
|
return 0;
|
|
@@ -97990,37 +97977,101 @@ function sameScope(a, b) {
|
|
|
97990
97977
|
function scopeAllowed(recordScope, allowedScopes) {
|
|
97991
97978
|
return allowedScopes.some((scope) => sameScope(recordScope, scope));
|
|
97992
97979
|
}
|
|
97993
|
-
function
|
|
97994
|
-
if (!request.includeExpired && isExpired2(record3))
|
|
97995
|
-
return null;
|
|
97980
|
+
function scoreMemoryRecordDetailed(record3, request) {
|
|
97981
|
+
if (!request.includeExpired && isExpired2(record3)) {
|
|
97982
|
+
return { item: null, skipReason: "filtered" };
|
|
97983
|
+
}
|
|
97996
97984
|
if (record3.supersededBy)
|
|
97997
|
-
return null;
|
|
97998
|
-
if (record3.metadata.deleted === true)
|
|
97999
|
-
return null;
|
|
98000
|
-
|
|
98001
|
-
|
|
98002
|
-
|
|
98003
|
-
|
|
98004
|
-
|
|
97985
|
+
return { item: null, skipReason: "filtered" };
|
|
97986
|
+
if (record3.metadata.deleted === true) {
|
|
97987
|
+
return { item: null, skipReason: "filtered" };
|
|
97988
|
+
}
|
|
97989
|
+
if (!scopeAllowed(record3.scope, request.scopes)) {
|
|
97990
|
+
return { item: null, skipReason: "filtered" };
|
|
97991
|
+
}
|
|
97992
|
+
if (request.kinds && !request.kinds.includes(record3.kind)) {
|
|
97993
|
+
return { item: null, skipReason: "filtered" };
|
|
97994
|
+
}
|
|
97995
|
+
const queryTokens = request.mode === "injection" && request.task ? tokenize(request.task) : tokenize(request.query);
|
|
98005
97996
|
const textTokens = tokenize(record3.text);
|
|
98006
97997
|
const tagTokens = tokenize(record3.tags.join(" "));
|
|
97998
|
+
const fileTokens = tokenize([
|
|
97999
|
+
record3.source.filePath,
|
|
98000
|
+
...collectMetadataStrings(record3.metadata, [
|
|
98001
|
+
"file",
|
|
98002
|
+
"filePath",
|
|
98003
|
+
"files",
|
|
98004
|
+
"touchedFiles"
|
|
98005
|
+
])
|
|
98006
|
+
].filter((value) => typeof value === "string").join(" "));
|
|
98007
|
+
const symbolTokens = tokenize(collectMetadataStrings(record3.metadata, ["symbol", "symbols"]).join(" "));
|
|
98008
|
+
const kindQueryOverlap = overlap(queryTokens, tokenize(normalizeKindText(record3.kind)));
|
|
98007
98009
|
const textOverlap = overlap(queryTokens, textTokens);
|
|
98008
98010
|
const tagOverlap = overlap(queryTokens, tagTokens);
|
|
98009
|
-
const
|
|
98011
|
+
const fileOverlap = overlap(queryTokens, fileTokens);
|
|
98012
|
+
const symbolOverlap = overlap(queryTokens, symbolTokens);
|
|
98013
|
+
const kindMatch = request.kinds?.includes(record3.kind) ?? false;
|
|
98014
|
+
const scopeMatch = scopeAllowed(record3.scope, request.scopes);
|
|
98015
|
+
const hasQuerySignal = textOverlap > 0 || tagOverlap > 0 || fileOverlap > 0 || symbolOverlap > 0 || kindQueryOverlap > 0;
|
|
98016
|
+
if (request.mode === "injection" && request.requireQuerySignal !== false && !hasQuerySignal) {
|
|
98017
|
+
return { item: null, skipReason: "no_signal" };
|
|
98018
|
+
}
|
|
98019
|
+
const score = textOverlap * 0.45 + tagOverlap * 0.2 + fileOverlap * 0.05 + symbolOverlap * 0.05 + scopeSpecificityBoost(record3.scope) * 0.15 + kindProfileBoost(record3.kind, request) * 0.1 + record3.confidence * 0.1;
|
|
98010
98020
|
const reasonParts = [
|
|
98011
98021
|
textOverlap > 0 ? `text_overlap=${textOverlap.toFixed(2)}` : null,
|
|
98012
98022
|
tagOverlap > 0 ? `tag_overlap=${tagOverlap.toFixed(2)}` : null,
|
|
98023
|
+
fileOverlap > 0 ? `file_overlap=${fileOverlap.toFixed(2)}` : null,
|
|
98024
|
+
symbolOverlap > 0 ? `symbol_overlap=${symbolOverlap.toFixed(2)}` : null,
|
|
98025
|
+
kindQueryOverlap > 0 ? `kind_query=${kindQueryOverlap.toFixed(2)}` : null,
|
|
98013
98026
|
`scope=${record3.scope.type}`,
|
|
98014
98027
|
`confidence=${record3.confidence.toFixed(2)}`
|
|
98015
98028
|
].filter(Boolean);
|
|
98016
98029
|
return {
|
|
98017
|
-
|
|
98018
|
-
|
|
98019
|
-
|
|
98030
|
+
item: {
|
|
98031
|
+
record: record3,
|
|
98032
|
+
score,
|
|
98033
|
+
reason: reasonParts.join(", "),
|
|
98034
|
+
signals: {
|
|
98035
|
+
textOverlap,
|
|
98036
|
+
tagOverlap,
|
|
98037
|
+
fileOverlap,
|
|
98038
|
+
symbolOverlap,
|
|
98039
|
+
kindMatch,
|
|
98040
|
+
scopeMatch
|
|
98041
|
+
}
|
|
98042
|
+
}
|
|
98020
98043
|
};
|
|
98021
98044
|
}
|
|
98022
|
-
function
|
|
98023
|
-
|
|
98045
|
+
function scoreMemoryRecordsWithDiagnostics(records, request) {
|
|
98046
|
+
const minScore = request.minScore ?? 0;
|
|
98047
|
+
const diagnostics = {
|
|
98048
|
+
candidateCount: records.length,
|
|
98049
|
+
preScoredFilteredCount: 0,
|
|
98050
|
+
scoredCount: 0,
|
|
98051
|
+
returnedCount: 0,
|
|
98052
|
+
noSignalCount: 0,
|
|
98053
|
+
belowThresholdCount: 0
|
|
98054
|
+
};
|
|
98055
|
+
const items = [];
|
|
98056
|
+
for (const record3 of records) {
|
|
98057
|
+
const result = scoreMemoryRecordDetailed(record3, request);
|
|
98058
|
+
if (!result.item) {
|
|
98059
|
+
if (result.skipReason === "filtered")
|
|
98060
|
+
diagnostics.preScoredFilteredCount++;
|
|
98061
|
+
if (result.skipReason === "no_signal")
|
|
98062
|
+
diagnostics.noSignalCount++;
|
|
98063
|
+
continue;
|
|
98064
|
+
}
|
|
98065
|
+
diagnostics.scoredCount++;
|
|
98066
|
+
if (result.item.score < minScore) {
|
|
98067
|
+
diagnostics.belowThresholdCount++;
|
|
98068
|
+
continue;
|
|
98069
|
+
}
|
|
98070
|
+
items.push(result.item);
|
|
98071
|
+
}
|
|
98072
|
+
items.sort((a, b) => b.score - a.score || a.record.id.localeCompare(b.record.id));
|
|
98073
|
+
diagnostics.returnedCount = items.length;
|
|
98074
|
+
return { items, diagnostics };
|
|
98024
98075
|
}
|
|
98025
98076
|
|
|
98026
98077
|
// src/memory/local-jsonl-provider.ts
|
|
@@ -98096,13 +98147,23 @@ class LocalJsonlMemoryProvider {
|
|
|
98096
98147
|
await this.audit("delete", id, reason);
|
|
98097
98148
|
}
|
|
98098
98149
|
async recall(request) {
|
|
98150
|
+
return (await this.recallWithDiagnostics(request)).items;
|
|
98151
|
+
}
|
|
98152
|
+
async recallWithDiagnostics(request) {
|
|
98099
98153
|
await this.initialize();
|
|
98100
98154
|
const records = await this.list({
|
|
98101
98155
|
scopes: request.scopes,
|
|
98102
98156
|
kinds: request.kinds,
|
|
98103
98157
|
includeExpired: request.includeExpired
|
|
98104
98158
|
});
|
|
98105
|
-
|
|
98159
|
+
const result = scoreMemoryRecordsWithDiagnostics(records, request);
|
|
98160
|
+
return {
|
|
98161
|
+
items: result.items.slice(0, request.maxItems),
|
|
98162
|
+
diagnostics: {
|
|
98163
|
+
...result.diagnostics,
|
|
98164
|
+
returnedCount: Math.min(result.diagnostics.returnedCount, request.maxItems)
|
|
98165
|
+
}
|
|
98166
|
+
};
|
|
98106
98167
|
}
|
|
98107
98168
|
async recordRecallUsage(event) {
|
|
98108
98169
|
await this.initialize();
|
|
@@ -98307,7 +98368,8 @@ function toRecallBundle(input) {
|
|
|
98307
98368
|
generatedAt: input.generatedAt,
|
|
98308
98369
|
items: block.items,
|
|
98309
98370
|
tokenEstimate: block.tokenEstimate,
|
|
98310
|
-
promptBlock: block.promptBlock
|
|
98371
|
+
promptBlock: block.promptBlock,
|
|
98372
|
+
diagnostics: input.diagnostics
|
|
98311
98373
|
};
|
|
98312
98374
|
}
|
|
98313
98375
|
|
|
@@ -98368,20 +98430,29 @@ class MemoryGateway {
|
|
|
98368
98430
|
query,
|
|
98369
98431
|
task: input.task,
|
|
98370
98432
|
agentRole: this.context.agentRole,
|
|
98433
|
+
mode: input.mode ?? "manual",
|
|
98371
98434
|
scopes,
|
|
98372
98435
|
kinds: input.kinds,
|
|
98373
98436
|
maxItems,
|
|
98374
98437
|
tokenBudget,
|
|
98375
98438
|
minScore: input.minScore ?? this.config.recall.minScore,
|
|
98439
|
+
requireQuerySignal: input.requireQuerySignal,
|
|
98376
98440
|
includeExpired: input.includeExpired
|
|
98377
98441
|
};
|
|
98378
|
-
const
|
|
98442
|
+
const recallResult = this.provider.recallWithDiagnostics ? await this.provider.recallWithDiagnostics(request) : { items: await this.provider.recall(request) };
|
|
98379
98443
|
const bundle = toRecallBundle({
|
|
98380
98444
|
id: createBundleId(query, generatedAt),
|
|
98381
98445
|
query,
|
|
98382
98446
|
generatedAt,
|
|
98383
|
-
items:
|
|
98384
|
-
tokenBudget
|
|
98447
|
+
items: recallResult.items,
|
|
98448
|
+
tokenBudget,
|
|
98449
|
+
diagnostics: recallResult.diagnostics ? {
|
|
98450
|
+
injectionSkipReason: input.mode === "injection" ? resolveInjectionSkipReason(recallResult.diagnostics) : undefined,
|
|
98451
|
+
candidateCount: recallResult.diagnostics.candidateCount,
|
|
98452
|
+
preScoredFilteredCount: recallResult.diagnostics.preScoredFilteredCount,
|
|
98453
|
+
noSignalCount: recallResult.diagnostics.noSignalCount,
|
|
98454
|
+
belowThresholdCount: recallResult.diagnostics.belowThresholdCount
|
|
98455
|
+
} : undefined
|
|
98385
98456
|
});
|
|
98386
98457
|
await this.provider.recordRecallUsage?.({
|
|
98387
98458
|
bundleId: bundle.id,
|
|
@@ -98569,6 +98640,19 @@ function validateRequestedScopes(requested, allowed) {
|
|
|
98569
98640
|
}
|
|
98570
98641
|
return requested;
|
|
98571
98642
|
}
|
|
98643
|
+
function resolveInjectionSkipReason(diagnostics) {
|
|
98644
|
+
if (diagnostics.returnedCount > 0)
|
|
98645
|
+
return;
|
|
98646
|
+
if (diagnostics.candidateCount === 0)
|
|
98647
|
+
return "no_results";
|
|
98648
|
+
const signalEligibleCount = diagnostics.candidateCount - diagnostics.preScoredFilteredCount;
|
|
98649
|
+
if (signalEligibleCount > 0 && diagnostics.noSignalCount > 0 && diagnostics.noSignalCount >= signalEligibleCount) {
|
|
98650
|
+
return "no_signal";
|
|
98651
|
+
}
|
|
98652
|
+
if (diagnostics.belowThresholdCount > 0)
|
|
98653
|
+
return "below_threshold";
|
|
98654
|
+
return "no_results";
|
|
98655
|
+
}
|
|
98572
98656
|
function scopeKey(scope) {
|
|
98573
98657
|
return JSON.stringify({
|
|
98574
98658
|
type: scope.type,
|
|
@@ -98963,8 +99047,15 @@ async function recallForAgent(input) {
|
|
|
98963
99047
|
agentId: input.agentId,
|
|
98964
99048
|
runId: input.sessionID
|
|
98965
99049
|
}, { config: input.config });
|
|
98966
|
-
|
|
99050
|
+
const resolvedConfig = resolveMemoryConfig(input.config);
|
|
99051
|
+
if (!gateway.isEnabled()) {
|
|
99052
|
+
await logInjectionSkipped(input, "disabled");
|
|
99053
|
+
return null;
|
|
99054
|
+
}
|
|
99055
|
+
if (!resolvedConfig.recall.injection.enabled) {
|
|
99056
|
+
await logInjectionSkipped(input, "disabled");
|
|
98967
99057
|
return null;
|
|
99058
|
+
}
|
|
98968
99059
|
const scopes = gateway.deriveAllowedScopes();
|
|
98969
99060
|
const planInput = {
|
|
98970
99061
|
userGoal: compactText(input.userGoal),
|
|
@@ -98975,6 +99066,8 @@ async function recallForAgent(input) {
|
|
|
98975
99066
|
touchedFiles: extractTouchedFiles(input.agentTask)
|
|
98976
99067
|
};
|
|
98977
99068
|
const plan = buildMemoryRecallPlan(planInput, { scopes });
|
|
99069
|
+
plan.maxItems = resolvedConfig.recall.injection.maxItems;
|
|
99070
|
+
plan.tokenBudget = resolvedConfig.recall.injection.tokenBudget;
|
|
98978
99071
|
await input.appendRunLog(input.directory, input.sessionID, {
|
|
98979
99072
|
event: "recall_requested",
|
|
98980
99073
|
runId: input.sessionID ?? "unknown",
|
|
@@ -98990,10 +99083,13 @@ async function recallForAgent(input) {
|
|
|
98990
99083
|
const recallInput = {
|
|
98991
99084
|
query: plan.query,
|
|
98992
99085
|
task: planInput.agentTask,
|
|
99086
|
+
mode: "injection",
|
|
98993
99087
|
scopes: plan.scopes,
|
|
98994
99088
|
kinds: plan.kinds,
|
|
98995
99089
|
maxItems: plan.maxItems,
|
|
98996
|
-
tokenBudget: plan.tokenBudget
|
|
99090
|
+
tokenBudget: plan.tokenBudget,
|
|
99091
|
+
minScore: resolvedConfig.recall.injection.minScore,
|
|
99092
|
+
requireQuerySignal: resolvedConfig.recall.injection.requireQuerySignal
|
|
98997
99093
|
};
|
|
98998
99094
|
const bundle = await gateway.recall(recallInput);
|
|
98999
99095
|
await input.appendRunLog(input.directory, input.sessionID, {
|
|
@@ -99006,8 +99102,31 @@ async function recallForAgent(input) {
|
|
|
99006
99102
|
scores: bundle.items.map((item) => item.score),
|
|
99007
99103
|
tokenEstimate: bundle.tokenEstimate
|
|
99008
99104
|
});
|
|
99105
|
+
if (bundle.items.length === 0) {
|
|
99106
|
+
await logInjectionSkipped(input, bundle.diagnostics?.injectionSkipReason ?? "no_results", bundle);
|
|
99107
|
+
}
|
|
99009
99108
|
return { bundle, scopes };
|
|
99010
99109
|
}
|
|
99110
|
+
async function logInjectionSkipped(input, reason, bundle) {
|
|
99111
|
+
await input.appendRunLog(input.directory, input.sessionID, {
|
|
99112
|
+
event: "prompt_injection_skipped",
|
|
99113
|
+
runId: input.sessionID ?? "unknown",
|
|
99114
|
+
agentRole: input.agentRole,
|
|
99115
|
+
agentId: input.agentId,
|
|
99116
|
+
bundleId: bundle?.id,
|
|
99117
|
+
memoryIds: bundle?.items.map((item) => item.record.id),
|
|
99118
|
+
scores: bundle?.items.map((item) => item.score),
|
|
99119
|
+
tokenEstimate: bundle?.tokenEstimate,
|
|
99120
|
+
rejectionReason: reason,
|
|
99121
|
+
metadata: {
|
|
99122
|
+
reason,
|
|
99123
|
+
candidateCount: bundle?.diagnostics?.candidateCount,
|
|
99124
|
+
preScoredFilteredCount: bundle?.diagnostics?.preScoredFilteredCount,
|
|
99125
|
+
noSignalCount: bundle?.diagnostics?.noSignalCount,
|
|
99126
|
+
belowThresholdCount: bundle?.diagnostics?.belowThresholdCount
|
|
99127
|
+
}
|
|
99128
|
+
});
|
|
99129
|
+
}
|
|
99011
99130
|
function parseTaskToolInput(input) {
|
|
99012
99131
|
const record3 = input;
|
|
99013
99132
|
const rawTool = typeof record3.tool === "string" ? record3.tool : undefined;
|
|
@@ -105260,7 +105379,7 @@ function verifyFullAutoPhaseApproval(directory, sessionID, phase, config3) {
|
|
|
105260
105379
|
};
|
|
105261
105380
|
}
|
|
105262
105381
|
const events = files.map((f) => parseEvidence(f)).filter((e) => Boolean(e));
|
|
105263
|
-
const phaseBoundary = events.filter((e) =>
|
|
105382
|
+
const phaseBoundary = events.filter((e) => e.phase === phase && e.trigger_source === "phase_boundary" && (e.verdict ?? "").toUpperCase() === "APPROVED");
|
|
105264
105383
|
if (phaseBoundary.length === 0) {
|
|
105265
105384
|
return failClosed ? {
|
|
105266
105385
|
ok: false,
|
|
@@ -114959,6 +115078,10 @@ var swarm_memory_recall = createSwarmTool({
|
|
|
114959
115078
|
memory_ids: bundle.items.map((item) => item.record.id),
|
|
114960
115079
|
total: bundle.items.length,
|
|
114961
115080
|
token_estimate: bundle.tokenEstimate,
|
|
115081
|
+
signals: bundle.items.map((item) => ({
|
|
115082
|
+
memory_id: item.record.id,
|
|
115083
|
+
...item.signals
|
|
115084
|
+
})),
|
|
114962
115085
|
prompt_block: bundle.promptBlock
|
|
114963
115086
|
}, null, 2);
|
|
114964
115087
|
}
|
package/dist/memory/config.d.ts
CHANGED
|
@@ -7,6 +7,13 @@ export interface MemoryConfig {
|
|
|
7
7
|
defaultMaxItems: number;
|
|
8
8
|
defaultTokenBudget: number;
|
|
9
9
|
minScore: number;
|
|
10
|
+
injection: {
|
|
11
|
+
enabled: boolean;
|
|
12
|
+
minScore: number;
|
|
13
|
+
requireQuerySignal: boolean;
|
|
14
|
+
maxItems: number;
|
|
15
|
+
tokenBudget: number;
|
|
16
|
+
};
|
|
10
17
|
};
|
|
11
18
|
writes: {
|
|
12
19
|
mode: 'propose';
|
package/dist/memory/gateway.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type MemoryConfig } from './config';
|
|
2
2
|
import type { MemoryProposalStore, MemoryProvider } from './provider';
|
|
3
|
-
import type { MemoryContext, MemoryKind, MemoryProposal, MemoryRecord, MemoryScopeRef, MemorySource, RecallBundle } from './types';
|
|
3
|
+
import type { MemoryContext, MemoryKind, MemoryProposal, MemoryRecord, MemoryScopeRef, MemorySource, RecallBundle, RecallMode } from './types';
|
|
4
4
|
export interface MemoryGatewayOptions {
|
|
5
5
|
config?: Partial<MemoryConfig>;
|
|
6
6
|
provider?: MemoryProvider & Partial<MemoryProposalStore>;
|
|
@@ -18,11 +18,13 @@ export interface ProposeMemoryInput {
|
|
|
18
18
|
export interface RecallMemoryInput {
|
|
19
19
|
query: string;
|
|
20
20
|
task?: string;
|
|
21
|
+
mode?: RecallMode;
|
|
21
22
|
scopes?: MemoryScopeRef[];
|
|
22
23
|
kinds?: MemoryKind[];
|
|
23
24
|
maxItems?: number;
|
|
24
25
|
tokenBudget?: number;
|
|
25
26
|
minScore?: number;
|
|
27
|
+
requireQuerySignal?: boolean;
|
|
26
28
|
includeExpired?: boolean;
|
|
27
29
|
}
|
|
28
30
|
export declare class MemoryGateway {
|
package/dist/memory/index.d.ts
CHANGED
|
@@ -12,4 +12,4 @@ export { findSecrets, redactSecrets } from './redaction';
|
|
|
12
12
|
export { MEMORY_RECALL_PROFILES, type MemoryRecallProfile, normalizeMemoryAgentRole, resolveMemoryRecallProfile, } from './role-profiles';
|
|
13
13
|
export { appendMemoryRunLog, sanitizeRunId } from './run-log';
|
|
14
14
|
export { computeMemoryContentHash, createBundleId, createMemoryId, createProposalId, isExpired, normalizeMemoryText, validateMemoryProposal, validateMemoryRecordRules, } from './schema';
|
|
15
|
-
export type { MemoryContext, MemoryKind, MemoryListFilter, MemoryProposal, MemoryRecord, MemoryScopeRef, MemoryScopeType, RecallBundle, RecallRequest, RecallResultItem, } from './types';
|
|
15
|
+
export type { MemoryContext, MemoryKind, MemoryListFilter, MemoryProposal, MemoryRecord, MemoryScopeRef, MemoryScopeType, RecallBundle, RecallInjectionSkipReason, RecallMode, RecallRequest, RecallResultItem, } from './types';
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type MemoryConfig } from './config';
|
|
2
2
|
import type { MemoryProposalStore, MemoryProvider, MemoryRecallUsageEvent } from './provider';
|
|
3
|
+
import type { RecallScoringDiagnostics } from './scoring';
|
|
3
4
|
import type { MemoryListFilter, MemoryProposal, MemoryRecord, RecallRequest, RecallResultItem } from './types';
|
|
4
5
|
export declare class LocalJsonlMemoryProvider implements MemoryProvider, MemoryProposalStore {
|
|
5
6
|
readonly name = "local-jsonl";
|
|
@@ -15,6 +16,10 @@ export declare class LocalJsonlMemoryProvider implements MemoryProvider, MemoryP
|
|
|
15
16
|
get(id: string): Promise<MemoryRecord | null>;
|
|
16
17
|
delete(id: string, reason?: string): Promise<void>;
|
|
17
18
|
recall(request: RecallRequest): Promise<RecallResultItem[]>;
|
|
19
|
+
recallWithDiagnostics(request: RecallRequest): Promise<{
|
|
20
|
+
items: RecallResultItem[];
|
|
21
|
+
diagnostics: RecallScoringDiagnostics;
|
|
22
|
+
}>;
|
|
18
23
|
recordRecallUsage(event: MemoryRecallUsageEvent): Promise<void>;
|
|
19
24
|
list(filter?: MemoryListFilter): Promise<MemoryRecord[]>;
|
|
20
25
|
createProposal(proposal: MemoryProposal): Promise<MemoryProposal>;
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
import type { RecallScoringDiagnostics } from './scoring';
|
|
1
2
|
import type { MemoryListFilter, MemoryProposal, MemoryRecord, RecallRequest, RecallResultItem } from './types';
|
|
3
|
+
export interface MemoryRecallResult {
|
|
4
|
+
items: RecallResultItem[];
|
|
5
|
+
diagnostics?: RecallScoringDiagnostics;
|
|
6
|
+
}
|
|
2
7
|
export interface MemoryRecallUsageEvent {
|
|
3
8
|
bundleId: string;
|
|
4
9
|
query: string;
|
|
@@ -18,6 +23,7 @@ export interface MemoryProvider {
|
|
|
18
23
|
get(id: string): Promise<MemoryRecord | null>;
|
|
19
24
|
delete(id: string, reason?: string): Promise<void>;
|
|
20
25
|
recall(request: RecallRequest): Promise<RecallResultItem[]>;
|
|
26
|
+
recallWithDiagnostics?(request: RecallRequest): Promise<MemoryRecallResult>;
|
|
21
27
|
recordRecallUsage?(event: MemoryRecallUsageEvent): Promise<void>;
|
|
22
28
|
list(filter: MemoryListFilter): Promise<MemoryRecord[]>;
|
|
23
29
|
}
|
package/dist/memory/run-log.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type MemoryRunLogEventName = 'recall_requested' | 'recall_returned' | 'prompt_injected' | 'proposal_created' | 'proposal_rejected_by_validation';
|
|
1
|
+
export type MemoryRunLogEventName = 'recall_requested' | 'recall_returned' | 'prompt_injection_skipped' | 'prompt_injected' | 'proposal_created' | 'proposal_rejected_by_validation';
|
|
2
2
|
export interface MemoryRunLogEvent {
|
|
3
3
|
event: MemoryRunLogEventName;
|
|
4
4
|
runId: string;
|
package/dist/memory/scoring.d.ts
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
import type { MemoryRecord, MemoryScopeRef, RecallRequest, RecallResultItem } from './types';
|
|
2
|
+
export interface RecallScoringDiagnostics {
|
|
3
|
+
candidateCount: number;
|
|
4
|
+
preScoredFilteredCount: number;
|
|
5
|
+
scoredCount: number;
|
|
6
|
+
returnedCount: number;
|
|
7
|
+
noSignalCount: number;
|
|
8
|
+
belowThresholdCount: number;
|
|
9
|
+
}
|
|
2
10
|
export declare function sameScope(a: MemoryScopeRef, b: MemoryScopeRef): boolean;
|
|
3
11
|
export declare function scopeAllowed(recordScope: MemoryScopeRef, allowedScopes: MemoryScopeRef[]): boolean;
|
|
4
12
|
export declare function scoreMemoryRecord(record: MemoryRecord, request: RecallRequest): RecallResultItem | null;
|
|
5
13
|
export declare function scoreMemoryRecords(records: MemoryRecord[], request: RecallRequest): RecallResultItem[];
|
|
14
|
+
export declare function scoreMemoryRecordsWithDiagnostics(records: MemoryRecord[], request: RecallRequest): {
|
|
15
|
+
items: RecallResultItem[];
|
|
16
|
+
diagnostics: RecallScoringDiagnostics;
|
|
17
|
+
};
|
package/dist/memory/types.d.ts
CHANGED
|
@@ -56,15 +56,19 @@ export interface MemoryProposal {
|
|
|
56
56
|
createdAt: string;
|
|
57
57
|
metadata: Record<string, unknown>;
|
|
58
58
|
}
|
|
59
|
+
export type RecallMode = 'manual' | 'injection' | 'curator' | 'evaluation';
|
|
60
|
+
export type RecallInjectionSkipReason = 'disabled' | 'no_signal' | 'below_threshold' | 'no_results';
|
|
59
61
|
export interface RecallRequest {
|
|
60
62
|
query: string;
|
|
61
63
|
task?: string;
|
|
62
64
|
agentRole?: string;
|
|
65
|
+
mode?: RecallMode;
|
|
63
66
|
scopes: MemoryScopeRef[];
|
|
64
67
|
kinds?: MemoryKind[];
|
|
65
68
|
maxItems: number;
|
|
66
69
|
tokenBudget: number;
|
|
67
70
|
minScore?: number;
|
|
71
|
+
requireQuerySignal?: boolean;
|
|
68
72
|
includeExpired?: boolean;
|
|
69
73
|
includePendingProposals?: boolean;
|
|
70
74
|
}
|
|
@@ -72,6 +76,14 @@ export interface RecallResultItem {
|
|
|
72
76
|
record: MemoryRecord;
|
|
73
77
|
score: number;
|
|
74
78
|
reason: string;
|
|
79
|
+
signals: {
|
|
80
|
+
textOverlap: number;
|
|
81
|
+
tagOverlap: number;
|
|
82
|
+
fileOverlap?: number;
|
|
83
|
+
symbolOverlap?: number;
|
|
84
|
+
kindMatch: boolean;
|
|
85
|
+
scopeMatch: boolean;
|
|
86
|
+
};
|
|
75
87
|
}
|
|
76
88
|
export interface RecallBundle {
|
|
77
89
|
id: string;
|
|
@@ -80,6 +92,13 @@ export interface RecallBundle {
|
|
|
80
92
|
items: RecallResultItem[];
|
|
81
93
|
tokenEstimate: number;
|
|
82
94
|
promptBlock: string;
|
|
95
|
+
diagnostics?: {
|
|
96
|
+
injectionSkipReason?: RecallInjectionSkipReason;
|
|
97
|
+
candidateCount?: number;
|
|
98
|
+
preScoredFilteredCount?: number;
|
|
99
|
+
noSignalCount?: number;
|
|
100
|
+
belowThresholdCount?: number;
|
|
101
|
+
};
|
|
83
102
|
}
|
|
84
103
|
export interface MemoryContext {
|
|
85
104
|
directory: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-swarm",
|
|
3
|
-
"version": "7.32.
|
|
3
|
+
"version": "7.32.3",
|
|
4
4
|
"description": "Architect-centric agentic swarm plugin for OpenCode - hub-and-spoke orchestration with SME consultation, code generation, and QA review",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|