@integrity-labs/agt-cli 0.28.1101 → 0.28.1103
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/dist/bin/agt.js +5 -5
- package/dist/{chunk-U2CHXYDJ.js → chunk-FQPGSXUX.js} +2 -2
- package/dist/{chunk-3ZUCX5MN.js → chunk-HTK57ZUK.js} +401 -4
- package/dist/chunk-HTK57ZUK.js.map +1 -0
- package/dist/{chunk-NULQEO5H.js → chunk-NNCRFBTL.js} +1 -1
- package/dist/{chunk-NULQEO5H.js.map → chunk-NNCRFBTL.js.map} +1 -1
- package/dist/{claude-pair-runtime-OTQOPMBH.js → claude-pair-runtime-7K2E2HMM.js} +2 -2
- package/dist/lib/manager-worker.js +22 -16
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-RVYRYF6U.js → persistent-session-Q2HSRKRJ.js} +3 -3
- package/dist/{responsiveness-probe-OPCRQN27.js → responsiveness-probe-JC5WBBFG.js} +3 -3
- package/dist/{session-auth-dead-XOCRHVHW.js → session-auth-dead-MDHN6IVP.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-3ZUCX5MN.js.map +0 -1
- /package/dist/{chunk-U2CHXYDJ.js.map → chunk-FQPGSXUX.js.map} +0 -0
- /package/dist/{claude-pair-runtime-OTQOPMBH.js.map → claude-pair-runtime-7K2E2HMM.js.map} +0 -0
- /package/dist/{persistent-session-RVYRYF6U.js.map → persistent-session-Q2HSRKRJ.js.map} +0 -0
- /package/dist/{responsiveness-probe-OPCRQN27.js.map → responsiveness-probe-JC5WBBFG.js.map} +0 -0
- /package/dist/{session-auth-dead-XOCRHVHW.js.map → session-auth-dead-MDHN6IVP.js.map} +0 -0
package/dist/bin/agt.js
CHANGED
|
@@ -40,12 +40,12 @@ import {
|
|
|
40
40
|
success,
|
|
41
41
|
table,
|
|
42
42
|
warn
|
|
43
|
-
} from "../chunk-
|
|
43
|
+
} from "../chunk-HTK57ZUK.js";
|
|
44
44
|
import {
|
|
45
45
|
getProjectDir,
|
|
46
46
|
isSessionResumeDisabled,
|
|
47
47
|
readDirectChatSessionState
|
|
48
|
-
} from "../chunk-
|
|
48
|
+
} from "../chunk-FQPGSXUX.js";
|
|
49
49
|
import {
|
|
50
50
|
AnchorSessionClient,
|
|
51
51
|
CHANNEL_REGISTRY,
|
|
@@ -79,7 +79,7 @@ import {
|
|
|
79
79
|
serializeManifestForSlackCli,
|
|
80
80
|
sessionFileExists,
|
|
81
81
|
sessionTranscriptDir
|
|
82
|
-
} from "../chunk-
|
|
82
|
+
} from "../chunk-NNCRFBTL.js";
|
|
83
83
|
import "../chunk-OCMJ5E6J.js";
|
|
84
84
|
import "../chunk-XWVM4KPK.js";
|
|
85
85
|
import "../chunk-EL5MWGGH.js";
|
|
@@ -5474,7 +5474,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
5474
5474
|
import { existsSync as existsSync11, realpathSync as realpathSync2 } from "fs";
|
|
5475
5475
|
import chalk18 from "chalk";
|
|
5476
5476
|
import ora16 from "ora";
|
|
5477
|
-
var cliVersion = true ? "0.28.
|
|
5477
|
+
var cliVersion = true ? "0.28.1103" : "dev";
|
|
5478
5478
|
async function fetchLatestVersion() {
|
|
5479
5479
|
const host2 = getHost();
|
|
5480
5480
|
if (!host2) return null;
|
|
@@ -6734,7 +6734,7 @@ function handleError(err) {
|
|
|
6734
6734
|
}
|
|
6735
6735
|
|
|
6736
6736
|
// src/bin/agt.ts
|
|
6737
|
-
var cliVersion2 = true ? "0.28.
|
|
6737
|
+
var cliVersion2 = true ? "0.28.1103" : "dev";
|
|
6738
6738
|
var program = new Command();
|
|
6739
6739
|
program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
|
|
6740
6740
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
rotateDailySession,
|
|
25
25
|
sessionFileExists,
|
|
26
26
|
todayLocalIso
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-NNCRFBTL.js";
|
|
28
28
|
import {
|
|
29
29
|
classifyUnanswerablePane,
|
|
30
30
|
findUsageLimitResetHint,
|
|
@@ -6113,4 +6113,4 @@ export {
|
|
|
6113
6113
|
stopAllSessionsAndWait,
|
|
6114
6114
|
getProjectDir
|
|
6115
6115
|
};
|
|
6116
|
-
//# sourceMappingURL=chunk-
|
|
6116
|
+
//# sourceMappingURL=chunk-FQPGSXUX.js.map
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
parseEnvFileEntries,
|
|
17
17
|
parseEnvIntegrations,
|
|
18
18
|
shellQuote
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-FQPGSXUX.js";
|
|
20
20
|
import {
|
|
21
21
|
BIND_FAILURE_QUARANTINE_THRESHOLD,
|
|
22
22
|
INTEGRATIONS_SECTION_END,
|
|
@@ -79,7 +79,7 @@ import {
|
|
|
79
79
|
sessionTranscriptDir,
|
|
80
80
|
worseConnectivityOutcome,
|
|
81
81
|
wrapScheduledTaskPrompt
|
|
82
|
-
} from "./chunk-
|
|
82
|
+
} from "./chunk-NNCRFBTL.js";
|
|
83
83
|
import {
|
|
84
84
|
classifyUnanswerablePane,
|
|
85
85
|
isConsumerTermsDialogVisible,
|
|
@@ -4214,6 +4214,402 @@ exit 0
|
|
|
4214
4214
|
settings["hooks"] = hooks;
|
|
4215
4215
|
writeFileSync4(settingsPath, JSON.stringify(settings, null, 2));
|
|
4216
4216
|
}
|
|
4217
|
+
var LONG_COMMAND_BOUNDED_TIMEOUT_MS = 12e4;
|
|
4218
|
+
var LONG_COMMAND_HOOK_FILENAME = "agt-long-command-hook.sh";
|
|
4219
|
+
var LONG_COMMAND_HOOK_JS_FILENAME = "agt-long-command-hook.mjs";
|
|
4220
|
+
var LONG_COMMAND_HOOK_JS = String.raw`'use strict';
|
|
4221
|
+
// ENG-11393 long-command hook. Generated by provisionLongCommandHook; see index.ts.
|
|
4222
|
+
// Exit 2 + stderr refuses a foreground Bash call (Claude Code shows the reason);
|
|
4223
|
+
// exit 0 allows. Any internal error ALLOWS: a crashing guard must not block
|
|
4224
|
+
// every Bash call.
|
|
4225
|
+
const BOUND = __BOUND__;
|
|
4226
|
+
const SHELLS = new Set(['bash', 'sh', 'zsh', 'dash', 'ksh']);
|
|
4227
|
+
const TURBO_META = new Set(['login', 'logout', 'link', 'unlink', 'prune', 'daemon', 'telemetry', 'gen', 'generate', 'info', 'ls', 'query', 'bin', 'scan', 'completion', 'boundaries']);
|
|
4228
|
+
const PREFIX_CMDS = new Set(['sudo', 'nice', 'time', 'nohup', 'command', 'exec', 'stdbuf', 'ionice']);
|
|
4229
|
+
const KEYWORDS = new Set(['if', 'do', 'then', 'else', 'elif', '{', '!']);
|
|
4230
|
+
const FILE_RE = /\.(test|spec)\.[cm]?[jt]sx?(:\d+)?$/;
|
|
4231
|
+
|
|
4232
|
+
let raw = '';
|
|
4233
|
+
process.stdin.setEncoding('utf8');
|
|
4234
|
+
process.stdin.on('data', (d) => { raw += d; });
|
|
4235
|
+
process.stdin.on('end', () => {
|
|
4236
|
+
let code = 0;
|
|
4237
|
+
try { code = main(raw); } catch (e) { code = 0; }
|
|
4238
|
+
process.exit(code);
|
|
4239
|
+
});
|
|
4240
|
+
|
|
4241
|
+
function main(text) {
|
|
4242
|
+
let input;
|
|
4243
|
+
try { input = JSON.parse(text); } catch (e) { return 0; }
|
|
4244
|
+
if (!input || input.tool_name !== 'Bash') return 0;
|
|
4245
|
+
const ti = input.tool_input || {};
|
|
4246
|
+
if (ti.run_in_background === true) return 0;
|
|
4247
|
+
const t = Number(ti.timeout);
|
|
4248
|
+
if (ti.timeout !== undefined && ti.timeout !== null && Number.isFinite(t) && t <= BOUND) return 0;
|
|
4249
|
+
const cmd = typeof ti.command === 'string' ? ti.command : '';
|
|
4250
|
+
if (!cmd) return 0;
|
|
4251
|
+
const reason = classify(cmd, 0);
|
|
4252
|
+
if (!reason) return 0;
|
|
4253
|
+
process.stderr.write('agt-long-command-hook: this looks like ' + reason + ', which can block you for minutes, and you cannot answer anyone while a foreground command runs. Re-run this exact command with the Bash tool parameter run_in_background: true. You are notified when it finishes, and you stay responsive meanwhile. Do NOT use a trailing & or nohup instead: that detaches it with no completion notification. If you are sure it is quick, pass an explicit timeout of ' + BOUND + ' ms or less.\n');
|
|
4254
|
+
return 2;
|
|
4255
|
+
}
|
|
4256
|
+
|
|
4257
|
+
// 1. Heredocs. A body is DATA unless the command that READS it is a shell
|
|
4258
|
+
// (Obi Wan 6159f6f97145 on #6845): each unquoted << operator is tied to the
|
|
4259
|
+
// command word of its own segment, not to the first word of the line, and a
|
|
4260
|
+
// "<<WORD" inside quotes opens nothing. A body piped into a shell
|
|
4261
|
+
// ("cat <<EOF | bash") is executed too (Obi Wan bf1bec45130a): every heredoc
|
|
4262
|
+
// in a pipeline becomes exec when a later stage of that pipeline is a shell.
|
|
4263
|
+
// The command word that reads a segment's stdin: shell keywords ("if", "do",
|
|
4264
|
+
// "!", ...) and prefixes (sudo, env, timeout) are stripped first, exactly as
|
|
4265
|
+
// classify does (Obi Wan 7a32094bc1df).
|
|
4266
|
+
function readerOf(seg) {
|
|
4267
|
+
let w = seg;
|
|
4268
|
+
while (w.length && KEYWORDS.has(w[0])) w = w.slice(1);
|
|
4269
|
+
return skipPrefixes(w)[0] || '';
|
|
4270
|
+
}
|
|
4271
|
+
|
|
4272
|
+
function heredocOps(line) {
|
|
4273
|
+
const ops = [];
|
|
4274
|
+
let q = null;
|
|
4275
|
+
let seg = [];
|
|
4276
|
+
let word = '';
|
|
4277
|
+
let pipeline = [];
|
|
4278
|
+
let piped = false;
|
|
4279
|
+
// Command substitutions opened INSIDE double quotes ("$(cat <<'EOF' ...").
|
|
4280
|
+
// In bash a quote inside $(...) does not close the outer one, and the heredoc
|
|
4281
|
+
// inside it is a real heredoc (Obi Wan 17d273c999ef: the usual shape of a
|
|
4282
|
+
// commit or PR body). Each entry saves the ENCLOSING segment and pipeline,
|
|
4283
|
+
// restored when the $( closes (CodeRabbit on #6845: in
|
|
4284
|
+
// cat <<EOF | sed "$(...)" | bash the substitution must not end the outer
|
|
4285
|
+
// pipeline, or the heredoc piped into bash reads as data), plus the
|
|
4286
|
+
// open-paren depth inside that $( .
|
|
4287
|
+
const subst = [];
|
|
4288
|
+
const endWord = () => { if (word) { seg.push(word); word = ''; } };
|
|
4289
|
+
const endSeg = (pipe) => {
|
|
4290
|
+
endWord();
|
|
4291
|
+
if (piped && SHELLS.has(base(readerOf(seg)))) for (const op of pipeline) op.exec = true;
|
|
4292
|
+
seg = [];
|
|
4293
|
+
piped = pipe;
|
|
4294
|
+
if (!pipe) pipeline = [];
|
|
4295
|
+
};
|
|
4296
|
+
for (let i = 0; i < line.length; i++) {
|
|
4297
|
+
const c = line[i];
|
|
4298
|
+
if (q === "'") { if (c === "'") q = null; else word += c; continue; }
|
|
4299
|
+
if (q === '"') {
|
|
4300
|
+
if (c === '\\' && i + 1 < line.length) { word += line[++i]; continue; }
|
|
4301
|
+
if (c === '$' && line[i + 1] === '(') {
|
|
4302
|
+
subst.push({ depth: 0, seg, word, pipeline, piped, q: '"' });
|
|
4303
|
+
seg = []; word = ''; pipeline = []; piped = false; q = null; i++;
|
|
4304
|
+
continue;
|
|
4305
|
+
}
|
|
4306
|
+
if (c === '"') q = null; else word += c;
|
|
4307
|
+
continue;
|
|
4308
|
+
}
|
|
4309
|
+
if (c === '\\' && i + 1 < line.length) { word += line[++i]; continue; }
|
|
4310
|
+
if (c === "'" || c === '"') { q = c; continue; }
|
|
4311
|
+
// An UNQUOTED $( keeps the enclosing pipeline too (CodeRabbit on #6845:
|
|
4312
|
+
// cat <<EOF | sed $(...) | bash), and returns to unquoted text on its ).
|
|
4313
|
+
if (c === '$' && line[i + 1] === '(') {
|
|
4314
|
+
subst.push({ depth: 0, seg, word, pipeline, piped, q: null });
|
|
4315
|
+
seg = []; word = ''; pipeline = []; piped = false; i++;
|
|
4316
|
+
continue;
|
|
4317
|
+
}
|
|
4318
|
+
if (subst.length && c === '(') { subst[subst.length - 1].depth++; endSeg(false); continue; }
|
|
4319
|
+
if (subst.length && c === ')') {
|
|
4320
|
+
endSeg(false);
|
|
4321
|
+
const top = subst[subst.length - 1];
|
|
4322
|
+
if (top.depth > 0) { top.depth--; continue; }
|
|
4323
|
+
subst.pop();
|
|
4324
|
+
// Back in the enclosing word, in the quote state it was opened from.
|
|
4325
|
+
seg = top.seg; word = top.word + '$()'; pipeline = top.pipeline; piped = top.piped; q = top.q;
|
|
4326
|
+
continue;
|
|
4327
|
+
}
|
|
4328
|
+
if (c === '<' && line[i + 1] === '<' && line[i + 2] !== '<' && line[i - 1] !== '<') {
|
|
4329
|
+
endWord();
|
|
4330
|
+
let j = i + 2;
|
|
4331
|
+
let dash = false;
|
|
4332
|
+
if (line[j] === '-') { dash = true; j++; }
|
|
4333
|
+
while (line[j] === ' ' || line[j] === '\t') j++;
|
|
4334
|
+
let qc = '';
|
|
4335
|
+
if (line[j] === "'" || line[j] === '"') { qc = line[j]; j++; }
|
|
4336
|
+
const m = /^[A-Za-z_][A-Za-z0-9_]*/.exec(line.slice(j));
|
|
4337
|
+
if (m) {
|
|
4338
|
+
j += m[0].length;
|
|
4339
|
+
if (qc && line[j] === qc) j++;
|
|
4340
|
+
const op = { word: m[0], dash, exec: SHELLS.has(base(readerOf(seg))) };
|
|
4341
|
+
ops.push(op);
|
|
4342
|
+
pipeline.push(op);
|
|
4343
|
+
i = j - 1;
|
|
4344
|
+
continue;
|
|
4345
|
+
}
|
|
4346
|
+
}
|
|
4347
|
+
if (c === '|') {
|
|
4348
|
+
if (line[i + 1] === '|') { i++; endSeg(false); continue; }
|
|
4349
|
+
if (line[i + 1] === '&') i++;
|
|
4350
|
+
endSeg(true);
|
|
4351
|
+
continue;
|
|
4352
|
+
}
|
|
4353
|
+
if (c === ';' || c === '&' || c === '(' || c === ')') { endSeg(false); continue; }
|
|
4354
|
+
if (c === ' ' || c === '\t') { endWord(); continue; }
|
|
4355
|
+
word += c;
|
|
4356
|
+
}
|
|
4357
|
+
endSeg(false);
|
|
4358
|
+
return ops;
|
|
4359
|
+
}
|
|
4360
|
+
|
|
4361
|
+
function splitHeredocs(cmd) {
|
|
4362
|
+
const lines = cmd.split('\n');
|
|
4363
|
+
const kept = [];
|
|
4364
|
+
const execBodies = [];
|
|
4365
|
+
let pending = [];
|
|
4366
|
+
let body = [];
|
|
4367
|
+
for (const line of lines) {
|
|
4368
|
+
if (pending.length > 0) {
|
|
4369
|
+
const cur = pending[0];
|
|
4370
|
+
const cmp = cur.dash ? line.replace(/^\t+/, '') : line;
|
|
4371
|
+
if (cmp === cur.word) {
|
|
4372
|
+
if (cur.exec) execBodies.push(body.join('\n'));
|
|
4373
|
+
body = [];
|
|
4374
|
+
pending.shift();
|
|
4375
|
+
} else {
|
|
4376
|
+
body.push(line);
|
|
4377
|
+
}
|
|
4378
|
+
continue;
|
|
4379
|
+
}
|
|
4380
|
+
kept.push(line);
|
|
4381
|
+
for (const op of heredocOps(line)) pending.push(op);
|
|
4382
|
+
}
|
|
4383
|
+
return { text: kept.join('\n'), execBodies };
|
|
4384
|
+
}
|
|
4385
|
+
|
|
4386
|
+
// 2. Segments: split on ; & | && || newline ( ) respecting quotes and escapes.
|
|
4387
|
+
function tokenize(text) {
|
|
4388
|
+
const segs = [];
|
|
4389
|
+
let words = [];
|
|
4390
|
+
let word = '';
|
|
4391
|
+
let inWord = false;
|
|
4392
|
+
let q = null;
|
|
4393
|
+
const endWord = () => { if (inWord) { words.push(word); word = ''; inWord = false; } };
|
|
4394
|
+
const endSeg = () => { endWord(); if (words.length) segs.push(words); words = []; };
|
|
4395
|
+
for (let i = 0; i < text.length; i++) {
|
|
4396
|
+
const c = text[i];
|
|
4397
|
+
if (q === "'") { if (c === "'") q = null; else word += c; continue; }
|
|
4398
|
+
if (q === '"') {
|
|
4399
|
+
if (c === '\\' && i + 1 < text.length) { word += text[++i]; continue; }
|
|
4400
|
+
if (c === '"') q = null; else word += c;
|
|
4401
|
+
continue;
|
|
4402
|
+
}
|
|
4403
|
+
if (c === '\\' && i + 1 < text.length) { if (text[i + 1] !== '\n') { word += text[i + 1]; inWord = true; } i++; continue; }
|
|
4404
|
+
if (c === "'" || c === '"') { q = c; inWord = true; continue; }
|
|
4405
|
+
if (c === '#' && !inWord) { while (i < text.length && text[i] !== '\n') i++; endSeg(); continue; }
|
|
4406
|
+
if (c === ';' || c === '&' || c === '|' || c === '\n' || c === '(' || c === ')') { endSeg(); continue; }
|
|
4407
|
+
if (c === ' ' || c === '\t') { endWord(); continue; }
|
|
4408
|
+
word += c; inWord = true;
|
|
4409
|
+
}
|
|
4410
|
+
endSeg();
|
|
4411
|
+
return segs;
|
|
4412
|
+
}
|
|
4413
|
+
|
|
4414
|
+
function base(w) { return String(w).split('/').pop(); }
|
|
4415
|
+
|
|
4416
|
+
// 3. Classify.
|
|
4417
|
+
function classify(cmd, depth) {
|
|
4418
|
+
if (depth > 4) return null;
|
|
4419
|
+
const { text, execBodies } = splitHeredocs(cmd);
|
|
4420
|
+
for (const b of execBodies) { const r = classify(b, depth + 1); if (r) return r; }
|
|
4421
|
+
let loop = 0;
|
|
4422
|
+
for (let words of tokenize(text)) {
|
|
4423
|
+
while (words.length && KEYWORDS.has(words[0])) words = words.slice(1);
|
|
4424
|
+
if (!words.length) continue;
|
|
4425
|
+
const head = words[0];
|
|
4426
|
+
if (head === 'for' || head === 'while' || head === 'until' || head === 'select') {
|
|
4427
|
+
loop++;
|
|
4428
|
+
if (head === 'for' || head === 'select') continue; // the rest is a word list, not a command
|
|
4429
|
+
words = words.slice(1);
|
|
4430
|
+
if (!words.length) continue;
|
|
4431
|
+
} else if (head === 'done') {
|
|
4432
|
+
if (loop > 0) loop--;
|
|
4433
|
+
continue;
|
|
4434
|
+
}
|
|
4435
|
+
const r = classifyCommand(words, loop, depth);
|
|
4436
|
+
if (r) return r;
|
|
4437
|
+
}
|
|
4438
|
+
return null;
|
|
4439
|
+
}
|
|
4440
|
+
|
|
4441
|
+
function skipPrefixes(words) {
|
|
4442
|
+
let w = words.slice();
|
|
4443
|
+
for (let guard = 0; guard < 20 && w.length; guard++) {
|
|
4444
|
+
const h = base(w[0]);
|
|
4445
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(w[0])) { w = w.slice(1); continue; }
|
|
4446
|
+
if (h === 'env') {
|
|
4447
|
+
// CodeRabbit on #6845: GNU env's -u/--unset NAME and -C/--chdir DIR take
|
|
4448
|
+
// a SEPARATE operand, which is not the command. The joined forms
|
|
4449
|
+
// (-uNAME, --unset=NAME, -CDIR, --chdir=DIR) carry their own; "--" ends
|
|
4450
|
+
// the options.
|
|
4451
|
+
w = w.slice(1);
|
|
4452
|
+
while (w.length) {
|
|
4453
|
+
if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(w[0])) { w = w.slice(1); continue; }
|
|
4454
|
+
const f = w[0];
|
|
4455
|
+
if (!f.startsWith('-')) break;
|
|
4456
|
+
w = w.slice(1);
|
|
4457
|
+
if (f === '--') break;
|
|
4458
|
+
if ((f === '-u' || f === '--unset' || f === '-C' || f === '--chdir') && w.length) w = w.slice(1);
|
|
4459
|
+
}
|
|
4460
|
+
continue;
|
|
4461
|
+
}
|
|
4462
|
+
if (h === 'timeout') { w = w.slice(1); while (w.length && w[0].startsWith('-')) { const f = w[0]; w = w.slice(1); if ((f === '-s' || f === '-k' || f === '--signal' || f === '--kill-after') && w.length) w = w.slice(1); } if (w.length && /^[0-9.]+[smhd]?$/.test(w[0])) w = w.slice(1); continue; }
|
|
4463
|
+
// "command -v X" / "command -V X" only LOOKS X up (Obi Wan e9e75aab20fb).
|
|
4464
|
+
if (h === 'command' && (w[1] === '-v' || w[1] === '-V')) return [];
|
|
4465
|
+
if (PREFIX_CMDS.has(h)) { w = w.slice(1); while (w.length && w[0].startsWith('-')) { const f = w[0]; w = w.slice(1); if (h === 'nice' && f === '-n' && w.length) w = w.slice(1); } continue; }
|
|
4466
|
+
break;
|
|
4467
|
+
}
|
|
4468
|
+
return w;
|
|
4469
|
+
}
|
|
4470
|
+
|
|
4471
|
+
// GNU sleep also takes "inf"/"infinity" and float notation (1e3). Anything
|
|
4472
|
+
// it would accept that we cannot read is treated as unbounded rather than as
|
|
4473
|
+
// zero (Obi Wan 4d961cccc4ba); flags are ignored.
|
|
4474
|
+
function sleepSeconds(arg) {
|
|
4475
|
+
if (!arg || arg.startsWith('-')) return null;
|
|
4476
|
+
if (/^inf(inity)?[smhd]?$/i.test(arg)) return Infinity;
|
|
4477
|
+
const m = /^((?:[0-9]+\.?[0-9]*|\.[0-9]+)(?:[eE][+-]?[0-9]+)?)([smhd]?)$/.exec(arg);
|
|
4478
|
+
if (!m) return Infinity;
|
|
4479
|
+
const n = Number(m[1]);
|
|
4480
|
+
return Number.isFinite(n) ? n * ({ '': 1, s: 1, m: 60, h: 3600, d: 86400 })[m[2]] : Infinity;
|
|
4481
|
+
}
|
|
4482
|
+
|
|
4483
|
+
function hasFileTarget(args) { return args.some((a) => FILE_RE.test(a)); }
|
|
4484
|
+
|
|
4485
|
+
function classifyCommand(words0, loop, depth) {
|
|
4486
|
+
let words = skipPrefixes(words0);
|
|
4487
|
+
if (!words.length) return null;
|
|
4488
|
+
let cw = base(words[0]);
|
|
4489
|
+
let args = words.slice(1);
|
|
4490
|
+
|
|
4491
|
+
// A shell given a command string: judge the string (bash -lc 'pnpm install').
|
|
4492
|
+
if (SHELLS.has(cw)) {
|
|
4493
|
+
const i = args.findIndex((a) => /^-[A-Za-z]*c[A-Za-z]*$/.test(a));
|
|
4494
|
+
if (i >= 0 && i + 1 < args.length) return classify(args[i + 1], depth + 1);
|
|
4495
|
+
return null;
|
|
4496
|
+
}
|
|
4497
|
+
if (cw === 'eval') return classify(args.join(' '), depth + 1);
|
|
4498
|
+
|
|
4499
|
+
// Runners that put the real command after them.
|
|
4500
|
+
if (cw === 'npx' || cw === 'bunx' || cw === 'corepack') {
|
|
4501
|
+
while (args.length && args[0].startsWith('-')) args = args.slice(1);
|
|
4502
|
+
if (!args.length) return null;
|
|
4503
|
+
return classifyCommand(args, loop, depth);
|
|
4504
|
+
}
|
|
4505
|
+
|
|
4506
|
+
if (cw === 'vitest' || cw === 'jest') {
|
|
4507
|
+
if (args.some((a) => a === '--version' || a === '-v' || a === '--help' || a === '-h')) return null;
|
|
4508
|
+
return hasFileTarget(args) ? null : 'a whole test suite';
|
|
4509
|
+
}
|
|
4510
|
+
|
|
4511
|
+
if (cw === 'pnpm' || cw === 'npm' || cw === 'yarn' || cw === 'bun') {
|
|
4512
|
+
let recursive = false;
|
|
4513
|
+
let firstAt = -1;
|
|
4514
|
+
const rest = [];
|
|
4515
|
+
for (let i = 0; i < args.length; i++) {
|
|
4516
|
+
const a = args[i];
|
|
4517
|
+
if (a === '-r' || a === '--recursive' || a === '--workspaces' || a === '-ws') { recursive = true; continue; }
|
|
4518
|
+
if (a === '--filter' || a === '-F' || a === '-C' || a === '--dir' || a === '--prefix' || a === '-w' && cw === 'npm' || a === '--workspace') { i++; continue; }
|
|
4519
|
+
if (a.startsWith('-')) continue;
|
|
4520
|
+
if (!rest.length) firstAt = i;
|
|
4521
|
+
rest.push(a);
|
|
4522
|
+
}
|
|
4523
|
+
let sub = rest[0];
|
|
4524
|
+
// "yarn --version" / "pnpm -v" / "npm --help": a quick lookup, not a bare
|
|
4525
|
+
// "yarn" install (Obi Wan e9e75aab20fb; the loop above dropped the flag).
|
|
4526
|
+
if (sub === undefined) {
|
|
4527
|
+
if (args.some((a) => a === '--version' || a === '-v' || a === '--help' || a === '-h')) return null;
|
|
4528
|
+
return cw === 'yarn' ? 'a dependency install' : null;
|
|
4529
|
+
}
|
|
4530
|
+
if ((sub === 'exec' || sub === 'dlx' || sub === 'x') && rest.length > 1) return classifyCommand(args.slice(args.indexOf(rest[1], firstAt + 1)), loop, depth);
|
|
4531
|
+
const viaRun = sub === 'run' || sub === 'run-script';
|
|
4532
|
+
if (viaRun) sub = rest[1] === undefined ? 'run' : rest[1];
|
|
4533
|
+
// A file after a package "test" SCRIPT does not narrow the run unless the
|
|
4534
|
+
// script forwards its args, and this repo's root one does not (it runs the
|
|
4535
|
+
// whole turbo suite). Only a direct runner (vitest/jest, exec/dlx, a
|
|
4536
|
+
// workspace bin) earns the single-file exemption (Obi Wan f471dc98a67b).
|
|
4537
|
+
if (sub === 'test' || sub === 't') return 'a whole test suite';
|
|
4538
|
+
if (sub === 'install' || sub === 'i' || sub === 'ci' || sub === 'add') return 'a dependency install';
|
|
4539
|
+
if (sub === 'vitest' || sub === 'jest') return hasFileTarget(rest.slice(1)) ? null : 'a whole test suite';
|
|
4540
|
+
// Obi Wan 444c7455aaad: in a turbo monorepo a root "pnpm build" /
|
|
4541
|
+
// "pnpm typecheck" is a workspace-wide build. A quick one in a single
|
|
4542
|
+
// package passes with an explicit short timeout.
|
|
4543
|
+
if (sub === 'build' || sub === 'typecheck' || sub === 'type-check') return 'a workspace-wide build or typecheck';
|
|
4544
|
+
if (recursive) return 'a workspace-wide build or typecheck';
|
|
4545
|
+
// Obi Wan c0646feacb29: "pnpm turbo test", "yarn tsc -b", "pnpm nx run-many"
|
|
4546
|
+
// run a workspace binary, so judge the binary as if it were run directly.
|
|
4547
|
+
// Its own flags must survive (rest drops them): re-read from the original args.
|
|
4548
|
+
if (!viaRun) return classifyCommand(args.slice(firstAt), loop, depth);
|
|
4549
|
+
return null;
|
|
4550
|
+
}
|
|
4551
|
+
|
|
4552
|
+
if (cw === 'tsc') return args.some((a) => a === '-b' || a === '--build') ? 'a workspace-wide build or typecheck' : null;
|
|
4553
|
+
if (cw === 'turbo') {
|
|
4554
|
+
// "turbo build" runs a task exactly like "turbo run build" (Obi Wan 444c7455aaad).
|
|
4555
|
+
const first = args.find((a) => !a.startsWith('-'));
|
|
4556
|
+
if (first === undefined || TURBO_META.has(first)) return null;
|
|
4557
|
+
return 'a workspace-wide build or typecheck';
|
|
4558
|
+
}
|
|
4559
|
+
if (cw === 'nx') return args.includes('run-many') ? 'a workspace-wide build or typecheck' : null;
|
|
4560
|
+
|
|
4561
|
+
if (cw === 'gh') {
|
|
4562
|
+
if (args[0] === 'run' && args[1] === 'watch') return 'a watch or poll loop';
|
|
4563
|
+
if (args[0] === 'pr' && args[1] === 'checks' && args.includes('--watch')) return 'a watch or poll loop';
|
|
4564
|
+
return null;
|
|
4565
|
+
}
|
|
4566
|
+
if (cw === 'watch') return 'a watch or poll loop';
|
|
4567
|
+
if (cw === 'tail' && args.some((a) => a === '-f' || a === '-F' || a === '--follow' || /^-[A-Za-z]*[fF]$/.test(a))) return 'a watch or poll loop';
|
|
4568
|
+
if (cw === 'inotifywait' && args.some((a) => a === '-m' || a === '--monitor')) return 'a watch or poll loop';
|
|
4569
|
+
|
|
4570
|
+
if (cw === 'sleep') {
|
|
4571
|
+
if (loop > 0) return 'a watch or poll loop';
|
|
4572
|
+
const s = args.reduce((acc, a) => { const v = sleepSeconds(a); return v === null ? acc : acc + v; }, 0);
|
|
4573
|
+
return s >= 30 ? 'a watch or poll loop' : null;
|
|
4574
|
+
}
|
|
4575
|
+
return null;
|
|
4576
|
+
}
|
|
4577
|
+
`;
|
|
4578
|
+
var LONG_COMMAND_MAX_FOREGROUND_TIMEOUT_MS = 18e4;
|
|
4579
|
+
function provisionLongCommandHook(codeName) {
|
|
4580
|
+
const projectDir = getProjectDir2(codeName);
|
|
4581
|
+
const claudeDir = join4(projectDir, ".claude");
|
|
4582
|
+
mkdirSync3(claudeDir, { recursive: true });
|
|
4583
|
+
const hookScriptPath = join4(claudeDir, LONG_COMMAND_HOOK_FILENAME);
|
|
4584
|
+
const jsPath = join4(claudeDir, LONG_COMMAND_HOOK_JS_FILENAME);
|
|
4585
|
+
writeFileSync4(jsPath, LONG_COMMAND_HOOK_JS.replace("__BOUND__", String(LONG_COMMAND_BOUNDED_TIMEOUT_MS)), { mode: 420 });
|
|
4586
|
+
const hookScript = [
|
|
4587
|
+
"#!/usr/bin/env bash",
|
|
4588
|
+
"# ENG-11393: refuse known-slow foreground shell commands; see index.ts.",
|
|
4589
|
+
"# Fail open: no node, or any error in the matcher, allows the call.",
|
|
4590
|
+
"command -v node >/dev/null 2>&1 || exit 0",
|
|
4591
|
+
`exec node '${jsPath.replace(/'/g, `'\\''`)}'`
|
|
4592
|
+
].join("\n") + "\n";
|
|
4593
|
+
writeFileSync4(hookScriptPath, hookScript, { mode: 493 });
|
|
4594
|
+
const settingsPath = join4(claudeDir, "settings.local.json");
|
|
4595
|
+
let settings = {};
|
|
4596
|
+
try {
|
|
4597
|
+
settings = JSON.parse(readFileSync4(settingsPath, "utf-8"));
|
|
4598
|
+
} catch {
|
|
4599
|
+
}
|
|
4600
|
+
const hooks = settings["hooks"] ?? {};
|
|
4601
|
+
const groups = Array.isArray(hooks["PreToolUse"]) ? hooks["PreToolUse"] : [];
|
|
4602
|
+
const already = groups.some((g) => (g.hooks ?? []).some((h) => h.command === hookScriptPath));
|
|
4603
|
+
if (!already) {
|
|
4604
|
+
groups.push({ matcher: "Bash", hooks: [{ type: "command", command: hookScriptPath }] });
|
|
4605
|
+
}
|
|
4606
|
+
hooks["PreToolUse"] = groups;
|
|
4607
|
+
settings["hooks"] = hooks;
|
|
4608
|
+
const env = settings["env"] ?? {};
|
|
4609
|
+
env["BASH_MAX_TIMEOUT_MS"] = String(LONG_COMMAND_MAX_FOREGROUND_TIMEOUT_MS);
|
|
4610
|
+
settings["env"] = env;
|
|
4611
|
+
writeFileSync4(settingsPath, JSON.stringify(settings, null, 2));
|
|
4612
|
+
}
|
|
4217
4613
|
function provisionOrientHook(codeName) {
|
|
4218
4614
|
const projectDir = getProjectDir2(codeName);
|
|
4219
4615
|
const claudeDir = join4(projectDir, ".claude");
|
|
@@ -7122,7 +7518,7 @@ function exchangeFailureKind(err) {
|
|
|
7122
7518
|
}
|
|
7123
7519
|
|
|
7124
7520
|
// src/lib/api-client.ts
|
|
7125
|
-
var agtCliVersion = true ? "0.28.
|
|
7521
|
+
var agtCliVersion = true ? "0.28.1103" : "dev";
|
|
7126
7522
|
var lastConfigHash = null;
|
|
7127
7523
|
function setConfigHash(hash) {
|
|
7128
7524
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -12008,6 +12404,7 @@ export {
|
|
|
12008
12404
|
provisionIsolationHook,
|
|
12009
12405
|
provisionAutoKanbanProgressHook,
|
|
12010
12406
|
provisionChannelProgressHook,
|
|
12407
|
+
provisionLongCommandHook,
|
|
12011
12408
|
provisionOrientHook,
|
|
12012
12409
|
provisionPreCompactHook,
|
|
12013
12410
|
provisionSessionStateHook,
|
|
@@ -12095,4 +12492,4 @@ export {
|
|
|
12095
12492
|
managerInstallSystemUnitCommand,
|
|
12096
12493
|
managerUninstallSystemUnitCommand
|
|
12097
12494
|
};
|
|
12098
|
-
//# sourceMappingURL=chunk-
|
|
12495
|
+
//# sourceMappingURL=chunk-HTK57ZUK.js.map
|