indusagi-coding-agent 0.2.13 → 0.2.14
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 +19 -0
- package/dist/entry.js +1762 -958
- package/dist/guardrails.js +145 -35
- package/dist/index.js +1810 -1006
- package/dist/review-agent.js +344 -60
- package/dist/review-server.js +346 -62
- package/package.json +12 -3
- package/src/boot/auth-vault.ts +4 -5
- package/src/boot/runners/addon-wiring.ts +111 -3
- package/src/boot/runners/benchmark-integrity.ts +107 -0
- package/src/boot/runners/repl-runner.ts +2 -1
- package/src/boot/runners/session.ts +18 -8
- package/src/boot/server-token.ts +20 -11
- package/src/briefing/context-docs.ts +144 -12
- package/src/channels/oneshot.ts +6 -0
- package/src/conductor/conductor.ts +67 -12
- package/src/conductor/contract.ts +4 -3
- package/src/conductor/transcript-store/store.ts +4 -8
- package/src/console/auth-status.ts +9 -4
- package/src/console/components/AgentsView.ts +2 -2
- package/src/console/components/BackgroundAgents.ts +15 -2
- package/src/console/components/Banner.ts +20 -9
- package/src/console/components/Composer.ts +57 -82
- package/src/console/components/ScrollViewport.ts +46 -0
- package/src/console/components/TerminalConsole.ts +165 -162
- package/src/console/components/WorkingIndicator.ts +6 -5
- package/src/console/components/banner-sweep.ts +5 -1
- package/src/console/components/welcome.ts +3 -3
- package/src/console/contract.ts +10 -5
- package/src/console/index.ts +7 -7
- package/src/console/input/complete.ts +2 -2
- package/src/console/input/dir-reader.ts +3 -1
- package/src/console/input/graphemes.ts +22 -0
- package/src/console/input/keymap.ts +6 -4
- package/src/console/mount.ts +45 -3
- package/src/console/overlays/auth.ts +28 -8
- package/src/console/overlays/boards.ts +13 -40
- package/src/console/overlays/host.ts +10 -0
- package/src/console/overlays/pickers.ts +35 -30
- package/src/console/reducer.ts +12 -5
- package/src/console/slash/builtins.ts +4 -3
- package/src/console/slash/commands/integrations.ts +13 -14
- package/src/console/slash/commands/transcript.ts +3 -8
- package/src/console/slash/commands/workbench.ts +2 -2
- package/src/console/test-support.ts +48 -0
- package/src/integrations/sarvam/config.ts +15 -13
- package/src/kit/external-editor.ts +17 -1
- package/src/kit/run-shell.ts +31 -0
- package/src/launch/invocation/flags.ts +12 -0
- package/src/launch/login.ts +23 -10
- package/src/launch/oauth.ts +3 -0
- package/src/models.ts +78 -2
- package/src/security/private-state.ts +122 -0
- package/src/window-budget/summarize/condense.ts +4 -1
- package/src/workspace/brand.ts +1 -1
- package/src/workspace/locator.ts +2 -2
package/dist/entry.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/entry.ts
|
|
4
4
|
import { argv as processArgv, env as processEnv } from "node:process";
|
|
5
|
-
import { realpathSync as
|
|
5
|
+
import { realpathSync as realpathSync4 } from "node:fs";
|
|
6
6
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7
7
|
|
|
8
8
|
// src/workspace/brand.ts
|
|
@@ -18,7 +18,7 @@ var BRAND = Object.freeze({
|
|
|
18
18
|
envShareViewer: "INDUSAGI_SHARE_VIEWER_URL",
|
|
19
19
|
shareViewerUrl: "https://buildwithindusagi.ai/session/"
|
|
20
20
|
});
|
|
21
|
-
var VERSION = "0.2.
|
|
21
|
+
var VERSION = "0.2.14";
|
|
22
22
|
|
|
23
23
|
// src/launch/credentials.ts
|
|
24
24
|
import { createInterface as createInterface2 } from "node:readline/promises";
|
|
@@ -77,26 +77,153 @@ import {
|
|
|
77
77
|
|
|
78
78
|
// src/launch/login.ts
|
|
79
79
|
import { createInterface } from "node:readline/promises";
|
|
80
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
80
81
|
import chalk from "chalk";
|
|
81
82
|
|
|
82
83
|
// src/boot/server-token.ts
|
|
83
|
-
import {
|
|
84
|
+
import { unlink } from "node:fs/promises";
|
|
84
85
|
import os from "node:os";
|
|
85
86
|
import path from "node:path";
|
|
87
|
+
|
|
88
|
+
// src/security/private-state.ts
|
|
89
|
+
import {
|
|
90
|
+
chmodSync,
|
|
91
|
+
closeSync,
|
|
92
|
+
constants,
|
|
93
|
+
fchmodSync,
|
|
94
|
+
fstatSync,
|
|
95
|
+
lstatSync,
|
|
96
|
+
mkdirSync,
|
|
97
|
+
openSync,
|
|
98
|
+
readFileSync,
|
|
99
|
+
renameSync,
|
|
100
|
+
rmSync,
|
|
101
|
+
writeFileSync
|
|
102
|
+
} from "node:fs";
|
|
103
|
+
import { randomUUID } from "node:crypto";
|
|
104
|
+
import { dirname } from "node:path";
|
|
105
|
+
var PRIVATE_DIRECTORY_MODE = 448;
|
|
106
|
+
var PRIVATE_FILE_MODE = 384;
|
|
107
|
+
var NO_FOLLOW = constants.O_NOFOLLOW ?? 0;
|
|
108
|
+
function isPosix() {
|
|
109
|
+
return process.platform !== "win32";
|
|
110
|
+
}
|
|
111
|
+
function assertOwned(uid, path5) {
|
|
112
|
+
if (!isPosix() || process.getuid === void 0) return;
|
|
113
|
+
if (uid !== process.getuid()) {
|
|
114
|
+
throw new Error(`Refusing sensitive path not owned by the current user: ${path5}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function ensurePrivateDirectorySync(path5) {
|
|
118
|
+
try {
|
|
119
|
+
const current = lstatSync(path5);
|
|
120
|
+
if (current.isSymbolicLink() || !current.isDirectory()) {
|
|
121
|
+
throw new Error(`Refusing non-directory sensitive state path: ${path5}`);
|
|
122
|
+
}
|
|
123
|
+
assertOwned(current.uid, path5);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (error.code !== "ENOENT") throw error;
|
|
126
|
+
mkdirSync(path5, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
|
|
127
|
+
}
|
|
128
|
+
if (isPosix()) chmodSync(path5, PRIVATE_DIRECTORY_MODE);
|
|
129
|
+
}
|
|
130
|
+
function validateExistingFile(path5) {
|
|
131
|
+
try {
|
|
132
|
+
const current = lstatSync(path5);
|
|
133
|
+
if (current.isSymbolicLink() || !current.isFile()) {
|
|
134
|
+
throw new Error(`Refusing non-regular sensitive file: ${path5}`);
|
|
135
|
+
}
|
|
136
|
+
assertOwned(current.uid, path5);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
if (error.code === "ENOENT") return;
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function readPrivateFileSync(path5) {
|
|
143
|
+
ensurePrivateDirectorySync(dirname(path5));
|
|
144
|
+
try {
|
|
145
|
+
validateExistingFile(path5);
|
|
146
|
+
const fd = openSync(path5, constants.O_RDONLY | NO_FOLLOW);
|
|
147
|
+
try {
|
|
148
|
+
const current = fstatSync(fd);
|
|
149
|
+
if (!current.isFile()) throw new Error(`Refusing non-regular sensitive file: ${path5}`);
|
|
150
|
+
assertOwned(current.uid, path5);
|
|
151
|
+
if (isPosix()) fchmodSync(fd, PRIVATE_FILE_MODE);
|
|
152
|
+
return readFileSync(fd, "utf8");
|
|
153
|
+
} finally {
|
|
154
|
+
closeSync(fd);
|
|
155
|
+
}
|
|
156
|
+
} catch (error) {
|
|
157
|
+
if (error.code === "ENOENT") return null;
|
|
158
|
+
throw error;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function atomicWritePrivateFileSync(path5, content) {
|
|
162
|
+
const parent = dirname(path5);
|
|
163
|
+
ensurePrivateDirectorySync(parent);
|
|
164
|
+
validateExistingFile(path5);
|
|
165
|
+
const temporary = `${path5}.tmp-${process.pid}-${randomUUID()}`;
|
|
166
|
+
let fd;
|
|
167
|
+
try {
|
|
168
|
+
fd = openSync(
|
|
169
|
+
temporary,
|
|
170
|
+
constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | NO_FOLLOW,
|
|
171
|
+
PRIVATE_FILE_MODE
|
|
172
|
+
);
|
|
173
|
+
writeFileSync(fd, content, "utf8");
|
|
174
|
+
if (isPosix()) fchmodSync(fd, PRIVATE_FILE_MODE);
|
|
175
|
+
closeSync(fd);
|
|
176
|
+
fd = void 0;
|
|
177
|
+
renameSync(temporary, path5);
|
|
178
|
+
if (isPosix()) chmodSync(path5, PRIVATE_FILE_MODE);
|
|
179
|
+
} catch (error) {
|
|
180
|
+
if (fd !== void 0) closeSync(fd);
|
|
181
|
+
try {
|
|
182
|
+
rmSync(temporary, { force: true });
|
|
183
|
+
} catch {
|
|
184
|
+
}
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function appendPrivateFileSync(path5, content) {
|
|
189
|
+
ensurePrivateDirectorySync(dirname(path5));
|
|
190
|
+
validateExistingFile(path5);
|
|
191
|
+
const fd = openSync(
|
|
192
|
+
path5,
|
|
193
|
+
constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | NO_FOLLOW,
|
|
194
|
+
PRIVATE_FILE_MODE
|
|
195
|
+
);
|
|
196
|
+
try {
|
|
197
|
+
const current = fstatSync(fd);
|
|
198
|
+
if (!current.isFile()) throw new Error(`Refusing non-regular sensitive file: ${path5}`);
|
|
199
|
+
assertOwned(current.uid, path5);
|
|
200
|
+
if (isPosix()) fchmodSync(fd, PRIVATE_FILE_MODE);
|
|
201
|
+
writeFileSync(fd, content, "utf8");
|
|
202
|
+
} finally {
|
|
203
|
+
closeSync(fd);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/boot/server-token.ts
|
|
86
208
|
var INDUS_SERVER_URL = process.env.INDUS_SERVER_URL?.replace(/\/+$/, "") ?? "https://indus-server.vercel.app";
|
|
87
209
|
var CONFIG_DIR = path.join(os.homedir(), ".indusagi", "agent");
|
|
88
210
|
var TOKEN_FILE = path.join(CONFIG_DIR, "server-token.json");
|
|
89
|
-
|
|
211
|
+
function resolveTokenPaths(paths = {}) {
|
|
212
|
+
const configDir = paths.configDir ?? CONFIG_DIR;
|
|
213
|
+
return { configDir, tokenFile: paths.tokenFile ?? path.join(configDir, "server-token.json") };
|
|
214
|
+
}
|
|
215
|
+
async function getServerToken(paths = {}) {
|
|
90
216
|
try {
|
|
91
|
-
const data =
|
|
217
|
+
const data = readPrivateFileSync(resolveTokenPaths(paths).tokenFile);
|
|
218
|
+
if (data === null) return null;
|
|
92
219
|
return JSON.parse(data);
|
|
93
220
|
} catch {
|
|
94
221
|
return null;
|
|
95
222
|
}
|
|
96
223
|
}
|
|
97
|
-
async function storeServerToken(token) {
|
|
224
|
+
async function storeServerToken(token, paths = {}) {
|
|
98
225
|
try {
|
|
99
|
-
|
|
226
|
+
const { tokenFile } = resolveTokenPaths(paths);
|
|
100
227
|
const tokenData = {
|
|
101
228
|
access_token: token.access_token,
|
|
102
229
|
refresh_token: token.refresh_token,
|
|
@@ -105,20 +232,17 @@ async function storeServerToken(token) {
|
|
|
105
232
|
expires_at: token.expires_in !== void 0 ? new Date(Date.now() + token.expires_in * 1e3).toISOString() : null,
|
|
106
233
|
created_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
107
234
|
};
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
encoding: "utf8",
|
|
111
|
-
mode: 384
|
|
112
|
-
});
|
|
235
|
+
atomicWritePrivateFileSync(tokenFile, `${JSON.stringify(tokenData, null, 2)}
|
|
236
|
+
`);
|
|
113
237
|
return true;
|
|
114
238
|
} catch (error) {
|
|
115
239
|
console.error("Failed to store server token:", error.message);
|
|
116
240
|
return false;
|
|
117
241
|
}
|
|
118
242
|
}
|
|
119
|
-
async function clearServerToken() {
|
|
243
|
+
async function clearServerToken(paths = {}) {
|
|
120
244
|
try {
|
|
121
|
-
await unlink(
|
|
245
|
+
await unlink(resolveTokenPaths(paths).tokenFile);
|
|
122
246
|
return true;
|
|
123
247
|
} catch {
|
|
124
248
|
return false;
|
|
@@ -155,10 +279,10 @@ function err(line) {
|
|
|
155
279
|
process.stderr.write(`${line}
|
|
156
280
|
`);
|
|
157
281
|
}
|
|
158
|
-
function sleep(ms) {
|
|
159
|
-
return
|
|
282
|
+
function sleep(ms, signal) {
|
|
283
|
+
return delay(ms, void 0, { signal });
|
|
160
284
|
}
|
|
161
|
-
async function postJson(url, body) {
|
|
285
|
+
async function postJson(url, body, signal) {
|
|
162
286
|
const res = await fetch(url, {
|
|
163
287
|
method: "POST",
|
|
164
288
|
headers: {
|
|
@@ -166,7 +290,8 @@ async function postJson(url, body) {
|
|
|
166
290
|
accept: "application/json",
|
|
167
291
|
"user-agent": USER_AGENT
|
|
168
292
|
},
|
|
169
|
-
body: JSON.stringify(body)
|
|
293
|
+
body: JSON.stringify(body),
|
|
294
|
+
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(3e4)]) : AbortSignal.timeout(3e4)
|
|
170
295
|
});
|
|
171
296
|
const data = await res.json().catch(() => ({}));
|
|
172
297
|
return { status: res.status, data };
|
|
@@ -202,11 +327,11 @@ async function confirm(prompt, defaultValue) {
|
|
|
202
327
|
rl.close();
|
|
203
328
|
}
|
|
204
329
|
}
|
|
205
|
-
async function requestDeviceCode(serverUrl, clientId) {
|
|
330
|
+
async function requestDeviceCode(serverUrl, clientId, signal) {
|
|
206
331
|
const { status, data } = await postJson(`${serverUrl}/api/auth/device/code`, {
|
|
207
332
|
client_id: clientId,
|
|
208
333
|
scope: DEVICE_SCOPE
|
|
209
|
-
});
|
|
334
|
+
}, signal);
|
|
210
335
|
if (status >= 400 || typeof data.device_code !== "string") {
|
|
211
336
|
throw new LoginError(
|
|
212
337
|
`Authorization request failed: ${data.error_description ?? data.error ?? data.message ?? `HTTP ${status}`}`
|
|
@@ -214,18 +339,18 @@ async function requestDeviceCode(serverUrl, clientId) {
|
|
|
214
339
|
}
|
|
215
340
|
return data;
|
|
216
341
|
}
|
|
217
|
-
async function pollForToken(serverUrl, clientId, device) {
|
|
342
|
+
async function pollForToken(serverUrl, clientId, device, signal) {
|
|
218
343
|
let intervalMs = Math.max(1, device.interval ?? 5) * 1e3;
|
|
219
344
|
const deadline = Date.now() + (device.expires_in ?? 0) * 1e3;
|
|
220
345
|
while (Date.now() < deadline) {
|
|
221
|
-
await sleep(intervalMs);
|
|
346
|
+
await sleep(intervalMs, signal);
|
|
222
347
|
const { data } = await postJson(`${serverUrl}/api/auth/device/token`, {
|
|
223
348
|
grant_type: DEVICE_GRANT_TYPE,
|
|
224
349
|
device_code: device.device_code,
|
|
225
350
|
client_id: clientId
|
|
226
|
-
});
|
|
351
|
+
}, signal);
|
|
227
352
|
if (typeof data.access_token === "string") {
|
|
228
|
-
return data;
|
|
353
|
+
return { ...data, access_token: data.access_token };
|
|
229
354
|
}
|
|
230
355
|
const code = data.error;
|
|
231
356
|
switch (code) {
|
|
@@ -248,14 +373,17 @@ async function pollForToken(serverUrl, clientId, device) {
|
|
|
248
373
|
throw new LoginError("Timed out waiting for authorization. Run `indus login` again.");
|
|
249
374
|
}
|
|
250
375
|
async function runServerTierLogin(callbacks, serverUrl = INDUS_SERVER_URL, clientId = INDUS_CLIENT_ID) {
|
|
251
|
-
|
|
376
|
+
callbacks.signal?.throwIfAborted();
|
|
377
|
+
const device = await requestDeviceCode(serverUrl, clientId, callbacks.signal);
|
|
378
|
+
callbacks.signal?.throwIfAborted();
|
|
252
379
|
callbacks.onAuth({
|
|
253
380
|
url: device.verification_uri_complete ?? device.verification_uri ?? "",
|
|
254
381
|
instructions: `Enter code ${device.user_code} to authorize this device.`
|
|
255
382
|
});
|
|
256
383
|
callbacks.onProgress?.("Waiting for authorization...");
|
|
257
|
-
const token = await pollForToken(serverUrl, clientId, device);
|
|
258
|
-
|
|
384
|
+
const token = await pollForToken(serverUrl, clientId, device, callbacks.signal);
|
|
385
|
+
callbacks.signal?.throwIfAborted();
|
|
386
|
+
if (!await storeServerToken(token)) throw new LoginError("Could not save the server token.");
|
|
259
387
|
callbacks.onProgress?.("Server sign-in complete.");
|
|
260
388
|
}
|
|
261
389
|
async function doLogin(args) {
|
|
@@ -466,12 +594,12 @@ function openLoginUrl(url) {
|
|
|
466
594
|
const tryAt = (index) => {
|
|
467
595
|
if (index >= attempts.length) return Promise.resolve(false);
|
|
468
596
|
const { command, args } = attempts[index];
|
|
469
|
-
return new Promise((
|
|
597
|
+
return new Promise((resolve11) => {
|
|
470
598
|
let settled = false;
|
|
471
599
|
const finish = (ok) => {
|
|
472
600
|
if (settled) return;
|
|
473
601
|
settled = true;
|
|
474
|
-
|
|
602
|
+
resolve11(ok);
|
|
475
603
|
};
|
|
476
604
|
try {
|
|
477
605
|
const child = spawn(command, [...args], {
|
|
@@ -504,8 +632,11 @@ async function startOAuthLogin(providerId, callbacks, vault, account = "default"
|
|
|
504
632
|
const hint = envVar !== void 0 ? `set ${envVar} and restart` : "configure its OAuth client id";
|
|
505
633
|
throw new Error(`Browser sign-in for "${providerId}" is not configured: ${hint}.`);
|
|
506
634
|
}
|
|
635
|
+
callbacks.signal?.throwIfAborted();
|
|
507
636
|
const credentials = await provider.login(callbacks);
|
|
637
|
+
callbacks.signal?.throwIfAborted();
|
|
508
638
|
const existing = await vault.listAccounts(providerId);
|
|
639
|
+
callbacks.signal?.throwIfAborted();
|
|
509
640
|
const madeDefault = existing.length === 0;
|
|
510
641
|
await vault.putOAuth(providerId, account, credentials, madeDefault);
|
|
511
642
|
return { provider: providerId, account, madeDefault };
|
|
@@ -1247,6 +1378,18 @@ var FLAG_SPECS = [
|
|
|
1247
1378
|
group: "context",
|
|
1248
1379
|
describe: "Continue the most recent session in this directory."
|
|
1249
1380
|
},
|
|
1381
|
+
{
|
|
1382
|
+
name: "--trust-project-addons",
|
|
1383
|
+
kind: "boolean",
|
|
1384
|
+
group: "context",
|
|
1385
|
+
describe: "Trust executable project addons for the canonical workspace and their current content digest."
|
|
1386
|
+
},
|
|
1387
|
+
{
|
|
1388
|
+
name: "--allow-context-import",
|
|
1389
|
+
kind: "list",
|
|
1390
|
+
group: "context",
|
|
1391
|
+
describe: "Explicitly approve an exact external context file (comma-separated or repeated). Secret-like files remain blocked."
|
|
1392
|
+
},
|
|
1250
1393
|
/* ---- Tools ----------------------------------------------------------- */
|
|
1251
1394
|
{
|
|
1252
1395
|
name: "--tools",
|
|
@@ -1358,7 +1501,74 @@ var GPT_6_ASTRA_BASE = {
|
|
|
1358
1501
|
}
|
|
1359
1502
|
}
|
|
1360
1503
|
};
|
|
1504
|
+
var GPT_6_SOL_BASE = {
|
|
1505
|
+
id: "gpt-6-sol",
|
|
1506
|
+
name: "GPT-6 Sol",
|
|
1507
|
+
api: "openai-responses",
|
|
1508
|
+
reasoning: true,
|
|
1509
|
+
reasoningEfforts: ["high"],
|
|
1510
|
+
input: ["text", "image"],
|
|
1511
|
+
cost: {
|
|
1512
|
+
input: 10,
|
|
1513
|
+
cacheRead: 1,
|
|
1514
|
+
cacheWrite: 12.5,
|
|
1515
|
+
output: 50
|
|
1516
|
+
},
|
|
1517
|
+
contextWindow: 105e4,
|
|
1518
|
+
maxTokens: 128e3,
|
|
1519
|
+
longContextPricing: {
|
|
1520
|
+
threshold: 272e3,
|
|
1521
|
+
multipliers: {
|
|
1522
|
+
input: 2,
|
|
1523
|
+
cacheRead: 2,
|
|
1524
|
+
cacheWrite: 2,
|
|
1525
|
+
output: 1.5
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
};
|
|
1529
|
+
var GPT_6_LUNA_BASE = {
|
|
1530
|
+
id: "gpt-6-luna",
|
|
1531
|
+
name: "GPT-6 Luna",
|
|
1532
|
+
api: "openai-responses",
|
|
1533
|
+
reasoning: true,
|
|
1534
|
+
reasoningEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
1535
|
+
input: ["text", "image"],
|
|
1536
|
+
cost: {
|
|
1537
|
+
input: 0.1,
|
|
1538
|
+
cacheRead: 0.01,
|
|
1539
|
+
cacheWrite: 0.125,
|
|
1540
|
+
output: 0.5
|
|
1541
|
+
},
|
|
1542
|
+
contextWindow: 105e4,
|
|
1543
|
+
maxTokens: 128e3,
|
|
1544
|
+
longContextPricing: {
|
|
1545
|
+
threshold: 272e3,
|
|
1546
|
+
multipliers: { input: 2, cacheRead: 2, cacheWrite: 2, output: 1.5 }
|
|
1547
|
+
}
|
|
1548
|
+
};
|
|
1361
1549
|
var CODING_AGENT_MODELS = [
|
|
1550
|
+
{
|
|
1551
|
+
...GPT_6_SOL_BASE,
|
|
1552
|
+
provider: "openai",
|
|
1553
|
+
baseUrl: "https://api.openai.com/v1"
|
|
1554
|
+
},
|
|
1555
|
+
{
|
|
1556
|
+
...GPT_6_SOL_BASE,
|
|
1557
|
+
api: "openai-codex-responses",
|
|
1558
|
+
provider: "openai-codex",
|
|
1559
|
+
baseUrl: "https://chatgpt.com/backend-api"
|
|
1560
|
+
},
|
|
1561
|
+
{
|
|
1562
|
+
...GPT_6_LUNA_BASE,
|
|
1563
|
+
provider: "openai",
|
|
1564
|
+
baseUrl: "https://api.openai.com/v1"
|
|
1565
|
+
},
|
|
1566
|
+
{
|
|
1567
|
+
...GPT_6_LUNA_BASE,
|
|
1568
|
+
api: "openai-codex-responses",
|
|
1569
|
+
provider: "openai-codex",
|
|
1570
|
+
baseUrl: "https://chatgpt.com/backend-api"
|
|
1571
|
+
},
|
|
1362
1572
|
{
|
|
1363
1573
|
...GPT_6_ASTRA_BASE,
|
|
1364
1574
|
provider: "openai",
|
|
@@ -1397,8 +1607,15 @@ function createCodingAgentModelRegistry() {
|
|
|
1397
1607
|
return applyCodingAgentModelOverlay(new ModelRegistry());
|
|
1398
1608
|
}
|
|
1399
1609
|
function isReasoningEffortSupported(modelId, effort) {
|
|
1400
|
-
|
|
1401
|
-
|
|
1610
|
+
const id = modelId?.split("/").at(-1);
|
|
1611
|
+
if (id === "gpt-6-astra") {
|
|
1612
|
+
return GPT_6_ASTRA_BASE.reasoningEfforts.includes(effort);
|
|
1613
|
+
}
|
|
1614
|
+
if (id === "gpt-6-sol") return effort === "high";
|
|
1615
|
+
if (id === "gpt-6-luna") {
|
|
1616
|
+
return GPT_6_LUNA_BASE.reasoningEfforts.includes(effort);
|
|
1617
|
+
}
|
|
1618
|
+
return true;
|
|
1402
1619
|
}
|
|
1403
1620
|
|
|
1404
1621
|
// src/launch/invocation/read.ts
|
|
@@ -1771,13 +1988,13 @@ function defaultResumeDeps() {
|
|
|
1771
1988
|
},
|
|
1772
1989
|
mountPicker(sessions, totalCount) {
|
|
1773
1990
|
const byPath = new Map(sessions.map((s) => [s.path, s]));
|
|
1774
|
-
return new Promise((
|
|
1991
|
+
return new Promise((resolve11, reject) => {
|
|
1775
1992
|
let settled = false;
|
|
1776
1993
|
const settle = (value) => {
|
|
1777
1994
|
if (settled) return;
|
|
1778
1995
|
settled = true;
|
|
1779
1996
|
instance.unmount();
|
|
1780
|
-
|
|
1997
|
+
resolve11(value);
|
|
1781
1998
|
};
|
|
1782
1999
|
let instance;
|
|
1783
2000
|
try {
|
|
@@ -1796,7 +2013,7 @@ function defaultResumeDeps() {
|
|
|
1796
2013
|
void instance.waitUntilExit().then(() => {
|
|
1797
2014
|
if (!settled) {
|
|
1798
2015
|
settled = true;
|
|
1799
|
-
|
|
2016
|
+
resolve11(null);
|
|
1800
2017
|
}
|
|
1801
2018
|
});
|
|
1802
2019
|
});
|
|
@@ -1901,7 +2118,7 @@ import { join as join2 } from "node:path";
|
|
|
1901
2118
|
|
|
1902
2119
|
// src/boot/upgrade/upgrades.ts
|
|
1903
2120
|
import { promises as fs, constants as fsConstants } from "node:fs";
|
|
1904
|
-
import { join, dirname, basename } from "node:path";
|
|
2121
|
+
import { join, dirname as dirname2, basename } from "node:path";
|
|
1905
2122
|
var SECURE_FILE_MODE = 384;
|
|
1906
2123
|
var RETIRED_SUFFIX = ".retired";
|
|
1907
2124
|
async function pathExists(target) {
|
|
@@ -1934,7 +2151,7 @@ async function readJsonOrUndefined(target) {
|
|
|
1934
2151
|
}
|
|
1935
2152
|
}
|
|
1936
2153
|
async function writeJsonWithMode(target, value, mode) {
|
|
1937
|
-
await fs.mkdir(
|
|
2154
|
+
await fs.mkdir(dirname2(target), { recursive: true });
|
|
1938
2155
|
await fs.writeFile(target, `${JSON.stringify(value, null, 2)}
|
|
1939
2156
|
`, { mode });
|
|
1940
2157
|
await fs.chmod(target, mode);
|
|
@@ -1942,7 +2159,7 @@ async function writeJsonWithMode(target, value, mode) {
|
|
|
1942
2159
|
async function relocateWithoutClobber(from, into) {
|
|
1943
2160
|
if (!await pathExists(from)) return false;
|
|
1944
2161
|
if (await pathExists(into)) return false;
|
|
1945
|
-
await fs.mkdir(
|
|
2162
|
+
await fs.mkdir(dirname2(into), { recursive: true });
|
|
1946
2163
|
await fs.rename(from, into);
|
|
1947
2164
|
return true;
|
|
1948
2165
|
}
|
|
@@ -2099,7 +2316,6 @@ async function applyUpgrades(ws) {
|
|
|
2099
2316
|
}
|
|
2100
2317
|
|
|
2101
2318
|
// src/workspace/locator.ts
|
|
2102
|
-
import { mkdirSync } from "node:fs";
|
|
2103
2319
|
import { homedir } from "node:os";
|
|
2104
2320
|
import { isAbsolute, join as join3, resolve } from "node:path";
|
|
2105
2321
|
var LAYOUT = {
|
|
@@ -2163,7 +2379,7 @@ function createWorkspace(overrides = {}) {
|
|
|
2163
2379
|
}
|
|
2164
2380
|
function ensureDirs(workspace) {
|
|
2165
2381
|
for (const key of DIRECTORY_KEYS) {
|
|
2166
|
-
|
|
2382
|
+
ensurePrivateDirectorySync(workspace[key]);
|
|
2167
2383
|
}
|
|
2168
2384
|
return workspace;
|
|
2169
2385
|
}
|
|
@@ -2260,6 +2476,30 @@ var EMPTY_CONSOLE_STATE = {
|
|
|
2260
2476
|
tick: 0
|
|
2261
2477
|
};
|
|
2262
2478
|
|
|
2479
|
+
// src/console/input/graphemes.ts
|
|
2480
|
+
var segmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
2481
|
+
function previousGrapheme(text, at) {
|
|
2482
|
+
let previous = 0;
|
|
2483
|
+
for (const part of segmenter.segment(text)) {
|
|
2484
|
+
if (part.index >= at) break;
|
|
2485
|
+
previous = part.index;
|
|
2486
|
+
}
|
|
2487
|
+
return previous;
|
|
2488
|
+
}
|
|
2489
|
+
function nextGrapheme(text, at) {
|
|
2490
|
+
for (const part of segmenter.segment(text)) if (part.index > at) return part.index;
|
|
2491
|
+
return text.length;
|
|
2492
|
+
}
|
|
2493
|
+
function moveGrapheme(text, at, delta) {
|
|
2494
|
+
let next = Math.max(0, Math.min(at, text.length));
|
|
2495
|
+
for (let i = 0; i < Math.abs(delta); i++) next = delta < 0 ? previousGrapheme(text, next) : nextGrapheme(text, next);
|
|
2496
|
+
return next;
|
|
2497
|
+
}
|
|
2498
|
+
function snapGrapheme(text, at) {
|
|
2499
|
+
const clamped = Math.max(0, Math.min(at, text.length));
|
|
2500
|
+
return clamped === text.length ? clamped : previousGrapheme(text, clamped + 1);
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2263
2503
|
// src/console/reducer.ts
|
|
2264
2504
|
function clamp(offset, max) {
|
|
2265
2505
|
if (offset < 0) return 0;
|
|
@@ -2283,13 +2523,14 @@ function insertBuffer(state, text) {
|
|
|
2283
2523
|
function erasePrev(state) {
|
|
2284
2524
|
const at = clamp(state.caret, state.buffer.length);
|
|
2285
2525
|
if (at === 0) return state;
|
|
2286
|
-
const
|
|
2287
|
-
|
|
2526
|
+
const previous = previousGrapheme(state.buffer, at);
|
|
2527
|
+
const next = state.buffer.slice(0, previous) + state.buffer.slice(at);
|
|
2528
|
+
return withBuffer(state, next, previous);
|
|
2288
2529
|
}
|
|
2289
2530
|
function eraseNext(state) {
|
|
2290
2531
|
const at = clamp(state.caret, state.buffer.length);
|
|
2291
2532
|
if (at >= state.buffer.length) return state;
|
|
2292
|
-
const next = state.buffer.slice(0, at) + state.buffer.slice(at
|
|
2533
|
+
const next = state.buffer.slice(0, at) + state.buffer.slice(nextGrapheme(state.buffer, at));
|
|
2293
2534
|
return withBuffer(state, next, at);
|
|
2294
2535
|
}
|
|
2295
2536
|
function pushHistory(state, text) {
|
|
@@ -2332,6 +2573,10 @@ function patchRow(state, id, text) {
|
|
|
2332
2573
|
}
|
|
2333
2574
|
function consoleReducer(state, event) {
|
|
2334
2575
|
switch (event.type) {
|
|
2576
|
+
case "view:reset":
|
|
2577
|
+
return { ...state, rows: [], blocks: [], buffer: "", caret: 0, historyAt: null, stash: "", modal: NO_MODAL, busy: false };
|
|
2578
|
+
case "display:set":
|
|
2579
|
+
return { ...state, [event.key]: event.value };
|
|
2335
2580
|
// Composer buffer & caret
|
|
2336
2581
|
case "buffer:set":
|
|
2337
2582
|
return setBuffer(state, event.text);
|
|
@@ -2350,9 +2595,9 @@ function consoleReducer(state, event) {
|
|
|
2350
2595
|
case "buffer:eraseNext":
|
|
2351
2596
|
return eraseNext(state);
|
|
2352
2597
|
case "caret:move":
|
|
2353
|
-
return { ...state, caret:
|
|
2598
|
+
return { ...state, caret: moveGrapheme(state.buffer, state.caret, event.delta) };
|
|
2354
2599
|
case "caret:jump":
|
|
2355
|
-
return { ...state, caret:
|
|
2600
|
+
return { ...state, caret: snapGrapheme(state.buffer, event.offset) };
|
|
2356
2601
|
// History ring
|
|
2357
2602
|
case "history:push":
|
|
2358
2603
|
return pushHistory(state, event.text);
|
|
@@ -2582,7 +2827,7 @@ function resolveTheme(scheme) {
|
|
|
2582
2827
|
var THEME_SCHEMES = Object.keys(THEMES);
|
|
2583
2828
|
|
|
2584
2829
|
// src/console/slash/builtins.ts
|
|
2585
|
-
import { homedir as
|
|
2830
|
+
import { homedir as homedir2 } from "node:os";
|
|
2586
2831
|
import { join as join12 } from "node:path";
|
|
2587
2832
|
|
|
2588
2833
|
// src/briefing/contract.ts
|
|
@@ -2767,7 +3012,7 @@ function composeBriefing(input) {
|
|
|
2767
3012
|
}
|
|
2768
3013
|
|
|
2769
3014
|
// src/briefing/macros.ts
|
|
2770
|
-
import { readFileSync, readdirSync, statSync } from "node:fs";
|
|
3015
|
+
import { readFileSync as readFileSync2, readdirSync, statSync } from "node:fs";
|
|
2771
3016
|
import { basename as basename2, join as join4 } from "node:path";
|
|
2772
3017
|
var decimal = (ch) => ch.charCodeAt(0) >= 48 && ch.charCodeAt(0) <= 57;
|
|
2773
3018
|
var bareword = (ch) => {
|
|
@@ -2979,13 +3224,13 @@ function loadMacros(dir, opts = {}) {
|
|
|
2979
3224
|
const macros = [];
|
|
2980
3225
|
for (const entry of entries.sort()) {
|
|
2981
3226
|
if (entry.startsWith(".") || !entry.toLowerCase().endsWith(".md")) continue;
|
|
2982
|
-
const
|
|
3227
|
+
const path5 = join4(dir, entry);
|
|
2983
3228
|
try {
|
|
2984
|
-
if (!statSync(
|
|
3229
|
+
if (!statSync(path5).isFile()) continue;
|
|
2985
3230
|
} catch {
|
|
2986
3231
|
continue;
|
|
2987
3232
|
}
|
|
2988
|
-
const macro = readMacroFile(
|
|
3233
|
+
const macro = readMacroFile(path5, origin, label);
|
|
2989
3234
|
if (!seen.has(macro.name)) {
|
|
2990
3235
|
seen.add(macro.name);
|
|
2991
3236
|
macros.push(macro);
|
|
@@ -2993,17 +3238,17 @@ function loadMacros(dir, opts = {}) {
|
|
|
2993
3238
|
}
|
|
2994
3239
|
return macros;
|
|
2995
3240
|
}
|
|
2996
|
-
function readMacroFile(
|
|
3241
|
+
function readMacroFile(path5, origin, label) {
|
|
2997
3242
|
let text;
|
|
2998
3243
|
try {
|
|
2999
|
-
text =
|
|
3244
|
+
text = readFileSync2(path5, "utf8");
|
|
3000
3245
|
} catch (cause) {
|
|
3001
|
-
throw briefingFault("macro_invalid", `could not read macro file at ${
|
|
3246
|
+
throw briefingFault("macro_invalid", `could not read macro file at ${path5}`, cause);
|
|
3002
3247
|
}
|
|
3003
3248
|
const { frontmatter, body } = splitFrontmatter(text);
|
|
3004
|
-
const name = basename2(
|
|
3249
|
+
const name = basename2(path5).replace(/\.md$/i, "");
|
|
3005
3250
|
const declared = typeof frontmatter.description === "string" ? frontmatter.description.trim() : "";
|
|
3006
|
-
return { name, description: declared ? `${declared} (${label})` : deriveDescription(body, label), body, origin, source:
|
|
3251
|
+
return { name, description: declared ? `${declared} (${label})` : deriveDescription(body, label), body, origin, source: path5 };
|
|
3007
3252
|
}
|
|
3008
3253
|
function deriveDescription(body, label) {
|
|
3009
3254
|
const first = body.split("\n").find((line) => line.trim())?.trim() ?? "";
|
|
@@ -3029,8 +3274,8 @@ function unquoteScalar(value) {
|
|
|
3029
3274
|
}
|
|
3030
3275
|
|
|
3031
3276
|
// src/briefing/skills.ts
|
|
3032
|
-
import { readFileSync as
|
|
3033
|
-
import { basename as basename3, dirname as
|
|
3277
|
+
import { readFileSync as readFileSync3, readdirSync as readdirSync2, realpathSync, statSync as statSync2 } from "node:fs";
|
|
3278
|
+
import { basename as basename3, dirname as dirname3, join as join5 } from "node:path";
|
|
3034
3279
|
var SKILL_MANIFEST = "SKILL.md";
|
|
3035
3280
|
var PRUNED_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git"]);
|
|
3036
3281
|
var KNOWN_FRONTMATTER_KEYS = /* @__PURE__ */ new Set(["name", "description", "license", "compatibility", "metadata", "allowed-tools", "disable-model-invocation"]);
|
|
@@ -3065,7 +3310,7 @@ function* walkLevel(dir, atRoot, seen) {
|
|
|
3065
3310
|
seen.add(real);
|
|
3066
3311
|
yield* walkLevel(full, false, seen);
|
|
3067
3312
|
}
|
|
3068
|
-
} else if (stats.isFile() && (atRoot && entry.toLowerCase().endsWith(".md") || !atRoot && entry === SKILL_MANIFEST)) yield { path: full, dirName: basename3(
|
|
3313
|
+
} else if (stats.isFile() && (atRoot && entry.toLowerCase().endsWith(".md") || !atRoot && entry === SKILL_MANIFEST)) yield { path: full, dirName: basename3(dirname3(full)) };
|
|
3069
3314
|
}
|
|
3070
3315
|
}
|
|
3071
3316
|
function checkName(name, dirName, fromDir) {
|
|
@@ -3104,7 +3349,7 @@ function describeCause(cause) {
|
|
|
3104
3349
|
function parseCandidate(candidate, origin) {
|
|
3105
3350
|
let text;
|
|
3106
3351
|
try {
|
|
3107
|
-
text =
|
|
3352
|
+
text = readFileSync3(candidate.path, "utf8");
|
|
3108
3353
|
} catch (cause) {
|
|
3109
3354
|
return { card: null, diagnostic: diag("invalid", candidate.path, `could not read the skill file (${describeCause(cause)})`) };
|
|
3110
3355
|
}
|
|
@@ -3155,49 +3400,52 @@ function modelInvocableCards(cards) {
|
|
|
3155
3400
|
}
|
|
3156
3401
|
|
|
3157
3402
|
// src/briefing/context-docs.ts
|
|
3158
|
-
import {
|
|
3159
|
-
import { dirname as
|
|
3403
|
+
import { closeSync as closeSync2, constants as constants2, fstatSync as fstatSync2, lstatSync as lstatSync2, openSync as openSync2, readFileSync as readFileSync4, realpathSync as realpathSync2 } from "node:fs";
|
|
3404
|
+
import { basename as basename4, dirname as dirname4, extname, isAbsolute as isAbsolute2, join as join6, parse, resolve as resolve2, sep } from "node:path";
|
|
3160
3405
|
var DEFAULT_MAX_IMPORT_DEPTH = 5;
|
|
3161
3406
|
var DEFAULT_MAX_BYTES_PER_DOC = 4e4;
|
|
3162
3407
|
var CANDIDATE_FILES = ["AGENTS.md", "CLAUDE.md", "INDUSAGI.md", "CLAUDE.local.md", "AGENTS.local.md", join6(".indusagi", "CLAUDE.md"), join6(".claude", "CLAUDE.md")];
|
|
3163
|
-
var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".markdown", ".txt", ".text", ".json", ".jsonc", ".yaml", ".yml", ".toml", ".xml", ".csv", ".html", ".htm", ".css", ".js", ".ts", ".tsx", ".jsx", ".mjs", ".cjs", ".mts", ".cts", ".py", ".rb", ".go", ".rs", ".sh"
|
|
3408
|
+
var TEXT_FILE_EXTENSIONS = /* @__PURE__ */ new Set([".md", ".markdown", ".txt", ".text", ".json", ".jsonc", ".yaml", ".yml", ".toml", ".xml", ".csv", ".html", ".htm", ".css", ".js", ".ts", ".tsx", ".jsx", ".mjs", ".cjs", ".mts", ".cts", ".py", ".rb", ".go", ".rs", ".sh"]);
|
|
3164
3409
|
var IMPORT_REGEX = /(?:^|\s)@((?:[^\s\\]|\\ )+)/g;
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3410
|
+
var NO_FOLLOW2 = constants2.O_NOFOLLOW ?? 0;
|
|
3411
|
+
var SECRET_BASENAMES = /* @__PURE__ */ new Set([
|
|
3412
|
+
".env",
|
|
3413
|
+
"credentials",
|
|
3414
|
+
"credentials.json",
|
|
3415
|
+
"id_rsa",
|
|
3416
|
+
"id_dsa",
|
|
3417
|
+
"id_ecdsa",
|
|
3418
|
+
"id_ed25519"
|
|
3419
|
+
]);
|
|
3420
|
+
var SECRET_EXTENSIONS = /* @__PURE__ */ new Set([".key", ".pem", ".p12", ".pfx"]);
|
|
3421
|
+
function shortenPath(path5, cwd, home) {
|
|
3422
|
+
if (cwd && (path5 === cwd || path5.startsWith(`${cwd}${sep}`))) {
|
|
3423
|
+
const rest = path5.slice(cwd.length).replace(/^[/\\]+/, "");
|
|
3168
3424
|
return rest ? `./${rest}` : ".";
|
|
3169
3425
|
}
|
|
3170
|
-
return home &&
|
|
3171
|
-
}
|
|
3172
|
-
function dirChain(cwd) {
|
|
3173
|
-
const chain = [];
|
|
3174
|
-
let current = cwd;
|
|
3175
|
-
for (let i = 0; i < 256; i++) {
|
|
3176
|
-
chain.push(current);
|
|
3177
|
-
const parent = dirname3(current);
|
|
3178
|
-
if (parent === current || current === parse(current).root) break;
|
|
3179
|
-
current = parent;
|
|
3180
|
-
}
|
|
3181
|
-
return chain.reverse();
|
|
3182
|
-
}
|
|
3183
|
-
function safeRealpath(path4) {
|
|
3184
|
-
try {
|
|
3185
|
-
return realpathSync2(path4);
|
|
3186
|
-
} catch {
|
|
3187
|
-
return path4;
|
|
3188
|
-
}
|
|
3426
|
+
return home && (path5 === home || path5.startsWith(`${home}${sep}`)) ? `~${path5.slice(home.length)}` : path5;
|
|
3189
3427
|
}
|
|
3190
|
-
function isTextFile(
|
|
3191
|
-
const extension = extname(
|
|
3428
|
+
function isTextFile(path5) {
|
|
3429
|
+
const extension = extname(path5).toLowerCase();
|
|
3192
3430
|
return !extension || TEXT_FILE_EXTENSIONS.has(extension);
|
|
3193
3431
|
}
|
|
3194
|
-
function
|
|
3195
|
-
|
|
3432
|
+
function isLikelySecretFile(path5) {
|
|
3433
|
+
const name = basename4(path5).toLowerCase();
|
|
3434
|
+
return SECRET_BASENAMES.has(name) || name.startsWith(".env.") || SECRET_EXTENSIONS.has(extname(name));
|
|
3435
|
+
}
|
|
3436
|
+
function readFileBody(path5) {
|
|
3437
|
+
let fd;
|
|
3196
3438
|
try {
|
|
3197
|
-
const
|
|
3439
|
+
const before = lstatSync2(path5);
|
|
3440
|
+
if (before.isSymbolicLink() || !before.isFile()) return null;
|
|
3441
|
+
fd = openSync2(path5, constants2.O_RDONLY | NO_FOLLOW2);
|
|
3442
|
+
if (!fstatSync2(fd).isFile()) return null;
|
|
3443
|
+
const body = readFileSync4(fd, "utf8").trim();
|
|
3198
3444
|
return body || null;
|
|
3199
3445
|
} catch {
|
|
3200
3446
|
return null;
|
|
3447
|
+
} finally {
|
|
3448
|
+
if (fd !== void 0) closeSync2(fd);
|
|
3201
3449
|
}
|
|
3202
3450
|
}
|
|
3203
3451
|
function extractImports(body, baseDir, home) {
|
|
@@ -3216,23 +3464,46 @@ function extractImports(body, baseDir, home) {
|
|
|
3216
3464
|
}
|
|
3217
3465
|
return out2;
|
|
3218
3466
|
}
|
|
3219
|
-
function
|
|
3220
|
-
|
|
3221
|
-
|
|
3467
|
+
function canonicalExistingFile(path5) {
|
|
3468
|
+
try {
|
|
3469
|
+
const before = lstatSync2(path5);
|
|
3470
|
+
if (before.isSymbolicLink() || !before.isFile()) return null;
|
|
3471
|
+
return realpathSync2(path5);
|
|
3472
|
+
} catch {
|
|
3473
|
+
return null;
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
function isWithin(root, candidate) {
|
|
3477
|
+
return candidate === root || candidate.startsWith(`${root}${sep}`);
|
|
3478
|
+
}
|
|
3479
|
+
function loadTrustedDocTree(path5, cwd, home, seen, depth, maxDepth, maxBytes, out2, policy) {
|
|
3480
|
+
if (isLikelySecretFile(path5)) return;
|
|
3481
|
+
const real = canonicalExistingFile(path5);
|
|
3482
|
+
if (real === null || seen.has(real) || isLikelySecretFile(real)) return;
|
|
3483
|
+
if (!isWithin(policy.root, real) && !policy.approvedExternal.has(real)) return;
|
|
3222
3484
|
seen.add(real);
|
|
3223
|
-
const body = readFileBody(
|
|
3485
|
+
const body = readFileBody(real);
|
|
3224
3486
|
if (body === null) return;
|
|
3225
|
-
out2.push({ path: shortenPath(
|
|
3487
|
+
out2.push({ path: shortenPath(real, cwd, home), body: body.length > maxBytes ? body.slice(0, maxBytes) : body });
|
|
3226
3488
|
if (depth >= maxDepth) return;
|
|
3227
|
-
for (const child of extractImports(body,
|
|
3489
|
+
for (const child of extractImports(body, dirname4(real), home)) {
|
|
3490
|
+
loadTrustedDocTree(child, cwd, home, seen, depth + 1, maxDepth, maxBytes, out2, policy);
|
|
3491
|
+
}
|
|
3228
3492
|
}
|
|
3229
|
-
function gatherContextDocs(cwd, home, opts) {
|
|
3493
|
+
function gatherContextDocs(cwd, home, opts = {}) {
|
|
3230
3494
|
const out2 = [];
|
|
3231
3495
|
try {
|
|
3496
|
+
const root = realpathSync2(cwd);
|
|
3497
|
+
const approvedExternal = /* @__PURE__ */ new Set();
|
|
3498
|
+
for (const path5 of opts.approvedExternalPaths ?? []) {
|
|
3499
|
+
const real = canonicalExistingFile(path5);
|
|
3500
|
+
if (real !== null && !isLikelySecretFile(real)) approvedExternal.add(real);
|
|
3501
|
+
}
|
|
3502
|
+
const policy = { root, approvedExternal };
|
|
3232
3503
|
const seen = /* @__PURE__ */ new Set();
|
|
3233
|
-
const
|
|
3234
|
-
|
|
3235
|
-
|
|
3504
|
+
for (const name of CANDIDATE_FILES) {
|
|
3505
|
+
loadTrustedDocTree(join6(root, name), root, home, seen, 0, opts.maxImportDepth ?? DEFAULT_MAX_IMPORT_DEPTH, opts.maxBytesPerDoc ?? DEFAULT_MAX_BYTES_PER_DOC, out2, policy);
|
|
3506
|
+
}
|
|
3236
3507
|
} catch {
|
|
3237
3508
|
return out2;
|
|
3238
3509
|
}
|
|
@@ -3345,9 +3616,9 @@ function buildDynamicCommands(sources = {}) {
|
|
|
3345
3616
|
|
|
3346
3617
|
// src/console/slash/commands/integrations.ts
|
|
3347
3618
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
3348
|
-
import {
|
|
3349
|
-
import {
|
|
3350
|
-
import {
|
|
3619
|
+
import { getEnvApiKey as getEnvApiKey2 } from "indusagi/ai";
|
|
3620
|
+
import { writeFileSync as writeFileSync4 } from "node:fs";
|
|
3621
|
+
import { resolve as resolve5 } from "node:path";
|
|
3351
3622
|
import { createMCPAgentToolFactory, loadMCPConfig, MCPClientPool } from "indusagi/mcp";
|
|
3352
3623
|
import { createComposioGateway } from "indusagi/connectors-saas";
|
|
3353
3624
|
|
|
@@ -4467,14 +4738,14 @@ var DaemonTable = class {
|
|
|
4467
4738
|
if (handle.state !== "running") return;
|
|
4468
4739
|
const child = handle.child;
|
|
4469
4740
|
child.kill("SIGTERM");
|
|
4470
|
-
await new Promise((
|
|
4741
|
+
await new Promise((resolve11) => {
|
|
4471
4742
|
const timer = setTimeout(() => {
|
|
4472
4743
|
if (handle.state === "running") child.kill("SIGKILL");
|
|
4473
|
-
|
|
4744
|
+
resolve11();
|
|
4474
4745
|
}, graceMs);
|
|
4475
4746
|
child.once("exit", () => {
|
|
4476
4747
|
clearTimeout(timer);
|
|
4477
|
-
|
|
4748
|
+
resolve11();
|
|
4478
4749
|
});
|
|
4479
4750
|
});
|
|
4480
4751
|
}
|
|
@@ -5218,7 +5489,7 @@ function createLimiter(limit) {
|
|
|
5218
5489
|
queue.shift()?.();
|
|
5219
5490
|
};
|
|
5220
5491
|
return async (fn) => {
|
|
5221
|
-
if (active >= limit) await new Promise((
|
|
5492
|
+
if (active >= limit) await new Promise((resolve11) => queue.push(resolve11));
|
|
5222
5493
|
active++;
|
|
5223
5494
|
try {
|
|
5224
5495
|
return await fn();
|
|
@@ -5284,6 +5555,56 @@ import { Agent } from "indusagi/agent";
|
|
|
5284
5555
|
import { createZeroUsage as createZeroUsage2 } from "indusagi/ai";
|
|
5285
5556
|
import * as path3 from "node:path";
|
|
5286
5557
|
|
|
5558
|
+
// src/kit/run-shell.ts
|
|
5559
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
5560
|
+
function runShell(command, cwd, signal) {
|
|
5561
|
+
if (signal?.aborted) return Promise.resolve({ output: "Command cancelled.", exitCode: 130 });
|
|
5562
|
+
return new Promise((resolve11) => {
|
|
5563
|
+
let output = "", truncated = false, settled = false;
|
|
5564
|
+
let forceKill;
|
|
5565
|
+
const child = spawn3(command, { cwd, shell: true, detached: process.platform !== "win32" });
|
|
5566
|
+
const capture = (chunk) => {
|
|
5567
|
+
output += String(chunk);
|
|
5568
|
+
if (output.length > 1024 * 1024) {
|
|
5569
|
+
output = output.slice(-1024 * 1024);
|
|
5570
|
+
truncated = true;
|
|
5571
|
+
}
|
|
5572
|
+
};
|
|
5573
|
+
const kill = (signalName) => {
|
|
5574
|
+
try {
|
|
5575
|
+
if (process.platform !== "win32" && child.pid) process.kill(-child.pid, signalName);
|
|
5576
|
+
else child.kill(signalName);
|
|
5577
|
+
} catch {
|
|
5578
|
+
try {
|
|
5579
|
+
child.kill(signalName);
|
|
5580
|
+
} catch {
|
|
5581
|
+
}
|
|
5582
|
+
}
|
|
5583
|
+
};
|
|
5584
|
+
const abort = () => {
|
|
5585
|
+
kill("SIGTERM");
|
|
5586
|
+
forceKill = setTimeout(() => kill("SIGKILL"), 1e3);
|
|
5587
|
+
forceKill.unref();
|
|
5588
|
+
};
|
|
5589
|
+
const finish = (exitCode) => {
|
|
5590
|
+
if (settled) return;
|
|
5591
|
+
settled = true;
|
|
5592
|
+
signal?.removeEventListener("abort", abort);
|
|
5593
|
+
if (forceKill) clearTimeout(forceKill);
|
|
5594
|
+
resolve11({ output: (truncated ? "[older output truncated]\n" : "") + output, exitCode: signal?.aborted ? 130 : exitCode });
|
|
5595
|
+
};
|
|
5596
|
+
child.stdout?.on("data", capture);
|
|
5597
|
+
child.stderr?.on("data", capture);
|
|
5598
|
+
child.once("error", (error) => {
|
|
5599
|
+
capture(error.message);
|
|
5600
|
+
finish(1);
|
|
5601
|
+
});
|
|
5602
|
+
child.once("close", (code) => finish(code ?? 1));
|
|
5603
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
5604
|
+
if (signal?.aborted) abort();
|
|
5605
|
+
});
|
|
5606
|
+
}
|
|
5607
|
+
|
|
5287
5608
|
// src/conductor/catalog/catalog.ts
|
|
5288
5609
|
import { z } from "zod";
|
|
5289
5610
|
import { getModels, getProviders, modelRegistry } from "indusagi/ai";
|
|
@@ -5711,30 +6032,21 @@ function memoryBackend() {
|
|
|
5711
6032
|
}
|
|
5712
6033
|
function fsBackend(dir) {
|
|
5713
6034
|
const fileOf = async (sessionId) => {
|
|
5714
|
-
const
|
|
5715
|
-
return
|
|
6035
|
+
const path5 = await import("node:path");
|
|
6036
|
+
return path5.join(dir, `${sessionId}.ndjson`);
|
|
5716
6037
|
};
|
|
5717
6038
|
return {
|
|
5718
6039
|
locate: (sessionId) => `${dir}/${sessionId}.ndjson`,
|
|
5719
6040
|
read: async (sessionId) => {
|
|
5720
|
-
|
|
5721
|
-
try {
|
|
5722
|
-
return await fs3.readFile(await fileOf(sessionId), "utf8");
|
|
5723
|
-
} catch {
|
|
5724
|
-
return null;
|
|
5725
|
-
}
|
|
6041
|
+
return readPrivateFileSync(await fileOf(sessionId));
|
|
5726
6042
|
},
|
|
5727
6043
|
append: async (sessionId, line) => {
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
await fs3.appendFile(await fileOf(sessionId), `${line}
|
|
5731
|
-
`, "utf8");
|
|
6044
|
+
appendPrivateFileSync(await fileOf(sessionId), `${line}
|
|
6045
|
+
`);
|
|
5732
6046
|
},
|
|
5733
6047
|
rewrite: async (sessionId, text) => {
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
await fs3.writeFile(await fileOf(sessionId), text.length === 0 ? "" : `${text}
|
|
5737
|
-
`, "utf8");
|
|
6048
|
+
atomicWritePrivateFileSync(await fileOf(sessionId), text.length === 0 ? "" : `${text}
|
|
6049
|
+
`);
|
|
5738
6050
|
}
|
|
5739
6051
|
};
|
|
5740
6052
|
}
|
|
@@ -6372,7 +6684,10 @@ async function summarize(messages, deps = {}) {
|
|
|
6372
6684
|
const digest2 = localFallbackDigest(messages, deps.priorDigest);
|
|
6373
6685
|
return { message: toSummaryMessage(digest2, scope), coveredCount };
|
|
6374
6686
|
}
|
|
6375
|
-
const prompt = buildSummaryPrompt(messages, scope, deps.priorDigest)
|
|
6687
|
+
const prompt = buildSummaryPrompt(messages, scope, deps.priorDigest) + (deps.instructions ? `
|
|
6688
|
+
|
|
6689
|
+
User compaction guidance:
|
|
6690
|
+
${deps.instructions}` : "");
|
|
6376
6691
|
const context = {
|
|
6377
6692
|
systemPrompt: CONDENSER_BRIEF,
|
|
6378
6693
|
messages: [{ role: "user", content: prompt, timestamp: Date.now() }]
|
|
@@ -6496,8 +6811,8 @@ function collectVisibleReadPaths(kept, readToolName) {
|
|
|
6496
6811
|
if (!isRecord4(block2) || block2.type !== "toolCall") continue;
|
|
6497
6812
|
if (block2.name !== readToolName) continue;
|
|
6498
6813
|
const args = isRecord4(block2.arguments) ? block2.arguments : void 0;
|
|
6499
|
-
const
|
|
6500
|
-
if (
|
|
6814
|
+
const path5 = args && typeof args.path === "string" ? args.path : "";
|
|
6815
|
+
if (path5.length > 0) paths.add(path5);
|
|
6501
6816
|
}
|
|
6502
6817
|
}
|
|
6503
6818
|
return paths;
|
|
@@ -6513,8 +6828,8 @@ function collectDroppedReads(dropped, readToolName) {
|
|
|
6513
6828
|
if (block2.name !== readToolName) continue;
|
|
6514
6829
|
const id = typeof block2.id === "string" ? block2.id : "";
|
|
6515
6830
|
const args = isRecord4(block2.arguments) ? block2.arguments : void 0;
|
|
6516
|
-
const
|
|
6517
|
-
if (id.length > 0 &&
|
|
6831
|
+
const path5 = args && typeof args.path === "string" ? args.path : "";
|
|
6832
|
+
if (id.length > 0 && path5.length > 0) calls.set(id, { path: path5, order: i });
|
|
6518
6833
|
}
|
|
6519
6834
|
}
|
|
6520
6835
|
if (calls.size === 0) return [];
|
|
@@ -6565,7 +6880,7 @@ ${read.body}`,
|
|
|
6565
6880
|
|
|
6566
6881
|
// src/conductor/diagnostics.ts
|
|
6567
6882
|
import * as path2 from "node:path";
|
|
6568
|
-
import { existsSync
|
|
6883
|
+
import { existsSync } from "node:fs";
|
|
6569
6884
|
var MAX_PER_FILE = 10;
|
|
6570
6885
|
var MAX_TOTAL = 30;
|
|
6571
6886
|
var DELIVERED_KEYS_CAP = 500;
|
|
@@ -6622,18 +6937,18 @@ async function loadSpawn() {
|
|
|
6622
6937
|
return void 0;
|
|
6623
6938
|
}
|
|
6624
6939
|
}
|
|
6625
|
-
function captureOutput(
|
|
6626
|
-
return new Promise((
|
|
6940
|
+
function captureOutput(spawn4, bin, args, cwd, signal) {
|
|
6941
|
+
return new Promise((resolve11) => {
|
|
6627
6942
|
let settled = false;
|
|
6628
6943
|
const finish = (value) => {
|
|
6629
6944
|
if (!settled) {
|
|
6630
6945
|
settled = true;
|
|
6631
|
-
|
|
6946
|
+
resolve11(value);
|
|
6632
6947
|
}
|
|
6633
6948
|
};
|
|
6634
6949
|
let child;
|
|
6635
6950
|
try {
|
|
6636
|
-
child =
|
|
6951
|
+
child = spawn4(bin, args, { cwd, shell: false });
|
|
6637
6952
|
} catch {
|
|
6638
6953
|
finish();
|
|
6639
6954
|
return;
|
|
@@ -6662,9 +6977,9 @@ function captureOutput(spawn3, bin, args, cwd, signal) {
|
|
|
6662
6977
|
});
|
|
6663
6978
|
}
|
|
6664
6979
|
async function runTscDiagnostics(cwd, signal) {
|
|
6665
|
-
const
|
|
6666
|
-
if (!
|
|
6667
|
-
const output = await captureOutput(
|
|
6980
|
+
const spawn4 = await loadSpawn();
|
|
6981
|
+
if (!spawn4 || signal?.aborted) return [];
|
|
6982
|
+
const output = await captureOutput(spawn4, path2.join(cwd, "node_modules", ".bin", "tsc"), ["--noEmit", "--pretty", "false"], cwd, signal);
|
|
6668
6983
|
return output === void 0 ? [] : parseTscOutput(output, cwd);
|
|
6669
6984
|
}
|
|
6670
6985
|
function parseTscOutput(output, cwd) {
|
|
@@ -6684,9 +6999,9 @@ function parseTscOutput(output, cwd) {
|
|
|
6684
6999
|
}
|
|
6685
7000
|
async function runEslintDiagnostics(files, cwd, signal) {
|
|
6686
7001
|
if (files.length === 0) return [];
|
|
6687
|
-
const
|
|
6688
|
-
if (!
|
|
6689
|
-
const output = await captureOutput(
|
|
7002
|
+
const spawn4 = await loadSpawn();
|
|
7003
|
+
if (!spawn4 || signal?.aborted) return [];
|
|
7004
|
+
const output = await captureOutput(spawn4, path2.join(cwd, "node_modules", ".bin", "eslint"), ["--format", "json", ...files], cwd, signal);
|
|
6690
7005
|
return output === void 0 ? [] : parseEslintOutput(output, cwd);
|
|
6691
7006
|
}
|
|
6692
7007
|
function parseEslintOutput(output, cwd) {
|
|
@@ -6793,14 +7108,14 @@ function isTypeScriptOrJs(filePath) {
|
|
|
6793
7108
|
}
|
|
6794
7109
|
function hasTsConfig(cwd) {
|
|
6795
7110
|
try {
|
|
6796
|
-
return
|
|
7111
|
+
return existsSync(path2.join(cwd, "tsconfig.json"));
|
|
6797
7112
|
} catch {
|
|
6798
7113
|
return false;
|
|
6799
7114
|
}
|
|
6800
7115
|
}
|
|
6801
7116
|
function hasEslintConfig(cwd) {
|
|
6802
7117
|
try {
|
|
6803
|
-
return ["eslint.config.js", "eslint.config.mjs", "eslint.config.cjs", ".eslintrc", ".eslintrc.js", ".eslintrc.cjs", ".eslintrc.json", ".eslintrc.yml", ".eslintrc.yaml"].some((name) =>
|
|
7118
|
+
return ["eslint.config.js", "eslint.config.mjs", "eslint.config.cjs", ".eslintrc", ".eslintrc.js", ".eslintrc.cjs", ".eslintrc.json", ".eslintrc.yml", ".eslintrc.yaml"].some((name) => existsSync(path2.join(cwd, name)));
|
|
6804
7119
|
} catch {
|
|
6805
7120
|
return false;
|
|
6806
7121
|
}
|
|
@@ -6951,6 +7266,8 @@ var SessionConductorImpl = class {
|
|
|
6951
7266
|
#matcher;
|
|
6952
7267
|
#state;
|
|
6953
7268
|
#busy = false;
|
|
7269
|
+
#activeWork;
|
|
7270
|
+
#shellAbort;
|
|
6954
7271
|
#draining = false;
|
|
6955
7272
|
#queue = [];
|
|
6956
7273
|
#boundModel;
|
|
@@ -7010,6 +7327,7 @@ var SessionConductorImpl = class {
|
|
|
7010
7327
|
abort() {
|
|
7011
7328
|
this.clearQueue();
|
|
7012
7329
|
this.#condenseAbort?.abort();
|
|
7330
|
+
this.#shellAbort?.abort();
|
|
7013
7331
|
this.agent.abort();
|
|
7014
7332
|
const fault = conductorFault("aborted", "turn aborted by caller");
|
|
7015
7333
|
this.#dispatch({ type: "fault", fault });
|
|
@@ -7022,13 +7340,22 @@ var SessionConductorImpl = class {
|
|
|
7022
7340
|
return this.#state;
|
|
7023
7341
|
}
|
|
7024
7342
|
this.#busy = true;
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7343
|
+
const work = (async () => {
|
|
7344
|
+
try {
|
|
7345
|
+
await this.#runTurn(input);
|
|
7346
|
+
await this.#drainQueue();
|
|
7347
|
+
return this.#state;
|
|
7348
|
+
} finally {
|
|
7349
|
+
this.#busy = false;
|
|
7350
|
+
}
|
|
7351
|
+
})();
|
|
7352
|
+
this.#activeWork = work;
|
|
7353
|
+
return work;
|
|
7354
|
+
}
|
|
7355
|
+
async #stopWork() {
|
|
7356
|
+
if (!this.#busy) return;
|
|
7357
|
+
this.abort();
|
|
7358
|
+
await this.#activeWork;
|
|
7032
7359
|
}
|
|
7033
7360
|
async #drainQueue() {
|
|
7034
7361
|
if (this.#draining) return;
|
|
@@ -7066,7 +7393,7 @@ var SessionConductorImpl = class {
|
|
|
7066
7393
|
}
|
|
7067
7394
|
if (attempt < (this.deps.retry ?? DEFAULT_RETRY).maxAttempts && isTransient(error)) {
|
|
7068
7395
|
this.#hub.emit({ kind: "fault", fault: conductorFault("model", `transient model fault; retry ${attempt + 1}`, error), transient: true });
|
|
7069
|
-
await (this.deps.sleep ?? ((ms) => new Promise((
|
|
7396
|
+
await (this.deps.sleep ?? ((ms) => new Promise((resolve11) => setTimeout(resolve11, ms))))((this.deps.retry ?? DEFAULT_RETRY).baseDelayMs * 2 ** attempt);
|
|
7070
7397
|
continue;
|
|
7071
7398
|
}
|
|
7072
7399
|
if (isOverloadFault(error) && this.options.fallbackModelId) this.selectModel(this.options.fallbackModelId);
|
|
@@ -7117,8 +7444,16 @@ var SessionConductorImpl = class {
|
|
|
7117
7444
|
}
|
|
7118
7445
|
this.#applyModel(card);
|
|
7119
7446
|
}
|
|
7120
|
-
cycleModel(id) {
|
|
7121
|
-
|
|
7447
|
+
cycleModel(id, direction = 1) {
|
|
7448
|
+
if (id.trim()) {
|
|
7449
|
+
this.selectModel(id);
|
|
7450
|
+
return;
|
|
7451
|
+
}
|
|
7452
|
+
const cards = this.availableModels();
|
|
7453
|
+
if (!cards.length) return;
|
|
7454
|
+
const at = cards.findIndex((card) => card.id === this.#state.modelId);
|
|
7455
|
+
const index = at < 0 ? 0 : (at + direction + cards.length) % cards.length;
|
|
7456
|
+
this.selectModel(cards[index].id);
|
|
7122
7457
|
}
|
|
7123
7458
|
#applyModel(card) {
|
|
7124
7459
|
const model = withGatewayBaseUrl(card.model, this.#gatewayBaseUrls);
|
|
@@ -7133,28 +7468,36 @@ var SessionConductorImpl = class {
|
|
|
7133
7468
|
registerTools(tools) {
|
|
7134
7469
|
this.agent.setTools([...this.#deckTools, ...tools]);
|
|
7135
7470
|
}
|
|
7136
|
-
async condense() {
|
|
7471
|
+
async condense(instructions) {
|
|
7137
7472
|
if (this.#busy) return "busy";
|
|
7138
7473
|
this.#busy = true;
|
|
7139
7474
|
this.#condenseAbort = new AbortController();
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7475
|
+
const work = (async () => {
|
|
7476
|
+
try {
|
|
7477
|
+
const result = await this.#runCondense(true, this.#condenseAbort.signal, instructions);
|
|
7478
|
+
await this.#drainQueue();
|
|
7479
|
+
return result;
|
|
7480
|
+
} finally {
|
|
7481
|
+
this.#busy = false;
|
|
7482
|
+
this.#condenseAbort = void 0;
|
|
7483
|
+
}
|
|
7484
|
+
})();
|
|
7485
|
+
this.#activeWork = work;
|
|
7486
|
+
return work;
|
|
7148
7487
|
}
|
|
7149
7488
|
cancelCondense() {
|
|
7150
7489
|
this.#condenseAbort?.abort();
|
|
7151
7490
|
}
|
|
7152
|
-
async #runCondense(force, signal) {
|
|
7491
|
+
async #runCondense(force, signal, instructions) {
|
|
7153
7492
|
const before = [...this.agent.state.messages];
|
|
7154
7493
|
this.#dispatch({ type: "phase", phase: "condensing" });
|
|
7155
7494
|
try {
|
|
7156
|
-
const after = await (this.deps.condense ?? noopCondense)(before, { force, model: this.#boundModel, contextTokens: this.#state.contextTokens, signal });
|
|
7157
|
-
if (signal?.aborted)
|
|
7495
|
+
const after = await (this.deps.condense ?? noopCondense)(before, { force, model: this.#boundModel, contextTokens: this.#state.contextTokens, signal, instructions });
|
|
7496
|
+
if (signal?.aborted) {
|
|
7497
|
+
this.#dispatch({ type: "settled" });
|
|
7498
|
+
this.#hub.emit({ kind: "idle" });
|
|
7499
|
+
return "cancelled";
|
|
7500
|
+
}
|
|
7158
7501
|
if (after.length >= before.length) {
|
|
7159
7502
|
this.#dispatch({ type: "settled" });
|
|
7160
7503
|
return "nothing";
|
|
@@ -7181,10 +7524,12 @@ var SessionConductorImpl = class {
|
|
|
7181
7524
|
}
|
|
7182
7525
|
async #move(id, message) {
|
|
7183
7526
|
try {
|
|
7527
|
+
await this.#stopWork();
|
|
7184
7528
|
await this.store.branchAt(id);
|
|
7185
7529
|
this.agent.replaceMessages(this.store.messages());
|
|
7186
7530
|
this.#dispatch({ type: "head", head: this.store.head });
|
|
7187
7531
|
this.#dispatch({ type: "settled" });
|
|
7532
|
+
this.#hub.emit({ kind: "reset" });
|
|
7188
7533
|
this.#hub.emit({ kind: "idle" });
|
|
7189
7534
|
} catch (error) {
|
|
7190
7535
|
const fault = conductorFault("persistence", message, error);
|
|
@@ -7199,18 +7544,33 @@ var SessionConductorImpl = class {
|
|
|
7199
7544
|
return { canRestore: this.options.checkpoint?.hasSnapshot(id) ?? false };
|
|
7200
7545
|
}
|
|
7201
7546
|
async executeBash(command, opts = {}) {
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
${outcome.output}`.trimEnd(), timestamp: Date.now() }
|
|
7213
|
-
|
|
7547
|
+
if (this.#busy) throw new Error("A turn is running \u2014 stop it before running a shell command.");
|
|
7548
|
+
this.#busy = true;
|
|
7549
|
+
this.#shellAbort = new AbortController();
|
|
7550
|
+
const signal = opts.signal ? AbortSignal.any([opts.signal, this.#shellAbort.signal]) : this.#shellAbort.signal;
|
|
7551
|
+
const work = (async () => {
|
|
7552
|
+
try {
|
|
7553
|
+
this.#dispatch({ type: "phase", phase: "tooling" });
|
|
7554
|
+
const outcome = await runShell(command, this.#workspace, signal);
|
|
7555
|
+
if (!opts.excludeFromContext) {
|
|
7556
|
+
const message = { role: "user", content: `$ ${command}
|
|
7557
|
+
${outcome.output}`.trimEnd(), timestamp: Date.now() };
|
|
7558
|
+
const entry = await this.store.append(message, "note");
|
|
7559
|
+
this.agent.replaceMessages([...this.agent.state.messages, message]);
|
|
7560
|
+
this.#dispatch({ type: "head", head: this.store.head });
|
|
7561
|
+
this.#hub.emit({ kind: "persisted", entryId: entry.id });
|
|
7562
|
+
}
|
|
7563
|
+
this.#dispatch({ type: "settled" });
|
|
7564
|
+
this.#hub.emit({ kind: "idle" });
|
|
7565
|
+
await this.#drainQueue();
|
|
7566
|
+
return outcome;
|
|
7567
|
+
} finally {
|
|
7568
|
+
this.#busy = false;
|
|
7569
|
+
this.#shellAbort = void 0;
|
|
7570
|
+
}
|
|
7571
|
+
})();
|
|
7572
|
+
this.#activeWork = work;
|
|
7573
|
+
return work;
|
|
7214
7574
|
}
|
|
7215
7575
|
stats() {
|
|
7216
7576
|
const messages = this.agent.state.messages;
|
|
@@ -7280,6 +7640,7 @@ ${outcome.output}`.trimEnd(), timestamp: Date.now() }, "note");
|
|
|
7280
7640
|
this.#sessionName = name;
|
|
7281
7641
|
}
|
|
7282
7642
|
async resume(id) {
|
|
7643
|
+
await this.#stopWork();
|
|
7283
7644
|
if (!await this.store.load(id)) {
|
|
7284
7645
|
const fault = conductorFault("persistence", `no session "${id}" to resume`);
|
|
7285
7646
|
this.#dispatch({ type: "fault", fault });
|
|
@@ -7288,19 +7649,23 @@ ${outcome.output}`.trimEnd(), timestamp: Date.now() }, "note");
|
|
|
7288
7649
|
}
|
|
7289
7650
|
this.agent.replaceMessages(this.store.messages());
|
|
7290
7651
|
this.#state = { ...this.#state, head: this.store.head, usage: this.store.usage ?? createZeroUsage2(), phase: "idle" };
|
|
7652
|
+
this.#hub.emit({ kind: "reset" });
|
|
7291
7653
|
this.#hub.emit({ kind: "idle" });
|
|
7292
7654
|
}
|
|
7293
7655
|
async newSession() {
|
|
7294
|
-
this
|
|
7656
|
+
await this.#stopWork();
|
|
7295
7657
|
this.agent.replaceMessages([]);
|
|
7296
7658
|
this.store.startNewSession(newSessionId());
|
|
7297
7659
|
this.#queue.length = 0;
|
|
7298
7660
|
this.#sessionName = void 0;
|
|
7299
7661
|
this.#state = { phase: "idle", head: this.store.head, usage: createZeroUsage2(), contextTokens: 0, modelId: this.#state.modelId };
|
|
7662
|
+
this.#hub.emit({ kind: "reset" });
|
|
7300
7663
|
this.#hub.emit({ kind: "idle" });
|
|
7301
7664
|
}
|
|
7302
7665
|
#dispatch(action) {
|
|
7666
|
+
const phase = this.#state.phase;
|
|
7303
7667
|
this.#state = reduceState(this.#state, action);
|
|
7668
|
+
if (phase !== this.#state.phase) this.#hub.emit({ kind: "phase", phase: this.#state.phase });
|
|
7304
7669
|
}
|
|
7305
7670
|
};
|
|
7306
7671
|
|
|
@@ -8068,7 +8433,7 @@ var SETTING_KEYS = Object.freeze(
|
|
|
8068
8433
|
|
|
8069
8434
|
// src/kit/clipboard-image.ts
|
|
8070
8435
|
import { spawnSync } from "node:child_process";
|
|
8071
|
-
import { readFileSync as
|
|
8436
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "node:fs";
|
|
8072
8437
|
import { tmpdir } from "node:os";
|
|
8073
8438
|
import { join as join8 } from "node:path";
|
|
8074
8439
|
var READ_TIMEOUT_MS = 3e3;
|
|
@@ -8113,10 +8478,10 @@ function captureViaOsascript() {
|
|
|
8113
8478
|
{ timeout: READ_TIMEOUT_MS, encoding: "utf8" }
|
|
8114
8479
|
);
|
|
8115
8480
|
if (result.error || result.status !== 0) return null;
|
|
8116
|
-
const
|
|
8117
|
-
if (
|
|
8481
|
+
const path5 = String(result.stdout ?? "").trim();
|
|
8482
|
+
if (path5.length === 0) return null;
|
|
8118
8483
|
try {
|
|
8119
|
-
const bytes =
|
|
8484
|
+
const bytes = readFileSync5(path5);
|
|
8120
8485
|
return bytes.length > 0 ? bytes : null;
|
|
8121
8486
|
} catch {
|
|
8122
8487
|
return null;
|
|
@@ -8147,10 +8512,10 @@ function readClipboardImage(options = {}) {
|
|
|
8147
8512
|
if (bytes === null) return null;
|
|
8148
8513
|
const dir = options.dir ?? tmpdir();
|
|
8149
8514
|
const name = `indus-clipboard-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}.png`;
|
|
8150
|
-
const
|
|
8515
|
+
const path5 = join8(dir, name);
|
|
8151
8516
|
try {
|
|
8152
|
-
|
|
8153
|
-
return
|
|
8517
|
+
writeFileSync2(path5, bytes);
|
|
8518
|
+
return path5;
|
|
8154
8519
|
} catch {
|
|
8155
8520
|
return null;
|
|
8156
8521
|
}
|
|
@@ -8158,7 +8523,7 @@ function readClipboardImage(options = {}) {
|
|
|
8158
8523
|
|
|
8159
8524
|
// src/kit/external-editor.ts
|
|
8160
8525
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
8161
|
-
import { readFileSync as
|
|
8526
|
+
import { readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
8162
8527
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
8163
8528
|
import { join as join9 } from "node:path";
|
|
8164
8529
|
var FALLBACK_EDITOR = "vi";
|
|
@@ -8171,18 +8536,28 @@ function openInExternalEditor(buffer, options = {}) {
|
|
|
8171
8536
|
const env2 = options.env ?? process.env;
|
|
8172
8537
|
const dir = options.dir ?? tmpdir2();
|
|
8173
8538
|
const name = `indus-editor-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}.md`;
|
|
8174
|
-
const
|
|
8539
|
+
const path5 = join9(dir, name);
|
|
8175
8540
|
const [editor, ...editorArgs] = resolveEditor(env2);
|
|
8176
8541
|
try {
|
|
8177
|
-
|
|
8178
|
-
const
|
|
8542
|
+
writeFileSync3(path5, buffer, "utf8");
|
|
8543
|
+
const terminal = options.terminal ?? { stdin: process.stdin, stdout: process.stdout };
|
|
8544
|
+
const wasRaw = terminal.stdin.isRaw === true;
|
|
8545
|
+
let result;
|
|
8546
|
+
try {
|
|
8547
|
+
terminal.stdin.setRawMode?.(false);
|
|
8548
|
+
if (terminal.stdout.isTTY) terminal.stdout.write("\x1B[?1049h\x1B[?25h");
|
|
8549
|
+
result = spawnSync2(editor, [...editorArgs, path5], { stdio: "inherit" });
|
|
8550
|
+
} finally {
|
|
8551
|
+
if (terminal.stdout.isTTY) terminal.stdout.write("\x1B[?1049l\x1B[?25l");
|
|
8552
|
+
terminal.stdin.setRawMode?.(wasRaw);
|
|
8553
|
+
}
|
|
8179
8554
|
if (result.error || result.status !== 0) return null;
|
|
8180
|
-
return
|
|
8555
|
+
return readFileSync6(path5, "utf8").replace(/\n$/, "");
|
|
8181
8556
|
} catch {
|
|
8182
8557
|
return null;
|
|
8183
8558
|
} finally {
|
|
8184
8559
|
try {
|
|
8185
|
-
unlinkSync(
|
|
8560
|
+
unlinkSync(path5);
|
|
8186
8561
|
} catch {
|
|
8187
8562
|
}
|
|
8188
8563
|
}
|
|
@@ -8832,6 +9207,7 @@ function lastAssistantText(messages) {
|
|
|
8832
9207
|
return "";
|
|
8833
9208
|
}
|
|
8834
9209
|
function toPublishRole(role) {
|
|
9210
|
+
if (role === "toolResult") return "tool";
|
|
8835
9211
|
return PUBLISH_ROLES.has(role) ? role : "note";
|
|
8836
9212
|
}
|
|
8837
9213
|
function toPublishEntries(messages) {
|
|
@@ -8862,7 +9238,7 @@ function exportTranscriptHtml(ctx, target) {
|
|
|
8862
9238
|
const html = publishTranscript(toPublishEntries(messages), {
|
|
8863
9239
|
title: "Session Transcript"
|
|
8864
9240
|
});
|
|
8865
|
-
|
|
9241
|
+
writeFileSync4(outPath, html, "utf-8");
|
|
8866
9242
|
return { ok: true, path: outPath };
|
|
8867
9243
|
} catch (cause) {
|
|
8868
9244
|
const message = cause instanceof Error ? cause.message : String(cause);
|
|
@@ -9253,13 +9629,11 @@ function runLogin2(ctx) {
|
|
|
9253
9629
|
}
|
|
9254
9630
|
return HANDLED;
|
|
9255
9631
|
}
|
|
9256
|
-
function hasLocalProviderKey(provider) {
|
|
9257
|
-
if (provider
|
|
9632
|
+
async function hasLocalProviderKey(provider, ctx) {
|
|
9633
|
+
if (!provider) return false;
|
|
9258
9634
|
try {
|
|
9259
|
-
|
|
9260
|
-
|
|
9261
|
-
const entry = vault[provider];
|
|
9262
|
-
return entry !== null && typeof entry === "object" && Object.keys(entry).length > 0;
|
|
9635
|
+
if (getEnvApiKey2(provider)) return true;
|
|
9636
|
+
return (await ctx.services?.vault.listAccounts(provider) ?? []).length > 0;
|
|
9263
9637
|
} catch {
|
|
9264
9638
|
return false;
|
|
9265
9639
|
}
|
|
@@ -9275,7 +9649,7 @@ function runStatus(ctx) {
|
|
|
9275
9649
|
signedIn = false;
|
|
9276
9650
|
}
|
|
9277
9651
|
const eligible = isGatewayEligibleProvider(provider);
|
|
9278
|
-
const localKey = hasLocalProviderKey(provider);
|
|
9652
|
+
const localKey = await hasLocalProviderKey(provider, ctx);
|
|
9279
9653
|
const viaServer = signedIn && eligible && !localKey;
|
|
9280
9654
|
if (viaServer) {
|
|
9281
9655
|
ctx.setStatus(info(`\u25CF server tier \u2014 ${modelId} routing via ${INDUS_SERVER_URL} (signed in)`));
|
|
@@ -9456,12 +9830,7 @@ var compactCommand = {
|
|
|
9456
9830
|
ctx.setStatus({ kind: "busy", text: busyText });
|
|
9457
9831
|
void (async () => {
|
|
9458
9832
|
try {
|
|
9459
|
-
|
|
9460
|
-
await ctx.conductor.executeBash(
|
|
9461
|
-
`printf '%s' ${JSON.stringify(`Compaction guidance: ${instructions}`)}`
|
|
9462
|
-
);
|
|
9463
|
-
}
|
|
9464
|
-
switch (await ctx.conductor.condense()) {
|
|
9833
|
+
switch (await ctx.conductor.condense(instructions || void 0)) {
|
|
9465
9834
|
case "condensed":
|
|
9466
9835
|
ctx.setStatus(
|
|
9467
9836
|
info(
|
|
@@ -9636,7 +10005,7 @@ var transcriptCommands = [
|
|
|
9636
10005
|
];
|
|
9637
10006
|
|
|
9638
10007
|
// src/console/slash/commands/workbench.ts
|
|
9639
|
-
import { mkdtempSync, readFileSync as
|
|
10008
|
+
import { mkdtempSync, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
|
|
9640
10009
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
9641
10010
|
import { join as join11 } from "node:path";
|
|
9642
10011
|
function block(slug, title, markdown) {
|
|
@@ -9672,7 +10041,7 @@ function hotkeysBlock() {
|
|
|
9672
10041
|
function readChangelog(cwd) {
|
|
9673
10042
|
for (const name of CHANGELOG_NAMES) {
|
|
9674
10043
|
try {
|
|
9675
|
-
const text =
|
|
10044
|
+
const text = readFileSync8(join11(cwd, name), "utf8");
|
|
9676
10045
|
if (text.trim().length > 0) return text;
|
|
9677
10046
|
} catch {
|
|
9678
10047
|
}
|
|
@@ -9710,9 +10079,9 @@ function runDebug(ctx) {
|
|
|
9710
10079
|
const jsonl = records.map((r) => JSON.stringify(r)).join("\n") + "\n";
|
|
9711
10080
|
try {
|
|
9712
10081
|
const dir = mkdtempSync(join11(tmpdir3(), "indus-debug-"));
|
|
9713
|
-
const
|
|
9714
|
-
|
|
9715
|
-
ctx.setStatus(info(`Diagnostics written to ${
|
|
10082
|
+
const path5 = join11(dir, `session-${stats.sessionId || "unknown"}.jsonl`);
|
|
10083
|
+
writeFileSync5(path5, jsonl, "utf8");
|
|
10084
|
+
ctx.setStatus(info(`Diagnostics written to ${path5}`));
|
|
9716
10085
|
} catch (cause) {
|
|
9717
10086
|
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
9718
10087
|
ctx.setStatus(warn(`Could not write the diagnostics log (${detail}).`));
|
|
@@ -9836,7 +10205,7 @@ var workbenchCommands = [
|
|
|
9836
10205
|
{
|
|
9837
10206
|
name: "whats-new",
|
|
9838
10207
|
summary: "Show what changed in this build",
|
|
9839
|
-
aliases: ["changelog"],
|
|
10208
|
+
aliases: ["changelog", "release-notes"],
|
|
9840
10209
|
run: runChangelog
|
|
9841
10210
|
},
|
|
9842
10211
|
{
|
|
@@ -9862,7 +10231,7 @@ var workbenchCommands = [
|
|
|
9862
10231
|
// src/console/slash/builtins.ts
|
|
9863
10232
|
var PROJECT_DIR = ".indusagi";
|
|
9864
10233
|
function dynamicRoots() {
|
|
9865
|
-
const home =
|
|
10234
|
+
const home = homedir2();
|
|
9866
10235
|
const cwd = process.cwd();
|
|
9867
10236
|
return {
|
|
9868
10237
|
skills: [
|
|
@@ -10000,7 +10369,7 @@ function readKey(input, key) {
|
|
|
10000
10369
|
case "n":
|
|
10001
10370
|
return { verb: "flow:cycleModel" };
|
|
10002
10371
|
case "p":
|
|
10003
|
-
return { verb: "flow:cycleModel" };
|
|
10372
|
+
return { verb: "flow:cycleModel", direction: -1 };
|
|
10004
10373
|
case "t":
|
|
10005
10374
|
return { verb: "view:toggleReasoning" };
|
|
10006
10375
|
case "v":
|
|
@@ -10025,15 +10394,15 @@ function readKey(input, key) {
|
|
|
10025
10394
|
}
|
|
10026
10395
|
if (key.escape) return { verb: "flow:dismiss" };
|
|
10027
10396
|
if (key.tab) return key.shift ? { verb: "mode:cyclePermission" } : { verb: "flow:accept" };
|
|
10028
|
-
if (key.
|
|
10397
|
+
if (key.delete) return { verb: "edit:eraseNext" };
|
|
10398
|
+
if (key.backspace || input === "\x7F" || input === "\b") {
|
|
10029
10399
|
return { verb: "edit:erasePrev" };
|
|
10030
10400
|
}
|
|
10031
10401
|
if (key.leftArrow) return { verb: "nav:left" };
|
|
10032
10402
|
if (key.rightArrow) return { verb: "nav:right" };
|
|
10033
10403
|
if (key.upArrow) return { verb: "nav:up" };
|
|
10034
10404
|
if (key.downArrow) return { verb: "nav:down" };
|
|
10035
|
-
if (key.pageUp) return
|
|
10036
|
-
if (key.pageDown) return { verb: "nav:end" };
|
|
10405
|
+
if (key.pageUp || key.pageDown) return NO_INTENT;
|
|
10037
10406
|
return isPrintable(input) ? typed(input) : NO_INTENT;
|
|
10038
10407
|
}
|
|
10039
10408
|
var NO_CHORD = { armed: null };
|
|
@@ -10153,12 +10522,12 @@ function splitPathStem(stem) {
|
|
|
10153
10522
|
const body = stem.slice(sigil.length);
|
|
10154
10523
|
const slash = body.lastIndexOf("/");
|
|
10155
10524
|
if (slash < 0) return { dir: ".", leaf: body, sigil };
|
|
10156
|
-
return { dir: body.slice(0, slash) || "
|
|
10525
|
+
return { dir: body.slice(0, slash) || "/", leaf: body.slice(slash + 1), sigil };
|
|
10157
10526
|
}
|
|
10158
10527
|
function completePath(stem, readDir) {
|
|
10159
10528
|
const { dir, leaf, sigil } = splitPathStem(stem);
|
|
10160
10529
|
const lowerLeaf = leaf.toLowerCase();
|
|
10161
|
-
const prefix = dir === "." ? "" : `${dir}/`;
|
|
10530
|
+
const prefix = dir === "." ? "" : dir === "/" ? "/" : `${dir}/`;
|
|
10162
10531
|
const matches = readDir(dir).filter((e) => e.name.toLowerCase().startsWith(lowerLeaf)).sort((a, b) => {
|
|
10163
10532
|
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
|
|
10164
10533
|
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
|
|
@@ -10194,6 +10563,7 @@ function applySuggestion(buffer, span, suggestion) {
|
|
|
10194
10563
|
// src/console/input/dir-reader.ts
|
|
10195
10564
|
import { readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
|
|
10196
10565
|
import { resolve as resolve6 } from "node:path";
|
|
10566
|
+
import { homedir as homedir3 } from "node:os";
|
|
10197
10567
|
function entryIsDir(base, name, isDirent, isSymlink) {
|
|
10198
10568
|
if (isDirent) return true;
|
|
10199
10569
|
if (!isSymlink) return false;
|
|
@@ -10205,7 +10575,8 @@ function entryIsDir(base, name, isDirent, isSymlink) {
|
|
|
10205
10575
|
}
|
|
10206
10576
|
function createDirReader(cwd = process.cwd()) {
|
|
10207
10577
|
return (dirPath) => {
|
|
10208
|
-
const
|
|
10578
|
+
const expanded = dirPath === "~" ? homedir3() : dirPath.startsWith("~/") ? resolve6(homedir3(), dirPath.slice(2)) : dirPath;
|
|
10579
|
+
const target = resolve6(cwd, expanded);
|
|
10209
10580
|
try {
|
|
10210
10581
|
const dirents = readdirSync3(target, { withFileTypes: true });
|
|
10211
10582
|
return dirents.map((d) => ({
|
|
@@ -10220,11 +10591,12 @@ function createDirReader(cwd = process.cwd()) {
|
|
|
10220
10591
|
|
|
10221
10592
|
// src/console/components/TerminalConsole.ts
|
|
10222
10593
|
import { execFileSync } from "node:child_process";
|
|
10223
|
-
import { homedir as
|
|
10224
|
-
import
|
|
10225
|
-
import { Box as
|
|
10594
|
+
import { homedir as homedir6 } from "node:os";
|
|
10595
|
+
import React4, { useEffect as useEffect9, useMemo as useMemo2, useState as useState10 } from "indusagi/react-host";
|
|
10596
|
+
import { Box as Box12, Text as Text11, useInput as useInput6 } from "indusagi/react-host/ink";
|
|
10597
|
+
import { useStdin, useStdout as useStdout2 } from "ink";
|
|
10226
10598
|
import { MessageList, StreamingMarkdown, TaskPanel } from "indusagi/react-ink";
|
|
10227
|
-
import { Fragment as Fragment4, jsx as
|
|
10599
|
+
import { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs10 } from "indusagi/react-host/jsx-runtime";
|
|
10228
10600
|
|
|
10229
10601
|
// src/workspace/runtime-detect.ts
|
|
10230
10602
|
var BUN_VIRTUAL_FS_MARKERS = ["$bunfs", "~BUN", "%7EBUN"];
|
|
@@ -10239,13 +10611,13 @@ function isPackagedBinary() {
|
|
|
10239
10611
|
}
|
|
10240
10612
|
|
|
10241
10613
|
// src/settings/manager.ts
|
|
10242
|
-
import { existsSync as
|
|
10243
|
-
import { dirname as
|
|
10614
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "node:fs";
|
|
10615
|
+
import { dirname as dirname5, join as join13 } from "node:path";
|
|
10244
10616
|
function loadTier(filePath) {
|
|
10245
|
-
if (!
|
|
10617
|
+
if (!existsSync2(filePath)) return {};
|
|
10246
10618
|
let raw;
|
|
10247
10619
|
try {
|
|
10248
|
-
raw =
|
|
10620
|
+
raw = readFileSync9(filePath, "utf-8");
|
|
10249
10621
|
} catch {
|
|
10250
10622
|
return {};
|
|
10251
10623
|
}
|
|
@@ -10261,9 +10633,9 @@ function loadTier(filePath) {
|
|
|
10261
10633
|
return { ...parsed };
|
|
10262
10634
|
}
|
|
10263
10635
|
function writeTier(filePath, tier) {
|
|
10264
|
-
const dir =
|
|
10265
|
-
if (!
|
|
10266
|
-
|
|
10636
|
+
const dir = dirname5(filePath);
|
|
10637
|
+
if (!existsSync2(dir)) mkdirSync2(dir, { recursive: true });
|
|
10638
|
+
writeFileSync6(filePath, `${JSON.stringify(tier, null, 2)}
|
|
10267
10639
|
`, "utf-8");
|
|
10268
10640
|
}
|
|
10269
10641
|
var PreferenceStore = class _PreferenceStore {
|
|
@@ -10336,14 +10708,14 @@ var IMAGE_SNIFF_BYTES = PNG_SIGNATURE.length;
|
|
|
10336
10708
|
|
|
10337
10709
|
// src/sessions/library.ts
|
|
10338
10710
|
import {
|
|
10339
|
-
mkdir
|
|
10340
|
-
readFile
|
|
10711
|
+
mkdir,
|
|
10712
|
+
readFile,
|
|
10341
10713
|
readdir,
|
|
10342
10714
|
rename,
|
|
10343
10715
|
rm,
|
|
10344
10716
|
stat
|
|
10345
10717
|
} from "node:fs/promises";
|
|
10346
|
-
import { basename as
|
|
10718
|
+
import { basename as basename5, join as join14 } from "node:path";
|
|
10347
10719
|
var SESSION_FILE_EXT = ".ndjson";
|
|
10348
10720
|
var PREVIEW_LIMIT = 72;
|
|
10349
10721
|
var SessionLibrary = class {
|
|
@@ -10375,14 +10747,14 @@ var SessionLibrary = class {
|
|
|
10375
10747
|
if (!await this.#missing(toPath)) {
|
|
10376
10748
|
throw new Error(`SessionLibrary.rename: session "${toId}" already exists`);
|
|
10377
10749
|
}
|
|
10378
|
-
await
|
|
10750
|
+
await mkdir(this.#dir, { recursive: true });
|
|
10379
10751
|
await rename(fromPath, toPath);
|
|
10380
10752
|
return toPath;
|
|
10381
10753
|
}
|
|
10382
10754
|
async remove(id) {
|
|
10383
|
-
const
|
|
10384
|
-
if (await this.#missing(
|
|
10385
|
-
await rm(
|
|
10755
|
+
const path5 = this.pathOf(id);
|
|
10756
|
+
if (await this.#missing(path5)) return false;
|
|
10757
|
+
await rm(path5, { force: true });
|
|
10386
10758
|
return true;
|
|
10387
10759
|
}
|
|
10388
10760
|
pathOf(id) {
|
|
@@ -10437,41 +10809,41 @@ var SessionLibrary = class {
|
|
|
10437
10809
|
} catch {
|
|
10438
10810
|
return [];
|
|
10439
10811
|
}
|
|
10440
|
-
return names.filter((name) => name.endsWith(SESSION_FILE_EXT)).map((name) =>
|
|
10812
|
+
return names.filter((name) => name.endsWith(SESSION_FILE_EXT)).map((name) => basename5(name, SESSION_FILE_EXT));
|
|
10441
10813
|
}
|
|
10442
10814
|
async #shallowRow(id) {
|
|
10443
|
-
const
|
|
10444
|
-
const meta = await this.#fileMeta(
|
|
10445
|
-
return { id, path:
|
|
10815
|
+
const path5 = this.pathOf(id);
|
|
10816
|
+
const meta = await this.#fileMeta(path5);
|
|
10817
|
+
return { id, path: path5, ...meta };
|
|
10446
10818
|
}
|
|
10447
10819
|
async #deepRow(id) {
|
|
10448
|
-
const
|
|
10449
|
-
const meta = await this.#fileMeta(
|
|
10820
|
+
const path5 = this.pathOf(id);
|
|
10821
|
+
const meta = await this.#fileMeta(path5);
|
|
10450
10822
|
const store = await this.open(id);
|
|
10451
|
-
if (store === null) return { id, path:
|
|
10823
|
+
if (store === null) return { id, path: path5, ...meta };
|
|
10452
10824
|
const branch = store.pathTo();
|
|
10453
10825
|
const conversational = branch.filter(isConversational);
|
|
10454
10826
|
const opener = conversational.find((entry) => entry.role === "user");
|
|
10455
10827
|
const preview2 = opener ? previewOf(messageText(opener.content)) : void 0;
|
|
10456
10828
|
return {
|
|
10457
10829
|
id,
|
|
10458
|
-
path:
|
|
10830
|
+
path: path5,
|
|
10459
10831
|
...meta,
|
|
10460
10832
|
messageCount: conversational.length,
|
|
10461
10833
|
...preview2 ? { preview: preview2, name: preview2 } : {}
|
|
10462
10834
|
};
|
|
10463
10835
|
}
|
|
10464
|
-
async #fileMeta(
|
|
10836
|
+
async #fileMeta(path5) {
|
|
10465
10837
|
try {
|
|
10466
|
-
const info2 = await stat(
|
|
10838
|
+
const info2 = await stat(path5);
|
|
10467
10839
|
return { size: info2.size, lastModified: info2.mtimeMs };
|
|
10468
10840
|
} catch {
|
|
10469
10841
|
return {};
|
|
10470
10842
|
}
|
|
10471
10843
|
}
|
|
10472
|
-
async #missing(
|
|
10844
|
+
async #missing(path5) {
|
|
10473
10845
|
try {
|
|
10474
|
-
await
|
|
10846
|
+
await readFile(path5);
|
|
10475
10847
|
return false;
|
|
10476
10848
|
} catch {
|
|
10477
10849
|
return true;
|
|
@@ -10630,9 +11002,9 @@ function resolveSpecifierPath(specifier) {
|
|
|
10630
11002
|
function buildAliasMap() {
|
|
10631
11003
|
const map = {};
|
|
10632
11004
|
for (const specifier of BUNDLED_NAMESPACES) {
|
|
10633
|
-
const
|
|
10634
|
-
if (
|
|
10635
|
-
map[specifier] =
|
|
11005
|
+
const path5 = resolveSpecifierPath(specifier);
|
|
11006
|
+
if (path5 !== void 0) {
|
|
11007
|
+
map[specifier] = path5;
|
|
10636
11008
|
}
|
|
10637
11009
|
}
|
|
10638
11010
|
return map;
|
|
@@ -10680,8 +11052,8 @@ function createJitiLoader(options = {}) {
|
|
|
10680
11052
|
const base = options.base ?? process.cwd();
|
|
10681
11053
|
const home = options.home ?? homedir4();
|
|
10682
11054
|
return {
|
|
10683
|
-
async load(
|
|
10684
|
-
const absolute = resolvePath(
|
|
11055
|
+
async load(path5) {
|
|
11056
|
+
const absolute = resolvePath(path5, base, home);
|
|
10685
11057
|
const specifier = pathToFileURL(absolute).href;
|
|
10686
11058
|
const imported = await jiti.import(specifier);
|
|
10687
11059
|
const manifest = toManifest(imported);
|
|
@@ -10696,8 +11068,8 @@ function createJitiLoader(options = {}) {
|
|
|
10696
11068
|
}
|
|
10697
11069
|
|
|
10698
11070
|
// src/addons/manifest.ts
|
|
10699
|
-
import { readFileSync as
|
|
10700
|
-
import { basename as
|
|
11071
|
+
import { readFileSync as readFileSync10, readdirSync as readdirSync4, statSync as statSync4 } from "node:fs";
|
|
11072
|
+
import { basename as basename6, extname as extname3, isAbsolute as isAbsolute5, join as join15, resolve as resolve8 } from "node:path";
|
|
10701
11073
|
var ENTRY_EXTENSIONS = [
|
|
10702
11074
|
".ts",
|
|
10703
11075
|
".tsx",
|
|
@@ -10714,9 +11086,9 @@ function isHidden(name) {
|
|
|
10714
11086
|
function hasEntryExtension(name) {
|
|
10715
11087
|
return ENTRY_EXTENSIONS.includes(extname3(name).toLowerCase());
|
|
10716
11088
|
}
|
|
10717
|
-
function entryKind(
|
|
11089
|
+
function entryKind(path5) {
|
|
10718
11090
|
try {
|
|
10719
|
-
const stat2 = statSync4(
|
|
11091
|
+
const stat2 = statSync4(path5);
|
|
10720
11092
|
if (stat2.isDirectory()) return "directory";
|
|
10721
11093
|
if (stat2.isFile()) return "file";
|
|
10722
11094
|
return void 0;
|
|
@@ -10737,7 +11109,7 @@ function readManifestEntry(packageDir) {
|
|
|
10737
11109
|
return void 0;
|
|
10738
11110
|
}
|
|
10739
11111
|
try {
|
|
10740
|
-
const parsed = JSON.parse(
|
|
11112
|
+
const parsed = JSON.parse(readFileSync10(manifestPath, "utf8"));
|
|
10741
11113
|
if (typeof parsed !== "object" || parsed === null) {
|
|
10742
11114
|
return void 0;
|
|
10743
11115
|
}
|
|
@@ -10769,13 +11141,13 @@ function resolveTopLevelEntry(dir, name) {
|
|
|
10769
11141
|
if (isHidden(name)) {
|
|
10770
11142
|
return void 0;
|
|
10771
11143
|
}
|
|
10772
|
-
const
|
|
10773
|
-
const kind = entryKind(
|
|
11144
|
+
const path5 = join15(dir, name);
|
|
11145
|
+
const kind = entryKind(path5);
|
|
10774
11146
|
if (kind === "file") {
|
|
10775
|
-
return hasEntryExtension(name) ?
|
|
11147
|
+
return hasEntryExtension(name) ? path5 : void 0;
|
|
10776
11148
|
}
|
|
10777
11149
|
if (kind === "directory") {
|
|
10778
|
-
return resolvePackageEntry(
|
|
11150
|
+
return resolvePackageEntry(path5);
|
|
10779
11151
|
}
|
|
10780
11152
|
return void 0;
|
|
10781
11153
|
}
|
|
@@ -10790,9 +11162,9 @@ function discoverAddons(dir) {
|
|
|
10790
11162
|
return entries.sort();
|
|
10791
11163
|
}
|
|
10792
11164
|
function deriveAddonId(entryPath) {
|
|
10793
|
-
const file =
|
|
11165
|
+
const file = basename6(entryPath);
|
|
10794
11166
|
const stem = file.slice(0, file.length - extname3(file).length);
|
|
10795
|
-
const label = INDEX_BASENAMES.includes(stem) ?
|
|
11167
|
+
const label = INDEX_BASENAMES.includes(stem) ? basename6(join15(entryPath, "..")) : stem;
|
|
10796
11168
|
return addonId(label.length > 0 ? label : entryPath);
|
|
10797
11169
|
}
|
|
10798
11170
|
function addonsDirFor(workspace, dir = ADDONS_DIR) {
|
|
@@ -10809,12 +11181,12 @@ function discoverSources(discovery) {
|
|
|
10809
11181
|
}
|
|
10810
11182
|
const seen = /* @__PURE__ */ new Set();
|
|
10811
11183
|
const sources = [];
|
|
10812
|
-
for (const
|
|
10813
|
-
if (seen.has(
|
|
11184
|
+
for (const path5 of paths) {
|
|
11185
|
+
if (seen.has(path5)) {
|
|
10814
11186
|
continue;
|
|
10815
11187
|
}
|
|
10816
|
-
seen.add(
|
|
10817
|
-
sources.push({ id: deriveAddonId(
|
|
11188
|
+
seen.add(path5);
|
|
11189
|
+
sources.push({ id: deriveAddonId(path5), path: path5 });
|
|
10818
11190
|
}
|
|
10819
11191
|
return sources;
|
|
10820
11192
|
}
|
|
@@ -11383,6 +11755,7 @@ function ndjsonStrategy() {
|
|
|
11383
11755
|
},
|
|
11384
11756
|
onSignal(signal, ctx) {
|
|
11385
11757
|
const s = signal;
|
|
11758
|
+
if (s.kind === "tool_update") return;
|
|
11386
11759
|
ctx.out.write(ctx.framer.encodeLine({ type: "signal", name: s.kind, body: s }));
|
|
11387
11760
|
},
|
|
11388
11761
|
finish(state, ctx) {
|
|
@@ -11489,16 +11862,16 @@ function createDialogBridge(deps) {
|
|
|
11489
11862
|
ask(kind, payload, fallback) {
|
|
11490
11863
|
const id = nextAskId(seq);
|
|
11491
11864
|
const frame = { type: "ask", id, kind, payload };
|
|
11492
|
-
return new Promise((
|
|
11865
|
+
return new Promise((resolve11) => {
|
|
11493
11866
|
const timer = setTimeout(() => {
|
|
11494
11867
|
pending.delete(id);
|
|
11495
|
-
|
|
11868
|
+
resolve11(fallback);
|
|
11496
11869
|
}, deps.timings.dialogMs);
|
|
11497
11870
|
if (typeof timer.unref === "function") {
|
|
11498
11871
|
timer.unref();
|
|
11499
11872
|
}
|
|
11500
11873
|
pending.set(id, {
|
|
11501
|
-
settle: (value) =>
|
|
11874
|
+
settle: (value) => resolve11(value),
|
|
11502
11875
|
timer
|
|
11503
11876
|
});
|
|
11504
11877
|
emit(frame);
|
|
@@ -12127,6 +12500,7 @@ import { jsx as jsx2 } from "indusagi/react-host/jsx-runtime";
|
|
|
12127
12500
|
|
|
12128
12501
|
// src/console/auth-status.ts
|
|
12129
12502
|
import { useEffect, useState } from "indusagi/react-host";
|
|
12503
|
+
import { getEnvApiKey as getEnvApiKey3 } from "indusagi/ai";
|
|
12130
12504
|
function useAuthenticatedProviders(services, refreshKey) {
|
|
12131
12505
|
const [authed, setAuthed] = useState(null);
|
|
12132
12506
|
useEffect(() => {
|
|
@@ -12135,10 +12509,14 @@ function useAuthenticatedProviders(services, refreshKey) {
|
|
|
12135
12509
|
void (async () => {
|
|
12136
12510
|
const found = /* @__PURE__ */ new Set();
|
|
12137
12511
|
try {
|
|
12138
|
-
|
|
12512
|
+
const providers = /* @__PURE__ */ new Set([
|
|
12513
|
+
...services.listLoginProviders().map((provider) => provider.id),
|
|
12514
|
+
...services.conductor.availableModels().map((model) => model.provider)
|
|
12515
|
+
]);
|
|
12516
|
+
for (const provider of providers) {
|
|
12139
12517
|
try {
|
|
12140
|
-
if ((await services.vault.listAccounts(provider
|
|
12141
|
-
found.add(provider
|
|
12518
|
+
if (getEnvApiKey3(provider) || (await services.vault.listAccounts(provider)).length > 0) {
|
|
12519
|
+
found.add(provider);
|
|
12142
12520
|
}
|
|
12143
12521
|
} catch {
|
|
12144
12522
|
}
|
|
@@ -12156,15 +12534,12 @@ function useAuthenticatedProviders(services, refreshKey) {
|
|
|
12156
12534
|
return () => {
|
|
12157
12535
|
live3 = false;
|
|
12158
12536
|
};
|
|
12159
|
-
}, [refreshKey]);
|
|
12537
|
+
}, [services, refreshKey]);
|
|
12160
12538
|
return authed;
|
|
12161
12539
|
}
|
|
12162
12540
|
|
|
12163
12541
|
// src/console/overlays/boards.ts
|
|
12164
12542
|
import chalk2 from "chalk";
|
|
12165
|
-
import { readFileSync as readFileSync10 } from "node:fs";
|
|
12166
|
-
import { homedir as homedir5 } from "node:os";
|
|
12167
|
-
import { join as join16 } from "node:path";
|
|
12168
12543
|
import { useEffect as useEffect2, useMemo, useState as useState2 } from "indusagi/react-host";
|
|
12169
12544
|
import { Box, Text, useInput } from "indusagi/react-host/ink";
|
|
12170
12545
|
import {
|
|
@@ -12172,28 +12547,6 @@ import {
|
|
|
12172
12547
|
wrapSelectionIndex
|
|
12173
12548
|
} from "indusagi/react-ink";
|
|
12174
12549
|
import { Fragment, jsx, jsxs } from "indusagi/react-host/jsx-runtime";
|
|
12175
|
-
function readServerTierInfo() {
|
|
12176
|
-
let signedIn = false;
|
|
12177
|
-
try {
|
|
12178
|
-
const file = join16(homedir5(), ".indusagi", "agent", "server-token.json");
|
|
12179
|
-
const token = JSON.parse(readFileSync10(file, "utf8"));
|
|
12180
|
-
signedIn = typeof token.expires_at === "string" && new Date(token.expires_at).getTime() - Date.now() > 5 * 60 * 1e3;
|
|
12181
|
-
} catch {
|
|
12182
|
-
signedIn = false;
|
|
12183
|
-
}
|
|
12184
|
-
const localKeys = /* @__PURE__ */ new Set();
|
|
12185
|
-
try {
|
|
12186
|
-
const file = join16(homedir5(), ".indusagi", "agent", "auth.json");
|
|
12187
|
-
const vault = JSON.parse(readFileSync10(file, "utf8"));
|
|
12188
|
-
for (const [provider, entry] of Object.entries(vault)) {
|
|
12189
|
-
if (entry !== null && typeof entry === "object" && Object.keys(entry).length > 0) {
|
|
12190
|
-
localKeys.add(provider);
|
|
12191
|
-
}
|
|
12192
|
-
}
|
|
12193
|
-
} catch {
|
|
12194
|
-
}
|
|
12195
|
-
return { signedIn, localKeys };
|
|
12196
|
-
}
|
|
12197
12550
|
function truncate(text, width) {
|
|
12198
12551
|
if (text.length <= width) return text;
|
|
12199
12552
|
if (width <= 1) return text.slice(0, width);
|
|
@@ -12290,6 +12643,7 @@ function nextValue(values, current, direction) {
|
|
|
12290
12643
|
return values[(at + direction + values.length) % values.length];
|
|
12291
12644
|
}
|
|
12292
12645
|
function SettingsBoard({ theme, items, onClose }) {
|
|
12646
|
+
const [error, setError] = useState2();
|
|
12293
12647
|
const [query, setQuery] = useState2("");
|
|
12294
12648
|
const [selectedIndex, setSelectedIndex] = useState2(0);
|
|
12295
12649
|
const filtered = useMemo(
|
|
@@ -12306,7 +12660,15 @@ function SettingsBoard({ theme, items, onClose }) {
|
|
|
12306
12660
|
const item = filtered[selectedIndex];
|
|
12307
12661
|
if (!item) return;
|
|
12308
12662
|
const value = nextValue(item.values, item.value, direction);
|
|
12309
|
-
if (value && value !== item.value)
|
|
12663
|
+
if (value && value !== item.value) {
|
|
12664
|
+
setError(void 0);
|
|
12665
|
+
const failed = (error2) => setError(error2 instanceof Error ? error2.message : String(error2));
|
|
12666
|
+
try {
|
|
12667
|
+
void Promise.resolve(item.onChange(value)).catch(failed);
|
|
12668
|
+
} catch (error2) {
|
|
12669
|
+
failed(error2);
|
|
12670
|
+
}
|
|
12671
|
+
}
|
|
12310
12672
|
};
|
|
12311
12673
|
useInput((input, key) => {
|
|
12312
12674
|
if (key.escape) return onClose();
|
|
@@ -12321,7 +12683,7 @@ function SettingsBoard({ theme, items, onClose }) {
|
|
|
12321
12683
|
const { start, budget, below } = windowAround(filtered.length, selectedIndex);
|
|
12322
12684
|
const visible = filtered.slice(start, start + budget);
|
|
12323
12685
|
const selected = filtered[selectedIndex];
|
|
12324
|
-
const detail = selected ? `${selected.description} \xB7 ${selected.values.join(" / ")}` : void 0;
|
|
12686
|
+
const detail = error ?? (selected ? `${selected.description} \xB7 ${selected.values.join(" / ")}` : void 0);
|
|
12325
12687
|
const list = items.length === 0 ? jsx(Text, { children: theme.muted("No settings are available.") }) : filtered.length === 0 ? jsx(Text, { children: theme.muted("No settings matched the search.") }) : jsx(Box, {
|
|
12326
12688
|
flexDirection: "column",
|
|
12327
12689
|
children: visible.map((item, index) => {
|
|
@@ -12361,12 +12723,7 @@ function ModelBoard({ theme, models, onClose, onSelect, search }) {
|
|
|
12361
12723
|
const [query, setQuery] = useState2(search ?? "");
|
|
12362
12724
|
const [selectedIndex, setSelectedIndex] = useState2(0);
|
|
12363
12725
|
useEffect2(() => setQuery(search ?? ""), [search]);
|
|
12364
|
-
const
|
|
12365
|
-
const isServerTier = (provider) => serverTier.signedIn && isGatewayEligibleProvider(provider) && !serverTier.localKeys.has(provider);
|
|
12366
|
-
const available = useMemo(
|
|
12367
|
-
() => models.filter((model) => serverTier.localKeys.has(model.provider) || isServerTier(model.provider)),
|
|
12368
|
-
[models, serverTier]
|
|
12369
|
-
);
|
|
12726
|
+
const available = models;
|
|
12370
12727
|
const filtered = useMemo(() => available.filter((model) => modelMatches(model, query)), [available, query]);
|
|
12371
12728
|
useEffect2(() => setSelectedIndex(0), [query]);
|
|
12372
12729
|
useEffect2(() => {
|
|
@@ -12402,10 +12759,10 @@ function ModelBoard({ theme, models, onClose, onSelect, search }) {
|
|
|
12402
12759
|
jsx(Box, { width: 2, children: jsx(Text, { children: isSelected ? theme.color("accent", "\u203A") : " " }) }),
|
|
12403
12760
|
jsx(Text, { bold: isSelected, children: theme.color("text", model.id) }),
|
|
12404
12761
|
model.name ? jsx(Text, { children: theme.dim(` ${model.name}`) }) : null,
|
|
12405
|
-
|
|
12762
|
+
jsx(Text, { children: theme.dim(` ${model.provider}`) })
|
|
12406
12763
|
]
|
|
12407
12764
|
},
|
|
12408
|
-
model.id
|
|
12765
|
+
`${model.provider}/${model.id}`
|
|
12409
12766
|
);
|
|
12410
12767
|
})
|
|
12411
12768
|
});
|
|
@@ -12422,6 +12779,19 @@ function ModelBoard({ theme, models, onClose, onSelect, search }) {
|
|
|
12422
12779
|
|
|
12423
12780
|
// src/console/overlays/pickers.ts
|
|
12424
12781
|
var TOGGLE_VALUES = ["on", "off"];
|
|
12782
|
+
function saveSetting(settings, key, value) {
|
|
12783
|
+
const previous = settings.get(key);
|
|
12784
|
+
try {
|
|
12785
|
+
settings.set(key, value);
|
|
12786
|
+
settings.save();
|
|
12787
|
+
} catch (error) {
|
|
12788
|
+
settings.set(key, previous);
|
|
12789
|
+
throw error;
|
|
12790
|
+
}
|
|
12791
|
+
}
|
|
12792
|
+
function reportError(dispatch2, error) {
|
|
12793
|
+
dispatch2({ type: "status:set", status: { kind: "error", text: error instanceof Error ? error.message : String(error) } });
|
|
12794
|
+
}
|
|
12425
12795
|
function refToModel(ref) {
|
|
12426
12796
|
return {
|
|
12427
12797
|
id: ref.id,
|
|
@@ -12444,7 +12814,7 @@ function listModels(services) {
|
|
|
12444
12814
|
}
|
|
12445
12815
|
}
|
|
12446
12816
|
function ModelPicker(props) {
|
|
12447
|
-
const { services, theme, closeModal } = props;
|
|
12817
|
+
const { services, theme, closeModal, dispatch: dispatch2 } = props;
|
|
12448
12818
|
const authed = useAuthenticatedProviders(services);
|
|
12449
12819
|
if (!services) return null;
|
|
12450
12820
|
const all = listModels(services);
|
|
@@ -12455,7 +12825,8 @@ function ModelPicker(props) {
|
|
|
12455
12825
|
onSelect: (model) => {
|
|
12456
12826
|
try {
|
|
12457
12827
|
services.conductor.selectModel(model.id);
|
|
12458
|
-
} catch {
|
|
12828
|
+
} catch (error) {
|
|
12829
|
+
reportError(dispatch2, error);
|
|
12459
12830
|
}
|
|
12460
12831
|
closeModal();
|
|
12461
12832
|
},
|
|
@@ -12476,8 +12847,7 @@ function ScopedModelPicker(props) {
|
|
|
12476
12847
|
useEffect3(() => {
|
|
12477
12848
|
if (!services || payload.intent !== "reset") return;
|
|
12478
12849
|
try {
|
|
12479
|
-
services.settings
|
|
12480
|
-
services.settings.save();
|
|
12850
|
+
saveSetting(services.settings, "enabledModels", []);
|
|
12481
12851
|
dispatch2({
|
|
12482
12852
|
type: "status:set",
|
|
12483
12853
|
status: { kind: "info", text: "Per-scope model overrides cleared." }
|
|
@@ -12507,9 +12877,9 @@ function ScopedModelPicker(props) {
|
|
|
12507
12877
|
try {
|
|
12508
12878
|
const all = models.map((model) => model.id);
|
|
12509
12879
|
const next = ids.length === all.length ? [] : ids;
|
|
12510
|
-
services.settings
|
|
12511
|
-
|
|
12512
|
-
|
|
12880
|
+
saveSetting(services.settings, "enabledModels", next);
|
|
12881
|
+
} catch (error) {
|
|
12882
|
+
reportError(dispatch2, error);
|
|
12513
12883
|
}
|
|
12514
12884
|
closeModal();
|
|
12515
12885
|
},
|
|
@@ -12536,11 +12906,11 @@ function ThemePicker(props) {
|
|
|
12536
12906
|
themes: [...THEME_SCHEMES],
|
|
12537
12907
|
onSelect: (name) => {
|
|
12538
12908
|
if (isThemeScheme(name)) {
|
|
12539
|
-
dispatch2({ type: "scheme:set", scheme: name });
|
|
12540
12909
|
try {
|
|
12541
|
-
services.settings
|
|
12542
|
-
|
|
12543
|
-
} catch {
|
|
12910
|
+
saveSetting(services.settings, "colourScheme", name);
|
|
12911
|
+
dispatch2({ type: "scheme:set", scheme: name });
|
|
12912
|
+
} catch (error) {
|
|
12913
|
+
reportError(dispatch2, error);
|
|
12544
12914
|
}
|
|
12545
12915
|
}
|
|
12546
12916
|
closeModal();
|
|
@@ -12562,9 +12932,8 @@ function SettingsPicker(props) {
|
|
|
12562
12932
|
value: onOff(settings.get(key)),
|
|
12563
12933
|
values: [...TOGGLE_VALUES],
|
|
12564
12934
|
onChange: (value) => {
|
|
12565
|
-
settings
|
|
12566
|
-
|
|
12567
|
-
live3?.();
|
|
12935
|
+
saveSetting(settings, key, value === "on");
|
|
12936
|
+
live3?.(value === "on");
|
|
12568
12937
|
bump();
|
|
12569
12938
|
}
|
|
12570
12939
|
});
|
|
@@ -12576,8 +12945,7 @@ function SettingsPicker(props) {
|
|
|
12576
12945
|
values: [...DELIVERY_MODES],
|
|
12577
12946
|
onChange: (value) => {
|
|
12578
12947
|
if (isDeliveryMode(value)) {
|
|
12579
|
-
settings
|
|
12580
|
-
settings.save();
|
|
12948
|
+
saveSetting(settings, key, value);
|
|
12581
12949
|
}
|
|
12582
12950
|
bump();
|
|
12583
12951
|
}
|
|
@@ -12591,16 +12959,15 @@ function SettingsPicker(props) {
|
|
|
12591
12959
|
value: settings.get("colourScheme"),
|
|
12592
12960
|
values: [...THEME_SCHEMES],
|
|
12593
12961
|
onChange: (value) => {
|
|
12594
|
-
settings
|
|
12595
|
-
settings.save();
|
|
12962
|
+
saveSetting(settings, "colourScheme", value);
|
|
12596
12963
|
if (isThemeScheme(value)) dispatch2({ type: "scheme:set", scheme: value });
|
|
12597
12964
|
bump();
|
|
12598
12965
|
}
|
|
12599
12966
|
});
|
|
12600
|
-
items.push(toggleRow("show-images", "showImages", "Show images", "Render inline image content in the transcript.", () => dispatch2({ type: "
|
|
12967
|
+
items.push(toggleRow("show-images", "showImages", "Show images", "Render inline image content in the transcript.", (value) => dispatch2({ type: "display:set", key: "showImages", value })));
|
|
12601
12968
|
items.push(toggleRow("image-auto-resize", "imageAutoResize", "Auto-resize images", "Shrink oversized images to fit before handing them to a provider."));
|
|
12602
12969
|
items.push(toggleRow("block-images", "blockImages", "Block images", "Withhold image content from providers entirely."));
|
|
12603
|
-
items.push(toggleRow("show-reasoning", "showReasoning", "Show reasoning", "Stream the model's reasoning / thinking text as it arrives.", () => dispatch2({ type: "
|
|
12970
|
+
items.push(toggleRow("show-reasoning", "showReasoning", "Show reasoning", "Stream the model's reasoning / thinking text as it arrives.", (value) => dispatch2({ type: "display:set", key: "showReasoning", value })));
|
|
12604
12971
|
items.push(toggleRow("skill-commands", "enableSkillCommands", "Skill commands", "Surface discovered skills as their own slash commands."));
|
|
12605
12972
|
items.push(deliveryRow("steering-mode", "steeringMode", "Steering mode", "Whether queued steering corrections release one at a time or all at once."));
|
|
12606
12973
|
items.push(deliveryRow("follow-up-mode", "followUpMode", "Follow-up mode", "Whether queued follow-up prompts release one at a time or all at once."));
|
|
@@ -12609,7 +12976,6 @@ function SettingsPicker(props) {
|
|
|
12609
12976
|
items.push(toggleRow("quiet-startup", "quietStartup", "Quiet startup", "Suppress the banner and tips shown on a normal interactive launch."));
|
|
12610
12977
|
items.push(toggleRow("logo-sweep", "logoSweep", "Logo sweep", "Tint the startup wordmark and emblem along a static colour gradient."));
|
|
12611
12978
|
items.push(toggleRow("reduced-motion", "reducedMotion", "Reduced motion", "Suppress motion-flavoured flourishes such as the logo colour sweep."));
|
|
12612
|
-
items.push(toggleRow("hardware-cursor", "showHardwareCursor", "Hardware cursor", "Reveal the terminal's own cursor instead of the software-drawn caret."));
|
|
12613
12979
|
items.push({
|
|
12614
12980
|
id: "editor-padding",
|
|
12615
12981
|
label: "Editor padding",
|
|
@@ -12619,8 +12985,7 @@ function SettingsPicker(props) {
|
|
|
12619
12985
|
onChange: (value) => {
|
|
12620
12986
|
const parsed = Number.parseInt(value, 10);
|
|
12621
12987
|
if (Number.isFinite(parsed)) {
|
|
12622
|
-
settings
|
|
12623
|
-
settings.save();
|
|
12988
|
+
saveSetting(settings, "editorPaddingX", parsed);
|
|
12624
12989
|
}
|
|
12625
12990
|
bump();
|
|
12626
12991
|
}
|
|
@@ -12874,7 +13239,7 @@ function SignInDialog(props) {
|
|
|
12874
13239
|
var SERVER_TIER_ACCOUNT_ID = "server-session";
|
|
12875
13240
|
var SERVER_TIER_PROVIDER_ID2 = "indus-server";
|
|
12876
13241
|
function SignOutDialog(props) {
|
|
12877
|
-
const { services, closeModal } = props;
|
|
13242
|
+
const { services, closeModal, dispatch: dispatch2 } = props;
|
|
12878
13243
|
const [accounts, setAccounts] = useState5([]);
|
|
12879
13244
|
useEffect5(() => {
|
|
12880
13245
|
let live3 = true;
|
|
@@ -12926,7 +13291,10 @@ function SignOutDialog(props) {
|
|
|
12926
13291
|
} else {
|
|
12927
13292
|
await services.vault.remove(account.provider, account.accountId);
|
|
12928
13293
|
}
|
|
12929
|
-
|
|
13294
|
+
await services.refreshGatewayRouting();
|
|
13295
|
+
dispatch2({ type: "status:set", status: { kind: "info", text: "Signed out. Model routing refreshed." } });
|
|
13296
|
+
} catch (error) {
|
|
13297
|
+
dispatch2({ type: "status:set", status: { kind: "error", text: error instanceof Error ? error.message : "Sign-out failed." } });
|
|
12930
13298
|
}
|
|
12931
13299
|
closeModal();
|
|
12932
13300
|
}
|
|
@@ -12964,15 +13332,24 @@ function OAuthFlowDialog(props) {
|
|
|
12964
13332
|
})();
|
|
12965
13333
|
const [state, setState] = useState5(() => seedOAuthState(providerId, providerName, mode));
|
|
12966
13334
|
const pending = useRef(null);
|
|
13335
|
+
const cancelPrompt = useRef(null);
|
|
13336
|
+
const mounted = useRef(true);
|
|
13337
|
+
const saving = useRef(false);
|
|
13338
|
+
useEffect5(() => () => {
|
|
13339
|
+
mounted.current = false;
|
|
13340
|
+
}, []);
|
|
12967
13341
|
const merge = (next) => setState((prev) => ({ ...prev, ...next }));
|
|
12968
13342
|
useEffect5(() => {
|
|
12969
13343
|
if (mode !== "oauth") return;
|
|
12970
13344
|
let live3 = true;
|
|
13345
|
+
const controller = new AbortController();
|
|
12971
13346
|
const safeMerge = (next) => {
|
|
12972
13347
|
if (live3) merge(next);
|
|
12973
13348
|
};
|
|
12974
13349
|
const callbacks = {
|
|
13350
|
+
signal: controller.signal,
|
|
12975
13351
|
onAuth: (info2) => {
|
|
13352
|
+
if (!live3) return;
|
|
12976
13353
|
safeMerge({ authInfo: info2, progress: "Opening your browser to sign in\u2026" });
|
|
12977
13354
|
void services.openLoginUrl(info2.url).then((opened) => {
|
|
12978
13355
|
safeMerge({
|
|
@@ -12980,12 +13357,28 @@ function OAuthFlowDialog(props) {
|
|
|
12980
13357
|
});
|
|
12981
13358
|
});
|
|
12982
13359
|
},
|
|
12983
|
-
onPrompt: (prompt) => new Promise((
|
|
12984
|
-
|
|
13360
|
+
onPrompt: (prompt) => new Promise((resolve11, reject) => {
|
|
13361
|
+
if (!live3) {
|
|
13362
|
+
reject(new DOMException("Sign-in cancelled", "AbortError"));
|
|
13363
|
+
return;
|
|
13364
|
+
}
|
|
13365
|
+
cancelPrompt.current = () => reject(new DOMException("Sign-in cancelled", "AbortError"));
|
|
13366
|
+
pending.current = (value) => {
|
|
13367
|
+
cancelPrompt.current = null;
|
|
13368
|
+
resolve11(value);
|
|
13369
|
+
};
|
|
12985
13370
|
safeMerge({ prompt, inputLabel: prompt.message, inputValue: "" });
|
|
12986
13371
|
}),
|
|
12987
|
-
onManualCodeInput: () => new Promise((
|
|
12988
|
-
|
|
13372
|
+
onManualCodeInput: () => new Promise((resolve11, reject) => {
|
|
13373
|
+
if (!live3) {
|
|
13374
|
+
reject(new DOMException("Sign-in cancelled", "AbortError"));
|
|
13375
|
+
return;
|
|
13376
|
+
}
|
|
13377
|
+
cancelPrompt.current = () => reject(new DOMException("Sign-in cancelled", "AbortError"));
|
|
13378
|
+
pending.current = (value) => {
|
|
13379
|
+
cancelPrompt.current = null;
|
|
13380
|
+
resolve11(value);
|
|
13381
|
+
};
|
|
12989
13382
|
safeMerge({
|
|
12990
13383
|
prompt: { message: "Paste the authorization code or complete redirect URL:" },
|
|
12991
13384
|
inputLabel: "Authorization code or redirect URL",
|
|
@@ -12999,7 +13392,9 @@ function OAuthFlowDialog(props) {
|
|
|
12999
13392
|
void (async () => {
|
|
13000
13393
|
try {
|
|
13001
13394
|
await services.startOAuthLogin(providerId, callbacks, services.vault);
|
|
13395
|
+
if (!live3) return;
|
|
13002
13396
|
await services.refreshGatewayRouting();
|
|
13397
|
+
if (!live3) return;
|
|
13003
13398
|
selectProviderModel(services, providerId);
|
|
13004
13399
|
if (live3) {
|
|
13005
13400
|
dispatch2({
|
|
@@ -13014,15 +13409,23 @@ function OAuthFlowDialog(props) {
|
|
|
13014
13409
|
})();
|
|
13015
13410
|
return () => {
|
|
13016
13411
|
live3 = false;
|
|
13412
|
+
controller.abort();
|
|
13413
|
+
cancelPrompt.current?.();
|
|
13414
|
+
cancelPrompt.current = null;
|
|
13415
|
+
pending.current = null;
|
|
13017
13416
|
};
|
|
13018
13417
|
}, []);
|
|
13019
13418
|
const saveApiKey = () => {
|
|
13020
13419
|
const key = state.inputValue.trim();
|
|
13021
|
-
if (key.length === 0) return;
|
|
13420
|
+
if (key.length === 0 || saving.current) return;
|
|
13421
|
+
saving.current = true;
|
|
13022
13422
|
const account = state.accountId ?? "default";
|
|
13023
13423
|
void (async () => {
|
|
13024
13424
|
try {
|
|
13025
13425
|
await services.vault.putApiKey(providerId, account, key, true);
|
|
13426
|
+
if (!mounted.current) return;
|
|
13427
|
+
await services.refreshGatewayRouting();
|
|
13428
|
+
if (!mounted.current) return;
|
|
13026
13429
|
selectProviderModel(services, providerId);
|
|
13027
13430
|
dispatch2({
|
|
13028
13431
|
type: "status:set",
|
|
@@ -13045,12 +13448,12 @@ function OAuthFlowDialog(props) {
|
|
|
13045
13448
|
saveApiKey();
|
|
13046
13449
|
return;
|
|
13047
13450
|
}
|
|
13048
|
-
const
|
|
13049
|
-
if (
|
|
13451
|
+
const resolve11 = pending.current;
|
|
13452
|
+
if (resolve11 === null) return;
|
|
13050
13453
|
pending.current = null;
|
|
13051
13454
|
const value = state.inputValue;
|
|
13052
13455
|
merge({ inputValue: "", prompt: void 0 });
|
|
13053
|
-
|
|
13456
|
+
resolve11(value);
|
|
13054
13457
|
},
|
|
13055
13458
|
onClose: closeModal
|
|
13056
13459
|
});
|
|
@@ -13205,12 +13608,12 @@ function summarizeInput(input) {
|
|
|
13205
13608
|
}
|
|
13206
13609
|
function ApprovalDialog(props) {
|
|
13207
13610
|
const { payload, closeModal } = props;
|
|
13208
|
-
const { request, resolve:
|
|
13611
|
+
const { request, resolve: resolve11 } = payload;
|
|
13209
13612
|
let settled = false;
|
|
13210
13613
|
const settle = (choice) => {
|
|
13211
13614
|
if (settled) return;
|
|
13212
13615
|
settled = true;
|
|
13213
|
-
|
|
13616
|
+
resolve11(choice);
|
|
13214
13617
|
closeModal();
|
|
13215
13618
|
};
|
|
13216
13619
|
const args = summarizeInput(request.input);
|
|
@@ -13247,8 +13650,18 @@ function ApprovalOverlays(props) {
|
|
|
13247
13650
|
}
|
|
13248
13651
|
|
|
13249
13652
|
// src/console/overlays/host.ts
|
|
13653
|
+
import { Box as Box4, Text as Text4, useInput as useInput3 } from "indusagi/react-host/ink";
|
|
13654
|
+
function UnavailableOverlay({ closeModal }) {
|
|
13655
|
+
useInput3((_input, key) => {
|
|
13656
|
+
if (key.escape || key.return) closeModal();
|
|
13657
|
+
});
|
|
13658
|
+
return jsx6(Box4, { children: jsx6(Text4, { children: "This dialog is unavailable in this host. Esc / Enter to return." }) });
|
|
13659
|
+
}
|
|
13250
13660
|
function OverlayHost(props) {
|
|
13251
13661
|
if (props.modal.kind === "none") return null;
|
|
13662
|
+
if (!props.services && props.modal.kind !== "approval" && props.modal.kind !== "plugin") {
|
|
13663
|
+
return jsx6(UnavailableOverlay, { closeModal: props.closeModal });
|
|
13664
|
+
}
|
|
13252
13665
|
const forwarded = {
|
|
13253
13666
|
modal: props.modal,
|
|
13254
13667
|
services: props.services,
|
|
@@ -13267,31 +13680,31 @@ function OverlayHost(props) {
|
|
|
13267
13680
|
}
|
|
13268
13681
|
|
|
13269
13682
|
// src/console/startup.ts
|
|
13270
|
-
import { existsSync as
|
|
13271
|
-
import { join as
|
|
13683
|
+
import { existsSync as existsSync3, readFileSync as readFileSync11 } from "node:fs";
|
|
13684
|
+
import { join as join16 } from "node:path";
|
|
13272
13685
|
var PROFILE_DIR = ".indusagi";
|
|
13273
13686
|
var CONTEXT_FILES = ["AGENTS.md", "CLAUDE.md"];
|
|
13274
13687
|
function skillRoots(cwd, home) {
|
|
13275
13688
|
return [
|
|
13276
|
-
{ dir:
|
|
13277
|
-
{ dir:
|
|
13689
|
+
{ dir: join16(cwd, PROFILE_DIR, "skills"), origin: "project" },
|
|
13690
|
+
{ dir: join16(home, PROFILE_DIR, "skills"), origin: "user" }
|
|
13278
13691
|
];
|
|
13279
13692
|
}
|
|
13280
13693
|
function macroRoots(cwd, home) {
|
|
13281
13694
|
return [
|
|
13282
|
-
{ dir:
|
|
13283
|
-
{ dir:
|
|
13695
|
+
{ dir: join16(cwd, PROFILE_DIR, "commands"), origin: "project", label: "project" },
|
|
13696
|
+
{ dir: join16(home, PROFILE_DIR, "commands"), origin: "user", label: "user" }
|
|
13284
13697
|
];
|
|
13285
13698
|
}
|
|
13286
|
-
function shortenPath2(
|
|
13287
|
-
if (cwd.length > 0 &&
|
|
13288
|
-
const rest =
|
|
13699
|
+
function shortenPath2(path5, cwd, home) {
|
|
13700
|
+
if (cwd.length > 0 && path5.startsWith(cwd)) {
|
|
13701
|
+
const rest = path5.slice(cwd.length).replace(/^[/\\]+/, "");
|
|
13289
13702
|
return rest.length > 0 ? `./${rest}` : ".";
|
|
13290
13703
|
}
|
|
13291
|
-
if (home.length > 0 &&
|
|
13292
|
-
return `~${
|
|
13704
|
+
if (home.length > 0 && path5.startsWith(home)) {
|
|
13705
|
+
return `~${path5.slice(home.length)}`;
|
|
13293
13706
|
}
|
|
13294
|
-
return
|
|
13707
|
+
return path5;
|
|
13295
13708
|
}
|
|
13296
13709
|
var MAX_SECTION_LINES = 6;
|
|
13297
13710
|
function capLines(lines) {
|
|
@@ -13310,10 +13723,10 @@ function gatherContext(cwd, home) {
|
|
|
13310
13723
|
for (const root of [cwd, home]) {
|
|
13311
13724
|
if (root.length === 0) continue;
|
|
13312
13725
|
for (const name of CONTEXT_FILES) {
|
|
13313
|
-
const
|
|
13314
|
-
if (seen.has(
|
|
13315
|
-
seen.add(
|
|
13316
|
-
if (
|
|
13726
|
+
const path5 = join16(root, name);
|
|
13727
|
+
if (seen.has(path5)) continue;
|
|
13728
|
+
seen.add(path5);
|
|
13729
|
+
if (existsSync3(path5)) out2.push(shortenPath2(path5, cwd, home));
|
|
13317
13730
|
}
|
|
13318
13731
|
}
|
|
13319
13732
|
return out2;
|
|
@@ -13377,12 +13790,12 @@ function mascotRows(face) {
|
|
|
13377
13790
|
];
|
|
13378
13791
|
}
|
|
13379
13792
|
var TIPS = [
|
|
13380
|
-
"Run /
|
|
13793
|
+
"Run /help to explore commands and configured skill helpers",
|
|
13381
13794
|
'Ask in plain English \u2014 try "fix the failing tests" or "explain src/agent.ts"',
|
|
13382
|
-
"Shift+Tab cycles
|
|
13795
|
+
"Shift+Tab cycles: default \u2192 accept-edits \u2192 plan \u2192 bypass",
|
|
13383
13796
|
"Type @ to attach a file, or paste an image straight into the prompt",
|
|
13384
13797
|
"Run /status to check your model, account, and connectivity",
|
|
13385
|
-
"Use /
|
|
13798
|
+
"Use /help to discover specialized commands for the task at hand"
|
|
13386
13799
|
];
|
|
13387
13800
|
var WHATS_NEW = [
|
|
13388
13801
|
"Ctrl+X runs your newest queued message NOW \u2014 the current run stops cleanly",
|
|
@@ -13402,148 +13815,21 @@ function pickWelcomeVariant(seed) {
|
|
|
13402
13815
|
var PINNED_WELCOME_SEED = 12;
|
|
13403
13816
|
|
|
13404
13817
|
// src/console/components/AgentsView.ts
|
|
13405
|
-
import { useState as
|
|
13406
|
-
import { Box as
|
|
13818
|
+
import { useState as useState7 } from "indusagi/react-host";
|
|
13819
|
+
import { Box as Box6, Text as Text6, useInput as useInput4 } from "indusagi/react-host/ink";
|
|
13407
13820
|
import { wrapSelectionIndex as wrapSelectionIndex2 } from "indusagi/react-ink";
|
|
13821
|
+
import { jsx as jsx8, jsxs as jsxs5 } from "indusagi/react-host/jsx-runtime";
|
|
13822
|
+
|
|
13823
|
+
// src/console/components/BackgroundAgents.ts
|
|
13824
|
+
import { Box as Box5, Text as Text5 } from "indusagi/react-host/ink";
|
|
13825
|
+
import { useEffect as useEffect6, useState as useState6 } from "indusagi/react-host";
|
|
13826
|
+
import { splitAssistantMessage } from "indusagi/react-ink";
|
|
13408
13827
|
import { jsx as jsx7, jsxs as jsxs4 } from "indusagi/react-host/jsx-runtime";
|
|
13409
|
-
function
|
|
13410
|
-
|
|
13411
|
-
|
|
13412
|
-
|
|
13413
|
-
|
|
13414
|
-
if (flat.length <= width) return flat;
|
|
13415
|
-
if (width <= 1) return flat.slice(0, width);
|
|
13416
|
-
return `${flat.slice(0, width - 1)}\u2026`;
|
|
13417
|
-
}
|
|
13418
|
-
function runStatusLine(run, now, tokens) {
|
|
13419
|
-
let head;
|
|
13420
|
-
if (run.status === "error") head = "failed";
|
|
13421
|
-
else if (run.status === "done") head = "done";
|
|
13422
|
-
else if (run.startedAt > 0 && now >= run.startedAt) {
|
|
13423
|
-
head = `${Math.max(0, Math.round((now - run.startedAt) / 1e3))}s`;
|
|
13424
|
-
} else head = "working";
|
|
13425
|
-
const tok = tokens !== void 0 && tokens > 0 ? ` \xB7 \u2193 ${formatTokens2(tokens)} tokens` : "";
|
|
13426
|
-
return `${head}${tok}`;
|
|
13427
|
-
}
|
|
13428
|
-
var NAME_WIDTH = 12;
|
|
13429
|
-
function ActivityRow({ theme, line }) {
|
|
13430
|
-
if (line.tone === "tool") {
|
|
13431
|
-
return jsxs4(Box4, {
|
|
13432
|
-
children: [
|
|
13433
|
-
jsx7(Text4, { children: theme.color("success", "\u25CF ") }),
|
|
13434
|
-
jsx7(Text4, { children: theme.color("text", clampLine(line.text, 96)) })
|
|
13435
|
-
]
|
|
13436
|
-
});
|
|
13437
|
-
}
|
|
13438
|
-
if (line.tone === "result") {
|
|
13439
|
-
return jsx7(Box4, { marginLeft: 2, children: jsx7(Text4, { children: theme.dim(`\u2514 ${clampLine(line.text, 92)}`) }) });
|
|
13440
|
-
}
|
|
13441
|
-
return jsxs4(Box4, {
|
|
13442
|
-
children: [
|
|
13443
|
-
jsx7(Text4, { children: theme.color("accent", "\u25CF ") }),
|
|
13444
|
-
jsx7(Text4, { children: theme.color("text", clampLine(line.text, 96)) })
|
|
13445
|
-
]
|
|
13446
|
-
});
|
|
13447
|
-
}
|
|
13448
|
-
function AgentsView({ theme, runs, activity, tokens, now, onExit }) {
|
|
13449
|
-
const clock = now ?? Date.now();
|
|
13450
|
-
const [selectedIndex, setSelectedIndex] = useState6(runs.length > 0 ? 1 : 0);
|
|
13451
|
-
const rowCount = runs.length + 1;
|
|
13452
|
-
const index = Math.min(selectedIndex, rowCount - 1);
|
|
13453
|
-
const viewed = index > 0 ? runs[index - 1] : void 0;
|
|
13454
|
-
useInput3((input, key) => {
|
|
13455
|
-
if (key.escape || input === "x") return onExit();
|
|
13456
|
-
if (key.upArrow) return setSelectedIndex((i) => wrapSelectionIndex2(Math.min(i, rowCount - 1), -1, rowCount));
|
|
13457
|
-
if (key.downArrow) return setSelectedIndex((i) => wrapSelectionIndex2(Math.min(i, rowCount - 1), 1, rowCount));
|
|
13458
|
-
if (key.return && index === 0) onExit();
|
|
13459
|
-
});
|
|
13460
|
-
const lines = viewed ? activity[viewed.id] ?? [] : [];
|
|
13461
|
-
return jsxs4(Box4, {
|
|
13462
|
-
flexDirection: "column",
|
|
13463
|
-
marginTop: 1,
|
|
13464
|
-
children: [
|
|
13465
|
-
viewed ? jsxs4(Box4, {
|
|
13466
|
-
flexDirection: "column",
|
|
13467
|
-
children: [
|
|
13468
|
-
jsxs4(Box4, {
|
|
13469
|
-
marginBottom: 1,
|
|
13470
|
-
children: [
|
|
13471
|
-
jsx7(Text4, { children: theme.color("accent", "\u2736 ") }),
|
|
13472
|
-
jsx7(Text4, { bold: true, children: theme.color("accent", viewed.name) }),
|
|
13473
|
-
jsx7(Text4, { children: theme.dim(` ${runStatusLine(viewed, clock, tokens[viewed.id])}`) })
|
|
13474
|
-
]
|
|
13475
|
-
}),
|
|
13476
|
-
lines.length === 0 ? jsx7(Text4, { children: theme.muted(" Waiting for the first step\u2026") }) : lines.map((line, i) => jsx7(ActivityRow, { theme, line }, i)),
|
|
13477
|
-
jsx7(Box4, {
|
|
13478
|
-
marginTop: 1,
|
|
13479
|
-
children: jsx7(Text4, { wrap: "truncate", children: theme.muted(`\u2514 ${clampLine(viewed.objective, 100)}`) })
|
|
13480
|
-
})
|
|
13481
|
-
]
|
|
13482
|
-
}) : jsxs4(Box4, {
|
|
13483
|
-
children: [
|
|
13484
|
-
jsx7(Text4, { children: theme.muted("Select a sub-agent to view its live activity, or press Enter on ") }),
|
|
13485
|
-
jsx7(Text4, { bold: true, children: theme.color("text", "main") }),
|
|
13486
|
-
jsx7(Text4, { children: theme.muted(" to return.") })
|
|
13487
|
-
]
|
|
13488
|
-
}),
|
|
13489
|
-
jsxs4(Box4, {
|
|
13490
|
-
flexDirection: "column",
|
|
13491
|
-
marginTop: 1,
|
|
13492
|
-
borderStyle: "single",
|
|
13493
|
-
borderColor: theme.colors["borderMuted"],
|
|
13494
|
-
borderBottom: false,
|
|
13495
|
-
borderLeft: false,
|
|
13496
|
-
borderRight: false,
|
|
13497
|
-
paddingTop: 0,
|
|
13498
|
-
children: [
|
|
13499
|
-
jsxs4(Box4, {
|
|
13500
|
-
children: [
|
|
13501
|
-
jsx7(Text4, { children: index === 0 ? theme.color("accent", "\u203A ") : " " }),
|
|
13502
|
-
jsx7(Text4, { children: index === 0 ? theme.color("text", "\u25CF ") : theme.dim("\u25CB ") }),
|
|
13503
|
-
jsx7(Text4, { bold: index === 0, children: theme.color("text", "main") })
|
|
13504
|
-
]
|
|
13505
|
-
}),
|
|
13506
|
-
runs.map((run, i) => {
|
|
13507
|
-
const selected = index === i + 1;
|
|
13508
|
-
const dot = run.status === "running" ? theme.color("accent", "\u25D0") : run.status === "error" ? theme.color("error", "\u25CF") : theme.color("success", "\u25CF");
|
|
13509
|
-
return jsxs4(
|
|
13510
|
-
Box4,
|
|
13511
|
-
{
|
|
13512
|
-
children: [
|
|
13513
|
-
jsx7(Text4, { children: selected ? theme.color("accent", "\u203A ") : " " }),
|
|
13514
|
-
jsx7(Box4, { width: 2, flexShrink: 0, children: jsx7(Text4, { children: dot }) }),
|
|
13515
|
-
jsx7(Box4, {
|
|
13516
|
-
width: NAME_WIDTH,
|
|
13517
|
-
flexShrink: 0,
|
|
13518
|
-
children: jsx7(Text4, { bold: selected, children: theme.color("accent", clampLine(run.name, NAME_WIDTH - 1)) })
|
|
13519
|
-
}),
|
|
13520
|
-
jsx7(Box4, {
|
|
13521
|
-
flexGrow: 1,
|
|
13522
|
-
flexShrink: 1,
|
|
13523
|
-
children: jsx7(Text4, { wrap: "truncate", children: theme.muted(clampLine(run.objective, 56)) })
|
|
13524
|
-
}),
|
|
13525
|
-
jsx7(Text4, { children: theme.dim(` ${runStatusLine(run, clock, tokens[run.id])}`) })
|
|
13526
|
-
]
|
|
13527
|
-
},
|
|
13528
|
-
run.id
|
|
13529
|
-
);
|
|
13530
|
-
})
|
|
13531
|
-
]
|
|
13532
|
-
}),
|
|
13533
|
-
jsx7(Box4, { marginTop: 1, children: jsx7(Text4, { children: theme.dim("\u2191/\u2193 select \xB7 Enter to view \xB7 Enter on main / Esc to return") }) })
|
|
13534
|
-
]
|
|
13535
|
-
});
|
|
13536
|
-
}
|
|
13537
|
-
|
|
13538
|
-
// src/console/components/BackgroundAgents.ts
|
|
13539
|
-
import { Box as Box5, Text as Text5 } from "indusagi/react-host/ink";
|
|
13540
|
-
import { splitAssistantMessage } from "indusagi/react-ink";
|
|
13541
|
-
import { jsx as jsx8, jsxs as jsxs5 } from "indusagi/react-host/jsx-runtime";
|
|
13542
|
-
function readString2(args, key) {
|
|
13543
|
-
const value = args[key];
|
|
13544
|
-
if (typeof value !== "string") return void 0;
|
|
13545
|
-
const trimmed = value.trim();
|
|
13546
|
-
return trimmed.length > 0 ? trimmed : void 0;
|
|
13828
|
+
function readString2(args, key) {
|
|
13829
|
+
const value = args[key];
|
|
13830
|
+
if (typeof value !== "string") return void 0;
|
|
13831
|
+
const trimmed = value.trim();
|
|
13832
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
13547
13833
|
}
|
|
13548
13834
|
function deriveAgentRuns(messages) {
|
|
13549
13835
|
const runs = [];
|
|
@@ -13574,7 +13860,7 @@ function deriveAgentRuns(messages) {
|
|
|
13574
13860
|
return runs.map((run) => ({ ...run, status: status.get(run.id) ?? run.status }));
|
|
13575
13861
|
}
|
|
13576
13862
|
var MAX_VISIBLE_RUNS = 8;
|
|
13577
|
-
var
|
|
13863
|
+
var NAME_WIDTH = 12;
|
|
13578
13864
|
function clamp2(text, width) {
|
|
13579
13865
|
if (text.length <= width) return text;
|
|
13580
13866
|
if (width <= 1) return text.slice(0, width);
|
|
@@ -13584,7 +13870,7 @@ var OBJECTIVE_WIDTH = 64;
|
|
|
13584
13870
|
function oneLine(text) {
|
|
13585
13871
|
return text.replace(/\s+/g, " ").trim();
|
|
13586
13872
|
}
|
|
13587
|
-
function
|
|
13873
|
+
function formatTokens2(tokens) {
|
|
13588
13874
|
if (tokens >= 1e3) return `${(tokens / 1e3).toFixed(1)}k`;
|
|
13589
13875
|
return String(tokens);
|
|
13590
13876
|
}
|
|
@@ -13596,65 +13882,206 @@ function statusText(run, now, tokens) {
|
|
|
13596
13882
|
head = `${Math.max(0, Math.round((now - run.startedAt) / 1e3))}s`;
|
|
13597
13883
|
} else head = "running";
|
|
13598
13884
|
if (tokens !== void 0 && tokens > 0) {
|
|
13599
|
-
return `${head} \xB7 \u2193 ${
|
|
13885
|
+
return `${head} \xB7 \u2193 ${formatTokens2(tokens)} tokens`;
|
|
13600
13886
|
}
|
|
13601
13887
|
return head;
|
|
13602
13888
|
}
|
|
13889
|
+
function useAgentClock(active, supplied) {
|
|
13890
|
+
const [now, setNow] = useState6(Date.now);
|
|
13891
|
+
useEffect6(() => {
|
|
13892
|
+
if (!active || supplied !== void 0) return;
|
|
13893
|
+
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
13894
|
+
return () => clearInterval(timer);
|
|
13895
|
+
}, [active, supplied]);
|
|
13896
|
+
return supplied ?? now;
|
|
13897
|
+
}
|
|
13603
13898
|
function BackgroundAgents({ theme, runs, tokens, now }) {
|
|
13604
|
-
const clock =
|
|
13899
|
+
const clock = useAgentClock(runs.some((run) => run.status === "running"), now);
|
|
13605
13900
|
const runningCount = runs.reduce((n, run) => run.status === "running" ? n + 1 : n, 0);
|
|
13606
13901
|
if (runningCount === 0) return null;
|
|
13607
|
-
const
|
|
13608
|
-
|
|
13902
|
+
const running = runs.filter((run) => run.status === "running");
|
|
13903
|
+
const recentDone = runs.filter((run) => run.status !== "running").slice(-Math.max(0, MAX_VISIBLE_RUNS - running.length));
|
|
13904
|
+
const visible = [...running, ...recentDone].slice(0, MAX_VISIBLE_RUNS);
|
|
13905
|
+
return jsxs4(Box5, {
|
|
13609
13906
|
flexDirection: "column",
|
|
13610
13907
|
marginTop: 1,
|
|
13611
13908
|
children: [
|
|
13612
|
-
|
|
13909
|
+
jsxs4(Box5, {
|
|
13613
13910
|
children: [
|
|
13614
|
-
|
|
13615
|
-
|
|
13911
|
+
jsx7(Text5, { children: theme.color("text", "\u25CF ") }),
|
|
13912
|
+
jsx7(Text5, { bold: true, children: theme.color("text", "main") })
|
|
13616
13913
|
]
|
|
13617
13914
|
}),
|
|
13618
13915
|
visible.map((run) => {
|
|
13619
13916
|
const dot = run.status === "running" ? theme.color("accent", "\u25D0") : run.status === "error" ? theme.color("error", "\u25CF") : theme.color("success", "\u25CF");
|
|
13620
|
-
return
|
|
13917
|
+
return jsxs4(
|
|
13621
13918
|
Box5,
|
|
13622
13919
|
{
|
|
13623
13920
|
children: [
|
|
13624
|
-
|
|
13625
|
-
|
|
13626
|
-
width:
|
|
13921
|
+
jsx7(Box5, { width: 2, flexShrink: 0, children: jsx7(Text5, { children: dot }) }),
|
|
13922
|
+
jsx7(Box5, {
|
|
13923
|
+
width: NAME_WIDTH,
|
|
13627
13924
|
flexShrink: 0,
|
|
13628
|
-
children:
|
|
13925
|
+
children: jsx7(Text5, { bold: true, children: theme.color("accent", clamp2(run.name, NAME_WIDTH - 1)) })
|
|
13629
13926
|
}),
|
|
13630
|
-
|
|
13927
|
+
jsx7(Box5, {
|
|
13631
13928
|
flexGrow: 1,
|
|
13632
13929
|
flexShrink: 1,
|
|
13633
|
-
children:
|
|
13930
|
+
children: jsx7(Text5, { wrap: "truncate", children: theme.muted(clamp2(oneLine(run.objective), OBJECTIVE_WIDTH)) })
|
|
13634
13931
|
}),
|
|
13635
|
-
|
|
13932
|
+
jsx7(Text5, { children: theme.dim(` ${statusText(run, clock, tokens?.[run.id])}`) })
|
|
13636
13933
|
]
|
|
13637
13934
|
},
|
|
13638
13935
|
run.id
|
|
13639
13936
|
);
|
|
13640
13937
|
}),
|
|
13641
|
-
|
|
13938
|
+
jsxs4(Box5, {
|
|
13642
13939
|
marginTop: 1,
|
|
13643
13940
|
children: [
|
|
13644
|
-
|
|
13645
|
-
|
|
13941
|
+
jsx7(Text5, { children: theme.color("accent", "\u2736 ") }),
|
|
13942
|
+
jsx7(Text5, { children: theme.muted(`Waiting for ${runningCount} background agent${runningCount === 1 ? "" : "s"} to finish`) })
|
|
13646
13943
|
]
|
|
13647
13944
|
})
|
|
13648
13945
|
]
|
|
13649
13946
|
});
|
|
13650
13947
|
}
|
|
13651
13948
|
|
|
13949
|
+
// src/console/components/AgentsView.ts
|
|
13950
|
+
function formatTokens3(tokens) {
|
|
13951
|
+
return tokens >= 1e3 ? `${(tokens / 1e3).toFixed(1)}k` : String(tokens);
|
|
13952
|
+
}
|
|
13953
|
+
function clampLine(text, width) {
|
|
13954
|
+
const flat = text.replace(/\s+/g, " ").trim();
|
|
13955
|
+
if (flat.length <= width) return flat;
|
|
13956
|
+
if (width <= 1) return flat.slice(0, width);
|
|
13957
|
+
return `${flat.slice(0, width - 1)}\u2026`;
|
|
13958
|
+
}
|
|
13959
|
+
function runStatusLine(run, now, tokens) {
|
|
13960
|
+
let head;
|
|
13961
|
+
if (run.status === "error") head = "failed";
|
|
13962
|
+
else if (run.status === "done") head = "done";
|
|
13963
|
+
else if (run.startedAt > 0 && now >= run.startedAt) {
|
|
13964
|
+
head = `${Math.max(0, Math.round((now - run.startedAt) / 1e3))}s`;
|
|
13965
|
+
} else head = "working";
|
|
13966
|
+
const tok = tokens !== void 0 && tokens > 0 ? ` \xB7 \u2193 ${formatTokens3(tokens)} tokens` : "";
|
|
13967
|
+
return `${head}${tok}`;
|
|
13968
|
+
}
|
|
13969
|
+
var NAME_WIDTH2 = 12;
|
|
13970
|
+
function ActivityRow({ theme, line }) {
|
|
13971
|
+
if (line.tone === "tool") {
|
|
13972
|
+
return jsxs5(Box6, {
|
|
13973
|
+
children: [
|
|
13974
|
+
jsx8(Text6, { children: theme.color("success", "\u25CF ") }),
|
|
13975
|
+
jsx8(Text6, { children: theme.color("text", clampLine(line.text, 96)) })
|
|
13976
|
+
]
|
|
13977
|
+
});
|
|
13978
|
+
}
|
|
13979
|
+
if (line.tone === "result") {
|
|
13980
|
+
return jsx8(Box6, { marginLeft: 2, children: jsx8(Text6, { children: theme.dim(`\u2514 ${clampLine(line.text, 92)}`) }) });
|
|
13981
|
+
}
|
|
13982
|
+
return jsxs5(Box6, {
|
|
13983
|
+
children: [
|
|
13984
|
+
jsx8(Text6, { children: theme.color("accent", "\u25CF ") }),
|
|
13985
|
+
jsx8(Text6, { children: theme.color("text", clampLine(line.text, 96)) })
|
|
13986
|
+
]
|
|
13987
|
+
});
|
|
13988
|
+
}
|
|
13989
|
+
function AgentsView({ theme, runs, activity, tokens, now, onExit }) {
|
|
13990
|
+
const clock = useAgentClock(runs.some((run) => run.status === "running"), now);
|
|
13991
|
+
const [selectedIndex, setSelectedIndex] = useState7(runs.length > 0 ? 1 : 0);
|
|
13992
|
+
const rowCount = runs.length + 1;
|
|
13993
|
+
const index = Math.min(selectedIndex, rowCount - 1);
|
|
13994
|
+
const viewed = index > 0 ? runs[index - 1] : void 0;
|
|
13995
|
+
useInput4((input, key) => {
|
|
13996
|
+
if (key.escape || input === "x") return onExit();
|
|
13997
|
+
if (key.upArrow) return setSelectedIndex((i) => wrapSelectionIndex2(Math.min(i, rowCount - 1), -1, rowCount));
|
|
13998
|
+
if (key.downArrow) return setSelectedIndex((i) => wrapSelectionIndex2(Math.min(i, rowCount - 1), 1, rowCount));
|
|
13999
|
+
if (key.return && index === 0) onExit();
|
|
14000
|
+
});
|
|
14001
|
+
const lines = viewed ? activity[viewed.id] ?? [] : [];
|
|
14002
|
+
return jsxs5(Box6, {
|
|
14003
|
+
flexDirection: "column",
|
|
14004
|
+
marginTop: 1,
|
|
14005
|
+
children: [
|
|
14006
|
+
viewed ? jsxs5(Box6, {
|
|
14007
|
+
flexDirection: "column",
|
|
14008
|
+
children: [
|
|
14009
|
+
jsxs5(Box6, {
|
|
14010
|
+
marginBottom: 1,
|
|
14011
|
+
children: [
|
|
14012
|
+
jsx8(Text6, { children: theme.color("accent", "\u2736 ") }),
|
|
14013
|
+
jsx8(Text6, { bold: true, children: theme.color("accent", viewed.name) }),
|
|
14014
|
+
jsx8(Text6, { children: theme.dim(` ${runStatusLine(viewed, clock, tokens[viewed.id])}`) })
|
|
14015
|
+
]
|
|
14016
|
+
}),
|
|
14017
|
+
lines.length === 0 ? jsx8(Text6, { children: theme.muted(" Waiting for the first step\u2026") }) : lines.map((line, i) => jsx8(ActivityRow, { theme, line }, i)),
|
|
14018
|
+
jsx8(Box6, {
|
|
14019
|
+
marginTop: 1,
|
|
14020
|
+
children: jsx8(Text6, { wrap: "truncate", children: theme.muted(`\u2514 ${clampLine(viewed.objective, 100)}`) })
|
|
14021
|
+
})
|
|
14022
|
+
]
|
|
14023
|
+
}) : jsxs5(Box6, {
|
|
14024
|
+
children: [
|
|
14025
|
+
jsx8(Text6, { children: theme.muted("Select a sub-agent to view its live activity, or press Enter on ") }),
|
|
14026
|
+
jsx8(Text6, { bold: true, children: theme.color("text", "main") }),
|
|
14027
|
+
jsx8(Text6, { children: theme.muted(" to return.") })
|
|
14028
|
+
]
|
|
14029
|
+
}),
|
|
14030
|
+
jsxs5(Box6, {
|
|
14031
|
+
flexDirection: "column",
|
|
14032
|
+
marginTop: 1,
|
|
14033
|
+
borderStyle: "single",
|
|
14034
|
+
borderColor: theme.colors["borderMuted"],
|
|
14035
|
+
borderBottom: false,
|
|
14036
|
+
borderLeft: false,
|
|
14037
|
+
borderRight: false,
|
|
14038
|
+
paddingTop: 0,
|
|
14039
|
+
children: [
|
|
14040
|
+
jsxs5(Box6, {
|
|
14041
|
+
children: [
|
|
14042
|
+
jsx8(Text6, { children: index === 0 ? theme.color("accent", "\u203A ") : " " }),
|
|
14043
|
+
jsx8(Text6, { children: index === 0 ? theme.color("text", "\u25CF ") : theme.dim("\u25CB ") }),
|
|
14044
|
+
jsx8(Text6, { bold: index === 0, children: theme.color("text", "main") })
|
|
14045
|
+
]
|
|
14046
|
+
}),
|
|
14047
|
+
runs.map((run, i) => {
|
|
14048
|
+
const selected = index === i + 1;
|
|
14049
|
+
const dot = run.status === "running" ? theme.color("accent", "\u25D0") : run.status === "error" ? theme.color("error", "\u25CF") : theme.color("success", "\u25CF");
|
|
14050
|
+
return jsxs5(
|
|
14051
|
+
Box6,
|
|
14052
|
+
{
|
|
14053
|
+
children: [
|
|
14054
|
+
jsx8(Text6, { children: selected ? theme.color("accent", "\u203A ") : " " }),
|
|
14055
|
+
jsx8(Box6, { width: 2, flexShrink: 0, children: jsx8(Text6, { children: dot }) }),
|
|
14056
|
+
jsx8(Box6, {
|
|
14057
|
+
width: NAME_WIDTH2,
|
|
14058
|
+
flexShrink: 0,
|
|
14059
|
+
children: jsx8(Text6, { bold: selected, children: theme.color("accent", clampLine(run.name, NAME_WIDTH2 - 1)) })
|
|
14060
|
+
}),
|
|
14061
|
+
jsx8(Box6, {
|
|
14062
|
+
flexGrow: 1,
|
|
14063
|
+
flexShrink: 1,
|
|
14064
|
+
children: jsx8(Text6, { wrap: "truncate", children: theme.muted(clampLine(run.objective, 56)) })
|
|
14065
|
+
}),
|
|
14066
|
+
jsx8(Text6, { children: theme.dim(` ${runStatusLine(run, clock, tokens[run.id])}`) })
|
|
14067
|
+
]
|
|
14068
|
+
},
|
|
14069
|
+
run.id
|
|
14070
|
+
);
|
|
14071
|
+
})
|
|
14072
|
+
]
|
|
14073
|
+
}),
|
|
14074
|
+
jsx8(Box6, { marginTop: 1, children: jsx8(Text6, { children: theme.dim("\u2191/\u2193 select \xB7 Enter to view \xB7 Enter on main / Esc to return") }) })
|
|
14075
|
+
]
|
|
14076
|
+
});
|
|
14077
|
+
}
|
|
14078
|
+
|
|
13652
14079
|
// src/console/components/Banner.ts
|
|
13653
|
-
import { Fragment as Fragment3, jsx as
|
|
13654
|
-
import { Box as
|
|
14080
|
+
import { Fragment as Fragment3, jsx as jsx10, jsxs as jsxs6 } from "indusagi/react-host/jsx-runtime";
|
|
14081
|
+
import { Box as Box8, Text as Text7 } from "indusagi/react-host/ink";
|
|
13655
14082
|
import { ChangelogBlock } from "indusagi/react-ink";
|
|
13656
|
-
import { homedir as
|
|
13657
|
-
import { basename as
|
|
14083
|
+
import { homedir as homedir5 } from "node:os";
|
|
14084
|
+
import { basename as basename7 } from "node:path";
|
|
13658
14085
|
|
|
13659
14086
|
// src/console/components/banner-sweep.ts
|
|
13660
14087
|
var WELCOME_FALLBACK = "Welcome back!";
|
|
@@ -13665,6 +14092,70 @@ function welcomeLine(name) {
|
|
|
13665
14092
|
if (trimmed.length === 0 || trimmed.length > MAX_NAME) return WELCOME_FALLBACK;
|
|
13666
14093
|
return `Welcome back, ${trimmed}!`;
|
|
13667
14094
|
}
|
|
14095
|
+
function rowGradient(rowIndex, rowCount, primaryHex, secondaryHex) {
|
|
14096
|
+
if (rowCount <= 1) return primaryHex;
|
|
14097
|
+
const t = Math.max(0, Math.min(1, rowIndex / (rowCount - 1)));
|
|
14098
|
+
const a = Number.parseInt(primaryHex.replace("#", ""), 16);
|
|
14099
|
+
const b = Number.parseInt(secondaryHex.replace("#", ""), 16);
|
|
14100
|
+
const channel = (shift) => Math.round((a >> shift & 255) * (1 - t) + (b >> shift & 255) * t).toString(16).padStart(2, "0");
|
|
14101
|
+
return `#${channel(16)}${channel(8)}${channel(0)}`;
|
|
14102
|
+
}
|
|
14103
|
+
|
|
14104
|
+
// src/console/components/Banner.ts
|
|
14105
|
+
import chalk3 from "chalk";
|
|
14106
|
+
|
|
14107
|
+
// src/console/components/ScrollViewport.ts
|
|
14108
|
+
import React2, { useEffect as useEffect7, useState as useState8 } from "indusagi/react-host";
|
|
14109
|
+
import { Box as Box7, useInput as useInput5 } from "indusagi/react-host/ink";
|
|
14110
|
+
import { measureElement, useStdout } from "ink";
|
|
14111
|
+
import { jsx as jsx9 } from "indusagi/react-host/jsx-runtime";
|
|
14112
|
+
function useTerminalSize() {
|
|
14113
|
+
const { stdout } = useStdout();
|
|
14114
|
+
const read = () => ({ columns: Math.max(1, stdout.columns || 80), rows: Math.max(1, stdout.rows || 24) });
|
|
14115
|
+
const [size, setSize] = useState8(read);
|
|
14116
|
+
useEffect7(() => {
|
|
14117
|
+
const resize = () => setSize(read());
|
|
14118
|
+
stdout.on("resize", resize);
|
|
14119
|
+
return () => {
|
|
14120
|
+
stdout.off("resize", resize);
|
|
14121
|
+
};
|
|
14122
|
+
}, [stdout]);
|
|
14123
|
+
return size;
|
|
14124
|
+
}
|
|
14125
|
+
function ScrollViewport({ children, active = true, follow = true }) {
|
|
14126
|
+
const outer = React2.useRef(null);
|
|
14127
|
+
const inner = React2.useRef(null);
|
|
14128
|
+
const [metrics, setMetrics] = useState8({ height: 1, content: 1 });
|
|
14129
|
+
const [offset, setOffset] = useState8(0);
|
|
14130
|
+
useEffect7(() => {
|
|
14131
|
+
if (!outer.current || !inner.current) return;
|
|
14132
|
+
const height = measureElement(outer.current).height;
|
|
14133
|
+
const content = measureElement(inner.current).height;
|
|
14134
|
+
if (metrics.height !== height || metrics.content !== content) {
|
|
14135
|
+
const oldMax = Math.max(0, metrics.content - metrics.height);
|
|
14136
|
+
const newMax = Math.max(0, content - height);
|
|
14137
|
+
if (follow) setOffset((n) => n === 0 ? 0 : Math.max(0, Math.min(newMax, n + newMax - oldMax)));
|
|
14138
|
+
setMetrics({ height, content });
|
|
14139
|
+
}
|
|
14140
|
+
});
|
|
14141
|
+
const max = Math.max(0, metrics.content - metrics.height);
|
|
14142
|
+
const scroll = Math.min(max, offset);
|
|
14143
|
+
useInput5((_input, key) => {
|
|
14144
|
+
const step = Math.max(1, metrics.height - 2);
|
|
14145
|
+
if (key.pageUp) setOffset((n) => Math.min(max, n + (follow ? step : -step)));
|
|
14146
|
+
if (key.pageDown) setOffset((n) => Math.max(0, Math.min(max, n + (follow ? -step : step))));
|
|
14147
|
+
}, { isActive: active });
|
|
14148
|
+
const top = follow ? Math.max(0, max - scroll) : Math.max(0, scroll);
|
|
14149
|
+
return jsx9(Box7, {
|
|
14150
|
+
ref: outer,
|
|
14151
|
+
flexDirection: "column",
|
|
14152
|
+
flexGrow: 1,
|
|
14153
|
+
flexBasis: 0,
|
|
14154
|
+
minHeight: 1,
|
|
14155
|
+
overflow: "hidden",
|
|
14156
|
+
children: jsx9(Box7, { ref: inner, flexDirection: "column", flexShrink: 0, marginTop: -top, children })
|
|
14157
|
+
});
|
|
14158
|
+
}
|
|
13668
14159
|
|
|
13669
14160
|
// src/console/components/Banner.ts
|
|
13670
14161
|
var BRAND2 = "IndusCode";
|
|
@@ -13677,12 +14168,16 @@ var WORDMARK_ROWS = [
|
|
|
13677
14168
|
"\u2588\u2588\u2551\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551",
|
|
13678
14169
|
"\u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
|
|
13679
14170
|
];
|
|
14171
|
+
function StartupSummary({ theme, startup }) {
|
|
14172
|
+
if (!startup?.sections.length) return null;
|
|
14173
|
+
return jsx10(Text7, { wrap: "truncate-end", children: theme.muted(startup.sections.map((section2) => `${section2.title}: ${section2.count}`).join(" \xB7 ")) });
|
|
14174
|
+
}
|
|
13680
14175
|
function StartupNotices({ theme, notices }) {
|
|
13681
14176
|
if (notices.length === 0) return null;
|
|
13682
|
-
return
|
|
14177
|
+
return jsx10(Box8, {
|
|
13683
14178
|
flexDirection: "column",
|
|
13684
14179
|
marginBottom: 1,
|
|
13685
|
-
children: notices.map((notice, index) =>
|
|
14180
|
+
children: notices.map((notice, index) => jsx10(Text7, { children: paintNotice(theme, notice) }, index))
|
|
13686
14181
|
});
|
|
13687
14182
|
}
|
|
13688
14183
|
function paintNotice(theme, notice) {
|
|
@@ -13698,15 +14193,15 @@ function paintNotice(theme, notice) {
|
|
|
13698
14193
|
}
|
|
13699
14194
|
function StartupChangelogBlock({ theme, changelog }) {
|
|
13700
14195
|
if (changelog.mode === "full" && changelog.markdown !== void 0) {
|
|
13701
|
-
return
|
|
14196
|
+
return jsx10(ChangelogBlock, { markdown: changelog.markdown, theme, title: "What is new" });
|
|
13702
14197
|
}
|
|
13703
14198
|
if (changelog.mode === "condensed") {
|
|
13704
|
-
return jsxs6(
|
|
14199
|
+
return jsxs6(Box8, {
|
|
13705
14200
|
marginTop: 1,
|
|
13706
14201
|
children: [
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
14202
|
+
jsx10(Text7, { children: theme.muted(`Updated to v${changelog.version}. Use `) }),
|
|
14203
|
+
jsx10(Text7, { children: theme.color("accent", "/changelog") }),
|
|
14204
|
+
jsx10(Text7, { children: theme.muted(" to view the full changelog.") })
|
|
13710
14205
|
]
|
|
13711
14206
|
});
|
|
13712
14207
|
}
|
|
@@ -13716,46 +14211,46 @@ function WelcomeLine({ theme, name, tone = "accent" }) {
|
|
|
13716
14211
|
const paint = (text) => tone === "muted" ? theme.muted(text) : theme.color("accent", text);
|
|
13717
14212
|
const line = welcomeLine(name);
|
|
13718
14213
|
if (name !== void 0 && line !== "Welcome back!") {
|
|
13719
|
-
return jsxs6(
|
|
14214
|
+
return jsxs6(Box8, {
|
|
13720
14215
|
children: [
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
14216
|
+
jsx10(Text7, { children: paint("Welcome back, ") }),
|
|
14217
|
+
jsx10(Text7, { bold: true, children: name.trim() }),
|
|
14218
|
+
jsx10(Text7, { children: paint("!") })
|
|
13724
14219
|
]
|
|
13725
14220
|
});
|
|
13726
14221
|
}
|
|
13727
|
-
return
|
|
14222
|
+
return jsx10(Box8, { children: jsx10(Text7, { children: paint(line) }) });
|
|
13728
14223
|
}
|
|
13729
14224
|
function ShellLine({ theme, workspace, branch }) {
|
|
13730
|
-
const dir =
|
|
13731
|
-
return jsxs6(
|
|
14225
|
+
const dir = basename7(workspace);
|
|
14226
|
+
return jsxs6(Box8, {
|
|
13732
14227
|
children: [
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
14228
|
+
jsx10(Text7, { children: theme.color("customMessage", "\u279C") }),
|
|
14229
|
+
jsx10(Text7, { children: " " }),
|
|
14230
|
+
jsx10(Text7, { bold: true, children: theme.color("text", dir) }),
|
|
13736
14231
|
branch !== void 0 && branch !== null && branch.length > 0 ? jsxs6(Fragment3, {
|
|
13737
14232
|
children: [
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
14233
|
+
jsx10(Text7, { children: " " }),
|
|
14234
|
+
jsx10(Text7, { children: theme.color("accent", "git:(") }),
|
|
14235
|
+
jsx10(Text7, { children: theme.color("customMessage", branch) }),
|
|
14236
|
+
jsx10(Text7, { children: theme.color("accent", ")") })
|
|
13742
14237
|
]
|
|
13743
14238
|
}) : null,
|
|
13744
|
-
|
|
14239
|
+
jsx10(Text7, { children: theme.dim(" indus") })
|
|
13745
14240
|
]
|
|
13746
14241
|
});
|
|
13747
14242
|
}
|
|
13748
|
-
function Wordmark({ theme }) {
|
|
13749
|
-
return
|
|
14243
|
+
function Wordmark({ theme, sweep }) {
|
|
14244
|
+
return jsx10(Box8, {
|
|
13750
14245
|
flexDirection: "column",
|
|
13751
|
-
children: WORDMARK_ROWS.map((line, index) =>
|
|
14246
|
+
children: WORDMARK_ROWS.map((line, index) => jsx10(Text7, { children: sweep ? chalk3.hex(rowGradient(index, WORDMARK_ROWS.length, theme.colors.accent, theme.colors.customMessage))(line) : theme.color("accent", line) }, index))
|
|
13752
14247
|
});
|
|
13753
14248
|
}
|
|
13754
14249
|
function SessionFact({ theme, label, value }) {
|
|
13755
|
-
return jsxs6(
|
|
14250
|
+
return jsxs6(Box8, {
|
|
13756
14251
|
children: [
|
|
13757
|
-
|
|
13758
|
-
|
|
14252
|
+
jsx10(Text7, { children: theme.dim(`${label.padEnd(7)} `) }),
|
|
14253
|
+
jsx10(Text7, { children: theme.muted(value) })
|
|
13759
14254
|
]
|
|
13760
14255
|
});
|
|
13761
14256
|
}
|
|
@@ -13771,17 +14266,17 @@ function paintMascot(theme, tone, text) {
|
|
|
13771
14266
|
return theme.dim(text);
|
|
13772
14267
|
}
|
|
13773
14268
|
}
|
|
13774
|
-
function Mascot({ theme, face }) {
|
|
13775
|
-
return
|
|
14269
|
+
function Mascot({ theme, face, sweep }) {
|
|
14270
|
+
return jsx10(Box8, {
|
|
13776
14271
|
flexDirection: "column",
|
|
13777
14272
|
alignItems: "center",
|
|
13778
14273
|
marginY: 1,
|
|
13779
14274
|
children: mascotRows(face).map(
|
|
13780
|
-
(row, rowIndex) =>
|
|
13781
|
-
|
|
14275
|
+
(row, rowIndex) => jsx10(
|
|
14276
|
+
Box8,
|
|
13782
14277
|
{
|
|
13783
14278
|
children: row.map(
|
|
13784
|
-
(seg, segIndex) =>
|
|
14279
|
+
(seg, segIndex) => jsx10(Text7, { children: sweep && seg.tone === "head" ? chalk3.hex(rowGradient(rowIndex, 5, theme.colors.accent, theme.colors.customMessage))(seg.text) : paintMascot(theme, seg.tone, seg.text) }, segIndex)
|
|
13785
14280
|
)
|
|
13786
14281
|
},
|
|
13787
14282
|
rowIndex
|
|
@@ -13790,13 +14285,14 @@ function Mascot({ theme, face }) {
|
|
|
13790
14285
|
});
|
|
13791
14286
|
}
|
|
13792
14287
|
function shortenWorkspace(workspace) {
|
|
13793
|
-
const home =
|
|
14288
|
+
const home = homedir5();
|
|
13794
14289
|
if (home.length > 0 && workspace.startsWith(home)) {
|
|
13795
14290
|
return `~${workspace.slice(home.length)}`;
|
|
13796
14291
|
}
|
|
13797
14292
|
return workspace;
|
|
13798
14293
|
}
|
|
13799
14294
|
function Banner(props) {
|
|
14295
|
+
const { columns } = useTerminalSize();
|
|
13800
14296
|
const {
|
|
13801
14297
|
theme,
|
|
13802
14298
|
modelId,
|
|
@@ -13810,71 +14306,75 @@ function Banner(props) {
|
|
|
13810
14306
|
variantSeed,
|
|
13811
14307
|
whatsNew,
|
|
13812
14308
|
notices,
|
|
13813
|
-
changelog
|
|
14309
|
+
changelog,
|
|
14310
|
+
sweep,
|
|
14311
|
+
startup
|
|
13814
14312
|
} = props;
|
|
13815
14313
|
const noticeList = notices ?? [];
|
|
13816
|
-
if (quiet || compact) {
|
|
13817
|
-
return jsxs6(
|
|
14314
|
+
if (quiet || compact || columns < 76) {
|
|
14315
|
+
return jsxs6(Box8, {
|
|
13818
14316
|
flexDirection: "column",
|
|
13819
14317
|
marginBottom: 1,
|
|
13820
14318
|
children: [
|
|
13821
|
-
|
|
13822
|
-
|
|
14319
|
+
jsx10(StartupNotices, { theme, notices: noticeList }),
|
|
14320
|
+
jsx10(StartupSummary, { theme, startup }),
|
|
14321
|
+
jsxs6(Box8, {
|
|
13823
14322
|
children: [
|
|
13824
14323
|
compact ? jsxs6(Fragment3, {
|
|
13825
14324
|
children: [
|
|
13826
|
-
|
|
13827
|
-
|
|
13828
|
-
|
|
14325
|
+
jsx10(Text7, { children: theme.color("accent", COMPACT_EMBLEM.slice(0, 2)) }),
|
|
14326
|
+
jsx10(Text7, { children: theme.color("customMessage", COMPACT_EMBLEM.slice(2)) }),
|
|
14327
|
+
jsx10(Text7, { children: " " })
|
|
13829
14328
|
]
|
|
13830
14329
|
}) : null,
|
|
13831
|
-
|
|
13832
|
-
|
|
13833
|
-
|
|
13834
|
-
|
|
13835
|
-
|
|
14330
|
+
jsx10(Text7, { bold: true, children: theme.color("accent", BRAND2) }),
|
|
14331
|
+
jsx10(Text7, { children: " " }),
|
|
14332
|
+
jsx10(Text7, { children: theme.muted(`v${version}`) }),
|
|
14333
|
+
jsx10(Text7, { children: " " }),
|
|
14334
|
+
jsx10(Text7, { children: theme.dim(modelId) })
|
|
13836
14335
|
]
|
|
13837
14336
|
}),
|
|
13838
|
-
|
|
13839
|
-
changelog ?
|
|
14337
|
+
jsx10(WelcomeLine, { theme, name, tone: "muted" }),
|
|
14338
|
+
changelog ? jsx10(StartupChangelogBlock, { theme, changelog }) : null
|
|
13840
14339
|
]
|
|
13841
14340
|
});
|
|
13842
14341
|
}
|
|
13843
14342
|
if (started) {
|
|
13844
|
-
return jsxs6(
|
|
14343
|
+
return jsxs6(Box8, {
|
|
13845
14344
|
flexDirection: "column",
|
|
13846
14345
|
marginBottom: 1,
|
|
13847
14346
|
children: [
|
|
13848
|
-
|
|
13849
|
-
|
|
13850
|
-
|
|
13851
|
-
|
|
14347
|
+
jsx10(StartupNotices, { theme, notices: noticeList }),
|
|
14348
|
+
jsx10(StartupSummary, { theme, startup }),
|
|
14349
|
+
jsx10(ShellLine, { theme, workspace, branch }),
|
|
14350
|
+
jsx10(Box8, { marginTop: 1, children: jsx10(Wordmark, { theme, sweep }) }),
|
|
14351
|
+
jsxs6(Box8, {
|
|
13852
14352
|
marginTop: 1,
|
|
13853
14353
|
flexDirection: "column",
|
|
13854
14354
|
children: [
|
|
13855
|
-
jsxs6(
|
|
14355
|
+
jsxs6(Box8, {
|
|
13856
14356
|
children: [
|
|
13857
|
-
|
|
13858
|
-
|
|
13859
|
-
|
|
14357
|
+
jsx10(Text7, { bold: true, children: theme.color("accent", "indus console") }),
|
|
14358
|
+
jsx10(Text7, { children: " " }),
|
|
14359
|
+
jsx10(Text7, { children: theme.dim(`v${version}`) })
|
|
13860
14360
|
]
|
|
13861
14361
|
}),
|
|
13862
|
-
|
|
14362
|
+
jsx10(WelcomeLine, { theme, name, tone: "accent" })
|
|
13863
14363
|
]
|
|
13864
14364
|
}),
|
|
13865
|
-
jsxs6(
|
|
14365
|
+
jsxs6(Box8, {
|
|
13866
14366
|
flexDirection: "column",
|
|
13867
14367
|
borderStyle: "round",
|
|
13868
14368
|
borderColor: theme.colors["accent"],
|
|
13869
14369
|
paddingX: 1,
|
|
13870
14370
|
marginTop: 1,
|
|
13871
14371
|
children: [
|
|
13872
|
-
|
|
13873
|
-
|
|
13874
|
-
|
|
14372
|
+
jsx10(Text7, { bold: true, children: theme.color("accent", "Session") }),
|
|
14373
|
+
jsx10(SessionFact, { theme, label: "model", value: modelId }),
|
|
14374
|
+
jsx10(SessionFact, { theme, label: "cwd", value: shortenWorkspace(workspace) })
|
|
13875
14375
|
]
|
|
13876
14376
|
}),
|
|
13877
|
-
changelog ?
|
|
14377
|
+
changelog ? jsx10(StartupChangelogBlock, { theme, changelog }) : null
|
|
13878
14378
|
]
|
|
13879
14379
|
});
|
|
13880
14380
|
}
|
|
@@ -13882,43 +14382,44 @@ function Banner(props) {
|
|
|
13882
14382
|
const greeting = welcomeLine(name);
|
|
13883
14383
|
const news = whatsNew && whatsNew.length > 0 ? whatsNew : WHATS_NEW;
|
|
13884
14384
|
const metaLine = modelId;
|
|
13885
|
-
return jsxs6(
|
|
14385
|
+
return jsxs6(Box8, {
|
|
13886
14386
|
flexDirection: "column",
|
|
13887
14387
|
marginBottom: 1,
|
|
13888
14388
|
children: [
|
|
13889
|
-
|
|
13890
|
-
|
|
14389
|
+
jsx10(StartupNotices, { theme, notices: noticeList }),
|
|
14390
|
+
jsx10(StartupSummary, { theme, startup }),
|
|
14391
|
+
jsxs6(Box8, {
|
|
13891
14392
|
flexDirection: "column",
|
|
13892
14393
|
borderStyle: "round",
|
|
13893
14394
|
borderColor: theme.colors["accent"],
|
|
13894
14395
|
paddingX: 2,
|
|
13895
14396
|
paddingY: 1,
|
|
13896
14397
|
children: [
|
|
13897
|
-
jsxs6(
|
|
14398
|
+
jsxs6(Box8, {
|
|
13898
14399
|
children: [
|
|
13899
|
-
|
|
13900
|
-
|
|
13901
|
-
|
|
14400
|
+
jsx10(Text7, { children: theme.color("customMessage", "\u25CF ") }),
|
|
14401
|
+
jsx10(Text7, { bold: true, children: theme.color("accent", `${BRAND2} `) }),
|
|
14402
|
+
jsx10(Text7, { children: theme.dim(`v${version}`) })
|
|
13902
14403
|
]
|
|
13903
14404
|
}),
|
|
13904
|
-
jsxs6(
|
|
14405
|
+
jsxs6(Box8, {
|
|
13905
14406
|
marginTop: 1,
|
|
13906
14407
|
flexDirection: "row",
|
|
13907
14408
|
children: [
|
|
13908
|
-
jsxs6(
|
|
14409
|
+
jsxs6(Box8, {
|
|
13909
14410
|
flexDirection: "column",
|
|
13910
14411
|
alignItems: "center",
|
|
13911
14412
|
width: 32,
|
|
13912
14413
|
flexShrink: 0,
|
|
13913
14414
|
marginRight: 2,
|
|
13914
14415
|
children: [
|
|
13915
|
-
|
|
13916
|
-
|
|
13917
|
-
|
|
13918
|
-
|
|
14416
|
+
jsx10(Text7, { bold: true, children: theme.color("text", greeting) }),
|
|
14417
|
+
jsx10(Mascot, { theme, face: variant.mascot, sweep }),
|
|
14418
|
+
jsx10(Text7, { children: theme.dim(metaLine) }),
|
|
14419
|
+
jsx10(Text7, { children: theme.dim(shortenWorkspace(workspace)) })
|
|
13919
14420
|
]
|
|
13920
14421
|
}),
|
|
13921
|
-
jsxs6(
|
|
14422
|
+
jsxs6(Box8, {
|
|
13922
14423
|
flexDirection: "column",
|
|
13923
14424
|
flexGrow: 1,
|
|
13924
14425
|
borderStyle: "single",
|
|
@@ -13928,108 +14429,96 @@ function Banner(props) {
|
|
|
13928
14429
|
borderBottom: false,
|
|
13929
14430
|
paddingLeft: 2,
|
|
13930
14431
|
children: [
|
|
13931
|
-
|
|
13932
|
-
|
|
13933
|
-
|
|
14432
|
+
jsx10(Text7, { bold: true, children: theme.color("accent", "Tips for getting started") }),
|
|
14433
|
+
jsx10(Text7, { children: theme.color("text", variant.tip) }),
|
|
14434
|
+
jsx10(Box8, { marginTop: 1, children: jsx10(Text7, { bold: true, children: theme.color("accent", "What's new") }) }),
|
|
13934
14435
|
news.map(
|
|
13935
|
-
(line, index) => jsxs6(
|
|
14436
|
+
(line, index) => jsxs6(Box8, {
|
|
13936
14437
|
flexDirection: "row",
|
|
13937
14438
|
children: [
|
|
13938
|
-
|
|
13939
|
-
|
|
14439
|
+
jsx10(Box8, { width: 2, flexShrink: 0, children: jsx10(Text7, { children: theme.color("customMessage", "\u25B8") }) }),
|
|
14440
|
+
jsx10(Box8, { flexGrow: 1, children: jsx10(Text7, { children: theme.color("text", line) }) })
|
|
13940
14441
|
]
|
|
13941
14442
|
}, index)
|
|
13942
14443
|
),
|
|
13943
|
-
|
|
14444
|
+
jsx10(Box8, { marginTop: 1, children: jsx10(Text7, { italic: true, children: theme.muted("/release-notes for more") }) })
|
|
13944
14445
|
]
|
|
13945
14446
|
})
|
|
13946
14447
|
]
|
|
13947
14448
|
})
|
|
13948
14449
|
]
|
|
13949
14450
|
}),
|
|
13950
|
-
changelog ?
|
|
14451
|
+
changelog ? jsx10(StartupChangelogBlock, { theme, changelog }) : null
|
|
13951
14452
|
]
|
|
13952
14453
|
});
|
|
13953
14454
|
}
|
|
13954
14455
|
|
|
13955
14456
|
// src/console/components/Composer.ts
|
|
13956
|
-
import { Box as
|
|
13957
|
-
import { jsx as
|
|
13958
|
-
|
|
13959
|
-
var
|
|
13960
|
-
|
|
13961
|
-
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
|
|
13968
|
-
|
|
13969
|
-
|
|
13970
|
-
|
|
13971
|
-
|
|
13972
|
-
|
|
13973
|
-
|
|
14457
|
+
import { Box as Box9, Text as Text8 } from "indusagi/react-host/ink";
|
|
14458
|
+
import { jsx as jsx11, jsxs as jsxs7 } from "indusagi/react-host/jsx-runtime";
|
|
14459
|
+
import stringWidth from "string-width";
|
|
14460
|
+
var segmenter2 = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
14461
|
+
function editorLines(buffer, caret, width) {
|
|
14462
|
+
const lines = [[]];
|
|
14463
|
+
let column = 0;
|
|
14464
|
+
caret = snapGrapheme(buffer, caret);
|
|
14465
|
+
for (const { segment, index } of segmenter2.segment(buffer + " ")) {
|
|
14466
|
+
const cursor = index === caret;
|
|
14467
|
+
if (segment === "\n") {
|
|
14468
|
+
if (cursor) lines.at(-1).push({ text: " ", caret: true });
|
|
14469
|
+
lines.push([]);
|
|
14470
|
+
column = 0;
|
|
14471
|
+
continue;
|
|
14472
|
+
}
|
|
14473
|
+
const text = segment === " " ? " " : segment.replace(/[\x00-\x1f\x7f]/g, "");
|
|
14474
|
+
const cells2 = stringWidth(text);
|
|
14475
|
+
if (column + cells2 > width && column > 0) {
|
|
14476
|
+
lines.push([]);
|
|
14477
|
+
column = 0;
|
|
14478
|
+
}
|
|
14479
|
+
lines.at(-1).push({ text: cells2 > width ? "?" : text, caret: cursor });
|
|
14480
|
+
column += Math.min(width, cells2);
|
|
14481
|
+
}
|
|
14482
|
+
return lines;
|
|
13974
14483
|
}
|
|
13975
|
-
function Composer({ theme, buffer, caret,
|
|
13976
|
-
const
|
|
13977
|
-
const
|
|
13978
|
-
const
|
|
13979
|
-
|
|
13980
|
-
|
|
13981
|
-
|
|
13982
|
-
|
|
13983
|
-
|
|
13984
|
-
|
|
13985
|
-
|
|
13986
|
-
|
|
13987
|
-
|
|
13988
|
-
|
|
13989
|
-
|
|
13990
|
-
|
|
13991
|
-
|
|
13992
|
-
|
|
13993
|
-
|
|
13994
|
-
|
|
13995
|
-
|
|
13996
|
-
|
|
13997
|
-
|
|
13998
|
-
|
|
13999
|
-
|
|
14000
|
-
|
|
14001
|
-
|
|
14002
|
-
|
|
14003
|
-
|
|
14004
|
-
|
|
14005
|
-
|
|
14006
|
-
|
|
14007
|
-
jsx10(Box7, {
|
|
14008
|
-
width: 2,
|
|
14009
|
-
flexShrink: 0,
|
|
14010
|
-
children: jsx10(Text7, { children: active ? theme.color("accent", "\u25B8") : " " })
|
|
14011
|
-
}),
|
|
14012
|
-
jsx10(Box7, {
|
|
14013
|
-
width: nameWidth,
|
|
14014
|
-
flexShrink: 0,
|
|
14015
|
-
children: jsx10(Text7, { bold: active, children: theme.color("customMessage", name) })
|
|
14016
|
-
}),
|
|
14017
|
-
jsx10(Text7, { children: " " }),
|
|
14018
|
-
jsx10(Text7, { children: theme.muted(suggestion.detail) })
|
|
14019
|
-
]
|
|
14020
|
-
},
|
|
14021
|
-
suggestion.value
|
|
14022
|
-
);
|
|
14023
|
-
})
|
|
14024
|
-
}) : null
|
|
14025
|
-
]
|
|
14026
|
-
});
|
|
14484
|
+
function Composer({ theme, buffer, caret, suggestions, highlight, paddingX = 1 }) {
|
|
14485
|
+
const { columns, rows } = useTerminalSize();
|
|
14486
|
+
const padding = Math.max(0, Math.min(3, Math.floor(paddingX), Math.floor((columns - 8) / 2)));
|
|
14487
|
+
const sendWidth = columns >= 32 ? 7 : 0;
|
|
14488
|
+
const width = Math.max(1, columns - 2 - padding * 2 - 2 - sendWidth);
|
|
14489
|
+
const allLines = editorLines(buffer, caret, width);
|
|
14490
|
+
const caretRow = Math.max(0, allLines.findIndex((line) => line.some((cell) => cell.caret)));
|
|
14491
|
+
const editorBudget = Math.max(1, Math.min(6, Math.floor(rows / 4)));
|
|
14492
|
+
const top = Math.max(0, Math.min(caretRow - editorBudget + 1, allLines.length - editorBudget));
|
|
14493
|
+
const lines = allLines.slice(top, top + editorBudget);
|
|
14494
|
+
const budget = Math.max(1, Math.min(8, rows - lines.length - 12));
|
|
14495
|
+
const start = Math.max(0, Math.min(highlight - budget + 1, suggestions.length - budget));
|
|
14496
|
+
const shown = suggestions.slice(start, start + budget);
|
|
14497
|
+
const nameWidth = Math.max(1, Math.min(24, Math.floor(columns / 3)));
|
|
14498
|
+
return jsxs7(Box9, { flexDirection: "column", flexShrink: 0, children: [
|
|
14499
|
+
jsx11(Box9, {
|
|
14500
|
+
borderStyle: "round",
|
|
14501
|
+
borderColor: theme.colors.borderMuted ?? "gray",
|
|
14502
|
+
paddingX: padding,
|
|
14503
|
+
flexDirection: "column",
|
|
14504
|
+
children: lines.map((line, index) => jsxs7(Box9, { height: 1, flexShrink: 0, children: [
|
|
14505
|
+
jsx11(Box9, { width: 2, flexShrink: 0, children: jsx11(Text8, { children: theme.color("customMessage", index + top === 0 ? "\u203A " : "\xB7 ") }) }),
|
|
14506
|
+
jsx11(Box9, { width, flexShrink: 0, children: jsx11(Text8, { wrap: "truncate-end", children: line.map((cell, i) => jsx11(Text8, { inverse: cell.caret, children: cell.text }, i)) }) }),
|
|
14507
|
+
sendWidth ? jsx11(Box9, { width: sendWidth, flexShrink: 0, children: jsx11(Text8, { children: index === 0 ? theme.dim(" \u21B5 send") : "" }) }) : null
|
|
14508
|
+
] }, index))
|
|
14509
|
+
}),
|
|
14510
|
+
shown.length ? jsx11(Box9, { flexDirection: "column", marginTop: 1, children: shown.map((suggestion, index) => jsxs7(Box9, { height: 1, children: [
|
|
14511
|
+
jsx11(Box9, { width: 2, flexShrink: 0, children: jsx11(Text8, { children: start + index === highlight ? theme.color("accent", "\u25B8") : " " }) }),
|
|
14512
|
+
jsx11(Box9, { width: nameWidth, flexShrink: 0, children: jsx11(Text8, { wrap: "truncate-end", bold: start + index === highlight, children: theme.color("customMessage", suggestion.label) }) }),
|
|
14513
|
+
jsx11(Box9, { width: Math.max(1, columns - nameWidth - 2), children: jsx11(Text8, { wrap: "truncate-end", children: theme.muted(" " + suggestion.detail) }) })
|
|
14514
|
+
] }, suggestion.value)) }) : null
|
|
14515
|
+
] });
|
|
14027
14516
|
}
|
|
14028
14517
|
|
|
14029
14518
|
// src/console/components/StatusBar.ts
|
|
14030
|
-
import { Box as
|
|
14519
|
+
import { Box as Box10, Text as Text9 } from "indusagi/react-host/ink";
|
|
14031
14520
|
import { Footer, StatusLine } from "indusagi/react-ink";
|
|
14032
|
-
import { jsx as
|
|
14521
|
+
import { jsx as jsx12, jsxs as jsxs8 } from "indusagi/react-host/jsx-runtime";
|
|
14033
14522
|
function permissionBadge(mode) {
|
|
14034
14523
|
switch (mode) {
|
|
14035
14524
|
case "acceptEdits":
|
|
@@ -14046,26 +14535,26 @@ function permissionBadge(mode) {
|
|
|
14046
14535
|
}
|
|
14047
14536
|
function StatusBar({ theme, snapshot, branch, providerCount, status, permissionMode }) {
|
|
14048
14537
|
const badge = permissionMode !== void 0 ? permissionBadge(permissionMode) : null;
|
|
14049
|
-
return jsxs8(
|
|
14538
|
+
return jsxs8(Box10, {
|
|
14050
14539
|
flexDirection: "column",
|
|
14051
14540
|
children: [
|
|
14052
|
-
|
|
14053
|
-
badge !== null ?
|
|
14054
|
-
children: jsxs8(
|
|
14541
|
+
jsx12(StatusLine, { theme, snapshot, status, showBusyText: false }),
|
|
14542
|
+
badge !== null ? jsx12(Box10, {
|
|
14543
|
+
children: jsxs8(Text9, {
|
|
14055
14544
|
color: badge.color,
|
|
14056
14545
|
children: ["\u25CF permission: ", badge.label]
|
|
14057
14546
|
})
|
|
14058
14547
|
}) : null,
|
|
14059
|
-
|
|
14548
|
+
jsx12(Footer, { theme, branch, snapshot, availableProviderCount: providerCount })
|
|
14060
14549
|
]
|
|
14061
14550
|
});
|
|
14062
14551
|
}
|
|
14063
14552
|
|
|
14064
14553
|
// src/console/components/WorkingIndicator.ts
|
|
14065
|
-
import
|
|
14066
|
-
import { Box as
|
|
14067
|
-
import { jsx as
|
|
14068
|
-
var { useRef: useRef2 } =
|
|
14554
|
+
import React3, { useEffect as useEffect8, useState as useState9 } from "indusagi/react-host";
|
|
14555
|
+
import { Box as Box11, Text as Text10 } from "indusagi/react-host/ink";
|
|
14556
|
+
import { jsx as jsx13, jsxs as jsxs9 } from "indusagi/react-host/jsx-runtime";
|
|
14557
|
+
var { useRef: useRef2 } = React3;
|
|
14069
14558
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
14070
14559
|
var FRAME_MS = 120;
|
|
14071
14560
|
var WORD_MS = 4e3;
|
|
@@ -14115,11 +14604,11 @@ function phaseLabel(phase) {
|
|
|
14115
14604
|
return null;
|
|
14116
14605
|
}
|
|
14117
14606
|
}
|
|
14118
|
-
function WorkingIndicator({ theme, busy, phase }) {
|
|
14119
|
-
const [frame, setFrame] =
|
|
14607
|
+
function WorkingIndicator({ theme, busy, phase, reducedMotion = false }) {
|
|
14608
|
+
const [frame, setFrame] = useState9(0);
|
|
14120
14609
|
const startRef = useRef2(null);
|
|
14121
14610
|
const wordOffsetRef = useRef2(0);
|
|
14122
|
-
|
|
14611
|
+
useEffect8(() => {
|
|
14123
14612
|
if (!busy) {
|
|
14124
14613
|
startRef.current = null;
|
|
14125
14614
|
return;
|
|
@@ -14128,28 +14617,27 @@ function WorkingIndicator({ theme, busy, phase }) {
|
|
|
14128
14617
|
startRef.current = Date.now();
|
|
14129
14618
|
wordOffsetRef.current = Math.floor(Math.random() * WORKING_WORDS.length);
|
|
14130
14619
|
}
|
|
14131
|
-
const id = setInterval(() => setFrame((f) => (f + 1) % SPINNER_FRAMES.length), FRAME_MS);
|
|
14620
|
+
const id = setInterval(() => setFrame((f) => (f + 1) % SPINNER_FRAMES.length), reducedMotion ? 1e3 : FRAME_MS);
|
|
14132
14621
|
return () => clearInterval(id);
|
|
14133
|
-
}, [busy]);
|
|
14622
|
+
}, [busy, reducedMotion]);
|
|
14134
14623
|
if (!busy) return null;
|
|
14135
14624
|
const elapsedMs = startRef.current !== null ? Date.now() - startRef.current : 0;
|
|
14136
14625
|
const elapsedSec = Math.floor(elapsedMs / 1e3);
|
|
14137
|
-
const spinner = SPINNER_FRAMES[frame % SPINNER_FRAMES.length];
|
|
14138
|
-
const label = phaseLabel(phase) ?? pickWord(wordOffsetRef.current + Math.floor(elapsedMs / WORD_MS));
|
|
14139
|
-
return jsxs9(
|
|
14626
|
+
const spinner = reducedMotion ? "\u2022" : SPINNER_FRAMES[frame % SPINNER_FRAMES.length];
|
|
14627
|
+
const label = phaseLabel(phase) ?? (reducedMotion ? "Working" : pickWord(wordOffsetRef.current + Math.floor(elapsedMs / WORD_MS)));
|
|
14628
|
+
return jsxs9(Box11, {
|
|
14140
14629
|
marginTop: 1,
|
|
14141
14630
|
children: [
|
|
14142
|
-
|
|
14143
|
-
|
|
14631
|
+
jsx13(Text10, { children: theme.color("accent", `${spinner} ${label}\u2026 `) }),
|
|
14632
|
+
jsx13(Text10, { children: theme.muted(`(${elapsedSec}s \xB7 esc to interrupt)`) })
|
|
14144
14633
|
]
|
|
14145
14634
|
});
|
|
14146
14635
|
}
|
|
14147
14636
|
|
|
14148
14637
|
// src/console/components/TerminalConsole.ts
|
|
14149
|
-
var { useReducer, useRef: useRef3, useCallback } =
|
|
14638
|
+
var { useReducer, useRef: useRef3, useCallback } = React4;
|
|
14150
14639
|
var CHORD_WINDOW_MS = 600;
|
|
14151
14640
|
var CTRL_C_EXIT_WINDOW_MS = 500;
|
|
14152
|
-
var FALLBACK_TERMINAL_ROWS = 40;
|
|
14153
14641
|
var CHROME_ROWS = 14;
|
|
14154
14642
|
var MODAL_CHROME_ROWS = 24;
|
|
14155
14643
|
var MIN_VISIBLE_ROWS = 8;
|
|
@@ -14290,8 +14778,39 @@ function permissionModeStatusText(mode) {
|
|
|
14290
14778
|
}
|
|
14291
14779
|
function TerminalConsole(props) {
|
|
14292
14780
|
const { conductor, theme, slash, verbose, onExit, initialInput, services } = props;
|
|
14293
|
-
const
|
|
14294
|
-
const
|
|
14781
|
+
const { stdin, internal_eventEmitter } = useStdin();
|
|
14782
|
+
const { stdout } = useStdout2();
|
|
14783
|
+
const rawKey = useRef3("");
|
|
14784
|
+
useEffect9(() => {
|
|
14785
|
+
const capture = (data) => {
|
|
14786
|
+
rawKey.current = String(data);
|
|
14787
|
+
};
|
|
14788
|
+
internal_eventEmitter.prependListener("input", capture);
|
|
14789
|
+
return () => {
|
|
14790
|
+
internal_eventEmitter.removeListener("input", capture);
|
|
14791
|
+
};
|
|
14792
|
+
}, [internal_eventEmitter]);
|
|
14793
|
+
const [state, dispatch2] = useReducer(consoleReducer, theme.scheme, (scheme) => {
|
|
14794
|
+
let stored;
|
|
14795
|
+
try {
|
|
14796
|
+
stored = services?.settings.get("colourScheme");
|
|
14797
|
+
} catch {
|
|
14798
|
+
}
|
|
14799
|
+
const flag = (key, fallback) => {
|
|
14800
|
+
try {
|
|
14801
|
+
const value = services?.settings.get(key);
|
|
14802
|
+
return typeof value === "boolean" ? value : fallback;
|
|
14803
|
+
} catch {
|
|
14804
|
+
return fallback;
|
|
14805
|
+
}
|
|
14806
|
+
};
|
|
14807
|
+
return initConsoleState({
|
|
14808
|
+
scheme: typeof stored === "string" && isThemeScheme(stored) ? stored : scheme,
|
|
14809
|
+
showReasoning: flag("showReasoning", false),
|
|
14810
|
+
showImages: flag("showImages", true)
|
|
14811
|
+
});
|
|
14812
|
+
});
|
|
14813
|
+
const adapter = resolveTheme(state.scheme).adapter;
|
|
14295
14814
|
const chord = useRef3(NO_CHORD);
|
|
14296
14815
|
const chordTimer = useRef3(null);
|
|
14297
14816
|
const paste = useRef3(EMPTY_PASTE_VAULT);
|
|
@@ -14302,34 +14821,39 @@ function TerminalConsole(props) {
|
|
|
14302
14821
|
const liveReason = useRef3(null);
|
|
14303
14822
|
const rowSeed = useRef3(0);
|
|
14304
14823
|
const ctrlCAt = useRef3(0);
|
|
14305
|
-
const
|
|
14306
|
-
|
|
14307
|
-
|
|
14308
|
-
|
|
14309
|
-
const [
|
|
14310
|
-
const [
|
|
14311
|
-
const [
|
|
14312
|
-
const [,
|
|
14824
|
+
const resumeHandler = useRef3(null);
|
|
14825
|
+
useEffect9(() => () => {
|
|
14826
|
+
if (resumeHandler.current) process.off("SIGCONT", resumeHandler.current);
|
|
14827
|
+
}, []);
|
|
14828
|
+
const [highlight, setHighlight] = useState10(0);
|
|
14829
|
+
const [toolExecutions, setToolExecutions] = useState10({});
|
|
14830
|
+
const [taskTokens, setTaskTokens] = useState10({});
|
|
14831
|
+
const [subagentActivity, setSubagentActivity] = useState10({});
|
|
14832
|
+
const [expandTools, setExpandTools] = useState10(false);
|
|
14833
|
+
const [agentsOpen, setAgentsOpen] = useState10(false);
|
|
14834
|
+
const { rows: terminalRows, columns: terminalColumns } = useTerminalSize();
|
|
14835
|
+
const renderRows = Math.max(1, terminalRows - 1);
|
|
14836
|
+
const [, forceTick] = useState10(0);
|
|
14313
14837
|
const pulse = useCallback(() => forceTick((n) => n + 1), []);
|
|
14314
14838
|
const dirReader = useMemo2(() => createDirReader(process.cwd()), []);
|
|
14315
14839
|
const [approvalQueue, dispatchApproval] = useReducer(approvalQueueReducer, EMPTY_APPROVAL_QUEUE);
|
|
14316
14840
|
const approvalSeed = useRef3(0);
|
|
14317
14841
|
const approvalResolvers = useRef3(/* @__PURE__ */ new Map());
|
|
14318
14842
|
const settleApproval = useCallback((id, choice) => {
|
|
14319
|
-
const
|
|
14320
|
-
if (
|
|
14843
|
+
const resolve11 = approvalResolvers.current.get(id);
|
|
14844
|
+
if (resolve11 === void 0) return;
|
|
14321
14845
|
approvalResolvers.current.delete(id);
|
|
14322
14846
|
dispatchApproval({ type: "settle", id });
|
|
14323
|
-
|
|
14847
|
+
resolve11(choice);
|
|
14324
14848
|
}, []);
|
|
14325
14849
|
const denyAllApprovals = useCallback(() => {
|
|
14326
14850
|
const pending = [...approvalResolvers.current.entries()];
|
|
14327
14851
|
approvalResolvers.current.clear();
|
|
14328
14852
|
dispatchApproval({ type: "clear" });
|
|
14329
|
-
for (const [,
|
|
14853
|
+
for (const [, resolve11] of pending) resolve11("deny");
|
|
14330
14854
|
}, []);
|
|
14331
14855
|
const requestApproval = useCallback(
|
|
14332
|
-
(toolName, input, opts) => new Promise((
|
|
14856
|
+
(toolName, input, opts) => new Promise((resolve11) => {
|
|
14333
14857
|
approvalSeed.current += 1;
|
|
14334
14858
|
const id = `ap_${approvalSeed.current}`;
|
|
14335
14859
|
const request = {
|
|
@@ -14337,21 +14861,26 @@ function TerminalConsole(props) {
|
|
|
14337
14861
|
input,
|
|
14338
14862
|
suggestions: allowAlwaysRuleStrings(toolName, input)
|
|
14339
14863
|
};
|
|
14340
|
-
approvalResolvers.current.set(id, resolve9);
|
|
14341
14864
|
const signal = opts.signal;
|
|
14865
|
+
const onAbort = () => settleApproval(id, "deny");
|
|
14866
|
+
const finish = (choice) => {
|
|
14867
|
+
signal?.removeEventListener("abort", onAbort);
|
|
14868
|
+
resolve11(choice);
|
|
14869
|
+
};
|
|
14870
|
+
approvalResolvers.current.set(id, finish);
|
|
14342
14871
|
if (signal !== void 0) {
|
|
14343
14872
|
if (signal.aborted) {
|
|
14344
14873
|
approvalResolvers.current.delete(id);
|
|
14345
|
-
|
|
14874
|
+
resolve11("deny");
|
|
14346
14875
|
return;
|
|
14347
14876
|
}
|
|
14348
|
-
signal.addEventListener("abort",
|
|
14877
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
14349
14878
|
}
|
|
14350
|
-
dispatchApproval({ type: "enqueue", entry: { id, request, resolve:
|
|
14879
|
+
dispatchApproval({ type: "enqueue", entry: { id, request, resolve: finish } });
|
|
14351
14880
|
}),
|
|
14352
14881
|
[settleApproval]
|
|
14353
14882
|
);
|
|
14354
|
-
|
|
14883
|
+
useEffect9(() => {
|
|
14355
14884
|
conductor.setApprovalResolver(requestApproval);
|
|
14356
14885
|
return () => {
|
|
14357
14886
|
conductor.setApprovalResolver(void 0);
|
|
@@ -14361,7 +14890,7 @@ function TerminalConsole(props) {
|
|
|
14361
14890
|
const head = activeApproval(approvalQueue);
|
|
14362
14891
|
const headId = head?.id;
|
|
14363
14892
|
const approvalModalOpen = useRef3(false);
|
|
14364
|
-
|
|
14893
|
+
useEffect9(() => {
|
|
14365
14894
|
if (head === void 0) {
|
|
14366
14895
|
if (approvalModalOpen.current) {
|
|
14367
14896
|
approvalModalOpen.current = false;
|
|
@@ -14392,11 +14921,53 @@ function TerminalConsole(props) {
|
|
|
14392
14921
|
const answerText = useRef3("");
|
|
14393
14922
|
const reasonText = useRef3("");
|
|
14394
14923
|
const visibleFrom = useRef3(0);
|
|
14395
|
-
const [compactNote, setCompactNote] =
|
|
14396
|
-
|
|
14924
|
+
const [compactNote, setCompactNote] = useState10(null);
|
|
14925
|
+
const sessionId = conductor.snapshot().head.sessionId;
|
|
14926
|
+
const priorSession = useRef3(sessionId);
|
|
14927
|
+
const resetView = useCallback(() => {
|
|
14928
|
+
liveAnswer.current = null;
|
|
14929
|
+
liveReason.current = null;
|
|
14930
|
+
answerText.current = "";
|
|
14931
|
+
reasonText.current = "";
|
|
14932
|
+
visibleFrom.current = 0;
|
|
14933
|
+
activePaste.current = null;
|
|
14934
|
+
paste.current = EMPTY_PASTE_VAULT;
|
|
14935
|
+
burst.current = "";
|
|
14936
|
+
if (burstTimer.current !== null) {
|
|
14937
|
+
clearTimeout(burstTimer.current);
|
|
14938
|
+
burstTimer.current = null;
|
|
14939
|
+
}
|
|
14940
|
+
setToolExecutions({});
|
|
14941
|
+
setTaskTokens({});
|
|
14942
|
+
setSubagentActivity({});
|
|
14943
|
+
setCompactNote(null);
|
|
14944
|
+
setAgentsOpen(false);
|
|
14945
|
+
denyAllApprovals();
|
|
14946
|
+
dispatch2({ type: "view:reset" });
|
|
14947
|
+
}, [denyAllApprovals]);
|
|
14948
|
+
useEffect9(() => {
|
|
14949
|
+
if (priorSession.current !== sessionId) {
|
|
14950
|
+
priorSession.current = sessionId;
|
|
14951
|
+
resetView();
|
|
14952
|
+
}
|
|
14953
|
+
}, [sessionId, resetView]);
|
|
14954
|
+
useEffect9(() => {
|
|
14397
14955
|
const off = conductor.subscribe((signal) => {
|
|
14398
14956
|
switch (signal.kind) {
|
|
14957
|
+
case "reset": {
|
|
14958
|
+
resetView();
|
|
14959
|
+
break;
|
|
14960
|
+
}
|
|
14961
|
+
case "phase": {
|
|
14962
|
+
dispatch2({ type: "busy:set", busy: signal.phase === "streaming" || signal.phase === "tooling" || signal.phase === "condensing" });
|
|
14963
|
+
break;
|
|
14964
|
+
}
|
|
14399
14965
|
case "prompt": {
|
|
14966
|
+
liveAnswer.current = null;
|
|
14967
|
+
liveReason.current = null;
|
|
14968
|
+
answerText.current = "";
|
|
14969
|
+
reasonText.current = "";
|
|
14970
|
+
dispatch2({ type: "busy:set", busy: true });
|
|
14400
14971
|
break;
|
|
14401
14972
|
}
|
|
14402
14973
|
case "text": {
|
|
@@ -14404,10 +14975,8 @@ function TerminalConsole(props) {
|
|
|
14404
14975
|
const id = freshRowId(rowSeed.current++);
|
|
14405
14976
|
liveAnswer.current = id;
|
|
14406
14977
|
answerText.current = signal.delta;
|
|
14407
|
-
dispatch2({ type: "rows:append", row: { id, kind: "answer", text: answerText.current } });
|
|
14408
14978
|
} else {
|
|
14409
14979
|
answerText.current += signal.delta;
|
|
14410
|
-
dispatch2({ type: "rows:patch", id: liveAnswer.current, text: answerText.current });
|
|
14411
14980
|
}
|
|
14412
14981
|
break;
|
|
14413
14982
|
}
|
|
@@ -14416,19 +14985,14 @@ function TerminalConsole(props) {
|
|
|
14416
14985
|
const id = freshRowId(rowSeed.current++);
|
|
14417
14986
|
liveReason.current = id;
|
|
14418
14987
|
reasonText.current = signal.delta;
|
|
14419
|
-
dispatch2({ type: "rows:append", row: { id, kind: "reason", text: reasonText.current } });
|
|
14420
14988
|
} else {
|
|
14421
14989
|
reasonText.current += signal.delta;
|
|
14422
|
-
dispatch2({ type: "rows:patch", id: liveReason.current, text: reasonText.current });
|
|
14423
14990
|
}
|
|
14424
14991
|
break;
|
|
14425
14992
|
}
|
|
14426
14993
|
case "tool_start": {
|
|
14427
14994
|
liveAnswer.current = null;
|
|
14428
14995
|
liveReason.current = null;
|
|
14429
|
-
const id = `tool-${signal.id}`;
|
|
14430
|
-
const row = { id, kind: "toolRun", text: signal.name, runId: signal.id };
|
|
14431
|
-
dispatch2({ type: "rows:append", row });
|
|
14432
14996
|
setToolExecutions((current) => ({
|
|
14433
14997
|
...current,
|
|
14434
14998
|
[signal.id]: {
|
|
@@ -14473,11 +15037,6 @@ function TerminalConsole(props) {
|
|
|
14473
15037
|
break;
|
|
14474
15038
|
}
|
|
14475
15039
|
case "tool_end": {
|
|
14476
|
-
dispatch2({
|
|
14477
|
-
type: "rows:patch",
|
|
14478
|
-
id: `tool-${signal.id}`,
|
|
14479
|
-
text: signal.ok ? "done" : "failed"
|
|
14480
|
-
});
|
|
14481
15040
|
setToolExecutions((current) => {
|
|
14482
15041
|
const prior = current[signal.id];
|
|
14483
15042
|
if (prior === void 0) return current;
|
|
@@ -14502,7 +15061,7 @@ function TerminalConsole(props) {
|
|
|
14502
15061
|
if (signal.manual) {
|
|
14503
15062
|
const carried = [];
|
|
14504
15063
|
for (const message of conductor.messages()) {
|
|
14505
|
-
const content = message.content;
|
|
15064
|
+
const content = "content" in message ? message.content : void 0;
|
|
14506
15065
|
if (typeof content === "string" && content.startsWith(RESTORED_FILE_PREFIX)) {
|
|
14507
15066
|
const firstLine = content.slice(RESTORED_FILE_PREFIX.length).split("\n", 1)[0];
|
|
14508
15067
|
if (firstLine) carried.push(firstLine.trim());
|
|
@@ -14514,7 +15073,7 @@ function TerminalConsole(props) {
|
|
|
14514
15073
|
liveReason.current = null;
|
|
14515
15074
|
answerText.current = "";
|
|
14516
15075
|
reasonText.current = "";
|
|
14517
|
-
dispatch2({ type: "
|
|
15076
|
+
dispatch2({ type: "blocks:clear" });
|
|
14518
15077
|
}
|
|
14519
15078
|
dispatch2({
|
|
14520
15079
|
type: "status:set",
|
|
@@ -14541,6 +15100,8 @@ function TerminalConsole(props) {
|
|
|
14541
15100
|
break;
|
|
14542
15101
|
}
|
|
14543
15102
|
case "idle": {
|
|
15103
|
+
liveAnswer.current = null;
|
|
15104
|
+
liveReason.current = null;
|
|
14544
15105
|
dispatch2({ type: "busy:set", busy: false });
|
|
14545
15106
|
break;
|
|
14546
15107
|
}
|
|
@@ -14550,19 +15111,17 @@ function TerminalConsole(props) {
|
|
|
14550
15111
|
pulse();
|
|
14551
15112
|
});
|
|
14552
15113
|
return off;
|
|
14553
|
-
}, [conductor, pulse]);
|
|
15114
|
+
}, [conductor, pulse, resetView]);
|
|
14554
15115
|
const completion = useMemo2(
|
|
14555
15116
|
() => completeAt(state.buffer, state.caret, slash, dirReader),
|
|
14556
15117
|
[state.buffer, state.caret, slash, dirReader]
|
|
14557
15118
|
);
|
|
14558
15119
|
const suggestions = completion.suggestions;
|
|
14559
|
-
|
|
15120
|
+
useEffect9(() => {
|
|
14560
15121
|
if (highlight >= suggestions.length) setHighlight(0);
|
|
14561
15122
|
}, [suggestions.length, highlight]);
|
|
14562
15123
|
const runTurn = useCallback(
|
|
14563
15124
|
async (text) => {
|
|
14564
|
-
const id = freshRowId(rowSeed.current++);
|
|
14565
|
-
dispatch2({ type: "rows:append", row: { id, kind: "prompt", text } });
|
|
14566
15125
|
dispatch2({ type: "busy:set", busy: true });
|
|
14567
15126
|
if (conductor.snapshot().phase === "condensing") {
|
|
14568
15127
|
dispatch2({
|
|
@@ -14572,8 +15131,6 @@ function TerminalConsole(props) {
|
|
|
14572
15131
|
}
|
|
14573
15132
|
setCompactNote(null);
|
|
14574
15133
|
activePaste.current = null;
|
|
14575
|
-
answerText.current = "";
|
|
14576
|
-
reasonText.current = "";
|
|
14577
15134
|
try {
|
|
14578
15135
|
await conductor.submit(text);
|
|
14579
15136
|
} catch (err2) {
|
|
@@ -14592,15 +15149,29 @@ function TerminalConsole(props) {
|
|
|
14592
15149
|
const text = hasMarkers(raw, paste.current) ? expandMarkers(raw, paste.current) : raw;
|
|
14593
15150
|
const trimmed = text.trim();
|
|
14594
15151
|
dispatch2({ type: "buffer:set", text: "" });
|
|
14595
|
-
paste.current =
|
|
15152
|
+
paste.current = { bodies: /* @__PURE__ */ new Map(), minted: paste.current.minted };
|
|
15153
|
+
activePaste.current = null;
|
|
14596
15154
|
if (trimmed.length === 0) return;
|
|
14597
|
-
dispatch2({ type: "history:push", text
|
|
15155
|
+
dispatch2({ type: "history:push", text });
|
|
14598
15156
|
if (trimmed.startsWith("!")) {
|
|
14599
15157
|
const excludeFromContext = trimmed.startsWith("!!");
|
|
14600
15158
|
const command = trimmed.slice(excludeFromContext ? 2 : 1).trim();
|
|
14601
15159
|
if (command.length === 0) return;
|
|
14602
15160
|
dispatch2({ type: "status:set", status: { kind: "busy", text: `Running: ${command}` } });
|
|
14603
15161
|
void conductor.executeBash(command, { excludeFromContext }).then((outcome) => {
|
|
15162
|
+
const output = String(outcome.output ?? "");
|
|
15163
|
+
const fence = "`".repeat(Math.max(3, ...Array.from(output.matchAll(/`+/g), (m) => m[0].length + 1)));
|
|
15164
|
+
const recorded = conductor.messages().some((message) => message.role === "user" && message.content === `$ ${command}
|
|
15165
|
+
${output}`.trimEnd());
|
|
15166
|
+
if (!recorded || excludeFromContext) dispatch2({ type: "block:append", block: {
|
|
15167
|
+
id: freshRowId(rowSeed.current++),
|
|
15168
|
+
kind: "changelog",
|
|
15169
|
+
title: `$ ${command}`,
|
|
15170
|
+
markdown: `${fence}text
|
|
15171
|
+
${output || "(no output)"}
|
|
15172
|
+
${fence}`,
|
|
15173
|
+
timestamp: Date.now()
|
|
15174
|
+
} });
|
|
14604
15175
|
dispatch2({
|
|
14605
15176
|
type: "status:set",
|
|
14606
15177
|
status: {
|
|
@@ -14618,9 +15189,10 @@ function TerminalConsole(props) {
|
|
|
14618
15189
|
}
|
|
14619
15190
|
const resolution = resolveSlash(trimmed, slash);
|
|
14620
15191
|
if (resolution.kind === "match") {
|
|
14621
|
-
|
|
15192
|
+
void Promise.resolve().then(() => resolution.command.run({
|
|
14622
15193
|
args: resolution.args,
|
|
14623
15194
|
conductor,
|
|
15195
|
+
services,
|
|
14624
15196
|
dispatch: dispatch2,
|
|
14625
15197
|
openModal: (kind, payload) => dispatch2({ type: "modal:open", kind, payload }),
|
|
14626
15198
|
closeModal: () => dispatch2({ type: "modal:close" }),
|
|
@@ -14628,10 +15200,9 @@ function TerminalConsole(props) {
|
|
|
14628
15200
|
setStatus: (status) => dispatch2({ type: "status:set", status }),
|
|
14629
15201
|
setBuffer: (value) => dispatch2({ type: "buffer:set", text: value }),
|
|
14630
15202
|
appendBlock: (block2) => dispatch2({ type: "block:append", block: block2 })
|
|
14631
|
-
})
|
|
14632
|
-
void Promise.resolve(outcome).then((settled) => {
|
|
15203
|
+
})).then((settled) => {
|
|
14633
15204
|
if (settled.kind === "prompt") void runTurn(settled.text);
|
|
14634
|
-
});
|
|
15205
|
+
}).catch((error) => dispatch2({ type: "status:set", status: { kind: "error", text: error instanceof Error ? error.message : String(error) } }));
|
|
14635
15206
|
return;
|
|
14636
15207
|
}
|
|
14637
15208
|
if (resolution.kind === "miss") {
|
|
@@ -14643,7 +15214,7 @@ function TerminalConsole(props) {
|
|
|
14643
15214
|
}
|
|
14644
15215
|
void runTurn(text);
|
|
14645
15216
|
},
|
|
14646
|
-
[slash, conductor, onExit, runTurn]
|
|
15217
|
+
[slash, conductor, onExit, runTurn, services]
|
|
14647
15218
|
);
|
|
14648
15219
|
const flushBurst = useCallback(() => {
|
|
14649
15220
|
if (burstTimer.current !== null) {
|
|
@@ -14691,22 +15262,15 @@ function TerminalConsole(props) {
|
|
|
14691
15262
|
chordTimer.current = null;
|
|
14692
15263
|
}
|
|
14693
15264
|
}, []);
|
|
14694
|
-
|
|
15265
|
+
useEffect9(
|
|
14695
15266
|
() => () => {
|
|
14696
15267
|
if (chordTimer.current !== null) clearTimeout(chordTimer.current);
|
|
14697
15268
|
if (burstTimer.current !== null) clearTimeout(burstTimer.current);
|
|
14698
15269
|
},
|
|
14699
15270
|
[]
|
|
14700
15271
|
);
|
|
14701
|
-
useEffect7(() => {
|
|
14702
|
-
const onResize = () => setTerminalRows(process.stdout.rows ?? FALLBACK_TERMINAL_ROWS);
|
|
14703
|
-
process.stdout.on("resize", onResize);
|
|
14704
|
-
return () => {
|
|
14705
|
-
process.stdout.off("resize", onResize);
|
|
14706
|
-
};
|
|
14707
|
-
}, []);
|
|
14708
15272
|
const titleName = conductor.sessionName();
|
|
14709
|
-
|
|
15273
|
+
useEffect9(() => {
|
|
14710
15274
|
writeTerminalTitle(titleName && titleName.length > 0 ? titleName : "indus console");
|
|
14711
15275
|
}, [titleName]);
|
|
14712
15276
|
const requestExit = useCallback(() => {
|
|
@@ -14721,11 +15285,12 @@ function TerminalConsole(props) {
|
|
|
14721
15285
|
setHighlight(0);
|
|
14722
15286
|
return true;
|
|
14723
15287
|
}, [suggestions, highlight, state.buffer, completion.span]);
|
|
14724
|
-
|
|
15288
|
+
useInput6(
|
|
14725
15289
|
(rawInput, key) => {
|
|
14726
15290
|
const input = rawInput.replace(BRACKETED_PASTE, "");
|
|
14727
15291
|
if (input.length === 0 && input !== rawInput) return;
|
|
14728
|
-
const
|
|
15292
|
+
const isBackspaceByte = rawKey.current === "\x7F" || rawKey.current === "\b";
|
|
15293
|
+
const intent = readKey(input, { ...key, backspace: key.backspace || isBackspaceByte, delete: key.delete && !isBackspaceByte });
|
|
14729
15294
|
if (intent.verb === "text:type") {
|
|
14730
15295
|
burst.current += intent.text ?? "";
|
|
14731
15296
|
armChord(NO_CHORD);
|
|
@@ -14862,7 +15427,8 @@ function TerminalConsole(props) {
|
|
|
14862
15427
|
return;
|
|
14863
15428
|
}
|
|
14864
15429
|
case "flow:cycleModel":
|
|
14865
|
-
conductor.cycleModel?.("");
|
|
15430
|
+
conductor.cycleModel?.("", intent.direction ?? 1);
|
|
15431
|
+
pulse();
|
|
14866
15432
|
return;
|
|
14867
15433
|
case "model:cycleThinking": {
|
|
14868
15434
|
const level = conductor.cycleThinkingLevel();
|
|
@@ -14905,10 +15471,10 @@ function TerminalConsole(props) {
|
|
|
14905
15471
|
return;
|
|
14906
15472
|
}
|
|
14907
15473
|
case "input:pasteImage": {
|
|
14908
|
-
const
|
|
14909
|
-
if (
|
|
14910
|
-
const
|
|
14911
|
-
dispatch2({ type: "buffer:insert", text: `${
|
|
15474
|
+
const path5 = readClipboardImage();
|
|
15475
|
+
if (path5 !== null) {
|
|
15476
|
+
const sep2 = state.buffer.length > 0 && !/\s$/.test(state.buffer) ? " " : "";
|
|
15477
|
+
dispatch2({ type: "buffer:insert", text: `${sep2}${path5}` });
|
|
14912
15478
|
} else {
|
|
14913
15479
|
dispatch2({
|
|
14914
15480
|
type: "status:set",
|
|
@@ -14918,7 +15484,7 @@ function TerminalConsole(props) {
|
|
|
14918
15484
|
return;
|
|
14919
15485
|
}
|
|
14920
15486
|
case "input:externalEditor": {
|
|
14921
|
-
const edited = openInExternalEditor(state.buffer);
|
|
15487
|
+
const edited = openInExternalEditor(expandMarkers(state.buffer, paste.current), { terminal: { stdin, stdout } });
|
|
14922
15488
|
if (edited !== null) {
|
|
14923
15489
|
dispatch2({ type: "buffer:set", text: edited });
|
|
14924
15490
|
}
|
|
@@ -14932,9 +15498,30 @@ function TerminalConsole(props) {
|
|
|
14932
15498
|
case "view:expandTools":
|
|
14933
15499
|
setExpandTools((current) => !current);
|
|
14934
15500
|
return;
|
|
14935
|
-
case "flow:suspend":
|
|
14936
|
-
|
|
15501
|
+
case "flow:suspend": {
|
|
15502
|
+
if (process.platform === "win32") {
|
|
15503
|
+
dispatch2({ type: "status:set", status: { kind: "warning", text: "Process suspension is not supported on Windows." } });
|
|
15504
|
+
return;
|
|
15505
|
+
}
|
|
15506
|
+
const wasRaw = stdin.isRaw === true;
|
|
15507
|
+
const resume = () => {
|
|
15508
|
+
process.off("SIGCONT", resume);
|
|
15509
|
+
resumeHandler.current = null;
|
|
15510
|
+
stdin.setRawMode?.(wasRaw);
|
|
15511
|
+
if (stdout.isTTY) stdout.write("\x1B[?25l");
|
|
15512
|
+
dispatch2({ type: "status:set", status: { kind: "info", text: "Resumed console." } });
|
|
15513
|
+
};
|
|
15514
|
+
resumeHandler.current = resume;
|
|
15515
|
+
process.once("SIGCONT", resume);
|
|
15516
|
+
stdin.setRawMode?.(false);
|
|
15517
|
+
if (stdout.isTTY) stdout.write("\x1B[?25h");
|
|
15518
|
+
try {
|
|
15519
|
+
process.kill(process.pid, "SIGTSTP");
|
|
15520
|
+
} catch {
|
|
15521
|
+
resume();
|
|
15522
|
+
}
|
|
14937
15523
|
return;
|
|
15524
|
+
}
|
|
14938
15525
|
case "none":
|
|
14939
15526
|
default:
|
|
14940
15527
|
return;
|
|
@@ -14942,14 +15529,23 @@ function TerminalConsole(props) {
|
|
|
14942
15529
|
},
|
|
14943
15530
|
{ isActive: state.modal.kind === "none" && !agentsOpen }
|
|
14944
15531
|
);
|
|
14945
|
-
|
|
15532
|
+
useInput6((input, key) => {
|
|
15533
|
+
if (!key.ctrl || input !== "c") return;
|
|
15534
|
+
if (state.busy || conductor.isBusy?.() || conductor.snapshot().phase === "condensing") {
|
|
15535
|
+
denyAllApprovals();
|
|
15536
|
+
conductor.abort();
|
|
15537
|
+
}
|
|
15538
|
+
dispatch2({ type: "modal:close" });
|
|
15539
|
+
setAgentsOpen(false);
|
|
15540
|
+
}, { isActive: state.modal.kind !== "none" || agentsOpen });
|
|
15541
|
+
useInput6(
|
|
14946
15542
|
(_rawInput, key) => {
|
|
14947
15543
|
if (key.tab && key.shift) cyclePermission();
|
|
14948
15544
|
},
|
|
14949
15545
|
{ isActive: state.modal.kind === "approval" }
|
|
14950
15546
|
);
|
|
14951
15547
|
const seeded = useRef3(false);
|
|
14952
|
-
|
|
15548
|
+
useEffect9(() => {
|
|
14953
15549
|
if (seeded.current) return;
|
|
14954
15550
|
seeded.current = true;
|
|
14955
15551
|
const opening = conductor.permissionMode();
|
|
@@ -14983,7 +15579,7 @@ function TerminalConsole(props) {
|
|
|
14983
15579
|
const taskPanelRows = showTaskPanel ? 2 + Math.min(pendingMessages.length, 8) : 0;
|
|
14984
15580
|
const workingIndicatorRows = state.busy ? 2 : 0;
|
|
14985
15581
|
const maxItems = transcriptHeight(
|
|
14986
|
-
|
|
15582
|
+
renderRows,
|
|
14987
15583
|
modalOpen,
|
|
14988
15584
|
agentPanelRows(agentRuns) + streamingAnswerRows + taskPanelRows + workingIndicatorRows
|
|
14989
15585
|
);
|
|
@@ -14992,7 +15588,7 @@ function TerminalConsole(props) {
|
|
|
14992
15588
|
const startupMap = useMemo2(
|
|
14993
15589
|
() => gatherStartup({
|
|
14994
15590
|
cwd: process.cwd(),
|
|
14995
|
-
home:
|
|
15591
|
+
home: homedir6(),
|
|
14996
15592
|
version: VERSION,
|
|
14997
15593
|
lastSeenVersion
|
|
14998
15594
|
}),
|
|
@@ -15001,8 +15597,8 @@ function TerminalConsole(props) {
|
|
|
15001
15597
|
const quietStartup = (services?.settings.get("quietStartup") ?? false) && !verbose;
|
|
15002
15598
|
const sweep = (services?.settings.get("logoSweep") ?? false) && !(services?.settings.get("reducedMotion") ?? false) && Boolean(process.stdout.isTTY);
|
|
15003
15599
|
const welcomeSeed = PINNED_WELCOME_SEED;
|
|
15004
|
-
const [welcomeName, setWelcomeName] =
|
|
15005
|
-
|
|
15600
|
+
const [welcomeName, setWelcomeName] = useState10(void 0);
|
|
15601
|
+
useEffect9(() => {
|
|
15006
15602
|
if (!services) return;
|
|
15007
15603
|
let live3 = true;
|
|
15008
15604
|
const provider = services.settings.get("defaultProvider");
|
|
@@ -15014,119 +15610,127 @@ function TerminalConsole(props) {
|
|
|
15014
15610
|
live3 = false;
|
|
15015
15611
|
};
|
|
15016
15612
|
}, [services]);
|
|
15017
|
-
const
|
|
15613
|
+
const authRefreshKey = useMemo2(() => ({ status: state.status, modal: state.modal.kind }), [state.status, state.modal.kind]);
|
|
15614
|
+
const authedProviders = useAuthenticatedProviders(services, authRefreshKey);
|
|
15018
15615
|
const boundModelId = conductor.snapshot().modelId;
|
|
15019
15616
|
const boundProvider = boundModelId.includes("/") ? boundModelId.split("/")[0] : boundModelId;
|
|
15020
15617
|
const modelAuthed = authedProviders === null || authedProviders.has(boundProvider);
|
|
15021
15618
|
const bannerModelId = modelAuthed ? boundModelId : "no authenticated model \u2014 run /login";
|
|
15022
15619
|
const statusBarSnapshot = modelAuthed || !snapshot.model ? snapshot : { ...snapshot, model: { ...snapshot.model, provider: "no model", id: "run /login" } };
|
|
15023
|
-
return
|
|
15620
|
+
return jsx14(Box12, {
|
|
15024
15621
|
flexDirection: "column",
|
|
15025
|
-
|
|
15026
|
-
|
|
15027
|
-
|
|
15028
|
-
|
|
15029
|
-
|
|
15030
|
-
|
|
15031
|
-
|
|
15032
|
-
|
|
15033
|
-
|
|
15034
|
-
|
|
15035
|
-
|
|
15036
|
-
|
|
15037
|
-
|
|
15038
|
-
|
|
15039
|
-
|
|
15040
|
-
|
|
15041
|
-
|
|
15042
|
-
started: liveMessages.length > 0,
|
|
15043
|
-
branch,
|
|
15044
|
-
name: welcomeName,
|
|
15045
|
-
sweep,
|
|
15046
|
-
startup: startupMap,
|
|
15047
|
-
variantSeed: welcomeSeed
|
|
15048
|
-
}),
|
|
15049
|
-
compactNote !== null ? jsxs10(Box10, {
|
|
15050
|
-
flexDirection: "column",
|
|
15051
|
-
borderStyle: "round",
|
|
15052
|
-
borderColor: adapter.colors["borderMuted"],
|
|
15053
|
-
paddingX: 1,
|
|
15054
|
-
marginBottom: 1,
|
|
15055
|
-
children: [
|
|
15056
|
-
jsx13(Text10, {
|
|
15057
|
-
children: adapter.color("accent", "\u25C6 Context condensed \u2014 fresh session, history summarized")
|
|
15058
|
-
}),
|
|
15059
|
-
compactNote.length > 0 ? jsxs10(Fragment4, {
|
|
15060
|
-
children: [
|
|
15061
|
-
jsx13(Text10, { children: adapter.muted("Files carried into the new context:") }),
|
|
15062
|
-
compactNote.map(
|
|
15063
|
-
(file, index) => jsx13(Text10, { children: adapter.muted(` \xB7 ${file}`) }, index)
|
|
15064
|
-
)
|
|
15065
|
-
]
|
|
15066
|
-
}) : jsx13(Text10, {
|
|
15067
|
-
children: adapter.muted("No files re-attached; the summary digest carries the history.")
|
|
15068
|
-
})
|
|
15069
|
-
]
|
|
15070
|
-
}) : null,
|
|
15071
|
-
jsx13(MessageList, {
|
|
15072
|
-
messages: liveMessages,
|
|
15073
|
-
theme: adapter,
|
|
15074
|
-
showThinking: state.showReasoning,
|
|
15075
|
-
showImages: state.showImages,
|
|
15076
|
-
expandToolOutputs: expandTools,
|
|
15077
|
-
maxItems,
|
|
15078
|
-
displayBlocks: [...state.blocks]
|
|
15079
|
-
}),
|
|
15080
|
-
liveAnswer.current !== null && answerText.current ? jsx13(Box10, {
|
|
15081
|
-
flexDirection: "column",
|
|
15082
|
-
marginBottom: 1,
|
|
15083
|
-
children: jsx13(StreamingMarkdown, { theme: adapter, children: answerText.current })
|
|
15084
|
-
}) : null,
|
|
15085
|
-
showTaskPanel ? jsx13(TaskPanel, {
|
|
15086
|
-
theme: adapter,
|
|
15087
|
-
snapshot,
|
|
15088
|
-
toolExecutions: SHOW_TOOL_ACTIVITY ? toolExecutions : {},
|
|
15089
|
-
expandToolOutputs: expandTools,
|
|
15090
|
-
pendingMessages
|
|
15091
|
-
}) : null,
|
|
15092
|
-
jsx13(WorkingIndicator, {
|
|
15093
|
-
theme: adapter,
|
|
15094
|
-
busy: state.busy || conductor.snapshot().phase === "condensing",
|
|
15095
|
-
phase: conductor.snapshot().phase
|
|
15096
|
-
}),
|
|
15097
|
-
jsx13(Composer, {
|
|
15098
|
-
theme: adapter,
|
|
15099
|
-
buffer: state.buffer,
|
|
15100
|
-
caret: state.caret,
|
|
15101
|
-
busy: state.busy,
|
|
15102
|
-
suggestions,
|
|
15103
|
-
highlight
|
|
15104
|
-
}),
|
|
15105
|
-
jsx13(StatusBar, {
|
|
15106
|
-
theme: adapter,
|
|
15107
|
-
snapshot: statusBarSnapshot,
|
|
15108
|
-
branch,
|
|
15109
|
-
providerCount,
|
|
15110
|
-
status: state.status,
|
|
15111
|
-
permissionMode: conductor.permissionMode()
|
|
15112
|
-
}),
|
|
15113
|
-
jsx13(BackgroundAgents, { theme: adapter, runs: agentRuns, tokens: taskTokens })
|
|
15114
|
-
]
|
|
15115
|
-
}),
|
|
15116
|
-
jsx13(OverlayHost, {
|
|
15117
|
-
modal: state.modal,
|
|
15118
|
-
services,
|
|
15622
|
+
width: terminalColumns,
|
|
15623
|
+
height: renderRows,
|
|
15624
|
+
overflow: "hidden",
|
|
15625
|
+
children: modalOpen ? jsx14(ScrollViewport, { follow: false, children: jsx14(OverlayHost, {
|
|
15626
|
+
modal: state.modal,
|
|
15627
|
+
services,
|
|
15628
|
+
theme: adapter,
|
|
15629
|
+
dispatch: dispatch2,
|
|
15630
|
+
closeModal: () => dispatch2({ type: "modal:close" })
|
|
15631
|
+
}) }, state.modal.kind) : agentsOpen ? jsx14(ScrollViewport, { follow: false, children: jsx14(AgentsView, {
|
|
15632
|
+
theme: adapter,
|
|
15633
|
+
runs: agentRuns,
|
|
15634
|
+
activity: subagentActivity,
|
|
15635
|
+
tokens: taskTokens,
|
|
15636
|
+
onExit: () => setAgentsOpen(false)
|
|
15637
|
+
}) }, "agents") : jsxs10(Fragment4, { children: [
|
|
15638
|
+
terminalRows >= 18 ? jsx14(Box12, { flexShrink: 0, flexDirection: "column", children: jsx14(Banner, {
|
|
15119
15639
|
theme: adapter,
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
|
|
15123
|
-
|
|
15640
|
+
modelId: bannerModelId,
|
|
15641
|
+
workspace: process.cwd(),
|
|
15642
|
+
version: VERSION,
|
|
15643
|
+
verbose,
|
|
15644
|
+
quiet: quietStartup,
|
|
15645
|
+
compact: liveMessages.length > 0 || terminalRows < 32,
|
|
15646
|
+
started: liveMessages.length > 0,
|
|
15647
|
+
branch,
|
|
15648
|
+
name: welcomeName,
|
|
15649
|
+
sweep,
|
|
15650
|
+
startup: startupMap,
|
|
15651
|
+
variantSeed: welcomeSeed
|
|
15652
|
+
}) }) : null,
|
|
15653
|
+
jsx14(ScrollViewport, { children: jsxs10(Fragment4, { children: [
|
|
15654
|
+
compactNote !== null ? jsx14(Text11, { children: adapter.muted(
|
|
15655
|
+
`Context condensed.${compactNote.length ? " Files carried: " + compactNote.join(", ") : ""}`
|
|
15656
|
+
) }) : null,
|
|
15657
|
+
jsx14(MessageList, {
|
|
15658
|
+
messages: liveMessages,
|
|
15659
|
+
theme: adapter,
|
|
15660
|
+
showThinking: state.showReasoning,
|
|
15661
|
+
showImages: state.showImages,
|
|
15662
|
+
expandToolOutputs: expandTools,
|
|
15663
|
+
maxItems: liveMessages.length + state.blocks.length,
|
|
15664
|
+
displayBlocks: [...state.blocks]
|
|
15665
|
+
}),
|
|
15666
|
+
state.showReasoning && liveReason.current !== null && reasonText.current ? jsx14(Box12, {
|
|
15667
|
+
flexDirection: "column",
|
|
15668
|
+
marginBottom: 1,
|
|
15669
|
+
children: jsx14(StreamingMarkdown, { theme: adapter, dim: true, children: reasonText.current })
|
|
15670
|
+
}) : null,
|
|
15671
|
+
liveAnswer.current !== null && answerText.current ? jsx14(Box12, {
|
|
15672
|
+
flexDirection: "column",
|
|
15673
|
+
marginBottom: 1,
|
|
15674
|
+
children: jsx14(StreamingMarkdown, { theme: adapter, children: answerText.current })
|
|
15675
|
+
}) : null,
|
|
15676
|
+
showTaskPanel ? jsx14(TaskPanel, {
|
|
15677
|
+
theme: adapter,
|
|
15678
|
+
snapshot,
|
|
15679
|
+
toolExecutions: SHOW_TOOL_ACTIVITY ? toolExecutions : {},
|
|
15680
|
+
expandToolOutputs: expandTools,
|
|
15681
|
+
pendingMessages
|
|
15682
|
+
}) : null,
|
|
15683
|
+
jsx14(BackgroundAgents, { theme: adapter, runs: agentRuns, tokens: taskTokens })
|
|
15684
|
+
] }) }, snapshot.sessionId),
|
|
15685
|
+
jsx14(Box12, { flexDirection: "column", flexShrink: 0, children: jsxs10(Fragment4, { children: [
|
|
15686
|
+
jsx14(WorkingIndicator, { theme: adapter, busy: state.busy || conductor.snapshot().phase === "condensing", phase: conductor.snapshot().phase, reducedMotion: services?.settings.get("reducedMotion") ?? false }),
|
|
15687
|
+
jsx14(Composer, {
|
|
15688
|
+
theme: adapter,
|
|
15689
|
+
buffer: state.buffer,
|
|
15690
|
+
caret: state.caret,
|
|
15691
|
+
busy: state.busy,
|
|
15692
|
+
suggestions,
|
|
15693
|
+
highlight,
|
|
15694
|
+
paddingX: services?.settings.get("editorPaddingX") ?? 1
|
|
15695
|
+
}),
|
|
15696
|
+
terminalRows >= 12 ? jsx14(StatusBar, {
|
|
15697
|
+
theme: adapter,
|
|
15698
|
+
snapshot: statusBarSnapshot,
|
|
15699
|
+
branch,
|
|
15700
|
+
providerCount,
|
|
15701
|
+
status: state.status,
|
|
15702
|
+
permissionMode: conductor.permissionMode()
|
|
15703
|
+
}) : null
|
|
15704
|
+
] }) })
|
|
15705
|
+
] })
|
|
15124
15706
|
});
|
|
15125
15707
|
}
|
|
15126
15708
|
|
|
15127
15709
|
// src/console/mount.ts
|
|
15128
15710
|
import { createElement as createElement2 } from "indusagi/react-host";
|
|
15129
15711
|
import { render as render2 } from "indusagi/react-host/ink";
|
|
15712
|
+
var SYNC_OUTPUT_BEGIN = "\x1B[?2026h";
|
|
15713
|
+
var SYNC_OUTPUT_END = "\x1B[?2026l";
|
|
15714
|
+
function supportsSynchronizedOutput(stream) {
|
|
15715
|
+
if (!stream.isTTY || process.env["INDUS_TUI_SYNC_OUTPUT"] === "0") return false;
|
|
15716
|
+
const term = process.env["TERM"] ?? "";
|
|
15717
|
+
return process.env["TMUX"] === void 0 && process.env["STY"] === void 0 && !term.startsWith("screen") && !term.startsWith("tmux");
|
|
15718
|
+
}
|
|
15719
|
+
function synchronizedOutputStream(stream, enabled = supportsSynchronizedOutput(stream)) {
|
|
15720
|
+
if (!enabled) return stream;
|
|
15721
|
+
const write = (chunk, encodingOrCallback, callback) => {
|
|
15722
|
+
const framed = typeof chunk === "string" ? `${SYNC_OUTPUT_BEGIN}${chunk}${SYNC_OUTPUT_END}` : Buffer.concat([Buffer.from(SYNC_OUTPUT_BEGIN), Buffer.from(chunk), Buffer.from(SYNC_OUTPUT_END)]);
|
|
15723
|
+
if (typeof encodingOrCallback === "function") return stream.write(framed, encodingOrCallback);
|
|
15724
|
+
return stream.write(framed, encodingOrCallback, callback);
|
|
15725
|
+
};
|
|
15726
|
+
return new Proxy(stream, {
|
|
15727
|
+
get(target, property) {
|
|
15728
|
+
if (property === "write") return write;
|
|
15729
|
+
const value = Reflect.get(target, property, target);
|
|
15730
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
15731
|
+
}
|
|
15732
|
+
});
|
|
15733
|
+
}
|
|
15130
15734
|
async function mountConsole(conductor, opts = {}) {
|
|
15131
15735
|
const theme = resolveTheme(opts.scheme ?? null);
|
|
15132
15736
|
const slash = opts.slash ?? DEFAULT_SLASH_REGISTRY;
|
|
@@ -15144,15 +15748,23 @@ async function mountConsole(conductor, opts = {}) {
|
|
|
15144
15748
|
instance.unmount();
|
|
15145
15749
|
}
|
|
15146
15750
|
};
|
|
15147
|
-
const
|
|
15148
|
-
|
|
15149
|
-
|
|
15751
|
+
const wasRaw = process.stdin.isRaw === true;
|
|
15752
|
+
const stdout = synchronizedOutputStream(process.stdout);
|
|
15753
|
+
const instance = render2(createElement2(TerminalConsole, props), { exitOnCtrlC: false, stdout });
|
|
15754
|
+
try {
|
|
15755
|
+
await instance.waitUntilExit();
|
|
15756
|
+
return { clean: exited };
|
|
15757
|
+
} finally {
|
|
15758
|
+
instance.unmount();
|
|
15759
|
+
if (process.stdin.isTTY) process.stdin.setRawMode(wasRaw);
|
|
15760
|
+
if (process.stdout.isTTY) process.stdout.write("\x1B[?25h");
|
|
15761
|
+
}
|
|
15150
15762
|
}
|
|
15151
15763
|
|
|
15152
15764
|
// src/boot/runners/session.ts
|
|
15153
|
-
import { existsSync as
|
|
15154
|
-
import { join as join22 } from "node:path";
|
|
15155
|
-
import { homedir as
|
|
15765
|
+
import { existsSync as existsSync8, readFileSync as readFileSync17 } from "node:fs";
|
|
15766
|
+
import { isAbsolute as isAbsolute6, join as join22, resolve as resolve10 } from "node:path";
|
|
15767
|
+
import { homedir as homedir10 } from "node:os";
|
|
15156
15768
|
import { createMCPAgentToolFactory as createMCPAgentToolFactory4, loadMCPConfig as loadMCPConfig2, MCPClientPool as MCPClientPool2 } from "indusagi/mcp";
|
|
15157
15769
|
|
|
15158
15770
|
// src/boot/runners/delegate-runner.ts
|
|
@@ -15209,7 +15821,7 @@ async function acquireTaskSlot() {
|
|
|
15209
15821
|
if (activeTasks < MAX_PARALLEL_TASKS) {
|
|
15210
15822
|
activeTasks++;
|
|
15211
15823
|
} else {
|
|
15212
|
-
await new Promise((
|
|
15824
|
+
await new Promise((resolve11) => taskQueue.push(resolve11));
|
|
15213
15825
|
}
|
|
15214
15826
|
let released = false;
|
|
15215
15827
|
return () => {
|
|
@@ -15314,7 +15926,7 @@ ${request.context}` : request.objective;
|
|
|
15314
15926
|
}
|
|
15315
15927
|
|
|
15316
15928
|
// src/boot/runners/checkpoint.ts
|
|
15317
|
-
import { mkdirSync as mkdirSync3, rmSync, writeFileSync as
|
|
15929
|
+
import { mkdirSync as mkdirSync3, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "node:fs";
|
|
15318
15930
|
import { dirname as dirname22, normalize as normalize2 } from "node:path";
|
|
15319
15931
|
var CHECKPOINT_HANDLE_KEY = "checkpoint";
|
|
15320
15932
|
var ROOT_NODE_ID = "__root__";
|
|
@@ -15382,7 +15994,7 @@ var CheckpointStore = class {
|
|
|
15382
15994
|
snapshotFor(nodeId) {
|
|
15383
15995
|
const paths = this.byNode.get(nodeId);
|
|
15384
15996
|
if (paths === void 0) return [];
|
|
15385
|
-
return [...paths].map(([
|
|
15997
|
+
return [...paths].map(([path5, previous]) => ({ path: path5, previous }));
|
|
15386
15998
|
}
|
|
15387
15999
|
/** Whether a node has ANY recorded file snapshot (the picker's restore gate). */
|
|
15388
16000
|
hasSnapshot(nodeId) {
|
|
@@ -15408,15 +16020,15 @@ var CheckpointStore = class {
|
|
|
15408
16020
|
restore(nodeId) {
|
|
15409
16021
|
const snapshots = this.snapshotFor(nodeId);
|
|
15410
16022
|
const restored = [];
|
|
15411
|
-
for (const { path:
|
|
16023
|
+
for (const { path: path5, previous } of snapshots) {
|
|
15412
16024
|
try {
|
|
15413
16025
|
if (previous === null) {
|
|
15414
|
-
|
|
16026
|
+
rmSync2(path5, { force: true });
|
|
15415
16027
|
} else {
|
|
15416
|
-
mkdirSync3(dirname22(
|
|
15417
|
-
|
|
16028
|
+
mkdirSync3(dirname22(path5), { recursive: true });
|
|
16029
|
+
writeFileSync7(path5, previous, "utf8");
|
|
15418
16030
|
}
|
|
15419
|
-
restored.push(
|
|
16031
|
+
restored.push(path5);
|
|
15420
16032
|
} catch {
|
|
15421
16033
|
}
|
|
15422
16034
|
}
|
|
@@ -15463,15 +16075,15 @@ function createReadStateStore() {
|
|
|
15463
16075
|
}
|
|
15464
16076
|
|
|
15465
16077
|
// src/integrations/zoho/config.ts
|
|
15466
|
-
import { existsSync as
|
|
15467
|
-
import { homedir as
|
|
15468
|
-
import { dirname as
|
|
16078
|
+
import { existsSync as existsSync4, readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync4 } from "node:fs";
|
|
16079
|
+
import { homedir as homedir7 } from "node:os";
|
|
16080
|
+
import { dirname as dirname6, join as join17 } from "node:path";
|
|
15469
16081
|
var ENV_URL = "ZOHO_MCP_URL";
|
|
15470
16082
|
var ENV_DISABLE = "ZOHO_DISABLED";
|
|
15471
|
-
function readJsonFile(
|
|
16083
|
+
function readJsonFile(path5) {
|
|
15472
16084
|
try {
|
|
15473
|
-
if (!
|
|
15474
|
-
const raw = readFileSync12(
|
|
16085
|
+
if (!existsSync4(path5)) return void 0;
|
|
16086
|
+
const raw = readFileSync12(path5, "utf8");
|
|
15475
16087
|
const parsed = JSON.parse(raw);
|
|
15476
16088
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
15477
16089
|
return void 0;
|
|
@@ -15490,11 +16102,11 @@ function configFromRecord(rec) {
|
|
|
15490
16102
|
const auth = rec.auth === "none" || rec.auth === "oauth" || rec.auth === "auto" ? rec.auth : "auto";
|
|
15491
16103
|
return { url, id, enabled, auth };
|
|
15492
16104
|
}
|
|
15493
|
-
function profileZohoPath(home =
|
|
15494
|
-
return
|
|
16105
|
+
function profileZohoPath(home = homedir7()) {
|
|
16106
|
+
return join17(home, ".indusagi", "agent", "zoho.json");
|
|
15495
16107
|
}
|
|
15496
16108
|
function projectZohoPath(cwd) {
|
|
15497
|
-
return
|
|
16109
|
+
return join17(cwd, ".indusagi", "zoho.json");
|
|
15498
16110
|
}
|
|
15499
16111
|
function resolveZohoConfig(opts = {}) {
|
|
15500
16112
|
const env2 = opts.env ?? process.env;
|
|
@@ -15506,7 +16118,7 @@ function resolveZohoConfig(opts = {}) {
|
|
|
15506
16118
|
const fromEnv = env2[ENV_URL]?.trim();
|
|
15507
16119
|
const fromProject = configFromRecord(readJsonFile(projectZohoPath(cwd)));
|
|
15508
16120
|
const fromProfile = configFromRecord(
|
|
15509
|
-
readJsonFile(profileZohoPath(opts.home ??
|
|
16121
|
+
readJsonFile(profileZohoPath(opts.home ?? homedir7()))
|
|
15510
16122
|
);
|
|
15511
16123
|
const base = (fromArg ? { url: fromArg, id: "zoho", enabled: true, auth: "auto" } : void 0) ?? (fromEnv ? { url: fromEnv, id: "zoho", enabled: true, auth: "auto" } : void 0) ?? fromProject ?? fromProfile;
|
|
15512
16124
|
if (!base) return void 0;
|
|
@@ -15518,9 +16130,9 @@ function resolveZohoConfig(opts = {}) {
|
|
|
15518
16130
|
}
|
|
15519
16131
|
|
|
15520
16132
|
// src/integrations/zoho/attach.ts
|
|
15521
|
-
import { existsSync as
|
|
15522
|
-
import { homedir as
|
|
15523
|
-
import { join as
|
|
16133
|
+
import { existsSync as existsSync5, readFileSync as readFileSync13 } from "node:fs";
|
|
16134
|
+
import { homedir as homedir8 } from "node:os";
|
|
16135
|
+
import { join as join18 } from "node:path";
|
|
15524
16136
|
import { connectZohoMcp } from "indusagi/zoho";
|
|
15525
16137
|
import { createMCPAgentToolFactory as createMCPAgentToolFactory2 } from "indusagi/mcp";
|
|
15526
16138
|
var live = null;
|
|
@@ -15529,15 +16141,15 @@ var cancelConnect = false;
|
|
|
15529
16141
|
var lastAuthUrl;
|
|
15530
16142
|
function zohoTokenPath(id = "zoho") {
|
|
15531
16143
|
const xdg = process.env.XDG_CONFIG_HOME;
|
|
15532
|
-
const home = process.env.HOME ?? process.env.USERPROFILE ??
|
|
15533
|
-
const dir = xdg && xdg.length > 0 ?
|
|
15534
|
-
return
|
|
16144
|
+
const home = process.env.HOME ?? process.env.USERPROFILE ?? homedir8();
|
|
16145
|
+
const dir = xdg && xdg.length > 0 ? join18(xdg, "indusagi", "credentials", "mcp") : join18(home, ".config", "indusagi", "credentials", "mcp");
|
|
16146
|
+
return join18(dir, `${id.replace(/[^a-zA-Z0-9._-]/g, "-")}.json`);
|
|
15535
16147
|
}
|
|
15536
16148
|
function hasUsableZohoTokens(id = "zoho") {
|
|
15537
|
-
const
|
|
16149
|
+
const path5 = zohoTokenPath(id);
|
|
15538
16150
|
try {
|
|
15539
|
-
if (!
|
|
15540
|
-
const raw = readFileSync13(
|
|
16151
|
+
if (!existsSync5(path5)) return false;
|
|
16152
|
+
const raw = readFileSync13(path5, "utf8");
|
|
15541
16153
|
const parsed = JSON.parse(raw);
|
|
15542
16154
|
return typeof parsed?.tokens?.access_token === "string" && parsed.tokens.access_token.length > 0;
|
|
15543
16155
|
} catch {
|
|
@@ -15676,17 +16288,18 @@ async function loadZohoAgentTools(opts) {
|
|
|
15676
16288
|
}
|
|
15677
16289
|
|
|
15678
16290
|
// src/integrations/sarvam/config.ts
|
|
15679
|
-
import { existsSync as
|
|
15680
|
-
import { homedir as
|
|
15681
|
-
import {
|
|
16291
|
+
import { existsSync as existsSync6, readFileSync as readFileSync14 } from "node:fs";
|
|
16292
|
+
import { homedir as homedir9 } from "node:os";
|
|
16293
|
+
import { join as join19 } from "node:path";
|
|
15682
16294
|
var ENV_KEY = "SARVAM_API_KEY";
|
|
15683
16295
|
var ENV_DISABLE2 = "SARVAM_DISABLED";
|
|
15684
16296
|
var ENV_BASE_URL = "SARVAM_API_BASE_URL";
|
|
15685
16297
|
var ENV_BASE_PATH = "SARVAM_MCP_BASE_PATH";
|
|
15686
|
-
function readJsonFile2(
|
|
16298
|
+
function readJsonFile2(path5, sensitive = false) {
|
|
15687
16299
|
try {
|
|
15688
|
-
if (!
|
|
15689
|
-
const raw = readFileSync14(
|
|
16300
|
+
if (!sensitive && !existsSync6(path5)) return void 0;
|
|
16301
|
+
const raw = sensitive ? readPrivateFileSync(path5) : readFileSync14(path5, "utf8");
|
|
16302
|
+
if (raw === null) return void 0;
|
|
15690
16303
|
const parsed = JSON.parse(raw);
|
|
15691
16304
|
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
15692
16305
|
return void 0;
|
|
@@ -15696,11 +16309,11 @@ function readJsonFile2(path4) {
|
|
|
15696
16309
|
return void 0;
|
|
15697
16310
|
}
|
|
15698
16311
|
}
|
|
15699
|
-
function configFromRecord2(rec) {
|
|
16312
|
+
function configFromRecord2(rec, includeApiKey = true) {
|
|
15700
16313
|
if (!rec) return void 0;
|
|
15701
16314
|
const enabled = rec.enabled === false ? false : true;
|
|
15702
16315
|
const id = typeof rec.id === "string" && rec.id.trim() ? rec.id.trim() : "sarvam";
|
|
15703
|
-
const apiKey = typeof rec.apiKey === "string" ? rec.apiKey.trim() : void 0;
|
|
16316
|
+
const apiKey = includeApiKey && typeof rec.apiKey === "string" ? rec.apiKey.trim() : void 0;
|
|
15704
16317
|
const baseUrl = typeof rec.baseUrl === "string" ? rec.baseUrl.trim() : void 0;
|
|
15705
16318
|
const basePath = typeof rec.basePath === "string" ? rec.basePath.trim() : void 0;
|
|
15706
16319
|
const command = typeof rec.command === "string" ? rec.command.trim() : void 0;
|
|
@@ -15713,11 +16326,11 @@ function configFromRecord2(rec) {
|
|
|
15713
16326
|
...command ? { command } : {}
|
|
15714
16327
|
};
|
|
15715
16328
|
}
|
|
15716
|
-
function profileSarvamPath(home =
|
|
15717
|
-
return
|
|
16329
|
+
function profileSarvamPath(home = homedir9()) {
|
|
16330
|
+
return join19(home, ".indusagi", "agent", "sarvam.json");
|
|
15718
16331
|
}
|
|
15719
16332
|
function projectSarvamPath(cwd) {
|
|
15720
|
-
return
|
|
16333
|
+
return join19(cwd, ".indusagi", "sarvam.json");
|
|
15721
16334
|
}
|
|
15722
16335
|
function resolveSarvamConfig(opts = {}) {
|
|
15723
16336
|
const env2 = opts.env ?? process.env;
|
|
@@ -15727,9 +16340,9 @@ function resolveSarvamConfig(opts = {}) {
|
|
|
15727
16340
|
}
|
|
15728
16341
|
const fromArgKey = opts.apiKey?.trim();
|
|
15729
16342
|
const fromEnvKey = env2[ENV_KEY]?.trim();
|
|
15730
|
-
const fromProject = configFromRecord2(readJsonFile2(projectSarvamPath(cwd)));
|
|
16343
|
+
const fromProject = configFromRecord2(readJsonFile2(projectSarvamPath(cwd)), false);
|
|
15731
16344
|
const fromProfile = configFromRecord2(
|
|
15732
|
-
readJsonFile2(profileSarvamPath(opts.home ??
|
|
16345
|
+
readJsonFile2(profileSarvamPath(opts.home ?? homedir9()), true)
|
|
15733
16346
|
);
|
|
15734
16347
|
const fileBase = fromProject ?? fromProfile;
|
|
15735
16348
|
const apiKey = fromArgKey || fromEnvKey || fileBase?.apiKey;
|
|
@@ -15854,8 +16467,6 @@ async function loadSarvamAgentTools(opts) {
|
|
|
15854
16467
|
}
|
|
15855
16468
|
|
|
15856
16469
|
// src/boot/auth-vault.ts
|
|
15857
|
-
import { mkdirSync as mkdirSync6, readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "node:fs";
|
|
15858
|
-
import { dirname as dirname7 } from "node:path";
|
|
15859
16470
|
import {
|
|
15860
16471
|
ensureFreshOAuthCredentials,
|
|
15861
16472
|
getOAuthProvider as getOAuthProvider3
|
|
@@ -15879,8 +16490,9 @@ function normaliseRecord(value) {
|
|
|
15879
16490
|
return void 0;
|
|
15880
16491
|
}
|
|
15881
16492
|
function readAuthFile(filePath) {
|
|
16493
|
+
const text = readPrivateFileSync(filePath);
|
|
16494
|
+
if (text === null) return {};
|
|
15882
16495
|
try {
|
|
15883
|
-
const text = readFileSync15(filePath, "utf8");
|
|
15884
16496
|
const parsed = JSON.parse(text);
|
|
15885
16497
|
if (parsed === null || typeof parsed !== "object") return {};
|
|
15886
16498
|
const file = {};
|
|
@@ -15899,9 +16511,8 @@ function readAuthFile(filePath) {
|
|
|
15899
16511
|
}
|
|
15900
16512
|
}
|
|
15901
16513
|
function writeAuthFile(filePath, data) {
|
|
15902
|
-
|
|
15903
|
-
|
|
15904
|
-
`, { mode: 384 });
|
|
16514
|
+
atomicWritePrivateFileSync(filePath, `${JSON.stringify(data, null, 2)}
|
|
16515
|
+
`);
|
|
15905
16516
|
}
|
|
15906
16517
|
function toCredentials(record) {
|
|
15907
16518
|
const { kind: _kind, isDefault: _isDefault, ...credentials } = record;
|
|
@@ -15995,8 +16606,8 @@ function createAuthVault(authPath) {
|
|
|
15995
16606
|
}
|
|
15996
16607
|
|
|
15997
16608
|
// src/boot/runners/memdir.ts
|
|
15998
|
-
import { existsSync as
|
|
15999
|
-
import { join as
|
|
16609
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as writeFileSync9 } from "node:fs";
|
|
16610
|
+
import { join as join20 } from "node:path";
|
|
16000
16611
|
var MEMORY_ENTRYPOINT = "MEMORY.md";
|
|
16001
16612
|
var MAX_ENTRYPOINT_LINES = 200;
|
|
16002
16613
|
var MAX_ENTRYPOINT_BYTES = 25e3;
|
|
@@ -16022,27 +16633,27 @@ function truncateEntrypointContent(raw) {
|
|
|
16022
16633
|
}
|
|
16023
16634
|
function memoryDirFor(workspace, cwd) {
|
|
16024
16635
|
const slug = cwd.replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
16025
|
-
return
|
|
16636
|
+
return join20(workspace.profileDir, "memory", `--${slug}--`);
|
|
16026
16637
|
}
|
|
16027
16638
|
var DiskMemoryStore = class {
|
|
16028
16639
|
memDir;
|
|
16029
16640
|
file;
|
|
16030
16641
|
constructor(memDir) {
|
|
16031
16642
|
this.memDir = memDir;
|
|
16032
|
-
this.file =
|
|
16643
|
+
this.file = join20(memDir, MEMORY_ENTRYPOINT);
|
|
16033
16644
|
}
|
|
16034
16645
|
/** The current note, or `""` when no file has been written yet. */
|
|
16035
16646
|
read() {
|
|
16036
16647
|
try {
|
|
16037
|
-
return
|
|
16648
|
+
return existsSync7(this.file) ? readFileSync15(this.file, "utf8") : "";
|
|
16038
16649
|
} catch {
|
|
16039
16650
|
return "";
|
|
16040
16651
|
}
|
|
16041
16652
|
}
|
|
16042
16653
|
/** Overwrite the note, creating the memory directory as needed (mode 0o600). */
|
|
16043
16654
|
replace(content) {
|
|
16044
|
-
|
|
16045
|
-
|
|
16655
|
+
mkdirSync5(this.memDir, { recursive: true });
|
|
16656
|
+
writeFileSync9(this.file, content, { mode: 384 });
|
|
16046
16657
|
}
|
|
16047
16658
|
/** Add a single line to the end of the note (composed of read + replace). */
|
|
16048
16659
|
append(line) {
|
|
@@ -16055,9 +16666,9 @@ ${line}`;
|
|
|
16055
16666
|
function loadMemoryDoc(memDir) {
|
|
16056
16667
|
let raw;
|
|
16057
16668
|
try {
|
|
16058
|
-
const file =
|
|
16059
|
-
if (!
|
|
16060
|
-
raw =
|
|
16669
|
+
const file = join20(memDir, MEMORY_ENTRYPOINT);
|
|
16670
|
+
if (!existsSync7(file)) return void 0;
|
|
16671
|
+
raw = readFileSync15(file, "utf8");
|
|
16061
16672
|
} catch {
|
|
16062
16673
|
return void 0;
|
|
16063
16674
|
}
|
|
@@ -16068,11 +16679,104 @@ function loadMemoryDoc(memDir) {
|
|
|
16068
16679
|
}
|
|
16069
16680
|
|
|
16070
16681
|
// src/boot/runners/addon-wiring.ts
|
|
16682
|
+
import { createHash } from "node:crypto";
|
|
16683
|
+
import { lstatSync as lstatSync3, readFileSync as readFileSync16, readdirSync as readdirSync5, realpathSync as realpathSync3 } from "node:fs";
|
|
16684
|
+
import { join as join21, relative, resolve as resolve9 } from "node:path";
|
|
16685
|
+
var TRUST_FILE = "addon-trust.json";
|
|
16686
|
+
function hashAddonTree(addonsDir) {
|
|
16687
|
+
let root;
|
|
16688
|
+
try {
|
|
16689
|
+
const rootStat = lstatSync3(addonsDir);
|
|
16690
|
+
if (rootStat.isSymbolicLink() || !rootStat.isDirectory()) return null;
|
|
16691
|
+
root = realpathSync3(addonsDir);
|
|
16692
|
+
} catch (error) {
|
|
16693
|
+
if (error.code === "ENOENT") return null;
|
|
16694
|
+
throw error;
|
|
16695
|
+
}
|
|
16696
|
+
const files = [];
|
|
16697
|
+
const visit = (dir) => {
|
|
16698
|
+
for (const entry of readdirSync5(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
|
|
16699
|
+
const path5 = join21(dir, entry.name);
|
|
16700
|
+
const info2 = lstatSync3(path5);
|
|
16701
|
+
if (info2.isSymbolicLink()) throw new Error(`Refusing symlink in project addon tree: ${path5}`);
|
|
16702
|
+
if (info2.isDirectory()) visit(path5);
|
|
16703
|
+
else if (info2.isFile()) files.push(path5);
|
|
16704
|
+
else throw new Error(`Refusing special file in project addon tree: ${path5}`);
|
|
16705
|
+
}
|
|
16706
|
+
};
|
|
16707
|
+
visit(root);
|
|
16708
|
+
const hash = createHash("sha256");
|
|
16709
|
+
for (const file of files) {
|
|
16710
|
+
hash.update(relative(root, file));
|
|
16711
|
+
hash.update("\0");
|
|
16712
|
+
hash.update(readFileSync16(file));
|
|
16713
|
+
hash.update("\0");
|
|
16714
|
+
}
|
|
16715
|
+
return hash.digest("hex");
|
|
16716
|
+
}
|
|
16717
|
+
function readTrustStore(path5) {
|
|
16718
|
+
const raw = readPrivateFileSync(path5);
|
|
16719
|
+
if (raw === null) return { version: 1, projects: [] };
|
|
16720
|
+
try {
|
|
16721
|
+
const parsed = JSON.parse(raw);
|
|
16722
|
+
if (parsed.version !== 1 || !Array.isArray(parsed.projects)) return { version: 1, projects: [] };
|
|
16723
|
+
return {
|
|
16724
|
+
version: 1,
|
|
16725
|
+
projects: parsed.projects.filter((record) => typeof record?.root === "string" && typeof record?.digest === "string" && typeof record?.approvedAt === "string")
|
|
16726
|
+
};
|
|
16727
|
+
} catch {
|
|
16728
|
+
return { version: 1, projects: [] };
|
|
16729
|
+
}
|
|
16730
|
+
}
|
|
16731
|
+
function persistTrust(path5, root, digest) {
|
|
16732
|
+
const store = readTrustStore(path5);
|
|
16733
|
+
const projects = store.projects.filter((record) => record.root !== root);
|
|
16734
|
+
projects.push({ root, digest, approvedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
16735
|
+
atomicWritePrivateFileSync(path5, `${JSON.stringify({ version: 1, projects }, null, 2)}
|
|
16736
|
+
`);
|
|
16737
|
+
}
|
|
16071
16738
|
async function buildAddonHost(ctx) {
|
|
16072
16739
|
const host = createAddonHost({ handles: {} });
|
|
16073
|
-
host.onFault(() => {
|
|
16740
|
+
host.onFault((fault) => {
|
|
16741
|
+
process.stderr.write(`Addon ${fault.kind} fault: ${fault.message}
|
|
16742
|
+
`);
|
|
16074
16743
|
});
|
|
16075
|
-
|
|
16744
|
+
const workspace = resolve9(ctx.invocation.cwd ?? process.cwd());
|
|
16745
|
+
const addonsDir = join21(workspace, ".indus", "addons");
|
|
16746
|
+
let canonicalRoot;
|
|
16747
|
+
let digest;
|
|
16748
|
+
try {
|
|
16749
|
+
canonicalRoot = realpathSync3(workspace);
|
|
16750
|
+
digest = hashAddonTree(addonsDir);
|
|
16751
|
+
} catch (error) {
|
|
16752
|
+
process.stderr.write(`Project addons blocked: ${error instanceof Error ? error.message : String(error)}
|
|
16753
|
+
`);
|
|
16754
|
+
return host.loadAll({ explicitPaths: [] });
|
|
16755
|
+
}
|
|
16756
|
+
if (digest === null) return host.loadAll({ explicitPaths: [] });
|
|
16757
|
+
const trustPath = join21(ctx.workspace.profileDir, TRUST_FILE);
|
|
16758
|
+
const approvedNow = ctx.invocation.flags["trust-project-addons"] === true;
|
|
16759
|
+
let trusted = false;
|
|
16760
|
+
try {
|
|
16761
|
+
const store = readTrustStore(trustPath);
|
|
16762
|
+
trusted = store.projects.some((record) => record.root === canonicalRoot && record.digest === digest);
|
|
16763
|
+
if (!trusted && approvedNow) {
|
|
16764
|
+
persistTrust(trustPath, canonicalRoot, digest);
|
|
16765
|
+
trusted = true;
|
|
16766
|
+
}
|
|
16767
|
+
} catch (error) {
|
|
16768
|
+
process.stderr.write(`Project addons blocked: ${error instanceof Error ? error.message : String(error)}
|
|
16769
|
+
`);
|
|
16770
|
+
return host.loadAll({ explicitPaths: [] });
|
|
16771
|
+
}
|
|
16772
|
+
if (!trusted) {
|
|
16773
|
+
process.stderr.write(
|
|
16774
|
+
`Project addons are disabled until explicitly trusted for this exact content. Re-run with --trust-project-addons to approve ${canonicalRoot}.
|
|
16775
|
+
`
|
|
16776
|
+
);
|
|
16777
|
+
return host.loadAll({ explicitPaths: [] });
|
|
16778
|
+
}
|
|
16779
|
+
return host.loadAll({ workspace: canonicalRoot });
|
|
16076
16780
|
}
|
|
16077
16781
|
function wrapToolsWithAddons(tools, bundle) {
|
|
16078
16782
|
const chain = bundle.interceptors;
|
|
@@ -16113,12 +16817,107 @@ function concatAddonTools(deck, bundle) {
|
|
|
16113
16817
|
return fresh.length === 0 ? deck : [...deck, ...fresh];
|
|
16114
16818
|
}
|
|
16115
16819
|
|
|
16820
|
+
// src/boot/runners/benchmark-integrity.ts
|
|
16821
|
+
import { appendFileSync } from "node:fs";
|
|
16822
|
+
import path4 from "node:path";
|
|
16823
|
+
var GUARDED_TOOLS = /* @__PURE__ */ new Set(["read", "write", "edit", "grep", "find", "ls", "bash"]);
|
|
16824
|
+
var PATH_KEYS = /* @__PURE__ */ new Set(["path", "file", "file_path", "directory", "dir", "cwd", "search_path"]);
|
|
16825
|
+
var FORBIDDEN_ABSOLUTE = [
|
|
16826
|
+
"/tests",
|
|
16827
|
+
"/solution",
|
|
16828
|
+
"/solutions",
|
|
16829
|
+
"/reference",
|
|
16830
|
+
"/reference_solution",
|
|
16831
|
+
"/reference-solutions",
|
|
16832
|
+
"/reward.txt",
|
|
16833
|
+
"/rewards",
|
|
16834
|
+
"/grader",
|
|
16835
|
+
"/verifier"
|
|
16836
|
+
];
|
|
16837
|
+
var FORBIDDEN_BASENAMES = /* @__PURE__ */ new Set([
|
|
16838
|
+
"solution.sh",
|
|
16839
|
+
"solve.sh",
|
|
16840
|
+
"reward.txt",
|
|
16841
|
+
"expected_answer.txt",
|
|
16842
|
+
"expected_output.txt"
|
|
16843
|
+
]);
|
|
16844
|
+
function normalizeCandidate(value, cwd) {
|
|
16845
|
+
return path4.resolve(cwd, value);
|
|
16846
|
+
}
|
|
16847
|
+
function forbiddenPath(value, cwd) {
|
|
16848
|
+
const resolved = normalizeCandidate(value, cwd);
|
|
16849
|
+
const base = path4.basename(resolved).toLowerCase();
|
|
16850
|
+
if (FORBIDDEN_BASENAMES.has(base)) return true;
|
|
16851
|
+
return FORBIDDEN_ABSOLUTE.some((prefix) => resolved === prefix || resolved.startsWith(`${prefix}/`));
|
|
16852
|
+
}
|
|
16853
|
+
function pathValues(args) {
|
|
16854
|
+
if (args === null || typeof args !== "object" || Array.isArray(args)) return [];
|
|
16855
|
+
const values = [];
|
|
16856
|
+
for (const [key, value] of Object.entries(args)) {
|
|
16857
|
+
if (PATH_KEYS.has(key) && typeof value === "string") values.push(value);
|
|
16858
|
+
}
|
|
16859
|
+
return values;
|
|
16860
|
+
}
|
|
16861
|
+
function forbiddenShell(command, cwd) {
|
|
16862
|
+
const lower = command.toLowerCase();
|
|
16863
|
+
if ([...FORBIDDEN_BASENAMES].some((name) => lower.includes(name))) return true;
|
|
16864
|
+
if (FORBIDDEN_ABSOLUTE.some((prefix) => new RegExp(`(^|[\\s'"=])${prefix.replaceAll("/", "\\/")}(?:[/\\s'";|&]|$)`, "i").test(command))) return true;
|
|
16865
|
+
if (/(^|[\s'"=])\.\.\/(?:tests|solutions?|reference(?:[-_]solutions?)?|grader|verifier)(?:[/\s'";|&]|$)/i.test(command)) return true;
|
|
16866
|
+
if (/\b(?:find|ls|grep|rg)\s+(?:-[^\s]+\s+)*\/(?:\s|$)/i.test(command)) return true;
|
|
16867
|
+
const retrievesOnline = /\b(?:curl|wget|git\s+clone|gh\s+repo\s+clone)\b/i.test(command);
|
|
16868
|
+
const benchmarkMaterial = /terminal[-_ ]bench|reference[-_ ]solution|solution\.sh|solve\.sh|benchmark[-_ ]solution/i.test(command);
|
|
16869
|
+
if (retrievesOnline && benchmarkMaterial) return true;
|
|
16870
|
+
return false;
|
|
16871
|
+
}
|
|
16872
|
+
function denialReason(tool, args, cwd) {
|
|
16873
|
+
if (tool === "bash") {
|
|
16874
|
+
const command = typeof args?.command === "string" ? args.command : "";
|
|
16875
|
+
if (forbiddenShell(command, cwd)) return "Terminal-Bench integrity guard blocked benchmark-owned or solution material.";
|
|
16876
|
+
return void 0;
|
|
16877
|
+
}
|
|
16878
|
+
if (pathValues(args).some((candidate) => forbiddenPath(candidate, cwd))) {
|
|
16879
|
+
return "Terminal-Bench integrity guard blocked benchmark-owned or solution material.";
|
|
16880
|
+
}
|
|
16881
|
+
return void 0;
|
|
16882
|
+
}
|
|
16883
|
+
function recordDenial(tool, callId, reason, env2) {
|
|
16884
|
+
const auditPath = env2.INDUSAGI_BENCHMARK_AUDIT_LOG ?? "/logs/agent/integrity-denials.jsonl";
|
|
16885
|
+
try {
|
|
16886
|
+
appendFileSync(auditPath, `${JSON.stringify({ type: "integrity_denial", tool, call_id: callId, reason })}
|
|
16887
|
+
`, { encoding: "utf8" });
|
|
16888
|
+
} catch {
|
|
16889
|
+
}
|
|
16890
|
+
}
|
|
16891
|
+
function wrapOne2(tool, cwd, env2) {
|
|
16892
|
+
const execute = tool.execute.bind(tool);
|
|
16893
|
+
return {
|
|
16894
|
+
...tool,
|
|
16895
|
+
async execute(callId, args, signal, onUpdate) {
|
|
16896
|
+
const reason = denialReason(tool.name, args, cwd);
|
|
16897
|
+
if (reason !== void 0) {
|
|
16898
|
+
recordDenial(tool.name, callId, reason, env2);
|
|
16899
|
+
return {
|
|
16900
|
+
content: [{ type: "text", text: reason }],
|
|
16901
|
+
details: void 0,
|
|
16902
|
+
isError: true
|
|
16903
|
+
};
|
|
16904
|
+
}
|
|
16905
|
+
return execute(callId, args, signal, onUpdate);
|
|
16906
|
+
}
|
|
16907
|
+
};
|
|
16908
|
+
}
|
|
16909
|
+
function wrapToolsForTerminalBench(tools, cwd, env2 = process.env) {
|
|
16910
|
+
if (env2.INDUSAGI_BENCHMARK_PROFILE !== "terminal-bench") return tools;
|
|
16911
|
+
return tools.map((tool) => GUARDED_TOOLS.has(tool.name) ? wrapOne2(tool, cwd, env2) : tool);
|
|
16912
|
+
}
|
|
16913
|
+
|
|
16116
16914
|
// src/boot/runners/session.ts
|
|
16117
16915
|
function authenticatedProviders(ctx) {
|
|
16118
16916
|
try {
|
|
16119
|
-
const
|
|
16120
|
-
|
|
16121
|
-
|
|
16917
|
+
const path5 = ctx.workspace.authPath;
|
|
16918
|
+
const raw = readPrivateFileSync(path5);
|
|
16919
|
+
if (raw === null) return [];
|
|
16920
|
+
const data = JSON.parse(raw);
|
|
16122
16921
|
return Object.keys(data).filter((id) => {
|
|
16123
16922
|
const accounts = data[id];
|
|
16124
16923
|
return id.length > 0 && accounts !== null && typeof accounts === "object" && Object.keys(accounts).length > 0;
|
|
@@ -16196,9 +16995,9 @@ var PROVIDER_ENV = {
|
|
|
16196
16995
|
};
|
|
16197
16996
|
function primeProviderEnv(ctx) {
|
|
16198
16997
|
try {
|
|
16199
|
-
const
|
|
16200
|
-
if (!
|
|
16201
|
-
const data = JSON.parse(readFileSync17(
|
|
16998
|
+
const path5 = ctx.workspace.authPath;
|
|
16999
|
+
if (!existsSync8(path5)) return;
|
|
17000
|
+
const data = JSON.parse(readFileSync17(path5, "utf8"));
|
|
16202
17001
|
for (const [provider, accounts] of Object.entries(data)) {
|
|
16203
17002
|
if (provider.startsWith("_") || accounts === null || typeof accounts !== "object") continue;
|
|
16204
17003
|
const envVar = PROVIDER_ENV[provider];
|
|
@@ -16242,7 +17041,7 @@ function resolveThinkingLevel(raw, modelId) {
|
|
|
16242
17041
|
}
|
|
16243
17042
|
function resolveText(value) {
|
|
16244
17043
|
try {
|
|
16245
|
-
if (
|
|
17044
|
+
if (existsSync8(value)) return readFileSync17(value, "utf8");
|
|
16246
17045
|
} catch {
|
|
16247
17046
|
}
|
|
16248
17047
|
return value;
|
|
@@ -16251,7 +17050,7 @@ var PROFILE_DIR2 = ".indusagi";
|
|
|
16251
17050
|
function skillRoots2(cwd) {
|
|
16252
17051
|
return [
|
|
16253
17052
|
{ dir: join22(cwd, PROFILE_DIR2, "skills"), origin: "project" },
|
|
16254
|
-
{ dir: join22(
|
|
17053
|
+
{ dir: join22(homedir10(), PROFILE_DIR2, "skills"), origin: "user" }
|
|
16255
17054
|
];
|
|
16256
17055
|
}
|
|
16257
17056
|
function gatherModelSkills(cwd) {
|
|
@@ -16282,8 +17081,9 @@ function selectTools(cwd, inv, runner, memoryStore, checkpoint, workflowRunner)
|
|
|
16282
17081
|
return visible.filter((tool) => allow.has(canon2(tool.name)));
|
|
16283
17082
|
}
|
|
16284
17083
|
function composeSystem(tools, inv, cwd, skills = [], memoryDoc) {
|
|
17084
|
+
const approvedExternalPaths = Array.isArray(inv.flags["allow-context-import"]) ? inv.flags["allow-context-import"].filter((path5) => typeof path5 === "string").map((path5) => isAbsolute6(path5) ? path5 : resolve10(cwd, path5)) : [];
|
|
16285
17085
|
const contextDocs = [
|
|
16286
|
-
...gatherContextDocs(cwd,
|
|
17086
|
+
...gatherContextDocs(cwd, homedir10(), { approvedExternalPaths }),
|
|
16287
17087
|
...memoryDoc ? [memoryDoc] : []
|
|
16288
17088
|
];
|
|
16289
17089
|
let base = inv.system !== void 0 ? resolveText(inv.system) : composeBriefing({ tools, contextDocs, skills });
|
|
@@ -16375,9 +17175,9 @@ async function loadMcpTools(inv, cwd) {
|
|
|
16375
17175
|
console.error = () => {
|
|
16376
17176
|
};
|
|
16377
17177
|
try {
|
|
16378
|
-
for (const
|
|
17178
|
+
for (const path5 of paths) {
|
|
16379
17179
|
try {
|
|
16380
|
-
const servers = loadMCPConfig2(
|
|
17180
|
+
const servers = loadMCPConfig2(path5);
|
|
16381
17181
|
if (servers.length === 0) continue;
|
|
16382
17182
|
const pool = new MCPClientPool2({ servers });
|
|
16383
17183
|
await pool.connectAll();
|
|
@@ -16409,7 +17209,8 @@ var condenseTranscript = async (messages, opts) => {
|
|
|
16409
17209
|
const deps = model ? {
|
|
16410
17210
|
model,
|
|
16411
17211
|
...opts?.apiKey !== void 0 ? { apiKey: opts.apiKey } : {},
|
|
16412
|
-
...opts?.signal !== void 0 ? { signal: opts.signal } : {}
|
|
17212
|
+
...opts?.signal !== void 0 ? { signal: opts.signal } : {},
|
|
17213
|
+
...opts?.instructions !== void 0 ? { instructions: opts.instructions } : {}
|
|
16413
17214
|
} : {};
|
|
16414
17215
|
const cleared = clearStaleToolResults(messages);
|
|
16415
17216
|
if (opts?.force) {
|
|
@@ -16449,7 +17250,7 @@ function resolveDefaultMode(store) {
|
|
|
16449
17250
|
const mode = tier.permissions?.defaultMode;
|
|
16450
17251
|
if (mode !== void 0 && isPermissionMode(mode)) return mode;
|
|
16451
17252
|
}
|
|
16452
|
-
return "
|
|
17253
|
+
return "acceptEdits";
|
|
16453
17254
|
}
|
|
16454
17255
|
function readOnlyNamesFromDeck(tools) {
|
|
16455
17256
|
const names = /* @__PURE__ */ new Set();
|
|
@@ -16536,7 +17337,10 @@ async function buildSessionConductor(ctx) {
|
|
|
16536
17337
|
basePath: typeof inv.sarvamBasePath === "string" ? inv.sarvamBasePath : typeof inv.flags?.["sarvam-base-path"] === "string" ? inv.flags["sarvam-base-path"] : void 0
|
|
16537
17338
|
})
|
|
16538
17339
|
];
|
|
16539
|
-
const tools =
|
|
17340
|
+
const tools = wrapToolsForTerminalBench(
|
|
17341
|
+
wrapToolsWithAddons(concatAddonTools(deck, addons), addons),
|
|
17342
|
+
cwd
|
|
17343
|
+
);
|
|
16540
17344
|
const skills = gatherModelSkills(cwd);
|
|
16541
17345
|
const system = composeSystem(tools, inv, cwd, skills, memoryDoc);
|
|
16542
17346
|
const thinking = resolveThinkingLevel(inv.thinking, modelId);
|
|
@@ -16885,7 +17689,7 @@ function isProgramEntry() {
|
|
|
16885
17689
|
const entryArg = processArgv[1];
|
|
16886
17690
|
if (!entryArg) return false;
|
|
16887
17691
|
try {
|
|
16888
|
-
return
|
|
17692
|
+
return realpathSync4(fileURLToPath2(import.meta.url)) === realpathSync4(entryArg);
|
|
16889
17693
|
} catch {
|
|
16890
17694
|
return false;
|
|
16891
17695
|
}
|