@glbgpt/cli 0.1.4 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -39
- package/dist/src/coding/backgroundTasks.d.ts +34 -0
- package/dist/src/coding/backgroundTasks.js +154 -0
- package/dist/src/coding/backgroundTasks.js.map +1 -0
- package/dist/src/coding/backgroundTools.d.ts +9 -0
- package/dist/src/coding/backgroundTools.js +63 -0
- package/dist/src/coding/backgroundTools.js.map +1 -0
- package/dist/src/coding/bashTool.d.ts +27 -0
- package/dist/src/coding/bashTool.js +144 -0
- package/dist/src/coding/bashTool.js.map +1 -0
- package/dist/src/coding/dangerousCommands.d.ts +29 -0
- package/dist/src/coding/dangerousCommands.js +156 -0
- package/dist/src/coding/dangerousCommands.js.map +1 -0
- package/dist/src/coding/editDiff.d.ts +45 -0
- package/dist/src/coding/editDiff.js +156 -0
- package/dist/src/coding/editDiff.js.map +1 -0
- package/dist/src/coding/editTool.d.ts +14 -0
- package/dist/src/coding/editTool.js +154 -0
- package/dist/src/coding/editTool.js.map +1 -0
- package/dist/src/coding/index.d.ts +25 -0
- package/dist/src/coding/index.js +30 -0
- package/dist/src/coding/index.js.map +1 -0
- package/dist/src/coding/outputAccumulator.d.ts +34 -0
- package/dist/src/coding/outputAccumulator.js +111 -0
- package/dist/src/coding/outputAccumulator.js.map +1 -0
- package/dist/src/coding/permissionGate.d.ts +65 -0
- package/dist/src/coding/permissionGate.js +138 -0
- package/dist/src/coding/permissionGate.js.map +1 -0
- package/dist/src/coding/permissionStore.d.ts +36 -0
- package/dist/src/coding/permissionStore.js +56 -0
- package/dist/src/coding/permissionStore.js.map +1 -0
- package/dist/src/coding/permissions.d.ts +34 -0
- package/dist/src/coding/permissions.js +18 -0
- package/dist/src/coding/permissions.js.map +1 -0
- package/dist/src/coding/projectContext.d.ts +21 -0
- package/dist/src/coding/projectContext.js +118 -0
- package/dist/src/coding/projectContext.js.map +1 -0
- package/dist/src/coding/readState.d.ts +22 -0
- package/dist/src/coding/readState.js +30 -0
- package/dist/src/coding/readState.js.map +1 -0
- package/dist/src/coding/truncate.d.ts +39 -0
- package/dist/src/coding/truncate.js +83 -0
- package/dist/src/coding/truncate.js.map +1 -0
- package/dist/src/coding/writeTool.d.ts +14 -0
- package/dist/src/coding/writeTool.js +82 -0
- package/dist/src/coding/writeTool.js.map +1 -0
- package/dist/src/commands/execCommand.d.ts +8 -0
- package/dist/src/commands/execCommand.js +45 -5
- package/dist/src/commands/execCommand.js.map +1 -1
- package/dist/src/core/catalog.js +5 -0
- package/dist/src/core/catalog.js.map +1 -1
- package/dist/src/core/compaction.d.ts +52 -0
- package/dist/src/core/compaction.js +151 -0
- package/dist/src/core/compaction.js.map +1 -0
- package/dist/src/core/contextPrune.js +8 -1
- package/dist/src/core/contextPrune.js.map +1 -1
- package/dist/src/core/runChat.d.ts +1 -1
- package/dist/src/core/runChat.js +1 -1
- package/dist/src/core/runChat.js.map +1 -1
- package/dist/src/core/session.d.ts +10 -1
- package/dist/src/core/session.js +11 -2
- package/dist/src/core/session.js.map +1 -1
- package/dist/src/core/turnLoop.d.ts +18 -2
- package/dist/src/core/turnLoop.js +79 -12
- package/dist/src/core/turnLoop.js.map +1 -1
- package/dist/src/exec/output.d.ts +3 -2
- package/dist/src/exec/output.js +17 -4
- package/dist/src/exec/output.js.map +1 -1
- package/dist/src/fs/index.d.ts +4 -1
- package/dist/src/fs/index.js +7 -2
- package/dist/src/fs/index.js.map +1 -1
- package/dist/src/fs/limits.d.ts +1 -1
- package/dist/src/fs/limits.js +3 -1
- package/dist/src/fs/limits.js.map +1 -1
- package/dist/src/fs/readFileTool.d.ts +2 -1
- package/dist/src/fs/readFileTool.js +4 -1
- package/dist/src/fs/readFileTool.js.map +1 -1
- package/dist/src/fs/workspaceGuard.d.ts +8 -0
- package/dist/src/fs/workspaceGuard.js +48 -0
- package/dist/src/fs/workspaceGuard.js.map +1 -1
- package/dist/src/index.js +37 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/tui/App.d.ts +10 -1
- package/dist/src/tui/App.js +114 -15
- package/dist/src/tui/App.js.map +1 -1
- package/dist/src/tui/approvalBridge.d.ts +21 -0
- package/dist/src/tui/approvalBridge.js +45 -0
- package/dist/src/tui/approvalBridge.js.map +1 -0
- package/dist/src/tui/chatController.d.ts +21 -0
- package/dist/src/tui/chatController.js +155 -16
- package/dist/src/tui/chatController.js.map +1 -1
- package/dist/src/tui/commands.js +16 -2
- package/dist/src/tui/commands.js.map +1 -1
- package/dist/src/tui/models.d.ts +4 -0
- package/dist/src/tui/models.js +8 -1
- package/dist/src/tui/models.js.map +1 -1
- package/dist/src/tui/run.d.ts +7 -0
- package/dist/src/tui/run.js +69 -9
- package/dist/src/tui/run.js.map +1 -1
- package/dist/src/web/webFetchTool.js +41 -5
- package/dist/src/web/webFetchTool.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Project context + coding guidance injected as ONE client-side system message
|
|
5
|
+
* (the server's base system prompt stays untouched and precedes it).
|
|
6
|
+
*
|
|
7
|
+
* AGENTS.md discovery (codex lineage, 2026-08-21 dossier): walk from the workspace
|
|
8
|
+
* root UP to the repository root (nearest ancestor containing `.git`; the workspace
|
|
9
|
+
* itself when none), taking the first hit of AGENTS.md > CLAUDE.md per directory,
|
|
10
|
+
* emitted root-first so deeper files override shallower ones by proximity. One
|
|
11
|
+
* shared byte budget caps the total.
|
|
12
|
+
*/
|
|
13
|
+
const CONTEXT_FILE_CANDIDATES = ['AGENTS.md', 'CLAUDE.md'];
|
|
14
|
+
export const PROJECT_CONTEXT_MAX_BYTES = 32 * 1024;
|
|
15
|
+
async function readFirstCandidate(dir) {
|
|
16
|
+
for (const name of CONTEXT_FILE_CANDIDATES) {
|
|
17
|
+
const file = path.join(dir, name);
|
|
18
|
+
try {
|
|
19
|
+
const stat = await fs.stat(file);
|
|
20
|
+
if (!stat.isFile())
|
|
21
|
+
continue;
|
|
22
|
+
const content = (await fs.readFile(file, 'utf8')).replace(/^\uFEFF/, '');
|
|
23
|
+
if (content.trim().length === 0)
|
|
24
|
+
continue;
|
|
25
|
+
return { path: file, content };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Missing/unreadable → try the next candidate.
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
async function isRepoRoot(dir) {
|
|
34
|
+
try {
|
|
35
|
+
await fs.stat(path.join(dir, '.git'));
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Collect context files from the repo root down to `workspaceRoot` (root-first order),
|
|
44
|
+
* within one shared byte budget. Files that would blow the budget are skipped whole
|
|
45
|
+
* (never truncated mid-file — a half instruction is worse than none).
|
|
46
|
+
*/
|
|
47
|
+
export async function loadProjectContext(workspaceRoot, maxBytes = PROJECT_CONTEXT_MAX_BYTES) {
|
|
48
|
+
// Walk upward collecting candidate dirs until (and including) the repo root.
|
|
49
|
+
const dirs = [];
|
|
50
|
+
let dir = workspaceRoot;
|
|
51
|
+
for (let depth = 0; depth < 64; depth++) {
|
|
52
|
+
dirs.push(dir);
|
|
53
|
+
if (await isRepoRoot(dir))
|
|
54
|
+
break;
|
|
55
|
+
const parent = path.dirname(dir);
|
|
56
|
+
if (parent === dir)
|
|
57
|
+
break;
|
|
58
|
+
dir = parent;
|
|
59
|
+
}
|
|
60
|
+
dirs.reverse(); // root-first
|
|
61
|
+
const files = [];
|
|
62
|
+
let budget = maxBytes;
|
|
63
|
+
for (const d of dirs) {
|
|
64
|
+
const file = await readFirstCandidate(d);
|
|
65
|
+
if (!file)
|
|
66
|
+
continue;
|
|
67
|
+
const bytes = Buffer.byteLength(file.content, 'utf8');
|
|
68
|
+
if (bytes > budget)
|
|
69
|
+
continue;
|
|
70
|
+
budget -= bytes;
|
|
71
|
+
files.push(file);
|
|
72
|
+
}
|
|
73
|
+
return files;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* The coding-guidance system message. Kept deliberately short (pi style): tool-choice
|
|
77
|
+
* strategy the tool descriptions cannot express, the safety posture, and the project
|
|
78
|
+
* instructions. Written to degrade gracefully for models without tool_use — every
|
|
79
|
+
* rule is scoped to "when the tools are available".
|
|
80
|
+
*/
|
|
81
|
+
export function buildCodingSystemMessage(opts) {
|
|
82
|
+
const lines = [
|
|
83
|
+
'When file and shell tools are available, follow these guidelines:',
|
|
84
|
+
'- Prefer the dedicated tools over bash equivalents: read_file over cat/head/tail/sed, ' +
|
|
85
|
+
'grep over grep/rg, glob over find, list_dir over ls, edit_file over sed/awk, ' +
|
|
86
|
+
'write_file over echo/heredoc redirection. They are safer and their output is easier to review.',
|
|
87
|
+
'- Use edit_file for targeted changes (one call with multiple edits[] for several spots in ' +
|
|
88
|
+
'one file); use write_file only for new files or complete rewrites.',
|
|
89
|
+
'- Read a file before editing or overwriting it; re-read it if it changed.',
|
|
90
|
+
'- Use bash for real commands (builds, tests, git, package managers). Shell state does not ' +
|
|
91
|
+
'persist between bash calls and the working directory is always the workspace root — use ' +
|
|
92
|
+
'absolute paths or `cd` within a single command.',
|
|
93
|
+
'- For long-running commands (dev servers, watchers) use bash with run_in_background: true, ' +
|
|
94
|
+
'then poll bash_output and stop with bash_kill when done.',
|
|
95
|
+
'- After making changes, verify them when possible (run the tests or build the project).',
|
|
96
|
+
'- Independent read-only tool calls can be issued together in one round; mutations run one at a time.',
|
|
97
|
+
'- Some actions require user approval. If one is denied, do not retry it verbatim — adjust ' +
|
|
98
|
+
'your approach or ask the user.',
|
|
99
|
+
'- Match the style of the surrounding code; keep changes minimal and scoped to the request.',
|
|
100
|
+
`Workspace root: ${opts.workspaceRoot}`,
|
|
101
|
+
];
|
|
102
|
+
if (opts.contextFiles.length > 0) {
|
|
103
|
+
lines.push('');
|
|
104
|
+
lines.push('<project_context>');
|
|
105
|
+
lines.push('');
|
|
106
|
+
lines.push('Project-specific instructions and guidelines:');
|
|
107
|
+
for (const f of opts.contextFiles) {
|
|
108
|
+
lines.push('');
|
|
109
|
+
lines.push(`<project_instructions path="${f.path}">`);
|
|
110
|
+
lines.push(f.content.trimEnd());
|
|
111
|
+
lines.push('</project_instructions>');
|
|
112
|
+
}
|
|
113
|
+
lines.push('');
|
|
114
|
+
lines.push('</project_context>');
|
|
115
|
+
}
|
|
116
|
+
return lines.join('\n');
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=projectContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectContext.js","sourceRoot":"","sources":["../../../src/coding/projectContext.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-scoped record of which files the model has READ, keyed by canonical
|
|
3
|
+
* (realpath) file path. write_file/edit_file consult it to enforce the
|
|
4
|
+
* read-before-mutate rule (Claude Code lineage):
|
|
5
|
+
*
|
|
6
|
+
* - Overwriting or editing an existing file the model never read this session
|
|
7
|
+
* is refused (it would be writing blind).
|
|
8
|
+
* - A file whose mtime changed since the recorded read is refused until re-read
|
|
9
|
+
* (the user or a linter touched it — the model's mental copy is stale).
|
|
10
|
+
*
|
|
11
|
+
* A PARTIAL read (offset/limit range) still counts as "read": files past the
|
|
12
|
+
* whole-file read limits can only ever be range-read, and grep-located edits
|
|
13
|
+
* are a normal flow. Staleness is judged by mtime alone.
|
|
14
|
+
*/
|
|
15
|
+
export declare class ReadFileState {
|
|
16
|
+
private readonly files;
|
|
17
|
+
/** Record a successful read (read_file) or a mutation we just made ourselves. */
|
|
18
|
+
record(realPath: string, mtimeMs: number): void;
|
|
19
|
+
has(realPath: string): boolean;
|
|
20
|
+
/** True when the file's current mtime no longer matches the recorded read. */
|
|
21
|
+
isStale(realPath: string, currentMtimeMs: number): boolean;
|
|
22
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-scoped record of which files the model has READ, keyed by canonical
|
|
3
|
+
* (realpath) file path. write_file/edit_file consult it to enforce the
|
|
4
|
+
* read-before-mutate rule (Claude Code lineage):
|
|
5
|
+
*
|
|
6
|
+
* - Overwriting or editing an existing file the model never read this session
|
|
7
|
+
* is refused (it would be writing blind).
|
|
8
|
+
* - A file whose mtime changed since the recorded read is refused until re-read
|
|
9
|
+
* (the user or a linter touched it — the model's mental copy is stale).
|
|
10
|
+
*
|
|
11
|
+
* A PARTIAL read (offset/limit range) still counts as "read": files past the
|
|
12
|
+
* whole-file read limits can only ever be range-read, and grep-located edits
|
|
13
|
+
* are a normal flow. Staleness is judged by mtime alone.
|
|
14
|
+
*/
|
|
15
|
+
export class ReadFileState {
|
|
16
|
+
files = new Map();
|
|
17
|
+
/** Record a successful read (read_file) or a mutation we just made ourselves. */
|
|
18
|
+
record(realPath, mtimeMs) {
|
|
19
|
+
this.files.set(realPath, { mtimeMs });
|
|
20
|
+
}
|
|
21
|
+
has(realPath) {
|
|
22
|
+
return this.files.has(realPath);
|
|
23
|
+
}
|
|
24
|
+
/** True when the file's current mtime no longer matches the recorded read. */
|
|
25
|
+
isStale(realPath, currentMtimeMs) {
|
|
26
|
+
const rec = this.files.get(realPath);
|
|
27
|
+
return rec !== undefined && rec.mtimeMs !== currentMtimeMs;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=readState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readState.js","sourceRoot":"","sources":["../../../src/coding/readState.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,aAAa;IACP,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;IAEhE,iFAAiF;IACjF,MAAM,CAAC,QAAgB,EAAE,OAAe;QACtC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,GAAG,CAAC,QAAgB;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAED,8EAA8E;IAC9E,OAAO,CAAC,QAAgB,EAAE,cAAsB;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACrC,OAAO,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,OAAO,KAAK,cAAc,CAAC;IAC7D,CAAC;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tail truncation for command output (pi contract, 2026-08-21 dossier):
|
|
3
|
+
* two independent limits — max lines and max bytes — whichever is hit first.
|
|
4
|
+
* Never returns a partial line, with ONE explicit exception: when the final
|
|
5
|
+
* line alone exceeds the byte limit, its tail is returned and flagged
|
|
6
|
+
* `lastLinePartial`. Byte cuts land on UTF-8 boundaries so multibyte
|
|
7
|
+
* characters are never split.
|
|
8
|
+
*
|
|
9
|
+
* Tail (not head) because for command output the errors and final results
|
|
10
|
+
* live at the end.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_MAX_OUTPUT_LINES = 2000;
|
|
13
|
+
export declare const DEFAULT_MAX_OUTPUT_BYTES: number;
|
|
14
|
+
export interface TailTruncation {
|
|
15
|
+
/** The (possibly truncated) text to show. */
|
|
16
|
+
text: string;
|
|
17
|
+
truncated: boolean;
|
|
18
|
+
truncatedBy: 'lines' | 'bytes' | null;
|
|
19
|
+
/** Line count of the full input. */
|
|
20
|
+
totalLines: number;
|
|
21
|
+
/** 1-based line number of the first line included in `text`. */
|
|
22
|
+
startLine: number;
|
|
23
|
+
/** Only the tail of the final line fit (that single line exceeds maxBytes). */
|
|
24
|
+
lastLinePartial: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** UTF-8 byte length without allocating an encoded copy per call site. */
|
|
27
|
+
export declare function utf8Len(s: string): number;
|
|
28
|
+
/**
|
|
29
|
+
* Cut `s` to at most `maxBytes` UTF-8 bytes, keeping the END and never
|
|
30
|
+
* splitting a multibyte character (walks forward off continuation bytes).
|
|
31
|
+
*/
|
|
32
|
+
export declare function cutToBytesFromEnd(s: string, maxBytes: number): string;
|
|
33
|
+
export declare function truncateTail(input: string, maxLines?: number, maxBytes?: number): TailTruncation;
|
|
34
|
+
/**
|
|
35
|
+
* The footnote appended to truncated tool output. Always names the next step
|
|
36
|
+
* (the full-output spill path) so the model can read/grep the rest instead of
|
|
37
|
+
* re-running the command.
|
|
38
|
+
*/
|
|
39
|
+
export declare function truncationFootnote(t: TailTruncation, fullOutputPath: string): string;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tail truncation for command output (pi contract, 2026-08-21 dossier):
|
|
3
|
+
* two independent limits — max lines and max bytes — whichever is hit first.
|
|
4
|
+
* Never returns a partial line, with ONE explicit exception: when the final
|
|
5
|
+
* line alone exceeds the byte limit, its tail is returned and flagged
|
|
6
|
+
* `lastLinePartial`. Byte cuts land on UTF-8 boundaries so multibyte
|
|
7
|
+
* characters are never split.
|
|
8
|
+
*
|
|
9
|
+
* Tail (not head) because for command output the errors and final results
|
|
10
|
+
* live at the end.
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_MAX_OUTPUT_LINES = 2000;
|
|
13
|
+
export const DEFAULT_MAX_OUTPUT_BYTES = 50 * 1024;
|
|
14
|
+
/** UTF-8 byte length without allocating an encoded copy per call site. */
|
|
15
|
+
export function utf8Len(s) {
|
|
16
|
+
return Buffer.byteLength(s, 'utf8');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Cut `s` to at most `maxBytes` UTF-8 bytes, keeping the END and never
|
|
20
|
+
* splitting a multibyte character (walks forward off continuation bytes).
|
|
21
|
+
*/
|
|
22
|
+
export function cutToBytesFromEnd(s, maxBytes) {
|
|
23
|
+
const buf = Buffer.from(s, 'utf8');
|
|
24
|
+
if (buf.length <= maxBytes)
|
|
25
|
+
return s;
|
|
26
|
+
let start = buf.length - maxBytes;
|
|
27
|
+
// 0b10xxxxxx marks a UTF-8 continuation byte — move forward to a character start.
|
|
28
|
+
while (start < buf.length && (buf[start] & 0xc0) === 0x80)
|
|
29
|
+
start += 1;
|
|
30
|
+
return buf.toString('utf8', start);
|
|
31
|
+
}
|
|
32
|
+
export function truncateTail(input, maxLines = DEFAULT_MAX_OUTPUT_LINES, maxBytes = DEFAULT_MAX_OUTPUT_BYTES) {
|
|
33
|
+
const lines = input.split('\n');
|
|
34
|
+
const totalLines = lines.length;
|
|
35
|
+
// Pass 1: line limit.
|
|
36
|
+
let kept = lines.length <= maxLines ? lines : lines.slice(lines.length - maxLines);
|
|
37
|
+
let truncatedBy = kept.length < totalLines ? 'lines' : null;
|
|
38
|
+
// Pass 2: byte limit over the kept tail — drop whole lines from the front.
|
|
39
|
+
let bytes = kept.reduce((n, l) => n + utf8Len(l), 0) + Math.max(0, kept.length - 1);
|
|
40
|
+
if (bytes > maxBytes) {
|
|
41
|
+
truncatedBy = 'bytes';
|
|
42
|
+
while (kept.length > 1 && bytes > maxBytes) {
|
|
43
|
+
const dropped = kept.shift();
|
|
44
|
+
bytes -= utf8Len(dropped) + 1; // +1 for the newline joining it
|
|
45
|
+
}
|
|
46
|
+
if (kept.length === 1 && utf8Len(kept[0]) > maxBytes) {
|
|
47
|
+
// The single remaining (final) line alone exceeds the limit — the one
|
|
48
|
+
// sanctioned partial-line case.
|
|
49
|
+
return {
|
|
50
|
+
text: cutToBytesFromEnd(kept[0], maxBytes),
|
|
51
|
+
truncated: true,
|
|
52
|
+
truncatedBy: 'bytes',
|
|
53
|
+
totalLines,
|
|
54
|
+
startLine: totalLines,
|
|
55
|
+
lastLinePartial: true,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
text: kept.join('\n'),
|
|
61
|
+
truncated: truncatedBy !== null,
|
|
62
|
+
truncatedBy,
|
|
63
|
+
totalLines,
|
|
64
|
+
startLine: totalLines - kept.length + 1,
|
|
65
|
+
lastLinePartial: false,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The footnote appended to truncated tool output. Always names the next step
|
|
70
|
+
* (the full-output spill path) so the model can read/grep the rest instead of
|
|
71
|
+
* re-running the command.
|
|
72
|
+
*/
|
|
73
|
+
export function truncationFootnote(t, fullOutputPath) {
|
|
74
|
+
const kb = (DEFAULT_MAX_OUTPUT_BYTES / 1024).toFixed(0);
|
|
75
|
+
if (t.lastLinePartial) {
|
|
76
|
+
return `[Showing last ${kb}KB of line ${t.totalLines}. Full output: ${fullOutputPath}]`;
|
|
77
|
+
}
|
|
78
|
+
const range = `lines ${t.startLine}-${t.totalLines} of ${t.totalLines}`;
|
|
79
|
+
return t.truncatedBy === 'bytes'
|
|
80
|
+
? `[Showing ${range} (${kb}KB limit). Full output: ${fullOutputPath}]`
|
|
81
|
+
: `[Showing ${range}. Full output: ${fullOutputPath}]`;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=truncate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../../src/coding/truncate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ClientTool } from '../core/types.js';
|
|
2
|
+
import type { PermissionGate } from './permissions.js';
|
|
3
|
+
import type { ReadFileState } from './readState.js';
|
|
4
|
+
/**
|
|
5
|
+
* The `write_file` tool: create a new file or fully overwrite an existing one.
|
|
6
|
+
* Jailed to the workspace (same guard as the fs read tools). Overwriting an
|
|
7
|
+
* EXISTING file requires it to have been read this session and unchanged since
|
|
8
|
+
* (readFileState) — writing blind over content the model never saw is refused.
|
|
9
|
+
*/
|
|
10
|
+
export declare function createWriteFileTool(opts: {
|
|
11
|
+
root: string;
|
|
12
|
+
gate: PermissionGate;
|
|
13
|
+
readState: ReadFileState;
|
|
14
|
+
}): ClientTool;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { GuardError, resolveForWrite, sanitizeFsError } from '../fs/workspaceGuard.js';
|
|
4
|
+
/**
|
|
5
|
+
* The `write_file` tool: create a new file or fully overwrite an existing one.
|
|
6
|
+
* Jailed to the workspace (same guard as the fs read tools). Overwriting an
|
|
7
|
+
* EXISTING file requires it to have been read this session and unchanged since
|
|
8
|
+
* (readFileState) — writing blind over content the model never saw is refused.
|
|
9
|
+
*/
|
|
10
|
+
export function createWriteFileTool(opts) {
|
|
11
|
+
return {
|
|
12
|
+
name: 'write_file',
|
|
13
|
+
readOnly: false,
|
|
14
|
+
description: 'Write content to a file inside the workspace, creating it (and parent directories) if needed ' +
|
|
15
|
+
'or fully overwriting it. Use write_file only for new files or complete rewrites; use edit_file ' +
|
|
16
|
+
'for targeted changes. Overwriting an existing file requires reading it first in this session.',
|
|
17
|
+
parameters: {
|
|
18
|
+
type: 'object',
|
|
19
|
+
properties: {
|
|
20
|
+
path: { type: 'string', description: 'File path relative to the workspace root.' },
|
|
21
|
+
content: { type: 'string', description: 'Full content to write (UTF-8).' },
|
|
22
|
+
},
|
|
23
|
+
required: ['path', 'content'],
|
|
24
|
+
},
|
|
25
|
+
async execute(args) {
|
|
26
|
+
if (typeof args.path !== 'string' || !args.path.trim()) {
|
|
27
|
+
return { error: 'Missing required "path" argument.' };
|
|
28
|
+
}
|
|
29
|
+
if (typeof args.content !== 'string') {
|
|
30
|
+
return { error: 'Missing required "content" argument (must be a string).' };
|
|
31
|
+
}
|
|
32
|
+
const content = args.content;
|
|
33
|
+
try {
|
|
34
|
+
const file = await resolveForWrite(opts.root, args.path);
|
|
35
|
+
let exists = false;
|
|
36
|
+
try {
|
|
37
|
+
const stat = await fs.stat(file);
|
|
38
|
+
if (stat.isDirectory())
|
|
39
|
+
return { error: `Is a directory, not a file: ${args.path}` };
|
|
40
|
+
if (!stat.isFile())
|
|
41
|
+
return { error: `Not a regular file: ${args.path}` };
|
|
42
|
+
exists = true;
|
|
43
|
+
if (!opts.readState.has(file)) {
|
|
44
|
+
return {
|
|
45
|
+
error: `File already exists and has not been read yet: ${args.path}. Read it first before overwriting it (or use edit_file for a targeted change).`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (opts.readState.isStale(file, stat.mtimeMs)) {
|
|
49
|
+
return {
|
|
50
|
+
error: `File has been modified since read, either by the user or by another tool: ${args.path}. Read it again before overwriting it.`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
if (err.code !== 'ENOENT')
|
|
56
|
+
throw err;
|
|
57
|
+
}
|
|
58
|
+
const preview = content.length > 2000 ? content.slice(0, 2000) + '\n… (truncated preview)' : content;
|
|
59
|
+
const verdict = await opts.gate.check({ kind: 'write', path: file, preview });
|
|
60
|
+
if (!verdict.ok)
|
|
61
|
+
return { error: verdict.message };
|
|
62
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
63
|
+
await fs.writeFile(file, content, 'utf8');
|
|
64
|
+
const stat = await fs.stat(file);
|
|
65
|
+
opts.readState.record(file, stat.mtimeMs); // follow-up edits pass read-before-mutate
|
|
66
|
+
const bytes = Buffer.byteLength(content, 'utf8');
|
|
67
|
+
return {
|
|
68
|
+
output: exists
|
|
69
|
+
? `Successfully overwrote ${args.path} (${bytes} bytes).`
|
|
70
|
+
: `Successfully created ${args.path} (${bytes} bytes).`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (err instanceof GuardError)
|
|
75
|
+
return { error: err.message };
|
|
76
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
77
|
+
return { error: `write_file failed: ${sanitizeFsError(message, opts.root)}` };
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=writeTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writeTool.js","sourceRoot":"","sources":["../../../src/coding/writeTool.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,14 @@ export interface ExecOptions {
|
|
|
13
13
|
jsonl?: boolean;
|
|
14
14
|
outputLastMessage?: string;
|
|
15
15
|
maxCredits?: number;
|
|
16
|
+
/** Enable file writes (write_file/edit_file) — headless is fail-closed without it. */
|
|
17
|
+
allowWrite?: boolean;
|
|
18
|
+
/** Enable shell commands (bash) — headless is fail-closed without it. */
|
|
19
|
+
allowBash?: boolean;
|
|
20
|
+
/** Enable everything without asking (implies --allow-write and --allow-bash). */
|
|
21
|
+
yolo?: boolean;
|
|
22
|
+
/** Skip AGENTS.md/CLAUDE.md discovery. */
|
|
23
|
+
noProjectContext?: boolean;
|
|
16
24
|
}
|
|
17
25
|
/** Injectable dependencies (production defaults; overridden in tests). */
|
|
18
26
|
export interface ExecDeps {
|
|
@@ -10,6 +10,7 @@ import { getDefaultChatModel, resolveChatModel, modelSupportsTools } from '../tu
|
|
|
10
10
|
import { UsageError, resolvePromptText, injectFiles, loadOutputSchema } from '../exec/input.js';
|
|
11
11
|
import { ExecOutput } from '../exec/output.js';
|
|
12
12
|
import { createFsTools, workspaceRoot } from '../fs/index.js';
|
|
13
|
+
import { BackgroundBashTasks, CodingPermissionGate, ReadFileState, createCodingTools, buildCodingSystemMessage, loadProjectContext, } from '../coding/index.js';
|
|
13
14
|
import { createWebTools } from '../web/index.js';
|
|
14
15
|
import { resolveImageRef, ImageRefError } from '../util/imageRef.js';
|
|
15
16
|
import { AiApiClient } from '../media/aiApiClient.js';
|
|
@@ -23,7 +24,13 @@ import { flushTelemetry, initTelemetryForCli, track } from '../telemetry/telemet
|
|
|
23
24
|
*/
|
|
24
25
|
export async function runExec(positional, opts, deps = {}) {
|
|
25
26
|
const sinks = deps.sinks ?? {
|
|
26
|
-
|
|
27
|
+
// Drain-aware stdout (pi A3): when the pipe is full, the returned promise
|
|
28
|
+
// backpressures the model stream instead of buffering it in memory.
|
|
29
|
+
out: (s) => {
|
|
30
|
+
if (process.stdout.write(s))
|
|
31
|
+
return;
|
|
32
|
+
return new Promise((resolve) => process.stdout.once('drain', resolve));
|
|
33
|
+
},
|
|
27
34
|
err: (s) => process.stderr.write(s),
|
|
28
35
|
};
|
|
29
36
|
// Unattended surface: an overridden base URL must be visible in the logs even when
|
|
@@ -104,10 +111,25 @@ export async function runExec(positional, opts, deps = {}) {
|
|
|
104
111
|
// fs read tools + budget-gated media generation (spec 2026-07-19-mcp-media-tools-design.md).
|
|
105
112
|
const registry = new ToolRegistry();
|
|
106
113
|
let media;
|
|
114
|
+
let codingSystem;
|
|
115
|
+
let backgroundTasks;
|
|
107
116
|
if (modelSupportsTools(model)) {
|
|
108
117
|
const root = await workspaceRoot(deps.workspaceRootDir);
|
|
109
|
-
|
|
118
|
+
// Coding tools: headless is fail-closed — writes/bash are denied with a message
|
|
119
|
+
// naming the enable flag unless the user opted in (--allow-write/--allow-bash/--yolo).
|
|
120
|
+
const readState = new ReadFileState();
|
|
121
|
+
const gate = new CodingPermissionGate({
|
|
122
|
+
root,
|
|
123
|
+
mode: opts.yolo ? 'yolo' : 'default',
|
|
124
|
+
headlessAllow: { bash: opts.allowBash === true, write: opts.allowWrite === true },
|
|
125
|
+
});
|
|
126
|
+
for (const t of createFsTools(root, { readState }))
|
|
127
|
+
registry.register(t);
|
|
128
|
+
backgroundTasks = new BackgroundBashTasks();
|
|
129
|
+
for (const t of createCodingTools({ root, gate, readState, background: backgroundTasks }))
|
|
110
130
|
registry.register(t);
|
|
131
|
+
const contextFiles = opts.noProjectContext ? [] : await loadProjectContext(root);
|
|
132
|
+
codingSystem = buildCodingSystemMessage({ workspaceRoot: root, contextFiles });
|
|
111
133
|
for (const t of createWebTools({ baseUrl: apiBaseUrl(), getToken: () => token }))
|
|
112
134
|
registry.register(t);
|
|
113
135
|
media =
|
|
@@ -126,11 +148,17 @@ export async function runExec(positional, opts, deps = {}) {
|
|
|
126
148
|
output.start();
|
|
127
149
|
let result;
|
|
128
150
|
try {
|
|
129
|
-
result = await runChatTurn({
|
|
151
|
+
result = await runChatTurn({
|
|
152
|
+
backend,
|
|
153
|
+
model,
|
|
154
|
+
prompt: promptContent,
|
|
155
|
+
system: [codingSystem, opts.system].filter(Boolean).join('\n\n'),
|
|
156
|
+
outputSchema,
|
|
157
|
+
registry,
|
|
158
|
+
}, (event) => {
|
|
130
159
|
switch (event.type) {
|
|
131
160
|
case 'assistant_delta':
|
|
132
|
-
output.delta(event.text);
|
|
133
|
-
break;
|
|
161
|
+
return output.delta(event.text);
|
|
134
162
|
case 'usage':
|
|
135
163
|
output.usageEvent(event.promptTokens, event.completionTokens);
|
|
136
164
|
break;
|
|
@@ -151,6 +179,7 @@ export async function runExec(positional, opts, deps = {}) {
|
|
|
151
179
|
for (const r of await media.drain())
|
|
152
180
|
output.mediaResult(r);
|
|
153
181
|
}
|
|
182
|
+
killBackgroundTasks(backgroundTasks, sinks);
|
|
154
183
|
output.finishError(err instanceof Error ? err.message : String(err));
|
|
155
184
|
return 1;
|
|
156
185
|
}
|
|
@@ -166,10 +195,21 @@ export async function runExec(positional, opts, deps = {}) {
|
|
|
166
195
|
for (const r of await media.drain())
|
|
167
196
|
output.mediaResult(r);
|
|
168
197
|
}
|
|
198
|
+
killBackgroundTasks(backgroundTasks, sinks);
|
|
169
199
|
output.finishResult(result.structured);
|
|
170
200
|
await flushTelemetry();
|
|
171
201
|
return 0;
|
|
172
202
|
}
|
|
203
|
+
/** exec is one turn: any background bash task still running dies with the process. */
|
|
204
|
+
function killBackgroundTasks(tasks, sinks) {
|
|
205
|
+
if (!tasks)
|
|
206
|
+
return;
|
|
207
|
+
const running = tasks.running();
|
|
208
|
+
if (running.length > 0) {
|
|
209
|
+
sinks.err(`Stopping ${running.length} background task${running.length === 1 ? '' : 's'} (exec is single-turn).\n`);
|
|
210
|
+
}
|
|
211
|
+
tasks.killAll();
|
|
212
|
+
}
|
|
173
213
|
/** Read all of stdin as UTF-8. */
|
|
174
214
|
async function readStdinAll() {
|
|
175
215
|
const chunks = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execCommand.js","sourceRoot":"","sources":["../../../src/commands/execCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAuB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC7F,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAqC,MAAM,mBAAmB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,eAAe,EAAkB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"execCommand.js","sourceRoot":"","sources":["../../../src/commands/execCommand.ts"],"names":[],"mappings":"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"}
|
package/dist/src/core/catalog.js
CHANGED
|
@@ -24,6 +24,7 @@ export function parseCatalog(raw) {
|
|
|
24
24
|
label: typeof m.label === 'string' && m.label ? m.label : m.id.trim(),
|
|
25
25
|
toolUse: m.tool_use === true || m.toolUse === true,
|
|
26
26
|
...(structuredOutputOf(m) ? { structuredOutput: structuredOutputOf(m) } : {}),
|
|
27
|
+
...(contextWindowOf(m) ? { contextWindow: contextWindowOf(m) } : {}),
|
|
27
28
|
}))
|
|
28
29
|
: [];
|
|
29
30
|
if (models.length === 0)
|
|
@@ -35,6 +36,10 @@ export function parseCatalog(raw) {
|
|
|
35
36
|
return { chat: { default: def, models }, media: { disabled } };
|
|
36
37
|
}
|
|
37
38
|
/** Optional catalog capability (snake_case from the server, camelCase from our own cache). */
|
|
39
|
+
function contextWindowOf(m) {
|
|
40
|
+
const v = m?.context_window ?? m?.contextWindow;
|
|
41
|
+
return typeof v === 'number' && v > 0 ? v : undefined;
|
|
42
|
+
}
|
|
38
43
|
function structuredOutputOf(m) {
|
|
39
44
|
const v = m?.structured_output ?? m?.structuredOutput;
|
|
40
45
|
return v === 'json_schema' || v === 'json_object' ? v : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../src/core/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAkB,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAoB1D;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACzD,MAAM,CAAC,GAAG,GAA0B,CAAC;IACrC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC;QAC1C,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM;aACV,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;aAC5D,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;YAChB,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;YACf,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;YACrE,OAAO,EAAE,CAAC,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI;YAClD,GAAG,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../../src/core/catalog.ts"],"names":[],"mappings":"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"}
|