@glbgpt/cli 0.1.4 → 0.2.1
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 +82 -40
- 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 +13 -0
- package/dist/src/commands/execCommand.js +73 -6
- package/dist/src/commands/execCommand.js.map +1 -1
- package/dist/src/commands/updateCommand.d.ts +7 -0
- package/dist/src/commands/updateCommand.js +11 -0
- package/dist/src/commands/updateCommand.js.map +1 -0
- package/dist/src/core/catalog.d.ts +5 -0
- package/dist/src/core/catalog.js +31 -1
- 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/core/updateCheck.d.ts +35 -0
- package/dist/src/core/updateCheck.js +71 -2
- package/dist/src/core/updateCheck.js.map +1 -1
- package/dist/src/core/updateRunner.d.ts +7 -0
- package/dist/src/core/updateRunner.js +26 -0
- package/dist/src/core/updateRunner.js.map +1 -0
- 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 +44 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/server.js +17 -1
- package/dist/src/mcp/server.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/UpdatePrompt.d.ts +17 -0
- package/dist/src/tui/UpdatePrompt.js +42 -0
- package/dist/src/tui/UpdatePrompt.js.map +1 -0
- 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 +107 -22
- 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":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAIvF;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAInC;IACC,OAAO;QACL,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,KAAK;QACf,WAAW,EACT,+FAA+F;YAC/F,iGAAiG;YACjG,+FAA+F;QACjG,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,2CAA2C,EAAE;gBAClF,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,gCAAgC,EAAE;aAC3E;YACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;SAC9B;QACD,KAAK,CAAC,OAAO,CAAC,IAAI;YAChB,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACvD,OAAO,EAAE,KAAK,EAAE,mCAAmC,EAAE,CAAC;YACxD,CAAC;YACD,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACrC,OAAO,EAAE,KAAK,EAAE,yDAAyD,EAAE,CAAC;YAC9E,CAAC;YACD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;gBAEzD,IAAI,MAAM,GAAG,KAAK,CAAC;gBACnB,IAAI,CAAC;oBACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACjC,IAAI,IAAI,CAAC,WAAW,EAAE;wBAAE,OAAO,EAAE,KAAK,EAAE,+BAA+B,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;oBACrF,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;wBAAE,OAAO,EAAE,KAAK,EAAE,uBAAuB,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;oBACzE,MAAM,GAAG,IAAI,CAAC;oBACd,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;wBAC9B,OAAO;4BACL,KAAK,EAAE,kDAAkD,IAAI,CAAC,IAAI,iFAAiF;yBACpJ,CAAC;oBACJ,CAAC;oBACD,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;wBAC/C,OAAO;4BACL,KAAK,EAAE,6EAA6E,IAAI,CAAC,IAAI,wCAAwC;yBACtI,CAAC;oBACJ,CAAC;gBACH,CAAC;gBAAC,OAAO,GAAY,EAAE,CAAC;oBACtB,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;wBAAE,MAAM,GAAG,CAAC;gBAClE,CAAC;gBAED,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,yBAAyB,CAAC,CAAC,CAAC,OAAO,CAAC;gBACrG,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC9E,IAAI,CAAC,OAAO,CAAC,EAAE;oBAAE,OAAO,EAAE,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC;gBAEnD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACxD,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;gBAC1C,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,0CAA0C;gBAErF,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACjD,OAAO;oBACL,MAAM,EAAE,MAAM;wBACZ,CAAC,CAAC,0BAA0B,IAAI,CAAC,IAAI,KAAK,KAAK,UAAU;wBACzD,CAAC,CAAC,wBAAwB,IAAI,CAAC,IAAI,KAAK,KAAK,UAAU;iBAC1D,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,UAAU;oBAAE,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC7D,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACjE,OAAO,EAAE,KAAK,EAAE,sBAAsB,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YAChF,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -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 {
|
|
@@ -25,6 +33,11 @@ export interface ExecDeps {
|
|
|
25
33
|
readImage?: (p: string) => Promise<Buffer>;
|
|
26
34
|
writeFile?: (p: string, data: string) => Promise<void>;
|
|
27
35
|
resolveToken?: () => Promise<string | null>;
|
|
36
|
+
/** Update-notice source (tests). Defaults to the real cache-only check on the real CLI entry. */
|
|
37
|
+
checkUpdate?: () => Promise<{
|
|
38
|
+
latest: string;
|
|
39
|
+
command: string;
|
|
40
|
+
} | null>;
|
|
28
41
|
/** Override the workspace root the fs tools are jailed to (tests; default `process.cwd()`). */
|
|
29
42
|
workspaceRootDir?: string;
|
|
30
43
|
/** Injectable media surface (tests). */
|
|
@@ -5,17 +5,20 @@ import { runChatTurn } from '../core/runChat.js';
|
|
|
5
5
|
import { ToolRegistry } from '../core/toolRegistry.js';
|
|
6
6
|
import { resolveToken as defaultResolveToken } from '../auth/token.js';
|
|
7
7
|
import { apiBaseUrl, baseUrlOverrideWarnings } from '../config/env.js';
|
|
8
|
-
import { ensureCatalog } from '../core/catalog.js';
|
|
8
|
+
import { ensureCatalog, getCatalogCliVersions } from '../core/catalog.js';
|
|
9
9
|
import { getDefaultChatModel, resolveChatModel, modelSupportsTools } from '../tui/models.js';
|
|
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';
|
|
16
17
|
import { SessionBudget, resolveMaxCredits } from '../media/budget.js';
|
|
17
18
|
import { createExecMedia } from '../exec/media.js';
|
|
18
19
|
import { flushTelemetry, initTelemetryForCli, track } from '../telemetry/telemetry.js';
|
|
20
|
+
import { compareVersions, effectiveUpdateNotice } from '../core/updateCheck.js';
|
|
21
|
+
import { VERSION } from '../version.js';
|
|
19
22
|
/**
|
|
20
23
|
* Run one non-interactive model call and render it per the chosen output mode.
|
|
21
24
|
* Returns the process exit code (0 success; 1 usage/auth/turn failure) rather than exiting,
|
|
@@ -23,7 +26,13 @@ import { flushTelemetry, initTelemetryForCli, track } from '../telemetry/telemet
|
|
|
23
26
|
*/
|
|
24
27
|
export async function runExec(positional, opts, deps = {}) {
|
|
25
28
|
const sinks = deps.sinks ?? {
|
|
26
|
-
|
|
29
|
+
// Drain-aware stdout (pi A3): when the pipe is full, the returned promise
|
|
30
|
+
// backpressures the model stream instead of buffering it in memory.
|
|
31
|
+
out: (s) => {
|
|
32
|
+
if (process.stdout.write(s))
|
|
33
|
+
return;
|
|
34
|
+
return new Promise((resolve) => process.stdout.once('drain', resolve));
|
|
35
|
+
},
|
|
27
36
|
err: (s) => process.stderr.write(s),
|
|
28
37
|
};
|
|
29
38
|
// Unattended surface: an overridden base URL must be visible in the logs even when
|
|
@@ -40,6 +49,31 @@ export async function runExec(positional, opts, deps = {}) {
|
|
|
40
49
|
// be rejected client-side just because this machine hasn't fetched the list yet).
|
|
41
50
|
const token = await (deps.resolveToken ?? defaultResolveToken)();
|
|
42
51
|
const { refreshed } = await ensureCatalog({ baseUrl: apiBaseUrl(), token });
|
|
52
|
+
// Advise-only update lines, stderr only: the payload on stdout stays machine-clean, and
|
|
53
|
+
// agent hosts (Claude Code & co. running `glbgpt exec`) read stderr and relay it to
|
|
54
|
+
// their user — the TUI-only notice never reached this surface at all. Local-only reads
|
|
55
|
+
// (registry cache + the catalog's cli block — hence after ensureCatalog); deliberately
|
|
56
|
+
// ignores "Skip until next version", which is an interactive-TUI choice. Defaulted only
|
|
57
|
+
// for the real CLI entry: tests inject sinks, and opt in via deps.checkUpdate.
|
|
58
|
+
const checkUpdate = deps.checkUpdate ??
|
|
59
|
+
(deps.sinks === undefined
|
|
60
|
+
? async () => (await effectiveUpdateNotice(getCatalogCliVersions())).notice
|
|
61
|
+
: undefined);
|
|
62
|
+
try {
|
|
63
|
+
const notice = await checkUpdate?.();
|
|
64
|
+
if (notice) {
|
|
65
|
+
sinks.err(`Update available: glbgpt ${VERSION} → ${notice.latest} — run: ${notice.command}\n`);
|
|
66
|
+
}
|
|
67
|
+
if (deps.sinks === undefined) {
|
|
68
|
+
const min = getCatalogCliVersions().minVersion;
|
|
69
|
+
if (min && compareVersions(min, VERSION) > 0) {
|
|
70
|
+
sinks.err(`WARNING: glbgpt ${VERSION} is below the minimum supported version (${min}) — run: glbgpt update\n`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Advisory only — never let the update check break an exec run.
|
|
76
|
+
}
|
|
43
77
|
let model;
|
|
44
78
|
try {
|
|
45
79
|
model = opts.model?.trim() ? resolveChatModel(opts.model.trim()) : getDefaultChatModel();
|
|
@@ -104,10 +138,25 @@ export async function runExec(positional, opts, deps = {}) {
|
|
|
104
138
|
// fs read tools + budget-gated media generation (spec 2026-07-19-mcp-media-tools-design.md).
|
|
105
139
|
const registry = new ToolRegistry();
|
|
106
140
|
let media;
|
|
141
|
+
let codingSystem;
|
|
142
|
+
let backgroundTasks;
|
|
107
143
|
if (modelSupportsTools(model)) {
|
|
108
144
|
const root = await workspaceRoot(deps.workspaceRootDir);
|
|
109
|
-
|
|
145
|
+
// Coding tools: headless is fail-closed — writes/bash are denied with a message
|
|
146
|
+
// naming the enable flag unless the user opted in (--allow-write/--allow-bash/--yolo).
|
|
147
|
+
const readState = new ReadFileState();
|
|
148
|
+
const gate = new CodingPermissionGate({
|
|
149
|
+
root,
|
|
150
|
+
mode: opts.yolo ? 'yolo' : 'default',
|
|
151
|
+
headlessAllow: { bash: opts.allowBash === true, write: opts.allowWrite === true },
|
|
152
|
+
});
|
|
153
|
+
for (const t of createFsTools(root, { readState }))
|
|
154
|
+
registry.register(t);
|
|
155
|
+
backgroundTasks = new BackgroundBashTasks();
|
|
156
|
+
for (const t of createCodingTools({ root, gate, readState, background: backgroundTasks }))
|
|
110
157
|
registry.register(t);
|
|
158
|
+
const contextFiles = opts.noProjectContext ? [] : await loadProjectContext(root);
|
|
159
|
+
codingSystem = buildCodingSystemMessage({ workspaceRoot: root, contextFiles });
|
|
111
160
|
for (const t of createWebTools({ baseUrl: apiBaseUrl(), getToken: () => token }))
|
|
112
161
|
registry.register(t);
|
|
113
162
|
media =
|
|
@@ -126,11 +175,17 @@ export async function runExec(positional, opts, deps = {}) {
|
|
|
126
175
|
output.start();
|
|
127
176
|
let result;
|
|
128
177
|
try {
|
|
129
|
-
result = await runChatTurn({
|
|
178
|
+
result = await runChatTurn({
|
|
179
|
+
backend,
|
|
180
|
+
model,
|
|
181
|
+
prompt: promptContent,
|
|
182
|
+
system: [codingSystem, opts.system].filter(Boolean).join('\n\n'),
|
|
183
|
+
outputSchema,
|
|
184
|
+
registry,
|
|
185
|
+
}, (event) => {
|
|
130
186
|
switch (event.type) {
|
|
131
187
|
case 'assistant_delta':
|
|
132
|
-
output.delta(event.text);
|
|
133
|
-
break;
|
|
188
|
+
return output.delta(event.text);
|
|
134
189
|
case 'usage':
|
|
135
190
|
output.usageEvent(event.promptTokens, event.completionTokens);
|
|
136
191
|
break;
|
|
@@ -151,6 +206,7 @@ export async function runExec(positional, opts, deps = {}) {
|
|
|
151
206
|
for (const r of await media.drain())
|
|
152
207
|
output.mediaResult(r);
|
|
153
208
|
}
|
|
209
|
+
killBackgroundTasks(backgroundTasks, sinks);
|
|
154
210
|
output.finishError(err instanceof Error ? err.message : String(err));
|
|
155
211
|
return 1;
|
|
156
212
|
}
|
|
@@ -166,10 +222,21 @@ export async function runExec(positional, opts, deps = {}) {
|
|
|
166
222
|
for (const r of await media.drain())
|
|
167
223
|
output.mediaResult(r);
|
|
168
224
|
}
|
|
225
|
+
killBackgroundTasks(backgroundTasks, sinks);
|
|
169
226
|
output.finishResult(result.structured);
|
|
170
227
|
await flushTelemetry();
|
|
171
228
|
return 0;
|
|
172
229
|
}
|
|
230
|
+
/** exec is one turn: any background bash task still running dies with the process. */
|
|
231
|
+
function killBackgroundTasks(tasks, sinks) {
|
|
232
|
+
if (!tasks)
|
|
233
|
+
return;
|
|
234
|
+
const running = tasks.running();
|
|
235
|
+
if (running.length > 0) {
|
|
236
|
+
sinks.err(`Stopping ${running.length} background task${running.length === 1 ? '' : 's'} (exec is single-turn).\n`);
|
|
237
|
+
}
|
|
238
|
+
tasks.killAll();
|
|
239
|
+
}
|
|
173
240
|
/** Read all of stdin as UTF-8. */
|
|
174
241
|
async function readStdinAll() {
|
|
175
242
|
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;
|
|
1
|
+
{"version":3,"file":"execCommand.js","sourceRoot":"","sources":["../../../src/commands/execCommand.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `glbgpt update`: run the channel-appropriate npm upgrade on the user's behalf.
|
|
3
|
+
* No pre-check against the registry — npm itself is the authority on whether a newer
|
|
4
|
+
* version exists (installing the same version again is a cheap no-op), which also makes
|
|
5
|
+
* this the escape hatch when the 20h notice cache is stale.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runUpdate(): Promise<number>;
|