skyloom 1.16.1 → 1.17.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.
Files changed (92) hide show
  1. package/README.md +15 -3
  2. package/dist/cli/loom_chat.d.ts.map +1 -1
  3. package/dist/cli/loom_chat.js +17 -0
  4. package/dist/cli/loom_chat.js.map +1 -1
  5. package/dist/cli/main.js +37 -1
  6. package/dist/cli/main.js.map +1 -1
  7. package/dist/core/agent.d.ts +2 -0
  8. package/dist/core/agent.d.ts.map +1 -1
  9. package/dist/core/agent.js +25 -4
  10. package/dist/core/agent.js.map +1 -1
  11. package/dist/core/bgproc.d.ts +59 -0
  12. package/dist/core/bgproc.d.ts.map +1 -0
  13. package/dist/core/bgproc.js +135 -0
  14. package/dist/core/bgproc.js.map +1 -0
  15. package/dist/core/commands.d.ts.map +1 -1
  16. package/dist/core/commands.js +20 -0
  17. package/dist/core/commands.js.map +1 -1
  18. package/dist/core/diagnostics.d.ts +39 -0
  19. package/dist/core/diagnostics.d.ts.map +1 -0
  20. package/dist/core/diagnostics.js +206 -0
  21. package/dist/core/diagnostics.js.map +1 -0
  22. package/dist/core/diff.d.ts +31 -0
  23. package/dist/core/diff.d.ts.map +1 -0
  24. package/dist/core/diff.js +82 -0
  25. package/dist/core/diff.js.map +1 -0
  26. package/dist/core/envcontext.d.ts +25 -0
  27. package/dist/core/envcontext.d.ts.map +1 -0
  28. package/dist/core/envcontext.js +112 -0
  29. package/dist/core/envcontext.js.map +1 -0
  30. package/dist/core/factory.d.ts +2 -0
  31. package/dist/core/factory.d.ts.map +1 -1
  32. package/dist/core/factory.js +35 -2
  33. package/dist/core/factory.js.map +1 -1
  34. package/dist/core/sandbox.d.ts +1 -0
  35. package/dist/core/sandbox.d.ts.map +1 -1
  36. package/dist/core/sandbox.js +1 -0
  37. package/dist/core/sandbox.js.map +1 -1
  38. package/dist/core/security.d.ts +22 -2
  39. package/dist/core/security.d.ts.map +1 -1
  40. package/dist/core/security.js +54 -24
  41. package/dist/core/security.js.map +1 -1
  42. package/dist/core/skill.d.ts +4 -0
  43. package/dist/core/skill.d.ts.map +1 -1
  44. package/dist/core/skill.js +1 -0
  45. package/dist/core/skill.js.map +1 -1
  46. package/dist/core/subagent.d.ts +75 -0
  47. package/dist/core/subagent.d.ts.map +1 -0
  48. package/dist/core/subagent.js +287 -0
  49. package/dist/core/subagent.js.map +1 -0
  50. package/dist/core/tool.d.ts +25 -1
  51. package/dist/core/tool.d.ts.map +1 -1
  52. package/dist/core/tool.js +113 -36
  53. package/dist/core/tool.js.map +1 -1
  54. package/dist/plugins/loader.d.ts +49 -8
  55. package/dist/plugins/loader.d.ts.map +1 -1
  56. package/dist/plugins/loader.js +129 -16
  57. package/dist/plugins/loader.js.map +1 -1
  58. package/dist/tools/builtin.d.ts.map +1 -1
  59. package/dist/tools/builtin.js +126 -13
  60. package/dist/tools/builtin.js.map +1 -1
  61. package/dist/tools/spawn.d.ts +23 -0
  62. package/dist/tools/spawn.d.ts.map +1 -0
  63. package/dist/tools/spawn.js +77 -0
  64. package/dist/tools/spawn.js.map +1 -0
  65. package/docs/OPTIMIZATION_PLAN.md +21 -4
  66. package/package.json +1 -1
  67. package/src/cli/loom_chat.ts +11 -0
  68. package/src/cli/main.ts +31 -1
  69. package/src/core/agent.ts +25 -4
  70. package/src/core/bgproc.ts +153 -0
  71. package/src/core/commands.ts +20 -0
  72. package/src/core/diagnostics.ts +178 -0
  73. package/src/core/diff.ts +98 -0
  74. package/src/core/envcontext.ts +79 -0
  75. package/src/core/factory.ts +31 -2
  76. package/src/core/sandbox.ts +1 -1
  77. package/src/core/security.ts +62 -21
  78. package/src/core/skill.ts +1 -1
  79. package/src/core/subagent.ts +272 -0
  80. package/src/core/tool.ts +119 -40
  81. package/src/plugins/loader.ts +145 -18
  82. package/src/tools/builtin.ts +115 -13
  83. package/src/tools/spawn.ts +92 -0
  84. package/tests/agent.test.ts +35 -2
  85. package/tests/bgproc.test.ts +65 -0
  86. package/tests/diagnostics.test.ts +86 -0
  87. package/tests/edit_diff.test.ts +102 -0
  88. package/tests/envcontext.test.ts +67 -0
  89. package/tests/plugins.test.ts +84 -0
  90. package/tests/security.test.ts +87 -0
  91. package/tests/subagent.test.ts +211 -0
  92. package/tests/tool.test.ts +116 -0
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Code diagnostics — the LSP capability that matters most to an agent: surface
3
+ * real type/lint errors (with line:col) so the model fixes root causes instead
4
+ * of guessing.
5
+ *
6
+ * Strategy, in order:
7
+ * 1. TS/JS → the TypeScript compiler API, resolved from the user's workspace
8
+ * node_modules (then sky's own). Real semantic diagnostics, no
9
+ * language server to install.
10
+ * 2. other → a configured external checker command (config.diagnostics map
11
+ * of `ext -> "cmd {file}"`), output parsed for `file:line:col msg`.
12
+ *
13
+ * This is intentionally not a full LSP client (hover/goto/rename); it delivers
14
+ * the diagnostics that close the agent's edit→verify loop on a per-file basis.
15
+ */
16
+ export type Severity = 'error' | 'warning' | 'info';
17
+ export interface Diagnostic {
18
+ line: number;
19
+ column: number;
20
+ severity: Severity;
21
+ message: string;
22
+ code?: string;
23
+ source?: string;
24
+ }
25
+ /** Semantic + syntactic diagnostics for one TS/JS file via the compiler API. */
26
+ export declare function getTypeScriptDiagnostics(file: string, cwd?: string): Diagnostic[] | {
27
+ unavailable: string;
28
+ };
29
+ /** Parse generic `path:line:col: message` style compiler/linter output. */
30
+ export declare function parseDiagnosticOutput(output: string, source: string): Diagnostic[];
31
+ /**
32
+ * Get diagnostics for a file. `config.diagnostics` is an optional map of
33
+ * `ext -> command` for non-TS languages (e.g. { py: "ruff check {file}" }).
34
+ */
35
+ export declare function getDiagnostics(file: string, config?: any, cwd?: string): Diagnostic[] | {
36
+ unavailable: string;
37
+ };
38
+ export declare function formatDiagnostics(file: string, diags: Diagnostic[]): string;
39
+ //# sourceMappingURL=diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../src/core/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AASH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA4BD,gFAAgF;AAChF,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAsB,GAAG,UAAU,EAAE,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAkD1H;AAED,2EAA2E;AAC3E,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,EAAE,CAelF;AAiBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,GAAE,MAAsB,GAAG,UAAU,EAAE,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAa9H;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,CAY3E"}
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ /**
3
+ * Code diagnostics — the LSP capability that matters most to an agent: surface
4
+ * real type/lint errors (with line:col) so the model fixes root causes instead
5
+ * of guessing.
6
+ *
7
+ * Strategy, in order:
8
+ * 1. TS/JS → the TypeScript compiler API, resolved from the user's workspace
9
+ * node_modules (then sky's own). Real semantic diagnostics, no
10
+ * language server to install.
11
+ * 2. other → a configured external checker command (config.diagnostics map
12
+ * of `ext -> "cmd {file}"`), output parsed for `file:line:col msg`.
13
+ *
14
+ * This is intentionally not a full LSP client (hover/goto/rename); it delivers
15
+ * the diagnostics that close the agent's edit→verify loop on a per-file basis.
16
+ */
17
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
18
+ if (k2 === undefined) k2 = k;
19
+ var desc = Object.getOwnPropertyDescriptor(m, k);
20
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
21
+ desc = { enumerable: true, get: function() { return m[k]; } };
22
+ }
23
+ Object.defineProperty(o, k2, desc);
24
+ }) : (function(o, m, k, k2) {
25
+ if (k2 === undefined) k2 = k;
26
+ o[k2] = m[k];
27
+ }));
28
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
29
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
30
+ }) : function(o, v) {
31
+ o["default"] = v;
32
+ });
33
+ var __importStar = (this && this.__importStar) || (function () {
34
+ var ownKeys = function(o) {
35
+ ownKeys = Object.getOwnPropertyNames || function (o) {
36
+ var ar = [];
37
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
38
+ return ar;
39
+ };
40
+ return ownKeys(o);
41
+ };
42
+ return function (mod) {
43
+ if (mod && mod.__esModule) return mod;
44
+ var result = {};
45
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
46
+ __setModuleDefault(result, mod);
47
+ return result;
48
+ };
49
+ })();
50
+ Object.defineProperty(exports, "__esModule", { value: true });
51
+ exports.getTypeScriptDiagnostics = getTypeScriptDiagnostics;
52
+ exports.parseDiagnosticOutput = parseDiagnosticOutput;
53
+ exports.getDiagnostics = getDiagnostics;
54
+ exports.formatDiagnostics = formatDiagnostics;
55
+ const fs = __importStar(require("fs"));
56
+ const path = __importStar(require("path"));
57
+ const child_process_1 = require("child_process");
58
+ const logger_1 = require("./logger");
59
+ const log = (0, logger_1.getLogger)('diagnostics');
60
+ const TS_EXTS = new Set(['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs']);
61
+ /** Resolve the TypeScript module the way an LSP would: workspace first. */
62
+ function loadTypescript(cwd) {
63
+ const bases = [cwd, process.cwd(), __dirname];
64
+ for (const base of bases) {
65
+ try {
66
+ const p = require.resolve('typescript', { paths: [base] });
67
+ return require(p);
68
+ }
69
+ catch { /* try next */ }
70
+ }
71
+ try {
72
+ return require('typescript');
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ }
78
+ function findNearest(file, name) {
79
+ let dir = path.dirname(path.resolve(file));
80
+ for (let i = 0; i < 40; i++) {
81
+ const candidate = path.join(dir, name);
82
+ if (fs.existsSync(candidate))
83
+ return candidate;
84
+ const parent = path.dirname(dir);
85
+ if (parent === dir)
86
+ break;
87
+ dir = parent;
88
+ }
89
+ return null;
90
+ }
91
+ /** Semantic + syntactic diagnostics for one TS/JS file via the compiler API. */
92
+ function getTypeScriptDiagnostics(file, cwd = process.cwd()) {
93
+ const ts = loadTypescript(cwd);
94
+ if (!ts)
95
+ return { unavailable: 'typescript not installed in workspace or sky — cannot type-check.' };
96
+ const abs = path.resolve(file);
97
+ let options = { allowJs: true, checkJs: false, noEmit: true, skipLibCheck: true };
98
+ let fileNames = [abs];
99
+ const tsconfig = findNearest(abs, 'tsconfig.json');
100
+ if (tsconfig) {
101
+ try {
102
+ const read = ts.readConfigFile(tsconfig, ts.sys.readFile);
103
+ const parsed = ts.parseJsonConfigFileContent(read.config || {}, ts.sys, path.dirname(tsconfig));
104
+ options = { ...parsed.options, noEmit: true };
105
+ // Keep the project's file set so cross-file types resolve, but ensure our
106
+ // target is included.
107
+ fileNames = parsed.fileNames.includes(abs) ? parsed.fileNames : [...parsed.fileNames, abs];
108
+ }
109
+ catch (e) {
110
+ log.warn('tsconfig_parse_failed', { tsconfig, error: String(e) });
111
+ }
112
+ }
113
+ let program;
114
+ try {
115
+ program = ts.createProgram(fileNames, options);
116
+ }
117
+ catch (e) {
118
+ return { unavailable: `failed to build TypeScript program: ${e}` };
119
+ }
120
+ const source = program.getSourceFile(abs);
121
+ if (!source)
122
+ return { unavailable: `file not part of the TypeScript program: ${abs}` };
123
+ const raw = [
124
+ ...program.getSyntacticDiagnostics(source),
125
+ ...program.getSemanticDiagnostics(source),
126
+ ];
127
+ const out = [];
128
+ for (const d of raw) {
129
+ const message = ts.flattenDiagnosticMessageText(d.messageText, '\n');
130
+ let line = 1, column = 1;
131
+ if (d.file && typeof d.start === 'number') {
132
+ const pos = d.file.getLineAndCharacterOfPosition(d.start);
133
+ line = pos.line + 1;
134
+ column = pos.character + 1;
135
+ }
136
+ const severity = d.category === 1 ? 'error' : d.category === 0 ? 'warning' : 'info';
137
+ out.push({ line, column, severity, message, code: d.code ? `TS${d.code}` : undefined, source: 'ts' });
138
+ }
139
+ out.sort((a, b) => a.line - b.line || a.column - b.column);
140
+ return out;
141
+ }
142
+ /** Parse generic `path:line:col: message` style compiler/linter output. */
143
+ function parseDiagnosticOutput(output, source) {
144
+ const out = [];
145
+ const re = /^(.*?):(\d+):(\d+):?\s*(error|warning|info)?:?\s*(.*)$/gim;
146
+ let m;
147
+ while ((m = re.exec(output)) !== null) {
148
+ const sev = (m[4] || 'error').toLowerCase();
149
+ out.push({
150
+ line: parseInt(m[2], 10) || 1,
151
+ column: parseInt(m[3], 10) || 1,
152
+ severity: sev === 'warning' || sev === 'info' ? sev : 'error',
153
+ message: (m[5] || '').trim(),
154
+ source,
155
+ });
156
+ }
157
+ return out;
158
+ }
159
+ /** Run a configured external checker for a non-TS file. */
160
+ function getExternalDiagnostics(file, command) {
161
+ const cmd = command.includes('{file}')
162
+ ? command.replace(/\{file\}/g, JSON.stringify(file))
163
+ : `${command} ${JSON.stringify(file)}`;
164
+ let output = '';
165
+ try {
166
+ output = (0, child_process_1.execSync)(cmd, { encoding: 'utf8', timeout: 60000, stdio: ['ignore', 'pipe', 'pipe'] });
167
+ }
168
+ catch (e) {
169
+ // Linters exit non-zero when they find problems — that's the normal path.
170
+ output = `${e.stdout || ''}\n${e.stderr || ''}`;
171
+ }
172
+ return parseDiagnosticOutput(output, command.split(/\s+/)[0]);
173
+ }
174
+ /**
175
+ * Get diagnostics for a file. `config.diagnostics` is an optional map of
176
+ * `ext -> command` for non-TS languages (e.g. { py: "ruff check {file}" }).
177
+ */
178
+ function getDiagnostics(file, config, cwd = process.cwd()) {
179
+ const abs = path.resolve(file);
180
+ if (!fs.existsSync(abs))
181
+ return { unavailable: `file not found: ${abs}` };
182
+ const ext = path.extname(abs).toLowerCase();
183
+ const map = (config?.diagnostics || {});
184
+ const extKey = ext.replace(/^\./, '');
185
+ // Explicit user config wins.
186
+ if (map[extKey])
187
+ return getExternalDiagnostics(abs, map[extKey]);
188
+ if (TS_EXTS.has(ext))
189
+ return getTypeScriptDiagnostics(abs, cwd);
190
+ return { unavailable: `no diagnostics provider for '${ext}'. Configure one in config.yaml diagnostics: { ${extKey || 'ext'}: "<checker> {file}" }` };
191
+ }
192
+ function formatDiagnostics(file, diags) {
193
+ if (diags.length === 0)
194
+ return `✓ ${file} — no diagnostics (clean).`;
195
+ const errs = diags.filter(d => d.severity === 'error').length;
196
+ const warns = diags.filter(d => d.severity === 'warning').length;
197
+ const head = `${file} — ${errs} error${errs !== 1 ? 's' : ''}, ${warns} warning${warns !== 1 ? 's' : ''}:`;
198
+ const lines = diags.slice(0, 100).map(d => {
199
+ const mark = d.severity === 'error' ? '✗' : d.severity === 'warning' ? '⚠' : 'ℹ';
200
+ const code = d.code ? ` ${d.code}` : '';
201
+ return ` ${mark} ${d.line}:${d.column}${code} — ${d.message.replace(/\n/g, ' ')}`;
202
+ });
203
+ const more = diags.length > 100 ? `\n …and ${diags.length - 100} more` : '';
204
+ return `${head}\n${lines.join('\n')}${more}`;
205
+ }
206
+ //# sourceMappingURL=diagnostics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diagnostics.js","sourceRoot":"","sources":["../../src/core/diagnostics.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;GAcG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+CH,4DAkDC;AAGD,sDAeC;AAqBD,wCAaC;AAED,8CAYC;AAjKD,uCAAyB;AACzB,2CAA6B;AAC7B,iDAAyC;AACzC,qCAAqC;AAErC,MAAM,GAAG,GAAG,IAAA,kBAAS,EAAC,aAAa,CAAC,CAAC;AAarC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAExF,2EAA2E;AAC3E,SAAS,cAAc,CAAC,GAAW;IACjC,MAAM,KAAK,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IAC9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC3D,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC,CAAC,cAAc,CAAC,CAAC;IAC5B,CAAC;IACD,IAAI,CAAC;QAAC,OAAO,OAAO,CAAC,YAAY,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;AAC9D,CAAC;AAED,SAAS,WAAW,CAAC,IAAY,EAAE,IAAY;IAC7C,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACvC,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,SAAS,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,MAAM,KAAK,GAAG;YAAE,MAAM;QAC1B,GAAG,GAAG,MAAM,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gFAAgF;AAChF,SAAgB,wBAAwB,CAAC,IAAY,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IAChF,MAAM,EAAE,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,WAAW,EAAE,mEAAmE,EAAE,CAAC;IAErG,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,OAAO,GAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IACvF,IAAI,SAAS,GAAa,CAAC,GAAG,CAAC,CAAC;IAEhC,MAAM,QAAQ,GAAG,WAAW,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IACnD,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,EAAE,CAAC,cAAc,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC1D,MAAM,MAAM,GAAG,EAAE,CAAC,0BAA0B,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,EAAE,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;YAChG,OAAO,GAAG,EAAE,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YAC9C,0EAA0E;YAC1E,sBAAsB;YACtB,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAC7F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAED,IAAI,OAAY,CAAC;IACjB,IAAI,CAAC;QACH,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,EAAE,WAAW,EAAE,uCAAuC,CAAC,EAAE,EAAE,CAAC;IACrE,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,WAAW,EAAE,4CAA4C,GAAG,EAAE,EAAE,CAAC;IAEvF,MAAM,GAAG,GAAG;QACV,GAAG,OAAO,CAAC,uBAAuB,CAAC,MAAM,CAAC;QAC1C,GAAG,OAAO,CAAC,sBAAsB,CAAC,MAAM,CAAC;KAC1C,CAAC;IAEF,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,EAAE,CAAC,4BAA4B,CAAC,CAAC,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACrE,IAAI,IAAI,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,IAAI,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC1C,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YAC1D,IAAI,GAAG,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;YACpB,MAAM,GAAG,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC;QAC7B,CAAC;QACD,MAAM,QAAQ,GAAa,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QAC9F,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACxG,CAAC;IACD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IAC3D,OAAO,GAAG,CAAC;AACb,CAAC;AAED,2EAA2E;AAC3E,SAAgB,qBAAqB,CAAC,MAAc,EAAE,MAAc;IAClE,MAAM,GAAG,GAAiB,EAAE,CAAC;IAC7B,MAAM,EAAE,GAAG,2DAA2D,CAAC;IACvE,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,WAAW,EAAc,CAAC;QACxD,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC;YAC7B,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC;YAC/B,QAAQ,EAAE,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO;YAC7D,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YAC5B,MAAM;SACP,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,2DAA2D;AAC3D,SAAS,sBAAsB,CAAC,IAAY,EAAE,OAAe;IAC3D,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACpC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;IACzC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,CAAC;QACH,MAAM,GAAG,IAAA,wBAAQ,EAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IAClG,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,0EAA0E;QAC1E,MAAM,GAAG,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,KAAK,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;IAClD,CAAC;IACD,OAAO,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc,CAAC,IAAY,EAAE,MAAY,EAAE,MAAc,OAAO,CAAC,GAAG,EAAE;IACpF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,WAAW,EAAE,mBAAmB,GAAG,EAAE,EAAE,CAAC;IAE1E,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,WAAW,IAAI,EAAE,CAA2B,CAAC;IAClE,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAEtC,6BAA6B;IAC7B,IAAI,GAAG,CAAC,MAAM,CAAC;QAAE,OAAO,sBAAsB,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;IACjE,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO,wBAAwB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAEhE,OAAO,EAAE,WAAW,EAAE,gCAAgC,GAAG,kDAAkD,MAAM,IAAI,KAAK,wBAAwB,EAAE,CAAC;AACvJ,CAAC;AAED,SAAgB,iBAAiB,CAAC,IAAY,EAAE,KAAmB;IACjE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,IAAI,4BAA4B,CAAC;IACrE,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM,CAAC;IAC9D,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;IACjE,MAAM,IAAI,GAAG,GAAG,IAAI,MAAM,IAAI,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC;IAC3G,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QACxC,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QACjF,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxC,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;IACrF,CAAC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7E,OAAO,GAAG,IAAI,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;AAC/C,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Minimal line-based unified diff for edit previews.
3
+ *
4
+ * Edits applied by edit_file are localized (a contiguous region changes), so a
5
+ * single trimmed hunk — common prefix/suffix removed, the differing middle
6
+ * shown with a few lines of context — is enough to let the model and the user
7
+ * see exactly what changed without diffing whole files line-by-line.
8
+ */
9
+ export interface DiffOptions {
10
+ /** Lines of unchanged context around the change (default 3). */
11
+ context?: number;
12
+ /** Optional path shown in the diff header. */
13
+ path?: string;
14
+ }
15
+ export interface DiffStat {
16
+ added: number;
17
+ removed: number;
18
+ }
19
+ /** Result of rendering a diff: the text plus +/- line counts. */
20
+ export interface DiffResult {
21
+ text: string;
22
+ stat: DiffStat;
23
+ }
24
+ /**
25
+ * Produce a compact unified diff between two strings. Returns the diff text and
26
+ * a +/- line stat. Identical inputs yield an empty diff (stat 0/0).
27
+ */
28
+ export declare function unifiedDiff(oldStr: string, newStr: string, opts?: DiffOptions): DiffResult;
29
+ /** Count non-overlapping occurrences of `needle` in `haystack`. */
30
+ export declare function countOccurrences(haystack: string, needle: string): number;
31
+ //# sourceMappingURL=diff.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.ts","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,WAAW;IAC1B,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,iEAAiE;AACjE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;CAChB;AAgBD;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,UAAU,CAwC9F;AAED,mEAAmE;AACnE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CASzE"}
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ /**
3
+ * Minimal line-based unified diff for edit previews.
4
+ *
5
+ * Edits applied by edit_file are localized (a contiguous region changes), so a
6
+ * single trimmed hunk — common prefix/suffix removed, the differing middle
7
+ * shown with a few lines of context — is enough to let the model and the user
8
+ * see exactly what changed without diffing whole files line-by-line.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.unifiedDiff = unifiedDiff;
12
+ exports.countOccurrences = countOccurrences;
13
+ function commonPrefixLen(a, b) {
14
+ const n = Math.min(a.length, b.length);
15
+ let i = 0;
16
+ while (i < n && a[i] === b[i])
17
+ i++;
18
+ return i;
19
+ }
20
+ function commonSuffixLen(a, b, skip) {
21
+ const max = Math.min(a.length, b.length) - skip;
22
+ let i = 0;
23
+ while (i < max && a[a.length - 1 - i] === b[b.length - 1 - i])
24
+ i++;
25
+ return i;
26
+ }
27
+ /**
28
+ * Produce a compact unified diff between two strings. Returns the diff text and
29
+ * a +/- line stat. Identical inputs yield an empty diff (stat 0/0).
30
+ */
31
+ function unifiedDiff(oldStr, newStr, opts = {}) {
32
+ if (oldStr === newStr)
33
+ return { text: '', stat: { added: 0, removed: 0 } };
34
+ const context = Math.max(0, opts.context ?? 3);
35
+ const oldLines = oldStr.split('\n');
36
+ const newLines = newStr.split('\n');
37
+ let pre = commonPrefixLen(oldLines, newLines);
38
+ const suf = commonSuffixLen(oldLines, newLines, pre);
39
+ // The changed region (exclusive of the common prefix/suffix).
40
+ const oldChanged = oldLines.slice(pre, oldLines.length - suf);
41
+ const newChanged = newLines.slice(pre, newLines.length - suf);
42
+ // Context window bounds.
43
+ const ctxStart = Math.max(0, pre - context);
44
+ const oldCtxAfterStart = oldLines.length - suf;
45
+ const newCtxAfterStart = newLines.length - suf;
46
+ const oldCtxAfter = oldLines.slice(oldCtxAfterStart, oldCtxAfterStart + context);
47
+ const leading = oldLines.slice(ctxStart, pre);
48
+ const lines = [];
49
+ if (opts.path)
50
+ lines.push(`--- ${opts.path}`, `+++ ${opts.path}`);
51
+ // Hunk header (1-based line numbers).
52
+ const oldStart = ctxStart + 1;
53
+ const oldCount = leading.length + oldChanged.length + oldCtxAfter.length;
54
+ const newStart = ctxStart + 1;
55
+ const newCount = leading.length + newChanged.length + oldCtxAfter.length;
56
+ lines.push(`@@ -${oldStart},${oldCount} +${newStart},${newCount} @@`);
57
+ for (const l of leading)
58
+ lines.push(` ${l}`);
59
+ for (const l of oldChanged)
60
+ lines.push(`-${l}`);
61
+ for (const l of newChanged)
62
+ lines.push(`+${l}`);
63
+ for (const l of oldCtxAfter)
64
+ lines.push(` ${l}`);
65
+ return {
66
+ text: lines.join('\n'),
67
+ stat: { added: newChanged.length, removed: oldChanged.length },
68
+ };
69
+ }
70
+ /** Count non-overlapping occurrences of `needle` in `haystack`. */
71
+ function countOccurrences(haystack, needle) {
72
+ if (!needle)
73
+ return 0;
74
+ let count = 0;
75
+ let idx = haystack.indexOf(needle);
76
+ while (idx !== -1) {
77
+ count++;
78
+ idx = haystack.indexOf(needle, idx + needle.length);
79
+ }
80
+ return count;
81
+ }
82
+ //# sourceMappingURL=diff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/core/diff.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Environment context snapshot — a small, model-visible block describing the
3
+ * runtime world (working directory, platform, git, Node, date), kept separate
4
+ * from conversation history. Mirrors Claude Code's <env> block so the agent
5
+ * grounds itself without having to probe with tools every turn.
6
+ */
7
+ export interface GitInfo {
8
+ repo: boolean;
9
+ branch?: string;
10
+ }
11
+ /**
12
+ * Cheap git detection: walk up for a `.git` (handles worktrees, where `.git`
13
+ * is a file pointing at the real gitdir), then read HEAD for the branch. No
14
+ * subprocess — just file reads.
15
+ */
16
+ export declare function gitInfo(cwd?: string): GitInfo;
17
+ /**
18
+ * Build the environment block. `now` is injectable for deterministic tests.
19
+ */
20
+ export declare function buildEnvBlock(opts?: {
21
+ cwd?: string;
22
+ lang?: string;
23
+ now?: Date;
24
+ }): string;
25
+ //# sourceMappingURL=envcontext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envcontext.d.ts","sourceRoot":"","sources":["../../src/core/envcontext.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAyB5D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,IAAI,CAAA;CAAE,GAAG,MAAM,CA2BxF"}
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ /**
3
+ * Environment context snapshot — a small, model-visible block describing the
4
+ * runtime world (working directory, platform, git, Node, date), kept separate
5
+ * from conversation history. Mirrors Claude Code's <env> block so the agent
6
+ * grounds itself without having to probe with tools every turn.
7
+ */
8
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.gitInfo = gitInfo;
43
+ exports.buildEnvBlock = buildEnvBlock;
44
+ const fs = __importStar(require("fs"));
45
+ const os = __importStar(require("os"));
46
+ const path = __importStar(require("path"));
47
+ /**
48
+ * Cheap git detection: walk up for a `.git` (handles worktrees, where `.git`
49
+ * is a file pointing at the real gitdir), then read HEAD for the branch. No
50
+ * subprocess — just file reads.
51
+ */
52
+ function gitInfo(cwd = process.cwd()) {
53
+ let dir = path.resolve(cwd);
54
+ for (let i = 0; i < 40; i++) {
55
+ const dotGit = path.join(dir, '.git');
56
+ if (fs.existsSync(dotGit)) {
57
+ let gitDir = dotGit;
58
+ try {
59
+ if (fs.statSync(dotGit).isFile()) {
60
+ const m = fs.readFileSync(dotGit, 'utf8').match(/gitdir:\s*(.+)/);
61
+ if (m)
62
+ gitDir = path.resolve(dir, m[1].trim());
63
+ }
64
+ }
65
+ catch { /* treat as repo without branch */ }
66
+ try {
67
+ const head = fs.readFileSync(path.join(gitDir, 'HEAD'), 'utf8').trim();
68
+ const ref = head.match(/ref:\s*refs\/heads\/(.+)/);
69
+ return { repo: true, branch: ref ? ref[1] : head.slice(0, 8) };
70
+ }
71
+ catch {
72
+ return { repo: true };
73
+ }
74
+ }
75
+ const parent = path.dirname(dir);
76
+ if (parent === dir)
77
+ break;
78
+ dir = parent;
79
+ }
80
+ return { repo: false };
81
+ }
82
+ /**
83
+ * Build the environment block. `now` is injectable for deterministic tests.
84
+ */
85
+ function buildEnvBlock(opts) {
86
+ const cwd = opts?.cwd || process.cwd();
87
+ const lang = opts?.lang || 'zh';
88
+ const now = opts?.now || new Date();
89
+ const git = gitInfo(cwd);
90
+ const date = now.toISOString().slice(0, 10);
91
+ const platform = `${process.platform} ${os.release()}`;
92
+ const gitLine = git.repo ? (git.branch ? `yes (branch: ${git.branch})` : 'yes') : 'no';
93
+ if (lang === 'en') {
94
+ return [
95
+ '## Environment',
96
+ `- Working directory: ${cwd}`,
97
+ `- Platform: ${platform}`,
98
+ `- Node: ${process.version}`,
99
+ `- Git repo: ${gitLine}`,
100
+ `- Date: ${date}`,
101
+ ].join('\n');
102
+ }
103
+ return [
104
+ '## 运行环境',
105
+ `- 工作目录: ${cwd}`,
106
+ `- 平台: ${platform}`,
107
+ `- Node: ${process.version}`,
108
+ `- Git 仓库: ${gitLine === 'no' ? '否' : gitLine.replace('yes', '是')}`,
109
+ `- 日期: ${date}`,
110
+ ].join('\n');
111
+ }
112
+ //# sourceMappingURL=envcontext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envcontext.js","sourceRoot":"","sources":["../../src/core/envcontext.ts"],"names":[],"mappings":"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"}
@@ -17,6 +17,7 @@ export declare class SystemContext {
17
17
  workspacePath: string;
18
18
  mcp: any;
19
19
  mcpStatus: string[];
20
+ plugins: any;
20
21
  constructor(opts: {
21
22
  config: ReturnType<typeof loadConfig>;
22
23
  bus: MessageBus;
@@ -26,6 +27,7 @@ export declare class SystemContext {
26
27
  workspacePath?: string;
27
28
  mcp?: any;
28
29
  mcpStatus?: string[];
30
+ plugins?: any;
29
31
  });
30
32
  initAll(): Promise<void>;
31
33
  closeAll(): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/core/factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/core/factory.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,7 @@ class SystemContext {
21
21
  this.workspacePath = '';
22
22
  this.mcp = null;
23
23
  this.mcpStatus = [];
24
+ this.plugins = null;
24
25
  this.config = opts.config;
25
26
  this.bus = opts.bus;
26
27
  this.llm = opts.llm;
@@ -29,8 +30,18 @@ class SystemContext {
29
30
  this.workspacePath = opts.workspacePath || '';
30
31
  this.mcp = opts.mcp || null;
31
32
  this.mcpStatus = opts.mcpStatus || [];
33
+ this.plugins = opts.plugins || null;
32
34
  }
33
35
  async initAll() {
36
+ // Plugin `init` hook — fires once after load, before agents come up.
37
+ if (this.plugins) {
38
+ try {
39
+ await this.plugins.emit('init', { config: this.config });
40
+ }
41
+ catch (e) {
42
+ log.warn('plugin_init_hook_failed', { error: String(e) });
43
+ }
44
+ }
34
45
  if (this.mcp) {
35
46
  try {
36
47
  this.mcpStatus = await this.mcp.connectAll();
@@ -47,6 +58,12 @@ class SystemContext {
47
58
  }
48
59
  }
49
60
  async closeAll() {
61
+ // Terminate any background shell jobs started this session.
62
+ try {
63
+ const { getBackgroundManager } = require('./bgproc');
64
+ getBackgroundManager().killAll();
65
+ }
66
+ catch { /* best-effort */ }
50
67
  for (const agent of this.agentMap.values()) {
51
68
  await agent.close();
52
69
  }
@@ -103,10 +120,11 @@ function createSystemContext() {
103
120
  catch (e) {
104
121
  log.warn('skills_not_available', { error: String(e) });
105
122
  }
106
- // Load plugins
123
+ // Load plugins (ordered hook lifecycle — see plugins/loader)
124
+ let pluginLoader = null;
107
125
  try {
108
126
  const { PluginLoader } = require('../plugins/loader');
109
- const pluginLoader = new PluginLoader(baseToolRegistry);
127
+ pluginLoader = new PluginLoader(baseToolRegistry, config);
110
128
  const pluginConfig = config.plugins;
111
129
  const pluginDirs = pluginConfig?.enabled ? (pluginConfig.directories || []) : [];
112
130
  pluginLoader.loadFromDirectories(pluginDirs);
@@ -173,6 +191,20 @@ function createSystemContext() {
173
191
  catch (e) {
174
192
  log.warn('delegate_tool_not_available', { agent: name, error: String(e) });
175
193
  }
194
+ // Register the spawn_agent tool — isolated-context subagents (Task tool).
195
+ try {
196
+ const { createSpawnAgentTool } = require('../tools/spawn');
197
+ agentRegistry.register(createSpawnAgentTool({
198
+ config,
199
+ llm,
200
+ bus,
201
+ baseToolRegistry,
202
+ baseSkillRegistry,
203
+ }));
204
+ }
205
+ catch (e) {
206
+ log.warn('spawn_tool_not_available', { agent: name, error: String(e) });
207
+ }
176
208
  // Register model self-service tools (list_models / set_my_model)
177
209
  try {
178
210
  const { createModelTools } = require('../tools/model_tool');
@@ -213,6 +245,7 @@ function createSystemContext() {
213
245
  toolRegistry: baseToolRegistry,
214
246
  workspacePath,
215
247
  mcp: mcpManager,
248
+ plugins: pluginLoader,
216
249
  });
217
250
  }
218
251
  // ── Task orchestration ──