@integrity-labs/agt-cli 0.27.65 → 0.27.67
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 +186 -15
- package/dist/bin/agt.js.map +1 -1
- package/dist/{chunk-CF3SEPE3.js → chunk-DA3KY3D2.js} +107 -23
- package/dist/chunk-DA3KY3D2.js.map +1 -0
- package/dist/{chunk-UMFTYZO7.js → chunk-EYWW624B.js} +250 -163
- package/dist/chunk-EYWW624B.js.map +1 -0
- package/dist/{chunk-PM3CC2SJ.js → chunk-KPD5KJY7.js} +80 -1
- package/dist/chunk-KPD5KJY7.js.map +1 -0
- package/dist/{claude-pair-runtime-R7PGK4LT.js → claude-pair-runtime-6GSA5KRH.js} +2 -2
- package/dist/lib/manager-worker.js +30 -9
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-BN3PGV3A.js → persistent-session-2WJIWIMQ.js} +3 -3
- package/dist/{responsiveness-probe-QR6VWUKX.js → responsiveness-probe-RAWYP7LQ.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-CF3SEPE3.js.map +0 -1
- package/dist/chunk-PM3CC2SJ.js.map +0 -1
- package/dist/chunk-UMFTYZO7.js.map +0 -1
- /package/dist/{claude-pair-runtime-R7PGK4LT.js.map → claude-pair-runtime-6GSA5KRH.js.map} +0 -0
- /package/dist/{persistent-session-BN3PGV3A.js.map → persistent-session-2WJIWIMQ.js.map} +0 -0
- /package/dist/{responsiveness-probe-QR6VWUKX.js.map → responsiveness-probe-RAWYP7LQ.js.map} +0 -0
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
parseDeliveryTarget,
|
|
10
10
|
registerFramework,
|
|
11
11
|
wrapScheduledTaskPrompt
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KPD5KJY7.js";
|
|
13
13
|
|
|
14
14
|
// ../../packages/core/dist/integrations/registry.js
|
|
15
15
|
var INTEGRATION_REGISTRY = [
|
|
@@ -2356,6 +2356,212 @@ function extractAllowedDomains(input) {
|
|
|
2356
2356
|
}
|
|
2357
2357
|
registerFramework(nemoClawAdapter);
|
|
2358
2358
|
|
|
2359
|
+
// ../../packages/core/dist/provisioning/mcp-config-guards.js
|
|
2360
|
+
import { chmodSync as chmodSync4, existsSync as existsSync4, readFileSync as readFileSync4, renameSync as renameSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
2361
|
+
var MCP_FILE_MODE = 384;
|
|
2362
|
+
var REQUIRED_ENV_RULES_BY_SERVER = {
|
|
2363
|
+
"cloud-broker": [
|
|
2364
|
+
{ key: "AGT_HOST", mustBeConcrete: false },
|
|
2365
|
+
{ key: "AGT_API_KEY", mustBeConcrete: false },
|
|
2366
|
+
// ENG-4744: this is the bug shape — writer used to omit this
|
|
2367
|
+
// entirely, or render it as a literal `${AGT_AGENT_ID}` instead
|
|
2368
|
+
// of the agent's real UUID. The broker has no way to substitute
|
|
2369
|
+
// it post-spawn, so a placeholder here = silently broken agent.
|
|
2370
|
+
{ key: "AGT_AGENT_ID", mustBeConcrete: true }
|
|
2371
|
+
]
|
|
2372
|
+
};
|
|
2373
|
+
var PLACEHOLDER_RE = /\$\{[^}]+\}/;
|
|
2374
|
+
function validateRenderedMcpConfig(config) {
|
|
2375
|
+
const errors = [];
|
|
2376
|
+
if (typeof config !== "object" || config === null || Array.isArray(config)) {
|
|
2377
|
+
return {
|
|
2378
|
+
ok: false,
|
|
2379
|
+
errors: [
|
|
2380
|
+
{
|
|
2381
|
+
kind: "invalid_json_shape",
|
|
2382
|
+
server: "*",
|
|
2383
|
+
message: "config root must be a non-null object"
|
|
2384
|
+
}
|
|
2385
|
+
]
|
|
2386
|
+
};
|
|
2387
|
+
}
|
|
2388
|
+
const root = config;
|
|
2389
|
+
if (root.mcpServers === void 0) {
|
|
2390
|
+
return { ok: true };
|
|
2391
|
+
}
|
|
2392
|
+
if (typeof root.mcpServers !== "object" || root.mcpServers === null) {
|
|
2393
|
+
return {
|
|
2394
|
+
ok: false,
|
|
2395
|
+
errors: [
|
|
2396
|
+
{
|
|
2397
|
+
kind: "invalid_json_shape",
|
|
2398
|
+
server: "*",
|
|
2399
|
+
message: "mcpServers must be an object"
|
|
2400
|
+
}
|
|
2401
|
+
]
|
|
2402
|
+
};
|
|
2403
|
+
}
|
|
2404
|
+
if (Array.isArray(root.mcpServers)) {
|
|
2405
|
+
return {
|
|
2406
|
+
ok: false,
|
|
2407
|
+
errors: [
|
|
2408
|
+
{
|
|
2409
|
+
kind: "invalid_json_shape",
|
|
2410
|
+
server: "*",
|
|
2411
|
+
message: "mcpServers must be an object"
|
|
2412
|
+
}
|
|
2413
|
+
]
|
|
2414
|
+
};
|
|
2415
|
+
}
|
|
2416
|
+
for (const [serverKey, raw] of Object.entries(root.mcpServers)) {
|
|
2417
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
2418
|
+
errors.push({
|
|
2419
|
+
kind: "invalid_json_shape",
|
|
2420
|
+
server: serverKey,
|
|
2421
|
+
message: `entry must be an object`
|
|
2422
|
+
});
|
|
2423
|
+
continue;
|
|
2424
|
+
}
|
|
2425
|
+
const entry = raw;
|
|
2426
|
+
const entryRecord = entry;
|
|
2427
|
+
if (typeof entryRecord["url"] === "string") {
|
|
2428
|
+
const type = entryRecord["type"];
|
|
2429
|
+
if (type !== "http" && type !== "sse") {
|
|
2430
|
+
errors.push({
|
|
2431
|
+
kind: "remote_mcp_missing_type",
|
|
2432
|
+
server: serverKey,
|
|
2433
|
+
message: `url-based entry must include \`type: "http"\` or \`type: "sse"\` (Claude Code MCP schema requires it)`
|
|
2434
|
+
});
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
const rules = REQUIRED_ENV_RULES_BY_SERVER[serverKey];
|
|
2438
|
+
if (rules) {
|
|
2439
|
+
const env = entry.env ?? {};
|
|
2440
|
+
for (const rule of rules) {
|
|
2441
|
+
const value = env[rule.key];
|
|
2442
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
2443
|
+
errors.push({
|
|
2444
|
+
kind: "missing_required_env",
|
|
2445
|
+
server: serverKey,
|
|
2446
|
+
message: `missing required env key: ${rule.key}`
|
|
2447
|
+
});
|
|
2448
|
+
continue;
|
|
2449
|
+
}
|
|
2450
|
+
if (rule.mustBeConcrete && PLACEHOLDER_RE.test(value)) {
|
|
2451
|
+
errors.push({
|
|
2452
|
+
kind: "unexpanded_placeholder",
|
|
2453
|
+
server: serverKey,
|
|
2454
|
+
message: `env.${rule.key} contains an unexpanded \${...} placeholder; expected a concrete value`
|
|
2455
|
+
});
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
return errors.length === 0 ? { ok: true } : { ok: false, errors };
|
|
2461
|
+
}
|
|
2462
|
+
function formatValidationErrors(errors) {
|
|
2463
|
+
return errors.map((e) => `${e.server}:${e.kind}=${e.message}`).join("; ");
|
|
2464
|
+
}
|
|
2465
|
+
function safeWriteJsonAtomic(path, content, opts = {}) {
|
|
2466
|
+
const keepBackup = opts.keepBackup !== false;
|
|
2467
|
+
const rename = opts.renamer ?? renameSync3;
|
|
2468
|
+
const tmpPath = `${path}.new`;
|
|
2469
|
+
const bakPath = `${path}.bak`;
|
|
2470
|
+
let movedOriginalToBackup = false;
|
|
2471
|
+
try {
|
|
2472
|
+
writeFileSync4(tmpPath, content);
|
|
2473
|
+
if (opts.mode !== void 0) {
|
|
2474
|
+
chmodSync4(tmpPath, opts.mode);
|
|
2475
|
+
}
|
|
2476
|
+
} catch (err) {
|
|
2477
|
+
try {
|
|
2478
|
+
if (existsSync4(tmpPath))
|
|
2479
|
+
unlinkSync3(tmpPath);
|
|
2480
|
+
} catch {
|
|
2481
|
+
}
|
|
2482
|
+
throw err;
|
|
2483
|
+
}
|
|
2484
|
+
try {
|
|
2485
|
+
if (keepBackup && existsSync4(path)) {
|
|
2486
|
+
rename(path, bakPath);
|
|
2487
|
+
movedOriginalToBackup = true;
|
|
2488
|
+
}
|
|
2489
|
+
rename(tmpPath, path);
|
|
2490
|
+
} catch (err) {
|
|
2491
|
+
try {
|
|
2492
|
+
if (existsSync4(tmpPath))
|
|
2493
|
+
unlinkSync3(tmpPath);
|
|
2494
|
+
} catch {
|
|
2495
|
+
}
|
|
2496
|
+
if (movedOriginalToBackup && !existsSync4(path) && existsSync4(bakPath)) {
|
|
2497
|
+
try {
|
|
2498
|
+
renameSync3(bakPath, path);
|
|
2499
|
+
} catch {
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
throw err;
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
function safeWriteMcpJson(path, config) {
|
|
2506
|
+
const validation = validateRenderedMcpConfig(config);
|
|
2507
|
+
if (!validation.ok) {
|
|
2508
|
+
return { written: false, errors: validation.errors };
|
|
2509
|
+
}
|
|
2510
|
+
safeWriteJsonAtomic(path, JSON.stringify(config, null, 2), { mode: MCP_FILE_MODE });
|
|
2511
|
+
return { written: true, errors: [] };
|
|
2512
|
+
}
|
|
2513
|
+
var SECRET_FIELD_NAME_RE = /TOKEN|KEY|SECRET|BEARER|PASSWORD/i;
|
|
2514
|
+
function collectSecretFields(config) {
|
|
2515
|
+
const out = /* @__PURE__ */ new Map();
|
|
2516
|
+
if (typeof config !== "object" || config === null)
|
|
2517
|
+
return out;
|
|
2518
|
+
const servers = config.mcpServers;
|
|
2519
|
+
if (typeof servers !== "object" || servers === null)
|
|
2520
|
+
return out;
|
|
2521
|
+
for (const [server, raw] of Object.entries(servers)) {
|
|
2522
|
+
if (typeof raw !== "object" || raw === null)
|
|
2523
|
+
continue;
|
|
2524
|
+
const entry = raw;
|
|
2525
|
+
for (const [block, location] of [
|
|
2526
|
+
[entry.env, "env"],
|
|
2527
|
+
[entry.headers, "header"]
|
|
2528
|
+
]) {
|
|
2529
|
+
if (!block)
|
|
2530
|
+
continue;
|
|
2531
|
+
for (const [field, value] of Object.entries(block)) {
|
|
2532
|
+
if (typeof value !== "string")
|
|
2533
|
+
continue;
|
|
2534
|
+
if (!SECRET_FIELD_NAME_RE.test(field))
|
|
2535
|
+
continue;
|
|
2536
|
+
out.set(`${server}\0${field}`, { location, value });
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
return out;
|
|
2541
|
+
}
|
|
2542
|
+
function mcpMirrorParityErrors(provision2, project) {
|
|
2543
|
+
const a = collectSecretFields(provision2);
|
|
2544
|
+
const b = collectSecretFields(project);
|
|
2545
|
+
const mismatches = [];
|
|
2546
|
+
const keys = /* @__PURE__ */ new Set([...a.keys(), ...b.keys()]);
|
|
2547
|
+
for (const key of keys) {
|
|
2548
|
+
const [server, field] = key.split("\0");
|
|
2549
|
+
const pv = a.get(key);
|
|
2550
|
+
const pj = b.get(key);
|
|
2551
|
+
if (pv && !pj) {
|
|
2552
|
+
mismatches.push({ server, field, location: pv.location, reason: "missing-in-project" });
|
|
2553
|
+
} else if (!pv && pj) {
|
|
2554
|
+
mismatches.push({ server, field, location: pj.location, reason: "missing-in-provision" });
|
|
2555
|
+
} else if (pv && pj && pv.value !== pj.value) {
|
|
2556
|
+
mismatches.push({ server, field, location: pv.location, reason: "value-diverges" });
|
|
2557
|
+
}
|
|
2558
|
+
}
|
|
2559
|
+
return mismatches;
|
|
2560
|
+
}
|
|
2561
|
+
function formatMirrorMismatch(m) {
|
|
2562
|
+
return `[mcp-mirror] [parity-violation] server=${m.server} field=${m.field} location=${m.location} reason=${m.reason}`;
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2359
2565
|
// ../../packages/core/dist/provisioning/frameworks/claudecode/identity.js
|
|
2360
2566
|
function buildMemorySection(hasQmd) {
|
|
2361
2567
|
const recall = hasQmd ? `### Recall
|
|
@@ -3324,15 +3530,21 @@ When you receive a request via any channel (Slack, Telegram, direct chat):
|
|
|
3324
3530
|
3. **Create the kanban task** with kanban.add. Title should be specific
|
|
3325
3531
|
enough to be self-explanatory \u2014 "Pull Linear ENG sprint velocity for
|
|
3326
3532
|
this fortnight" beats "Linear stats".
|
|
3327
|
-
4. Reply in the channel thread
|
|
3533
|
+
4. Reply in the channel thread with a brief acknowledgement that names the
|
|
3534
|
+
created task: "On it \u2014 <task title>".
|
|
3535
|
+
- **On Slack, do NOT paste the kanban URL.** A progress card with an
|
|
3536
|
+
**Open card** button is posted into the thread automatically when the
|
|
3537
|
+
task is channel-sourced \u2014 a pasted link on top of it is duplicate noise.
|
|
3538
|
+
- On channels without a progress card (Telegram, direct chat), include
|
|
3539
|
+
the tracking link: "On it \u2014 tracking here: ${kanbanUrl ?? "my kanban board"}".
|
|
3328
3540
|
5. Move the task to in_progress with kanban.move
|
|
3329
3541
|
6. Do the work
|
|
3330
3542
|
7. Mark done with kanban.done including a result summary
|
|
3331
3543
|
8. Reply in the channel thread with the result
|
|
3332
3544
|
|
|
3333
3545
|
Everything that isn't exempt gets a task \u2014 but only after the request is
|
|
3334
|
-
clear. Don't bury a clarifying question underneath
|
|
3335
|
-
ask the question alone, no
|
|
3546
|
+
clear. Don't bury a clarifying question underneath an "on it" acknowledgement;
|
|
3547
|
+
ask the question alone, no task created yet, and let the user answer before
|
|
3336
3548
|
anything goes on the board.
|
|
3337
3549
|
|
|
3338
3550
|
When asked about existing work, tasks, or what you've been doing \u2014 call kanban.list
|
|
@@ -3458,157 +3670,11 @@ ${frontmatter.environment === "prod" ? "- Production environment: exercise extra
|
|
|
3458
3670
|
}
|
|
3459
3671
|
|
|
3460
3672
|
// ../../packages/core/dist/provisioning/frameworks/claudecode/index.js
|
|
3461
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync5, chmodSync as
|
|
3673
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync5, chmodSync as chmodSync5, readdirSync, rmSync, copyFileSync } from "fs";
|
|
3462
3674
|
import { join as join4, relative, dirname as dirname4 } from "path";
|
|
3463
3675
|
import { homedir as homedir3 } from "os";
|
|
3464
3676
|
import { execFile as execFile3 } from "child_process";
|
|
3465
3677
|
|
|
3466
|
-
// ../../packages/core/dist/provisioning/mcp-config-guards.js
|
|
3467
|
-
import { existsSync as existsSync4, readFileSync as readFileSync4, renameSync as renameSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
3468
|
-
var REQUIRED_ENV_RULES_BY_SERVER = {
|
|
3469
|
-
"cloud-broker": [
|
|
3470
|
-
{ key: "AGT_HOST", mustBeConcrete: false },
|
|
3471
|
-
{ key: "AGT_API_KEY", mustBeConcrete: false },
|
|
3472
|
-
// ENG-4744: this is the bug shape — writer used to omit this
|
|
3473
|
-
// entirely, or render it as a literal `${AGT_AGENT_ID}` instead
|
|
3474
|
-
// of the agent's real UUID. The broker has no way to substitute
|
|
3475
|
-
// it post-spawn, so a placeholder here = silently broken agent.
|
|
3476
|
-
{ key: "AGT_AGENT_ID", mustBeConcrete: true }
|
|
3477
|
-
]
|
|
3478
|
-
};
|
|
3479
|
-
var PLACEHOLDER_RE = /\$\{[^}]+\}/;
|
|
3480
|
-
function validateRenderedMcpConfig(config) {
|
|
3481
|
-
const errors = [];
|
|
3482
|
-
if (typeof config !== "object" || config === null || Array.isArray(config)) {
|
|
3483
|
-
return {
|
|
3484
|
-
ok: false,
|
|
3485
|
-
errors: [
|
|
3486
|
-
{
|
|
3487
|
-
kind: "invalid_json_shape",
|
|
3488
|
-
server: "*",
|
|
3489
|
-
message: "config root must be a non-null object"
|
|
3490
|
-
}
|
|
3491
|
-
]
|
|
3492
|
-
};
|
|
3493
|
-
}
|
|
3494
|
-
const root = config;
|
|
3495
|
-
if (root.mcpServers === void 0) {
|
|
3496
|
-
return { ok: true };
|
|
3497
|
-
}
|
|
3498
|
-
if (typeof root.mcpServers !== "object" || root.mcpServers === null) {
|
|
3499
|
-
return {
|
|
3500
|
-
ok: false,
|
|
3501
|
-
errors: [
|
|
3502
|
-
{
|
|
3503
|
-
kind: "invalid_json_shape",
|
|
3504
|
-
server: "*",
|
|
3505
|
-
message: "mcpServers must be an object"
|
|
3506
|
-
}
|
|
3507
|
-
]
|
|
3508
|
-
};
|
|
3509
|
-
}
|
|
3510
|
-
if (Array.isArray(root.mcpServers)) {
|
|
3511
|
-
return {
|
|
3512
|
-
ok: false,
|
|
3513
|
-
errors: [
|
|
3514
|
-
{
|
|
3515
|
-
kind: "invalid_json_shape",
|
|
3516
|
-
server: "*",
|
|
3517
|
-
message: "mcpServers must be an object"
|
|
3518
|
-
}
|
|
3519
|
-
]
|
|
3520
|
-
};
|
|
3521
|
-
}
|
|
3522
|
-
for (const [serverKey, raw] of Object.entries(root.mcpServers)) {
|
|
3523
|
-
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
3524
|
-
errors.push({
|
|
3525
|
-
kind: "invalid_json_shape",
|
|
3526
|
-
server: serverKey,
|
|
3527
|
-
message: `entry must be an object`
|
|
3528
|
-
});
|
|
3529
|
-
continue;
|
|
3530
|
-
}
|
|
3531
|
-
const entry = raw;
|
|
3532
|
-
const entryRecord = entry;
|
|
3533
|
-
if (typeof entryRecord["url"] === "string") {
|
|
3534
|
-
const type = entryRecord["type"];
|
|
3535
|
-
if (type !== "http" && type !== "sse") {
|
|
3536
|
-
errors.push({
|
|
3537
|
-
kind: "remote_mcp_missing_type",
|
|
3538
|
-
server: serverKey,
|
|
3539
|
-
message: `url-based entry must include \`type: "http"\` or \`type: "sse"\` (Claude Code MCP schema requires it)`
|
|
3540
|
-
});
|
|
3541
|
-
}
|
|
3542
|
-
}
|
|
3543
|
-
const rules = REQUIRED_ENV_RULES_BY_SERVER[serverKey];
|
|
3544
|
-
if (rules) {
|
|
3545
|
-
const env = entry.env ?? {};
|
|
3546
|
-
for (const rule of rules) {
|
|
3547
|
-
const value = env[rule.key];
|
|
3548
|
-
if (typeof value !== "string" || value.length === 0) {
|
|
3549
|
-
errors.push({
|
|
3550
|
-
kind: "missing_required_env",
|
|
3551
|
-
server: serverKey,
|
|
3552
|
-
message: `missing required env key: ${rule.key}`
|
|
3553
|
-
});
|
|
3554
|
-
continue;
|
|
3555
|
-
}
|
|
3556
|
-
if (rule.mustBeConcrete && PLACEHOLDER_RE.test(value)) {
|
|
3557
|
-
errors.push({
|
|
3558
|
-
kind: "unexpanded_placeholder",
|
|
3559
|
-
server: serverKey,
|
|
3560
|
-
message: `env.${rule.key} contains an unexpanded \${...} placeholder; expected a concrete value`
|
|
3561
|
-
});
|
|
3562
|
-
}
|
|
3563
|
-
}
|
|
3564
|
-
}
|
|
3565
|
-
}
|
|
3566
|
-
return errors.length === 0 ? { ok: true } : { ok: false, errors };
|
|
3567
|
-
}
|
|
3568
|
-
function formatValidationErrors(errors) {
|
|
3569
|
-
return errors.map((e) => `${e.server}:${e.kind}=${e.message}`).join("; ");
|
|
3570
|
-
}
|
|
3571
|
-
function safeWriteJsonAtomic(path, content, opts = {}) {
|
|
3572
|
-
const keepBackup = opts.keepBackup !== false;
|
|
3573
|
-
const rename = opts.renamer ?? renameSync3;
|
|
3574
|
-
const tmpPath = `${path}.new`;
|
|
3575
|
-
const bakPath = `${path}.bak`;
|
|
3576
|
-
let movedOriginalToBackup = false;
|
|
3577
|
-
try {
|
|
3578
|
-
writeFileSync4(tmpPath, content);
|
|
3579
|
-
} catch (err) {
|
|
3580
|
-
throw err;
|
|
3581
|
-
}
|
|
3582
|
-
try {
|
|
3583
|
-
if (keepBackup && existsSync4(path)) {
|
|
3584
|
-
rename(path, bakPath);
|
|
3585
|
-
movedOriginalToBackup = true;
|
|
3586
|
-
}
|
|
3587
|
-
rename(tmpPath, path);
|
|
3588
|
-
} catch (err) {
|
|
3589
|
-
try {
|
|
3590
|
-
if (existsSync4(tmpPath))
|
|
3591
|
-
unlinkSync3(tmpPath);
|
|
3592
|
-
} catch {
|
|
3593
|
-
}
|
|
3594
|
-
if (movedOriginalToBackup && !existsSync4(path) && existsSync4(bakPath)) {
|
|
3595
|
-
try {
|
|
3596
|
-
renameSync3(bakPath, path);
|
|
3597
|
-
} catch {
|
|
3598
|
-
}
|
|
3599
|
-
}
|
|
3600
|
-
throw err;
|
|
3601
|
-
}
|
|
3602
|
-
}
|
|
3603
|
-
function safeWriteMcpJson(path, config) {
|
|
3604
|
-
const validation = validateRenderedMcpConfig(config);
|
|
3605
|
-
if (!validation.ok) {
|
|
3606
|
-
return { written: false, errors: validation.errors };
|
|
3607
|
-
}
|
|
3608
|
-
safeWriteJsonAtomic(path, JSON.stringify(config, null, 2));
|
|
3609
|
-
return { written: true, errors: [] };
|
|
3610
|
-
}
|
|
3611
|
-
|
|
3612
3678
|
// ../../packages/core/dist/provisioning/remote-mcp.js
|
|
3613
3679
|
function envVarForToken(definitionId) {
|
|
3614
3680
|
return `${definitionId.replace(/-/g, "_").toUpperCase()}_ACCESS_TOKEN`;
|
|
@@ -3788,7 +3854,19 @@ function syncMcpToProject(codeName) {
|
|
|
3788
3854
|
try {
|
|
3789
3855
|
const content = readFileSync5(provisionMcpPath, "utf-8");
|
|
3790
3856
|
mkdirSync4(projectDir, { recursive: true });
|
|
3791
|
-
writeFileSync5(projectMcpPath, content);
|
|
3857
|
+
writeFileSync5(projectMcpPath, content, { mode: MCP_FILE_MODE });
|
|
3858
|
+
try {
|
|
3859
|
+
chmodSync5(projectMcpPath, MCP_FILE_MODE);
|
|
3860
|
+
} catch {
|
|
3861
|
+
}
|
|
3862
|
+
try {
|
|
3863
|
+
const mismatches = mcpMirrorParityErrors(JSON.parse(content), JSON.parse(readFileSync5(projectMcpPath, "utf-8")));
|
|
3864
|
+
for (const m of mismatches) {
|
|
3865
|
+
process.stderr.write(`${formatMirrorMismatch(m)} agent=${codeName}
|
|
3866
|
+
`);
|
|
3867
|
+
}
|
|
3868
|
+
} catch {
|
|
3869
|
+
}
|
|
3792
3870
|
} catch {
|
|
3793
3871
|
}
|
|
3794
3872
|
renderChannelMessageHandlerForAgent(codeName);
|
|
@@ -3898,7 +3976,15 @@ function deployArtifactsToProject(codeName, provisionDir) {
|
|
|
3898
3976
|
continue;
|
|
3899
3977
|
}
|
|
3900
3978
|
}
|
|
3901
|
-
|
|
3979
|
+
if (file === ".mcp.json") {
|
|
3980
|
+
writeFileSync5(dest, srcContent, { mode: MCP_FILE_MODE });
|
|
3981
|
+
try {
|
|
3982
|
+
chmodSync5(dest, MCP_FILE_MODE);
|
|
3983
|
+
} catch {
|
|
3984
|
+
}
|
|
3985
|
+
} else {
|
|
3986
|
+
writeFileSync5(dest, srcContent);
|
|
3987
|
+
}
|
|
3902
3988
|
} catch {
|
|
3903
3989
|
}
|
|
3904
3990
|
}
|
|
@@ -4006,7 +4092,7 @@ function deployArtifactsToProject(codeName, provisionDir) {
|
|
|
4006
4092
|
const upToDate = existsSync5(hookDest) && readFileSync5(hookDest, "utf-8") === srcContent;
|
|
4007
4093
|
if (!upToDate)
|
|
4008
4094
|
writeFileSync5(hookDest, srcContent);
|
|
4009
|
-
|
|
4095
|
+
chmodSync5(hookDest, 493);
|
|
4010
4096
|
}
|
|
4011
4097
|
} catch {
|
|
4012
4098
|
}
|
|
@@ -4606,7 +4692,7 @@ Your \`tools:\` allowlist (above) names every MCP server the parent has connecte
|
|
|
4606
4692
|
|
|
4607
4693
|
## Hard rules \u2014 Credential Access Control
|
|
4608
4694
|
|
|
4609
|
-
1. **Never** read raw secrets out of \`.mcp.json\`, \`~/.augmented/*/provision/.mcp.json\`, or any agent config file. Those files contain bot tokens, API keys, and OAuth credentials. The Credential Access Control guardrail (\`block_read: true\` on secrets) treats reads of those values as a violation regardless of intent.
|
|
4695
|
+
1. **Never** read raw secrets out of \`.mcp.json\`, \`~/.augmented/*/provision/.mcp.json\`, \`.env.integrations\`, or any agent config file. Those files contain bot tokens, API keys, and OAuth credentials. The Credential Access Control guardrail (\`block_read: true\` on secrets) treats reads of those values as a violation regardless of intent. As **defence-in-depth (not structural enforcement)**, the plugin's \`settings.json\` also denies \`Bash(cat:*/.mcp.json)\`, \`Bash(cat:*/.env.integrations)\`, and \`Bash(jq:*/.mcp.json)\` (ENG-5901 / ADR-0018) \u2014 these block the obvious copy-paste paths but a determined in-process reader can still reach the values; the durable fix is Phase 2/3 of ADR-0018.
|
|
4610
4696
|
2. **Never** post Slack messages via raw \`chat.postMessage\` + a bot token lifted from config. Use the channel MCP's reply tool (\`mcp__slack-channel__slack_reply\`, \`mcp__telegram-channel__telegram_reply\`, \`mcp__direct-chat__direct_chat_reply\`, etc.) so the call goes through the audited path.
|
|
4611
4697
|
3. If an \`mcp__*\` tool you expect to be available returns "No such tool available.", **stop and surface the gap to the parent** in your summary rather than working around it. A missing MCP binding is a platform bug worth fixing \u2014 it's the exact failure shape this sub-agent was added to prevent (see ENG-5897 / ENG-5905).
|
|
4612
4698
|
4. When verifying a capability is wired, confirm the relevant env var exists **without printing its value** \u2014 use \`[ -n "$POSTIZ_API_KEY" ] && echo present || echo absent\`, never \`echo $POSTIZ_API_KEY\`. The Credential Access Control guardrail covers tool-call output as well as file reads.
|
|
@@ -5021,7 +5107,7 @@ ${sections}`
|
|
|
5021
5107
|
if (envLines.length > 1) {
|
|
5022
5108
|
const envPath = join4(agentDir, ".env");
|
|
5023
5109
|
writeFileSync5(envPath, envLines.join("\n") + "\n");
|
|
5024
|
-
|
|
5110
|
+
chmodSync5(envPath, SECRET_FILE_MODE);
|
|
5025
5111
|
}
|
|
5026
5112
|
},
|
|
5027
5113
|
// Claude Code has no gateway process — methods intentionally omitted
|
|
@@ -5555,7 +5641,7 @@ ${sections}`
|
|
|
5555
5641
|
if (envLines.length > 1) {
|
|
5556
5642
|
const envPath = join4(agentDir, ".env.integrations");
|
|
5557
5643
|
writeFileSync5(envPath, envLines.join("\n") + "\n");
|
|
5558
|
-
|
|
5644
|
+
chmodSync5(envPath, SECRET_FILE_MODE);
|
|
5559
5645
|
}
|
|
5560
5646
|
writeXurlStoreForIntegrations(decryptedIntegrations);
|
|
5561
5647
|
for (const integration of decryptedIntegrations) {
|
|
@@ -5754,14 +5840,14 @@ ${sections}`
|
|
|
5754
5840
|
mkdirSync4(join4(filePath, ".."), { recursive: true });
|
|
5755
5841
|
if (isPluginManaged && existsSync5(filePath)) {
|
|
5756
5842
|
try {
|
|
5757
|
-
|
|
5843
|
+
chmodSync5(filePath, READ_WRITE_MODE);
|
|
5758
5844
|
} catch {
|
|
5759
5845
|
}
|
|
5760
5846
|
}
|
|
5761
5847
|
writeFileSync5(filePath, file.content);
|
|
5762
5848
|
if (isPluginManaged) {
|
|
5763
5849
|
try {
|
|
5764
|
-
|
|
5850
|
+
chmodSync5(filePath, READ_ONLY_MODE);
|
|
5765
5851
|
} catch {
|
|
5766
5852
|
}
|
|
5767
5853
|
}
|
|
@@ -5942,7 +6028,7 @@ ${sections}`
|
|
|
5942
6028
|
return;
|
|
5943
6029
|
const tokenPath = join4(agentDir, ".tokens.json");
|
|
5944
6030
|
writeFileSync5(tokenPath, JSON.stringify(tokens, null, 2));
|
|
5945
|
-
|
|
6031
|
+
chmodSync5(tokenPath, SECRET_FILE_MODE);
|
|
5946
6032
|
}
|
|
5947
6033
|
};
|
|
5948
6034
|
registerFramework(claudeCodeAdapter);
|
|
@@ -6520,7 +6606,7 @@ import { homedir as homedir6, userInfo } from "os";
|
|
|
6520
6606
|
import { spawn as spawn3 } from "child_process";
|
|
6521
6607
|
|
|
6522
6608
|
// src/lib/watchdog.ts
|
|
6523
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, unlinkSync as unlinkSync4, existsSync as existsSync7, mkdirSync as mkdirSync6, openSync, closeSync, chmodSync as
|
|
6609
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, unlinkSync as unlinkSync4, existsSync as existsSync7, mkdirSync as mkdirSync6, openSync, closeSync, chmodSync as chmodSync6 } from "fs";
|
|
6524
6610
|
import { join as join7 } from "path";
|
|
6525
6611
|
import { spawn as spawn2, execFileSync } from "child_process";
|
|
6526
6612
|
var DEFAULT_CONFIG_DIR = join7(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
@@ -6614,7 +6700,7 @@ function startWatchdog(opts) {
|
|
|
6614
6700
|
const { logFile } = getManagerPaths(configDir);
|
|
6615
6701
|
const logFd = openSync(logFile, "a", 384);
|
|
6616
6702
|
try {
|
|
6617
|
-
|
|
6703
|
+
chmodSync6(logFile, 384);
|
|
6618
6704
|
} catch {
|
|
6619
6705
|
}
|
|
6620
6706
|
const intervalSec = String(Math.max(Math.floor(opts.intervalMs / 1e3), 5));
|
|
@@ -7127,6 +7213,7 @@ async function managerUninstallSystemUnitCommand() {
|
|
|
7127
7213
|
export {
|
|
7128
7214
|
getIntegration,
|
|
7129
7215
|
extractCommandNotFound,
|
|
7216
|
+
safeWriteJsonAtomic,
|
|
7130
7217
|
INTEGRATIONS_SECTION_START,
|
|
7131
7218
|
INTEGRATIONS_SECTION_END,
|
|
7132
7219
|
estimateActiveTasksTokens,
|
|
@@ -7163,4 +7250,4 @@ export {
|
|
|
7163
7250
|
managerInstallSystemUnitCommand,
|
|
7164
7251
|
managerUninstallSystemUnitCommand
|
|
7165
7252
|
};
|
|
7166
|
-
//# sourceMappingURL=chunk-
|
|
7253
|
+
//# sourceMappingURL=chunk-EYWW624B.js.map
|