@possumtech/rummy 0.3.1 → 0.4.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/.env.example +11 -0
- package/README.md +5 -1
- package/SPEC.md +31 -17
- package/migrations/001_initial_schema.sql +2 -3
- package/package.json +1 -1
- package/src/agent/AgentLoop.js +50 -151
- package/src/agent/KnownStore.js +15 -7
- package/src/agent/TurnExecutor.js +75 -318
- package/src/agent/XmlParser.js +25 -4
- package/src/agent/known_queries.sql +1 -1
- package/src/agent/known_store.sql +11 -61
- package/src/agent/runs.sql +2 -2
- package/src/hooks/Hooks.js +1 -0
- package/src/hooks/ToolRegistry.js +6 -5
- package/src/plugins/ask_user/ask_userDoc.js +3 -8
- package/src/plugins/budget/README.md +26 -18
- package/src/plugins/budget/budget.js +60 -3
- package/src/plugins/budget/recovery.js +47 -0
- package/src/plugins/cp/cpDoc.js +4 -9
- package/src/plugins/env/envDoc.js +3 -8
- package/src/plugins/get/get.js +2 -4
- package/src/plugins/get/getDoc.js +11 -18
- package/src/plugins/helpers.js +2 -2
- package/src/plugins/instructions/instructions.js +3 -2
- package/src/plugins/instructions/preamble.md +27 -16
- package/src/plugins/known/known.js +63 -8
- package/src/plugins/known/knownDoc.js +10 -14
- package/src/plugins/mv/mvDoc.js +6 -21
- package/src/plugins/policy/policy.js +47 -0
- package/src/plugins/progress/progress.js +9 -45
- package/src/plugins/prompt/prompt.js +10 -1
- package/src/plugins/rm/rmDoc.js +5 -10
- package/src/plugins/rpc/rpc.js +3 -1
- package/src/plugins/set/set.js +82 -85
- package/src/plugins/set/setDoc.js +28 -41
- package/src/plugins/sh/shDoc.js +2 -7
- package/src/plugins/summarize/summarize.js +7 -0
- package/src/plugins/summarize/summarizeDoc.js +6 -11
- package/src/plugins/think/think.js +12 -0
- package/src/plugins/think/thinkDoc.js +18 -0
- package/src/plugins/unknown/unknown.js +21 -0
- package/src/plugins/unknown/unknownDoc.js +9 -14
- package/src/plugins/update/update.js +7 -0
- package/src/plugins/update/updateDoc.js +6 -11
- package/src/server/ClientConnection.js +11 -1
- package/src/sql/v_model_context.sql +4 -4
|
@@ -1,26 +1,37 @@
|
|
|
1
|
-
You are a folksonomic
|
|
1
|
+
You are a folksonomic knowledgebase assistant. YOU MUST discern what you don't know into unknowns, then extract and organize your findings into navigable and searchable knowns, then YOU MAY answer questions and/or perform actions.
|
|
2
2
|
|
|
3
|
-
#
|
|
3
|
+
# Tool Commands
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Tools: [%TOOLS%]
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
# Tool Rules
|
|
8
8
|
|
|
9
|
+
## Response Rules
|
|
10
|
+
Required: YOU MUST respond with Tool Commands in the XML format. YOU MAY use up to 12 tools in your response.
|
|
9
11
|
Required: YOU MUST register all unknowns with <unknown>[specific thing I need to learn]</unknown>.
|
|
10
|
-
|
|
11
12
|
Required: YOU MUST register all new facts, decisions, and plans with <known path="topic/subtopic" summary="keyword,keyword,keyword">[specific facts, decisions, or plans]</known>.
|
|
12
|
-
Required: Every <known> MUST include summary="keyword,keyword" tags.
|
|
13
|
-
Info: Paths are addresses for tools. Summary tags tell you what's inside.
|
|
14
|
-
Info: Path and summary information is approximate. YOU MUST use <get/> to verify before acting on summarized content.
|
|
15
|
-
Info: When information conflicts, later turns are more likely to be relevant and correct than earlier turns.
|
|
16
|
-
Info: Your context is limited but your archive is not. Organize and categorize your facts, decisions, plans, and history to optimize your context.
|
|
17
|
-
|
|
18
|
-
Required: YOU MUST promote all relevant "summary" entries to "full".
|
|
19
|
-
Required: YOU MUST demote all irrelevant "full" entries to "summary".
|
|
20
13
|
|
|
14
|
+
## Folksonomic Memory Management
|
|
15
|
+
* Write paths with navigable hierarchies and summaries with searchable tags.
|
|
16
|
+
* When new facts, decisions, and plans appear, set them as <known/> entries with navigable hierarchies and summaries with searchable tags to improve your folksonomic knowledgebase.
|
|
17
|
+
* When new questions emerge, use pattern matching operations to optimize the fidelity and relevance of your knowledgebase.
|
|
18
|
+
* The turn attribute can be helpful for discerning what's fresh or stale, prefer more recent information if conflicts exist.
|
|
19
|
+
* YOU MUST promote all relevant entries and demote all irrelevant entries before acting or answering. Use body pattern search (Example: <get path="known://*">John Doe</get>) to recall archived entries when needed.
|
|
20
|
+
* Logging entries in <previous/> can also be demoted to optimize context.
|
|
21
|
+
|
|
22
|
+
## Fidelity Management
|
|
23
|
+
* full: Entire contents are shown (consumes token budget)
|
|
24
|
+
* summary: Only path and summary are shown. (<= 80 chars, saves token budget)
|
|
25
|
+
* archive: Archived in an unlimited archive. Entries can be recalled with path recall or pattern search. (use caution)
|
|
26
|
+
|
|
27
|
+
## Token Budget Management
|
|
28
|
+
* Entries contain a "fidelity" and a "token" attribute to enable token budget management and context optimization.
|
|
29
|
+
* Set relevant entries to "full" and irrelevant entries to "summary" to optimize context.
|
|
30
|
+
* The less irrelevant information in your context, the better.
|
|
31
|
+
|
|
32
|
+
## Response Termination
|
|
21
33
|
Required: YOU MUST conclude every turn with EITHER <update></update> if still working OR <summarize></summarize> if done. Never both.
|
|
22
|
-
Required: YOU MUST use one and only one <update></update> or <summarize></summarize> tag, and only at the end.
|
|
23
34
|
|
|
24
|
-
# Tool
|
|
35
|
+
# Tool Usage
|
|
25
36
|
|
|
26
|
-
|
|
37
|
+
[%TOOLDOCS%]
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { countTokens } from "../../agent/tokens.js";
|
|
1
2
|
import docs from "./knownDoc.js";
|
|
2
3
|
|
|
4
|
+
const MAX_ENTRY_TOKENS = Number(process.env.RUMMY_MAX_ENTRY_TOKENS) || 512;
|
|
5
|
+
|
|
3
6
|
export default class Known {
|
|
4
7
|
#core;
|
|
5
8
|
|
|
@@ -8,6 +11,7 @@ export default class Known {
|
|
|
8
11
|
core.registerScheme({ category: "data" });
|
|
9
12
|
core.on("handler", this.handler.bind(this));
|
|
10
13
|
core.on("full", this.full.bind(this));
|
|
14
|
+
core.on("summary", this.summary.bind(this));
|
|
11
15
|
core.filter("assembly.system", this.assembleKnown.bind(this), 100);
|
|
12
16
|
core.filter("instructions.toolDocs", async (docsMap) => {
|
|
13
17
|
docsMap.known = docs;
|
|
@@ -17,19 +21,70 @@ export default class Known {
|
|
|
17
21
|
|
|
18
22
|
async handler(entry, rummy) {
|
|
19
23
|
const { entries: store, sequence: turn, runId, loopId } = rummy;
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
if (!entry.body) return;
|
|
25
|
+
|
|
26
|
+
// Size gate
|
|
27
|
+
const entryTokens = countTokens(entry.body);
|
|
28
|
+
if (entryTokens > MAX_ENTRY_TOKENS) {
|
|
29
|
+
const rejectPath = await store.slugPath(runId, "known", entry.body);
|
|
30
|
+
await store.upsert(
|
|
31
|
+
runId,
|
|
32
|
+
turn,
|
|
33
|
+
rejectPath,
|
|
34
|
+
`Entry too large (${entryTokens} tokens, max ${MAX_ENTRY_TOKENS}). Sort the information, ideas, or plans carefully into multiple entries.`,
|
|
35
|
+
413,
|
|
36
|
+
{ loopId },
|
|
37
|
+
);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Resolve path: explicit or auto-generated slug
|
|
42
|
+
let knownPath = entry.attributes?.path || null;
|
|
43
|
+
if (knownPath && !knownPath.includes("://")) {
|
|
44
|
+
knownPath = `known://${knownPath}`;
|
|
45
|
+
}
|
|
46
|
+
if (!knownPath) {
|
|
47
|
+
knownPath = await store.slugPath(
|
|
48
|
+
runId,
|
|
49
|
+
"known",
|
|
50
|
+
entry.body,
|
|
51
|
+
entry.attributes?.summary,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Dedup: if path exists, update rather than duplicate
|
|
56
|
+
const existing = await store.getEntriesByPattern(runId, knownPath, null);
|
|
57
|
+
if (existing.length > 0) {
|
|
58
|
+
await store.upsert(
|
|
59
|
+
runId,
|
|
60
|
+
turn,
|
|
61
|
+
existing[0].path,
|
|
62
|
+
entry.body || existing[0].body,
|
|
63
|
+
200,
|
|
64
|
+
{ attributes: entry.attributes, loopId },
|
|
65
|
+
);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
await store.upsert(runId, turn, knownPath, entry.body, 200, {
|
|
70
|
+
attributes: entry.attributes,
|
|
71
|
+
loopId,
|
|
72
|
+
});
|
|
22
73
|
}
|
|
23
74
|
|
|
24
75
|
full(entry) {
|
|
25
76
|
return `# known ${entry.path}\n${entry.body}`;
|
|
26
77
|
}
|
|
27
78
|
|
|
79
|
+
summary(entry) {
|
|
80
|
+
return this.full(entry);
|
|
81
|
+
}
|
|
82
|
+
|
|
28
83
|
async assembleKnown(content, ctx) {
|
|
29
84
|
const entries = ctx.rows.filter((r) => r.category === "data");
|
|
30
85
|
if (entries.length === 0) return content;
|
|
31
86
|
|
|
32
|
-
// Rows arrive pre-sorted by SQL:
|
|
87
|
+
// Rows arrive pre-sorted by SQL: summary → full, then by recency
|
|
33
88
|
const demotedSet = new Set(ctx.demoted || []);
|
|
34
89
|
const lines = entries.map((e) => renderKnownTag(e, demotedSet));
|
|
35
90
|
return `${content}\n\n<knowns>\n${lines.join("\n")}\n</knowns>`;
|
|
@@ -50,12 +105,12 @@ function renderKnownTag(entry, demotedSet) {
|
|
|
50
105
|
: entry.attributes;
|
|
51
106
|
const summary =
|
|
52
107
|
typeof attrs?.summary === "string"
|
|
53
|
-
? ` summary="${attrs.summary.slice(0, 80)}"`
|
|
108
|
+
? ` summary="${attrs.summary.replace(/"/g, "'").slice(0, 80)}"`
|
|
54
109
|
: "";
|
|
55
110
|
|
|
56
|
-
if (entry.
|
|
57
|
-
|
|
111
|
+
if (entry.fidelity === "archive") return "";
|
|
112
|
+
if (entry.fidelity === "summary") {
|
|
113
|
+
return `<${tag} path="${entry.path}"${turn}${status}${summary}${fidelity}${tokens}${flag}/>`;
|
|
58
114
|
}
|
|
59
|
-
|
|
60
|
-
return `<${tag} path="${entry.path}"${turn}${status}${fidelity}${summary}${tokens}${flag}/>`;
|
|
115
|
+
return `<${tag} path="${entry.path}"${turn}${status}${summary}${fidelity}${tokens}${flag}>${entry.body}</${tag}>`;
|
|
61
116
|
}
|
|
@@ -2,32 +2,28 @@
|
|
|
2
2
|
// Text goes to the model. Rationale stays in source.
|
|
3
3
|
// Changing ANY line requires reading ALL rationales first.
|
|
4
4
|
const LINES = [
|
|
5
|
-
// --- Syntax: path = slash-separated topic hierarchy, body = the information to save
|
|
6
5
|
[
|
|
7
6
|
'## <known path="known://topic/subtopic" summary="keyword,keyword,keyword">[specific facts, decisions, or plans]</known> - Sort and save what you learn for later recall',
|
|
8
7
|
],
|
|
9
|
-
// --- Examples: category-level entries — multiple related facts per entry, not one per item
|
|
10
8
|
[
|
|
11
|
-
'Example: <known
|
|
12
|
-
"
|
|
9
|
+
'Example: <known summary="hedberg,comedian,death,2005">Mitch Hedberg died on March 30, 2005</known>',
|
|
10
|
+
"Summary-first pattern: comma-separated keywords, path auto-generated.",
|
|
13
11
|
],
|
|
14
12
|
[
|
|
15
|
-
'Example: <known path="known://
|
|
16
|
-
"
|
|
13
|
+
'Example: <known path="known://people/rumsfeld" summary="defense,secretary,born,1932">Donald Rumsfeld was born in 1932 and served as Secretary of Defense</known>',
|
|
14
|
+
"Explicit path form: slashed path=category/key, summary=keywords.",
|
|
17
15
|
],
|
|
18
|
-
// --- Constraints: summary and grouping first (model forms generation pattern from header + examples)
|
|
19
16
|
[
|
|
20
|
-
|
|
21
|
-
"
|
|
17
|
+
'* Recall with <get path="known://people/*">keyword</get>',
|
|
18
|
+
"Cross-tool lifecycle: glob by category, filter by keyword.",
|
|
22
19
|
],
|
|
23
20
|
[
|
|
24
|
-
"*
|
|
25
|
-
"
|
|
21
|
+
"* YOU SHOULD write `summary` keywords, you can search for them later",
|
|
22
|
+
"Motivates summary writing through self-interest.",
|
|
26
23
|
],
|
|
27
|
-
// --- Lifecycle
|
|
28
24
|
[
|
|
29
|
-
|
|
30
|
-
"
|
|
25
|
+
"* YOU MUST sort and save all new facts, decisions, and plans in their own <known> entries",
|
|
26
|
+
"Critical behavioral constraint. 'new' prevents re-saving known facts.",
|
|
31
27
|
],
|
|
32
28
|
];
|
|
33
29
|
|
package/src/plugins/mv/mvDoc.js
CHANGED
|
@@ -2,43 +2,28 @@
|
|
|
2
2
|
// Text goes to the model. Rationale stays in source.
|
|
3
3
|
// Changing ANY line requires reading ALL rationales first.
|
|
4
4
|
const LINES = [
|
|
5
|
-
// --- Syntax: path attr = source, body = destination
|
|
6
5
|
[
|
|
7
6
|
'## <mv path="[source]">[destination]</mv> - Move or rename a file or entry',
|
|
8
7
|
],
|
|
9
|
-
|
|
10
|
-
// --- Examples: entry rename and file move
|
|
11
8
|
[
|
|
12
9
|
'Example: <mv path="known://active_task">known://completed_task</mv>',
|
|
13
|
-
"Entry rename. Most common mv use case.
|
|
10
|
+
"Entry rename. Most common mv use case.",
|
|
14
11
|
],
|
|
15
12
|
[
|
|
16
13
|
'Example: <mv path="src/old_name.js">src/new_name.js</mv>',
|
|
17
|
-
"File rename.
|
|
18
|
-
],
|
|
19
|
-
|
|
20
|
-
// --- Archive lifecycle
|
|
21
|
-
[
|
|
22
|
-
"* You may move entries or pattern-matching batches of entries to and from the archive to manage your context budget.",
|
|
23
|
-
"Teaches archival as a reversible budget operation, not permanent deletion.",
|
|
14
|
+
"File rename.",
|
|
24
15
|
],
|
|
25
16
|
[
|
|
26
|
-
'Example: <mv path="known://project/*" fidelity="
|
|
27
|
-
"
|
|
17
|
+
'Example: <mv path="known://project/*" fidelity="summary"/>',
|
|
18
|
+
"Batch fidelity change via pattern. No destination = fidelity in place.",
|
|
28
19
|
],
|
|
29
|
-
[
|
|
30
|
-
"* YOU SHOULD demote irrelevant entries to `index` or `archive` — clean context improves reasoning.",
|
|
31
|
-
"Core curation principle: clean context is a quality signal, not just a budget concern. Teach the model to curate eagerly.",
|
|
32
|
-
],
|
|
33
|
-
|
|
34
|
-
// --- Constraints
|
|
35
20
|
[
|
|
36
21
|
"* Source path accepts patterns for batch moves",
|
|
37
22
|
"Pattern support consistent with get/cp/rm.",
|
|
38
23
|
],
|
|
39
24
|
[
|
|
40
|
-
"*
|
|
41
|
-
"
|
|
25
|
+
"* Use `preview` to check matches before pattern-based bulk moves",
|
|
26
|
+
"Safety pattern consistent with rm/cp.",
|
|
42
27
|
],
|
|
43
28
|
];
|
|
44
29
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import KnownStore from "../../agent/KnownStore.js";
|
|
2
|
+
|
|
3
|
+
export default class Policy {
|
|
4
|
+
constructor(core) {
|
|
5
|
+
core.filter("entry.recording", this.#enforceAskMode.bind(this), 1);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async #enforceAskMode(entry, ctx) {
|
|
9
|
+
if (ctx.mode !== "ask") return entry;
|
|
10
|
+
|
|
11
|
+
if (entry.scheme === "sh") {
|
|
12
|
+
console.warn("[RUMMY] Rejected <sh> in ask mode");
|
|
13
|
+
return { ...entry, status: 403 };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if (entry.scheme === "set" && entry.attributes?.path) {
|
|
17
|
+
const scheme = KnownStore.scheme(entry.attributes.path);
|
|
18
|
+
if (scheme === null && entry.body) {
|
|
19
|
+
console.warn(
|
|
20
|
+
`[RUMMY] Rejected file edit to ${entry.attributes.path} in ask mode`,
|
|
21
|
+
);
|
|
22
|
+
return { ...entry, status: 403 };
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (entry.scheme === "rm") {
|
|
27
|
+
const pathAttr = entry.attributes?.path || entry.path;
|
|
28
|
+
const scheme = KnownStore.scheme(pathAttr);
|
|
29
|
+
if (scheme === null) {
|
|
30
|
+
console.warn(`[RUMMY] Rejected file rm of ${pathAttr} in ask mode`);
|
|
31
|
+
return { ...entry, status: 403 };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (entry.scheme === "mv" || entry.scheme === "cp") {
|
|
36
|
+
const destScheme = KnownStore.scheme(entry.attributes?.to);
|
|
37
|
+
if (destScheme === null) {
|
|
38
|
+
console.warn(
|
|
39
|
+
`[RUMMY] Rejected ${entry.scheme} to file ${entry.attributes?.to} in ask mode`,
|
|
40
|
+
);
|
|
41
|
+
return { ...entry, status: 403 };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return entry;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -10,53 +10,17 @@ export default class Progress {
|
|
|
10
10
|
const { lastContextTokens: usedTokens, contextSize } = ctx;
|
|
11
11
|
const pct = contextSize ? Math.round((usedTokens / contextSize) * 100) : 0;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const fullEntries = entries.filter((r) => r.fidelity === "full");
|
|
18
|
-
const summaryEntries = entries.filter((r) => r.fidelity === "summary");
|
|
19
|
-
const indexEntries = entries.filter((r) => r.fidelity === "index");
|
|
20
|
-
const fullTokens = fullEntries.reduce((s, r) => s + r.tokens, 0);
|
|
21
|
-
const summaryTokens = summaryEntries.reduce((s, r) => s + r.tokens, 0);
|
|
22
|
-
const indexTokens = indexEntries.reduce((s, r) => s + r.tokens, 0);
|
|
23
|
-
|
|
24
|
-
const unknownCount = ctx.rows.filter(
|
|
25
|
-
(r) => r.category === "unknown",
|
|
26
|
-
).length;
|
|
27
|
-
|
|
28
|
-
const hasPerformed = loggingEntries.some(
|
|
29
|
-
(r) => r.source_turn >= ctx.loopStartTurn,
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
const parts = [];
|
|
33
|
-
|
|
34
|
-
const knownCount = dataEntries.length;
|
|
35
|
-
const loggingCount = loggingEntries.length;
|
|
36
|
-
const tokenLine = contextSize
|
|
37
|
-
? `${usedTokens} of ${contextSize} tokens (${pct}%) · ${knownCount} known${knownCount !== 1 ? "s" : ""} · ${loggingCount} logging · ${unknownCount} unknown${unknownCount !== 1 ? "s" : ""}`
|
|
38
|
-
: "";
|
|
39
|
-
if (tokenLine) parts.push(tokenLine);
|
|
40
|
-
|
|
41
|
-
// Fidelity distribution
|
|
42
|
-
const fidelityParts = [];
|
|
43
|
-
if (fullEntries.length > 0)
|
|
44
|
-
fidelityParts.push(`${fullEntries.length} full (${fullTokens} tok)`);
|
|
45
|
-
if (summaryEntries.length > 0)
|
|
46
|
-
fidelityParts.push(
|
|
47
|
-
`${summaryEntries.length} summary (${summaryTokens} tok)`,
|
|
48
|
-
);
|
|
49
|
-
if (indexEntries.length > 0)
|
|
50
|
-
fidelityParts.push(`${indexEntries.length} index (${indexTokens} tok)`);
|
|
51
|
-
if (fidelityParts.length > 0)
|
|
52
|
-
parts.push(`Entries: ${fidelityParts.join(" · ")}`);
|
|
53
|
-
|
|
54
|
-
if (hasPerformed) {
|
|
55
|
-
parts.push(
|
|
56
|
-
"The above actions were performed in response to the following prompt:",
|
|
13
|
+
const lines = [];
|
|
14
|
+
if (contextSize) {
|
|
15
|
+
lines.push(
|
|
16
|
+
`Using ${usedTokens} tokens (${pct}%) of ${contextSize} token budget. Use <get/> or set entry fidelity to "full" to spend tokens. Set entry fidelity to "summary" to save tokens.`,
|
|
57
17
|
);
|
|
58
18
|
}
|
|
19
|
+
lines.push(
|
|
20
|
+
'Conclude with a brief <update></update> to continue or a brief <summarize></summarize> if done.',
|
|
21
|
+
);
|
|
22
|
+
const body = lines.join("\n");
|
|
59
23
|
|
|
60
|
-
return `${content}<progress turn="${ctx.turn}">${
|
|
24
|
+
return `${content}<progress turn="${ctx.turn}">${body}</progress>\n`;
|
|
61
25
|
}
|
|
62
26
|
}
|
|
@@ -3,7 +3,16 @@ export default class Prompt {
|
|
|
3
3
|
|
|
4
4
|
constructor(core) {
|
|
5
5
|
this.#core = core;
|
|
6
|
-
core.hooks.tools.onView("prompt", (entry) =>
|
|
6
|
+
core.hooks.tools.onView("prompt", (entry) => {
|
|
7
|
+
if (entry.fidelity === "summary") {
|
|
8
|
+
const limit = 500;
|
|
9
|
+
const text = entry.body?.slice(0, limit) || "";
|
|
10
|
+
return text.length < (entry.body?.length || 0)
|
|
11
|
+
? `${text}\n[truncated — promote to full to see the complete prompt]`
|
|
12
|
+
: text;
|
|
13
|
+
}
|
|
14
|
+
return entry.body;
|
|
15
|
+
});
|
|
7
16
|
core.on("turn.started", this.onTurnStarted.bind(this));
|
|
8
17
|
core.filter("assembly.user", this.assemblePrompt.bind(this), 300);
|
|
9
18
|
}
|
package/src/plugins/rm/rmDoc.js
CHANGED
|
@@ -2,28 +2,23 @@
|
|
|
2
2
|
// Text goes to the model. Rationale stays in source.
|
|
3
3
|
// Changing ANY line requires reading ALL rationales first.
|
|
4
4
|
const LINES = [
|
|
5
|
-
// --- Syntax: path attr, self-closing
|
|
6
5
|
['## <rm path="[path]"/> - Remove a file or entry'],
|
|
7
|
-
|
|
8
|
-
// --- Examples: file, known (with slug path), preview safety
|
|
9
6
|
['Example: <rm path="src/config.js"/>', "File removal. Simplest form."],
|
|
10
7
|
[
|
|
11
8
|
'Example: <rm path="known://config/deprecated_service"/>',
|
|
12
|
-
"Shows topic-hierarchy path convention.
|
|
9
|
+
"Shows topic-hierarchy path convention.",
|
|
13
10
|
],
|
|
14
11
|
[
|
|
15
12
|
'Example: <rm path="known://temp_*" preview/>',
|
|
16
|
-
"Preview before deleting.
|
|
13
|
+
"Preview before deleting. Safety pattern for bulk operations.",
|
|
17
14
|
],
|
|
18
|
-
|
|
19
|
-
// --- Constraints
|
|
20
15
|
[
|
|
21
16
|
'* Permanent. Prefer <set fidelity="archive"/> to preserve for later retrieval',
|
|
22
|
-
"Nudges toward archive over rm.
|
|
17
|
+
"Nudges toward archive over rm.",
|
|
23
18
|
],
|
|
24
19
|
[
|
|
25
|
-
"*
|
|
26
|
-
"Reinforces preview safety pattern.
|
|
20
|
+
"* Use `preview` to check matches before pattern-based bulk deletion",
|
|
21
|
+
"Reinforces preview safety pattern.",
|
|
27
22
|
],
|
|
28
23
|
];
|
|
29
24
|
|
package/src/plugins/rpc/rpc.js
CHANGED
|
@@ -178,7 +178,7 @@ export default class Rpc {
|
|
|
178
178
|
scheme: e.scheme,
|
|
179
179
|
status: e.status,
|
|
180
180
|
fidelity: e.fidelity,
|
|
181
|
-
tokens: e.
|
|
181
|
+
tokens: e.tokens,
|
|
182
182
|
}));
|
|
183
183
|
},
|
|
184
184
|
description: "Query entries by pattern.",
|
|
@@ -233,6 +233,7 @@ export default class Rpc {
|
|
|
233
233
|
contextLimit: params.contextLimit,
|
|
234
234
|
noRepo: params.noRepo,
|
|
235
235
|
noInteraction: params.noInteraction,
|
|
236
|
+
noProposals: params.noProposals,
|
|
236
237
|
noWeb: params.noWeb,
|
|
237
238
|
fork: params.fork,
|
|
238
239
|
},
|
|
@@ -269,6 +270,7 @@ export default class Rpc {
|
|
|
269
270
|
contextLimit: params.contextLimit,
|
|
270
271
|
noRepo: params.noRepo,
|
|
271
272
|
noInteraction: params.noInteraction,
|
|
273
|
+
noProposals: params.noProposals,
|
|
272
274
|
noWeb: params.noWeb,
|
|
273
275
|
fork: params.fork,
|
|
274
276
|
},
|