@agent-native/core 0.51.7 → 0.51.9
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/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/plan-blocks.d.ts +19 -0
- package/dist/cli/plan-blocks.d.ts.map +1 -0
- package/dist/cli/plan-blocks.js +96 -0
- package/dist/cli/plan-blocks.js.map +1 -0
- package/dist/cli/plan-local.d.ts +7 -4
- package/dist/cli/plan-local.d.ts.map +1 -1
- package/dist/cli/plan-local.js +31 -5
- package/dist/cli/plan-local.js.map +1 -1
- package/dist/cli/recap.d.ts.map +1 -1
- package/dist/cli/recap.js +10 -44
- package/dist/cli/recap.js.map +1 -1
- package/dist/cli/skills.d.ts +15 -2
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +311 -36
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/assistant-ui-recovery.d.ts.map +1 -1
- package/dist/client/assistant-ui-recovery.js +15 -12
- package/dist/client/assistant-ui-recovery.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/skills.js
CHANGED
|
@@ -21,7 +21,7 @@ Usage:
|
|
|
21
21
|
npx @agent-native/core@latest skills list
|
|
22
22
|
npx @agent-native/core@latest skills status [assets|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|all] [--scope user|project] [--json]
|
|
23
23
|
npx @agent-native/core@latest skills update [assets|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|all] [--scope user|project] [--dry-run] [--json]
|
|
24
|
-
npx @agent-native/core@latest skills add assets|design-exploration|visual-plan|visual-recap|context-xray [--client codex|claude-code|claude-code-cli|cowork|all] [--scope user|project] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]
|
|
24
|
+
npx @agent-native/core@latest skills add assets|design-exploration|visual-plan|visual-recap|context-xray [--client codex|claude-code|claude-code-cli|cowork|all] [--scope user|project] [--mode hosted|local-files|self-hosted] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]
|
|
25
25
|
npx @agent-native/core@latest skills add <manifest-or-app-dir|skill-repo> [--skill <name>] [--client ...] [--yes]
|
|
26
26
|
|
|
27
27
|
Examples:
|
|
@@ -30,6 +30,8 @@ Examples:
|
|
|
30
30
|
npx @agent-native/core@latest skills add visual-plan
|
|
31
31
|
npx @agent-native/core@latest skills add visual-recap
|
|
32
32
|
npx @agent-native/core@latest skills add visual-recap --with-github-action
|
|
33
|
+
npx @agent-native/core@latest skills add visual-plan --mode local-files
|
|
34
|
+
npx @agent-native/core@latest skills add visual-plan --mode self-hosted --mcp-url https://my-plan-app.example.com
|
|
33
35
|
npx @agent-native/core@latest skills status visual-plan
|
|
34
36
|
npx @agent-native/core@latest skills update visual-plan
|
|
35
37
|
npx @agent-native/core@latest skills add visual-plan --no-connect
|
|
@@ -59,6 +61,13 @@ deployment) instead of the built-in hosted default — a bare origin gets the
|
|
|
59
61
|
standard /_agent-native/mcp path appended. Use app-skill pack for marketplace
|
|
60
62
|
bundles and custom adapter output.
|
|
61
63
|
|
|
64
|
+
When installing visual-plan or visual-recap interactively, the CLI asks where
|
|
65
|
+
plans and recaps should live: hosted Plans for shareable links/comments, local
|
|
66
|
+
files for "No sharing, all local.", or a self-hosted/custom Plan app URL.
|
|
67
|
+
Pass --mode to choose directly. Local-files mode skips MCP registration and
|
|
68
|
+
auth and installs instructions that default to a no-auth block catalog fetch,
|
|
69
|
+
MDX folders, and local preview.
|
|
70
|
+
|
|
62
71
|
When installing visual-recap interactively, the CLI offers to add the optional PR
|
|
63
72
|
Visual Recap GitHub Action. Pass --with-github-action to write it directly, then
|
|
64
73
|
run "npx @agent-native/core@latest recap setup" / "npx @agent-native/core@latest recap doctor" to configure and
|
|
@@ -252,6 +261,22 @@ the connector without authenticating, then run
|
|
|
252
261
|
whenever you are ready, or choose a narrower \`--client\`. Auth and MCP tool
|
|
253
262
|
loading are per client config/session.
|
|
254
263
|
|
|
264
|
+
**Local-only / text installs.** If the user wants no sharing and all local files,
|
|
265
|
+
install with \`--mode local-files\`:
|
|
266
|
+
|
|
267
|
+
\`\`\`bash
|
|
268
|
+
npx @agent-native/core@latest skills add visual-plan --mode local-files
|
|
269
|
+
\`\`\`
|
|
270
|
+
|
|
271
|
+
This mode does not register the Plan MCP connector. Before authoring structured
|
|
272
|
+
MDX, fetch the no-auth, schema-only block catalog with
|
|
273
|
+
\`npx @agent-native/core@latest plan blocks --out plan-blocks.md\`, read that file,
|
|
274
|
+
write \`plans/<slug>/plan.mdx\` locally, then run \`plan local preview\`. Plain
|
|
275
|
+
text skill installs (Vercel Skills CLI, copied GitHub files, etc.) can follow
|
|
276
|
+
that same local flow if \`@agent-native/core\` is available. Text alone cannot
|
|
277
|
+
register MCP tools; hosted/shareable Plans still need the Agent-Native CLI
|
|
278
|
+
install/reconnect step above.
|
|
279
|
+
|
|
255
280
|
**Browser (people you share with).** Open the Plans editor and create & edit
|
|
256
281
|
with no sign-up — you work as a guest. Sign in only when you want to save or
|
|
257
282
|
share; signing in claims the plans you made as a guest into your account.
|
|
@@ -259,9 +284,10 @@ share; signing in claims the plans you made as a guest into your account.
|
|
|
259
284
|
Sharing and commenting require an account: public/shared plans are viewable by
|
|
260
285
|
anyone with the link, but commenting on them needs an agent-native account.
|
|
261
286
|
|
|
262
|
-
For fully offline, no-account use,
|
|
263
|
-
|
|
264
|
-
|
|
287
|
+
For fully offline, no-account use, use local-files mode and the local preview
|
|
288
|
+
command. The optional \`plan blocks\` lookup reads only public schema metadata; if
|
|
289
|
+
network access is unavailable, use the bundled references and validate with
|
|
290
|
+
\`plan local preview\`.
|
|
265
291
|
|
|
266
292
|
If a Plans tool returns \`needs auth\`, \`Unauthorized\`, or \`Session terminated\`,
|
|
267
293
|
do not keep retrying the tool. Stop and give the user the reconnect step for the
|
|
@@ -1291,11 +1317,20 @@ planning, repo-owned/source-controlled planning artifacts, or when
|
|
|
1291
1317
|
\`AGENT_NATIVE_PLANS_MODE=local-files\` is set. Also use it when a user or repo
|
|
1292
1318
|
policy says a plan must stay under their own brand, domain, source control, or
|
|
1293
1319
|
infrastructure. In this mode the plan data must never be sent to the Plan MCP
|
|
1294
|
-
server or Plan app action surface.
|
|
1320
|
+
server or Plan app action surface. Schema-only block catalog lookup is allowed
|
|
1321
|
+
because it sends no plan content: use the MCP \`get-plan-blocks\` tool if it is
|
|
1322
|
+
already available, or run
|
|
1323
|
+
\`npx @agent-native/core@latest plan blocks --out plan-blocks.md\` and read that
|
|
1324
|
+
file before authoring MDX.
|
|
1295
1325
|
|
|
1296
1326
|
The local-files contract is:
|
|
1297
1327
|
|
|
1298
1328
|
- Read source context from local files and shell commands only.
|
|
1329
|
+
- Fetch/read the block catalog before writing structured MDX. The
|
|
1330
|
+
\`plan blocks\` command calls the public no-auth \`get-plan-blocks\` route and
|
|
1331
|
+
writes only registry metadata to disk; use \`--format schema\` if exact nested
|
|
1332
|
+
fields are needed. If network access is unavailable, use the bundled
|
|
1333
|
+
references and rely on \`plan local preview\` to catch invalid tags.
|
|
1299
1334
|
- Write the plan as a local MDX folder under \`plans/<slug>/\`: \`plan.mdx\`,
|
|
1300
1335
|
optional \`canvas.mdx\`, optional \`prototype.mdx\`, and optional
|
|
1301
1336
|
\`.plan-state.json\`.
|
|
@@ -1306,7 +1341,8 @@ The local-files contract is:
|
|
|
1306
1341
|
- Do **not** call \`create-visual-plan\`, \`create-ui-plan\`,
|
|
1307
1342
|
\`create-prototype-plan\`, \`create-plan-design\`, \`import-visual-plan-source\`,
|
|
1308
1343
|
\`update-visual-plan\`, \`patch-visual-plan-source\`, \`get-plan-feedback\`,
|
|
1309
|
-
\`export-visual-plan\`, or any hosted Plan tool for that plan
|
|
1344
|
+
\`export-visual-plan\`, or any hosted Plan tool for that plan except the
|
|
1345
|
+
schema-only block catalog lookup above.
|
|
1310
1346
|
- Treat feedback as file or chat feedback: update the MDX files directly, rerun
|
|
1311
1347
|
the local preview command, and summarize the new local URL/path. Hosted
|
|
1312
1348
|
comments, sharing, history, and publish/export receipts are unavailable until
|
|
@@ -1437,6 +1473,12 @@ In local-files mode:
|
|
|
1437
1473
|
The existing \`npx @agent-native/core@latest recap collect-diff\`, \`scan\`, and
|
|
1438
1474
|
\`build-prompt --local-files\` helpers are safe to use because they operate on
|
|
1439
1475
|
local files and do not write to the Plan database.
|
|
1476
|
+
- Fetch/read the block catalog before writing structured MDX. Use
|
|
1477
|
+
\`npx @agent-native/core@latest plan blocks --out plan-blocks.md\` when the Plan
|
|
1478
|
+
MCP connector is not registered; it calls the public no-auth
|
|
1479
|
+
\`get-plan-blocks\` route and sends no recap content. If network access is
|
|
1480
|
+
unavailable, use the bundled references and validate with
|
|
1481
|
+
\`plan local preview\`.
|
|
1440
1482
|
- Write the recap as a local MDX folder under \`plans/<slug>/\`: \`plan.mdx\`,
|
|
1441
1483
|
optional \`canvas.mdx\`, optional \`prototype.mdx\`, and optional
|
|
1442
1484
|
\`.plan-state.json\`. Set \`kind: "recap"\` and \`localOnly: true\` in
|
|
@@ -1448,7 +1490,8 @@ In local-files mode:
|
|
|
1448
1490
|
- Do **not** call \`create-visual-recap\`, \`create-visual-plan\`,
|
|
1449
1491
|
\`import-visual-plan-source\`, \`update-visual-plan\`,
|
|
1450
1492
|
\`patch-visual-plan-source\`, \`get-plan-feedback\`, \`export-visual-plan\`,
|
|
1451
|
-
\`set-resource-visibility\`, or any hosted Plan tool for that recap
|
|
1493
|
+
\`set-resource-visibility\`, or any hosted Plan tool for that recap except the
|
|
1494
|
+
schema-only block catalog lookup above.
|
|
1452
1495
|
- Treat review feedback as file or chat feedback: update the MDX files directly,
|
|
1453
1496
|
rerun the local preview command, and summarize the new local URL/path.
|
|
1454
1497
|
Hosted comments, sharing, screenshots, usage attachment, and PR sticky comment
|
|
@@ -1811,12 +1854,19 @@ memorized tags — they drift and silently produce a wrong tag (\`ApiEndpoint\`
|
|
|
1811
1854
|
instead of \`Endpoint\`, \`JsonExplorer\` instead of \`Json\`, \`Tabs\` instead of
|
|
1812
1855
|
\`TabsBlock\`) that errors on import.
|
|
1813
1856
|
|
|
1814
|
-
**Before writing any structured plan content,
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1857
|
+
**Before writing any structured plan content, fetch/read the block catalog.** In
|
|
1858
|
+
hosted or self-hosted mode, call \`get-plan-blocks\` on the Plan MCP connector
|
|
1859
|
+
(\`plan\` or legacy \`agent-native-plans\`). In local-files mode, or when the skill
|
|
1860
|
+
was installed as plain text and no MCP tools are registered, run
|
|
1861
|
+
\`npx @agent-native/core@latest plan blocks --out plan-blocks.md\` and read that
|
|
1862
|
+
file first. The CLI command calls the public no-auth \`get-plan-blocks\` route and
|
|
1863
|
+
sends no plan/recap content. If network access is unavailable, use the bundled
|
|
1864
|
+
references and validate with \`plan local preview\`.
|
|
1865
|
+
|
|
1866
|
+
The catalog returns the authoritative, always-current block vocabulary generated
|
|
1867
|
+
live from the app's own block registry — the same config the renderer and MDX
|
|
1868
|
+
round-trip use — so it can never be stale even if this SKILL.md is an old
|
|
1869
|
+
installed copy:
|
|
1820
1870
|
|
|
1821
1871
|
- \`get-plan-blocks\` (default \`format: "reference"\`) → a compact table of every
|
|
1822
1872
|
block's runtime \`type\`, exact MDX \`<Tag>\`, placement, and key data fields.
|
|
@@ -2244,12 +2294,62 @@ function stableSkillHash(files) {
|
|
|
2244
2294
|
}
|
|
2245
2295
|
return hash.digest("hex").slice(0, 16);
|
|
2246
2296
|
}
|
|
2247
|
-
function
|
|
2297
|
+
function insertAfterFrontmatter(markdown, block) {
|
|
2298
|
+
if (!block.trim())
|
|
2299
|
+
return markdown;
|
|
2300
|
+
const match = markdown.match(/^---\n[\s\S]*?\n---\n/);
|
|
2301
|
+
if (!match)
|
|
2302
|
+
return `${block}\n\n${markdown}`;
|
|
2303
|
+
return `${match[0]}\n${block.trim()}\n\n${markdown.slice(match[0].length)}`;
|
|
2304
|
+
}
|
|
2305
|
+
function planModeInstructionBlock(input) {
|
|
2306
|
+
if (input.mode === "local-files") {
|
|
2307
|
+
return `## Installed Mode
|
|
2308
|
+
|
|
2309
|
+
Default storage for this installation: local files. Create and update plans and
|
|
2310
|
+
recaps as MDX folders under \`plans/<slug>/\`. Before authoring structured MDX,
|
|
2311
|
+
run \`npx @agent-native/core@latest plan blocks --out plan-blocks.md\` and read
|
|
2312
|
+
the no-auth block catalog; it sends no plan content. Then run
|
|
2313
|
+
\`npx @agent-native/core@latest plan local preview --dir plans/<slug> --kind plan|recap\`,
|
|
2314
|
+
and report the local preview URL or path. No sharing, all local. Use a hosted
|
|
2315
|
+
or self-hosted Plan MCP connector only if the user explicitly asks to publish or
|
|
2316
|
+
share.`;
|
|
2317
|
+
}
|
|
2318
|
+
if (input.mode === "self-hosted") {
|
|
2319
|
+
return `## Installed Mode
|
|
2320
|
+
|
|
2321
|
+
Default storage for this installation: the configured self-hosted/custom Plan
|
|
2322
|
+
app${input.mcpUrl ? ` at \`${input.mcpUrl}\`` : ""}. Use that Plan MCP connector
|
|
2323
|
+
for plans and recaps instead of assuming \`https://plan.agent-native.com\`.`;
|
|
2324
|
+
}
|
|
2325
|
+
return "";
|
|
2326
|
+
}
|
|
2327
|
+
function applyPlanModeToSkillMarkdown(markdown, input) {
|
|
2328
|
+
if (input.appSkillId !== "visual-plans")
|
|
2329
|
+
return markdown;
|
|
2330
|
+
const block = planModeInstructionBlock({
|
|
2331
|
+
mode: input.mode,
|
|
2332
|
+
mcpUrl: input.mcpUrl,
|
|
2333
|
+
});
|
|
2334
|
+
return insertAfterFrontmatter(markdown, block);
|
|
2335
|
+
}
|
|
2336
|
+
function skillFilesForBuiltIn(appSkillId, options = {}) {
|
|
2248
2337
|
const entry = BUILT_IN_APP_SKILLS[appSkillId];
|
|
2249
2338
|
const skills = {
|
|
2250
|
-
[entry.skillName]: entry.skillMarkdown,
|
|
2339
|
+
[entry.skillName]: applyPlanModeToSkillMarkdown(entry.skillMarkdown, {
|
|
2340
|
+
appSkillId,
|
|
2341
|
+
mode: options.planMode,
|
|
2342
|
+
mcpUrl: options.mcpUrl,
|
|
2343
|
+
}),
|
|
2251
2344
|
...builtInExtraSkills(entry),
|
|
2252
2345
|
};
|
|
2346
|
+
for (const [skillName, skillMarkdown] of Object.entries(builtInExtraSkills(entry))) {
|
|
2347
|
+
skills[skillName] = applyPlanModeToSkillMarkdown(skillMarkdown, {
|
|
2348
|
+
appSkillId,
|
|
2349
|
+
mode: options.planMode,
|
|
2350
|
+
mcpUrl: options.mcpUrl,
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2253
2353
|
const extraFiles = builtInExtraFiles(entry);
|
|
2254
2354
|
const out = {};
|
|
2255
2355
|
for (const [skillName, skillMarkdown] of Object.entries(skills)) {
|
|
@@ -2261,11 +2361,12 @@ function skillFilesForBuiltIn(appSkillId) {
|
|
|
2261
2361
|
appSkillId,
|
|
2262
2362
|
displayName: entry.manifest.displayName,
|
|
2263
2363
|
skillName,
|
|
2264
|
-
mcpUrl: isLocalOnlyBuiltInSkill(entry)
|
|
2364
|
+
mcpUrl: isLocalOnlyBuiltInSkill(entry) || options.planMode === "local-files"
|
|
2265
2365
|
? ""
|
|
2266
|
-
: entry.manifest.hosted.mcpUrl,
|
|
2366
|
+
: (options.mcpUrl ?? entry.manifest.hosted.mcpUrl),
|
|
2267
2367
|
files,
|
|
2268
2368
|
contentHash: stableSkillHash(files),
|
|
2369
|
+
planMode: options.planMode,
|
|
2269
2370
|
};
|
|
2270
2371
|
}
|
|
2271
2372
|
return out;
|
|
@@ -2295,6 +2396,7 @@ function writeSkillFolder(dir, bundle, installedAt = new Date().toISOString()) {
|
|
|
2295
2396
|
mcpUrl: bundle.mcpUrl,
|
|
2296
2397
|
installedAt,
|
|
2297
2398
|
updateCommand: `npx @agent-native/core@latest skills update ${bundle.skillName}`,
|
|
2399
|
+
...(bundle.planMode ? { planMode: bundle.planMode } : {}),
|
|
2298
2400
|
};
|
|
2299
2401
|
fs.writeFileSync(path.join(dir, AGENT_NATIVE_SKILL_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}\n`, "utf-8");
|
|
2300
2402
|
}
|
|
@@ -2324,7 +2426,10 @@ function builtInSkillsRootForAgent(agent, scope, baseDir) {
|
|
|
2324
2426
|
* (which would have to be published to npm first). Returns the written folders.
|
|
2325
2427
|
*/
|
|
2326
2428
|
function installBuiltInInstructions(input) {
|
|
2327
|
-
const bundles = Object.values(skillFilesForBuiltIn(input.appSkillId
|
|
2429
|
+
const bundles = Object.values(skillFilesForBuiltIn(input.appSkillId, {
|
|
2430
|
+
planMode: input.planMode,
|
|
2431
|
+
mcpUrl: input.mcpUrl,
|
|
2432
|
+
})).filter((bundle) => !input.onlySkillNames || input.onlySkillNames.includes(bundle.skillName));
|
|
2328
2433
|
const written = [];
|
|
2329
2434
|
for (const agent of input.skillsAgents) {
|
|
2330
2435
|
const root = builtInSkillsRootForAgent(agent, input.scope, input.baseDir);
|
|
@@ -2438,7 +2543,7 @@ function clientFilterForStatus(parsed) {
|
|
|
2438
2543
|
}
|
|
2439
2544
|
function collectSkillInstallStates(parsed, options) {
|
|
2440
2545
|
const appSkillIds = targetIdsForStatus(parsed);
|
|
2441
|
-
const
|
|
2546
|
+
const defaultLatest = latestSkillBundlesForTargets(appSkillIds);
|
|
2442
2547
|
const roots = skillSearchRoots({
|
|
2443
2548
|
baseDir: options.baseDir ?? process.cwd(),
|
|
2444
2549
|
clients: clientFilterForStatus(parsed),
|
|
@@ -2447,7 +2552,7 @@ function collectSkillInstallStates(parsed, options) {
|
|
|
2447
2552
|
const states = [];
|
|
2448
2553
|
const seenDirs = new Set();
|
|
2449
2554
|
for (const root of roots) {
|
|
2450
|
-
for (const bundle of Object.values(
|
|
2555
|
+
for (const bundle of Object.values(defaultLatest)) {
|
|
2451
2556
|
const dir = path.join(root.root, bundle.skillName);
|
|
2452
2557
|
const resolvedDir = path.resolve(dir);
|
|
2453
2558
|
if (seenDirs.has(resolvedDir) || !fs.existsSync(dir))
|
|
@@ -2456,35 +2561,41 @@ function collectSkillInstallStates(parsed, options) {
|
|
|
2456
2561
|
continue;
|
|
2457
2562
|
seenDirs.add(resolvedDir);
|
|
2458
2563
|
const files = listSkillFolderFiles(dir);
|
|
2459
|
-
const installedHash = Object.keys(files).length > 0 ? stableSkillHash(files) : null;
|
|
2460
2564
|
const metadata = readSkillInstallMetadata(dir);
|
|
2565
|
+
const stateBundle = skillFilesForBuiltIn(bundle.appSkillId, {
|
|
2566
|
+
planMode: metadata?.planMode,
|
|
2567
|
+
mcpUrl: metadata?.mcpUrl,
|
|
2568
|
+
})[bundle.skillName] ?? bundle;
|
|
2569
|
+
const installedHash = Object.keys(files).length > 0 ? stableSkillHash(files) : null;
|
|
2461
2570
|
states.push({
|
|
2462
|
-
appSkillId:
|
|
2463
|
-
displayName:
|
|
2464
|
-
skillName:
|
|
2571
|
+
appSkillId: stateBundle.appSkillId,
|
|
2572
|
+
displayName: stateBundle.displayName,
|
|
2573
|
+
skillName: stateBundle.skillName,
|
|
2465
2574
|
path: dir,
|
|
2466
2575
|
root: root.root,
|
|
2467
2576
|
scope: root.scope,
|
|
2468
2577
|
client: root.client,
|
|
2469
|
-
latestHash:
|
|
2578
|
+
latestHash: stateBundle.contentHash,
|
|
2470
2579
|
installedHash,
|
|
2471
2580
|
metadataHash: metadata?.contentHash,
|
|
2472
|
-
current: installedHash ===
|
|
2581
|
+
current: installedHash === stateBundle.contentHash,
|
|
2473
2582
|
managed: metadata?.source === "agent-native",
|
|
2583
|
+
planMode: metadata?.planMode,
|
|
2584
|
+
mcpUrl: metadata?.mcpUrl,
|
|
2474
2585
|
});
|
|
2475
2586
|
}
|
|
2476
2587
|
}
|
|
2477
2588
|
return states.sort((a, b) => `${a.skillName}:${a.path}`.localeCompare(`${b.skillName}:${b.path}`));
|
|
2478
2589
|
}
|
|
2479
2590
|
function updateSkillInstallStates(states, dryRun) {
|
|
2480
|
-
const latest = latestSkillBundlesForTargets([
|
|
2481
|
-
...new Set(states.map((state) => state.appSkillId)),
|
|
2482
|
-
]);
|
|
2483
2591
|
const updated = [];
|
|
2484
2592
|
for (const state of states) {
|
|
2485
2593
|
if (state.current && state.managed)
|
|
2486
2594
|
continue;
|
|
2487
|
-
const bundle =
|
|
2595
|
+
const bundle = skillFilesForBuiltIn(state.appSkillId, {
|
|
2596
|
+
planMode: state.planMode,
|
|
2597
|
+
mcpUrl: state.mcpUrl,
|
|
2598
|
+
})[state.skillName];
|
|
2488
2599
|
if (!bundle)
|
|
2489
2600
|
continue;
|
|
2490
2601
|
if (!dryRun)
|
|
@@ -2622,6 +2733,56 @@ async function promptForScope(context) {
|
|
|
2622
2733
|
}
|
|
2623
2734
|
return result === "project" ? "project" : "user";
|
|
2624
2735
|
}
|
|
2736
|
+
async function promptForPlanMode(context) {
|
|
2737
|
+
const clack = await import("@clack/prompts");
|
|
2738
|
+
const result = await clack.select({
|
|
2739
|
+
message: "Where should visual plans and recaps live?",
|
|
2740
|
+
options: [
|
|
2741
|
+
{
|
|
2742
|
+
value: "hosted",
|
|
2743
|
+
label: "Hosted Plans, shareable links",
|
|
2744
|
+
hint: "Stores plans at plan.agent-native.com. Enables sharing, comments, browser editor. Requires one-time browser sign-in.",
|
|
2745
|
+
},
|
|
2746
|
+
{
|
|
2747
|
+
value: "local-files",
|
|
2748
|
+
label: "Local files only",
|
|
2749
|
+
hint: "Writes plans/<name>/plan.mdx in this repo and opens a local preview. No sharing, all local.",
|
|
2750
|
+
},
|
|
2751
|
+
{
|
|
2752
|
+
value: "self-hosted",
|
|
2753
|
+
label: "Self-hosted/custom URL",
|
|
2754
|
+
hint: "Connect to your own Plan app or local dev tunnel.",
|
|
2755
|
+
},
|
|
2756
|
+
],
|
|
2757
|
+
initialValue: context.initialMode,
|
|
2758
|
+
});
|
|
2759
|
+
if (clack.isCancel(result)) {
|
|
2760
|
+
clack.cancel("Cancelled.");
|
|
2761
|
+
return null;
|
|
2762
|
+
}
|
|
2763
|
+
return normalizePlanInstallMode(String(result));
|
|
2764
|
+
}
|
|
2765
|
+
async function promptForPlanMcpUrl() {
|
|
2766
|
+
const clack = await import("@clack/prompts");
|
|
2767
|
+
const result = await clack.text({
|
|
2768
|
+
message: "Plan app URL or MCP URL",
|
|
2769
|
+
placeholder: "https://my-plan-app.example.com",
|
|
2770
|
+
validate(value) {
|
|
2771
|
+
try {
|
|
2772
|
+
resolveMcpUrlOverride(value);
|
|
2773
|
+
return undefined;
|
|
2774
|
+
}
|
|
2775
|
+
catch (err) {
|
|
2776
|
+
return err?.message ?? "Enter a valid http:// or https:// URL.";
|
|
2777
|
+
}
|
|
2778
|
+
},
|
|
2779
|
+
});
|
|
2780
|
+
if (clack.isCancel(result)) {
|
|
2781
|
+
clack.cancel("Cancelled.");
|
|
2782
|
+
return null;
|
|
2783
|
+
}
|
|
2784
|
+
return String(result).trim();
|
|
2785
|
+
}
|
|
2625
2786
|
async function promptForSkills(context) {
|
|
2626
2787
|
const clack = await import("@clack/prompts");
|
|
2627
2788
|
const result = await clack.multiselect({
|
|
@@ -2659,6 +2820,30 @@ async function resolveSkillsClients(parsed, options) {
|
|
|
2659
2820
|
}
|
|
2660
2821
|
return selected;
|
|
2661
2822
|
}
|
|
2823
|
+
function normalizePlanInstallMode(value) {
|
|
2824
|
+
const normalized = value?.trim().toLowerCase();
|
|
2825
|
+
if (!normalized || normalized === "hosted")
|
|
2826
|
+
return "hosted";
|
|
2827
|
+
if (normalized === "local" ||
|
|
2828
|
+
normalized === "local-file" ||
|
|
2829
|
+
normalized === "local-files" ||
|
|
2830
|
+
normalized === "files") {
|
|
2831
|
+
return "local-files";
|
|
2832
|
+
}
|
|
2833
|
+
if (normalized === "self-hosted" ||
|
|
2834
|
+
normalized === "selfhosted" ||
|
|
2835
|
+
normalized === "custom" ||
|
|
2836
|
+
normalized === "custom-url") {
|
|
2837
|
+
return "self-hosted";
|
|
2838
|
+
}
|
|
2839
|
+
throw new Error('--mode must be one of "hosted", "local-files", or "self-hosted".');
|
|
2840
|
+
}
|
|
2841
|
+
function targetIncludesPlans(target) {
|
|
2842
|
+
return normalizeKnownSkillTarget(target) === "visual-plans";
|
|
2843
|
+
}
|
|
2844
|
+
function targetsIncludePlans(targets) {
|
|
2845
|
+
return targets.some(targetIncludesPlans);
|
|
2846
|
+
}
|
|
2662
2847
|
async function resolveSkillTargets(parsed, options) {
|
|
2663
2848
|
if (parsed.target || !shouldPrompt(parsed, options)) {
|
|
2664
2849
|
return [parsed.target ?? "assets"];
|
|
@@ -2755,6 +2940,14 @@ export function parseSkillsArgs(argv) {
|
|
|
2755
2940
|
}
|
|
2756
2941
|
else if ((value = eat("--mcp-url")) !== undefined)
|
|
2757
2942
|
out.mcpUrl = value;
|
|
2943
|
+
else if ((value = eat("--mode")) !== undefined)
|
|
2944
|
+
out.planMode = normalizePlanInstallMode(value);
|
|
2945
|
+
else if (arg === "--hosted")
|
|
2946
|
+
out.planMode = "hosted";
|
|
2947
|
+
else if (arg === "--local" || arg === "--local-files")
|
|
2948
|
+
out.planMode = "local-files";
|
|
2949
|
+
else if (arg === "--self-hosted" || arg === "--custom-url")
|
|
2950
|
+
out.planMode = "self-hosted";
|
|
2758
2951
|
else if (arg === "--yes" || arg === "-y")
|
|
2759
2952
|
out.yes = true;
|
|
2760
2953
|
else if (arg === "--dry-run")
|
|
@@ -2785,6 +2978,9 @@ export function parseSkillsArgs(argv) {
|
|
|
2785
2978
|
if (out.scope !== "user" && out.scope !== "project") {
|
|
2786
2979
|
throw new Error("--scope must be either user or project.");
|
|
2787
2980
|
}
|
|
2981
|
+
if (out.planMode === "local-files" && out.mcpUrl) {
|
|
2982
|
+
throw new Error("--mode local-files cannot be combined with --mcp-url.");
|
|
2983
|
+
}
|
|
2788
2984
|
return out;
|
|
2789
2985
|
}
|
|
2790
2986
|
function loadSkillTarget(target, onlySkillNames) {
|
|
@@ -2898,6 +3094,8 @@ function dryRunInstallCommand(parsed, target) {
|
|
|
2898
3094
|
"--scope",
|
|
2899
3095
|
parsed.scope,
|
|
2900
3096
|
];
|
|
3097
|
+
if (parsed.planMode)
|
|
3098
|
+
args.push("--mode", parsed.planMode);
|
|
2901
3099
|
if (parsed.mcpUrl)
|
|
2902
3100
|
args.push("--mcp-url", parsed.mcpUrl);
|
|
2903
3101
|
if (parsed.instructions && !parsed.mcp)
|
|
@@ -3159,6 +3357,20 @@ async function connectAfterEnsure(installTarget, clients, parsed, options) {
|
|
|
3159
3357
|
export async function addAgentNativeSkill(parsed, options = {}) {
|
|
3160
3358
|
const target = parsed.target ?? "assets";
|
|
3161
3359
|
const knownTarget = normalizeKnownSkillTarget(target);
|
|
3360
|
+
const planMode = knownTarget === "visual-plans"
|
|
3361
|
+
? (parsed.planMode ?? (parsed.mcpUrl ? "self-hosted" : "hosted"))
|
|
3362
|
+
: undefined;
|
|
3363
|
+
if (parsed.planMode && knownTarget !== "visual-plans") {
|
|
3364
|
+
throw new Error("--mode only applies to visual-plan / visual-recap.");
|
|
3365
|
+
}
|
|
3366
|
+
if (planMode === "local-files" && parsed.mcpUrl) {
|
|
3367
|
+
throw new Error("--mode local-files cannot be combined with --mcp-url.");
|
|
3368
|
+
}
|
|
3369
|
+
if (planMode === "self-hosted" && !parsed.mcpUrl) {
|
|
3370
|
+
throw new Error("--mode self-hosted requires --mcp-url <url>.");
|
|
3371
|
+
}
|
|
3372
|
+
const shouldRegisterMcp = parsed.mcp &&
|
|
3373
|
+
!(knownTarget === "visual-plans" && planMode === "local-files");
|
|
3162
3374
|
// For multi-skill bundles (the plan bundle), a single-skill target installs
|
|
3163
3375
|
// only that skill. `installsRecap` controls the PR Visual Recap github-action
|
|
3164
3376
|
// offer, which is only relevant when the recap skill is part of the install.
|
|
@@ -3258,12 +3470,15 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
3258
3470
|
displayName: installTarget.displayName,
|
|
3259
3471
|
skillNames: installTarget.skillNames,
|
|
3260
3472
|
skillsAgents,
|
|
3261
|
-
mcpUrl:
|
|
3262
|
-
|
|
3473
|
+
mcpUrl: knownTarget === "visual-plans" && planMode === "local-files"
|
|
3474
|
+
? ""
|
|
3475
|
+
: installTarget.loaded.manifest.hosted.mcpUrl,
|
|
3476
|
+
mcpClients: shouldRegisterMcp ? clients : [],
|
|
3263
3477
|
dryRun: true,
|
|
3264
3478
|
commands: [dryRunInstallCommand(parsed, target)],
|
|
3265
3479
|
githubActionPath,
|
|
3266
3480
|
githubActionSuggestedCommand,
|
|
3481
|
+
planMode,
|
|
3267
3482
|
};
|
|
3268
3483
|
}
|
|
3269
3484
|
finally {
|
|
@@ -3279,7 +3494,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
3279
3494
|
try {
|
|
3280
3495
|
if (parsed.instructions) {
|
|
3281
3496
|
if (skillsAgents.length === 0) {
|
|
3282
|
-
if (!
|
|
3497
|
+
if (!shouldRegisterMcp) {
|
|
3283
3498
|
throw new Error("Skill instructions can only be installed for Codex or Claude Code clients. Use an MCP-capable client or omit --instructions-only.");
|
|
3284
3499
|
}
|
|
3285
3500
|
}
|
|
@@ -3295,6 +3510,8 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
3295
3510
|
scope: parsed.scope,
|
|
3296
3511
|
baseDir: options.baseDir ?? process.cwd(),
|
|
3297
3512
|
dryRun: parsed.dryRun,
|
|
3513
|
+
planMode,
|
|
3514
|
+
mcpUrl: installTarget.loaded.manifest.hosted.mcpUrl,
|
|
3298
3515
|
});
|
|
3299
3516
|
instructionSource = instructionsWritten[0];
|
|
3300
3517
|
commands.push(...instructionsWritten.map((dir) => `write ${dir}`));
|
|
@@ -3333,7 +3550,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
3333
3550
|
scope: parsed.scope,
|
|
3334
3551
|
dryRun: Boolean(parsed.dryRun),
|
|
3335
3552
|
});
|
|
3336
|
-
if (
|
|
3553
|
+
if (shouldRegisterMcp) {
|
|
3337
3554
|
commands.push(`npx @agent-native/core@latest app-skill ensure --manifest ${installTarget.loaded.file} --client ${parsed.client} --scope ${parsed.scope} --yes`);
|
|
3338
3555
|
if (!parsed.dryRun) {
|
|
3339
3556
|
await ensureAppSkill(installTarget.loaded, {
|
|
@@ -3414,13 +3631,16 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
3414
3631
|
instructionSource,
|
|
3415
3632
|
skillNames: installTarget.skillNames,
|
|
3416
3633
|
skillsAgents,
|
|
3417
|
-
mcpUrl:
|
|
3418
|
-
|
|
3634
|
+
mcpUrl: knownTarget === "visual-plans" && planMode === "local-files"
|
|
3635
|
+
? ""
|
|
3636
|
+
: installTarget.loaded.manifest.hosted.mcpUrl,
|
|
3637
|
+
mcpClients: shouldRegisterMcp ? clients : [],
|
|
3419
3638
|
dryRun: parsed.dryRun,
|
|
3420
3639
|
commands,
|
|
3421
3640
|
written: instructionsWritten,
|
|
3422
3641
|
connected,
|
|
3423
3642
|
connectCommand,
|
|
3643
|
+
planMode,
|
|
3424
3644
|
githubActionPath,
|
|
3425
3645
|
githubActionExisted,
|
|
3426
3646
|
githubActionSuggestedCommand,
|
|
@@ -3454,6 +3674,7 @@ function skillStateJson(state) {
|
|
|
3454
3674
|
installedHash: state.installedHash,
|
|
3455
3675
|
latestHash: state.latestHash,
|
|
3456
3676
|
metadataHash: state.metadataHash,
|
|
3677
|
+
planMode: state.planMode,
|
|
3457
3678
|
};
|
|
3458
3679
|
}
|
|
3459
3680
|
function formatSkillState(state) {
|
|
@@ -3464,6 +3685,13 @@ function formatSkillState(state) {
|
|
|
3464
3685
|
: "";
|
|
3465
3686
|
return `${state.skillName.padEnd(22)} ${status.padEnd(7)} ${state.scope}/${state.client} ${managed}${hashes}\n ${state.path}`;
|
|
3466
3687
|
}
|
|
3688
|
+
function planModeSummary(mode) {
|
|
3689
|
+
if (mode === "local-files")
|
|
3690
|
+
return "Local files - No sharing, all local.";
|
|
3691
|
+
if (mode === "self-hosted")
|
|
3692
|
+
return "Self-hosted/custom Plan app";
|
|
3693
|
+
return "Hosted Plans - shareable links and comments";
|
|
3694
|
+
}
|
|
3467
3695
|
function runSkillsStatusOrUpdate(parsed, options, update) {
|
|
3468
3696
|
const before = collectSkillInstallStates(parsed, options);
|
|
3469
3697
|
const changed = update ? updateSkillInstallStates(before, parsed.dryRun) : [];
|
|
@@ -3586,6 +3814,45 @@ export async function runSkills(argv, options = {}) {
|
|
|
3586
3814
|
selectedAll: targets.length === skillPromptOptions().length,
|
|
3587
3815
|
preselected,
|
|
3588
3816
|
});
|
|
3817
|
+
const includesPlans = targetsIncludePlans(targets);
|
|
3818
|
+
if (parsed.planMode && !includesPlans) {
|
|
3819
|
+
throw new Error("--mode only applies to visual-plan / visual-recap.");
|
|
3820
|
+
}
|
|
3821
|
+
if (includesPlans) {
|
|
3822
|
+
if (!parsed.planMode && parsed.mcpUrl) {
|
|
3823
|
+
parsed.planMode = "self-hosted";
|
|
3824
|
+
}
|
|
3825
|
+
if (!parsed.planMode && shouldPrompt(parsed, options)) {
|
|
3826
|
+
const prompt = options.promptPlanMode ?? promptForPlanMode;
|
|
3827
|
+
const mode = await prompt({ initialMode: "hosted" });
|
|
3828
|
+
if (!mode) {
|
|
3829
|
+
telemetry.track("skills_cli cancelled", { step: "plan-mode" });
|
|
3830
|
+
return;
|
|
3831
|
+
}
|
|
3832
|
+
parsed.planMode = mode;
|
|
3833
|
+
}
|
|
3834
|
+
if (!parsed.planMode)
|
|
3835
|
+
parsed.planMode = "hosted";
|
|
3836
|
+
if (parsed.planMode === "self-hosted" && !parsed.mcpUrl) {
|
|
3837
|
+
if (shouldPrompt(parsed, options)) {
|
|
3838
|
+
const prompt = options.promptPlanMcpUrl ?? promptForPlanMcpUrl;
|
|
3839
|
+
const mcpUrl = await prompt();
|
|
3840
|
+
if (!mcpUrl) {
|
|
3841
|
+
telemetry.track("skills_cli cancelled", {
|
|
3842
|
+
step: "plan-mcp-url",
|
|
3843
|
+
});
|
|
3844
|
+
return;
|
|
3845
|
+
}
|
|
3846
|
+
parsed.mcpUrl = mcpUrl;
|
|
3847
|
+
}
|
|
3848
|
+
else {
|
|
3849
|
+
throw new Error("--mode self-hosted requires --mcp-url <url> in non-interactive mode.");
|
|
3850
|
+
}
|
|
3851
|
+
}
|
|
3852
|
+
telemetry.track("skills_cli plan mode selected", {
|
|
3853
|
+
mode: parsed.planMode,
|
|
3854
|
+
});
|
|
3855
|
+
}
|
|
3589
3856
|
const clients = await resolveSkillsClients(parsed, optionsWithTelemetry);
|
|
3590
3857
|
if (!clients) {
|
|
3591
3858
|
telemetry.track("skills_cli cancelled", { step: "clients" });
|
|
@@ -3684,6 +3951,11 @@ export async function runSkills(argv, options = {}) {
|
|
|
3684
3951
|
.filter((result) => result.local)
|
|
3685
3952
|
.flatMap((result) => result.commands)),
|
|
3686
3953
|
];
|
|
3954
|
+
const planModes = [
|
|
3955
|
+
...new Set(results
|
|
3956
|
+
.map((result) => result.planMode)
|
|
3957
|
+
.filter((mode) => Boolean(mode))),
|
|
3958
|
+
];
|
|
3687
3959
|
const authConnected = results.some((result) => result.connected);
|
|
3688
3960
|
const pendingConnectCommands = [
|
|
3689
3961
|
...new Set(results
|
|
@@ -3720,6 +3992,9 @@ export async function runSkills(argv, options = {}) {
|
|
|
3720
3992
|
? `MCP config ${mcpClients.join(", ")}`
|
|
3721
3993
|
: "MCP config not required",
|
|
3722
3994
|
mcpUrls.length ? `MCP URL ${mcpUrls.join(", ")}` : "",
|
|
3995
|
+
planModes.length
|
|
3996
|
+
? `Plan mode ${planModes.map(planModeSummary).join(", ")}`
|
|
3997
|
+
: "",
|
|
3723
3998
|
authConnected
|
|
3724
3999
|
? "Authentication completed"
|
|
3725
4000
|
: pendingConnectCommands.length
|