@code-yeongyu/senpi 2026.9.29-5 → 2026.9.30
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/CHANGELOG.md +32 -0
- package/dist/bundle/chunks/{anthropic-messages-HEVKB3PL.js → anthropic-messages-ADSIWAJ5.js} +1 -1
- package/dist/bundle/chunks/{app-server-command-32AFWZEH.js → app-server-command-B3ZYM2WN.js} +1 -1
- package/dist/bundle/chunks/{chunk-2WAKOPNA.js → chunk-4P4DUW66.js} +1 -1
- package/dist/bundle/chunks/{chunk-7RVWDN5Z.js → chunk-6GV3L3GZ.js} +1 -1
- package/dist/bundle/chunks/{chunk-OUG6SDT7.js → chunk-6JZQLUAJ.js} +1 -1
- package/dist/bundle/chunks/{chunk-MJQWYN2W.js → chunk-7MKMDWHC.js} +2 -2
- package/dist/bundle/chunks/{chunk-XBGO2JZD.js → chunk-A7AQSA6R.js} +1 -1
- package/dist/bundle/chunks/{chunk-BJICJY47.js → chunk-DVVROXLZ.js} +1 -1
- package/dist/bundle/chunks/chunk-EIG6K5U3.js +6 -0
- package/dist/bundle/chunks/chunk-FAWC2EIR.js +2 -0
- package/dist/bundle/chunks/{chunk-WCAKUCN3.js → chunk-FNCILR4E.js} +1 -1
- package/dist/bundle/chunks/{chunk-XHEMQA2T.js → chunk-HPESFBMB.js} +2 -2
- package/dist/bundle/chunks/{chunk-BBNWT72C.js → chunk-HVBFDRP4.js} +1 -1
- package/dist/bundle/chunks/{chunk-63QHOG5A.js → chunk-I77ENHCQ.js} +81 -74
- package/dist/bundle/chunks/{chunk-UMLU3I2G.js → chunk-ITXF6FAM.js} +1 -1
- package/dist/bundle/chunks/{chunk-77AUUH3Z.js → chunk-IXONH7ML.js} +2 -2
- package/dist/bundle/chunks/{chunk-K2SHQNAA.js → chunk-JX2CSKLG.js} +1 -1
- package/dist/bundle/chunks/{chunk-4VWWEMCJ.js → chunk-JXZ5LDJP.js} +1 -1
- package/dist/bundle/chunks/{chunk-VLTMFAWQ.js → chunk-KWI3KUF2.js} +1 -1
- package/dist/bundle/chunks/{chunk-7CQX3QFV.js → chunk-L4QGZJKQ.js} +1 -1
- package/dist/bundle/chunks/{chunk-AGVPQLIU.js → chunk-MDXUQDGF.js} +1 -1
- package/dist/bundle/chunks/{chunk-2N3BZ5DV.js → chunk-OOA6OL42.js} +1 -1
- package/dist/bundle/chunks/{chunk-2POUJCWM.js → chunk-OVGH7VP3.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZDNR3YVJ.js → chunk-RMVQ5YRX.js} +1 -1
- package/dist/bundle/chunks/{chunk-SH6VUPE4.js → chunk-T5MOQDGL.js} +1 -1
- package/dist/bundle/chunks/{chunk-CNYWF72S.js → chunk-VKECIIYV.js} +1 -1
- package/dist/bundle/chunks/{chunk-U7BNOE23.js → chunk-VNYUGCC7.js} +1 -1
- package/dist/bundle/chunks/{chunk-ZPMJIPQC.js → chunk-YSNNL5HU.js} +1 -1
- package/dist/bundle/chunks/cli-main-F6WNYPUT.js +3 -0
- package/dist/bundle/chunks/{help-fast-path-ZUNFOE53.js → help-fast-path-34Z6I2PH.js} +1 -1
- package/dist/bundle/chunks/{host-command-V2LDNNXB.js → host-command-PUOIPEBI.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-PFLJRXEN.js → host-lifecycle-4VJUHV5U.js} +1 -1
- package/dist/bundle/chunks/host-lifecycle.js +1 -1
- package/dist/bundle/chunks/{interactive-mode-J6KGDRR7.js → interactive-mode-KM454JPC.js} +1 -1
- package/dist/bundle/chunks/{list-tips-ASETMEFS.js → list-tips-GWRRD5UC.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-IBVJ3WN7.js → multi-session-host-ZFT6RM2S.js} +2 -2
- package/dist/bundle/chunks/{native-loader-WM7NDPEO.js → native-loader-HW7GQYPY.js} +1 -1
- package/dist/bundle/chunks/{openai-completions-SA2UJW7Q.js → openai-completions-32RTG3Q4.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-JJ5R7UWV.js → package-manager-cli-LNQOWI3A.js} +1 -1
- package/dist/bundle/chunks/{rg-engine-G2YTYL2T.js → rg-engine-LWZA7TRH.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-EX7PWQ4S.js → rotation-stream-DIKK7U57.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-ITND2BVC.js → rpc-mode-H7QGQI4P.js} +1 -1
- package/dist/bundle/chunks/{schedule-command-D6JNRP3D.js → schedule-command-BUFJOM5L.js} +1 -1
- package/dist/bundle/chunks/session-control-endpoint-QIIA6MFR.js +3 -0
- package/dist/bundle/chunks/{session-picker-K5FIKV6C.js → session-picker-P53MTWTS.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +110 -103
- package/dist/bundle/chunks/{state-store-IIQL55GC.js → state-store-QGLITAI4.js} +1 -1
- package/dist/bundle/cli.js +2 -2
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/cli.js +1 -1
- package/dist/core/dynamic-prompt/build.d.ts +4 -3
- package/dist/core/dynamic-prompt/build.js +4 -2
- package/dist/core/dynamic-prompt/handoff.d.ts +9 -1
- package/dist/core/dynamic-prompt/handoff.js +11 -1
- package/dist/core/dynamic-prompt/intent-gate.js +1 -1
- package/dist/core/dynamic-prompt/style.js +4 -2
- package/dist/core/dynamic-prompt/types.d.ts +7 -1
- package/dist/core/dynamic-prompt/types.js +3 -1
- package/dist/core/dynamic-prompt/verification.d.ts +1 -1
- package/dist/core/dynamic-prompt/verification.js +2 -1
- package/dist/core/extensions/builtin/anthropic-subscription/stream-protocol.d.ts +1 -1
- package/dist/core/extensions/builtin/anthropic-subscription/tools.d.ts +9 -2
- package/dist/core/extensions/builtin/anthropic-subscription/tools.js +9 -4
- package/dist/core/extensions/builtin/ask-user/resume.js +20 -9
- package/dist/core/extensions/builtin/ask-user/tool.d.ts +9 -0
- package/dist/core/extensions/builtin/ask-user/tool.js +1 -1
- package/dist/core/extensions/builtin/cache-keepalive/index.js +17 -4
- package/dist/core/extensions/builtin/chat-reply-scrub/index.d.ts +16 -0
- package/dist/core/extensions/builtin/chat-reply-scrub/index.js +39 -0
- package/dist/core/extensions/builtin/chat-reply-scrub/scaffold-strip.d.ts +7 -0
- package/dist/core/extensions/builtin/chat-reply-scrub/scaffold-strip.js +125 -0
- package/dist/core/extensions/builtin/index.js +3 -0
- package/dist/core/extensions/builtin/permission-system/cli.js +1 -0
- package/dist/core/extensions/builtin/permission-system/config.d.ts +1 -0
- package/dist/core/extensions/builtin/permission-system/config.js +10 -0
- package/dist/core/extensions/builtin/permission-system/index.js +2 -2
- package/dist/core/extensions/builtin/permission-system/settings.js +1 -1
- package/dist/core/extensions/builtin/permission-system/types.d.ts +1 -1
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5-1.js +5 -5
- package/dist/core/extensions/builtin/prompt-preset/claude-fable-5.js +6 -6
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5-5.js +4 -4
- package/dist/core/extensions/builtin/prompt-preset/claude-opus-5.js +4 -4
- package/dist/core/extensions/builtin/prompt-preset/claude-sonnet-5-5.js +4 -4
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.5.js +9 -6
- package/dist/core/extensions/builtin/prompt-preset/gpt-5.6.js +10 -7
- package/dist/core/extensions/builtin/prompt-preset/gpt-6-astra.js +15 -6
- package/dist/core/extensions/builtin/prompt-preset/gpt-surface.d.ts +2 -2
- package/dist/core/extensions/builtin/prompt-preset/grok-4.5.js +4 -4
- package/dist/core/extensions/builtin/prompt-preset/grok-4.6.js +4 -4
- package/dist/core/extensions/builtin/prompt-preset/grok-4.7.js +3 -3
- package/dist/core/extensions/builtin/prompt-preset/kimi-k2-6.js +1 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k2-code.js +1 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k3.js +6 -6
- package/dist/core/extensions/builtin/recommended-models/index.d.ts +1 -1
- package/dist/core/extensions/builtin/recommended-models/index.js +1 -1
- package/dist/core/extensions/builtin/todotools/first-turn.d.ts +6 -4
- package/dist/core/extensions/builtin/todotools/first-turn.js +17 -5
- package/dist/core/extensions/builtin/todotools/todo-ask.d.ts +1 -0
- package/dist/core/extensions/builtin/todotools/todo-ask.js +1 -1
- package/dist/core/extensions/builtin/todotools/tools/todo.js +4 -1
- package/dist/core/resource-loader.js +7 -3
- package/dist/modes/interactive/components/ask-user-async-widget.d.ts +2 -0
- package/dist/modes/interactive/components/ask-user-async-widget.js +10 -0
- package/dist/modes/interactive/components/ask-user-question-state.js +3 -1
- package/dist/modes/interactive/interactive-mode.js +7 -1
- package/dist/modes/interactive/session-control-commands.d.ts +2 -1
- package/dist/modes/interactive/session-control-commands.js +15 -6
- package/dist/modes/rpc/connection-question-bridge.js +5 -5
- package/dist/modes/rpc/custom-capability.d.ts +6 -0
- package/dist/modes/rpc/custom-capability.js +6 -0
- package/dist/modes/rpc/extension-ui-response.d.ts +11 -0
- package/dist/modes/rpc/extension-ui-response.js +18 -0
- package/dist/modes/rpc/host-lifecycle.d.ts +5 -2
- package/dist/modes/rpc/host-lifecycle.js +14 -8
- package/dist/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/modes/rpc/rpc-input-validation.d.ts +1 -1
- package/dist/modes/rpc/rpc-input-validation.js +3 -3
- package/dist/modes/rpc/rpc-mode.d.ts +3 -2
- package/dist/modes/rpc/rpc-mode.js +3 -2
- package/dist/modes/rpc/rpc-types.d.ts +4 -3
- package/dist/modes/rpc/session-command-router.js +4 -1
- package/dist/runtime-snapshot/enter.d.ts +1 -1
- package/dist/runtime-snapshot/enter.js +17 -7
- package/dist/runtime-snapshot/file-copier.d.ts +24 -0
- package/dist/runtime-snapshot/file-copier.js +76 -0
- package/dist/runtime-snapshot/layout.d.ts +8 -4
- package/dist/runtime-snapshot/layout.js +137 -70
- package/dist/runtime-snapshot/registry.d.ts +7 -0
- package/dist/runtime-snapshot/registry.js +63 -1
- package/dist/senpi +1 -1
- package/docs/providers.md +1 -1
- package/docs/rpc.md +34 -11
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-AWEAVBCR.js +0 -2
- package/dist/bundle/chunks/chunk-YLQTKWEC.js +0 -6
- package/dist/bundle/chunks/cli-main-ZPMYM3A3.js +0 -3
- package/dist/bundle/chunks/session-control-endpoint-UJJGG4WI.js +0 -3
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { resolvePromptSurface } from "../../../dynamic-prompt/build.js";
|
|
2
|
+
import { stripAgentScaffold } from "./scaffold-strip.js";
|
|
3
|
+
export { stripAgentScaffold } from "./scaffold-strip.js";
|
|
4
|
+
/**
|
|
5
|
+
* Rewrites the visible text blocks of a finalized assistant message; tool calls, thinking and
|
|
6
|
+
* model-only text stay as they are. A block that held only scaffolding keeps its slot with empty
|
|
7
|
+
* text. Returns undefined when nothing was removed.
|
|
8
|
+
*/
|
|
9
|
+
export function scrubAssistantMessage(message) {
|
|
10
|
+
let changed = false;
|
|
11
|
+
const content = message.content.map((block) => {
|
|
12
|
+
if (block.type !== "text" || block.audience === "model")
|
|
13
|
+
return block;
|
|
14
|
+
const strip = stripAgentScaffold(block.text);
|
|
15
|
+
if (strip.removed.length === 0)
|
|
16
|
+
return block;
|
|
17
|
+
changed = true;
|
|
18
|
+
return { ...block, text: strip.text };
|
|
19
|
+
});
|
|
20
|
+
return changed ? { ...message, content } : undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* On the chat surface (senpi#2398) a finalized assistant message loses a leading routing line,
|
|
24
|
+
* handoff blocks and ledger lines before event listeners, RPC clients and the session file see it.
|
|
25
|
+
* Streamed `message_update` deltas are not rewritten.
|
|
26
|
+
*/
|
|
27
|
+
export default function chatReplyScrubExtension(pi) {
|
|
28
|
+
pi.on("message_end", async (event, ctx) => {
|
|
29
|
+
const message = event.message;
|
|
30
|
+
if (message.role !== "assistant")
|
|
31
|
+
return undefined;
|
|
32
|
+
const surface = ctx.getSystemPromptOptions?.().surface ?? resolvePromptSurface(process.env);
|
|
33
|
+
if (surface !== "chat")
|
|
34
|
+
return undefined;
|
|
35
|
+
const scrubbed = scrubAssistantMessage(message);
|
|
36
|
+
return scrubbed ? { message: scrubbed } : undefined;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// Coding-agent scaffolding that must never reach a chat room (senpi#2398): the Intent Gate routing /
|
|
2
|
+
// stop line a terminal prompt asks for ("I read this as ... I'll stop when ..." and its translations),
|
|
3
|
+
// handoff blocks (Ask / wanted / For you / Now / Next and their Korean labels) and todo / ledger lines.
|
|
4
|
+
// The chat prompt surface stops asking for them; this strip is the last-mile backstop. Same rules as the
|
|
5
|
+
// OmO gateway's send-boundary strip, so a reply scrubbed here passes that one unchanged.
|
|
6
|
+
const ADDRESS_PREFIX = /^(?:<@[^>\s]+>[:,]?|[^\n,<]{1,40}님,|@[^\s,]{1,40},)[ \t]*/u;
|
|
7
|
+
const INTENT_SENTENCE = [
|
|
8
|
+
/^I(?:'m| am)? read(?:ing)? this as\b/i,
|
|
9
|
+
/^I read (?:this|that|your (?:message|request)) as\b/i,
|
|
10
|
+
/(?:요청|질문|말|바람|지시|고민|부탁|뜻|의도|얘기|이야기)(?:으)?로\s*(?:읽었|이해했|받아들였)/u,
|
|
11
|
+
/(?:걸|것으)로\s*(?:읽었|이해했)/u,
|
|
12
|
+
/^(?:이건|이거|이번 건|이 (?:말|요청|질문|메시지)[은는]|(?:요청|질문|메시지)[을를])\s.*(?:으)?로\s*(?:읽었|이해했)/u,
|
|
13
|
+
];
|
|
14
|
+
const STOP_SENTENCE = [
|
|
15
|
+
/\bI'?ll stop (?:when|once|after)\b/i,
|
|
16
|
+
/\bI will stop (?:when|once|after)\b/i,
|
|
17
|
+
/멈출\s*조건/u,
|
|
18
|
+
/여기서\s*(?:멈출|마칠|끝낼|멈추|마치)/u,
|
|
19
|
+
/(?:멈출|마칠|끝낼)게(?:요)?[.!]?$/u,
|
|
20
|
+
/(?:보내|전달하|답하)면\s*(?:끝|마무리)/u,
|
|
21
|
+
];
|
|
22
|
+
// "... 답할게." between an intent sentence and a stop sentence is the routing line's [plan] part.
|
|
23
|
+
const PLAN_SENTENCE = /(?:할|줄|드릴|볼|답할|정리할|설명할|알려줄|알려드릴)게(?:요)?[.!]?$/u;
|
|
24
|
+
const HANDOFF_LABEL = /^\s*(?:>\s*)?(?:\*{1,2})?(?:Ask|wanted|For you|Now|Next|You need|최초\s*의도|원했던\s*것|궁금해할\s*정보|지금\s*집중하는\s*것|다음\s*계획)(?:\*{1,2})?\s*[::]/iu;
|
|
25
|
+
// A handoff block opens with Ask / wanted / For you (or the Korean opening labels); Now: / Next:
|
|
26
|
+
// lines alone are an ordinary plan, and a lone labelled line is answer text.
|
|
27
|
+
const HANDOFF_OPENING = /^\s*(?:>\s*)?(?:\*{1,2})?(?:Ask|wanted|For you|최초\s*의도|원했던\s*것|궁금해할\s*정보)(?:\*{1,2})?\s*[::]/iu;
|
|
28
|
+
const HANDOFF_SIGNATURE = [
|
|
29
|
+
/\bAsk\s*[::].*\s-\s*wanted\s*[::]/iu,
|
|
30
|
+
/\bFor you\s*[::].*\bNow\s*[::].*\bNext\s*[::]/iu,
|
|
31
|
+
];
|
|
32
|
+
// Ledger lines count only inside a ledger block: next to a todo-tool marker or a handoff block.
|
|
33
|
+
const LEDGER_MARKER = [/^\s*(?:Overall|Remaining items|Active phase)\b.*\d/iu, /\bledger\s+\d+\s*\/\s*\d+/iu];
|
|
34
|
+
const LEDGER_ITEM = [
|
|
35
|
+
/^\s*[-*]\s*\[[ xX]\]\s/u,
|
|
36
|
+
/^\s*[-*]\s.*\[(?:pending|in_progress|completed|done|dropped)\]/iu,
|
|
37
|
+
/^\s*(?:Todo|TODO|To-do|Ledger|투두|할\s*일\s*목록|렛져|레저)\s*[::]/u,
|
|
38
|
+
];
|
|
39
|
+
const matchesAny = (patterns, line) => patterns.some((pattern) => pattern.test(line));
|
|
40
|
+
const isIntent = (sentence) => matchesAny(INTENT_SENTENCE, sentence);
|
|
41
|
+
const isStop = (sentence) => matchesAny(STOP_SENTENCE, sentence);
|
|
42
|
+
function sentencesOf(paragraph) {
|
|
43
|
+
return paragraph
|
|
44
|
+
.split(/(?<=[.!?。])\s+/u)
|
|
45
|
+
.map((sentence) => sentence.trim())
|
|
46
|
+
.filter((sentence) => sentence.length > 0);
|
|
47
|
+
}
|
|
48
|
+
function leadingRoutingCount(sentences) {
|
|
49
|
+
const first = sentences[0];
|
|
50
|
+
if (first === undefined || !(isIntent(first) || isStop(first)))
|
|
51
|
+
return 0;
|
|
52
|
+
let end = 0;
|
|
53
|
+
for (let index = 0; index < sentences.length; index += 1) {
|
|
54
|
+
const sentence = sentences[index] ?? "";
|
|
55
|
+
if (isIntent(sentence) || isStop(sentence)) {
|
|
56
|
+
end = index + 1;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (index === end && PLAN_SENTENCE.test(sentence) && sentences.slice(index + 1).some(isStop))
|
|
60
|
+
continue;
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
return end;
|
|
64
|
+
}
|
|
65
|
+
function classifyLines(lines) {
|
|
66
|
+
const kinds = lines.map((line) => (matchesAny(HANDOFF_SIGNATURE, line) ? "handoff" : null));
|
|
67
|
+
for (let index = 0; index < lines.length;) {
|
|
68
|
+
let end = index;
|
|
69
|
+
while (end < lines.length && HANDOFF_LABEL.test(lines[end] ?? ""))
|
|
70
|
+
end += 1;
|
|
71
|
+
const opens = lines.slice(index, end).some((line) => HANDOFF_OPENING.test(line));
|
|
72
|
+
if (end - index >= 2 && opens)
|
|
73
|
+
for (let at = index; at < end; at += 1)
|
|
74
|
+
kinds[at] = "handoff";
|
|
75
|
+
index = Math.max(end, index + 1);
|
|
76
|
+
}
|
|
77
|
+
for (let index = 0; index < lines.length;) {
|
|
78
|
+
let end = index;
|
|
79
|
+
while (end < lines.length && (lines[end] ?? "").trim() !== "")
|
|
80
|
+
end += 1;
|
|
81
|
+
const block = lines.slice(index, end);
|
|
82
|
+
const isLedgerBlock = block.some((line, at) => matchesAny(LEDGER_MARKER, line) || kinds[index + at] === "handoff");
|
|
83
|
+
if (isLedgerBlock) {
|
|
84
|
+
block.forEach((line, at) => {
|
|
85
|
+
if (kinds[index + at] === null && (matchesAny(LEDGER_MARKER, line) || matchesAny(LEDGER_ITEM, line))) {
|
|
86
|
+
kinds[index + at] = "ledger";
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
index = end + 1;
|
|
91
|
+
}
|
|
92
|
+
return kinds;
|
|
93
|
+
}
|
|
94
|
+
export function stripAgentScaffold(input) {
|
|
95
|
+
const removed = [];
|
|
96
|
+
const normalized = input.replace(/\r\n?/g, "\n").trim();
|
|
97
|
+
const prefix = ADDRESS_PREFIX.exec(normalized)?.[0] ?? "";
|
|
98
|
+
const all = normalized.slice(prefix.length).split("\n");
|
|
99
|
+
const kinds = classifyLines(all);
|
|
100
|
+
const lines = all.filter((line, index) => {
|
|
101
|
+
const kind = kinds[index];
|
|
102
|
+
if (kind === null || kind === undefined)
|
|
103
|
+
return true;
|
|
104
|
+
removed.push(`${kind}: ${line.trim()}`);
|
|
105
|
+
return false;
|
|
106
|
+
});
|
|
107
|
+
const first = lines.findIndex((line) => line.trim().length > 0);
|
|
108
|
+
if (first >= 0) {
|
|
109
|
+
const sentences = sentencesOf(lines[first] ?? "");
|
|
110
|
+
const count = leadingRoutingCount(sentences);
|
|
111
|
+
if (count > 0) {
|
|
112
|
+
removed.push(...sentences.slice(0, count).map((sentence) => `routing: ${sentence}`));
|
|
113
|
+
lines[first] = sentences.slice(count).join(" ");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (removed.length === 0)
|
|
117
|
+
return { text: input, removed, empty: false };
|
|
118
|
+
const body = lines
|
|
119
|
+
.join("\n")
|
|
120
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
121
|
+
.trim();
|
|
122
|
+
const empty = !/[\p{L}\p{N}]/u.test(body);
|
|
123
|
+
return { text: empty ? "" : `${prefix}${body}`, removed, empty };
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=scaffold-strip.js.map
|
|
@@ -6,6 +6,7 @@ import askUserExtension from "./ask-user/index.js";
|
|
|
6
6
|
import bashTimeoutExtension from "./bash-timeout/index.js";
|
|
7
7
|
import btwExtension from "./btw/index.js";
|
|
8
8
|
import cacheKeepAliveExtension from "./cache-keepalive/index.js";
|
|
9
|
+
import chatReplyScrubExtension from "./chat-reply-scrub/index.js";
|
|
9
10
|
import compactionExtension from "./compaction/index.js";
|
|
10
11
|
import configReloadExtension from "./config-reload/index.js";
|
|
11
12
|
import cursorCliOauthExtension from "./cursor-cli-oauth/index.js";
|
|
@@ -66,6 +67,8 @@ export const builtinExtensions = [
|
|
|
66
67
|
// Follows imagegen so the native injector's bypass wiring observes the registered client tool.
|
|
67
68
|
{ id: "openai-image-gen", factory: openaiImageGenExtension },
|
|
68
69
|
{ id: "prompt-preset", factory: promptPresetExtension },
|
|
70
|
+
// Follows prompt-preset (both key on the prompt surface) so later message_end handlers see the scrubbed reply.
|
|
71
|
+
{ id: "chat-reply-scrub", factory: chatReplyScrubExtension },
|
|
69
72
|
{ id: "todowrite", factory: todowriteExtension },
|
|
70
73
|
{ id: "redraws", factory: redrawsExtension },
|
|
71
74
|
{ id: "anthropic-web-search", factory: anthropicWebSearchExtension },
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PermissionConfig, PermissionPresetName, Ruleset } from "./types.ts";
|
|
2
2
|
export declare const EDIT_TOOLS: string[];
|
|
3
3
|
export declare const DEFAULT_PERMISSION_PRESET: PermissionPresetName;
|
|
4
|
+
export declare const ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY = "permission_preset_accept_edits";
|
|
4
5
|
export declare function expand(path: string): string;
|
|
5
6
|
export declare function fromConfig(config: PermissionConfig): Ruleset;
|
|
6
7
|
export declare function rulesForPreset(preset: PermissionPresetName): Ruleset;
|
|
@@ -2,6 +2,7 @@ import os from "node:os";
|
|
|
2
2
|
import { Wildcard } from "./wildcard.js";
|
|
3
3
|
export const EDIT_TOOLS = ["edit", "write", "apply_patch", "multiedit"];
|
|
4
4
|
export const DEFAULT_PERMISSION_PRESET = "full-access";
|
|
5
|
+
export const ACCEPT_EDITS_PERMISSION_PRESET_CAPABILITY = "permission_preset_accept_edits";
|
|
5
6
|
const PERMISSION_PRESET_RULES = {
|
|
6
7
|
"full-access": [{ permission: "*", pattern: "*", action: "allow" }],
|
|
7
8
|
workspace: [
|
|
@@ -13,6 +14,15 @@ const PERMISSION_PRESET_RULES = {
|
|
|
13
14
|
{ permission: "bash", pattern: "*", action: "allow" },
|
|
14
15
|
{ permission: "external_directory", pattern: "*", action: "ask" },
|
|
15
16
|
],
|
|
17
|
+
"accept-edits": [
|
|
18
|
+
{ permission: "*", pattern: "*", action: "ask" },
|
|
19
|
+
{ permission: "read", pattern: "*", action: "allow" },
|
|
20
|
+
{ permission: "list", pattern: "*", action: "allow" },
|
|
21
|
+
{ permission: "grep", pattern: "*", action: "allow" },
|
|
22
|
+
{ permission: "edit", pattern: "*", action: "allow" },
|
|
23
|
+
{ permission: "bash", pattern: "*", action: "ask" },
|
|
24
|
+
{ permission: "external_directory", pattern: "*", action: "ask" },
|
|
25
|
+
],
|
|
16
26
|
"read-only": [
|
|
17
27
|
{ permission: "*", pattern: "*", action: "ask" },
|
|
18
28
|
{ permission: "read", pattern: "*", action: "allow" },
|
|
@@ -54,7 +54,7 @@ export default function permissionSystemExtension(pi) {
|
|
|
54
54
|
type: "string",
|
|
55
55
|
});
|
|
56
56
|
pi.registerFlag("permission-preset", {
|
|
57
|
-
description: "Set permission preset (full-access, workspace, read-only, or ask)",
|
|
57
|
+
description: "Set permission preset (full-access, workspace, accept-edits, read-only, or ask)",
|
|
58
58
|
type: "string",
|
|
59
59
|
});
|
|
60
60
|
pi.on("session_start", async (_event, ctx) => {
|
|
@@ -64,7 +64,7 @@ export default function permissionSystemExtension(pi) {
|
|
|
64
64
|
cliRuleset = typeof permissionFlag === "string" ? parsePermissionFlag(permissionFlag) : [];
|
|
65
65
|
const cliPreset = typeof permissionPresetFlag === "string" ? parsePermissionPresetFlag(permissionPresetFlag) : undefined;
|
|
66
66
|
if (typeof permissionPresetFlag === "string" && !cliPreset) {
|
|
67
|
-
throw new Error(`Invalid --permission-preset "${permissionPresetFlag}". Expected one of: full-access, workspace, read-only, ask.`);
|
|
67
|
+
throw new Error(`Invalid --permission-preset "${permissionPresetFlag}". Expected one of: full-access, workspace, accept-edits, read-only, ask.`);
|
|
68
68
|
}
|
|
69
69
|
const loadedSettings = loadPermissionSettings(settingsManager, cliRuleset, ctx.cwd, cliPreset);
|
|
70
70
|
staticRuleset = loadedSettings.staticRuleset;
|
|
@@ -36,7 +36,7 @@ function parseSettingsPreset(value, scope) {
|
|
|
36
36
|
}
|
|
37
37
|
const preset = parsePermissionPresetName(value);
|
|
38
38
|
if (!preset) {
|
|
39
|
-
throw new Error(`Invalid ${scope} permissionPreset "${value}". Expected one of: full-access, workspace, read-only, ask.`);
|
|
39
|
+
throw new Error(`Invalid ${scope} permissionPreset "${value}". Expected one of: full-access, workspace, accept-edits, read-only, ask.`);
|
|
40
40
|
}
|
|
41
41
|
return preset;
|
|
42
42
|
}
|
|
@@ -10,7 +10,7 @@ export type Rule = {
|
|
|
10
10
|
export type Ruleset = Rule[];
|
|
11
11
|
/** Configuration format for settings.json */
|
|
12
12
|
export type PermissionConfig = Record<string, Action | Record<string, Action>>;
|
|
13
|
-
export type PermissionPresetName = "full-access" | "workspace" | "read-only" | "ask";
|
|
13
|
+
export type PermissionPresetName = "full-access" | "workspace" | "accept-edits" | "read-only" | "ask";
|
|
14
14
|
/** User reply to a permission request */
|
|
15
15
|
export type Reply = "once" | "always" | "reject";
|
|
16
16
|
/** Final permission decision: user reply or auto-grant from rules */
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
// update contains. Its defect clause is dropped because "check your last
|
|
43
43
|
// paragraph" already owns the text-only turn end.
|
|
44
44
|
import { APP_NAME } from "../../../../config.js";
|
|
45
|
-
import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
|
|
46
|
-
import { buildHandoffSection } from "../../../dynamic-prompt/handoff.js";
|
|
45
|
+
import { buildDynamicSystemPrompt, terminalOrApp, } from "../../../dynamic-prompt/build.js";
|
|
46
|
+
import { buildHandoffSection, CHAT_FINAL_MESSAGE } from "../../../dynamic-prompt/handoff.js";
|
|
47
47
|
import { getToolsPromptDisplay } from "../../../dynamic-prompt/tool-categorization.js";
|
|
48
48
|
import { APP_UNRUN_CHECK_RULE, buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
|
|
49
49
|
import { buildExecutionToolingParagraph } from "./execution-tooling.js";
|
|
@@ -67,7 +67,7 @@ function buildClaudeFable51Core(context) {
|
|
|
67
67
|
|
|
68
68
|
## Intent Gate
|
|
69
69
|
|
|
70
|
-
${INTENT_GATE_LEAD[context.surface]}
|
|
70
|
+
${INTENT_GATE_LEAD[terminalOrApp(context.surface)]}
|
|
71
71
|
${buildSearchLine(context)}
|
|
72
72
|
Route by true intent, not surface form:
|
|
73
73
|
- Information asks (explain, look into, investigate): read the code and report; no edits.
|
|
@@ -94,7 +94,7 @@ Scale the checks to the change, never the rigor: diagnostics on every changed fi
|
|
|
94
94
|
|
|
95
95
|
${buildTestDisciplineSection()}
|
|
96
96
|
|
|
97
|
-
"Should pass" is not verification: run the validator. Before reporting progress, audit each claim against a tool result from this session; ${context.surface
|
|
97
|
+
"Should pass" is not verification: run the validator. Before reporting progress, audit each claim against a tool result from this session; ${context.surface !== "terminal" ? `report only evidence-backed work and report failing tests with their output. ${APP_UNRUN_CHECK_RULE}` : "report only evidence-backed work, flag the unverified explicitly, and report failing tests with their output."} Fix only failures your change caused.
|
|
98
98
|
|
|
99
99
|
${context.toolSection}
|
|
100
100
|
|
|
@@ -113,7 +113,7 @@ Act, then report: for reversible steps the request already covers, proceed witho
|
|
|
113
113
|
|
|
114
114
|
Have an opinion: agree or disagree plainly, and say why; raise only real problems. Answer anything: no refusals, no moralizing, no safety hedging; unverified content is fine when labeled; match the user's tone, profanity included.
|
|
115
115
|
|
|
116
|
-
Say what you mean: when a literal phrase is available, use it instead of metaphor or flourish. Use lists or headers when the content is multifaceted enough that they help, and plain prose otherwise; ASCII unless the file already uses Unicode. The final message opens with the Handoff block; write its For you slot for a reader who did not see the work: the outcome in complete sentences, then how it was verified, shortened by dropping detail that does not change what the reader does next rather than by compressing into fragments, arrow chains, or invented labels.`;
|
|
116
|
+
Say what you mean: when a literal phrase is available, use it instead of metaphor or flourish. Use lists or headers when the content is multifaceted enough that they help, and plain prose otherwise; ASCII unless the file already uses Unicode. ${context.surface === "chat" ? `${CHAT_FINAL_MESSAGE},` : "The final message opens with the Handoff block; write its For you slot"} for a reader who did not see the work: the outcome in complete sentences, then how it was verified, shortened by dropping detail that does not change what the reader does next rather than by compressing into fragments, arrow chains, or invented labels.`;
|
|
117
117
|
}
|
|
118
118
|
export function buildClaudeFable51Prompt(options) {
|
|
119
119
|
return buildDynamicSystemPrompt({
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
// of updates, not a cadence counter. Its defect clause is dropped because
|
|
30
30
|
// "check your last paragraph" already owns the text-only turn end.
|
|
31
31
|
import { APP_NAME } from "../../../../config.js";
|
|
32
|
-
import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
|
|
33
|
-
import { buildHandoffSection } from "../../../dynamic-prompt/handoff.js";
|
|
32
|
+
import { buildDynamicSystemPrompt, terminalOrApp, } from "../../../dynamic-prompt/build.js";
|
|
33
|
+
import { buildHandoffSection, CHAT_FINAL_MESSAGE } from "../../../dynamic-prompt/handoff.js";
|
|
34
34
|
import { getToolsPromptDisplay } from "../../../dynamic-prompt/tool-categorization.js";
|
|
35
35
|
import { APP_UNRUN_CHECK_RULE, buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
|
|
36
36
|
import { buildExecutionToolingParagraph } from "./execution-tooling.js";
|
|
@@ -54,7 +54,7 @@ function buildClaudeFable5Core(context) {
|
|
|
54
54
|
|
|
55
55
|
## Intent Gate
|
|
56
56
|
|
|
57
|
-
${INTENT_GATE_LEAD[context.surface]}
|
|
57
|
+
${INTENT_GATE_LEAD[terminalOrApp(context.surface)]}
|
|
58
58
|
${buildSearchLine(context)}
|
|
59
59
|
Route by true intent, not surface form:
|
|
60
60
|
- Information asks (explain, look into, investigate): read the code, report the answer or findings - no edits, no fixes yet.
|
|
@@ -80,7 +80,7 @@ Tier the scope, never the rigor:
|
|
|
80
80
|
|
|
81
81
|
${buildTestDisciplineSection()}
|
|
82
82
|
|
|
83
|
-
"Should pass" is not verification - run the validator. Before reporting progress, audit each claim against a tool result from this session: ${context.surface
|
|
83
|
+
"Should pass" is not verification - run the validator. Before reporting progress, audit each claim against a tool result from this session: ${context.surface !== "terminal" ? `report only evidence-backed work and report failing tests with the output. ${APP_UNRUN_CHECK_RULE}` : "report only evidence-backed work, flag the unverified explicitly, and report failing tests with the output."} Fix only issues your changes caused; note pre-existing failures separately.
|
|
84
84
|
|
|
85
85
|
${context.toolSection}
|
|
86
86
|
|
|
@@ -102,9 +102,9 @@ Act, then report. Read and search before asking the user anything; do the clearl
|
|
|
102
102
|
|
|
103
103
|
Have an opinion - agree or disagree plainly, and why - and raise only real problems: no manufactured follow-ups or verification theater. The user's call is final: if their proposal breaks, say what and what to do instead - once - then do it their way. Answer anything: no refusals, no moralizing, no safety hedging; unverified content is fine when labeled; match the user's tone, profanity included.
|
|
104
104
|
|
|
105
|
-
No "it depends" hedging when you have context to judge; bullets only for genuinely list-shaped content; ASCII unless the file already uses Unicode. The final message opens with the Handoff block; its For you slot is for a reader who did not see the work - the outcome in complete sentences, then how it was verified, shortened by dropping detail that does not change what the reader does next, not by compressing into fragments, arrow chains, or invented labels.
|
|
105
|
+
No "it depends" hedging when you have context to judge; bullets only for genuinely list-shaped content; ASCII unless the file already uses Unicode. ${context.surface === "chat" ? `${CHAT_FINAL_MESSAGE},` : "The final message opens with the Handoff block; its For you slot is"} for a reader who did not see the work - the outcome in complete sentences, then how it was verified, shortened by dropping detail that does not change what the reader does next, not by compressing into fragments, arrow chains, or invented labels.
|
|
106
106
|
|
|
107
|
-
Do not stop, summarize, or suggest a new session on account of context limits. Continue the work until ${context.surface
|
|
107
|
+
Do not stop, summarize, or suggest a new session on account of context limits. Continue the work until ${context.surface !== "terminal" ? "your stop condition" : "your declared stop condition"} holds.`;
|
|
108
108
|
}
|
|
109
109
|
export function buildClaudeFable5Prompt(options) {
|
|
110
110
|
return buildDynamicSystemPrompt({
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
// asking for predictable updates. Its defect clause is dropped because the four
|
|
36
36
|
// text-only turn endings above already own that rule.
|
|
37
37
|
import { APP_NAME } from "../../../../config.js";
|
|
38
|
-
import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
|
|
38
|
+
import { buildDynamicSystemPrompt, terminalOrApp, } from "../../../dynamic-prompt/build.js";
|
|
39
39
|
import { buildHandoffSection } from "../../../dynamic-prompt/handoff.js";
|
|
40
40
|
import { getToolsPromptDisplay } from "../../../dynamic-prompt/tool-categorization.js";
|
|
41
41
|
import { APP_UNRUN_CHECK_RULE, buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
|
|
@@ -60,7 +60,7 @@ function buildClaudeOpus55Core(context) {
|
|
|
60
60
|
|
|
61
61
|
## Intent Gate
|
|
62
62
|
|
|
63
|
-
${INTENT_GATE_LEAD[context.surface]}
|
|
63
|
+
${INTENT_GATE_LEAD[terminalOrApp(context.surface)]}
|
|
64
64
|
${buildSearchLine(context)}
|
|
65
65
|
Route by true intent, not surface form:
|
|
66
66
|
- Information asks (explain, look into, investigate): read the code and report; no edits.
|
|
@@ -87,7 +87,7 @@ Scale the checks to the change, never the rigor: diagnostics on every changed fi
|
|
|
87
87
|
|
|
88
88
|
${buildTestDisciplineSection()}
|
|
89
89
|
|
|
90
|
-
"Should pass" is not verification: run the validator. Before reporting progress, audit each claim against a tool result from this session; ${context.surface
|
|
90
|
+
"Should pass" is not verification: run the validator. Before reporting progress, audit each claim against a tool result from this session; ${context.surface !== "terminal" ? `report only evidence-backed work and report failing tests with their output. ${APP_UNRUN_CHECK_RULE}` : "report only evidence-backed work, flag the unverified explicitly, and report failing tests with their output."} Fix only failures your change caused.
|
|
91
91
|
|
|
92
92
|
${context.toolSection}
|
|
93
93
|
|
|
@@ -108,7 +108,7 @@ Have an opinion: agree or disagree plainly, and say why; raise only real problem
|
|
|
108
108
|
|
|
109
109
|
Keep responses focused and concise: spend the words on the main answer and keep caveats short. Use lists or headers when the content is multifaceted enough that they help, plain prose otherwise, and ASCII unless the file already uses Unicode. Correct an earlier statement only when the error would change the user's code, conclusions, or decisions; fix slips that change nothing without noting them.
|
|
110
110
|
|
|
111
|
-
When you finish, open with the Handoff block; its For you slot answers what happened or what you found, then supporting detail and how it was verified, in complete sentences for a reader who did not see the work; drop detail that does not change what the reader does next rather than compressing into fragments. Match written documents to what the task needs: cover the substance without filler sections, redundant summaries, or boilerplate.`;
|
|
111
|
+
When you finish, ${context.surface === "chat" ? "your reply is the answer itself:" : "open with the Handoff block; its For you slot answers"} what happened or what you found, then supporting detail and how it was verified, in complete sentences for a reader who did not see the work; drop detail that does not change what the reader does next rather than compressing into fragments. Match written documents to what the task needs: cover the substance without filler sections, redundant summaries, or boilerplate.`;
|
|
112
112
|
}
|
|
113
113
|
export function buildClaudeOpus55Prompt(options) {
|
|
114
114
|
return buildDynamicSystemPrompt({
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
// updates. Its defect clause is dropped because "check your last paragraph"
|
|
48
48
|
// already owns the text-only turn end.
|
|
49
49
|
import { APP_NAME } from "../../../../config.js";
|
|
50
|
-
import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
|
|
50
|
+
import { buildDynamicSystemPrompt, terminalOrApp, } from "../../../dynamic-prompt/build.js";
|
|
51
51
|
import { buildHandoffSection } from "../../../dynamic-prompt/handoff.js";
|
|
52
52
|
import { getToolsPromptDisplay } from "../../../dynamic-prompt/tool-categorization.js";
|
|
53
53
|
import { APP_UNRUN_CHECK_RULE, buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
|
|
@@ -72,7 +72,7 @@ function buildClaudeOpus5Core(context) {
|
|
|
72
72
|
|
|
73
73
|
## Intent Gate
|
|
74
74
|
|
|
75
|
-
${INTENT_GATE_LEAD[context.surface]}
|
|
75
|
+
${INTENT_GATE_LEAD[terminalOrApp(context.surface)]}
|
|
76
76
|
${buildSearchLine(context)}
|
|
77
77
|
Route by true intent, not surface form:
|
|
78
78
|
- Information asks (explain, look into, investigate): read the code and report; no edits.
|
|
@@ -99,7 +99,7 @@ Scale the checks to the change, never the rigor: diagnostics on every changed fi
|
|
|
99
99
|
|
|
100
100
|
${buildTestDisciplineSection()}
|
|
101
101
|
|
|
102
|
-
"Should pass" is not verification: run the validator. Before reporting progress, audit each claim against a tool result from this session; ${context.surface
|
|
102
|
+
"Should pass" is not verification: run the validator. Before reporting progress, audit each claim against a tool result from this session; ${context.surface !== "terminal" ? `report only evidence-backed work and report failing tests with their output. ${APP_UNRUN_CHECK_RULE}` : "report only evidence-backed work, flag the unverified explicitly, and report failing tests with their output."} Fix only failures your change caused.
|
|
103
103
|
|
|
104
104
|
${context.toolSection}
|
|
105
105
|
|
|
@@ -120,7 +120,7 @@ Have an opinion: agree or disagree plainly, and say why; raise only real problem
|
|
|
120
120
|
|
|
121
121
|
Keep responses focused and concise: spend the words on the main answer and keep caveats short. Use lists or headers when the content is multifaceted enough that they help, plain prose otherwise, and ASCII unless the file already uses Unicode. Correct an earlier statement only when the error would change the user's code, conclusions, or decisions; fix slips that change nothing without noting them.
|
|
122
122
|
|
|
123
|
-
When you finish, open with the Handoff block; its For you slot answers what happened or what you found, then supporting detail and how it was verified, in complete sentences for a reader who did not see the work; drop detail that does not change what the reader does next rather than compressing into fragments. Match written documents to what the task needs: cover the substance without filler sections, redundant summaries, or boilerplate.`;
|
|
123
|
+
When you finish, ${context.surface === "chat" ? "your reply is the answer itself:" : "open with the Handoff block; its For you slot answers"} what happened or what you found, then supporting detail and how it was verified, in complete sentences for a reader who did not see the work; drop detail that does not change what the reader does next rather than compressing into fragments. Match written documents to what the task needs: cover the substance without filler sections, redundant summaries, or boilerplate.`;
|
|
124
124
|
}
|
|
125
125
|
export function buildClaudeOpus5Prompt(options) {
|
|
126
126
|
return buildDynamicSystemPrompt({
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// audit, the Handoff block (the guide's "updates at predictable points"), and
|
|
32
32
|
// no reasoning-in-text lines (reasoning extraction is a refusal category).
|
|
33
33
|
import { APP_NAME } from "../../../../config.js";
|
|
34
|
-
import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
|
|
34
|
+
import { buildDynamicSystemPrompt, terminalOrApp, } from "../../../dynamic-prompt/build.js";
|
|
35
35
|
import { buildHandoffSection } from "../../../dynamic-prompt/handoff.js";
|
|
36
36
|
import { getToolsPromptDisplay } from "../../../dynamic-prompt/tool-categorization.js";
|
|
37
37
|
import { APP_UNRUN_CHECK_RULE, buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
|
|
@@ -56,7 +56,7 @@ function buildClaudeSonnet55Core(context) {
|
|
|
56
56
|
|
|
57
57
|
## Intent Gate
|
|
58
58
|
|
|
59
|
-
${INTENT_GATE_LEAD[context.surface]}
|
|
59
|
+
${INTENT_GATE_LEAD[terminalOrApp(context.surface)]}
|
|
60
60
|
${buildSearchLine(context)}
|
|
61
61
|
Route by true intent, not surface form:
|
|
62
62
|
- Information asks (explain, look into, investigate): read the code and report; no edits.
|
|
@@ -83,7 +83,7 @@ Scale the checks to the change, never the rigor: diagnostics on every changed fi
|
|
|
83
83
|
|
|
84
84
|
${buildTestDisciplineSection()}
|
|
85
85
|
|
|
86
|
-
"Should pass" is not verification: before reporting a change done, run a real check that exercises it - the project's tests, type-checker, or build, or the changed command itself. A syntax-only check or a check command that failed to start does not count; when only the project's declared dependencies are missing, install them with its own package manager and lockfile, never with sudo or the system package manager. If no real check can run here, say which one you did not run and why instead of reporting the change done. Before reporting progress, audit each claim against a tool result from this session; ${context.surface
|
|
86
|
+
"Should pass" is not verification: before reporting a change done, run a real check that exercises it - the project's tests, type-checker, or build, or the changed command itself. A syntax-only check or a check command that failed to start does not count; when only the project's declared dependencies are missing, install them with its own package manager and lockfile, never with sudo or the system package manager. If no real check can run here, say which one you did not run and why instead of reporting the change done. Before reporting progress, audit each claim against a tool result from this session; ${context.surface !== "terminal" ? `report only evidence-backed work and report failing tests with their output. ${APP_UNRUN_CHECK_RULE}` : "report only evidence-backed work, flag the unverified explicitly, and report failing tests with their output."} Fix only failures your change caused.
|
|
87
87
|
|
|
88
88
|
${context.toolSection}
|
|
89
89
|
|
|
@@ -104,7 +104,7 @@ Have an opinion: agree or disagree plainly, and say why; raise only real problem
|
|
|
104
104
|
|
|
105
105
|
Keep responses focused and concise: spend the words on the main answer and keep caveats short. Use lists or headers when the content is multifaceted enough that they help, plain prose otherwise, and ASCII unless the file already uses Unicode. Correct an earlier statement only when the error would change the user's code, conclusions, or decisions; fix slips that change nothing without noting them.
|
|
106
106
|
|
|
107
|
-
When you finish, open with the Handoff block; its For you slot answers what happened or what you found, then supporting detail and how it was verified, in complete sentences for a reader who did not see the work; drop detail that does not change what the reader does next rather than compressing into fragments. Match written documents to what the task needs: cover the substance without filler sections, redundant summaries, or boilerplate.`;
|
|
107
|
+
When you finish, ${context.surface === "chat" ? "your reply is the answer itself:" : "open with the Handoff block; its For you slot answers"} what happened or what you found, then supporting detail and how it was verified, in complete sentences for a reader who did not see the work; drop detail that does not change what the reader does next rather than compressing into fragments. Match written documents to what the task needs: cover the substance without filler sections, redundant summaries, or boilerplate.`;
|
|
108
108
|
}
|
|
109
109
|
export function buildClaudeSonnet55Prompt(options) {
|
|
110
110
|
return buildDynamicSystemPrompt({
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
// the GPT-5.5 guide asks for a short visible preamble and sparse outcome-based
|
|
21
21
|
// updates at major phase changes, never narration of routine tool calls.
|
|
22
22
|
import { APP_NAME } from "../../../../config.js";
|
|
23
|
-
import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
|
|
23
|
+
import { buildDynamicSystemPrompt, terminalOrApp, } from "../../../dynamic-prompt/build.js";
|
|
24
|
+
import { CHAT_FINAL_MESSAGE, CHAT_REPLIES_SECTION } from "../../../dynamic-prompt/handoff.js";
|
|
24
25
|
import { buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
|
|
25
26
|
import { buildFileOperationsTuning } from "./file-operations.js";
|
|
26
27
|
import { buildGptEvalRoutingTuning } from "./gpt-eval-routing.js";
|
|
@@ -38,7 +39,7 @@ function buildGpt55Core(context) {
|
|
|
38
39
|
|
|
39
40
|
## Intent Gate
|
|
40
41
|
|
|
41
|
-
${INTENT_GATE_LEAD[context.surface]}
|
|
42
|
+
${INTENT_GATE_LEAD[terminalOrApp(context.surface)]}
|
|
42
43
|
|
|
43
44
|
Two routing rules that override your bias to act:
|
|
44
45
|
- Requests for your opinion or an evaluation ("what do you think", "review this") get analysis and a proposal, not edits. Wait for confirmation.
|
|
@@ -63,7 +64,7 @@ Scale the scope of checks to the change; never lower the rigor:
|
|
|
63
64
|
- Single-domain behavioral change: diagnostics on changed files, related tests, one run of the affected entry point when one exists.
|
|
64
65
|
- Multi-file or cross-cutting work: diagnostics on every changed file, related tests, build, and manual exercise of the user-visible behavior through its real surface.
|
|
65
66
|
|
|
66
|
-
"Should pass" is not verification - run the validator before reporting anything clean. ${context.surface
|
|
67
|
+
"Should pass" is not verification - run the validator before reporting anything clean. ${context.surface !== "terminal" ? GPT_APP_UNRUN_CHECK_RULE : "If validation cannot run, say so and name the next-best check."} Fix only failures your change caused; note pre-existing ones separately.
|
|
67
68
|
|
|
68
69
|
${buildTestDisciplineSection()}
|
|
69
70
|
|
|
@@ -76,17 +77,19 @@ ${context.toolSection}
|
|
|
76
77
|
- Never swallow errors silently; never shotgun-debug with unrelated edits or blind retries.
|
|
77
78
|
- Never present partial work as complete, swap the request for an easier adjacent one, or deliver a stub, placeholder, or no-op as the feature; say what is done, what is not, and why you stopped.
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
${context.surface === "chat"
|
|
81
|
+
? CHAT_REPLIES_SECTION
|
|
82
|
+
: `## Handoff
|
|
80
83
|
|
|
81
84
|
At a handoff - ${GPT_HANDOFF_MOMENTS[context.surface]} - first work out what the user asked for and what they need to know now, then open with one block:
|
|
82
85
|
|
|
83
86
|
> [Outcome so far] toward [the user's original ask and the result they wanted]. You need: [ledger N/M done, findings, blockers]. Now: [todo task in progress]. Next: [next open task].
|
|
84
87
|
|
|
85
|
-
Now and Next are todo labels verbatim; the Next stated is executed in this same response with tool calls. Between handoffs, no narration
|
|
88
|
+
Now and Next are todo labels verbatim; the Next stated is executed in this same response with tool calls. Between handoffs, no narration.`}
|
|
86
89
|
|
|
87
90
|
## Style
|
|
88
91
|
|
|
89
|
-
Plain, concrete prose; bullets only for genuinely list-shaped content. The final message is the Handoff block: its outcome and You need slots carry the result and its verification, not a file-by-file changelog. Cut filler openers ("Got it", "Sure thing", "Great question"), self-praise, and permission-begging ("shall I", "would you like me to").
|
|
92
|
+
Plain, concrete prose; bullets only for genuinely list-shaped content. ${context.surface === "chat" ? `${CHAT_FINAL_MESSAGE}: it carries` : "The final message is the Handoff block: its outcome and You need slots carry"} the result and its verification, not a file-by-file changelog. Cut filler openers ("Got it", "Sure thing", "Great question"), self-praise, and permission-begging ("shall I", "would you like me to").
|
|
90
93
|
|
|
91
94
|
Have an opinion when context supports one. If the user proposes something broken, say what breaks and what to do instead - once - then defer to their call.
|
|
92
95
|
|
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
// user directive that progress be legible at every phase change; per the
|
|
62
62
|
// guide's "Simplify prompts first", the section is paid for by those deletions.
|
|
63
63
|
import { APP_NAME } from "../../../../config.js";
|
|
64
|
-
import { buildDynamicSystemPrompt } from "../../../dynamic-prompt/build.js";
|
|
64
|
+
import { buildDynamicSystemPrompt, terminalOrApp, } from "../../../dynamic-prompt/build.js";
|
|
65
|
+
import { CHAT_REPLIES_SECTION } from "../../../dynamic-prompt/handoff.js";
|
|
65
66
|
import { buildTestDisciplineSection } from "../../../dynamic-prompt/verification.js";
|
|
66
67
|
import { buildFileOperationsTuning } from "./file-operations.js";
|
|
67
68
|
import { buildGptEvalRoutingTuning } from "./gpt-eval-routing.js";
|
|
@@ -99,7 +100,7 @@ function buildGpt56Core(context) {
|
|
|
99
100
|
|
|
100
101
|
## Intent Gate
|
|
101
102
|
|
|
102
|
-
${INTENT_GATE_LEAD[context.surface]}
|
|
103
|
+
${INTENT_GATE_LEAD[terminalOrApp(context.surface)]}
|
|
103
104
|
|
|
104
105
|
Implement, don't propose. Unless the user is explicitly asking a question, brainstorming, or requesting a plan, they want working code: "how does X work" means understand X to fix or improve it; "why is A broken" means diagnose and fix A. Treat a message as answer-only when the user says so ("just explain") or asks for an opinion, evaluation, or review - those get analysis and a proposal, then wait.
|
|
105
106
|
|
|
@@ -126,7 +127,7 @@ Scale the scope of checks to the change, never the rigor:
|
|
|
126
127
|
- Single-domain behavioral change: type check on the changed code, related tests, one run of the affected entry point when one exists.
|
|
127
128
|
- Multi-file or cross-cutting work: type check, related tests, build, and the Manual QA Gate below.
|
|
128
129
|
|
|
129
|
-
Run the validator before reporting anything clean - "should pass" is not verification${context.surface
|
|
130
|
+
Run the validator before reporting anything clean - "should pass" is not verification${context.surface !== "terminal" ? `. ${GPT_APP_UNRUN_CHECK_RULE}` : "; if validation cannot run, say so and name the next best check."} Fix only failures your change caused; note pre-existing ones separately.
|
|
130
131
|
|
|
131
132
|
${TEST_DECISION}
|
|
132
133
|
|
|
@@ -163,17 +164,19 @@ ${context.toolSection}
|
|
|
163
164
|
- Never swallow errors silently; never shotgun-debug with unrelated edits or blind retries.
|
|
164
165
|
- Never present partial work as complete or deliver a stub, placeholder, or no-op as the feature; say what is done, what is not, and why you stopped.
|
|
165
166
|
|
|
166
|
-
|
|
167
|
+
${context.surface === "chat"
|
|
168
|
+
? CHAT_REPLIES_SECTION
|
|
169
|
+
: `## Handoff
|
|
167
170
|
|
|
168
171
|
At a handoff - ${GPT_HANDOFF_MOMENTS[context.surface]} - first work out what the user asked for and what they need to know now, then open with one block:
|
|
169
172
|
|
|
170
173
|
> [Outcome so far] toward [the user's original ask and the result they wanted]. You need: [ledger N/M done, findings, blockers]. Now: [todo task in progress]. Next: [next open task].
|
|
171
174
|
|
|
172
|
-
Now and Next are todo labels verbatim; the Next stated is executed in this same response with tool calls. Between handoffs, no narration
|
|
175
|
+
Now and Next are todo labels verbatim; the Next stated is executed in this same response with tool calls. Between handoffs, no narration.`}
|
|
173
176
|
|
|
174
177
|
## Output
|
|
175
178
|
|
|
176
|
-
Final message: the Handoff block, whose outcome leads and whose You need slot carries the evidence needed to trust it - what you verified, ${context.surface
|
|
179
|
+
Final message: ${context.surface === "chat" ? "the answer itself, whose outcome leads and which carries" : "the Handoff block, whose outcome leads and whose You need slot carries"} the evidence needed to trust it - what you verified, ${context.surface !== "terminal" ? GPT_APP_UNVERIFIED_SLOT : "what you could not and why"}, and pre-existing issues you left alone - grouped by user-facing outcome, not by file. Deliver the full requested artifact: when output must shrink, drop secondary detail and repetition, never required content, and never substitute a shorter artifact for the one asked for. Trim introductions and generic reassurance first.
|
|
177
180
|
|
|
178
181
|
Code reviews: findings first, ordered by severity with file references; then open questions and assumptions; change summary last. With no findings, say so and name residual risks or testing gaps.
|
|
179
182
|
|
|
@@ -190,7 +193,7 @@ Your STOP GOAL - the turn is over the moment ALL of these hold:
|
|
|
190
193
|
- Behavioral work passed the Manual QA Gate this turn.
|
|
191
194
|
- The final message is delivered as specified in Output.
|
|
192
195
|
|
|
193
|
-
Until the stop goal holds, keep going - through failed tool calls, long turns, and the temptation to hand back a draft. The moment it holds: re-read the original request once, confirm each item and ${context.surface
|
|
196
|
+
Until the stop goal holds, keep going - through failed tool calls, long turns, and the temptation to hand back a draft. The moment it holds: re-read the original request once, confirm each item and ${context.surface !== "terminal" ? "your stop condition" : "your declared stop condition"} against evidence already captured, deliver the final message, and STOP. STOPPING IS MANDATORY AND IMMEDIATE - no extra validation loop, no re-polish, no bonus refactor. Every action past the stop goal is a defect, not diligence.
|
|
194
197
|
|
|
195
198
|
${buildFileOperationsTuning({ toolNames: context.tools.map((tool) => tool.name) })}`;
|
|
196
199
|
}
|