dsh-continual-evolve 0.10.6 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -122
- package/README.zh.md +26 -97
- package/cordis.patch.yml +2 -2
- package/lib/index.d.ts +44 -241
- package/lib/index.js +30 -253
- package/lib/memory-guide.d.ts +13 -14
- package/lib/memory-guide.js +32 -21
- package/lib/memory-section.d.ts +77 -0
- package/lib/memory-section.js +189 -0
- package/package.json +2 -17
- package/lib/apply.d.ts +0 -22
- package/lib/apply.js +0 -157
- package/lib/approval.d.ts +0 -72
- package/lib/approval.js +0 -127
- package/lib/auto.d.ts +0 -236
- package/lib/auto.js +0 -773
- package/lib/autocase.d.ts +0 -38
- package/lib/autocase.js +0 -76
- package/lib/benchmark-command.d.ts +0 -9
- package/lib/benchmark-command.js +0 -357
- package/lib/benchmark.d.ts +0 -151
- package/lib/benchmark.js +0 -250
- package/lib/command.d.ts +0 -49
- package/lib/command.js +0 -568
- package/lib/consolidate.d.ts +0 -90
- package/lib/consolidate.js +0 -180
- package/lib/copy.d.ts +0 -74
- package/lib/copy.js +0 -160
- package/lib/declines.d.ts +0 -101
- package/lib/declines.js +0 -175
- package/lib/evaluate.d.ts +0 -74
- package/lib/evaluate.js +0 -271
- package/lib/evolve-event.d.ts +0 -40
- package/lib/evolve-event.js +0 -59
- package/lib/failures.d.ts +0 -42
- package/lib/failures.js +0 -171
- package/lib/fate.d.ts +0 -130
- package/lib/fate.js +0 -350
- package/lib/goal-command.d.ts +0 -7
- package/lib/goal-command.js +0 -37
- package/lib/goal.d.ts +0 -72
- package/lib/goal.js +0 -72
- package/lib/inject.d.ts +0 -196
- package/lib/inject.js +0 -412
- package/lib/llm-text.d.ts +0 -104
- package/lib/llm-text.js +0 -140
- package/lib/logfile.d.ts +0 -71
- package/lib/logfile.js +0 -159
- package/lib/memory-agent.d.ts +0 -129
- package/lib/memory-agent.js +0 -568
- package/lib/memory-benchmark.d.ts +0 -76
- package/lib/memory-benchmark.js +0 -170
- package/lib/memory-index.d.ts +0 -114
- package/lib/memory-index.js +0 -197
- package/lib/message-source.d.ts +0 -23
- package/lib/message-source.js +0 -12
- package/lib/mount-command.d.ts +0 -10
- package/lib/mount-command.js +0 -48
- package/lib/mount.d.ts +0 -42
- package/lib/mount.js +0 -212
- package/lib/notify.d.ts +0 -59
- package/lib/notify.js +0 -97
- package/lib/plan.d.ts +0 -16
- package/lib/plan.js +0 -126
- package/lib/planner.d.ts +0 -61
- package/lib/planner.js +0 -144
- package/lib/pool.d.ts +0 -7
- package/lib/pool.js +0 -25
- package/lib/prefix-cache.d.ts +0 -78
- package/lib/prefix-cache.js +0 -168
- package/lib/project.d.ts +0 -28
- package/lib/project.js +0 -66
- package/lib/projection.d.ts +0 -22
- package/lib/projection.js +0 -112
- package/lib/promotion.d.ts +0 -94
- package/lib/promotion.js +0 -171
- package/lib/recall.d.ts +0 -85
- package/lib/recall.js +0 -142
- package/lib/record-language.d.ts +0 -85
- package/lib/record-language.js +0 -152
- package/lib/render.d.ts +0 -13
- package/lib/render.js +0 -80
- package/lib/review-scheduler.d.ts +0 -38
- package/lib/review-scheduler.js +0 -191
- package/lib/review.d.ts +0 -60
- package/lib/review.js +0 -145
- package/lib/rollback.d.ts +0 -9
- package/lib/rollback.js +0 -68
- package/lib/rubric.d.ts +0 -29
- package/lib/rubric.js +0 -119
- package/lib/runtime.d.ts +0 -24
- package/lib/runtime.js +0 -87
- package/lib/score.d.ts +0 -64
- package/lib/score.js +0 -191
- package/lib/search.d.ts +0 -83
- package/lib/search.js +0 -136
- package/lib/service.d.ts +0 -49
- package/lib/service.js +0 -180
- package/lib/skill-render.d.ts +0 -23
- package/lib/skill-render.js +0 -69
- package/lib/skill.d.ts +0 -15
- package/lib/skill.js +0 -80
- package/lib/skillquality.d.ts +0 -85
- package/lib/skillquality.js +0 -320
- package/lib/source.d.ts +0 -30
- package/lib/source.js +0 -43
- package/lib/state.d.ts +0 -26
- package/lib/state.js +0 -151
- package/lib/store.d.ts +0 -62
- package/lib/store.js +0 -164
- package/lib/token-usage.d.ts +0 -68
- package/lib/token-usage.js +0 -211
- package/lib/tool.d.ts +0 -34
- package/lib/tool.js +0 -320
- package/lib/turn-snapshot.d.ts +0 -72
- package/lib/turn-snapshot.js +0 -238
- package/lib/types.d.ts +0 -208
- package/lib/types.js +0 -127
- package/lib/usage.d.ts +0 -36
- package/lib/usage.js +0 -98
- package/lib/validate.d.ts +0 -28
- package/lib/validate.js +0 -181
- package/lib/wrapup-command.d.ts +0 -10
- package/lib/wrapup-command.js +0 -243
- package/lib/wrapup.d.ts +0 -260
- package/lib/wrapup.js +0 -539
package/lib/logfile.d.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Plugin-owned file logging: a cordis logger exporter that appends every
|
|
3
|
-
* log message — from this plugin or any other — to a JSONL file under the
|
|
4
|
-
* evolve store. Logging becomes a property of the plugin itself: no extra
|
|
5
|
-
* component to install, and it works no matter how `dsh web` is launched
|
|
6
|
-
* (foreground terminal, nohup, restart scripts, ...). The official
|
|
7
|
-
* `cordis-plugin-logger-console` remains an optional add-on for live
|
|
8
|
-
* terminal output; this file exporter is the baseline that always exists.
|
|
9
|
-
*
|
|
10
|
-
* - file: `<baseDir>/evolve/plugin.log` (0600, JSONL)
|
|
11
|
-
* - rotation: when the file exceeds `logMaxBytes` it is renamed to
|
|
12
|
-
* `plugin.log.1` (replacing the previous `.1`)
|
|
13
|
-
* - level: `levels.default` = logLevel (0=error, 1=info, 2=warn, 3=debug)
|
|
14
|
-
* - failure containment: a write error is swallowed — logging never
|
|
15
|
-
* disturbs the agent loop
|
|
16
|
-
*/
|
|
17
|
-
import type { Context } from "@deepseek-ai/cordis";
|
|
18
|
-
/** Name of the plugin log file under `<baseDir>/evolve/`. */
|
|
19
|
-
export declare const PLUGIN_LOG_FILE_NAME = "plugin.log";
|
|
20
|
-
/** Default rotation threshold (5 MiB). */
|
|
21
|
-
export declare const DEFAULT_LOG_MAX_BYTES: number;
|
|
22
|
-
export interface FileLoggerConfig {
|
|
23
|
-
/** 0=error, 1=info, 2=warn, 3=debug. */
|
|
24
|
-
logLevel?: number;
|
|
25
|
-
/** Rotate the log when it exceeds this many bytes. */
|
|
26
|
-
logMaxBytes?: number;
|
|
27
|
-
}
|
|
28
|
-
/** Full path of the plugin log file. */
|
|
29
|
-
export declare function pluginLogFilePath(baseDir: string): string;
|
|
30
|
-
/** JSON-safe rendering of a log message's arguments. */
|
|
31
|
-
export declare function renderArgs(args: readonly unknown[]): unknown[];
|
|
32
|
-
/** One JSONL record as written to the log file. */
|
|
33
|
-
export declare function logRecord(message: {
|
|
34
|
-
ts: number;
|
|
35
|
-
type: string;
|
|
36
|
-
name: string;
|
|
37
|
-
args: readonly unknown[];
|
|
38
|
-
}): string;
|
|
39
|
-
/** Human-readable rendering of one stored JSONL line (unparseable lines pass through). */
|
|
40
|
-
export declare function formatLogLine(line: string): string;
|
|
41
|
-
/**
|
|
42
|
-
* The distinct session ids mentioned in one stored log line, drawn from the
|
|
43
|
-
* rendered message and the raw args (unparseable lines fall back to a raw
|
|
44
|
-
* text scan). Exact-token matching, so `session-abc` never matches
|
|
45
|
-
* `session-abcd`.
|
|
46
|
-
*/
|
|
47
|
-
export declare function sessionIdsInLine(line: string): string[];
|
|
48
|
-
/**
|
|
49
|
-
* Keep only the lines mentioning the given session id (exact token match).
|
|
50
|
-
* An empty/whitespace session id filters everything out — the caller should
|
|
51
|
-
* validate the argument before calling.
|
|
52
|
-
*/
|
|
53
|
-
export declare function filterLogBySession(lines: readonly string[], sessionId: string): string[];
|
|
54
|
-
/** Append one line, rotating the file first when it exceeds maxBytes. */
|
|
55
|
-
export declare function appendOrRotate(path: string, maxBytes: number, line: string): void;
|
|
56
|
-
/**
|
|
57
|
-
* Register the file exporter on the context. Returns the exporter so tests
|
|
58
|
-
* can drive it directly. The exporter is disposed with the plugin's scope.
|
|
59
|
-
*/
|
|
60
|
-
export declare function registerFileLogger(ctx: Context, baseDir: string, config?: FileLoggerConfig): {
|
|
61
|
-
levels: {
|
|
62
|
-
default: number;
|
|
63
|
-
};
|
|
64
|
-
export(message: {
|
|
65
|
-
ts: number;
|
|
66
|
-
type: string;
|
|
67
|
-
name: string;
|
|
68
|
-
args: readonly unknown[];
|
|
69
|
-
}): void;
|
|
70
|
-
};
|
|
71
|
-
//# sourceMappingURL=logfile.d.ts.map
|
package/lib/logfile.js
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import { Logger } from "@deepseek-ai/cordis";
|
|
2
|
-
import { appendFileSync, existsSync, mkdirSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
/** Name of the plugin log file under `<baseDir>/evolve/`. */
|
|
5
|
-
export const PLUGIN_LOG_FILE_NAME = "plugin.log";
|
|
6
|
-
/** Default rotation threshold (5 MiB). */
|
|
7
|
-
export const DEFAULT_LOG_MAX_BYTES = 5 * 1024 * 1024;
|
|
8
|
-
/** Full path of the plugin log file. */
|
|
9
|
-
export function pluginLogFilePath(baseDir) {
|
|
10
|
-
return join(baseDir, "evolve", PLUGIN_LOG_FILE_NAME);
|
|
11
|
-
}
|
|
12
|
-
/** JSON-safe rendering of a log message's arguments. */
|
|
13
|
-
export function renderArgs(args) {
|
|
14
|
-
return args.map((arg) => {
|
|
15
|
-
if (arg instanceof Error) {
|
|
16
|
-
return { name: arg.name, message: arg.message, stack: arg.stack };
|
|
17
|
-
}
|
|
18
|
-
if (typeof arg === "object" && arg !== null) {
|
|
19
|
-
try {
|
|
20
|
-
return JSON.parse(JSON.stringify(arg));
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return String(arg);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return arg;
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
/** One JSONL record as written to the log file. */
|
|
30
|
-
export function logRecord(message) {
|
|
31
|
-
// `message` is the printf-rendered text (cordis handles %s/%o/...), so
|
|
32
|
-
// humans and machines both get a usable line; `args` keeps the raw
|
|
33
|
-
// payload for tooling. Errors render as their stack (JSON.stringify of
|
|
34
|
-
// an Error is just {}).
|
|
35
|
-
const rendered = Logger.format({
|
|
36
|
-
formatters: {
|
|
37
|
-
o: (value) => (value instanceof Error ? value.stack ?? value.message : JSON.stringify(value)),
|
|
38
|
-
},
|
|
39
|
-
maxLength: 10240,
|
|
40
|
-
export: () => { },
|
|
41
|
-
}, {
|
|
42
|
-
sn: 0,
|
|
43
|
-
ts: message.ts,
|
|
44
|
-
name: message.name,
|
|
45
|
-
type: message.type,
|
|
46
|
-
level: 0,
|
|
47
|
-
args: message.args,
|
|
48
|
-
});
|
|
49
|
-
return JSON.stringify({
|
|
50
|
-
ts: new Date(message.ts).toISOString(),
|
|
51
|
-
type: message.type,
|
|
52
|
-
name: message.name,
|
|
53
|
-
args: renderArgs(message.args),
|
|
54
|
-
message: rendered,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
/** Human-readable rendering of one stored JSONL line (unparseable lines pass through). */
|
|
58
|
-
export function formatLogLine(line) {
|
|
59
|
-
try {
|
|
60
|
-
const record = JSON.parse(line);
|
|
61
|
-
const ts = record.ts ?? "";
|
|
62
|
-
const type = record.type ? `[${record.type[0]?.toUpperCase() ?? "?"}]` : "[?]";
|
|
63
|
-
const name = record.name ?? "";
|
|
64
|
-
const body = typeof record.message === "string" && record.message.length > 0 ? record.message : "";
|
|
65
|
-
const args = body
|
|
66
|
-
? ""
|
|
67
|
-
: Array.isArray(record.args)
|
|
68
|
-
? record.args.map((arg) => (typeof arg === "object" && arg !== null ? JSON.stringify(arg) : String(arg))).join(" ")
|
|
69
|
-
: "";
|
|
70
|
-
return `${ts} ${type} ${name} ${body || args}`.trimEnd();
|
|
71
|
-
}
|
|
72
|
-
catch {
|
|
73
|
-
return line;
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
/** A session id as it appears in log text (dsh `session-<hex-uuid>` ids). */
|
|
77
|
-
const SESSION_TOKEN_RE = /\bsession-[0-9a-fA-F-]+\b/g;
|
|
78
|
-
/**
|
|
79
|
-
* The distinct session ids mentioned in one stored log line, drawn from the
|
|
80
|
-
* rendered message and the raw args (unparseable lines fall back to a raw
|
|
81
|
-
* text scan). Exact-token matching, so `session-abc` never matches
|
|
82
|
-
* `session-abcd`.
|
|
83
|
-
*/
|
|
84
|
-
export function sessionIdsInLine(line) {
|
|
85
|
-
const ids = [];
|
|
86
|
-
const collect = (text) => {
|
|
87
|
-
for (const match of text.matchAll(SESSION_TOKEN_RE)) {
|
|
88
|
-
ids.push(match[0]);
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
try {
|
|
92
|
-
const record = JSON.parse(line);
|
|
93
|
-
if (typeof record.message === "string")
|
|
94
|
-
collect(record.message);
|
|
95
|
-
if (Array.isArray(record.args)) {
|
|
96
|
-
for (const arg of record.args) {
|
|
97
|
-
collect(typeof arg === "object" && arg !== null ? JSON.stringify(arg) : String(arg));
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
collect(line);
|
|
103
|
-
}
|
|
104
|
-
return [...new Set(ids)];
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Keep only the lines mentioning the given session id (exact token match).
|
|
108
|
-
* An empty/whitespace session id filters everything out — the caller should
|
|
109
|
-
* validate the argument before calling.
|
|
110
|
-
*/
|
|
111
|
-
export function filterLogBySession(lines, sessionId) {
|
|
112
|
-
const needle = sessionId.trim();
|
|
113
|
-
if (!needle) {
|
|
114
|
-
return [];
|
|
115
|
-
}
|
|
116
|
-
return lines.filter((line) => sessionIdsInLine(line).includes(needle));
|
|
117
|
-
}
|
|
118
|
-
/** Append one line, rotating the file first when it exceeds maxBytes. */
|
|
119
|
-
export function appendOrRotate(path, maxBytes, line) {
|
|
120
|
-
const dir = dirname(path);
|
|
121
|
-
if (!existsSync(path)) {
|
|
122
|
-
mkdirSync(dir, { recursive: true });
|
|
123
|
-
// 0600: the log can carry session context and must not be world-readable
|
|
124
|
-
writeFileSync(path, "", { encoding: "utf8", mode: 0o600 });
|
|
125
|
-
}
|
|
126
|
-
if (maxBytes > 0) {
|
|
127
|
-
try {
|
|
128
|
-
if (statSync(path).size > maxBytes) {
|
|
129
|
-
renameSync(path, `${path}.1`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
catch {
|
|
133
|
-
// stat/rename failures fall through to the append attempt
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
appendFileSync(path, `${line}\n`, "utf8");
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Register the file exporter on the context. Returns the exporter so tests
|
|
140
|
-
* can drive it directly. The exporter is disposed with the plugin's scope.
|
|
141
|
-
*/
|
|
142
|
-
export function registerFileLogger(ctx, baseDir, config = {}) {
|
|
143
|
-
const path = pluginLogFilePath(baseDir);
|
|
144
|
-
const maxBytes = config.logMaxBytes ?? DEFAULT_LOG_MAX_BYTES;
|
|
145
|
-
const exporter = {
|
|
146
|
-
levels: { default: config.logLevel ?? 1 },
|
|
147
|
-
export(message) {
|
|
148
|
-
try {
|
|
149
|
-
appendOrRotate(path, maxBytes, logRecord(message));
|
|
150
|
-
}
|
|
151
|
-
catch {
|
|
152
|
-
// logging must never disturb the agent loop
|
|
153
|
-
}
|
|
154
|
-
},
|
|
155
|
-
};
|
|
156
|
-
ctx.logger.exporter(exporter);
|
|
157
|
-
return exporter;
|
|
158
|
-
}
|
|
159
|
-
//# sourceMappingURL=logfile.js.map
|
package/lib/memory-agent.d.ts
DELETED
|
@@ -1,129 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dedicated background memory extraction agent.
|
|
3
|
-
*
|
|
4
|
-
* This is the DSH counterpart of ZCode's project-memory agent loop. It keeps
|
|
5
|
-
* an independent request history, exposes only a frozen memory manifest and a
|
|
6
|
-
* structured proposal tool, and never writes state itself. Every accepted edit
|
|
7
|
-
* is handed to EvolutionEngine so scope approval, snapshots, versioning,
|
|
8
|
-
* rollback, and audit remain mandatory.
|
|
9
|
-
*/
|
|
10
|
-
import type { Context } from "@deepseek-ai/cordis";
|
|
11
|
-
import type { Agent } from "@deepseek-ai/dsh-agent";
|
|
12
|
-
import { type ToolSchema } from "@deepseek-ai/dsh-llm";
|
|
13
|
-
import { type ScopeApprovalDecision } from "./approval.js";
|
|
14
|
-
import { type LlmSessionId } from "./llm-text.js";
|
|
15
|
-
import { type PrefixCacheOptions } from "./prefix-cache.js";
|
|
16
|
-
import { type EvolutionEngine } from "./service.js";
|
|
17
|
-
import { type TokenUsageTarget } from "./token-usage.js";
|
|
18
|
-
import { type RecordLanguage, type RecordLanguagePreference } from "./record-language.js";
|
|
19
|
-
import type { EntrySource, HarnessEntry, HarnessScope, HarnessState, RefinementEdit, RefinementProposal, RefinementResult } from "./types.js";
|
|
20
|
-
/** ZCode parity: the extractor may inspect memory and propose at most five times. */
|
|
21
|
-
export declare const MEMORY_AGENT_MAX_TURNS = 5;
|
|
22
|
-
/** Bound one proposal so approval text and engine compensation stay reviewable. */
|
|
23
|
-
export declare const MEMORY_AGENT_MAX_EDITS = 20;
|
|
24
|
-
/**
|
|
25
|
-
* System-prompt size budget (chars): the prompt ships on EVERY extractor
|
|
26
|
-
* turn (up to five per snapshot), so each added line is recurring token
|
|
27
|
-
* spend, not one-off text. Raise this cap only in the same commit that
|
|
28
|
-
* justifies the added lines (regression pressure beats silent bloat).
|
|
29
|
-
*/
|
|
30
|
-
export declare const MEMORY_AGENT_SYSTEM_PROMPT_BUDGET_CHARS = 3000;
|
|
31
|
-
/** The complete tool-name allowlist exposed by the memory agent. */
|
|
32
|
-
export declare const MEMORY_AGENT_TOOL_NAMES: readonly ["memory_search", "memory_propose"];
|
|
33
|
-
export type MemoryAgentToolName = (typeof MEMORY_AGENT_TOOL_NAMES)[number];
|
|
34
|
-
/** One frozen memory entry visible to the extractor for the whole run. */
|
|
35
|
-
export type MemoryManifestEntry = HarnessEntry;
|
|
36
|
-
/** A memory-only edit with an explicit persistence target. */
|
|
37
|
-
export type ScopedMemoryEdit = RefinementEdit & {
|
|
38
|
-
kind: "memory";
|
|
39
|
-
targetScope: HarnessScope;
|
|
40
|
-
};
|
|
41
|
-
/** Structured result returned by `memory_propose`. */
|
|
42
|
-
export interface MemoryExtractionProposal extends Omit<RefinementProposal, "edits"> {
|
|
43
|
-
edits: ScopedMemoryEdit[];
|
|
44
|
-
}
|
|
45
|
-
/** Baseline states captured before the first extractor model turn. */
|
|
46
|
-
export interface MemoryScopeBaselines {
|
|
47
|
-
local: HarnessState;
|
|
48
|
-
project?: HarnessState;
|
|
49
|
-
global: HarnessState;
|
|
50
|
-
}
|
|
51
|
-
/** Result of one bounded extractor loop. */
|
|
52
|
-
export interface MemoryAgentRun {
|
|
53
|
-
proposal: MemoryExtractionProposal;
|
|
54
|
-
turns: number;
|
|
55
|
-
searches: number;
|
|
56
|
-
}
|
|
57
|
-
/** Scoped results after the proposal crosses the governed engine boundary. */
|
|
58
|
-
export interface MemoryApplicationResult {
|
|
59
|
-
results: RefinementResult[];
|
|
60
|
-
declinedScopes: HarnessScope[];
|
|
61
|
-
}
|
|
62
|
-
/** Provider-facing schemas for the closed memory-only tool set. */
|
|
63
|
-
export declare const MEMORY_AGENT_TOOL_SCHEMAS: readonly ToolSchema[];
|
|
64
|
-
/** Instructions for the dedicated loop; model text is always untrusted. */
|
|
65
|
-
export declare const MEMORY_AGENT_SYSTEM_PROMPT = "You are the dedicated background memory extraction agent for a continual-evolution harness.\n\nYou receive only an incremental conversation checkpoint and a frozen manifest of existing memory entries. Your entire job is to decide whether this checkpoint contains a durable fact worth remembering. Never propose prompt notes, skills, subagent specs, code changes, or general conversation summaries.\n\nRules:\n- Use memory_search before creating when the manifest may already cover the topic. Update an existing entry instead of creating a near-duplicate.\n- Every memory entry contains exactly one fact. Classify it with metadata.memoryType = user | feedback | project | reference.\n- feedback and project memories must state the fact, Why it matters, and How to apply it next time.\n- Never invent a user preference. Ground every proposal in the supplied conversation evidence and existing memory.\n- Every edit must have kind=memory, an explicit targetScope, and a coherent blastRadius.\n- targetScope=local is session staging. project persists within the current repository. global persists across projects. project/global require human approval before application.\n- update/delete/archive must name an existing id from the same targetScope. Prefer archive over delete when the fact is obsolete but should remain restorable.\n- Do not remember: code structure or file paths re-readable from the repository; git history, diffs, commit hashes, or CI logs; content already written in project instruction files; temporary session state, one-off debugging trails, or current task progress; model-only speculation without conversation evidence; an already-applied troubleshooting fix with no recurrence evidence (the fixed state on disk is its own record).\n- Be specific enough to act on: prefer a fact that tells the next session what to DO over a summary of what happened. If the fact is obvious from the conversation itself with no future action attached, skip it.\n- Save only what is surprising or non-obvious: routine chatter, restated context, and facts with no bearing on future work are no-ops, not memories.\n- Granularity examples (vague \u2192 reject; sharp \u2192 save):\n - \"user communicates in Chinese\" \u2192 \"user reads English with effort \u2014 write memory and handoff content in Chinese prose\".\n - \"user works on the desktop project\" \u2192 \"desktop profile loads npm-installed plugin copies \u2014 source edits need a release before they take effect\".\n - \"fixed fcitx5 by setting GTK_IM_MODULE tonight\" \u2192 reject (one-off applied fix, already on disk, no recurrence evidence).\n- You cannot read or write source files, call agents, use MCP, use the network, or mutate the harness directly. memory_propose is the only finish tool and never writes state itself.\n- If no durable memory is justified, call memory_propose with edits=[].\n- Always finish by calling memory_propose. Do not return unproposed prose.";
|
|
66
|
-
/** Build the frozen memory manifest from a merged harness view. */
|
|
67
|
-
export declare function buildMemoryManifest(state: HarnessState): MemoryManifestEntry[];
|
|
68
|
-
/** Render a bounded manifest index; full bodies remain available through memory_search. */
|
|
69
|
-
export declare function formatMemoryManifest(entries: readonly MemoryManifestEntry[], maxChars?: number): string;
|
|
70
|
-
/** Rank frozen manifest entries with CJK-aware token overlap and stable tie-breaking. */
|
|
71
|
-
export declare function searchMemoryManifest(entries: readonly MemoryManifestEntry[], query: string, maxResults?: number): MemoryManifestEntry[];
|
|
72
|
-
/** Inputs for one bounded background memory extraction loop. */
|
|
73
|
-
export interface MemoryAgentOptions {
|
|
74
|
-
provider: string;
|
|
75
|
-
model: string;
|
|
76
|
-
sessionId?: LlmSessionId;
|
|
77
|
-
manifest: readonly MemoryManifestEntry[];
|
|
78
|
-
trajectory: string;
|
|
79
|
-
trajectoryEvents?: readonly unknown[];
|
|
80
|
-
prefixCache?: PrefixCacheOptions;
|
|
81
|
-
maxOutputTokens?: number;
|
|
82
|
-
signal?: AbortSignal;
|
|
83
|
-
tokenUsage?: TokenUsageTarget;
|
|
84
|
-
/**
|
|
85
|
-
* Authoring language for the proposal. Absent → resolved per call
|
|
86
|
-
* (explicit config upstream, else durable client preference, else
|
|
87
|
-
* trajectory detection, else `en`).
|
|
88
|
-
*/
|
|
89
|
-
language?: RecordLanguage;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Run the dedicated loop against a frozen manifest.
|
|
93
|
-
*
|
|
94
|
-
* @throws On provider failure, abort, malformed tool arguments, policy denial,
|
|
95
|
-
* a non-memory proposal, or exhaustion of the bounded internal turn budget.
|
|
96
|
-
*/
|
|
97
|
-
export declare function runMemoryAgent(ctx: Context, options: MemoryAgentOptions): Promise<MemoryAgentRun>;
|
|
98
|
-
/** Strictly parse and policy-check the structured `memory_propose` payload. */
|
|
99
|
-
export declare function parseMemoryExtractionProposal(value: unknown, manifest: readonly MemoryManifestEntry[]): MemoryExtractionProposal;
|
|
100
|
-
export interface ApplyMemoryProposalOptions {
|
|
101
|
-
agent: Agent;
|
|
102
|
-
baselines: MemoryScopeBaselines;
|
|
103
|
-
projectKey?: string;
|
|
104
|
-
requireApproval: boolean;
|
|
105
|
-
source?: EntrySource;
|
|
106
|
-
signal?: AbortSignal;
|
|
107
|
-
/** Outer cursor used to scope reusable approval decisions. */
|
|
108
|
-
decisionCursor?: string;
|
|
109
|
-
/** Prior decisions for the same cursor and exact scoped proposal. */
|
|
110
|
-
scopeDecisions?: Readonly<Record<string, ScopeApprovalDecision>>;
|
|
111
|
-
/** Persist each decision before a later scope can fail. */
|
|
112
|
-
onScopeDecision?: (key: string, decision: ScopeApprovalDecision) => void;
|
|
113
|
-
/** Plugin `recordLanguage` preference for the approval dialog copy. */
|
|
114
|
-
recordLanguage?: RecordLanguagePreference;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Render the authoritative persistent-scope diff shown to the human. Model
|
|
118
|
-
* prose is retained only as an explicitly untrusted summary; actions, targets,
|
|
119
|
-
* content previews, memory types, and conflict warnings come from code.
|
|
120
|
-
*/
|
|
121
|
-
export declare function renderMemoryApprovalDetails(proposal: MemoryExtractionProposal, scope: "project" | "global", state: HarnessState, maxChars?: number): string;
|
|
122
|
-
/**
|
|
123
|
-
* Apply one accepted proposal through the only mutation engine. All persistent
|
|
124
|
-
* approvals are resolved before the first write, so an unavailable approval
|
|
125
|
-
* boundary cannot leave a partially applied batch. Explicit rejection is a
|
|
126
|
-
* no-op for that scope; service/question failures remain retryable errors.
|
|
127
|
-
*/
|
|
128
|
-
export declare function applyMemoryExtractionProposal(ctx: Context, engine: EvolutionEngine, proposal: MemoryExtractionProposal, options: ApplyMemoryProposalOptions): Promise<MemoryApplicationResult>;
|
|
129
|
-
//# sourceMappingURL=memory-agent.d.ts.map
|