agent-trellis 0.8.0 → 0.9.0
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 +45 -206
- package/dist/adapters/zcode.d.ts +21 -0
- package/dist/adapters/zcode.js +234 -0
- package/dist/cli.js +119 -10
- package/dist/commands/doctor.js +2 -0
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +4 -1
- package/dist/commands/mcp.d.ts +56 -14
- package/dist/commands/mcp.js +105 -28
- package/dist/commands/mcpGateway.js +2 -1
- package/dist/commands/mcpImport.d.ts +21 -2
- package/dist/commands/mcpImport.js +30 -7
- package/dist/commands/memory.d.ts +13 -1
- package/dist/commands/memory.js +15 -0
- package/dist/commands/migrate.js +4 -1
- package/dist/commands/onboard.js +15 -4
- package/dist/commands/remoteSkill.d.ts +90 -0
- package/dist/commands/remoteSkill.js +392 -0
- package/dist/commands/rollback.js +55 -1
- package/dist/commands/secretsAudit.js +4 -1
- package/dist/commands/skill.d.ts +37 -6
- package/dist/commands/skill.js +73 -15
- package/dist/commands/sync.js +3 -1
- package/dist/core/adapter.d.ts +11 -1
- package/dist/core/canonical.d.ts +17 -1
- package/dist/core/canonical.js +54 -0
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.js +1 -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 +42 -0
- package/dist/lib/backup.js +36 -3
- package/dist/lib/chatAgents.d.ts +42 -0
- package/dist/lib/chatAgents.js +59 -0
- package/dist/lib/dirDigest.d.ts +11 -0
- package/dist/lib/dirDigest.js +52 -0
- package/dist/lib/envVarNames.d.ts +3 -0
- package/dist/lib/envVarNames.js +19 -0
- package/dist/lib/installAgent.d.ts +1 -1
- package/dist/lib/installAgent.js +1 -1
- package/dist/lib/mcpMigrateRead.d.ts +1 -0
- package/dist/lib/mcpMigrateRead.js +19 -1
- package/dist/lib/realHomeSnapshot.js +5 -0
- package/dist/lib/remoteSkillLock.d.ts +26 -0
- package/dist/lib/remoteSkillLock.js +88 -0
- package/dist/lib/remoteSkillSource.d.ts +45 -0
- package/dist/lib/remoteSkillSource.js +206 -0
- package/dist/lib/runtimeControlProvider.js +2 -0
- package/dist/lib/taskStore.js +1 -1
- package/dist/lib/terminalPicker.js +33 -6
- package/dist/lib/zcodeOwnership.d.ts +17 -0
- package/dist/lib/zcodeOwnership.js +37 -0
- package/dist/pi-bridge/bundle.js +2 -1
- package/dist/probes/codex.d.ts +7 -0
- package/dist/probes/codex.js +37 -5
- package/dist/probes/zcode.d.ts +32 -0
- package/dist/probes/zcode.js +140 -0
- package/docs/architecture.md +9 -5
- 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 +244 -14
- package/docs/overview.md +6 -3
- package/docs/overview.zh-CN.md +5 -3
- package/docs/roadmap.md +2 -1
- 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 +5 -2
- package/schema/servers.example.yaml +1 -1
- package/docs/assets/agent-trellis-architecture-horizontal.svg +0 -80
- package/docs/assets/agent-trellis-architecture-vertical.svg +0 -82
- package/docs/assets/trellis-mark.svg +0 -12
|
@@ -11,6 +11,7 @@ import { join } from "node:path";
|
|
|
11
11
|
import { loadCanonicalSource, ensureGitignoreEntry, ensureShellEnvSource, upsertServerYaml, writeSecretsPolicyExtraction } from "../core/canonical.js";
|
|
12
12
|
import { openBackupSession } from "../lib/backup.js";
|
|
13
13
|
import { parseDotenv, writeLocalSecretValue } from "../lib/secretEnv.js";
|
|
14
|
+
import { collectMcpSyncReport, printReport as printMcpSyncReport } from "./mcp.js";
|
|
14
15
|
const DEFAULT_ENV_FILE_TILDE = "~/.trellis/mcp/servers.local.env";
|
|
15
16
|
class SkipImport extends Error {
|
|
16
17
|
}
|
|
@@ -309,25 +310,47 @@ export function applyMcpImportPlan(path, homeDir = homedir(), backup) {
|
|
|
309
310
|
ownSession.finalize();
|
|
310
311
|
return publicPlan(plan);
|
|
311
312
|
}
|
|
312
|
-
|
|
313
|
+
/**
|
|
314
|
+
* See `applyMcpAddWithSync`'s doc comment (mcp.ts) — same split, same
|
|
315
|
+
* reason: a non-CLI caller (trellis-gui's sidecar) gets the same
|
|
316
|
+
* structured result a JSON-mode CLI run prints, without scraping
|
|
317
|
+
* stdout or re-deriving the plan-then-apply-then-cascade-sync
|
|
318
|
+
* sequencing itself. Unlike `mcp add`/`mcp remove`, `applyMcpImportPlan`
|
|
319
|
+
* already opens its own backup session unconditionally (it always has,
|
|
320
|
+
* per design.md's original survey of `openBackupSession` call sites) —
|
|
321
|
+
* no tasks.md 3.5-style fix needed here.
|
|
322
|
+
*/
|
|
323
|
+
export async function applyMcpImportWithSync(path, opts = {}) {
|
|
324
|
+
const homeDir = opts.homeDir ?? homedir();
|
|
325
|
+
const plan = opts.dryRun ? collectMcpImportPlan(path, homeDir) : applyMcpImportPlan(path, homeDir);
|
|
326
|
+
const failed = plan.items.some((item) => item.action === "conflict" || item.action === "invalid-input");
|
|
327
|
+
const changed = plan.items.some((item) => item.action === "create");
|
|
328
|
+
let syncReport;
|
|
329
|
+
if (!failed && changed && existsSync(join(homeDir, ".trellis"))) {
|
|
330
|
+
syncReport = await collectMcpSyncReport({ homeDir, dryRun: opts.dryRun });
|
|
331
|
+
}
|
|
332
|
+
return { plan, ...(syncReport ? { sync: syncReport } : {}) };
|
|
333
|
+
}
|
|
334
|
+
export async function runMcpImport(path, opts = {}) {
|
|
313
335
|
const homeDir = opts.homeDir ?? homedir();
|
|
314
336
|
if (!path) {
|
|
315
337
|
console.error("Usage: trellis mcp import <json-file> [--dry-run]");
|
|
316
338
|
return { exitCode: 1 };
|
|
317
339
|
}
|
|
318
340
|
try {
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
applyMcpImportPlan(path, homeDir);
|
|
322
|
-
const result = publicPlan(internal);
|
|
341
|
+
const { plan: result, sync: syncReport } = await applyMcpImportWithSync(path, { homeDir, dryRun: opts.dryRun });
|
|
342
|
+
const failed = result.items.some((item) => item.action === "conflict" || item.action === "invalid-input");
|
|
323
343
|
if (opts.json)
|
|
324
|
-
console.log(JSON.stringify(result, null, 2));
|
|
344
|
+
console.log(JSON.stringify(syncReport ? { ...result, sync: syncReport } : result, null, 2));
|
|
325
345
|
else {
|
|
326
346
|
console.log(`${opts.dryRun ? "[dry run] " : ""}mcp import ${path}`);
|
|
327
347
|
for (const item of result.items)
|
|
328
348
|
console.log(` [${item.action}] ${item.name} — ${item.detail}`);
|
|
349
|
+
if (syncReport)
|
|
350
|
+
printMcpSyncReport(syncReport, opts.dryRun ?? false);
|
|
329
351
|
}
|
|
330
|
-
|
|
352
|
+
const syncConflict = syncReport?.reports.some((r) => r.items.some((i) => i.action === "conflict")) ?? false;
|
|
353
|
+
return { exitCode: failed || syncConflict ? 1 : 0 };
|
|
331
354
|
}
|
|
332
355
|
catch (err) {
|
|
333
356
|
console.error(err instanceof Error ? err.message : String(err));
|
|
@@ -12,9 +12,21 @@
|
|
|
12
12
|
* server process — both are plain file operations, same posture as
|
|
13
13
|
* every other Trellis write.
|
|
14
14
|
*/
|
|
15
|
-
import type { McpConfig, McpServerDef } from "../core/types.js";
|
|
15
|
+
import type { AgentId, McpConfig, McpServerDef } from "../core/types.js";
|
|
16
16
|
import type { BackupSession } from "../lib/backup.js";
|
|
17
17
|
import { type MemoryExtractionPlan, type MemorySyncPlan } from "../lib/memoryGraph.js";
|
|
18
|
+
export interface MemoryListEntry {
|
|
19
|
+
name: string;
|
|
20
|
+
scope: readonly AgentId[];
|
|
21
|
+
}
|
|
22
|
+
/** Canonical `memories/*.md` profile files — the list `trellis-gui`'s
|
|
23
|
+
* Memory view reads (tasks.md 6.2), mirroring `collectSkillList`'s
|
|
24
|
+
* shape exactly (skill.ts) since both are "canonical files with a
|
|
25
|
+
* resolved managed-agent scope" lists. Distinct from this file's own
|
|
26
|
+
* `MEMORY_SERVER_NAME` sync/extraction pipeline below, which is about
|
|
27
|
+
* the separate shared-Memory-MCP-server knowledge graph, not these
|
|
28
|
+
* per-topic markdown files. */
|
|
29
|
+
export declare function collectMemoryList(homeDir?: string): MemoryListEntry[];
|
|
18
30
|
/** Exported so `onboard` (`trellis onboard --memory on|off`,
|
|
19
31
|
* trellis-onboard-mcp-mode) can look up and write this same entry
|
|
20
32
|
* without hardcoding the name a second time. */
|
package/dist/commands/memory.js
CHANGED
|
@@ -16,7 +16,22 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
16
16
|
import { homedir } from "node:os";
|
|
17
17
|
import { dirname, join } from "node:path";
|
|
18
18
|
import { loadCanonicalSource } from "../core/canonical.js";
|
|
19
|
+
import { resolveScope } from "../core/types.js";
|
|
19
20
|
import { parseMemoryGraph, planMemoryExtraction, planMemorySync, renderMemoryGraph } from "../lib/memoryGraph.js";
|
|
21
|
+
/** Canonical `memories/*.md` profile files — the list `trellis-gui`'s
|
|
22
|
+
* Memory view reads (tasks.md 6.2), mirroring `collectSkillList`'s
|
|
23
|
+
* shape exactly (skill.ts) since both are "canonical files with a
|
|
24
|
+
* resolved managed-agent scope" lists. Distinct from this file's own
|
|
25
|
+
* `MEMORY_SERVER_NAME` sync/extraction pipeline below, which is about
|
|
26
|
+
* the separate shared-Memory-MCP-server knowledge graph, not these
|
|
27
|
+
* per-topic markdown files. */
|
|
28
|
+
export function collectMemoryList(homeDir = homedir()) {
|
|
29
|
+
const canonical = loadCanonicalSource(homeDir);
|
|
30
|
+
return canonical.memories.map((memory) => ({
|
|
31
|
+
name: memory.name,
|
|
32
|
+
scope: resolveScope(memory.scope, canonical.managedAgents),
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
20
35
|
/** Exported so `onboard` (`trellis onboard --memory on|off`,
|
|
21
36
|
* trellis-onboard-mcp-mode) can look up and write this same entry
|
|
22
37
|
* without hardcoding the name a second time. */
|
package/dist/commands/migrate.js
CHANGED
|
@@ -12,10 +12,11 @@ import * as codexProbe from "../probes/codex.js";
|
|
|
12
12
|
import * as kiroProbe from "../probes/kiro.js";
|
|
13
13
|
import * as piProbe from "../probes/pi.js";
|
|
14
14
|
import * as kimiCodeProbe from "../probes/kimi-code.js";
|
|
15
|
+
import * as zcodeProbe from "../probes/zcode.js";
|
|
15
16
|
import { AGENTS_MD_TEMPLATE } from "./init.js";
|
|
16
17
|
import { decideDirImport } from "../lib/dirEquals.js";
|
|
17
18
|
import { deepEqual } from "../lib/deepEqual.js";
|
|
18
|
-
import { readClaudeCodeMcpDefs, readCodexMcpDefs, readKiroMcpDefs, readKimiCodeMcpDefs, resolvedEnvTextMap } from "../lib/mcpMigrateRead.js";
|
|
19
|
+
import { readClaudeCodeMcpDefs, readCodexMcpDefs, readKiroMcpDefs, readKimiCodeMcpDefs, readZcodeMcpDefs, resolvedEnvTextMap } from "../lib/mcpMigrateRead.js";
|
|
19
20
|
import { parseDotenv, writeLocalSecretValue } from "../lib/secretEnv.js";
|
|
20
21
|
import { findLiteralSecret } from "../adapters/mcpPlan.js";
|
|
21
22
|
import { ensureGitignoreEntry, ensureShellEnvSource, loadCanonicalSource, upsertServerYaml, writeSecretsPolicyExtraction } from "../core/canonical.js";
|
|
@@ -51,6 +52,7 @@ const PROBES = {
|
|
|
51
52
|
kiro: (homeDir) => kiroProbe.probe(homeDir),
|
|
52
53
|
pi: (homeDir) => piProbe.probe(homeDir),
|
|
53
54
|
"kimi-code": (homeDir) => kimiCodeProbe.probe(homeDir),
|
|
55
|
+
zcode: (homeDir) => zcodeProbe.probe(homeDir),
|
|
54
56
|
};
|
|
55
57
|
/** pi has no static MCP config to read at all (roadmap.md P14/
|
|
56
58
|
* trellis-migrate-mcp-servers) — deliberately absent, not an oversight;
|
|
@@ -60,6 +62,7 @@ const MCP_READERS = {
|
|
|
60
62
|
kiro: readKiroMcpDefs,
|
|
61
63
|
codex: readCodexMcpDefs,
|
|
62
64
|
"kimi-code": readKimiCodeMcpDefs,
|
|
65
|
+
zcode: readZcodeMcpDefs,
|
|
63
66
|
};
|
|
64
67
|
function planSkill(name, sourceDir, isSymlink, caseCorrect, canonicalDir) {
|
|
65
68
|
if (isSymlink) {
|
package/dist/commands/onboard.js
CHANGED
|
@@ -23,6 +23,7 @@ import * as codexProbe from "../probes/codex.js";
|
|
|
23
23
|
import * as kiroProbe from "../probes/kiro.js";
|
|
24
24
|
import * as piProbe from "../probes/pi.js";
|
|
25
25
|
import * as kimiCodeProbe from "../probes/kimi-code.js";
|
|
26
|
+
import * as zcodeProbe from "../probes/zcode.js";
|
|
26
27
|
import { ALL_AGENTS, capabilityDeliveryForAgent } from "../core/types.js";
|
|
27
28
|
import { loadCanonicalSource, removeServerYaml, upsertServerYaml, writeMcpModeYaml, writeMcpRoutesYaml, writeMcpRuntimeDeliveryYaml } from "../core/canonical.js";
|
|
28
29
|
import { buildCapabilityInventory, parseCapabilitySelectionFile, resolveSelectedNames, selectionContains } from "../core/capabilitySelection.js";
|
|
@@ -47,6 +48,7 @@ const PROBES = {
|
|
|
47
48
|
kiro: (homeDir) => kiroProbe.probe(homeDir),
|
|
48
49
|
pi: (homeDir) => piProbe.probe(homeDir),
|
|
49
50
|
"kimi-code": (homeDir) => kimiCodeProbe.probe(homeDir),
|
|
51
|
+
zcode: (homeDir) => zcodeProbe.probe(homeDir),
|
|
50
52
|
};
|
|
51
53
|
/**
|
|
52
54
|
* Scores only real source-side content. The recommendation is a hint for a
|
|
@@ -824,14 +826,23 @@ export async function collectOnboardPlan(opts = {}) {
|
|
|
824
826
|
if (!requestedRoutes && shouldPromptForRoutes) {
|
|
825
827
|
requestedRoutes = await resolveInteractiveMcpRoutes(managedAgents, availableMcpNames, currentMcpAfterMigration.hub !== undefined);
|
|
826
828
|
}
|
|
827
|
-
|
|
829
|
+
// ZCode's generic ~/.agents/skills discovery bypasses Trellis scope. Its
|
|
830
|
+
// default is therefore Runtime-first unless a capability-selection file
|
|
831
|
+
// explicitly chooses native/both, or canonical already has a choice.
|
|
832
|
+
const zcodeRuntimeRecommendation = managedAgents.includes("zcode") && currentMcpAfterMigration.runtime?.delivery?.zcode === undefined
|
|
833
|
+
? { zcode: "mcp" }
|
|
834
|
+
: {};
|
|
835
|
+
const requestedRuntimeDelivery = {
|
|
836
|
+
...zcodeRuntimeRecommendation,
|
|
837
|
+
...(capabilitySelection?.runtimeDelivery ?? {}),
|
|
838
|
+
};
|
|
828
839
|
let mcpSyncOverride;
|
|
829
|
-
if ((requestedRoutes && Object.keys(requestedRoutes).length > 0) ||
|
|
840
|
+
if ((requestedRoutes && Object.keys(requestedRoutes).length > 0) || Object.keys(requestedRuntimeDelivery).length > 0) {
|
|
830
841
|
const currentMcp = currentMcpAfterMigration;
|
|
831
842
|
const routes = requestedRoutes && Object.keys(requestedRoutes).length > 0
|
|
832
843
|
? { ...(currentMcp.routes ?? {}), ...requestedRoutes }
|
|
833
844
|
: currentMcp.routes;
|
|
834
|
-
const delivery =
|
|
845
|
+
const delivery = Object.keys(requestedRuntimeDelivery).length > 0
|
|
835
846
|
? { ...(currentMcp.runtime?.delivery ?? {}), ...requestedRuntimeDelivery }
|
|
836
847
|
: currentMcp.runtime?.delivery;
|
|
837
848
|
mcpSyncOverride = {
|
|
@@ -842,7 +853,7 @@ export async function collectOnboardPlan(opts = {}) {
|
|
|
842
853
|
if (!opts.dryRun && requestedRoutes && Object.keys(requestedRoutes).length > 0) {
|
|
843
854
|
writeMcpRoutesYaml(join(homeDir, ".trellis", "mcp", "servers.yaml"), routes ?? {}, backupSession);
|
|
844
855
|
}
|
|
845
|
-
if (!opts.dryRun &&
|
|
856
|
+
if (!opts.dryRun && Object.keys(requestedRuntimeDelivery).length > 0) {
|
|
846
857
|
writeMcpRuntimeDeliveryYaml(join(homeDir, ".trellis", "mcp", "servers.yaml"), delivery ?? {}, backupSession);
|
|
847
858
|
}
|
|
848
859
|
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `trellis add` and `trellis update`: GitHub-hosted Skill import with
|
|
3
|
+
* Trellis-owned canonical storage, provenance, scope, backup, and sync.
|
|
4
|
+
*/
|
|
5
|
+
import type { Scope } from "../core/types.js";
|
|
6
|
+
import { type BackupSession } from "../lib/backup.js";
|
|
7
|
+
import { type RemoteSkillLockEntry } from "../lib/remoteSkillLock.js";
|
|
8
|
+
import { type FetchedRemoteRepository } from "../lib/remoteSkillSource.js";
|
|
9
|
+
import type { SyncReport } from "./sync.js";
|
|
10
|
+
export type RemoteSkillAction = "create" | "already-present" | "conflict" | "invalid-source" | "invalid-options";
|
|
11
|
+
export interface RemoteSkillAddPlan {
|
|
12
|
+
name: string;
|
|
13
|
+
action: RemoteSkillAction;
|
|
14
|
+
detail: string;
|
|
15
|
+
source?: string;
|
|
16
|
+
requestedRef?: string;
|
|
17
|
+
commit?: string;
|
|
18
|
+
subdirectory?: string;
|
|
19
|
+
digest?: string;
|
|
20
|
+
canonicalPath?: string;
|
|
21
|
+
scope?: Scope;
|
|
22
|
+
/** Present only in process memory; never included in CLI output. */
|
|
23
|
+
sourceDir?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface RemoteSkillAddOptions {
|
|
26
|
+
branch?: string;
|
|
27
|
+
agents?: readonly string[];
|
|
28
|
+
homeDir?: string;
|
|
29
|
+
dryRun?: boolean;
|
|
30
|
+
json?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** Builds an import plan from an already-fetched source. Keeping fetching
|
|
33
|
+
* outside this function makes the real Git transport testable with a local
|
|
34
|
+
* bare repository while public CLI input remains GitHub-only. */
|
|
35
|
+
export declare function collectRemoteSkillAddPlan(fetched: FetchedRemoteRepository, name: string | undefined, opts?: Omit<RemoteSkillAddOptions, "branch" | "dryRun" | "json">): RemoteSkillAddPlan;
|
|
36
|
+
export interface RemoteSkillAddOutcome {
|
|
37
|
+
plan: Omit<RemoteSkillAddPlan, "sourceDir">;
|
|
38
|
+
sync?: SyncReport;
|
|
39
|
+
}
|
|
40
|
+
export declare function applyRemoteSkillAddPlan(plan: RemoteSkillAddPlan, opts?: {
|
|
41
|
+
homeDir?: string;
|
|
42
|
+
dryRun?: boolean;
|
|
43
|
+
backupSession?: BackupSession;
|
|
44
|
+
}): Promise<RemoteSkillAddOutcome>;
|
|
45
|
+
/** CLI-facing remote add. The only source accepted here is normalized
|
|
46
|
+
* GitHub input; tests use collectRemoteSkillAddPlan with a local fetch. */
|
|
47
|
+
export declare function runRemoteSkillAdd(sourceInput: string | undefined, name: string | undefined, opts?: RemoteSkillAddOptions): Promise<{
|
|
48
|
+
exitCode: number;
|
|
49
|
+
}>;
|
|
50
|
+
export declare function runRemoteSkillList(sourceInput: string | undefined, opts?: {
|
|
51
|
+
branch?: string;
|
|
52
|
+
json?: boolean;
|
|
53
|
+
}): Promise<{
|
|
54
|
+
exitCode: number;
|
|
55
|
+
}>;
|
|
56
|
+
export type RemoteSkillUpdateAction = "already-current" | "update" | "conflict" | "not-tracked" | "invalid-source";
|
|
57
|
+
export interface RemoteSkillUpdatePlan {
|
|
58
|
+
name: string;
|
|
59
|
+
action: RemoteSkillUpdateAction;
|
|
60
|
+
detail: string;
|
|
61
|
+
source?: string;
|
|
62
|
+
requestedRef?: string;
|
|
63
|
+
previousCommit?: string;
|
|
64
|
+
commit?: string;
|
|
65
|
+
previousDigest?: string;
|
|
66
|
+
digest?: string;
|
|
67
|
+
canonicalPath?: string;
|
|
68
|
+
sourceDir?: string;
|
|
69
|
+
replaceDirectory?: boolean;
|
|
70
|
+
}
|
|
71
|
+
export declare function collectRemoteSkillUpdatePlan(name: string, fetched: FetchedRemoteRepository | undefined, homeDir?: string): RemoteSkillUpdatePlan;
|
|
72
|
+
export interface RemoteSkillUpdateOutcome {
|
|
73
|
+
plans: readonly Omit<RemoteSkillUpdatePlan, "sourceDir">[];
|
|
74
|
+
sync?: SyncReport;
|
|
75
|
+
}
|
|
76
|
+
export declare function applyRemoteSkillUpdatePlans(plans: readonly RemoteSkillUpdatePlan[], opts?: {
|
|
77
|
+
homeDir?: string;
|
|
78
|
+
dryRun?: boolean;
|
|
79
|
+
backupSession?: BackupSession;
|
|
80
|
+
}): Promise<RemoteSkillUpdateOutcome>;
|
|
81
|
+
export declare function runRemoteSkillUpdate(names: readonly string[], opts?: {
|
|
82
|
+
homeDir?: string;
|
|
83
|
+
dryRun?: boolean;
|
|
84
|
+
json?: boolean;
|
|
85
|
+
}): Promise<{
|
|
86
|
+
exitCode: number;
|
|
87
|
+
}>;
|
|
88
|
+
/** Used by Skill listing to distinguish remote provenance from local content
|
|
89
|
+
* without making a malformed bookkeeping file crash a read-only list. */
|
|
90
|
+
export declare function remoteSkillProvenance(homeDir: string): Record<string, RemoteSkillLockEntry>;
|