@agent-native/core 0.66.6 → 0.66.8
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/agent/run-manager.d.ts.map +1 -1
- package/dist/agent/run-manager.js +29 -4
- package/dist/agent/run-manager.js.map +1 -1
- package/dist/cli/code-agent-executor.js +2 -2
- package/dist/cli/code-agent-executor.js.map +1 -1
- package/dist/cli/index.js +2 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/skills.d.ts +9 -3
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +393 -45
- package/dist/cli/skills.js.map +1 -1
- package/dist/client/AgentPanel.d.ts.map +1 -1
- package/dist/client/AgentPanel.js +5 -6
- package/dist/client/AgentPanel.js.map +1 -1
- package/dist/client/blocks/library/AnnotatedCodeBlock.js +2 -2
- package/dist/client/blocks/library/AnnotatedCodeBlock.js.map +1 -1
- package/dist/client/blocks/library/DiffBlock.d.ts.map +1 -1
- package/dist/client/blocks/library/DiffBlock.js +1 -1
- package/dist/client/blocks/library/DiffBlock.js.map +1 -1
- package/dist/client/blocks/library/annotation-rail.d.ts +3 -1
- package/dist/client/blocks/library/annotation-rail.d.ts.map +1 -1
- package/dist/client/blocks/library/annotation-rail.js +32 -4
- package/dist/client/blocks/library/annotation-rail.js.map +1 -1
- package/dist/client/chat/runtime.d.ts.map +1 -1
- package/dist/client/chat/runtime.js +5 -2
- package/dist/client/chat/runtime.js.map +1 -1
- package/dist/client/error-format.d.ts +1 -1
- package/dist/client/error-format.d.ts.map +1 -1
- package/dist/client/error-format.js +23 -2
- package/dist/client/error-format.js.map +1 -1
- package/dist/client/sse-event-processor.d.ts.map +1 -1
- package/dist/client/sse-event-processor.js +3 -2
- package/dist/client/sse-event-processor.js.map +1 -1
- package/dist/file-upload/pre-upload-attachments.js +1 -1
- package/dist/file-upload/pre-upload-attachments.js.map +1 -1
- package/dist/scripts/runner.d.ts +1 -1
- package/dist/scripts/runner.d.ts.map +1 -1
- package/dist/scripts/runner.js +40 -6
- package/dist/scripts/runner.js.map +1 -1
- package/dist/templates/headless/AGENTS.md +1 -1
- package/dist/templates/headless/DEVELOPING.md +1 -1
- package/dist/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +11 -0
- package/docs/content/actions.md +11 -2
- package/docs/content/local-file-mode.md +25 -0
- package/docs/content/messaging.md +24 -0
- package/docs/content/skills-guide.md +3 -0
- package/docs/content/template-clips.md +60 -0
- package/docs/content/template-content.md +15 -0
- package/package.json +1 -1
- package/src/templates/headless/AGENTS.md +1 -1
- package/src/templates/headless/DEVELOPING.md +1 -1
- package/src/templates/workspace-core/.agents/skills/integration-webhooks/SKILL.md +11 -0
package/dist/cli/skills.js
CHANGED
|
@@ -19,13 +19,14 @@ const HELP = `npx @agent-native/core@latest skills
|
|
|
19
19
|
|
|
20
20
|
Usage:
|
|
21
21
|
npx @agent-native/core@latest skills list
|
|
22
|
-
npx @agent-native/core@latest skills status [assets|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|pi|all] [--scope user|project] [--json]
|
|
23
|
-
npx @agent-native/core@latest skills update [assets|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|pi|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|cowork|cursor|opencode|github-copilot|all] [--scope user|project] [--mode hosted|local-files|self-hosted] [--mcp-url <url>] [--no-connect] [--with-github-action] [--yes] [--dry-run] [--json]
|
|
22
|
+
npx @agent-native/core@latest skills status [assets|content|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|pi|all] [--scope user|project] [--json]
|
|
23
|
+
npx @agent-native/core@latest skills update [assets|content|design-exploration|visual-plan|visual-recap|context-xray] [--client codex|claude-code|pi|all] [--scope user|project] [--dry-run] [--json]
|
|
24
|
+
npx @agent-native/core@latest skills add assets|content|design-exploration|visual-plan|visual-recap|context-xray [--client codex|claude-code|cowork|cursor|opencode|github-copilot|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:
|
|
28
28
|
npx @agent-native/core@latest skills add assets
|
|
29
|
+
npx @agent-native/core@latest skills add content --mode local-files
|
|
29
30
|
npx @agent-native/core@latest skills add design-exploration
|
|
30
31
|
npx @agent-native/core@latest skills add visual-plan
|
|
31
32
|
npx @agent-native/core@latest skills add visual-recap
|
|
@@ -71,6 +72,12 @@ Pass --mode to choose directly. Local-files mode skips MCP registration and
|
|
|
71
72
|
auth and installs instructions that default to a no-auth block catalog fetch,
|
|
72
73
|
MDX folders, and the localhost bridge viewer.
|
|
73
74
|
|
|
75
|
+
When installing content with --mode local-files, the CLI installs Content
|
|
76
|
+
instructions and writes or updates agent-native.json with repo-backed Markdown /
|
|
77
|
+
MDX roots for docs, blog, content, and resources. Use a local Content app, Agent
|
|
78
|
+
Native Desktop, or another trusted local bridge for Content actions to read and
|
|
79
|
+
write those files.
|
|
80
|
+
|
|
74
81
|
When installing visual-recap interactively, the CLI offers to add the optional PR
|
|
75
82
|
Visual Recap GitHub Action. Pass --with-github-action to write it directly, then
|
|
76
83
|
run "npx @agent-native/core@latest recap setup" / "npx @agent-native/core@latest recap doctor" to configure and
|
|
@@ -161,6 +168,115 @@ of using a generic image generator.
|
|
|
161
168
|
- If you inspect local MCP config, redact \`Authorization\`, \`http_headers\`,
|
|
162
169
|
and token values. Never paste bearer tokens into chat or logs.
|
|
163
170
|
`;
|
|
171
|
+
const CONTENT_SKILL_MD = `---
|
|
172
|
+
name: content
|
|
173
|
+
description: >-
|
|
174
|
+
Use Content for repo-backed Markdown/MDX docs, blogs, resources, rich
|
|
175
|
+
document editing, local components, shareable copies, and Content local-file
|
|
176
|
+
workspaces. Prefer Content actions over raw filesystem writes when available.
|
|
177
|
+
metadata:
|
|
178
|
+
visibility: exported
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
# Content
|
|
182
|
+
|
|
183
|
+
Use the Content app when a workflow is about authoring, editing, reviewing, or
|
|
184
|
+
publishing Markdown/MDX documents: docs sites, blogs, resource libraries,
|
|
185
|
+
marketing pages, internal notes, and local MDX components. Content gives the
|
|
186
|
+
agent a document tree, a rich editor, normal document actions, and optional
|
|
187
|
+
local-file source of truth.
|
|
188
|
+
|
|
189
|
+
## Choose The Path
|
|
190
|
+
|
|
191
|
+
- Use Content actions when the Content MCP/action tools are available:
|
|
192
|
+
\`list-documents\`, \`search-documents\`, \`get-document\`,
|
|
193
|
+
\`pull-document\`, \`create-document\`, \`edit-document\`,
|
|
194
|
+
\`update-document\`, \`delete-document\`, \`share-local-file-document\`,
|
|
195
|
+
\`list-local-component-files\`, and \`write-local-component-file\`.
|
|
196
|
+
- Use \`pull-document\` or \`get-document\` before editing a page. Use
|
|
197
|
+
\`edit-document\` for precise find/replace changes and \`update-document\`
|
|
198
|
+
for full rewrites or new content.
|
|
199
|
+
- In Local File Mode, Content actions read and write the repo files declared in
|
|
200
|
+
\`agent-native.json\`; SQL remains cache/history/search glue, not the source of
|
|
201
|
+
truth for those pages.
|
|
202
|
+
- If Content tools are not visible and no local Content app or Desktop bridge is
|
|
203
|
+
running, treat this skill as repo-editing guidance. Edit configured
|
|
204
|
+
\`.md\`/\`.mdx\` files directly, preserve frontmatter and MDX imports, and tell
|
|
205
|
+
the user the Content action surface was not available.
|
|
206
|
+
|
|
207
|
+
## Action Examples
|
|
208
|
+
|
|
209
|
+
Prefer JSON input for action calls:
|
|
210
|
+
|
|
211
|
+
\`\`\`bash
|
|
212
|
+
pnpm action list-documents
|
|
213
|
+
pnpm action get-document '{"id":"local-file:..."}'
|
|
214
|
+
pnpm action edit-document '{"id":"local-file:...","find":"old copy","replace":"new copy"}'
|
|
215
|
+
pnpm action update-document '{"id":"local-file:...","content":"# Updated\\n\\nBody"}'
|
|
216
|
+
pnpm action share-local-file-document '{"id":"local-file:..."}'
|
|
217
|
+
\`\`\`
|
|
218
|
+
|
|
219
|
+
Run \`refresh-list\` after create/update/delete operations when you need the
|
|
220
|
+
open Content UI sidebar to repaint immediately.
|
|
221
|
+
|
|
222
|
+
## Local File Mode
|
|
223
|
+
|
|
224
|
+
Install into an existing repo with:
|
|
225
|
+
|
|
226
|
+
\`\`\`bash
|
|
227
|
+
npx @agent-native/core@latest skills add content --mode local-files --scope project
|
|
228
|
+
\`\`\`
|
|
229
|
+
|
|
230
|
+
The installer copies this skill and writes or updates \`agent-native.json\` with
|
|
231
|
+
Content roots for \`docs/\`, \`blog/\`, \`content/\`, and \`resources/\`, plus a
|
|
232
|
+
\`components/\` folder for local MDX components. A typical manifest looks like:
|
|
233
|
+
|
|
234
|
+
\`\`\`json
|
|
235
|
+
{
|
|
236
|
+
"version": 1,
|
|
237
|
+
"apps": {
|
|
238
|
+
"content": {
|
|
239
|
+
"mode": "local-files",
|
|
240
|
+
"roots": [
|
|
241
|
+
{ "name": "Docs", "path": "docs", "kind": "docs", "extensions": [".md", ".mdx"] },
|
|
242
|
+
{ "name": "Blog", "path": "blog", "kind": "blog", "extensions": [".md", ".mdx"] },
|
|
243
|
+
{ "name": "Content", "path": "content", "kind": "content", "extensions": [".md", ".mdx"] },
|
|
244
|
+
{ "name": "Resources", "path": "resources", "kind": "resources", "extensions": [".md", ".mdx"] }
|
|
245
|
+
],
|
|
246
|
+
"components": "components",
|
|
247
|
+
"extensions": "extensions",
|
|
248
|
+
"hide": ["**/_*.md", "**/_*.mdx"]
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
\`\`\`
|
|
253
|
+
|
|
254
|
+
Local File Mode does not make the host language model local, and the hosted
|
|
255
|
+
Content app cannot read private repo files by itself. File access requires a
|
|
256
|
+
local Content app, Agent Native Desktop, or another trusted local bridge.
|
|
257
|
+
|
|
258
|
+
## MDX And Components
|
|
259
|
+
|
|
260
|
+
- Preserve frontmatter keys you do not understand. Preserve MDX imports,
|
|
261
|
+
exports, JSX, and expression props unless the user explicitly asks to change
|
|
262
|
+
them.
|
|
263
|
+
- Use local components from the configured \`components\` folder. Components
|
|
264
|
+
should be PascalCase exports from \`.tsx\` files; simple editable input metadata
|
|
265
|
+
can live next to them as \`ComponentNameInputs\`.
|
|
266
|
+
- Use \`list-local-component-files\` and \`write-local-component-file\` for
|
|
267
|
+
component source changes when Content tools are available. Otherwise edit the
|
|
268
|
+
component files directly like normal repo source.
|
|
269
|
+
|
|
270
|
+
## Boundaries
|
|
271
|
+
|
|
272
|
+
- Moving, renaming, and reordering local-file pages are not first-class Content
|
|
273
|
+
UI operations yet. Use normal file operations when the user asks for those,
|
|
274
|
+
then let Content rediscover the file tree.
|
|
275
|
+
- Do not push/pull Notion, Builder.io, or other provider-backed content unless
|
|
276
|
+
the user explicitly asks for provider sync.
|
|
277
|
+
- Do not paste secrets, private provider data, or credential-looking values into
|
|
278
|
+
docs, generated pages, frontmatter, examples, or local components.
|
|
279
|
+
`;
|
|
164
280
|
const DESIGN_EXPLORATION_SKILL_MD = `---
|
|
165
281
|
name: design-exploration
|
|
166
282
|
description: >-
|
|
@@ -2164,6 +2280,53 @@ export const BUILT_IN_APP_SKILLS = {
|
|
|
2164
2280
|
}),
|
|
2165
2281
|
skillMarkdown: ASSETS_SKILL_MD,
|
|
2166
2282
|
},
|
|
2283
|
+
content: {
|
|
2284
|
+
skillName: "content",
|
|
2285
|
+
manifest: normalizeAppSkillManifest({
|
|
2286
|
+
schemaVersion: 1,
|
|
2287
|
+
id: "content",
|
|
2288
|
+
displayName: "Content",
|
|
2289
|
+
description: "Edit docs, blogs, resources, and MDX content through the Content app, including repo-backed Local File Mode.",
|
|
2290
|
+
hosted: {
|
|
2291
|
+
url: "https://content.agent-native.com",
|
|
2292
|
+
mcpUrl: "https://content.agent-native.com/_agent-native/mcp",
|
|
2293
|
+
},
|
|
2294
|
+
mcp: { serverName: "agent-native-content" },
|
|
2295
|
+
auth: {
|
|
2296
|
+
mode: "oauth",
|
|
2297
|
+
setup: "Authenticate with the Content MCP connector in the host app. Local File Mode requires a local Content app, Agent Native Desktop, or trusted local bridge for filesystem access.",
|
|
2298
|
+
},
|
|
2299
|
+
surfaces: [
|
|
2300
|
+
{
|
|
2301
|
+
id: "content-documents",
|
|
2302
|
+
action: "list-documents",
|
|
2303
|
+
path: "/",
|
|
2304
|
+
},
|
|
2305
|
+
{
|
|
2306
|
+
id: "content-local-files",
|
|
2307
|
+
action: "share-local-file-document",
|
|
2308
|
+
path: "/local-files",
|
|
2309
|
+
},
|
|
2310
|
+
],
|
|
2311
|
+
skills: [
|
|
2312
|
+
{
|
|
2313
|
+
path: "skills/content",
|
|
2314
|
+
visibility: "exported",
|
|
2315
|
+
exportAs: "content",
|
|
2316
|
+
},
|
|
2317
|
+
],
|
|
2318
|
+
hostAdapters: [
|
|
2319
|
+
"codex-plugin",
|
|
2320
|
+
"claude-marketplace",
|
|
2321
|
+
"vercel-skills",
|
|
2322
|
+
"plain-skill",
|
|
2323
|
+
"claude-skill",
|
|
2324
|
+
"chatgpt-mcp",
|
|
2325
|
+
"generic-mcp",
|
|
2326
|
+
],
|
|
2327
|
+
}),
|
|
2328
|
+
skillMarkdown: CONTENT_SKILL_MD,
|
|
2329
|
+
},
|
|
2167
2330
|
design: {
|
|
2168
2331
|
skillName: "design-exploration",
|
|
2169
2332
|
manifest: normalizeAppSkillManifest({
|
|
@@ -2318,6 +2481,12 @@ const BUILT_IN_APP_SKILL_ALIASES = {
|
|
|
2318
2481
|
"image-generation": "assets",
|
|
2319
2482
|
"agent-native-assets": "assets",
|
|
2320
2483
|
"agent-native-images": "assets",
|
|
2484
|
+
content: "content",
|
|
2485
|
+
docs: "content",
|
|
2486
|
+
documents: "content",
|
|
2487
|
+
"local-content": "content",
|
|
2488
|
+
"content-local-files": "content",
|
|
2489
|
+
"agent-native-content": "content",
|
|
2321
2490
|
design: "design",
|
|
2322
2491
|
"ui-design": "design",
|
|
2323
2492
|
"ux-design": "design",
|
|
@@ -2345,6 +2514,13 @@ const BUILT_IN_APP_SKILL_ALIASES = {
|
|
|
2345
2514
|
};
|
|
2346
2515
|
const BUILT_IN_APP_SKILL_DISPLAY_ALIASES = {
|
|
2347
2516
|
assets: ["images", "image-generation", "agent-native-images"],
|
|
2517
|
+
content: [
|
|
2518
|
+
"docs",
|
|
2519
|
+
"documents",
|
|
2520
|
+
"local-content",
|
|
2521
|
+
"content-local-files",
|
|
2522
|
+
"agent-native-content",
|
|
2523
|
+
],
|
|
2348
2524
|
design: [
|
|
2349
2525
|
"design-exploration",
|
|
2350
2526
|
"ux-exploration",
|
|
@@ -2431,6 +2607,12 @@ function isKnownSkill(value) {
|
|
|
2431
2607
|
function isLocalOnlyBuiltInSkill(entry) {
|
|
2432
2608
|
return Boolean(entry && "localOnly" in entry && entry.localOnly);
|
|
2433
2609
|
}
|
|
2610
|
+
function targetSupportsInstallMode(targetId) {
|
|
2611
|
+
return targetId === "visual-plans" || targetId === "content";
|
|
2612
|
+
}
|
|
2613
|
+
function localFilesModeSkipsMcp(targetId, mode) {
|
|
2614
|
+
return mode === "local-files" && targetSupportsInstallMode(targetId);
|
|
2615
|
+
}
|
|
2434
2616
|
function builtInExtraSkills(entry) {
|
|
2435
2617
|
return "extraSkills" in entry && entry.extraSkills ? entry.extraSkills : {};
|
|
2436
2618
|
}
|
|
@@ -2508,19 +2690,49 @@ for plans and recaps instead of assuming \`https://plan.agent-native.com\`.`;
|
|
|
2508
2690
|
}
|
|
2509
2691
|
return "";
|
|
2510
2692
|
}
|
|
2511
|
-
function
|
|
2512
|
-
if (input.
|
|
2513
|
-
return
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2693
|
+
function contentModeInstructionBlock(input) {
|
|
2694
|
+
if (input.mode === "local-files") {
|
|
2695
|
+
return `## Installed Mode
|
|
2696
|
+
|
|
2697
|
+
Default storage for this installation: Content Local File Mode. This repo should
|
|
2698
|
+
have an \`agent-native.json\` file with \`apps.content.mode: "local-files"\`;
|
|
2699
|
+
the installer writes one if missing and fills in default roots for \`docs/\`,
|
|
2700
|
+
\`blog/\`, \`content/\`, and \`resources/\`. Prefer Content document actions
|
|
2701
|
+
when a local Content app,
|
|
2702
|
+
Agent Native Desktop, or another trusted local bridge exposes them. If those
|
|
2703
|
+
tools are not currently available, edit the configured Markdown/MDX files and
|
|
2704
|
+
local components directly, preserving frontmatter, imports, JSX, and unknown MDX
|
|
2705
|
+
syntax. The hosted Content app cannot read private repo files by itself.`;
|
|
2706
|
+
}
|
|
2707
|
+
if (input.mode === "self-hosted") {
|
|
2708
|
+
return `## Installed Mode
|
|
2709
|
+
|
|
2710
|
+
Default storage for this installation: the configured self-hosted/custom Content
|
|
2711
|
+
app${input.mcpUrl ? ` at \`${input.mcpUrl}\`` : ""}. Use that Content MCP
|
|
2712
|
+
connector instead of assuming \`https://content.agent-native.com\`.`;
|
|
2713
|
+
}
|
|
2714
|
+
return "";
|
|
2715
|
+
}
|
|
2716
|
+
function applyInstallModeToSkillMarkdown(markdown, input) {
|
|
2717
|
+
let block = "";
|
|
2718
|
+
if (input.appSkillId === "visual-plans") {
|
|
2719
|
+
block = planModeInstructionBlock({
|
|
2720
|
+
mode: input.mode,
|
|
2721
|
+
mcpUrl: input.mcpUrl,
|
|
2722
|
+
});
|
|
2723
|
+
}
|
|
2724
|
+
else if (input.appSkillId === "content") {
|
|
2725
|
+
block = contentModeInstructionBlock({
|
|
2726
|
+
mode: input.mode,
|
|
2727
|
+
mcpUrl: input.mcpUrl,
|
|
2728
|
+
});
|
|
2729
|
+
}
|
|
2518
2730
|
return insertAfterFrontmatter(markdown, block);
|
|
2519
2731
|
}
|
|
2520
2732
|
function skillFilesForBuiltIn(appSkillId, options = {}) {
|
|
2521
2733
|
const entry = BUILT_IN_APP_SKILLS[appSkillId];
|
|
2522
2734
|
const skills = {
|
|
2523
|
-
[entry.skillName]:
|
|
2735
|
+
[entry.skillName]: applyInstallModeToSkillMarkdown(entry.skillMarkdown, {
|
|
2524
2736
|
appSkillId,
|
|
2525
2737
|
mode: options.planMode,
|
|
2526
2738
|
mcpUrl: options.mcpUrl,
|
|
@@ -2528,7 +2740,7 @@ function skillFilesForBuiltIn(appSkillId, options = {}) {
|
|
|
2528
2740
|
...builtInExtraSkills(entry),
|
|
2529
2741
|
};
|
|
2530
2742
|
for (const [skillName, skillMarkdown] of Object.entries(builtInExtraSkills(entry))) {
|
|
2531
|
-
skills[skillName] =
|
|
2743
|
+
skills[skillName] = applyInstallModeToSkillMarkdown(skillMarkdown, {
|
|
2532
2744
|
appSkillId,
|
|
2533
2745
|
mode: options.planMode,
|
|
2534
2746
|
mcpUrl: options.mcpUrl,
|
|
@@ -2545,7 +2757,8 @@ function skillFilesForBuiltIn(appSkillId, options = {}) {
|
|
|
2545
2757
|
appSkillId,
|
|
2546
2758
|
displayName: entry.manifest.displayName,
|
|
2547
2759
|
skillName,
|
|
2548
|
-
mcpUrl: isLocalOnlyBuiltInSkill(entry) ||
|
|
2760
|
+
mcpUrl: isLocalOnlyBuiltInSkill(entry) ||
|
|
2761
|
+
localFilesModeSkipsMcp(appSkillId, options.planMode)
|
|
2549
2762
|
? ""
|
|
2550
2763
|
: (options.mcpUrl ?? entry.manifest.hosted.mcpUrl),
|
|
2551
2764
|
files,
|
|
@@ -2584,6 +2797,90 @@ function writeSkillFolder(dir, bundle, installedAt = new Date().toISOString()) {
|
|
|
2584
2797
|
};
|
|
2585
2798
|
fs.writeFileSync(path.join(dir, AGENT_NATIVE_SKILL_METADATA_FILE), `${JSON.stringify(metadata, null, 2)}\n`, "utf-8");
|
|
2586
2799
|
}
|
|
2800
|
+
function isJsonRecord(value) {
|
|
2801
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
2802
|
+
}
|
|
2803
|
+
function defaultContentLocalFilesAppConfig() {
|
|
2804
|
+
return {
|
|
2805
|
+
mode: "local-files",
|
|
2806
|
+
roots: [
|
|
2807
|
+
{
|
|
2808
|
+
name: "Docs",
|
|
2809
|
+
path: "docs",
|
|
2810
|
+
kind: "docs",
|
|
2811
|
+
extensions: [".md", ".mdx"],
|
|
2812
|
+
},
|
|
2813
|
+
{
|
|
2814
|
+
name: "Blog",
|
|
2815
|
+
path: "blog",
|
|
2816
|
+
kind: "blog",
|
|
2817
|
+
extensions: [".md", ".mdx"],
|
|
2818
|
+
},
|
|
2819
|
+
{
|
|
2820
|
+
name: "Content",
|
|
2821
|
+
path: "content",
|
|
2822
|
+
kind: "content",
|
|
2823
|
+
extensions: [".md", ".mdx"],
|
|
2824
|
+
},
|
|
2825
|
+
{
|
|
2826
|
+
name: "Resources",
|
|
2827
|
+
path: "resources",
|
|
2828
|
+
kind: "resources",
|
|
2829
|
+
extensions: [".md", ".mdx"],
|
|
2830
|
+
},
|
|
2831
|
+
],
|
|
2832
|
+
components: "components",
|
|
2833
|
+
extensions: "extensions",
|
|
2834
|
+
hide: ["**/_*.md", "**/_*.mdx"],
|
|
2835
|
+
};
|
|
2836
|
+
}
|
|
2837
|
+
function contentLocalFilesManifestPath(baseDir) {
|
|
2838
|
+
return path.join(baseDir, "agent-native.json");
|
|
2839
|
+
}
|
|
2840
|
+
function shouldWriteContentLocalFilesManifest(targetId, mode) {
|
|
2841
|
+
return targetId === "content" && mode === "local-files";
|
|
2842
|
+
}
|
|
2843
|
+
function mergeContentLocalFilesManifest(existing) {
|
|
2844
|
+
const manifest = isJsonRecord(existing) ? { ...existing } : {};
|
|
2845
|
+
if (manifest.version === undefined)
|
|
2846
|
+
manifest.version = 1;
|
|
2847
|
+
const apps = isJsonRecord(manifest.apps) ? { ...manifest.apps } : {};
|
|
2848
|
+
const contentApp = isJsonRecord(apps.content) ? { ...apps.content } : {};
|
|
2849
|
+
const defaults = defaultContentLocalFilesAppConfig();
|
|
2850
|
+
contentApp.mode = "local-files";
|
|
2851
|
+
if (!Array.isArray(contentApp.roots) || contentApp.roots.length === 0) {
|
|
2852
|
+
contentApp.roots = defaults.roots;
|
|
2853
|
+
}
|
|
2854
|
+
if (contentApp.components === undefined) {
|
|
2855
|
+
contentApp.components = defaults.components;
|
|
2856
|
+
}
|
|
2857
|
+
if (contentApp.extensions === undefined) {
|
|
2858
|
+
contentApp.extensions = defaults.extensions;
|
|
2859
|
+
}
|
|
2860
|
+
if (!Array.isArray(contentApp.hide) || contentApp.hide.length === 0) {
|
|
2861
|
+
contentApp.hide = defaults.hide;
|
|
2862
|
+
}
|
|
2863
|
+
apps.content = contentApp;
|
|
2864
|
+
manifest.apps = apps;
|
|
2865
|
+
return manifest;
|
|
2866
|
+
}
|
|
2867
|
+
function writeContentLocalFilesManifest(baseDir, options = {}) {
|
|
2868
|
+
const manifestPath = contentLocalFilesManifestPath(baseDir);
|
|
2869
|
+
let existing = {};
|
|
2870
|
+
if (fs.existsSync(manifestPath)) {
|
|
2871
|
+
try {
|
|
2872
|
+
existing = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
2873
|
+
}
|
|
2874
|
+
catch (error) {
|
|
2875
|
+
throw new Error(`Could not parse ${manifestPath}: ${error?.message ?? error}`);
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
const manifest = mergeContentLocalFilesManifest(existing);
|
|
2879
|
+
if (!options.dryRun) {
|
|
2880
|
+
fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf-8");
|
|
2881
|
+
}
|
|
2882
|
+
return manifestPath;
|
|
2883
|
+
}
|
|
2587
2884
|
/**
|
|
2588
2885
|
* The skills directory a built-in skill's instructions are copied into for a
|
|
2589
2886
|
* given agent + scope. Mirrors the layout the skills installer uses so
|
|
@@ -2979,6 +3276,11 @@ const BUILT_IN_SKILL_PROMPT_OPTIONS = [
|
|
|
2979
3276
|
label: "assets",
|
|
2980
3277
|
hint: BUILT_IN_APP_SKILLS.assets.manifest.description,
|
|
2981
3278
|
},
|
|
3279
|
+
{
|
|
3280
|
+
value: "content",
|
|
3281
|
+
label: "content",
|
|
3282
|
+
hint: BUILT_IN_APP_SKILLS.content.manifest.description,
|
|
3283
|
+
},
|
|
2982
3284
|
{
|
|
2983
3285
|
value: "design-exploration",
|
|
2984
3286
|
label: "design-exploration",
|
|
@@ -3262,11 +3564,21 @@ function targetIncludesPlans(target) {
|
|
|
3262
3564
|
function targetsIncludePlans(targets) {
|
|
3263
3565
|
return targets.some(targetIncludesPlans);
|
|
3264
3566
|
}
|
|
3567
|
+
function targetIncludesInstallModeSkill(target) {
|
|
3568
|
+
return targetSupportsInstallMode(normalizeKnownSkillTarget(target));
|
|
3569
|
+
}
|
|
3570
|
+
function targetsIncludeInstallModeSkills(targets) {
|
|
3571
|
+
return targets.some(targetIncludesInstallModeSkill);
|
|
3572
|
+
}
|
|
3265
3573
|
function planSkillNamesSelected(skillNames) {
|
|
3266
3574
|
return Boolean(skillNames?.some((name) => normalizeKnownSkillTarget(name) === "visual-plans"));
|
|
3267
3575
|
}
|
|
3576
|
+
function installModeSkillNamesSelected(skillNames) {
|
|
3577
|
+
return Boolean(skillNames?.some((name) => targetSupportsInstallMode(normalizeKnownSkillTarget(name))));
|
|
3578
|
+
}
|
|
3268
3579
|
function shouldForwardPlanModeFlag(target, skillNames) {
|
|
3269
|
-
return
|
|
3580
|
+
return (targetIncludesInstallModeSkill(target) ||
|
|
3581
|
+
installModeSkillNamesSelected(skillNames));
|
|
3270
3582
|
}
|
|
3271
3583
|
function recapSkillNamesSelected(skillNames) {
|
|
3272
3584
|
return Boolean(skillNames?.some((name) => {
|
|
@@ -3484,6 +3796,9 @@ function loadSkillTarget(target, onlySkillNames) {
|
|
|
3484
3796
|
dir: process.cwd(),
|
|
3485
3797
|
},
|
|
3486
3798
|
skillNames,
|
|
3799
|
+
modeAwareId: targetSupportsInstallMode(knownTarget)
|
|
3800
|
+
? knownTarget
|
|
3801
|
+
: undefined,
|
|
3487
3802
|
materializeInstructions(outDir) {
|
|
3488
3803
|
const bundles = skillFilesForBuiltIn(knownTarget);
|
|
3489
3804
|
for (const bundle of Object.values(bundles)) {
|
|
@@ -3508,6 +3823,9 @@ function loadSkillTarget(target, onlySkillNames) {
|
|
|
3508
3823
|
skillNames: loaded.manifest.skills
|
|
3509
3824
|
.filter((skill) => skill.visibility === "exported" || skill.visibility === "both")
|
|
3510
3825
|
.map((skill) => skill.exportAs ?? path.basename(skill.path)),
|
|
3826
|
+
modeAwareId: targetSupportsInstallMode(loaded.manifest.id)
|
|
3827
|
+
? loaded.manifest.id
|
|
3828
|
+
: undefined,
|
|
3511
3829
|
materializeInstructions(outDir) {
|
|
3512
3830
|
const packed = buildAppSkillPack(loaded, outDir);
|
|
3513
3831
|
const vercelAdapter = path.join(packed.outDir, "adapters", "vercel-skills");
|
|
@@ -3571,7 +3889,7 @@ function preserveMcpUrlAppPathOverride(target, input) {
|
|
|
3571
3889
|
},
|
|
3572
3890
|
};
|
|
3573
3891
|
}
|
|
3574
|
-
function dryRunInstallCommand(parsed, target) {
|
|
3892
|
+
function dryRunInstallCommand(parsed, target, options = {}) {
|
|
3575
3893
|
const clients = parsed.clients ??
|
|
3576
3894
|
resolveSkillsClientArg(parsed.client, targetInstallsMcp(target, parsed));
|
|
3577
3895
|
const args = [
|
|
@@ -3585,7 +3903,8 @@ function dryRunInstallCommand(parsed, target) {
|
|
|
3585
3903
|
parsed.scope,
|
|
3586
3904
|
];
|
|
3587
3905
|
const forwardsPlanFlags = shouldForwardPlanModeFlag(target, parsed.plainSkillNames);
|
|
3588
|
-
|
|
3906
|
+
const forwardsInstallMode = forwardsPlanFlags || targetSupportsInstallMode(options.modeAwareTargetId);
|
|
3907
|
+
if (forwardsInstallMode && parsed.planMode)
|
|
3589
3908
|
args.push("--mode", parsed.planMode);
|
|
3590
3909
|
if (parsed.mcpUrl)
|
|
3591
3910
|
args.push("--mcp-url", parsed.mcpUrl);
|
|
@@ -3752,7 +4071,7 @@ async function addPlainSkillRepo(parsed, options) {
|
|
|
3752
4071
|
if (!parsed.instructions && parsed.mcp) {
|
|
3753
4072
|
throw new Error("Plain skill repositories only install skill instructions. Run without --mcp-only.");
|
|
3754
4073
|
}
|
|
3755
|
-
if (parsed.mcpUrl && !
|
|
4074
|
+
if (parsed.mcpUrl && !installModeSkillNamesSelected(parsed.plainSkillNames)) {
|
|
3756
4075
|
throw new Error("--mcp-url only applies to app-backed Agent Native skills.");
|
|
3757
4076
|
}
|
|
3758
4077
|
const clients = parsed.clients ?? resolveSkillsClientArg(parsed.client);
|
|
@@ -3942,20 +4261,6 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
3942
4261
|
}, options);
|
|
3943
4262
|
}
|
|
3944
4263
|
const knownTarget = normalizeKnownSkillTarget(target);
|
|
3945
|
-
const planMode = knownTarget === "visual-plans"
|
|
3946
|
-
? (parsed.planMode ?? (parsed.mcpUrl ? "self-hosted" : "hosted"))
|
|
3947
|
-
: undefined;
|
|
3948
|
-
if (parsed.planMode && knownTarget !== "visual-plans") {
|
|
3949
|
-
throw new Error("--mode only applies to visual-plan / visual-recap.");
|
|
3950
|
-
}
|
|
3951
|
-
if (planMode === "local-files" && parsed.mcpUrl) {
|
|
3952
|
-
throw new Error("--mode local-files cannot be combined with --mcp-url.");
|
|
3953
|
-
}
|
|
3954
|
-
if (planMode === "self-hosted" && !parsed.mcpUrl) {
|
|
3955
|
-
throw new Error("--mode self-hosted requires --mcp-url <url>.");
|
|
3956
|
-
}
|
|
3957
|
-
const shouldRegisterMcp = parsed.mcp &&
|
|
3958
|
-
!(knownTarget === "visual-plans" && planMode === "local-files");
|
|
3959
4264
|
// For multi-skill bundles (the plan bundle), a single-skill target installs
|
|
3960
4265
|
// only that skill. `installsRecap` controls the PR Visual Recap github-action
|
|
3961
4266
|
// offer, which is only relevant when the recap skill is part of the install.
|
|
@@ -3971,7 +4276,11 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
3971
4276
|
throw new Error(`Unknown skill or manifest path: ${target}. Run "npx @agent-native/core@latest skills list".`);
|
|
3972
4277
|
}
|
|
3973
4278
|
const knownBuiltIn = knownTarget ? BUILT_IN_APP_SKILLS[knownTarget] : null;
|
|
4279
|
+
const baseDir = options.baseDir ?? process.cwd();
|
|
3974
4280
|
if (isLocalOnlyBuiltInSkill(knownBuiltIn)) {
|
|
4281
|
+
if (parsed.planMode) {
|
|
4282
|
+
throw new Error("--mode only applies to visual-plan / visual-recap / content.");
|
|
4283
|
+
}
|
|
3975
4284
|
if (parsed.mcpUrl) {
|
|
3976
4285
|
throw new Error("Context X-Ray is installed locally and does not use --mcp-url yet.");
|
|
3977
4286
|
}
|
|
@@ -4004,7 +4313,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4004
4313
|
};
|
|
4005
4314
|
}
|
|
4006
4315
|
const localInstall = installLocalContextXray({
|
|
4007
|
-
baseDir
|
|
4316
|
+
baseDir,
|
|
4008
4317
|
clients,
|
|
4009
4318
|
scope: parsed.scope,
|
|
4010
4319
|
});
|
|
@@ -4030,6 +4339,25 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4030
4339
|
};
|
|
4031
4340
|
}
|
|
4032
4341
|
let installTarget = loadSkillTarget(target, onlySkillNames);
|
|
4342
|
+
const modeAwareTargetId = installTarget.modeAwareId;
|
|
4343
|
+
const planMode = modeAwareTargetId
|
|
4344
|
+
? (parsed.planMode ??
|
|
4345
|
+
(parsed.mcpUrl
|
|
4346
|
+
? "self-hosted"
|
|
4347
|
+
: modeAwareTargetId === "visual-plans"
|
|
4348
|
+
? "hosted"
|
|
4349
|
+
: undefined))
|
|
4350
|
+
: undefined;
|
|
4351
|
+
if (parsed.planMode && !modeAwareTargetId) {
|
|
4352
|
+
throw new Error("--mode only applies to visual-plan / visual-recap / content.");
|
|
4353
|
+
}
|
|
4354
|
+
if (planMode === "local-files" && parsed.mcpUrl) {
|
|
4355
|
+
throw new Error("--mode local-files cannot be combined with --mcp-url.");
|
|
4356
|
+
}
|
|
4357
|
+
if (planMode === "self-hosted" && !parsed.mcpUrl) {
|
|
4358
|
+
throw new Error("--mode self-hosted requires --mcp-url <url>.");
|
|
4359
|
+
}
|
|
4360
|
+
const shouldRegisterMcp = parsed.mcp && !localFilesModeSkipsMcp(modeAwareTargetId, planMode);
|
|
4033
4361
|
if (parsed.mcpUrl) {
|
|
4034
4362
|
installTarget = withMcpUrlOverride(installTarget, parsed.mcpUrl);
|
|
4035
4363
|
}
|
|
@@ -4042,6 +4370,9 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4042
4370
|
const skillsAgents = skillsAgentsForClients(clients);
|
|
4043
4371
|
if (parsed.dryRun) {
|
|
4044
4372
|
try {
|
|
4373
|
+
const localManifestPath = shouldWriteContentLocalFilesManifest(modeAwareTargetId, planMode)
|
|
4374
|
+
? contentLocalFilesManifestPath(baseDir)
|
|
4375
|
+
: undefined;
|
|
4045
4376
|
const githubActionPath = parsed.withGithubAction && installsRecap
|
|
4046
4377
|
? prVisualRecapWorkflowDisplayPath()
|
|
4047
4378
|
: undefined;
|
|
@@ -4059,15 +4390,19 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4059
4390
|
displayName: installTarget.displayName,
|
|
4060
4391
|
skillNames: installTarget.skillNames,
|
|
4061
4392
|
skillsAgents,
|
|
4062
|
-
mcpUrl:
|
|
4393
|
+
mcpUrl: localFilesModeSkipsMcp(modeAwareTargetId, planMode)
|
|
4063
4394
|
? ""
|
|
4064
4395
|
: installTarget.loaded.manifest.hosted.mcpUrl,
|
|
4065
4396
|
mcpClients: shouldRegisterMcp ? mcpClients : [],
|
|
4066
4397
|
dryRun: true,
|
|
4067
|
-
commands: [
|
|
4398
|
+
commands: [
|
|
4399
|
+
dryRunInstallCommand(parsed, target, { modeAwareTargetId }),
|
|
4400
|
+
...(localManifestPath ? [`write ${localManifestPath}`] : []),
|
|
4401
|
+
],
|
|
4068
4402
|
githubActionPath,
|
|
4069
4403
|
githubActionSuggestedCommand,
|
|
4070
4404
|
planMode,
|
|
4405
|
+
localManifestPath,
|
|
4071
4406
|
};
|
|
4072
4407
|
}
|
|
4073
4408
|
finally {
|
|
@@ -4081,6 +4416,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4081
4416
|
let connected = false;
|
|
4082
4417
|
let connectCommand;
|
|
4083
4418
|
let registeredMcpClients = shouldRegisterMcp ? mcpClients : [];
|
|
4419
|
+
let localManifestPath;
|
|
4084
4420
|
try {
|
|
4085
4421
|
if (parsed.instructions) {
|
|
4086
4422
|
if (skillsAgents.length === 0) {
|
|
@@ -4098,7 +4434,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4098
4434
|
onlySkillNames,
|
|
4099
4435
|
skillsAgents,
|
|
4100
4436
|
scope: parsed.scope,
|
|
4101
|
-
baseDir
|
|
4437
|
+
baseDir,
|
|
4102
4438
|
dryRun: parsed.dryRun,
|
|
4103
4439
|
planMode,
|
|
4104
4440
|
mcpUrl: installTarget.loaded.manifest.hosted.mcpUrl,
|
|
@@ -4121,6 +4457,12 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4121
4457
|
...installTarget.skillNames.flatMap((skill) => ["--skill", skill]),
|
|
4122
4458
|
...skillsAgents.flatMap((agent) => ["-a", agent]),
|
|
4123
4459
|
...(parsed.scope === "user" ? ["-g"] : []),
|
|
4460
|
+
...(modeAwareTargetId && parsed.planMode
|
|
4461
|
+
? ["--mode", parsed.planMode]
|
|
4462
|
+
: []),
|
|
4463
|
+
...(modeAwareTargetId && parsed.mcpUrl
|
|
4464
|
+
? ["--mcp-url", parsed.mcpUrl]
|
|
4465
|
+
: []),
|
|
4124
4466
|
...(parsed.yes || knownTarget ? ["-y"] : []),
|
|
4125
4467
|
];
|
|
4126
4468
|
commands.push(commandString("npx", args));
|
|
@@ -4133,6 +4475,10 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4133
4475
|
}
|
|
4134
4476
|
}
|
|
4135
4477
|
}
|
|
4478
|
+
if (shouldWriteContentLocalFilesManifest(modeAwareTargetId, planMode)) {
|
|
4479
|
+
localManifestPath = writeContentLocalFilesManifest(baseDir);
|
|
4480
|
+
commands.push(`write ${localManifestPath}`);
|
|
4481
|
+
}
|
|
4136
4482
|
// Skill instructions are now on disk (built-in folders copied or external
|
|
4137
4483
|
// pack materialized) — record the install before MCP registration/connect.
|
|
4138
4484
|
options.telemetry?.track("skills_cli install completed", {
|
|
@@ -4180,7 +4526,6 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4180
4526
|
}
|
|
4181
4527
|
// `--with-github-action`: also drop the PR Visual Recap workflow into the
|
|
4182
4528
|
// repo so PRs get automatic recaps. Only meaningful for the plan family.
|
|
4183
|
-
const baseDir = options.baseDir ?? process.cwd();
|
|
4184
4529
|
let withGithubAction = Boolean(parsed.withGithubAction);
|
|
4185
4530
|
let githubActionPath;
|
|
4186
4531
|
let githubActionExisted;
|
|
@@ -4233,7 +4578,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4233
4578
|
instructionSource,
|
|
4234
4579
|
skillNames: installTarget.skillNames,
|
|
4235
4580
|
skillsAgents,
|
|
4236
|
-
mcpUrl:
|
|
4581
|
+
mcpUrl: localFilesModeSkipsMcp(modeAwareTargetId, planMode)
|
|
4237
4582
|
? ""
|
|
4238
4583
|
: installTarget.loaded.manifest.hosted.mcpUrl,
|
|
4239
4584
|
mcpClients: registeredMcpClients,
|
|
@@ -4243,6 +4588,7 @@ export async function addAgentNativeSkill(parsed, options = {}) {
|
|
|
4243
4588
|
connected,
|
|
4244
4589
|
connectCommand,
|
|
4245
4590
|
planMode,
|
|
4591
|
+
localManifestPath,
|
|
4246
4592
|
githubActionPath,
|
|
4247
4593
|
githubActionExisted,
|
|
4248
4594
|
githubActionSuggestedCommand,
|
|
@@ -4306,10 +4652,10 @@ function formatSkillState(state) {
|
|
|
4306
4652
|
}
|
|
4307
4653
|
function planModeSummary(mode) {
|
|
4308
4654
|
if (mode === "local-files")
|
|
4309
|
-
return "Local files -
|
|
4655
|
+
return "Local files - no hosted writes by default";
|
|
4310
4656
|
if (mode === "self-hosted")
|
|
4311
|
-
return "Self-hosted/custom
|
|
4312
|
-
return "Hosted
|
|
4657
|
+
return "Self-hosted/custom app";
|
|
4658
|
+
return "Hosted app";
|
|
4313
4659
|
}
|
|
4314
4660
|
function skillInstructionAgentLabel(agent) {
|
|
4315
4661
|
if (agent === "codex")
|
|
@@ -4326,8 +4672,8 @@ function targetInstallsMcp(target, parsed) {
|
|
|
4326
4672
|
if (publicSkillSelectionNames(target))
|
|
4327
4673
|
return false;
|
|
4328
4674
|
const knownTarget = normalizeKnownSkillTarget(target);
|
|
4329
|
-
if (knownTarget
|
|
4330
|
-
return
|
|
4675
|
+
if (localFilesModeSkipsMcp(knownTarget, parsed.planMode))
|
|
4676
|
+
return false;
|
|
4331
4677
|
if (knownTarget) {
|
|
4332
4678
|
return !isLocalOnlyBuiltInSkill(BUILT_IN_APP_SKILLS[knownTarget]);
|
|
4333
4679
|
}
|
|
@@ -4515,8 +4861,10 @@ export async function runSkills(argv, options = {}) {
|
|
|
4515
4861
|
});
|
|
4516
4862
|
const includesPlans = targetsIncludePlans(targets) ||
|
|
4517
4863
|
planSkillNamesSelected(parsed.plainSkillNames);
|
|
4518
|
-
|
|
4519
|
-
|
|
4864
|
+
const includesInstallModeSkills = targetsIncludeInstallModeSkills(targets) ||
|
|
4865
|
+
installModeSkillNamesSelected(parsed.plainSkillNames);
|
|
4866
|
+
if (parsed.planMode && !includesInstallModeSkills) {
|
|
4867
|
+
throw new Error("--mode only applies to visual-plan / visual-recap / content.");
|
|
4520
4868
|
}
|
|
4521
4869
|
if (includesPlans) {
|
|
4522
4870
|
if (!parsed.planMode && parsed.mcpUrl) {
|
|
@@ -4709,7 +5057,7 @@ export async function runSkills(argv, options = {}) {
|
|
|
4709
5057
|
: "MCP config not required",
|
|
4710
5058
|
mcpUrls.length ? `MCP URL ${mcpUrls.join(", ")}` : "",
|
|
4711
5059
|
planModes.length
|
|
4712
|
-
? `
|
|
5060
|
+
? `Install mode ${planModes.map(planModeSummary).join(", ")}`
|
|
4713
5061
|
: "",
|
|
4714
5062
|
authConnected
|
|
4715
5063
|
? "Authentication completed"
|