agent-trellis 0.7.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -153
- package/dist/adapters/claude-code.js +3 -2
- package/dist/adapters/codex.js +3 -2
- package/dist/adapters/jsonMcp.d.ts +3 -1
- package/dist/adapters/jsonMcp.js +18 -4
- package/dist/adapters/kimi-code.d.ts +21 -0
- package/dist/adapters/kimi-code.js +107 -0
- package/dist/adapters/kiro.js +3 -2
- package/dist/adapters/mcpPlan.d.ts +6 -1
- package/dist/adapters/mcpPlan.js +106 -8
- package/dist/adapters/pi.js +22 -3
- package/dist/adapters/symlinkPlan.d.ts +7 -0
- package/dist/adapters/symlinkPlan.js +16 -7
- package/dist/adapters/zcode.d.ts +21 -0
- package/dist/adapters/zcode.js +234 -0
- package/dist/cli.js +145 -29
- package/dist/commands/doctor.d.ts +7 -2
- package/dist/commands/doctor.js +40 -2
- package/dist/commands/init.d.ts +4 -2
- package/dist/commands/init.js +29 -13
- package/dist/commands/kimi.d.ts +16 -0
- package/dist/commands/kimi.js +64 -0
- package/dist/commands/manage.d.ts +39 -0
- package/dist/commands/manage.js +126 -0
- package/dist/commands/mcp.d.ts +77 -14
- package/dist/commands/mcp.js +169 -29
- package/dist/commands/mcpGateway.d.ts +6 -0
- package/dist/commands/mcpGateway.js +35 -14
- package/dist/commands/mcpImport.d.ts +46 -0
- package/dist/commands/mcpImport.js +359 -0
- package/dist/commands/memory.d.ts +17 -3
- package/dist/commands/memory.js +27 -8
- package/dist/commands/migrate.d.ts +16 -5
- package/dist/commands/migrate.js +93 -17
- package/dist/commands/onboard.d.ts +74 -2
- package/dist/commands/onboard.js +469 -71
- package/dist/commands/rollback.js +28 -2
- package/dist/commands/secretsAudit.js +4 -1
- package/dist/commands/skill.d.ts +52 -6
- package/dist/commands/skill.js +114 -15
- package/dist/commands/sync.js +5 -1
- package/dist/core/adapter.d.ts +11 -1
- package/dist/core/canonical.d.ts +15 -7
- package/dist/core/canonical.js +101 -13
- package/dist/core/capabilitySelection.d.ts +45 -0
- package/dist/core/capabilitySelection.js +124 -0
- package/dist/core/types.d.ts +25 -2
- package/dist/core/types.js +8 -0
- package/dist/lib/agentBridge.d.ts +169 -0
- package/dist/lib/agentBridge.js +367 -0
- package/dist/lib/agentBridgeProvider.d.ts +14 -0
- package/dist/lib/agentBridgeProvider.js +95 -0
- package/dist/lib/backup.d.ts +32 -0
- package/dist/lib/backup.js +20 -1
- package/dist/lib/builtinSkills.d.ts +2 -0
- package/dist/lib/builtinSkills.js +4 -0
- package/dist/lib/chatAgents.d.ts +42 -0
- package/dist/lib/chatAgents.js +59 -0
- package/dist/lib/cliMetadata.d.ts +1 -0
- package/dist/lib/cliMetadata.js +14 -0
- package/dist/lib/envVarNames.d.ts +3 -0
- package/dist/lib/envVarNames.js +19 -0
- package/dist/lib/gatewayBackend.d.ts +28 -0
- package/dist/lib/gatewayBackend.js +72 -1
- package/dist/lib/installAgent.d.ts +7 -5
- package/dist/lib/installAgent.js +4 -3
- package/dist/lib/mcpConnect.js +5 -1
- package/dist/lib/mcpMigrateRead.d.ts +2 -0
- package/dist/lib/mcpMigrateRead.js +22 -1
- package/dist/lib/mcpRuntime.d.ts +46 -0
- package/dist/lib/mcpRuntime.js +185 -0
- package/dist/lib/mcpStatusProvider.d.ts +10 -0
- package/dist/lib/mcpStatusProvider.js +25 -0
- package/dist/lib/mcpToolRegistry.d.ts +18 -0
- package/dist/lib/mcpToolRegistry.js +107 -14
- package/dist/lib/memoryGraph.d.ts +1 -1
- package/dist/lib/memoryGraph.js +9 -3
- package/dist/lib/memoryProvider.d.ts +58 -0
- package/dist/lib/memoryProvider.js +175 -0
- package/dist/lib/memoryStatus.d.ts +17 -0
- package/dist/lib/memoryStatus.js +88 -0
- package/dist/lib/nativeMemory.d.ts +19 -0
- package/dist/lib/nativeMemory.js +129 -0
- package/dist/lib/realHomeSnapshot.js +5 -0
- package/dist/lib/runtimeControlProvider.d.ts +16 -0
- package/dist/lib/runtimeControlProvider.js +170 -0
- package/dist/lib/secretEnv.d.ts +2 -1
- package/dist/lib/secretEnv.js +6 -2
- package/dist/lib/skillProvider.d.ts +13 -0
- package/dist/lib/skillProvider.js +210 -0
- package/dist/lib/taskProvider.d.ts +7 -0
- package/dist/lib/taskProvider.js +43 -0
- package/dist/lib/taskStore.d.ts +46 -0
- package/dist/lib/taskStore.js +156 -0
- package/dist/lib/terminalPicker.d.ts +23 -49
- package/dist/lib/terminalPicker.js +80 -218
- package/dist/lib/zcodeOwnership.d.ts +17 -0
- package/dist/lib/zcodeOwnership.js +37 -0
- package/dist/pi-bridge/bundle.js +476 -37
- package/dist/pi-bridge/index.js +42 -21
- package/dist/pi-bridge/schemaTranslate.d.ts +4 -8
- package/dist/pi-bridge/schemaTranslate.js +4 -8
- package/dist/probes/codex.d.ts +7 -0
- package/dist/probes/codex.js +37 -5
- package/dist/probes/kimi-code.d.ts +12 -0
- package/dist/probes/kimi-code.js +55 -0
- package/dist/probes/zcode.d.ts +32 -0
- package/dist/probes/zcode.js +140 -0
- package/dist/sdk.d.ts +1 -1
- package/docs/architecture.md +230 -28
- package/docs/assets/brand-v3/trellis-mark-v3-a.png +0 -0
- package/docs/assets/brand-v3/trellis-mark-v3-a.svg +10 -0
- package/docs/assets/poster-series-v3/README.md +60 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-en.svg +51 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-horizontal-zh.svg +51 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-en.svg +48 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-memory-zh.svg +48 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-en.svg +56 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-migrate-zh.svg +56 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-en.svg +47 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-switch-zh.svg +47 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-en.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-en.svg +51 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.png +0 -0
- package/docs/assets/poster-series-v3/agent-trellis-poster-v3-unified-zh.svg +51 -0
- package/docs/getting-started.md +496 -42
- package/docs/overview.md +134 -0
- package/docs/overview.zh-CN.md +102 -0
- package/docs/research.md +59 -0
- package/docs/roadmap.md +11 -6
- package/docs/video/README.md +76 -0
- package/docs/video/build/audio/01-opening.aiff +0 -0
- package/docs/video/build/audio/01-opening.mp3 +0 -0
- package/docs/video/build/audio/02-pain.aiff +0 -0
- package/docs/video/build/audio/02-pain.mp3 +0 -0
- package/docs/video/build/audio/03-solution.aiff +0 -0
- package/docs/video/build/audio/03-solution.mp3 +0 -0
- package/docs/video/build/audio/04-install.aiff +0 -0
- package/docs/video/build/audio/04-install.mp3 +0 -0
- package/docs/video/build/audio/04-setup.mp3 +0 -0
- package/docs/video/build/audio/05-dryrun.mp3 +0 -0
- package/docs/video/build/audio/05-init.aiff +0 -0
- package/docs/video/build/audio/05-init.mp3 +0 -0
- package/docs/video/build/audio/05-interactive.mp3 +0 -0
- package/docs/video/build/audio/06-dryrun.aiff +0 -0
- package/docs/video/build/audio/06-dryrun.mp3 +0 -0
- package/docs/video/build/audio/06-onboard.mp3 +0 -0
- package/docs/video/build/audio/06-run.mp3 +0 -0
- package/docs/video/build/audio/07-onboard.aiff +0 -0
- package/docs/video/build/audio/07-onboard.mp3 +0 -0
- package/docs/video/build/audio/07-verify.mp3 +0 -0
- package/docs/video/build/audio/08-closing.mp3 +0 -0
- package/docs/video/build/audio/08-doctor.aiff +0 -0
- package/docs/video/build/audio/08-doctor.mp3 +0 -0
- package/docs/video/build/audio/09-rollback.aiff +0 -0
- package/docs/video/build/audio/09-rollback.mp3 +0 -0
- package/docs/video/build/audio/10-principles.aiff +0 -0
- package/docs/video/build/audio/10-principles.mp3 +0 -0
- package/docs/video/build/audio/11-closing.aiff +0 -0
- package/docs/video/build/audio/11-closing.mp3 +0 -0
- package/docs/video/build/frames/01-opening-0.png +0 -0
- package/docs/video/build/frames/02-pain-1.png +0 -0
- package/docs/video/build/frames/02-pain-2.png +0 -0
- package/docs/video/build/frames/03-solution-3.png +0 -0
- package/docs/video/build/frames/04-install-4.png +0 -0
- package/docs/video/build/frames/04-setup-4.png +0 -0
- package/docs/video/build/frames/04-setup-5.png +0 -0
- package/docs/video/build/frames/05-dryrun-6.png +0 -0
- package/docs/video/build/frames/05-init-5.png +0 -0
- package/docs/video/build/frames/05-interactive-5.png +0 -0
- package/docs/video/build/frames/05-interactive-6.png +0 -0
- package/docs/video/build/frames/06-dryrun-6.png +0 -0
- package/docs/video/build/frames/06-dryrun-7.png +0 -0
- package/docs/video/build/frames/06-onboard-7.png +0 -0
- package/docs/video/build/frames/06-onboard-8.png +0 -0
- package/docs/video/build/frames/06-run-7.png +0 -0
- package/docs/video/build/frames/06-run-8.png +0 -0
- package/docs/video/build/frames/07-onboard-10.png +0 -0
- package/docs/video/build/frames/07-onboard-7.png +0 -0
- package/docs/video/build/frames/07-onboard-8.png +0 -0
- package/docs/video/build/frames/07-onboard-9.png +0 -0
- package/docs/video/build/frames/07-verify-10.png +0 -0
- package/docs/video/build/frames/07-verify-8.png +0 -0
- package/docs/video/build/frames/07-verify-9.png +0 -0
- package/docs/video/build/frames/08-closing-10.png +0 -0
- package/docs/video/build/frames/08-closing-11.png +0 -0
- package/docs/video/build/frames/08-doctor-11.png +0 -0
- package/docs/video/build/frames/08-doctor-9.png +0 -0
- package/docs/video/build/frames/09-rollback-10.png +0 -0
- package/docs/video/build/frames/09-rollback-12.png +0 -0
- package/docs/video/build/frames/10-principles-11.png +0 -0
- package/docs/video/build/frames/10-principles-13.png +0 -0
- package/docs/video/build/frames/11-closing-12.png +0 -0
- package/docs/video/build/frames/11-closing-14.png +0 -0
- package/docs/video/build/segments/01-opening.mp4 +0 -0
- package/docs/video/build/segments/01-opening.txt +3 -0
- package/docs/video/build/segments/02-pain.mp4 +0 -0
- package/docs/video/build/segments/02-pain.txt +5 -0
- package/docs/video/build/segments/03-solution.mp4 +0 -0
- package/docs/video/build/segments/03-solution.txt +3 -0
- package/docs/video/build/segments/04-install.mp4 +0 -0
- package/docs/video/build/segments/04-install.txt +3 -0
- package/docs/video/build/segments/04-setup.mp4 +0 -0
- package/docs/video/build/segments/04-setup.txt +3 -0
- package/docs/video/build/segments/05-dryrun.mp4 +0 -0
- package/docs/video/build/segments/05-dryrun.txt +3 -0
- package/docs/video/build/segments/05-init.mp4 +0 -0
- package/docs/video/build/segments/05-init.txt +3 -0
- package/docs/video/build/segments/05-interactive.mp4 +0 -0
- package/docs/video/build/segments/05-interactive.txt +5 -0
- package/docs/video/build/segments/06-dryrun.mp4 +0 -0
- package/docs/video/build/segments/06-dryrun.txt +3 -0
- package/docs/video/build/segments/06-onboard.mp4 +0 -0
- package/docs/video/build/segments/06-onboard.txt +5 -0
- package/docs/video/build/segments/06-run.mp4 +0 -0
- package/docs/video/build/segments/06-run.txt +3 -0
- package/docs/video/build/segments/07-onboard.mp4 +0 -0
- package/docs/video/build/segments/07-onboard.txt +5 -0
- package/docs/video/build/segments/07-verify.mp4 +0 -0
- package/docs/video/build/segments/07-verify.txt +5 -0
- package/docs/video/build/segments/08-closing.mp4 +0 -0
- package/docs/video/build/segments/08-closing.txt +3 -0
- package/docs/video/build/segments/08-doctor.mp4 +0 -0
- package/docs/video/build/segments/08-doctor.txt +3 -0
- package/docs/video/build/segments/09-rollback.mp4 +0 -0
- package/docs/video/build/segments/09-rollback.txt +3 -0
- package/docs/video/build/segments/10-principles.mp4 +0 -0
- package/docs/video/build/segments/10-principles.txt +3 -0
- package/docs/video/build/segments/11-closing.mp4 +0 -0
- package/docs/video/build/segments/11-closing.txt +3 -0
- package/docs/video/build/segments/final.txt +8 -0
- package/docs/video/build-ai/audio/01-hook.mp3 +0 -0
- package/docs/video/build-ai/audio/02-pain.mp3 +0 -0
- package/docs/video/build-ai/audio/03-solution.mp3 +0 -0
- package/docs/video/build-ai/audio/04-how.mp3 +0 -0
- package/docs/video/build-ai/audio/05-safe.mp3 +0 -0
- package/docs/video/build-ai/audio/06-closing.mp3 +0 -0
- package/docs/video/build-ai/clips/01-hook.mp4 +0 -0
- package/docs/video/build-ai/clips/02-pain.mp4 +0 -0
- package/docs/video/build-ai/clips/03-solution.mp4 +0 -0
- package/docs/video/build-ai/clips/04-how.mp4 +0 -0
- package/docs/video/build-ai/clips/05-safe.mp4 +0 -0
- package/docs/video/build-ai/clips/06-closing.mp4 +0 -0
- package/docs/video/build-ai/first-frame-02-pain.png +0 -0
- package/docs/video/build-ai/first-frame-03-solution.png +0 -0
- package/docs/video/build-ai/first-frame-04-how.png +0 -0
- package/docs/video/build-ai/first-frame-05-safe.png +0 -0
- package/docs/video/build-ai/segments/01-hook.caption.txt +2 -0
- package/docs/video/build-ai/segments/01-hook.mp4 +0 -0
- package/docs/video/build-ai/segments/02-pain.mp4 +0 -0
- package/docs/video/build-ai/segments/03-solution.mp4 +0 -0
- package/docs/video/build-ai/segments/04-how.mp4 +0 -0
- package/docs/video/build-ai/segments/05-safe.mp4 +0 -0
- package/docs/video/build-ai/segments/06-closing.mp4 +0 -0
- package/docs/video/build-ai/segments/cap-01-hook.png +0 -0
- package/docs/video/build-ai/segments/cap-02-pain.png +0 -0
- package/docs/video/build-ai/segments/cap-03-solution.png +0 -0
- package/docs/video/build-ai/segments/cap-04-how.png +0 -0
- package/docs/video/build-ai/segments/cap-05-safe.png +0 -0
- package/docs/video/build-ai/segments/cap-06-closing.png +0 -0
- package/docs/video/build-ai/segments/final.txt +6 -0
- package/docs/video/build-posters/audio/01-hook.mp3 +0 -0
- package/docs/video/build-posters/audio/02-pain.mp3 +0 -0
- package/docs/video/build-posters/audio/03-solution.mp3 +0 -0
- package/docs/video/build-posters/audio/04-how.mp3 +0 -0
- package/docs/video/build-posters/audio/05-safe.mp3 +0 -0
- package/docs/video/build-posters/audio/06-closing.mp3 +0 -0
- package/docs/video/build-posters/cap-01-hook.png +0 -0
- package/docs/video/build-posters/cap-02-pain.png +0 -0
- package/docs/video/build-posters/cap-03-solution.png +0 -0
- package/docs/video/build-posters/cap-04-how.png +0 -0
- package/docs/video/build-posters/cap-05-safe.png +0 -0
- package/docs/video/build-posters/cap-06-closing.png +0 -0
- package/docs/video/build-posters/card-01-hook.png +0 -0
- package/docs/video/build-posters/card-06-closing.png +0 -0
- package/docs/video/build-posters/segments/01-hook.mp4 +0 -0
- package/docs/video/build-posters/segments/02-pain.mp4 +0 -0
- package/docs/video/build-posters/segments/03-solution.mp4 +0 -0
- package/docs/video/build-posters/segments/04-how.mp4 +0 -0
- package/docs/video/build-posters/segments/05-safe.mp4 +0 -0
- package/docs/video/build-posters/segments/06-closing.mp4 +0 -0
- package/docs/video/build-posters/segments/final.txt +6 -0
- package/docs/video/generate-video-ai.mjs +334 -0
- package/docs/video/generate-video-posters.mjs +204 -0
- package/docs/video/generate-video.mjs +426 -0
- package/docs/video/outline.zh-CN.md +102 -0
- package/docs/video/trellis-demo-video-ai.mp4 +0 -0
- package/docs/video/trellis-demo-video.mp4 +0 -0
- package/docs/video/voiceover.zh-CN.md +49 -0
- package/package.json +6 -2
- package/schema/builtin-skills/trellis-runtime/SKILL.md +117 -0
- package/schema/capability-selection.example.yaml +23 -0
- package/schema/scope.example.yaml +1 -1
- package/schema/servers.example.yaml +15 -1
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* already hold themselves to for every other kind of conflict.
|
|
9
9
|
*/
|
|
10
10
|
import { createHash } from "node:crypto";
|
|
11
|
-
import { existsSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { cpSync, existsSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
12
12
|
import { readlink, rm, symlink } from "node:fs/promises";
|
|
13
13
|
import { homedir } from "node:os";
|
|
14
14
|
import { join } from "node:path";
|
|
@@ -99,6 +99,23 @@ async function planOperation(homeDir, runId, op) {
|
|
|
99
99
|
}
|
|
100
100
|
return { action: "restore", path: op.path, description: `recreate ${op.path} -> ${op.beforeLinkTarget}` };
|
|
101
101
|
}
|
|
102
|
+
// Directory conflict detection is existence-only, not a deep content
|
|
103
|
+
// hash (see BackupOperation's "dir-create"/"dir-remove" doc comment
|
|
104
|
+
// in backup.ts) — a real, documented simplification, not an
|
|
105
|
+
// oversight: something touching a file inside an otherwise-untouched
|
|
106
|
+
// directory won't be caught as a conflict.
|
|
107
|
+
case "dir-create": {
|
|
108
|
+
if (!existsSync(op.path)) {
|
|
109
|
+
return { action: "already-reverted", path: op.path, description: `${op.path} no longer exists — nothing to undo` };
|
|
110
|
+
}
|
|
111
|
+
return { action: "restore", path: op.path, description: `delete ${op.path} (created by this run)` };
|
|
112
|
+
}
|
|
113
|
+
case "dir-remove": {
|
|
114
|
+
if (existsSync(op.path)) {
|
|
115
|
+
return { action: "conflict", path: op.path, description: `${op.path} exists again since this run — left untouched` };
|
|
116
|
+
}
|
|
117
|
+
return { action: "restore", path: op.path, description: `recreate ${op.path} from its content before this run (${join(runDir, op.beforeDir)})` };
|
|
118
|
+
}
|
|
102
119
|
}
|
|
103
120
|
}
|
|
104
121
|
export async function collectRollbackPlan(homeDirInput, runIdInput) {
|
|
@@ -130,11 +147,20 @@ async function restoreOperation(homeDir, runId, op) {
|
|
|
130
147
|
case "symlink-remove":
|
|
131
148
|
await symlink(op.beforeLinkTarget, op.path);
|
|
132
149
|
return;
|
|
150
|
+
case "dir-create":
|
|
151
|
+
rmSync(op.path, { recursive: true, force: true });
|
|
152
|
+
return;
|
|
153
|
+
case "dir-remove":
|
|
154
|
+
cpSync(join(runDir, op.beforeDir), op.path, { recursive: true });
|
|
155
|
+
return;
|
|
133
156
|
}
|
|
134
157
|
}
|
|
135
158
|
export async function applyRollbackPlan(homeDir, runId, manifest, items) {
|
|
136
159
|
const restorePaths = new Set(items.filter((i) => i.action === "restore").map((i) => i.path));
|
|
137
|
-
|
|
160
|
+
// Restore in reverse write order. A single onboarding transaction may
|
|
161
|
+
// update servers.yaml several times (mode, memory, routes); replaying
|
|
162
|
+
// restores forward would leave the file at an intermediate snapshot.
|
|
163
|
+
for (const op of [...manifest.operations].reverse()) {
|
|
138
164
|
if (!restorePaths.has(op.path))
|
|
139
165
|
continue;
|
|
140
166
|
await restoreOperation(homeDir, runId, op);
|
|
@@ -26,7 +26,9 @@ import { loadCanonicalSource } from "../core/canonical.js";
|
|
|
26
26
|
import { ClaudeCodeAdapter } from "../adapters/claude-code.js";
|
|
27
27
|
import { CodexAdapter } from "../adapters/codex.js";
|
|
28
28
|
import { KiroAdapter } from "../adapters/kiro.js";
|
|
29
|
-
import {
|
|
29
|
+
import { ZcodeAdapter } from "../adapters/zcode.js";
|
|
30
|
+
import { declaredEnvNames, extractJsonEnvVarNames, extractTomlEnvVarNames, extractZcodeEnvVarNames } from "../lib/envVarNames.js";
|
|
31
|
+
import { resolveZcodeProfile } from "../probes/zcode.js";
|
|
30
32
|
import { resolveSecretEnv } from "../lib/secretEnv.js";
|
|
31
33
|
/** Only agents in `managedAgents` — a present-but-unmanaged agent's config
|
|
32
34
|
* file is never even read (trellis-managed-agents), same restriction as
|
|
@@ -38,6 +40,7 @@ function auditedAgents(homeDir, managedAgents) {
|
|
|
38
40
|
{ id: "claude-code", probe: () => new ClaudeCodeAdapter(homeDir).probe(), configPath: (h) => join(h, ".claude.json"), extractNames: extractJsonEnvVarNames },
|
|
39
41
|
{ id: "codex", probe: () => new CodexAdapter(homeDir).probe(), configPath: (h) => join(h, ".codex", "config.toml"), extractNames: extractTomlEnvVarNames },
|
|
40
42
|
{ id: "kiro", probe: () => new KiroAdapter(homeDir).probe(), configPath: (h) => join(h, ".kiro", "settings", "mcp.json"), extractNames: extractJsonEnvVarNames },
|
|
43
|
+
{ id: "zcode", probe: () => new ZcodeAdapter(homeDir).probe(), configPath: (h) => resolveZcodeProfile(h)?.configPath ?? join(h, ".zcode", "cli", "config.json"), extractNames: extractZcodeEnvVarNames },
|
|
41
44
|
];
|
|
42
45
|
return all.filter((a) => managedAgents.includes(a.id));
|
|
43
46
|
}
|
package/dist/commands/skill.d.ts
CHANGED
|
@@ -8,6 +8,24 @@
|
|
|
8
8
|
* symlinkPlan.ts`'s pre-existing stale-symlink removal.
|
|
9
9
|
*/
|
|
10
10
|
import type { AgentId } from "../core/types.js";
|
|
11
|
+
import { type BackupSession } from "../lib/backup.js";
|
|
12
|
+
import type { SyncReport } from "./sync.js";
|
|
13
|
+
export type BuiltinSkillUpdateAction = "create" | "update" | "already-current";
|
|
14
|
+
export interface BuiltinSkillUpdatePlan {
|
|
15
|
+
name: "trellis-runtime";
|
|
16
|
+
action: BuiltinSkillUpdateAction;
|
|
17
|
+
detail: string;
|
|
18
|
+
path: string;
|
|
19
|
+
}
|
|
20
|
+
export declare function collectBuiltinSkillUpdatePlan(homeDir?: string): BuiltinSkillUpdatePlan;
|
|
21
|
+
export declare function applyBuiltinSkillUpdatePlan(plan: BuiltinSkillUpdatePlan, backup?: BackupSession): void;
|
|
22
|
+
export declare function runSkillUpdateBuiltin(opts?: {
|
|
23
|
+
homeDir?: string;
|
|
24
|
+
json?: boolean;
|
|
25
|
+
dryRun?: boolean;
|
|
26
|
+
}): {
|
|
27
|
+
exitCode: number;
|
|
28
|
+
};
|
|
11
29
|
export interface SkillListEntry {
|
|
12
30
|
name: string;
|
|
13
31
|
scope: readonly AgentId[];
|
|
@@ -27,25 +45,53 @@ export interface SkillAddPlan {
|
|
|
27
45
|
sourceDir?: string;
|
|
28
46
|
}
|
|
29
47
|
export declare function collectSkillAddPlan(name: string, fromPath: string, homeDir?: string): SkillAddPlan;
|
|
30
|
-
export declare function applySkillAddPlan(plan: SkillAddPlan, homeDir?: string): void;
|
|
48
|
+
export declare function applySkillAddPlan(plan: SkillAddPlan, homeDir?: string, backup?: BackupSession): void;
|
|
49
|
+
export interface SkillAddOutcome {
|
|
50
|
+
plan: SkillAddPlan;
|
|
51
|
+
sync?: SyncReport;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* See `applyMcpAddWithSync`'s doc comment (mcp.ts) — same split, same
|
|
55
|
+
* reason: a non-CLI caller needs the structured result a JSON-mode CLI
|
|
56
|
+
* run prints, without scraping stdout. Also opens its own backup session
|
|
57
|
+
* around the canonical copy-in, for the same reason `applyMcpAddWithSync`
|
|
58
|
+
* does (trellis-gui tasks.md 3.5): this direct write used to be the one
|
|
59
|
+
* path in this file with no backup/rollback trace at all.
|
|
60
|
+
*/
|
|
61
|
+
export declare function applySkillAddWithSync(plan: SkillAddPlan, opts?: {
|
|
62
|
+
homeDir?: string;
|
|
63
|
+
dryRun?: boolean;
|
|
64
|
+
backupSession?: BackupSession;
|
|
65
|
+
}): Promise<SkillAddOutcome>;
|
|
31
66
|
export declare function runSkillAdd(name: string, fromPath: string, opts?: {
|
|
32
67
|
homeDir?: string;
|
|
33
68
|
json?: boolean;
|
|
34
69
|
dryRun?: boolean;
|
|
35
|
-
}): {
|
|
70
|
+
}): Promise<{
|
|
36
71
|
exitCode: number;
|
|
37
|
-
}
|
|
72
|
+
}>;
|
|
38
73
|
export type SkillRemoveAction = "removed" | "not-found";
|
|
39
74
|
export interface SkillRemovePlan {
|
|
40
75
|
name: string;
|
|
41
76
|
action: SkillRemoveAction;
|
|
42
77
|
}
|
|
43
78
|
export declare function collectSkillRemovePlan(name: string, homeDir?: string): SkillRemovePlan;
|
|
44
|
-
export declare function applySkillRemovePlan(plan: SkillRemovePlan, homeDir?: string): void;
|
|
79
|
+
export declare function applySkillRemovePlan(plan: SkillRemovePlan, homeDir?: string, backup?: BackupSession): void;
|
|
80
|
+
export interface SkillRemoveOutcome {
|
|
81
|
+
plan: SkillRemovePlan;
|
|
82
|
+
sync?: SyncReport;
|
|
83
|
+
}
|
|
84
|
+
/** See `applySkillAddWithSync`'s doc comment — same split, same reason,
|
|
85
|
+
* same own-backup-session fix. */
|
|
86
|
+
export declare function applySkillRemoveWithSync(plan: SkillRemovePlan, opts?: {
|
|
87
|
+
homeDir?: string;
|
|
88
|
+
dryRun?: boolean;
|
|
89
|
+
backupSession?: BackupSession;
|
|
90
|
+
}): Promise<SkillRemoveOutcome>;
|
|
45
91
|
export declare function runSkillRemove(name: string, opts?: {
|
|
46
92
|
homeDir?: string;
|
|
47
93
|
json?: boolean;
|
|
48
94
|
dryRun?: boolean;
|
|
49
|
-
}): {
|
|
95
|
+
}): Promise<{
|
|
50
96
|
exitCode: number;
|
|
51
|
-
}
|
|
97
|
+
}>;
|
package/dist/commands/skill.js
CHANGED
|
@@ -7,16 +7,57 @@
|
|
|
7
7
|
* `decideDirImport` (src/lib/dirEquals.ts) and `src/adapters/
|
|
8
8
|
* symlinkPlan.ts`'s pre-existing stale-symlink removal.
|
|
9
9
|
*/
|
|
10
|
-
import { cpSync, existsSync, mkdirSync, rmSync } from "node:fs";
|
|
10
|
+
import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { homedir } from "node:os";
|
|
12
12
|
import { join } from "node:path";
|
|
13
|
+
import { dirname } from "node:path";
|
|
14
|
+
import { fileURLToPath } from "node:url";
|
|
13
15
|
import { decideDirImport } from "../lib/dirEquals.js";
|
|
14
16
|
import { findSkillFile } from "../lib/skillFile.js";
|
|
15
17
|
import { loadCanonicalSource } from "../core/canonical.js";
|
|
16
18
|
import { resolveScope } from "../core/types.js";
|
|
19
|
+
import { isBuiltinSkillName } from "../lib/builtinSkills.js";
|
|
20
|
+
import { openBackupSession } from "../lib/backup.js";
|
|
21
|
+
import { collectSyncReport, printReport as printSyncReport } from "./sync.js";
|
|
22
|
+
function builtinSkillTemplate() {
|
|
23
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
return readFileSync(join(here, "..", "..", "schema", "builtin-skills", "trellis-runtime", "SKILL.md"), "utf8");
|
|
25
|
+
}
|
|
26
|
+
export function collectBuiltinSkillUpdatePlan(homeDir = homedir()) {
|
|
27
|
+
const path = join(homeDir, ".trellis", "skills", "trellis-runtime", "SKILL.md");
|
|
28
|
+
if (!existsSync(path))
|
|
29
|
+
return { name: "trellis-runtime", action: "create", detail: "will install the package-owned Runtime Skill", path };
|
|
30
|
+
if (readFileSync(path, "utf8") === builtinSkillTemplate())
|
|
31
|
+
return { name: "trellis-runtime", action: "already-current", detail: "package-owned Runtime Skill is already current", path };
|
|
32
|
+
return { name: "trellis-runtime", action: "update", detail: "will refresh the package-owned Runtime Skill; existing Agent symlinks will see the update", path };
|
|
33
|
+
}
|
|
34
|
+
export function applyBuiltinSkillUpdatePlan(plan, backup) {
|
|
35
|
+
if (plan.action === "already-current")
|
|
36
|
+
return;
|
|
37
|
+
const content = builtinSkillTemplate();
|
|
38
|
+
mkdirSync(dirname(plan.path), { recursive: true });
|
|
39
|
+
if (backup)
|
|
40
|
+
backup.writeFile(plan.path, content);
|
|
41
|
+
else
|
|
42
|
+
writeFileSync(plan.path, content);
|
|
43
|
+
}
|
|
44
|
+
export function runSkillUpdateBuiltin(opts = {}) {
|
|
45
|
+
const homeDir = opts.homeDir ?? homedir();
|
|
46
|
+
const plan = collectBuiltinSkillUpdatePlan(homeDir);
|
|
47
|
+
if (!opts.dryRun && plan.action !== "already-current") {
|
|
48
|
+
const backup = openBackupSession(homeDir, "skill-update-builtin");
|
|
49
|
+
applyBuiltinSkillUpdatePlan(plan, backup);
|
|
50
|
+
backup.finalize();
|
|
51
|
+
}
|
|
52
|
+
if (opts.json)
|
|
53
|
+
console.log(JSON.stringify(plan, null, 2));
|
|
54
|
+
else
|
|
55
|
+
console.log(`${opts.dryRun ? "[dry run] " : ""}skill update-builtin\n [${plan.action}] ${plan.detail}`);
|
|
56
|
+
return { exitCode: 0 };
|
|
57
|
+
}
|
|
17
58
|
export function collectSkillList(homeDir = homedir()) {
|
|
18
59
|
const canonical = loadCanonicalSource(homeDir);
|
|
19
|
-
return canonical.skills.map((skill) => ({
|
|
60
|
+
return canonical.skills.filter((skill) => !isBuiltinSkillName(skill.name)).map((skill) => ({
|
|
20
61
|
name: skill.name,
|
|
21
62
|
scope: resolveScope(skill.scope, canonical.managedAgents),
|
|
22
63
|
}));
|
|
@@ -37,6 +78,9 @@ export function runSkillList(opts = {}) {
|
|
|
37
78
|
return { exitCode: 0 };
|
|
38
79
|
}
|
|
39
80
|
export function collectSkillAddPlan(name, fromPath, homeDir = homedir()) {
|
|
81
|
+
if (isBuiltinSkillName(name)) {
|
|
82
|
+
return { name, action: "conflict", detail: `"${name}" is a Trellis package-owned Skill and cannot be replaced with skill add` };
|
|
83
|
+
}
|
|
40
84
|
const skillFile = findSkillFile(fromPath);
|
|
41
85
|
if (!skillFile) {
|
|
42
86
|
return { name, action: "invalid-source", detail: `${fromPath} has no SKILL.md` };
|
|
@@ -54,51 +98,106 @@ export function collectSkillAddPlan(name, fromPath, homeDir = homedir()) {
|
|
|
54
98
|
return { name, action: "conflict", detail: `canonical skills/${name}/ already exists with different content — resolve by hand` };
|
|
55
99
|
}
|
|
56
100
|
}
|
|
57
|
-
export function applySkillAddPlan(plan, homeDir = homedir()) {
|
|
101
|
+
export function applySkillAddPlan(plan, homeDir = homedir(), backup) {
|
|
58
102
|
if (plan.action !== "create" || !plan.sourceDir)
|
|
59
103
|
return;
|
|
60
104
|
const dest = join(homeDir, ".trellis", "skills", plan.name);
|
|
105
|
+
if (backup) {
|
|
106
|
+
backup.createDirFromSource(dest, plan.sourceDir);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
61
109
|
mkdirSync(dest, { recursive: true });
|
|
62
110
|
cpSync(plan.sourceDir, dest, { recursive: true });
|
|
63
111
|
}
|
|
64
|
-
|
|
112
|
+
/**
|
|
113
|
+
* See `applyMcpAddWithSync`'s doc comment (mcp.ts) — same split, same
|
|
114
|
+
* reason: a non-CLI caller needs the structured result a JSON-mode CLI
|
|
115
|
+
* run prints, without scraping stdout. Also opens its own backup session
|
|
116
|
+
* around the canonical copy-in, for the same reason `applyMcpAddWithSync`
|
|
117
|
+
* does (trellis-gui tasks.md 3.5): this direct write used to be the one
|
|
118
|
+
* path in this file with no backup/rollback trace at all.
|
|
119
|
+
*/
|
|
120
|
+
export async function applySkillAddWithSync(plan, opts = {}) {
|
|
65
121
|
const homeDir = opts.homeDir ?? homedir();
|
|
66
|
-
const
|
|
122
|
+
const ownSession = !opts.dryRun && !opts.backupSession && plan.action === "create" ? openBackupSession(homeDir, "skill-add") : undefined;
|
|
123
|
+
const session = opts.backupSession ?? ownSession;
|
|
67
124
|
if (!opts.dryRun && plan.action === "create") {
|
|
68
|
-
applySkillAddPlan(plan, homeDir);
|
|
125
|
+
applySkillAddPlan(plan, homeDir, session);
|
|
126
|
+
}
|
|
127
|
+
ownSession?.finalize();
|
|
128
|
+
const failed = plan.action === "conflict" || plan.action === "invalid-source";
|
|
129
|
+
let syncReport;
|
|
130
|
+
if (!failed && plan.action === "create" && existsSync(join(homeDir, ".trellis"))) {
|
|
131
|
+
syncReport = await collectSyncReport({ target: "skills", homeDir, dryRun: opts.dryRun });
|
|
69
132
|
}
|
|
133
|
+
return { plan, ...(syncReport ? { sync: syncReport } : {}) };
|
|
134
|
+
}
|
|
135
|
+
export async function runSkillAdd(name, fromPath, opts = {}) {
|
|
136
|
+
const homeDir = opts.homeDir ?? homedir();
|
|
137
|
+
const plan = collectSkillAddPlan(name, fromPath, homeDir);
|
|
138
|
+
const { sync: syncReport } = await applySkillAddWithSync(plan, { homeDir, dryRun: opts.dryRun });
|
|
139
|
+
const failed = plan.action === "conflict" || plan.action === "invalid-source";
|
|
70
140
|
if (opts.json) {
|
|
71
|
-
console.log(JSON.stringify(plan, null, 2));
|
|
141
|
+
console.log(JSON.stringify(syncReport ? { ...plan, sync: syncReport } : plan, null, 2));
|
|
72
142
|
}
|
|
73
143
|
else {
|
|
74
144
|
console.log(`${opts.dryRun ? "[dry run] " : ""}skill add ${name}`);
|
|
75
145
|
console.log(` [${plan.action}] ${plan.detail}`);
|
|
146
|
+
if (syncReport)
|
|
147
|
+
printSyncReport(syncReport, opts.dryRun ?? false);
|
|
76
148
|
}
|
|
77
|
-
|
|
149
|
+
const syncConflict = syncReport?.reports.some((r) => r.items.some((i) => i.action === "conflict")) ?? false;
|
|
150
|
+
return { exitCode: failed || syncConflict ? 1 : 0 };
|
|
78
151
|
}
|
|
79
152
|
export function collectSkillRemovePlan(name, homeDir = homedir()) {
|
|
153
|
+
if (isBuiltinSkillName(name))
|
|
154
|
+
return { name, action: "not-found" };
|
|
80
155
|
const dir = join(homeDir, ".trellis", "skills", name);
|
|
81
156
|
return { name, action: existsSync(dir) ? "removed" : "not-found" };
|
|
82
157
|
}
|
|
83
|
-
export function applySkillRemovePlan(plan, homeDir = homedir()) {
|
|
158
|
+
export function applySkillRemovePlan(plan, homeDir = homedir(), backup) {
|
|
84
159
|
if (plan.action !== "removed")
|
|
85
160
|
return;
|
|
86
|
-
|
|
161
|
+
const dir = join(homeDir, ".trellis", "skills", plan.name);
|
|
162
|
+
if (backup) {
|
|
163
|
+
backup.removeDir(dir);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
rmSync(dir, { recursive: true, force: true });
|
|
87
167
|
}
|
|
88
|
-
|
|
168
|
+
/** See `applySkillAddWithSync`'s doc comment — same split, same reason,
|
|
169
|
+
* same own-backup-session fix. */
|
|
170
|
+
export async function applySkillRemoveWithSync(plan, opts = {}) {
|
|
89
171
|
const homeDir = opts.homeDir ?? homedir();
|
|
90
|
-
const
|
|
172
|
+
const ownSession = !opts.dryRun && !opts.backupSession && plan.action === "removed" ? openBackupSession(homeDir, "skill-remove") : undefined;
|
|
173
|
+
const session = opts.backupSession ?? ownSession;
|
|
91
174
|
if (!opts.dryRun) {
|
|
92
|
-
applySkillRemovePlan(plan, homeDir);
|
|
175
|
+
applySkillRemovePlan(plan, homeDir, session);
|
|
93
176
|
}
|
|
177
|
+
ownSession?.finalize();
|
|
178
|
+
const failed = plan.action === "not-found";
|
|
179
|
+
let syncReport;
|
|
180
|
+
if (!failed && existsSync(join(homeDir, ".trellis"))) {
|
|
181
|
+
syncReport = await collectSyncReport({ target: "skills", homeDir, dryRun: opts.dryRun });
|
|
182
|
+
}
|
|
183
|
+
return { plan, ...(syncReport ? { sync: syncReport } : {}) };
|
|
184
|
+
}
|
|
185
|
+
export async function runSkillRemove(name, opts = {}) {
|
|
186
|
+
const homeDir = opts.homeDir ?? homedir();
|
|
187
|
+
const plan = collectSkillRemovePlan(name, homeDir);
|
|
188
|
+
const { sync: syncReport } = await applySkillRemoveWithSync(plan, { homeDir, dryRun: opts.dryRun });
|
|
189
|
+
const failed = plan.action === "not-found";
|
|
94
190
|
if (opts.json) {
|
|
95
|
-
console.log(JSON.stringify(plan, null, 2));
|
|
191
|
+
console.log(JSON.stringify(syncReport ? { ...plan, sync: syncReport } : plan, null, 2));
|
|
96
192
|
}
|
|
97
193
|
else if (plan.action === "not-found") {
|
|
98
194
|
console.error(`"${name}" is not a canonical skill — nothing to remove.`);
|
|
99
195
|
}
|
|
100
196
|
else {
|
|
101
197
|
console.log(`${opts.dryRun ? "[dry run] " : ""}removed skill "${name}" from canonical source.`);
|
|
198
|
+
if (syncReport)
|
|
199
|
+
printSyncReport(syncReport, opts.dryRun ?? false);
|
|
102
200
|
}
|
|
103
|
-
|
|
201
|
+
const syncConflict = syncReport?.reports.some((r) => r.items.some((i) => i.action === "conflict")) ?? false;
|
|
202
|
+
return { exitCode: failed || syncConflict ? 1 : 0 };
|
|
104
203
|
}
|
package/dist/commands/sync.js
CHANGED
|
@@ -11,12 +11,16 @@ import { ClaudeCodeAdapter } from "../adapters/claude-code.js";
|
|
|
11
11
|
import { CodexAdapter } from "../adapters/codex.js";
|
|
12
12
|
import { KiroAdapter } from "../adapters/kiro.js";
|
|
13
13
|
import { PiAdapter } from "../adapters/pi.js";
|
|
14
|
+
import { KimiCodeAdapter } from "../adapters/kimi-code.js";
|
|
15
|
+
import { ZcodeAdapter } from "../adapters/zcode.js";
|
|
14
16
|
import { openBackupSession } from "../lib/backup.js";
|
|
15
17
|
const ADAPTER_FACTORY = {
|
|
16
18
|
"claude-code": (homeDir) => new ClaudeCodeAdapter(homeDir),
|
|
17
19
|
codex: (homeDir) => new CodexAdapter(homeDir),
|
|
18
20
|
kiro: (homeDir) => new KiroAdapter(homeDir),
|
|
19
21
|
pi: (homeDir) => new PiAdapter(homeDir),
|
|
22
|
+
"kimi-code": (homeDir) => new KimiCodeAdapter(homeDir),
|
|
23
|
+
zcode: (homeDir) => new ZcodeAdapter(homeDir),
|
|
20
24
|
};
|
|
21
25
|
/** Only agents in `canonical.managedAgents` — an agent present on this
|
|
22
26
|
* machine but not managed gets no adapter at all, not a zero-item plan
|
|
@@ -58,7 +62,7 @@ export async function collectSyncReport(opts = {}) {
|
|
|
58
62
|
// out (found via the sandbox: every agent reported "already in
|
|
59
63
|
// sync" even with real create items pending).
|
|
60
64
|
const kind = opts.target === "skills" ? "skill" : "instructions";
|
|
61
|
-
items = items.filter((item) => item.kind === kind);
|
|
65
|
+
items = items.filter((item) => item.kind === kind || (kind === "skill" && item.kind === "zcode-skill-control"));
|
|
62
66
|
}
|
|
63
67
|
if (!opts.dryRun) {
|
|
64
68
|
await adapter.apply(items, backup);
|
package/dist/core/adapter.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export interface AdapterPlanItem {
|
|
|
46
46
|
* a completely different target file and merge mechanism (see
|
|
47
47
|
* `approvedEnvVars` below) from `"mcp"`, not something the other
|
|
48
48
|
* three agents have an equivalent of. */
|
|
49
|
-
kind: "skill" | "instructions" | "mcp" | "extension" | "kiro-approved-env-vars";
|
|
49
|
+
kind: "skill" | "instructions" | "mcp" | "extension" | "kiro-approved-env-vars" | "zcode-skill-control";
|
|
50
50
|
/** Human-readable description of one change this adapter would make
|
|
51
51
|
* ("create" / "remove") or why it refused to ("conflict"). */
|
|
52
52
|
description: string;
|
|
@@ -88,6 +88,16 @@ export interface AdapterPlanItem {
|
|
|
88
88
|
* for Kiro, never a subtraction (trellis-kiro-approved-env-vars
|
|
89
89
|
* design.md D3/D4). */
|
|
90
90
|
approvedEnvVars?: string[];
|
|
91
|
+
/** ZCode Runtime-only isolation. `null` means the previous profile did
|
|
92
|
+
* not declare the value and restoration must remove the property. */
|
|
93
|
+
zcodeSkillControls?: {
|
|
94
|
+
featuresSkill: boolean | null;
|
|
95
|
+
skillsEnabled: boolean | null;
|
|
96
|
+
previous?: {
|
|
97
|
+
featuresSkill: boolean | null;
|
|
98
|
+
skillsEnabled: boolean | null;
|
|
99
|
+
};
|
|
100
|
+
};
|
|
91
101
|
}
|
|
92
102
|
export interface AdapterVerifyResult {
|
|
93
103
|
ok: boolean;
|
package/dist/core/canonical.d.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* workspace scope"). See openspec/changes/trellis-sync-p1/specs/
|
|
5
5
|
* canonical-source-loading/spec.md for the exact contract this implements.
|
|
6
6
|
*/
|
|
7
|
-
import type { AgentId, CanonicalSource, McpServerDef } from "./types.js";
|
|
7
|
+
import type { AgentId, CapabilityDelivery, CanonicalSource, McpRoute, McpServerDef } from "./types.js";
|
|
8
|
+
import type { BackupSession } from "../lib/backup.js";
|
|
8
9
|
/**
|
|
9
10
|
* The on-disk shape for one server entry — `static_env`/`env_aliases`
|
|
10
11
|
* (snake_case, like every other multi-word key across `.trellis/*.yaml`)
|
|
@@ -27,10 +28,10 @@ export type ServersYamlWriteResult = {
|
|
|
27
28
|
ok: false;
|
|
28
29
|
error: string;
|
|
29
30
|
};
|
|
30
|
-
export declare function upsertServerYaml(path: string, name: string, def: McpServerDef): ServersYamlWriteResult;
|
|
31
|
+
export declare function upsertServerYaml(path: string, name: string, def: McpServerDef, backup?: BackupSession): ServersYamlWriteResult;
|
|
31
32
|
/** Inverse of `upsertServerYaml` — same preservation guarantee, same
|
|
32
33
|
* refusal posture on a missing/unparseable file. */
|
|
33
|
-
export declare function removeServerYaml(path: string, name: string): ServersYamlWriteResult;
|
|
34
|
+
export declare function removeServerYaml(path: string, name: string, backup?: BackupSession): ServersYamlWriteResult;
|
|
34
35
|
/**
|
|
35
36
|
* `trellis onboard --mcp-mode <value>` (trellis-onboard-mcp-mode) —
|
|
36
37
|
* everything needed to select or clear the top-level `hub`/`gateway`
|
|
@@ -56,7 +57,14 @@ export type McpMode = {
|
|
|
56
57
|
* starter file). Selecting one mode always clears the other two
|
|
57
58
|
* (design.md D3) — never left for the caller to remember.
|
|
58
59
|
*/
|
|
59
|
-
export declare function writeMcpModeYaml(path: string, mode: McpMode): ServersYamlWriteResult;
|
|
60
|
+
export declare function writeMcpModeYaml(path: string, mode: McpMode, backup?: BackupSession): ServersYamlWriteResult;
|
|
61
|
+
export type McpRoutesWriteResult = ServersYamlWriteResult;
|
|
62
|
+
/** Writes explicit per-agent routes while preserving legacy hub/gateway
|
|
63
|
+
* shorthand. An empty route map removes the optional key. */
|
|
64
|
+
export declare function writeMcpRoutesYaml(path: string, routes: Partial<Record<AgentId, McpRoute>>, backup?: BackupSession): McpRoutesWriteResult;
|
|
65
|
+
/** Writes per-agent capability delivery preferences into servers.yaml.
|
|
66
|
+
* Omitted entries continue to use the native default. */
|
|
67
|
+
export declare function writeMcpRuntimeDeliveryYaml(path: string, delivery: Partial<Record<AgentId, CapabilityDelivery>>, backup?: BackupSession): ServersYamlWriteResult;
|
|
60
68
|
export type SecretsPolicyWriteResult = {
|
|
61
69
|
ok: true;
|
|
62
70
|
} | {
|
|
@@ -78,7 +86,7 @@ export type SecretsPolicyWriteResult = {
|
|
|
78
86
|
export declare function writeSecretsPolicyExtraction(path: string, extraction: {
|
|
79
87
|
varName: string;
|
|
80
88
|
envFilePath: string;
|
|
81
|
-
}): SecretsPolicyWriteResult;
|
|
89
|
+
}, backup?: BackupSession): SecretsPolicyWriteResult;
|
|
82
90
|
/**
|
|
83
91
|
* Ensures one exact line is present in a `.gitignore` file, creating the
|
|
84
92
|
* file if it doesn't exist yet — idempotent (a no-op if the line is
|
|
@@ -89,7 +97,7 @@ export declare function writeSecretsPolicyExtraction(path: string, extraction: {
|
|
|
89
97
|
* init`'s own bootstrap, so a machine that never extracts a secret never
|
|
90
98
|
* gains this file at all.
|
|
91
99
|
*/
|
|
92
|
-
export declare function ensureGitignoreEntry(gitignorePath: string, line: string): void;
|
|
100
|
+
export declare function ensureGitignoreEntry(gitignorePath: string, line: string, backup?: BackupSession): void;
|
|
93
101
|
/**
|
|
94
102
|
* Ensures a shell rc file sources the local secrets env file on every new
|
|
95
103
|
* shell — one generic pointer block, appended once, idempotent (detected
|
|
@@ -102,7 +110,7 @@ export declare function ensureGitignoreEntry(gitignorePath: string, line: string
|
|
|
102
110
|
* lines `parseDotenv` already expects, so that format never needs an
|
|
103
111
|
* `export` prefix of its own.
|
|
104
112
|
*/
|
|
105
|
-
export declare function ensureShellEnvSource(rcPath: string, envFilePath: string): void;
|
|
113
|
+
export declare function ensureShellEnvSource(rcPath: string, envFilePath: string, backup?: BackupSession): void;
|
|
106
114
|
/**
|
|
107
115
|
* `homeDir` defaults to the real `~` and is only ever overridden for tests
|
|
108
116
|
* and `scripts/sandbox.sh` — the same seam P0's probes use
|