@integrity-labs/agt-cli 0.19.13 → 0.19.15
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 +3 -3
- package/dist/{chunk-QFWR2NV5.js → chunk-3K3RO5NS.js} +102 -7
- package/dist/chunk-3K3RO5NS.js.map +1 -0
- package/dist/{chunk-SUUTWC6M.js → chunk-DVWBVANP.js} +419 -141
- package/dist/chunk-DVWBVANP.js.map +1 -0
- package/dist/{claude-pair-runtime-SJDLJNYF.js → claude-pair-runtime-UF4OMFCA.js} +2 -2
- package/dist/lib/manager-worker.js +296 -36
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-XBRQN7XE.js → persistent-session-M2GVL6Z6.js} +2 -2
- package/mcp/index.js +1 -1
- package/mcp/slack-channel.js +216 -1
- package/package.json +1 -1
- package/dist/chunk-QFWR2NV5.js.map +0 -1
- package/dist/chunk-SUUTWC6M.js.map +0 -1
- /package/dist/{claude-pair-runtime-SJDLJNYF.js.map → claude-pair-runtime-UF4OMFCA.js.map} +0 -0
- /package/dist/{persistent-session-XBRQN7XE.js.map → persistent-session-M2GVL6Z6.js.map} +0 -0
|
@@ -2632,11 +2632,146 @@ function extractAllowedDomains(input) {
|
|
|
2632
2632
|
registerFramework(nemoClawAdapter);
|
|
2633
2633
|
|
|
2634
2634
|
// ../../packages/core/dist/provisioning/frameworks/claudecode/index.js
|
|
2635
|
-
import { readFileSync as
|
|
2635
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync5, chmodSync as chmodSync4, readdirSync, rmSync, copyFileSync } from "fs";
|
|
2636
2636
|
import { join as join4, relative, dirname as dirname4 } from "path";
|
|
2637
2637
|
import { homedir as homedir3 } from "os";
|
|
2638
2638
|
import { execFile as execFile3 } from "child_process";
|
|
2639
2639
|
|
|
2640
|
+
// ../../packages/core/dist/provisioning/mcp-config-guards.js
|
|
2641
|
+
import { existsSync as existsSync4, readFileSync as readFileSync4, renameSync as renameSync3, writeFileSync as writeFileSync4, unlinkSync as unlinkSync3 } from "fs";
|
|
2642
|
+
var REQUIRED_ENV_RULES_BY_SERVER = {
|
|
2643
|
+
"cloud-broker": [
|
|
2644
|
+
{ key: "AGT_HOST", mustBeConcrete: false },
|
|
2645
|
+
{ key: "AGT_API_KEY", mustBeConcrete: false },
|
|
2646
|
+
// ENG-4744: this is the bug shape — writer used to omit this
|
|
2647
|
+
// entirely, or render it as a literal `${AGT_AGENT_ID}` instead
|
|
2648
|
+
// of the agent's real UUID. The broker has no way to substitute
|
|
2649
|
+
// it post-spawn, so a placeholder here = silently broken agent.
|
|
2650
|
+
{ key: "AGT_AGENT_ID", mustBeConcrete: true }
|
|
2651
|
+
]
|
|
2652
|
+
};
|
|
2653
|
+
var PLACEHOLDER_RE = /\$\{[^}]+\}/;
|
|
2654
|
+
function validateRenderedMcpConfig(config) {
|
|
2655
|
+
const errors = [];
|
|
2656
|
+
if (typeof config !== "object" || config === null || Array.isArray(config)) {
|
|
2657
|
+
return {
|
|
2658
|
+
ok: false,
|
|
2659
|
+
errors: [
|
|
2660
|
+
{
|
|
2661
|
+
kind: "invalid_json_shape",
|
|
2662
|
+
server: "*",
|
|
2663
|
+
message: "config root must be a non-null object"
|
|
2664
|
+
}
|
|
2665
|
+
]
|
|
2666
|
+
};
|
|
2667
|
+
}
|
|
2668
|
+
const root = config;
|
|
2669
|
+
if (root.mcpServers === void 0) {
|
|
2670
|
+
return { ok: true };
|
|
2671
|
+
}
|
|
2672
|
+
if (typeof root.mcpServers !== "object" || root.mcpServers === null) {
|
|
2673
|
+
return {
|
|
2674
|
+
ok: false,
|
|
2675
|
+
errors: [
|
|
2676
|
+
{
|
|
2677
|
+
kind: "invalid_json_shape",
|
|
2678
|
+
server: "*",
|
|
2679
|
+
message: "mcpServers must be an object"
|
|
2680
|
+
}
|
|
2681
|
+
]
|
|
2682
|
+
};
|
|
2683
|
+
}
|
|
2684
|
+
if (Array.isArray(root.mcpServers)) {
|
|
2685
|
+
return {
|
|
2686
|
+
ok: false,
|
|
2687
|
+
errors: [
|
|
2688
|
+
{
|
|
2689
|
+
kind: "invalid_json_shape",
|
|
2690
|
+
server: "*",
|
|
2691
|
+
message: "mcpServers must be an object"
|
|
2692
|
+
}
|
|
2693
|
+
]
|
|
2694
|
+
};
|
|
2695
|
+
}
|
|
2696
|
+
for (const [serverKey, raw] of Object.entries(root.mcpServers)) {
|
|
2697
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
|
|
2698
|
+
errors.push({
|
|
2699
|
+
kind: "invalid_json_shape",
|
|
2700
|
+
server: serverKey,
|
|
2701
|
+
message: `entry must be an object`
|
|
2702
|
+
});
|
|
2703
|
+
continue;
|
|
2704
|
+
}
|
|
2705
|
+
const entry = raw;
|
|
2706
|
+
const rules = REQUIRED_ENV_RULES_BY_SERVER[serverKey];
|
|
2707
|
+
if (rules) {
|
|
2708
|
+
const env2 = entry.env ?? {};
|
|
2709
|
+
for (const rule of rules) {
|
|
2710
|
+
const value = env2[rule.key];
|
|
2711
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
2712
|
+
errors.push({
|
|
2713
|
+
kind: "missing_required_env",
|
|
2714
|
+
server: serverKey,
|
|
2715
|
+
message: `missing required env key: ${rule.key}`
|
|
2716
|
+
});
|
|
2717
|
+
continue;
|
|
2718
|
+
}
|
|
2719
|
+
if (rule.mustBeConcrete && PLACEHOLDER_RE.test(value)) {
|
|
2720
|
+
errors.push({
|
|
2721
|
+
kind: "unexpanded_placeholder",
|
|
2722
|
+
server: serverKey,
|
|
2723
|
+
message: `env.${rule.key} contains an unexpanded \${...} placeholder; expected a concrete value`
|
|
2724
|
+
});
|
|
2725
|
+
}
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
return errors.length === 0 ? { ok: true } : { ok: false, errors };
|
|
2730
|
+
}
|
|
2731
|
+
function formatValidationErrors(errors) {
|
|
2732
|
+
return errors.map((e) => `${e.server}:${e.kind}=${e.message}`).join("; ");
|
|
2733
|
+
}
|
|
2734
|
+
function safeWriteJsonAtomic(path, content, opts = {}) {
|
|
2735
|
+
const keepBackup = opts.keepBackup !== false;
|
|
2736
|
+
const rename = opts.renamer ?? renameSync3;
|
|
2737
|
+
const tmpPath = `${path}.new`;
|
|
2738
|
+
const bakPath = `${path}.bak`;
|
|
2739
|
+
let movedOriginalToBackup = false;
|
|
2740
|
+
try {
|
|
2741
|
+
writeFileSync4(tmpPath, content);
|
|
2742
|
+
} catch (err) {
|
|
2743
|
+
throw err;
|
|
2744
|
+
}
|
|
2745
|
+
try {
|
|
2746
|
+
if (keepBackup && existsSync4(path)) {
|
|
2747
|
+
rename(path, bakPath);
|
|
2748
|
+
movedOriginalToBackup = true;
|
|
2749
|
+
}
|
|
2750
|
+
rename(tmpPath, path);
|
|
2751
|
+
} catch (err) {
|
|
2752
|
+
try {
|
|
2753
|
+
if (existsSync4(tmpPath))
|
|
2754
|
+
unlinkSync3(tmpPath);
|
|
2755
|
+
} catch {
|
|
2756
|
+
}
|
|
2757
|
+
if (movedOriginalToBackup && !existsSync4(path) && existsSync4(bakPath)) {
|
|
2758
|
+
try {
|
|
2759
|
+
renameSync3(bakPath, path);
|
|
2760
|
+
} catch {
|
|
2761
|
+
}
|
|
2762
|
+
}
|
|
2763
|
+
throw err;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
function safeWriteMcpJson(path, config) {
|
|
2767
|
+
const validation = validateRenderedMcpConfig(config);
|
|
2768
|
+
if (!validation.ok) {
|
|
2769
|
+
return { written: false, errors: validation.errors };
|
|
2770
|
+
}
|
|
2771
|
+
safeWriteJsonAtomic(path, JSON.stringify(config, null, 2));
|
|
2772
|
+
return { written: true, errors: [] };
|
|
2773
|
+
}
|
|
2774
|
+
|
|
2640
2775
|
// ../../packages/core/dist/provisioning/frameworks/claudecode/identity.js
|
|
2641
2776
|
function buildMemorySection(hasQmd) {
|
|
2642
2777
|
const recall = hasQmd ? `### Recall
|
|
@@ -3300,7 +3435,7 @@ function migrateLegacyClaudecodeDir(codeName, log) {
|
|
|
3300
3435
|
if (migratedCodeNames.has(codeName))
|
|
3301
3436
|
return;
|
|
3302
3437
|
const legacyRoot = join4(getHomeDir3(), ".augmented", codeName, "claudecode");
|
|
3303
|
-
if (!
|
|
3438
|
+
if (!existsSync5(legacyRoot)) {
|
|
3304
3439
|
migratedCodeNames.add(codeName);
|
|
3305
3440
|
return;
|
|
3306
3441
|
}
|
|
@@ -3318,25 +3453,25 @@ function migrateLegacyClaudecodeDir(codeName, log) {
|
|
|
3318
3453
|
walkAndMigrate(src, dest);
|
|
3319
3454
|
continue;
|
|
3320
3455
|
}
|
|
3321
|
-
if (entry.name === ".mcp.json" &&
|
|
3456
|
+
if (entry.name === ".mcp.json" && existsSync5(dest)) {
|
|
3322
3457
|
try {
|
|
3323
|
-
const oldCfg = JSON.parse(
|
|
3324
|
-
const newCfg = JSON.parse(
|
|
3458
|
+
const oldCfg = JSON.parse(readFileSync5(src, "utf-8"));
|
|
3459
|
+
const newCfg = JSON.parse(readFileSync5(dest, "utf-8"));
|
|
3325
3460
|
const merged = { mcpServers: { ...oldCfg.mcpServers ?? {}, ...newCfg.mcpServers ?? {} } };
|
|
3326
|
-
|
|
3461
|
+
writeFileSync5(dest, JSON.stringify(merged, null, 2));
|
|
3327
3462
|
emit(`[migrate] '${codeName}' merged .mcp.json (${Object.keys(merged.mcpServers).length} servers)`);
|
|
3328
3463
|
} catch (err) {
|
|
3329
3464
|
throw new Error(`Failed merging .mcp.json (${src} \u2192 ${dest}): ${err.message}`);
|
|
3330
3465
|
}
|
|
3331
3466
|
continue;
|
|
3332
3467
|
}
|
|
3333
|
-
if (!
|
|
3468
|
+
if (!existsSync5(dest)) {
|
|
3334
3469
|
copyFileSync(src, dest);
|
|
3335
3470
|
continue;
|
|
3336
3471
|
}
|
|
3337
3472
|
try {
|
|
3338
|
-
const srcStat =
|
|
3339
|
-
const destStat =
|
|
3473
|
+
const srcStat = readFileSync5(src);
|
|
3474
|
+
const destStat = readFileSync5(dest);
|
|
3340
3475
|
if (!srcStat.equals(destStat)) {
|
|
3341
3476
|
}
|
|
3342
3477
|
} catch (err) {
|
|
@@ -3362,16 +3497,69 @@ function syncMcpToProject(codeName) {
|
|
|
3362
3497
|
const provisionMcpPath = join4(agentDir, "provision", ".mcp.json");
|
|
3363
3498
|
const projectMcpPath = join4(projectDir, ".mcp.json");
|
|
3364
3499
|
try {
|
|
3365
|
-
const content =
|
|
3500
|
+
const content = readFileSync5(provisionMcpPath, "utf-8");
|
|
3366
3501
|
mkdirSync4(projectDir, { recursive: true });
|
|
3367
|
-
|
|
3502
|
+
writeFileSync5(projectMcpPath, content);
|
|
3503
|
+
} catch {
|
|
3504
|
+
}
|
|
3505
|
+
renderChannelMessageHandlerForAgent(codeName);
|
|
3506
|
+
}
|
|
3507
|
+
var INTEGRATIONS_SUMMARY_FILE = "integrations-summary.json";
|
|
3508
|
+
function integrationsSummaryPath(codeName) {
|
|
3509
|
+
return join4(getAgentDir(codeName), "provision", INTEGRATIONS_SUMMARY_FILE);
|
|
3510
|
+
}
|
|
3511
|
+
function writeIntegrationsSummaryForAgent(codeName, summaries) {
|
|
3512
|
+
const target = integrationsSummaryPath(codeName);
|
|
3513
|
+
try {
|
|
3514
|
+
mkdirSync4(dirname4(target), { recursive: true });
|
|
3515
|
+
writeFileSync5(target, JSON.stringify(summaries, null, 2));
|
|
3516
|
+
} catch {
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
function readIntegrationsSummaryForAgent(codeName) {
|
|
3520
|
+
try {
|
|
3521
|
+
const raw = readFileSync5(integrationsSummaryPath(codeName), "utf-8");
|
|
3522
|
+
const parsed = JSON.parse(raw);
|
|
3523
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
3524
|
+
} catch {
|
|
3525
|
+
return [];
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
function renderChannelMessageHandlerForAgent(codeName) {
|
|
3529
|
+
const agentDir = getAgentDir(codeName);
|
|
3530
|
+
const projectDir = getProjectDir(codeName);
|
|
3531
|
+
const provisionMcpPath = join4(agentDir, "provision", ".mcp.json");
|
|
3532
|
+
let mcpServerKeys;
|
|
3533
|
+
try {
|
|
3534
|
+
const config = JSON.parse(readFileSync5(provisionMcpPath, "utf-8"));
|
|
3535
|
+
mcpServerKeys = Object.keys(config.mcpServers ?? {});
|
|
3368
3536
|
} catch {
|
|
3537
|
+
return;
|
|
3538
|
+
}
|
|
3539
|
+
const integrations = readIntegrationsSummaryForAgent(codeName);
|
|
3540
|
+
const content = buildChannelMessageHandlerAgent({ mcpServerKeys, integrations });
|
|
3541
|
+
for (const baseDir of [agentDir, projectDir]) {
|
|
3542
|
+
const target = join4(baseDir, ".claude", "agents", "channel-message-handler.md");
|
|
3543
|
+
try {
|
|
3544
|
+
mkdirSync4(dirname4(target), { recursive: true });
|
|
3545
|
+
writeFileSync5(target, content);
|
|
3546
|
+
} catch {
|
|
3547
|
+
}
|
|
3548
|
+
}
|
|
3549
|
+
}
|
|
3550
|
+
function writeMcpJsonGuarded(codeName, path, config) {
|
|
3551
|
+
const result = safeWriteMcpJson(path, config);
|
|
3552
|
+
if (!result.written) {
|
|
3553
|
+
process.stderr.write(`[manager-worker] [mcp-validate] skipping write for '${codeName}': ${formatValidationErrors(result.errors)}
|
|
3554
|
+
`);
|
|
3555
|
+
return false;
|
|
3369
3556
|
}
|
|
3557
|
+
return true;
|
|
3370
3558
|
}
|
|
3371
3559
|
function readExistingMcpEnvVar(codeName, serverId, envKey) {
|
|
3372
3560
|
const mcpJsonPath = join4(getAgentDir(codeName), "provision", ".mcp.json");
|
|
3373
3561
|
try {
|
|
3374
|
-
const raw =
|
|
3562
|
+
const raw = readFileSync5(mcpJsonPath, "utf-8");
|
|
3375
3563
|
const config = JSON.parse(raw);
|
|
3376
3564
|
const server = config.mcpServers?.[serverId];
|
|
3377
3565
|
if (!server || typeof server !== "object")
|
|
@@ -3386,6 +3574,18 @@ function readExistingMcpEnvVar(codeName, serverId, envKey) {
|
|
|
3386
3574
|
return void 0;
|
|
3387
3575
|
}
|
|
3388
3576
|
}
|
|
3577
|
+
var PLACEHOLDER_LITERAL_RE = /\$\{[^}]+\}/;
|
|
3578
|
+
function resolveBrokerAgentId(codeName, fallback) {
|
|
3579
|
+
const existing = readExistingMcpEnvVar(codeName, "cloud-broker", "AGT_AGENT_ID");
|
|
3580
|
+
if (existing && !PLACEHOLDER_LITERAL_RE.test(existing))
|
|
3581
|
+
return existing;
|
|
3582
|
+
const fromAugmented = readExistingMcpEnvVar(codeName, "augmented", "AGT_AGENT_ID");
|
|
3583
|
+
if (fromAugmented && !PLACEHOLDER_LITERAL_RE.test(fromAugmented))
|
|
3584
|
+
return fromAugmented;
|
|
3585
|
+
if (fallback && !PLACEHOLDER_LITERAL_RE.test(fallback))
|
|
3586
|
+
return fallback;
|
|
3587
|
+
return void 0;
|
|
3588
|
+
}
|
|
3389
3589
|
function deployArtifactsToProject(codeName, provisionDir) {
|
|
3390
3590
|
const projectDir = getProjectDir(codeName);
|
|
3391
3591
|
mkdirSync4(projectDir, { recursive: true });
|
|
@@ -3396,27 +3596,27 @@ function deployArtifactsToProject(codeName, provisionDir) {
|
|
|
3396
3596
|
const src = join4(provisionDir, file);
|
|
3397
3597
|
const dest = join4(projectDir, file);
|
|
3398
3598
|
try {
|
|
3399
|
-
const srcContent =
|
|
3400
|
-
if (file === "CLAUDE.md" &&
|
|
3401
|
-
const destContent =
|
|
3599
|
+
const srcContent = readFileSync5(src, "utf-8");
|
|
3600
|
+
if (file === "CLAUDE.md" && existsSync5(dest)) {
|
|
3601
|
+
const destContent = readFileSync5(dest, "utf-8");
|
|
3402
3602
|
const stripIndex = (s) => s.replace(new RegExp(`${SKILLS_START}[\\s\\S]*?${SKILLS_END}`), "").trimEnd();
|
|
3403
3603
|
if (stripIndex(srcContent) === stripIndex(destContent))
|
|
3404
3604
|
continue;
|
|
3405
3605
|
const indexMatch = destContent.match(new RegExp(`${SKILLS_START}[\\s\\S]*?${SKILLS_END}`));
|
|
3406
3606
|
if (indexMatch) {
|
|
3407
|
-
|
|
3607
|
+
writeFileSync5(dest, srcContent.trimEnd() + "\n\n" + indexMatch[0] + "\n");
|
|
3408
3608
|
continue;
|
|
3409
3609
|
}
|
|
3410
3610
|
}
|
|
3411
|
-
|
|
3611
|
+
writeFileSync5(dest, srcContent);
|
|
3412
3612
|
} catch {
|
|
3413
3613
|
}
|
|
3414
3614
|
}
|
|
3415
3615
|
const skillsDir = join4(provisionDir, ".claude", "skills");
|
|
3416
3616
|
const destSkillsDir = join4(projectDir, ".claude", "skills");
|
|
3417
3617
|
try {
|
|
3418
|
-
if (
|
|
3419
|
-
const srcFolders =
|
|
3618
|
+
if (existsSync5(destSkillsDir)) {
|
|
3619
|
+
const srcFolders = existsSync5(skillsDir) ? new Set(readdirSync(skillsDir)) : /* @__PURE__ */ new Set();
|
|
3420
3620
|
for (const folder of readdirSync(destSkillsDir)) {
|
|
3421
3621
|
if (folder.startsWith("knowledge-") || folder === "core-knowledge" && !srcFolders.has(folder)) {
|
|
3422
3622
|
try {
|
|
@@ -3426,21 +3626,21 @@ function deployArtifactsToProject(codeName, provisionDir) {
|
|
|
3426
3626
|
}
|
|
3427
3627
|
}
|
|
3428
3628
|
}
|
|
3429
|
-
if (
|
|
3629
|
+
if (existsSync5(skillsDir)) {
|
|
3430
3630
|
for (const skillFolder of readdirSync(skillsDir)) {
|
|
3431
3631
|
const srcSkillFile = join4(skillsDir, skillFolder, "SKILL.md");
|
|
3432
|
-
if (!
|
|
3632
|
+
if (!existsSync5(srcSkillFile))
|
|
3433
3633
|
continue;
|
|
3434
3634
|
const destFolder = join4(destSkillsDir, skillFolder);
|
|
3435
3635
|
const destFile = join4(destFolder, "SKILL.md");
|
|
3436
|
-
const srcContent =
|
|
3636
|
+
const srcContent = readFileSync5(srcSkillFile, "utf-8");
|
|
3437
3637
|
try {
|
|
3438
|
-
if (
|
|
3638
|
+
if (existsSync5(destFile) && readFileSync5(destFile, "utf-8") === srcContent)
|
|
3439
3639
|
continue;
|
|
3440
3640
|
} catch {
|
|
3441
3641
|
}
|
|
3442
3642
|
mkdirSync4(destFolder, { recursive: true });
|
|
3443
|
-
|
|
3643
|
+
writeFileSync5(destFile, srcContent);
|
|
3444
3644
|
}
|
|
3445
3645
|
}
|
|
3446
3646
|
} catch {
|
|
@@ -3448,9 +3648,9 @@ function deployArtifactsToProject(codeName, provisionDir) {
|
|
|
3448
3648
|
const agentsDir = join4(provisionDir, ".claude", "agents");
|
|
3449
3649
|
const destAgentsDir = join4(projectDir, ".claude", "agents");
|
|
3450
3650
|
try {
|
|
3451
|
-
if (
|
|
3651
|
+
if (existsSync5(agentsDir)) {
|
|
3452
3652
|
const sourceAgentFiles = new Set(readdirSync(agentsDir).filter((f) => f.endsWith(".md")));
|
|
3453
|
-
if (
|
|
3653
|
+
if (existsSync5(destAgentsDir)) {
|
|
3454
3654
|
for (const destFile of readdirSync(destAgentsDir)) {
|
|
3455
3655
|
if (!destFile.endsWith(".md"))
|
|
3456
3656
|
continue;
|
|
@@ -3465,14 +3665,14 @@ function deployArtifactsToProject(codeName, provisionDir) {
|
|
|
3465
3665
|
for (const agentFile of sourceAgentFiles) {
|
|
3466
3666
|
const srcPath = join4(agentsDir, agentFile);
|
|
3467
3667
|
const destPath = join4(destAgentsDir, agentFile);
|
|
3468
|
-
const srcContent =
|
|
3668
|
+
const srcContent = readFileSync5(srcPath, "utf-8");
|
|
3469
3669
|
try {
|
|
3470
|
-
if (
|
|
3670
|
+
if (existsSync5(destPath) && readFileSync5(destPath, "utf-8") === srcContent)
|
|
3471
3671
|
continue;
|
|
3472
3672
|
} catch {
|
|
3473
3673
|
}
|
|
3474
3674
|
mkdirSync4(destAgentsDir, { recursive: true });
|
|
3475
|
-
|
|
3675
|
+
writeFileSync5(destPath, srcContent);
|
|
3476
3676
|
}
|
|
3477
3677
|
}
|
|
3478
3678
|
} catch {
|
|
@@ -3480,10 +3680,10 @@ function deployArtifactsToProject(codeName, provisionDir) {
|
|
|
3480
3680
|
const agentMcpPath = join4(getAgentDir(codeName), "provision", ".mcp.json");
|
|
3481
3681
|
const projectMcpPath = join4(projectDir, ".mcp.json");
|
|
3482
3682
|
try {
|
|
3483
|
-
const agentMcp = JSON.parse(
|
|
3683
|
+
const agentMcp = JSON.parse(readFileSync5(agentMcpPath, "utf-8"));
|
|
3484
3684
|
let projectMcp;
|
|
3485
3685
|
try {
|
|
3486
|
-
projectMcp = JSON.parse(
|
|
3686
|
+
projectMcp = JSON.parse(readFileSync5(projectMcpPath, "utf-8"));
|
|
3487
3687
|
} catch {
|
|
3488
3688
|
projectMcp = { mcpServers: {} };
|
|
3489
3689
|
}
|
|
@@ -3494,28 +3694,28 @@ function deployArtifactsToProject(codeName, provisionDir) {
|
|
|
3494
3694
|
return !(entry && typeof entry["url"] === "string" && entry["url"].startsWith("/"));
|
|
3495
3695
|
}));
|
|
3496
3696
|
projectMcp["mcpServers"] = { ...stripRelativeUrls(projectServers), ...stripRelativeUrls(agentServers) };
|
|
3497
|
-
|
|
3697
|
+
writeFileSync5(projectMcpPath, JSON.stringify(projectMcp, null, 2));
|
|
3498
3698
|
} catch {
|
|
3499
3699
|
}
|
|
3500
3700
|
const agentDir = getAgentDir(codeName);
|
|
3501
3701
|
for (const envFile of [".env", ".env.integrations"]) {
|
|
3502
3702
|
try {
|
|
3503
|
-
const content =
|
|
3504
|
-
|
|
3703
|
+
const content = readFileSync5(join4(agentDir, envFile), "utf-8");
|
|
3704
|
+
writeFileSync5(join4(projectDir, envFile), content);
|
|
3505
3705
|
} catch {
|
|
3506
3706
|
}
|
|
3507
3707
|
}
|
|
3508
3708
|
try {
|
|
3509
3709
|
const gitDir = join4(projectDir, ".git");
|
|
3510
3710
|
const hookSrc = join4(provisionDir, ".git-hooks", "pre-commit");
|
|
3511
|
-
if (
|
|
3711
|
+
if (existsSync5(gitDir) && existsSync5(hookSrc)) {
|
|
3512
3712
|
const hooksDir = join4(gitDir, "hooks");
|
|
3513
3713
|
mkdirSync4(hooksDir, { recursive: true });
|
|
3514
3714
|
const hookDest = join4(hooksDir, "pre-commit");
|
|
3515
|
-
const srcContent =
|
|
3516
|
-
const upToDate =
|
|
3715
|
+
const srcContent = readFileSync5(hookSrc, "utf-8");
|
|
3716
|
+
const upToDate = existsSync5(hookDest) && readFileSync5(hookDest, "utf-8") === srcContent;
|
|
3517
3717
|
if (!upToDate)
|
|
3518
|
-
|
|
3718
|
+
writeFileSync5(hookDest, srcContent);
|
|
3519
3719
|
chmodSync4(hookDest, 493);
|
|
3520
3720
|
}
|
|
3521
3721
|
} catch {
|
|
@@ -3556,7 +3756,7 @@ function provisionStopHook(codeName) {
|
|
|
3556
3756
|
"esac",
|
|
3557
3757
|
"exit 0"
|
|
3558
3758
|
].join("\n") + "\n";
|
|
3559
|
-
|
|
3759
|
+
writeFileSync5(hookScriptPath, hookScript, { mode: 493 });
|
|
3560
3760
|
const ghostHookPath = join4(claudeDir, "agt-ghost-reply-hook.sh");
|
|
3561
3761
|
const ghostHookScript = [
|
|
3562
3762
|
"#!/bin/bash",
|
|
@@ -3676,11 +3876,11 @@ function provisionStopHook(codeName) {
|
|
|
3676
3876
|
"fi",
|
|
3677
3877
|
"exit 0"
|
|
3678
3878
|
].join("\n") + "\n";
|
|
3679
|
-
|
|
3879
|
+
writeFileSync5(ghostHookPath, ghostHookScript, { mode: 493 });
|
|
3680
3880
|
const settingsPath = join4(claudeDir, "settings.local.json");
|
|
3681
3881
|
let settings = {};
|
|
3682
3882
|
try {
|
|
3683
|
-
settings = JSON.parse(
|
|
3883
|
+
settings = JSON.parse(readFileSync5(settingsPath, "utf-8"));
|
|
3684
3884
|
} catch {
|
|
3685
3885
|
}
|
|
3686
3886
|
const hooks = settings["hooks"] ?? {};
|
|
@@ -3693,7 +3893,7 @@ function provisionStopHook(codeName) {
|
|
|
3693
3893
|
}
|
|
3694
3894
|
];
|
|
3695
3895
|
settings["hooks"] = hooks;
|
|
3696
|
-
|
|
3896
|
+
writeFileSync5(settingsPath, JSON.stringify(settings, null, 2));
|
|
3697
3897
|
}
|
|
3698
3898
|
function provisionIsolationHook(codeName) {
|
|
3699
3899
|
const projectDir = getProjectDir(codeName);
|
|
@@ -3756,11 +3956,11 @@ function provisionIsolationHook(codeName) {
|
|
|
3756
3956
|
"",
|
|
3757
3957
|
"exit 0"
|
|
3758
3958
|
].join("\n") + "\n";
|
|
3759
|
-
|
|
3959
|
+
writeFileSync5(hookScriptPath, hookScript, { mode: 493 });
|
|
3760
3960
|
const settingsPath = join4(claudeDir, "settings.local.json");
|
|
3761
3961
|
let settings = {};
|
|
3762
3962
|
try {
|
|
3763
|
-
settings = JSON.parse(
|
|
3963
|
+
settings = JSON.parse(readFileSync5(settingsPath, "utf-8"));
|
|
3764
3964
|
} catch {
|
|
3765
3965
|
}
|
|
3766
3966
|
const hooks = settings["hooks"] ?? {};
|
|
@@ -3775,13 +3975,13 @@ function provisionIsolationHook(codeName) {
|
|
|
3775
3975
|
}
|
|
3776
3976
|
];
|
|
3777
3977
|
settings["hooks"] = hooks;
|
|
3778
|
-
|
|
3978
|
+
writeFileSync5(settingsPath, JSON.stringify(settings, null, 2));
|
|
3779
3979
|
}
|
|
3780
3980
|
function modifyJsonConfig(filePath, fn) {
|
|
3781
3981
|
let originalContent;
|
|
3782
3982
|
let config;
|
|
3783
3983
|
try {
|
|
3784
|
-
originalContent =
|
|
3984
|
+
originalContent = readFileSync5(filePath, "utf-8");
|
|
3785
3985
|
config = JSON.parse(originalContent);
|
|
3786
3986
|
} catch {
|
|
3787
3987
|
return;
|
|
@@ -3792,7 +3992,7 @@ function modifyJsonConfig(filePath, fn) {
|
|
|
3792
3992
|
const newContent = JSON.stringify(config, null, 2);
|
|
3793
3993
|
if (newContent === originalContent)
|
|
3794
3994
|
return;
|
|
3795
|
-
|
|
3995
|
+
writeFileSync5(filePath, newContent);
|
|
3796
3996
|
}
|
|
3797
3997
|
var SECRETS_DENY_PERMISSIONS = [
|
|
3798
3998
|
// Read blocks
|
|
@@ -3898,12 +4098,42 @@ function buildSettingsJson(input) {
|
|
|
3898
4098
|
settings["permissions"] = { deny: SECRETS_DENY_PERMISSIONS };
|
|
3899
4099
|
return settings;
|
|
3900
4100
|
}
|
|
3901
|
-
function
|
|
4101
|
+
function sanitizeMcpName(name) {
|
|
4102
|
+
return name.replace(/-/g, "_");
|
|
4103
|
+
}
|
|
4104
|
+
function buildChannelMessageHandlerAgent(args) {
|
|
4105
|
+
const mcpServerKeys = args?.mcpServerKeys ?? [];
|
|
4106
|
+
const integrations = args?.integrations ?? [];
|
|
4107
|
+
const mcpWildcards = Array.from(new Set(mcpServerKeys.map((k) => `mcp__${sanitizeMcpName(k)}__*`)));
|
|
4108
|
+
const tools = [
|
|
4109
|
+
"Bash",
|
|
4110
|
+
"Read",
|
|
4111
|
+
"Write",
|
|
4112
|
+
"Edit",
|
|
4113
|
+
"Grep",
|
|
4114
|
+
"Glob",
|
|
4115
|
+
"Skill",
|
|
4116
|
+
"Agent",
|
|
4117
|
+
...mcpWildcards
|
|
4118
|
+
].join(", ");
|
|
4119
|
+
const integrationsBlock = integrations.length === 0 ? "" : `
|
|
4120
|
+
## Integrations available
|
|
4121
|
+
|
|
4122
|
+
You inherit the parent agent's environment, including credentials for the integrations below. Env vars follow the convention \`<DEFINITION_ID>_ACCESS_TOKEN\` for OAuth and \`<DEFINITION_ID>_API_KEY\` for API-key integrations (e.g. \`GITHUB_ACCESS_TOKEN\`, \`POSTIZ_API_KEY\`). Where a CLI is listed, prefer it over raw curl \u2014 the CLI handles auth automatically.
|
|
4123
|
+
|
|
4124
|
+
${integrations.map((i) => {
|
|
4125
|
+
const cli = i.cliBinary ? ` \u2014 use the \`${i.cliBinary}\` CLI` : "";
|
|
4126
|
+
const desc = i.description ? `. ${i.description}` : "";
|
|
4127
|
+
return `- **${i.name}**${cli}${desc}`;
|
|
4128
|
+
}).join("\n")}
|
|
4129
|
+
|
|
4130
|
+
If asked about your capabilities, **check first** (run the CLI, echo the env var, or invoke an MCP tool) before answering. Do not claim a capability is absent without verifying \u2014 the parent's environment is yours.
|
|
4131
|
+
`;
|
|
3902
4132
|
return `---
|
|
3903
4133
|
name: channel-message-handler
|
|
3904
4134
|
description: Handles a single inbound Slack/Telegram/Direct-Chat message end to end. Posts the reply itself via the matching channel tool. The parent agent dispatches to this subagent only for slow requests (\u2265 ~60s) so the parent's listener turn stays free for new inbound work.
|
|
3905
4135
|
background: true
|
|
3906
|
-
tools:
|
|
4136
|
+
tools: ${tools}
|
|
3907
4137
|
---
|
|
3908
4138
|
|
|
3909
4139
|
You are dispatched by the parent agent to handle one channel message.
|
|
@@ -3920,7 +4150,7 @@ Your job:
|
|
|
3920
4150
|
3. End. Do not do additional follow-up work; if more is needed, the user will send another message.
|
|
3921
4151
|
|
|
3922
4152
|
Do NOT post intermediate progress updates unless the work spans 5+ minutes \u2014 keep noise low. The parent already sent a single-line acknowledgement before dispatching you.
|
|
3923
|
-
`;
|
|
4153
|
+
${integrationsBlock}`;
|
|
3924
4154
|
}
|
|
3925
4155
|
function buildPostizMcpEntry(integration) {
|
|
3926
4156
|
const rawBaseUrl = integration.config["base_url"];
|
|
@@ -4097,10 +4327,12 @@ var claudeCodeAdapter = {
|
|
|
4097
4327
|
teamMembers: input.teamMembers,
|
|
4098
4328
|
people: input.people
|
|
4099
4329
|
};
|
|
4330
|
+
const mcpJson = buildMcpJson(input);
|
|
4331
|
+
const initialMcpServerKeys = Object.keys(mcpJson.mcpServers ?? {});
|
|
4100
4332
|
const artifacts = [
|
|
4101
4333
|
{ relativePath: "CLAUDE.md", content: generateClaudeMd(claudeMdInput) },
|
|
4102
4334
|
{ relativePath: "settings.json", content: JSON.stringify(buildSettingsJson(input), null, 2) },
|
|
4103
|
-
{ relativePath: ".mcp.json", content: JSON.stringify(
|
|
4335
|
+
{ relativePath: ".mcp.json", content: JSON.stringify(mcpJson, null, 2) },
|
|
4104
4336
|
{ relativePath: "CHARTER.md", content: input.charterContent },
|
|
4105
4337
|
{ relativePath: "TOOLS.md", content: input.toolsContent },
|
|
4106
4338
|
// ENG-4684: named subagent the parent uses for slow channel-message
|
|
@@ -4108,9 +4340,19 @@ var claudeCodeAdapter = {
|
|
|
4108
4340
|
// turn return immediately on dispatch, so new inbound messages get a
|
|
4109
4341
|
// fresh turn while the subagent does the work in parallel. Triggered
|
|
4110
4342
|
// by the "Channel message triage" instruction in CLAUDE.md.
|
|
4343
|
+
// ENG-4821: integrations are rendered into the subagent body so it
|
|
4344
|
+
// stops claiming "no creds" for capabilities the parent has — and the
|
|
4345
|
+
// sidecar JSON keeps incremental writeIntegrations syncs in lockstep.
|
|
4111
4346
|
{
|
|
4112
4347
|
relativePath: ".claude/agents/channel-message-handler.md",
|
|
4113
|
-
content: buildChannelMessageHandlerAgent(
|
|
4348
|
+
content: buildChannelMessageHandlerAgent({
|
|
4349
|
+
mcpServerKeys: initialMcpServerKeys,
|
|
4350
|
+
integrations: integrationSummaries
|
|
4351
|
+
})
|
|
4352
|
+
},
|
|
4353
|
+
{
|
|
4354
|
+
relativePath: `provision/${INTEGRATIONS_SUMMARY_FILE}`,
|
|
4355
|
+
content: JSON.stringify(integrationSummaries, null, 2)
|
|
4114
4356
|
}
|
|
4115
4357
|
];
|
|
4116
4358
|
const knowledgeEntries = input.knowledge ?? [];
|
|
@@ -4165,7 +4407,7 @@ ${sections}`
|
|
|
4165
4407
|
} catch {
|
|
4166
4408
|
continue;
|
|
4167
4409
|
}
|
|
4168
|
-
if (
|
|
4410
|
+
if (existsSync5(join4(agentRoot, "registration.json"))) {
|
|
4169
4411
|
agents.add(entry);
|
|
4170
4412
|
}
|
|
4171
4413
|
}
|
|
@@ -4179,14 +4421,14 @@ ${sections}`
|
|
|
4179
4421
|
const projectDir = getProjectDir(codeName);
|
|
4180
4422
|
mkdirSync4(agentDir, { recursive: true });
|
|
4181
4423
|
mkdirSync4(projectDir, { recursive: true });
|
|
4182
|
-
|
|
4424
|
+
writeFileSync5(join4(agentDir, "registration.json"), JSON.stringify({
|
|
4183
4425
|
code_name: codeName,
|
|
4184
4426
|
team_dir: teamDir,
|
|
4185
4427
|
project_dir: projectDir,
|
|
4186
4428
|
framework: "claude-code",
|
|
4187
4429
|
registered_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
4188
4430
|
}, null, 2));
|
|
4189
|
-
if (
|
|
4431
|
+
if (existsSync5(teamDir)) {
|
|
4190
4432
|
deployArtifactsToProject(codeName, teamDir);
|
|
4191
4433
|
}
|
|
4192
4434
|
return true;
|
|
@@ -4198,9 +4440,9 @@ ${sections}`
|
|
|
4198
4440
|
try {
|
|
4199
4441
|
const agentDir = getAgentDir(codeName);
|
|
4200
4442
|
const regFile = join4(agentDir, "registration.json");
|
|
4201
|
-
if (
|
|
4202
|
-
const { unlinkSync:
|
|
4203
|
-
|
|
4443
|
+
if (existsSync5(regFile)) {
|
|
4444
|
+
const { unlinkSync: unlinkSync5 } = await import("fs");
|
|
4445
|
+
unlinkSync5(regFile);
|
|
4204
4446
|
}
|
|
4205
4447
|
return true;
|
|
4206
4448
|
} catch {
|
|
@@ -4224,7 +4466,7 @@ ${sections}`
|
|
|
4224
4466
|
}
|
|
4225
4467
|
if (envLines.length > 1) {
|
|
4226
4468
|
const envPath = join4(agentDir, ".env");
|
|
4227
|
-
|
|
4469
|
+
writeFileSync5(envPath, envLines.join("\n") + "\n");
|
|
4228
4470
|
chmodSync4(envPath, SECRET_FILE_MODE);
|
|
4229
4471
|
}
|
|
4230
4472
|
},
|
|
@@ -4273,13 +4515,15 @@ ${sections}`
|
|
|
4273
4515
|
mkdirSync4(dirname4(provisionMcpPath), { recursive: true });
|
|
4274
4516
|
let mcpConfig2 = { mcpServers: {} };
|
|
4275
4517
|
try {
|
|
4276
|
-
mcpConfig2 = JSON.parse(
|
|
4518
|
+
mcpConfig2 = JSON.parse(readFileSync5(provisionMcpPath, "utf-8"));
|
|
4277
4519
|
if (!mcpConfig2.mcpServers)
|
|
4278
4520
|
mcpConfig2.mcpServers = {};
|
|
4279
4521
|
} catch {
|
|
4280
4522
|
}
|
|
4281
4523
|
mcpConfig2.mcpServers["telegram"] = telegramEntry;
|
|
4282
|
-
|
|
4524
|
+
if (!writeMcpJsonGuarded(codeName, provisionMcpPath, mcpConfig2)) {
|
|
4525
|
+
return;
|
|
4526
|
+
}
|
|
4283
4527
|
syncMcpToProject(codeName);
|
|
4284
4528
|
return;
|
|
4285
4529
|
}
|
|
@@ -4290,7 +4534,7 @@ ${sections}`
|
|
|
4290
4534
|
if (channelId === "discord") {
|
|
4291
4535
|
const botToken = config["bot_token"];
|
|
4292
4536
|
if (botToken) {
|
|
4293
|
-
|
|
4537
|
+
writeFileSync5(join4(channelDir, ".env"), `DISCORD_BOT_TOKEN=${botToken}
|
|
4294
4538
|
`);
|
|
4295
4539
|
}
|
|
4296
4540
|
} else if (channelId === "slack") {
|
|
@@ -4313,8 +4557,8 @@ ${sections}`
|
|
|
4313
4557
|
if (botToken) {
|
|
4314
4558
|
const localSlackChannel = join4(getHomeDir3(), ".augmented", "_mcp", "slack-channel.js");
|
|
4315
4559
|
const slackEntry = {
|
|
4316
|
-
command:
|
|
4317
|
-
args:
|
|
4560
|
+
command: existsSync5(localSlackChannel) ? "node" : "npx",
|
|
4561
|
+
args: existsSync5(localSlackChannel) ? [localSlackChannel] : ["-y", "@augmented/claude-code-channel-slack"],
|
|
4318
4562
|
env: {
|
|
4319
4563
|
SLACK_BOT_TOKEN: botToken,
|
|
4320
4564
|
...appToken ? { SLACK_APP_TOKEN: appToken } : {},
|
|
@@ -4332,16 +4576,18 @@ ${sections}`
|
|
|
4332
4576
|
mkdirSync4(dirname4(provisionMcpPath), { recursive: true });
|
|
4333
4577
|
let mcpConfig2 = { mcpServers: {} };
|
|
4334
4578
|
try {
|
|
4335
|
-
mcpConfig2 = JSON.parse(
|
|
4579
|
+
mcpConfig2 = JSON.parse(readFileSync5(provisionMcpPath, "utf-8"));
|
|
4336
4580
|
if (!mcpConfig2.mcpServers)
|
|
4337
4581
|
mcpConfig2.mcpServers = {};
|
|
4338
4582
|
} catch {
|
|
4339
4583
|
}
|
|
4340
4584
|
mcpConfig2.mcpServers["slack"] = slackEntry;
|
|
4341
|
-
|
|
4585
|
+
if (!writeMcpJsonGuarded(codeName, provisionMcpPath, mcpConfig2)) {
|
|
4586
|
+
return;
|
|
4587
|
+
}
|
|
4342
4588
|
syncMcpToProject(codeName);
|
|
4343
4589
|
const staleChannelsPath = join4(getProjectDir(codeName), ".mcp-channels.json");
|
|
4344
|
-
if (
|
|
4590
|
+
if (existsSync5(staleChannelsPath)) {
|
|
4345
4591
|
try {
|
|
4346
4592
|
rmSync(staleChannelsPath, { force: true });
|
|
4347
4593
|
} catch {
|
|
@@ -4354,7 +4600,7 @@ ${sections}`
|
|
|
4354
4600
|
const mcpJsonPath = join4(agentDir, "provision", ".mcp.json");
|
|
4355
4601
|
let mcpConfig;
|
|
4356
4602
|
try {
|
|
4357
|
-
mcpConfig = JSON.parse(
|
|
4603
|
+
mcpConfig = JSON.parse(readFileSync5(mcpJsonPath, "utf-8"));
|
|
4358
4604
|
} catch {
|
|
4359
4605
|
mcpConfig = { mcpServers: {} };
|
|
4360
4606
|
}
|
|
@@ -4390,7 +4636,7 @@ ${sections}`
|
|
|
4390
4636
|
...oneshotBlockKitAskUserEnabled && process.env["AGT_API_KEY"] ? { AGT_API_KEY: process.env["AGT_API_KEY"] } : {},
|
|
4391
4637
|
...oneshotBlockKitAskUserEnabled && options?.agentId ? { AGT_AGENT_ID: options.agentId } : {}
|
|
4392
4638
|
} : {};
|
|
4393
|
-
if (isPersistent &&
|
|
4639
|
+
if (isPersistent && existsSync5(localSlackChannel)) {
|
|
4394
4640
|
mcpServers["slack"] = {
|
|
4395
4641
|
command: "node",
|
|
4396
4642
|
args: [localSlackChannel],
|
|
@@ -4416,15 +4662,16 @@ ${sections}`
|
|
|
4416
4662
|
};
|
|
4417
4663
|
}
|
|
4418
4664
|
}
|
|
4419
|
-
|
|
4420
|
-
|
|
4665
|
+
if (writeMcpJsonGuarded(codeName, mcpJsonPath, mcpConfig)) {
|
|
4666
|
+
syncMcpToProject(codeName);
|
|
4667
|
+
}
|
|
4421
4668
|
},
|
|
4422
4669
|
hasChannelCredentials(codeName, channelId) {
|
|
4423
4670
|
const provisionMcpPath = join4(getAgentDir(codeName), "provision", ".mcp.json");
|
|
4424
|
-
if (!
|
|
4671
|
+
if (!existsSync5(provisionMcpPath))
|
|
4425
4672
|
return false;
|
|
4426
4673
|
try {
|
|
4427
|
-
const parsed = JSON.parse(
|
|
4674
|
+
const parsed = JSON.parse(readFileSync5(provisionMcpPath, "utf-8"));
|
|
4428
4675
|
return Boolean(parsed.mcpServers?.[channelId]);
|
|
4429
4676
|
} catch {
|
|
4430
4677
|
return false;
|
|
@@ -4464,12 +4711,22 @@ ${sections}`
|
|
|
4464
4711
|
const schedulesPath = join4(agentDir, "schedules.json");
|
|
4465
4712
|
const mapped = mapScheduledTasks(tasks);
|
|
4466
4713
|
mkdirSync4(agentDir, { recursive: true });
|
|
4467
|
-
|
|
4714
|
+
writeFileSync5(schedulesPath, JSON.stringify({ schedules: mapped }, null, 2));
|
|
4468
4715
|
return Promise.resolve();
|
|
4469
4716
|
},
|
|
4470
4717
|
writeIntegrations(codeName, integrations) {
|
|
4471
4718
|
const agentDir = getAgentDir(codeName);
|
|
4472
4719
|
mkdirSync4(agentDir, { recursive: true });
|
|
4720
|
+
const summariesForSidecar = integrations.map((i) => {
|
|
4721
|
+
const def = INTEGRATION_REGISTRY.find((d) => d.id === i.definition_id);
|
|
4722
|
+
return {
|
|
4723
|
+
id: i.definition_id,
|
|
4724
|
+
name: def?.name || i.display_name || i.definition_id,
|
|
4725
|
+
cliBinary: def?.cli_tool?.binary,
|
|
4726
|
+
description: def?.description || (i.auth_type === "managed" ? "Managed integration via Composio" : void 0)
|
|
4727
|
+
};
|
|
4728
|
+
});
|
|
4729
|
+
writeIntegrationsSummaryForAgent(codeName, summariesForSidecar);
|
|
4473
4730
|
const decryptedIntegrations = integrations.map((integration) => ({
|
|
4474
4731
|
...integration,
|
|
4475
4732
|
credentials: decryptIntegrationCredentials(integration.credentials)
|
|
@@ -4502,7 +4759,7 @@ ${sections}`
|
|
|
4502
4759
|
}
|
|
4503
4760
|
if (envLines.length > 1) {
|
|
4504
4761
|
const envPath = join4(agentDir, ".env.integrations");
|
|
4505
|
-
|
|
4762
|
+
writeFileSync5(envPath, envLines.join("\n") + "\n");
|
|
4506
4763
|
chmodSync4(envPath, SECRET_FILE_MODE);
|
|
4507
4764
|
}
|
|
4508
4765
|
writeXurlStoreForIntegrations(decryptedIntegrations);
|
|
@@ -4534,53 +4791,50 @@ ${sections}`
|
|
|
4534
4791
|
}
|
|
4535
4792
|
const hasCloudBroker = integrations.some((i) => i.definition_id === "cloud-broker");
|
|
4536
4793
|
if (hasCloudBroker) {
|
|
4537
|
-
const
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
4546
|
-
|
|
4547
|
-
|
|
4548
|
-
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4794
|
+
const brokerAgentId = resolveBrokerAgentId(codeName);
|
|
4795
|
+
if (!brokerAgentId) {
|
|
4796
|
+
process.stderr.write(`[manager-worker] [cloud-broker] skipping write for '${codeName}': no real AGT_AGENT_ID available (no existing broker entry, no augmented entry to copy from). The full-provision artifact pipeline will recreate this on the next cycle.
|
|
4797
|
+
`);
|
|
4798
|
+
} else {
|
|
4799
|
+
this.writeMcpServer(codeName, "cloud-broker", {
|
|
4800
|
+
command: "npx",
|
|
4801
|
+
args: ["-y", "@integrity-labs/cloud-broker@latest"],
|
|
4802
|
+
env: {
|
|
4803
|
+
AGT_HOST: "${AGT_HOST}",
|
|
4804
|
+
AGT_API_KEY: "${AGT_API_KEY}",
|
|
4805
|
+
AGT_AGENT_ID: brokerAgentId,
|
|
4806
|
+
// ENG-4788: cloud-broker@0.6+ exits at startup if AGT_RUN_ID
|
|
4807
|
+
// is missing. Mirror buildMcpJson's entry on incremental sync
|
|
4808
|
+
// so an agent that connects AWS post-provision boots cleanly.
|
|
4809
|
+
AGT_RUN_ID: "${AGT_RUN_ID}",
|
|
4810
|
+
PATH: process.env["PATH"] ?? "",
|
|
4811
|
+
HOME: process.env["HOME"] ?? ""
|
|
4812
|
+
}
|
|
4813
|
+
});
|
|
4814
|
+
}
|
|
4553
4815
|
}
|
|
4554
4816
|
const projectDir = getProjectDir(codeName);
|
|
4555
4817
|
const claudeMdPath = join4(projectDir, "CLAUDE.md");
|
|
4556
4818
|
try {
|
|
4557
|
-
const existing =
|
|
4558
|
-
const
|
|
4559
|
-
const def = INTEGRATION_REGISTRY.find((d) => d.id === i.definition_id);
|
|
4560
|
-
return {
|
|
4561
|
-
id: i.definition_id,
|
|
4562
|
-
name: def?.name || i.display_name || i.definition_id,
|
|
4563
|
-
cliBinary: def?.cli_tool?.binary,
|
|
4564
|
-
description: def?.description || (i.auth_type === "managed" ? "Managed integration via Composio" : void 0)
|
|
4565
|
-
};
|
|
4566
|
-
});
|
|
4567
|
-
const newSection = buildIntegrationsSection(summaries);
|
|
4819
|
+
const existing = readFileSync5(claudeMdPath, "utf-8");
|
|
4820
|
+
const newSection = buildIntegrationsSection(summariesForSidecar);
|
|
4568
4821
|
let updated;
|
|
4569
4822
|
if (existing.includes("## Integrations")) {
|
|
4570
4823
|
updated = existing.replace(/## Integrations[\s\S]*?(?=## Rules)/, newSection);
|
|
4571
4824
|
} else {
|
|
4572
4825
|
updated = existing.replace("## Rules", `${newSection}## Rules`);
|
|
4573
4826
|
}
|
|
4574
|
-
|
|
4827
|
+
writeFileSync5(claudeMdPath, updated);
|
|
4575
4828
|
const agentDir2 = getAgentDir(codeName);
|
|
4576
4829
|
const envSrc = join4(agentDir2, ".env.integrations");
|
|
4577
4830
|
try {
|
|
4578
|
-
const envContent =
|
|
4579
|
-
|
|
4831
|
+
const envContent = readFileSync5(envSrc, "utf-8");
|
|
4832
|
+
writeFileSync5(join4(projectDir, ".env.integrations"), envContent);
|
|
4580
4833
|
} catch {
|
|
4581
4834
|
}
|
|
4582
4835
|
} catch {
|
|
4583
4836
|
}
|
|
4837
|
+
renderChannelMessageHandlerForAgent(codeName);
|
|
4584
4838
|
},
|
|
4585
4839
|
writeMcpServer(codeName, serverId, config) {
|
|
4586
4840
|
const agentDir = getAgentDir(codeName);
|
|
@@ -4588,7 +4842,7 @@ ${sections}`
|
|
|
4588
4842
|
mkdirSync4(join4(agentDir, "provision"), { recursive: true });
|
|
4589
4843
|
let mcpConfig;
|
|
4590
4844
|
try {
|
|
4591
|
-
mcpConfig = JSON.parse(
|
|
4845
|
+
mcpConfig = JSON.parse(readFileSync5(mcpJsonPath, "utf-8"));
|
|
4592
4846
|
} catch {
|
|
4593
4847
|
mcpConfig = { mcpServers: {} };
|
|
4594
4848
|
}
|
|
@@ -4640,8 +4894,9 @@ ${sections}`
|
|
|
4640
4894
|
serverEntry["env"] = config.env;
|
|
4641
4895
|
}
|
|
4642
4896
|
mcpServers[serverId] = serverEntry;
|
|
4643
|
-
|
|
4644
|
-
|
|
4897
|
+
if (writeMcpJsonGuarded(codeName, mcpJsonPath, mcpConfig)) {
|
|
4898
|
+
syncMcpToProject(codeName);
|
|
4899
|
+
}
|
|
4645
4900
|
},
|
|
4646
4901
|
getMcpPath(codeName) {
|
|
4647
4902
|
return join4(getAgentDir(codeName), "provision", ".mcp.json");
|
|
@@ -4651,7 +4906,7 @@ ${sections}`
|
|
|
4651
4906
|
const mcpJsonPath = join4(agentDir, "provision", ".mcp.json");
|
|
4652
4907
|
let mcpConfig;
|
|
4653
4908
|
try {
|
|
4654
|
-
mcpConfig = JSON.parse(
|
|
4909
|
+
mcpConfig = JSON.parse(readFileSync5(mcpJsonPath, "utf-8"));
|
|
4655
4910
|
} catch {
|
|
4656
4911
|
return;
|
|
4657
4912
|
}
|
|
@@ -4659,8 +4914,9 @@ ${sections}`
|
|
|
4659
4914
|
if (!mcpServers || !(serverId in mcpServers))
|
|
4660
4915
|
return;
|
|
4661
4916
|
delete mcpServers[serverId];
|
|
4662
|
-
|
|
4663
|
-
|
|
4917
|
+
if (writeMcpJsonGuarded(codeName, mcpJsonPath, mcpConfig)) {
|
|
4918
|
+
syncMcpToProject(codeName);
|
|
4919
|
+
}
|
|
4664
4920
|
},
|
|
4665
4921
|
installSkillFiles(codeName, skillId, files) {
|
|
4666
4922
|
assertValidCodeName(skillId);
|
|
@@ -4680,13 +4936,13 @@ ${sections}`
|
|
|
4680
4936
|
throw new Error(`Path traversal detected: ${file.relativePath} resolves outside ${skillDir}`);
|
|
4681
4937
|
}
|
|
4682
4938
|
mkdirSync4(join4(filePath, ".."), { recursive: true });
|
|
4683
|
-
if (isPluginManaged &&
|
|
4939
|
+
if (isPluginManaged && existsSync5(filePath)) {
|
|
4684
4940
|
try {
|
|
4685
4941
|
chmodSync4(filePath, READ_WRITE_MODE);
|
|
4686
4942
|
} catch {
|
|
4687
4943
|
}
|
|
4688
4944
|
}
|
|
4689
|
-
|
|
4945
|
+
writeFileSync5(filePath, file.content);
|
|
4690
4946
|
if (isPluginManaged) {
|
|
4691
4947
|
try {
|
|
4692
4948
|
chmodSync4(filePath, READ_ONLY_MODE);
|
|
@@ -4702,7 +4958,7 @@ ${sections}`
|
|
|
4702
4958
|
mkdirSync4(agentDir, { recursive: true });
|
|
4703
4959
|
let pluginsConfig;
|
|
4704
4960
|
try {
|
|
4705
|
-
pluginsConfig = JSON.parse(
|
|
4961
|
+
pluginsConfig = JSON.parse(readFileSync5(pluginsJsonPath, "utf-8"));
|
|
4706
4962
|
} catch {
|
|
4707
4963
|
pluginsConfig = { plugins: {} };
|
|
4708
4964
|
}
|
|
@@ -4715,7 +4971,7 @@ ${sections}`
|
|
|
4715
4971
|
installed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4716
4972
|
...pluginConfig ? { config: pluginConfig } : {}
|
|
4717
4973
|
};
|
|
4718
|
-
|
|
4974
|
+
writeFileSync5(pluginsJsonPath, JSON.stringify(pluginsConfig, null, 2));
|
|
4719
4975
|
},
|
|
4720
4976
|
/**
|
|
4721
4977
|
* Full plugin provisioning: install scripts, register hooks, apply permissions,
|
|
@@ -4750,7 +5006,7 @@ ${sections}`
|
|
|
4750
5006
|
const settingsPath = join4(claudeDir, "settings.local.json");
|
|
4751
5007
|
let settings = {};
|
|
4752
5008
|
try {
|
|
4753
|
-
settings = JSON.parse(
|
|
5009
|
+
settings = JSON.parse(readFileSync5(settingsPath, "utf-8"));
|
|
4754
5010
|
} catch {
|
|
4755
5011
|
}
|
|
4756
5012
|
const existingHooks = settings["hooks"] ?? {};
|
|
@@ -4784,13 +5040,13 @@ ${sections}`
|
|
|
4784
5040
|
}
|
|
4785
5041
|
}
|
|
4786
5042
|
settings["hooks"] = existingHooks;
|
|
4787
|
-
|
|
5043
|
+
writeFileSync5(settingsPath, JSON.stringify(settings, null, 2));
|
|
4788
5044
|
}
|
|
4789
5045
|
if (plugin.allowed_tools.length > 0) {
|
|
4790
5046
|
const settingsPath = join4(claudeDir, "settings.local.json");
|
|
4791
5047
|
let settings = {};
|
|
4792
5048
|
try {
|
|
4793
|
-
settings = JSON.parse(
|
|
5049
|
+
settings = JSON.parse(readFileSync5(settingsPath, "utf-8"));
|
|
4794
5050
|
} catch {
|
|
4795
5051
|
}
|
|
4796
5052
|
const existingPerms = settings["permissions"] ?? {};
|
|
@@ -4802,12 +5058,12 @@ ${sections}`
|
|
|
4802
5058
|
}
|
|
4803
5059
|
existingPerms["allow"] = allowList;
|
|
4804
5060
|
settings["permissions"] = existingPerms;
|
|
4805
|
-
|
|
5061
|
+
writeFileSync5(settingsPath, JSON.stringify(settings, null, 2));
|
|
4806
5062
|
}
|
|
4807
5063
|
if (contextValues && Object.keys(contextValues).length > 0) {
|
|
4808
5064
|
const configDir = join4(projectDir, `.${plugin.slug}`);
|
|
4809
5065
|
mkdirSync4(configDir, { recursive: true });
|
|
4810
|
-
|
|
5066
|
+
writeFileSync5(join4(configDir, "config.json"), JSON.stringify(contextValues, null, 2));
|
|
4811
5067
|
}
|
|
4812
5068
|
},
|
|
4813
5069
|
executePluginHook(ctx) {
|
|
@@ -4869,7 +5125,7 @@ ${sections}`
|
|
|
4869
5125
|
if (Object.keys(tokens).length === 0)
|
|
4870
5126
|
return;
|
|
4871
5127
|
const tokenPath = join4(agentDir, ".tokens.json");
|
|
4872
|
-
|
|
5128
|
+
writeFileSync5(tokenPath, JSON.stringify(tokens, null, 2));
|
|
4873
5129
|
chmodSync4(tokenPath, SECRET_FILE_MODE);
|
|
4874
5130
|
}
|
|
4875
5131
|
};
|
|
@@ -5159,13 +5415,13 @@ function jsonOutput(data) {
|
|
|
5159
5415
|
}
|
|
5160
5416
|
|
|
5161
5417
|
// src/lib/config.ts
|
|
5162
|
-
import { readFileSync as
|
|
5418
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, mkdirSync as mkdirSync5, existsSync as existsSync6 } from "fs";
|
|
5163
5419
|
import { join as join6 } from "path";
|
|
5164
5420
|
import { homedir as homedir5 } from "os";
|
|
5165
5421
|
var AUGMENTED_DIR2 = join6(homedir5(), ".augmented");
|
|
5166
5422
|
var CONFIG_PATH = join6(AUGMENTED_DIR2, "config.json");
|
|
5167
5423
|
function ensureAugmentedDir() {
|
|
5168
|
-
if (!
|
|
5424
|
+
if (!existsSync6(AUGMENTED_DIR2)) {
|
|
5169
5425
|
mkdirSync5(AUGMENTED_DIR2, { recursive: true });
|
|
5170
5426
|
}
|
|
5171
5427
|
}
|
|
@@ -5179,7 +5435,7 @@ function loadFromShellProfile(force = false) {
|
|
|
5179
5435
|
const candidates = shell.includes("zsh") ? [join6(home, ".zshrc"), join6(home, ".zprofile")] : shell.includes("fish") ? [join6(home, ".config", "fish", "config.fish")] : [join6(home, ".bashrc"), join6(home, ".bash_profile")];
|
|
5180
5436
|
for (const profile of candidates) {
|
|
5181
5437
|
try {
|
|
5182
|
-
const content =
|
|
5438
|
+
const content = readFileSync6(profile, "utf-8");
|
|
5183
5439
|
for (const key of ["AGT_HOST", "AGT_API_KEY", "AGT_TEAM"]) {
|
|
5184
5440
|
if (!force && process.env[key]) continue;
|
|
5185
5441
|
const match = content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map(
|
|
@@ -5204,7 +5460,7 @@ function getApiKey() {
|
|
|
5204
5460
|
}
|
|
5205
5461
|
function getConfig() {
|
|
5206
5462
|
try {
|
|
5207
|
-
const raw =
|
|
5463
|
+
const raw = readFileSync6(CONFIG_PATH, "utf-8");
|
|
5208
5464
|
return JSON.parse(raw);
|
|
5209
5465
|
} catch {
|
|
5210
5466
|
return {};
|
|
@@ -5212,7 +5468,7 @@ function getConfig() {
|
|
|
5212
5468
|
}
|
|
5213
5469
|
function saveConfig(config) {
|
|
5214
5470
|
ensureAugmentedDir();
|
|
5215
|
-
|
|
5471
|
+
writeFileSync6(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
5216
5472
|
}
|
|
5217
5473
|
function getActiveTeam() {
|
|
5218
5474
|
const envTeam = process.env["AGT_TEAM"];
|
|
@@ -5559,7 +5815,12 @@ var SLACK_SCOPE_REGISTRY = [
|
|
|
5559
5815
|
name: "Write Bot Profile",
|
|
5560
5816
|
description: "Update the bot's own profile (status emoji + status text). Used to surface live/offline state to operators without polling.",
|
|
5561
5817
|
category: "users",
|
|
5562
|
-
risk: "low"
|
|
5818
|
+
risk: "low",
|
|
5819
|
+
// ENG-4812: Slack rejects this scope under oauth_config.scopes.bot
|
|
5820
|
+
// with `illegal_bot_scopes`. It must be granted via a user token —
|
|
5821
|
+
// which is what `setBotStatus()` (calling users.profile.set in
|
|
5822
|
+
// packages/mcp/src/slack-channel.ts) actually requires anyway.
|
|
5823
|
+
token_type: "user"
|
|
5563
5824
|
},
|
|
5564
5825
|
// ── Channel Management ───────────────────────────────────────────────────
|
|
5565
5826
|
{
|
|
@@ -5701,6 +5962,9 @@ function getScopesByCategory() {
|
|
|
5701
5962
|
}
|
|
5702
5963
|
return map;
|
|
5703
5964
|
}
|
|
5965
|
+
function getSlackScopeDefinition(scope) {
|
|
5966
|
+
return SLACK_SCOPE_REGISTRY.find((s) => s.scope === scope);
|
|
5967
|
+
}
|
|
5704
5968
|
var SLACK_SCOPE_PRESETS = {
|
|
5705
5969
|
minimal: [
|
|
5706
5970
|
"app_mentions:read",
|
|
@@ -5786,9 +6050,23 @@ function generateSlackAppManifest(input) {
|
|
|
5786
6050
|
},
|
|
5787
6051
|
oauth_config: {
|
|
5788
6052
|
...redirect_urls && redirect_urls.length > 0 ? { redirect_urls } : {},
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
6053
|
+
// ENG-4812: partition by token_type so user-only scopes
|
|
6054
|
+
// (e.g. users.profile:write) don't end up under `bot` and
|
|
6055
|
+
// trigger Slack's `illegal_bot_scopes` rejection. Scopes
|
|
6056
|
+
// without an explicit token_type default to 'bot' — matches
|
|
6057
|
+
// pre-fix behaviour for the registry's standard-token-set.
|
|
6058
|
+
scopes: (() => {
|
|
6059
|
+
const botScopes = [];
|
|
6060
|
+
const userScopes = [];
|
|
6061
|
+
for (const scope of scopes) {
|
|
6062
|
+
const def = getSlackScopeDefinition(scope);
|
|
6063
|
+
if (def?.token_type === "user")
|
|
6064
|
+
userScopes.push(scope);
|
|
6065
|
+
else
|
|
6066
|
+
botScopes.push(scope);
|
|
6067
|
+
}
|
|
6068
|
+
return userScopes.length > 0 ? { bot: botScopes, user: userScopes } : { bot: botScopes };
|
|
6069
|
+
})()
|
|
5792
6070
|
},
|
|
5793
6071
|
settings: {
|
|
5794
6072
|
...botEvents.size > 0 ? { event_subscriptions: { bot_events: [...botEvents].sort() } } : {},
|
|
@@ -7559,13 +7837,13 @@ function provision(input, frameworkId = "openclaw") {
|
|
|
7559
7837
|
|
|
7560
7838
|
// src/commands/manager.ts
|
|
7561
7839
|
import chalk3 from "chalk";
|
|
7562
|
-
import { existsSync as
|
|
7840
|
+
import { existsSync as existsSync8, realpathSync } from "fs";
|
|
7563
7841
|
import { join as join8 } from "path";
|
|
7564
7842
|
import { homedir as homedir6, userInfo } from "os";
|
|
7565
7843
|
import { spawn as spawn3 } from "child_process";
|
|
7566
7844
|
|
|
7567
7845
|
// src/lib/watchdog.ts
|
|
7568
|
-
import { readFileSync as
|
|
7846
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, unlinkSync as unlinkSync4, existsSync as existsSync7, mkdirSync as mkdirSync6, openSync, closeSync, chmodSync as chmodSync5 } from "fs";
|
|
7569
7847
|
import { join as join7 } from "path";
|
|
7570
7848
|
import { spawn as spawn2, execFileSync } from "child_process";
|
|
7571
7849
|
var DEFAULT_CONFIG_DIR = join7(process.env["HOME"] ?? "/tmp", ".augmented");
|
|
@@ -7577,17 +7855,17 @@ function getManagerPaths(configDir) {
|
|
|
7577
7855
|
};
|
|
7578
7856
|
}
|
|
7579
7857
|
function ensureDir2(configDir) {
|
|
7580
|
-
if (!
|
|
7858
|
+
if (!existsSync7(configDir)) {
|
|
7581
7859
|
mkdirSync6(configDir, { recursive: true });
|
|
7582
7860
|
}
|
|
7583
7861
|
}
|
|
7584
7862
|
function writePidFile(configDir, pid) {
|
|
7585
7863
|
ensureDir2(configDir);
|
|
7586
|
-
|
|
7864
|
+
writeFileSync7(getManagerPaths(configDir).pidFile, String(pid), { mode: 384 });
|
|
7587
7865
|
}
|
|
7588
7866
|
function readPidFile(configDir) {
|
|
7589
7867
|
try {
|
|
7590
|
-
const raw =
|
|
7868
|
+
const raw = readFileSync7(getManagerPaths(configDir).pidFile, "utf-8").trim();
|
|
7591
7869
|
const pid = parseInt(raw, 10);
|
|
7592
7870
|
return isNaN(pid) ? null : pid;
|
|
7593
7871
|
} catch {
|
|
@@ -7596,7 +7874,7 @@ function readPidFile(configDir) {
|
|
|
7596
7874
|
}
|
|
7597
7875
|
function removePidFile(configDir) {
|
|
7598
7876
|
try {
|
|
7599
|
-
|
|
7877
|
+
unlinkSync4(getManagerPaths(configDir).pidFile);
|
|
7600
7878
|
} catch {
|
|
7601
7879
|
}
|
|
7602
7880
|
}
|
|
@@ -7625,7 +7903,7 @@ function defaultPgrep() {
|
|
|
7625
7903
|
}
|
|
7626
7904
|
function readStateFile(configDir) {
|
|
7627
7905
|
try {
|
|
7628
|
-
const raw =
|
|
7906
|
+
const raw = readFileSync7(getManagerPaths(configDir).stateFile, "utf-8");
|
|
7629
7907
|
return JSON.parse(raw);
|
|
7630
7908
|
} catch {
|
|
7631
7909
|
return null;
|
|
@@ -7633,7 +7911,7 @@ function readStateFile(configDir) {
|
|
|
7633
7911
|
}
|
|
7634
7912
|
function removeStateFile(configDir) {
|
|
7635
7913
|
try {
|
|
7636
|
-
|
|
7914
|
+
unlinkSync4(getManagerPaths(configDir).stateFile);
|
|
7637
7915
|
} catch {
|
|
7638
7916
|
}
|
|
7639
7917
|
}
|
|
@@ -7681,7 +7959,7 @@ function startWatchdog(opts) {
|
|
|
7681
7959
|
const deadline = Date.now() + 5e3;
|
|
7682
7960
|
const sleepBuf = new Int32Array(new SharedArrayBuffer(4));
|
|
7683
7961
|
while (Date.now() < deadline) {
|
|
7684
|
-
if (
|
|
7962
|
+
if (existsSync7(pidFile)) {
|
|
7685
7963
|
return { pid: child.pid };
|
|
7686
7964
|
}
|
|
7687
7965
|
if (child.exitCode !== null) {
|
|
@@ -8005,7 +8283,7 @@ function resolveStableAgtBin(rawPath) {
|
|
|
8005
8283
|
if (!prefix || !formula) return rawPath;
|
|
8006
8284
|
const candidates = [`${prefix}/bin/${formula}`, `${prefix}/bin/agt`];
|
|
8007
8285
|
for (const candidate of candidates) {
|
|
8008
|
-
if (!
|
|
8286
|
+
if (!existsSync8(candidate)) continue;
|
|
8009
8287
|
try {
|
|
8010
8288
|
realpathSync(candidate);
|
|
8011
8289
|
return candidate;
|
|
@@ -8236,4 +8514,4 @@ export {
|
|
|
8236
8514
|
managerInstallSystemUnitCommand,
|
|
8237
8515
|
managerUninstallSystemUnitCommand
|
|
8238
8516
|
};
|
|
8239
|
-
//# sourceMappingURL=chunk-
|
|
8517
|
+
//# sourceMappingURL=chunk-DVWBVANP.js.map
|