s-app-scoder-agent 0.9.2 → 0.9.6
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 +615 -638
- package/dist/{guardrails.js → agent/guardrails.js} +1 -1
- package/dist/agent/interaction.js +70 -0
- package/dist/agent/mcp-bridge.js +136 -0
- package/dist/agent/prompt-context.js +83 -0
- package/dist/agent/run-loop.js +318 -0
- package/dist/agent/session-persistence.js +61 -0
- package/dist/agent/tool-executor.js +158 -0
- package/dist/agent/types.js +88 -0
- package/dist/agent/verification.js +99 -0
- package/dist/agent.js +239 -1002
- package/dist/cli/args.js +230 -0
- package/dist/cli/init.js +79 -0
- package/dist/cli/main.js +211 -0
- package/dist/cli/mcp-command.js +185 -0
- package/dist/cli/repl.js +77 -0
- package/dist/cli/run-once.js +26 -0
- package/dist/{tui/commands.js → commands/definitions.js} +6 -16
- package/dist/commands/registry.js +260 -0
- package/dist/{config.js → config/config.js} +1 -1
- package/dist/{prompt-builder.js → context/prompt-builder.js} +12 -1
- package/dist/{prompt.js → context/prompt.js} +111 -9
- package/dist/{skills.js → context/skills.js} +41 -2
- package/dist/index.js +5 -798
- package/dist/io/console-reporter.js +24 -0
- package/dist/io/reporter.js +1 -0
- package/dist/mcp/connection.js +227 -0
- package/dist/mcp/env.js +8 -0
- package/dist/{mcp.js → mcp/manager.js} +3 -515
- package/dist/mcp/sse.js +28 -0
- package/dist/mcp/transport-http.js +140 -0
- package/dist/mcp/transport-stdio.js +98 -0
- package/dist/mcp/types.js +11 -0
- package/dist/media/image.js +149 -0
- package/dist/{server.js → server/server.js} +1 -1
- package/dist/{cost.js → session/cost.js} +1 -1
- package/dist/{session.js → session/session.js} +1 -1
- package/dist/{version.js → shared/version.js} +1 -1
- package/dist/tools/apply-patch.js +62 -0
- package/dist/tools/edit-file.js +29 -0
- package/dist/tools/file-edit-common.js +124 -0
- package/dist/tools/list-files.js +64 -0
- package/dist/tools/path-safety.js +75 -0
- package/dist/tools/read-file.js +64 -0
- package/dist/tools/registry.js +297 -0
- package/dist/tools/run-command.js +192 -0
- package/dist/tools/schemas.js +8 -0
- package/dist/tools/search.js +237 -0
- package/dist/tools/task-tool.js +48 -0
- package/dist/tools/types.js +1 -0
- package/dist/tools/write-file.js +34 -0
- package/dist/tui/app.js +59 -532
- package/dist/tui/ask-user-modal.js +2 -1
- package/dist/tui/at-complete.js +2 -93
- package/dist/tui/charset.js +41 -0
- package/dist/tui/chat-views.js +72 -16
- package/dist/tui/chrome.js +11 -4
- package/dist/tui/hooks/use-command-host.js +26 -0
- package/dist/tui/hooks/use-event-queue.js +69 -0
- package/dist/tui/hooks/use-keybinds.js +87 -0
- package/dist/tui/hooks/use-scroll.js +38 -0
- package/dist/tui/hooks/use-session-resume.js +47 -0
- package/dist/tui/hooks/use-submit.js +106 -0
- package/dist/tui/image.js +2 -149
- package/dist/tui/input.js +1 -1
- package/dist/tui/markdown/ast.js +5 -0
- package/dist/tui/markdown/diagram.js +239 -0
- package/dist/tui/markdown/inline-render.js +24 -0
- package/dist/tui/markdown/inline.js +93 -0
- package/dist/tui/markdown/parse.js +139 -0
- package/dist/tui/markdown/render.js +146 -0
- package/dist/tui/markdown/table.js +106 -0
- package/dist/tui/markdown.js +32 -379
- package/dist/tui/permission-modal.js +2 -1
- package/dist/tui/selectors.js +157 -0
- package/dist/tui/session-picker.js +4 -3
- package/dist/tui/sidebar.js +130 -15
- package/dist/tui/state.js +47 -118
- package/dist/tui/text-width.js +139 -0
- package/dist/tui/theme.js +7 -2
- package/dist/{build.js → workspace/build.js} +1 -1
- package/dist/workspace/file-index.js +93 -0
- package/package.json +5 -1
- package/dist/tools.js +0 -1223
- package/dist/tui/command-registry.js +0 -477
- package/dist/tui/review.js +0 -64
- package/dist/tui/transcript.js +0 -145
- /package/dist/{agents-guide.js → context/agents-guide.js} +0 -0
- /package/dist/{agents.js → context/agents.js} +0 -0
- /package/dist/{compaction.js → context/compaction.js} +0 -0
- /package/dist/{context.js → context/context.js} +0 -0
- /package/dist/{memory.js → context/memory.js} +0 -0
- /package/dist/{repo-map.js → context/repo-map.js} +0 -0
- /package/dist/{ui.js → io/terminal.js} +0 -0
- /package/dist/{llm.js → llm/llm.js} +0 -0
- /package/dist/{model-catalog.js → llm/model-catalog.js} +0 -0
- /package/dist/{provider-anthropic.js → llm/provider-anthropic.js} +0 -0
- /package/dist/{provider-registry.js → llm/provider-registry.js} +0 -0
- /package/dist/{retry.js → llm/retry.js} +0 -0
- /package/dist/{mcp-import.js → mcp/mcp-import.js} +0 -0
- /package/dist/{permissions.js → security/permissions.js} +0 -0
- /package/dist/{sandbox.js → security/sandbox.js} +0 -0
- /package/dist/{shell-scanner.js → security/shell-scanner.js} +0 -0
- /package/dist/{logger.js → session/logger.js} +0 -0
- /package/dist/{steering.js → session/steering.js} +0 -0
- /package/dist/{constants.js → shared/constants.js} +0 -0
- /package/dist/{json-schema.js → shared/json-schema.js} +0 -0
- /package/dist/{webfetch.js → tools/webfetch.js} +0 -0
- /package/dist/{diagnostics.js → workspace/diagnostics.js} +0 -0
- /package/dist/{diff.js → workspace/diff.js} +0 -0
- /package/dist/{snapshot.js → workspace/snapshot.js} +0 -0
- /package/dist/{watch.js → workspace/watch.js} +0 -0
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
* - versioning rõ ràng (PROMPT_VERSION được ghi vào session JSONL khi chạy),
|
|
4
4
|
* - test được độc lập (không cần instantiate Agent).
|
|
5
5
|
*
|
|
6
|
+
* V6 — compact rewrite (~40% ngắn hơn V5, giữ nguyên behaviour contract):
|
|
7
|
+
* - Gộp decision policy vào workflow; gộp anti-hallucination vào verification;
|
|
8
|
+
* tools chỉ giữ policy (mô tả tool đã có trong tool schema); nén output.
|
|
9
|
+
* - PROMPT_VERSION = 6. V5/V4 giữ lại nguyên vẹn để rollback qua rc
|
|
10
|
+
* "promptVersion": 5 | 4 (eval gate trước khi ship V6).
|
|
11
|
+
*
|
|
6
12
|
* V5 — structured sections + decision policy + anti-hallucination
|
|
7
|
-
* - Prompt tách thành section có ID + token budget (xem
|
|
8
|
-
* PROMPT_VERSION = 5. V4 giữ lại nguyên vẹn để rollback qua rc
|
|
9
|
-
* "promptVersion": 4 (eval gate trước khi ship V5).
|
|
13
|
+
* - Prompt tách thành section có ID + token budget (xem PROMPT_SECTIONS_V5).
|
|
10
14
|
* - V4 baseline (xem dưới) — V5 thêm: decision policy (khi nào plan / hỏi /
|
|
11
15
|
* dừng), anti-hallucination (không bịa API/path — verify bằng tool),
|
|
12
16
|
* trả lời theo ngôn ngữ của user, memory-respect sau compaction.
|
|
@@ -18,7 +22,7 @@
|
|
|
18
22
|
* - V3 baseline: stricter scope rules, clarification-before-action, safety
|
|
19
23
|
* boundaries, MCP/skills as passive listings only
|
|
20
24
|
*/
|
|
21
|
-
export const PROMPT_VERSION =
|
|
25
|
+
export const PROMPT_VERSION = 6;
|
|
22
26
|
/** V4 prompt — kept for rollback (rc "promptVersion": 4). */
|
|
23
27
|
export const SYSTEM_PROMPT_V4 = `You are Scoder, an autonomous coding agent running in a terminal.
|
|
24
28
|
You complete coding tasks end-to-end: exploring the code, editing files, and
|
|
@@ -104,7 +108,7 @@ verifying your work with the build command. You act; you don't just advise.
|
|
|
104
108
|
- If you add code, add only what's needed now; note follow-ups in your final
|
|
105
109
|
message instead of implementing them.`;
|
|
106
110
|
// ── V5 sections — each with a stable ID and an approximate token budget ──────
|
|
107
|
-
export const
|
|
111
|
+
export const PROMPT_SECTION_BUDGETS_V5 = {
|
|
108
112
|
identity: 60,
|
|
109
113
|
decision: 180,
|
|
110
114
|
workflow: 220,
|
|
@@ -115,7 +119,7 @@ export const PROMPT_SECTION_BUDGETS = {
|
|
|
115
119
|
memory: 60,
|
|
116
120
|
output: 60,
|
|
117
121
|
};
|
|
118
|
-
export const
|
|
122
|
+
export const PROMPT_SECTIONS_V5 = {
|
|
119
123
|
identity: `You are Scoder, an autonomous coding agent running in a terminal.
|
|
120
124
|
You complete coding tasks end-to-end: exploring the code, editing files, and
|
|
121
125
|
verifying your work with the build command. You act; you don't just advise.`,
|
|
@@ -193,7 +197,19 @@ verifying your work with the build command. You act; you don't just advise.`,
|
|
|
193
197
|
output: `## Output
|
|
194
198
|
- Reply in the user's language. Keep final reports concise and factual.
|
|
195
199
|
- End the run with <<CHAT_DONE>> only for conversational turns (see Verification).
|
|
196
|
-
- Never print secrets (API keys, tokens, .env contents)
|
|
200
|
+
- Never print secrets (API keys, tokens, .env contents).
|
|
201
|
+
|
|
202
|
+
## Terminal markdown
|
|
203
|
+
Your answers render in a terminal (Ink). Markdown displays best when you:
|
|
204
|
+
- Tables: at most 6 columns with short cell text; no line breaks inside cells;
|
|
205
|
+
escape literal pipes as \\| and keep pipes inside \`code spans\` intact.
|
|
206
|
+
- Diagrams: keep \`\`\`mermaid sources simple (flowchart/sequence with plain
|
|
207
|
+
node ids). The terminal shows a structured summary, not the graph image.
|
|
208
|
+
- Numeric comparisons/trends: prefer a \`\`\`chart fence (JSON array of
|
|
209
|
+
{"label","value"}) — it renders as a native terminal bar/pie chart.
|
|
210
|
+
- Code fences: always tag the language; keep lines reasonably short (they wrap
|
|
211
|
+
otherwise, which is fine, but short lines read better).
|
|
212
|
+
- Use headings (##), bullet lists, and **bold** freely — they render well.`,
|
|
197
213
|
};
|
|
198
214
|
/** V5 — assembled from the sections above (order matters). */
|
|
199
215
|
function assembleV5() {
|
|
@@ -208,12 +224,98 @@ function assembleV5() {
|
|
|
208
224
|
"memory",
|
|
209
225
|
"output",
|
|
210
226
|
];
|
|
227
|
+
return order.map((id) => PROMPT_SECTIONS_V5[id]).join("\n\n");
|
|
228
|
+
}
|
|
229
|
+
/** V5 prompt — kept for rollback (rc "promptVersion": 5). */
|
|
230
|
+
export const SYSTEM_PROMPT_V5 = assembleV5();
|
|
231
|
+
// ── V6 sections — compact: decision merged into workflow, antihalluc into
|
|
232
|
+
// verification, tools keeps policy only (schemas describe the tools) ──────
|
|
233
|
+
export const PROMPT_SECTION_BUDGETS = {
|
|
234
|
+
identity: 60,
|
|
235
|
+
workflow: 260,
|
|
236
|
+
tools: 200,
|
|
237
|
+
safety: 140,
|
|
238
|
+
verification: 200,
|
|
239
|
+
memory: 60,
|
|
240
|
+
output: 120,
|
|
241
|
+
};
|
|
242
|
+
export const PROMPT_SECTIONS = {
|
|
243
|
+
identity: PROMPT_SECTIONS_V5.identity,
|
|
244
|
+
workflow: `## How you work
|
|
245
|
+
1. ORIENT: use the REPO MAP (if present) to locate files; read every file you
|
|
246
|
+
will edit — never edit a file you haven't read. Respect AGENTS.md.
|
|
247
|
+
2. PLAN: tasks needing ≥3 steps or >1 file — call write_todos with the full
|
|
248
|
+
plan BEFORE editing; one in_progress at a time, mark done IMMEDIATELY.
|
|
249
|
+
Trivial single-step tasks need no plan. Ambiguous or irreversibly
|
|
250
|
+
destructive request? Ask ONE clarifying question (ask_user) — don't guess.
|
|
251
|
+
Focused sub-question that would burn many steps? Delegate it (task tool).
|
|
252
|
+
3. EDIT: small, focused changes matching the file's existing style; never
|
|
253
|
+
reformat, refactor, or fix unrelated code. Smallest change that solves it.
|
|
254
|
+
4. VERIFY: changed files? Run the build command. Read the FULL error output
|
|
255
|
+
before editing — fix the CAUSE, not the symptom. Same error twice? Step
|
|
256
|
+
back and re-read the failing code path instead of retrying the fix.
|
|
257
|
+
5. REPORT: state what changed, why, and anything unresolved — if something
|
|
258
|
+
failed, say exactly what.`,
|
|
259
|
+
tools: `## Tool policy
|
|
260
|
+
- Orient with list_files / grep / glob / repo_map — prefer them over shell
|
|
261
|
+
greps. read_file before every edit_file.
|
|
262
|
+
- edit_file: old_string MUST appear exactly once — otherwise re-read the file
|
|
263
|
+
and add more context.
|
|
264
|
+
- run_command IS the build command: run it only when you changed files; a
|
|
265
|
+
coding task ends with run_command(<buildCmd>). A build with no changes
|
|
266
|
+
proves nothing — skip it.
|
|
267
|
+
- web_fetch: exact URLs only (it cannot search) — library/API docs, versions.
|
|
268
|
+
- load_skill: only on explicit "/skill <name>" or a clear domain match — never
|
|
269
|
+
auto-load. MCP tools (mcp__<server>__<tool>): only when the task explicitly
|
|
270
|
+
requires external integration — never just because they exist.`,
|
|
271
|
+
safety: `## Safety & scope
|
|
272
|
+
- NEVER modify git hooks, CI configs, package.json scripts, dependencies, or
|
|
273
|
+
production infra configs unless explicitly asked; NEVER run destructive
|
|
274
|
+
commands (rm -rf, --force, --rebase) without explaining the risk first.
|
|
275
|
+
- Work within the EXACT scope of the request: no unrelated fixes, refactors,
|
|
276
|
+
or speculative features.
|
|
277
|
+
- If run_command is denied by permission policy, find a safer alternative or
|
|
278
|
+
report the limitation — do not retry the same denied command.`,
|
|
279
|
+
verification: `## Verification & honesty
|
|
280
|
+
- A coding task is done when the build passes; failing tests count as build
|
|
281
|
+
failures. Never claim completion without verifying first.
|
|
282
|
+
- NEVER invent file paths, function names, APIs, flags, versions, or error
|
|
283
|
+
meanings — verify with tools (read_file / grep / web_fetch) BEFORE using,
|
|
284
|
+
and cite file:line for claims you cannot show verbatim.
|
|
285
|
+
- If an environmental problem makes the task impossible, stop and report it.
|
|
286
|
+
- CONVERSATIONAL INPUT (greeting, thanks, or a question needing no code
|
|
287
|
+
changes and no shell commands): use no tools, edit no files, run no build —
|
|
288
|
+
reply briefly in the user's language and end with <<CHAT_DONE>> on its own
|
|
289
|
+
last line.`,
|
|
290
|
+
memory: `## Memory
|
|
291
|
+
- Treat the compaction summary and WorkingMemory ledger as ground truth — do
|
|
292
|
+
not re-ask, redo, or re-read what they already record.`,
|
|
293
|
+
output: `## Output
|
|
294
|
+
- Reply in the user's language; keep final reports concise. Never print
|
|
295
|
+
secrets (API keys, tokens, .env contents).
|
|
296
|
+
- Terminal markdown: tag code fences with the language; tables ≤6 columns,
|
|
297
|
+
short cells; keep mermaid sources simple (flowchart/sequence, plain ids);
|
|
298
|
+
numeric trends as a \`\`\`chart fence (JSON array of {"label","value"}).`,
|
|
299
|
+
};
|
|
300
|
+
/** V6 — assembled from the sections above (order matters). */
|
|
301
|
+
function assembleV6() {
|
|
302
|
+
const order = [
|
|
303
|
+
"identity",
|
|
304
|
+
"workflow",
|
|
305
|
+
"tools",
|
|
306
|
+
"safety",
|
|
307
|
+
"verification",
|
|
308
|
+
"memory",
|
|
309
|
+
"output",
|
|
310
|
+
];
|
|
211
311
|
return order.map((id) => PROMPT_SECTIONS[id]).join("\n\n");
|
|
212
312
|
}
|
|
213
|
-
export const SYSTEM_PROMPT =
|
|
313
|
+
export const SYSTEM_PROMPT = assembleV6();
|
|
214
314
|
/** Ghép phần động (workdir/build/env/skills/MCP) vào system prompt gốc. */
|
|
215
315
|
export function buildSystemPrompt(parts) {
|
|
216
|
-
const base = parts.base ?? (parts.promptVersion === 4 ? SYSTEM_PROMPT_V4 :
|
|
316
|
+
const base = parts.base ?? (parts.promptVersion === 4 ? SYSTEM_PROMPT_V4 :
|
|
317
|
+
parts.promptVersion === 5 ? SYSTEM_PROMPT_V5 :
|
|
318
|
+
SYSTEM_PROMPT);
|
|
217
319
|
return (base +
|
|
218
320
|
`\n\nWorking directory: ${parts.workdir}\nBuild command (stop condition): ${parts.buildCmd}\n${parts.envInfo}` +
|
|
219
321
|
(parts.agentsGuideBlock ?? "") +
|
|
@@ -192,9 +192,48 @@ export function discoverSkills(workdir) {
|
|
|
192
192
|
}
|
|
193
193
|
return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
194
194
|
}
|
|
195
|
+
/**
|
|
196
|
+
* Tìm skill theo tên. Ngoài exact match (case-insensitive), chịu cả trường
|
|
197
|
+
* hợp model/user dán thêm text sau tên skill — vd load_skill với name =
|
|
198
|
+
* "review-and-select-prompt cung cấp angular new feature": thử first token,
|
|
199
|
+
* rồi tên skill dài nhất là prefix của input (theo word boundary).
|
|
200
|
+
*/
|
|
195
201
|
export function findSkill(workdir, name) {
|
|
196
|
-
const
|
|
197
|
-
|
|
202
|
+
const skills = discoverSkills(workdir);
|
|
203
|
+
const wanted = name.trim().toLowerCase();
|
|
204
|
+
const exact = skills.find((s) => s.name.toLowerCase() === wanted);
|
|
205
|
+
if (exact)
|
|
206
|
+
return exact;
|
|
207
|
+
const firstToken = wanted.split(/\s+/)[0];
|
|
208
|
+
const byToken = skills.find((s) => s.name.toLowerCase() === firstToken);
|
|
209
|
+
if (byToken)
|
|
210
|
+
return byToken;
|
|
211
|
+
const byPrefix = skills
|
|
212
|
+
.filter((s) => {
|
|
213
|
+
const n = s.name.toLowerCase();
|
|
214
|
+
return wanted.startsWith(n) && wanted.length > n.length && /[\s/]/.test(wanted[n.length]);
|
|
215
|
+
})
|
|
216
|
+
.sort((a, b) => b.name.length - a.name.length)[0];
|
|
217
|
+
return byPrefix ?? null;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Tách "/skill <name> <task text…>": khớp tên skill DÀI NHẤT ở đầu arg
|
|
221
|
+
* (word boundary) và trả về phần text còn lại. Dùng cho slash command để
|
|
222
|
+
* stage skill rồi chạy ngay task đi kèm thay vì nuốt task text vào tên.
|
|
223
|
+
*/
|
|
224
|
+
export function matchSkillPrefix(workdir, arg) {
|
|
225
|
+
const trimmed = arg.trim();
|
|
226
|
+
const wanted = trimmed.toLowerCase();
|
|
227
|
+
const skills = discoverSkills(workdir).sort((a, b) => b.name.length - a.name.length);
|
|
228
|
+
for (const s of skills) {
|
|
229
|
+
const n = s.name.toLowerCase();
|
|
230
|
+
if (wanted === n)
|
|
231
|
+
return { skill: s, rest: "" };
|
|
232
|
+
if (wanted.startsWith(n) && /[\s/]/.test(wanted[n.length])) {
|
|
233
|
+
return { skill: s, rest: trimmed.slice(n.length).trim() };
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return null;
|
|
198
237
|
}
|
|
199
238
|
export function formatSkillIndex(skills) {
|
|
200
239
|
if (skills.length === 0)
|