@agent-native/core 0.122.2 → 0.122.4
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/corpus/README.md +2 -2
- package/corpus/core/CHANGELOG.md +12 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/agent/run-loop-with-resume.ts +12 -0
- package/corpus/core/src/cli/index.ts +2 -1
- package/corpus/core/src/cli/mcp.ts +13 -3
- package/corpus/core/src/cli/skills-content/rewind-skill.ts +36 -4
- package/corpus/core/src/cli/skills.ts +250 -37
- package/corpus/core/src/cli/telemetry-routing.ts +57 -0
- package/corpus/core/src/cli/telemetry.ts +3 -3
- package/corpus/core/src/integrations/a2a-continuation-processor.ts +182 -0
- package/corpus/core/src/integrations/a2a-continuations-store.ts +122 -12
- package/corpus/core/src/integrations/integration-campaign-recovery.ts +127 -0
- package/corpus/core/src/integrations/integration-campaigns-store.ts +1039 -0
- package/corpus/core/src/integrations/integration-durable-dispatch.ts +28 -3
- package/corpus/core/src/integrations/pending-tasks-retry-job.ts +8 -0
- package/corpus/core/src/integrations/plugin.ts +453 -35
- package/corpus/core/src/integrations/webhook-handler.ts +469 -11
- package/corpus/core/src/mcp/screen-memory-stdio.ts +21 -2
- package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +7 -3
- package/corpus/templates/content/app/components/editor/body-hydration.ts +10 -0
- package/corpus/templates/content/app/components/editor/database/DatabaseView.tsx +1 -0
- package/corpus/templates/content/app/root.tsx +12 -1
- package/corpus/templates/content/changelog/2026-07-23-new-pages-open-immediately-while-slow-network-work-continues.md +6 -0
- package/corpus/templates/content/changelog/2026-07-25-database-preview-actions-open-reliably.md +6 -0
- package/corpus/templates/content/e2e/playwright.config.ts +1 -1
- package/dist/agent/run-loop-with-resume.d.ts +7 -1
- package/dist/agent/run-loop-with-resume.d.ts.map +1 -1
- package/dist/agent/run-loop-with-resume.js +7 -0
- package/dist/agent/run-loop-with-resume.js.map +1 -1
- package/dist/cli/index.js +3 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp.d.ts.map +1 -1
- package/dist/cli/mcp.js +12 -3
- package/dist/cli/mcp.js.map +1 -1
- package/dist/cli/skills-content/rewind-skill.d.ts +1 -1
- package/dist/cli/skills-content/rewind-skill.d.ts.map +1 -1
- package/dist/cli/skills-content/rewind-skill.js +36 -4
- package/dist/cli/skills-content/rewind-skill.js.map +1 -1
- package/dist/cli/skills.d.ts +2 -0
- package/dist/cli/skills.d.ts.map +1 -1
- package/dist/cli/skills.js +191 -40
- package/dist/cli/skills.js.map +1 -1
- package/dist/cli/telemetry-routing.d.ts +2 -0
- package/dist/cli/telemetry-routing.d.ts.map +1 -0
- package/dist/cli/telemetry-routing.js +54 -0
- package/dist/cli/telemetry-routing.js.map +1 -0
- package/dist/cli/telemetry.js +3 -3
- package/dist/cli/telemetry.js.map +1 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/awareness.d.ts.map +1 -1
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +3 -3
- package/dist/integrations/a2a-continuation-processor.d.ts +14 -0
- package/dist/integrations/a2a-continuation-processor.d.ts.map +1 -1
- package/dist/integrations/a2a-continuation-processor.js +134 -1
- package/dist/integrations/a2a-continuation-processor.js.map +1 -1
- package/dist/integrations/a2a-continuations-store.d.ts +23 -0
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +99 -13
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/integration-campaign-recovery.d.ts +16 -0
- package/dist/integrations/integration-campaign-recovery.d.ts.map +1 -0
- package/dist/integrations/integration-campaign-recovery.js +94 -0
- package/dist/integrations/integration-campaign-recovery.js.map +1 -0
- package/dist/integrations/integration-campaigns-store.d.ts +121 -0
- package/dist/integrations/integration-campaigns-store.d.ts.map +1 -0
- package/dist/integrations/integration-campaigns-store.js +784 -0
- package/dist/integrations/integration-campaigns-store.js.map +1 -0
- package/dist/integrations/integration-durable-dispatch.d.ts +3 -0
- package/dist/integrations/integration-durable-dispatch.d.ts.map +1 -1
- package/dist/integrations/integration-durable-dispatch.js +22 -3
- package/dist/integrations/integration-durable-dispatch.js.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-retry-job.js +6 -0
- package/dist/integrations/pending-tasks-retry-job.js.map +1 -1
- package/dist/integrations/plugin.d.ts.map +1 -1
- package/dist/integrations/plugin.js +325 -18
- package/dist/integrations/plugin.js.map +1 -1
- package/dist/integrations/webhook-handler.d.ts +16 -1
- package/dist/integrations/webhook-handler.d.ts.map +1 -1
- package/dist/integrations/webhook-handler.js +368 -13
- package/dist/integrations/webhook-handler.js.map +1 -1
- package/dist/mcp/screen-memory-stdio.d.ts +2 -0
- package/dist/mcp/screen-memory-stdio.d.ts.map +1 -1
- package/dist/mcp/screen-memory-stdio.js +12 -2
- package/dist/mcp/screen-memory-stdio.js.map +1 -1
- package/dist/notifications/routes.d.ts +3 -3
- package/dist/observability/routes.d.ts +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +14 -14
- package/dist/provider-api/actions/provider-api.d.ts +8 -8
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/package.json +1 -1
- package/src/agent/run-loop-with-resume.ts +12 -0
- package/src/cli/index.ts +2 -1
- package/src/cli/mcp.ts +13 -3
- package/src/cli/skills-content/rewind-skill.ts +36 -4
- package/src/cli/skills.ts +250 -37
- package/src/cli/telemetry-routing.ts +57 -0
- package/src/cli/telemetry.ts +3 -3
- package/src/integrations/a2a-continuation-processor.ts +182 -0
- package/src/integrations/a2a-continuations-store.ts +122 -12
- package/src/integrations/integration-campaign-recovery.ts +127 -0
- package/src/integrations/integration-campaigns-store.ts +1039 -0
- package/src/integrations/integration-durable-dispatch.ts +28 -3
- package/src/integrations/pending-tasks-retry-job.ts +8 -0
- package/src/integrations/plugin.ts +453 -35
- package/src/integrations/webhook-handler.ts +469 -11
- package/src/mcp/screen-memory-stdio.ts +21 -2
package/corpus/README.md
CHANGED
package/corpus/core/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @agent-native/core
|
|
2
2
|
|
|
3
|
+
## 0.122.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 648c2d7: Install Rewind through Agent Native's complete local Screen Memory setup instead of treating it as a plain public skill, route every supported Rewind name through the same fail-before-writes checks, reject missing or disconnected local stores, keep explicit-store retrieval bound to Clips' feature configuration, and guide first-time users through consent-gated Clips Desktop setup.
|
|
8
|
+
|
|
9
|
+
## 0.122.3
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 6dd7ee0: Recover long-running messaging integrations across hosted function boundaries while preserving one logical agent turn and one final platform reply.
|
|
14
|
+
|
|
3
15
|
## 0.122.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/corpus/core/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-native/core",
|
|
3
|
-
"version": "0.122.
|
|
3
|
+
"version": "0.122.4",
|
|
4
4
|
"description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
|
|
5
5
|
"homepage": "https://github.com/BuilderIO/agent-native#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -124,6 +124,18 @@ async function appendContinuationAndJournal(
|
|
|
124
124
|
appendToolCallJournalNote(messages, events);
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Rebuild the same safe continuation context for a logical turn that resumes
|
|
129
|
+
* in a fresh hosted invocation.
|
|
130
|
+
*/
|
|
131
|
+
export async function appendDurableContinuationContext(
|
|
132
|
+
messages: EngineMessage[],
|
|
133
|
+
reason: AgentLoopContinuationReason,
|
|
134
|
+
threadId: string,
|
|
135
|
+
): Promise<void> {
|
|
136
|
+
await appendContinuationAndJournal(messages, reason, threadId);
|
|
137
|
+
}
|
|
138
|
+
|
|
127
139
|
async function hasCompletedSideEffectToolCallInCurrentTurn(
|
|
128
140
|
threadId: string | undefined,
|
|
129
141
|
localEvents: readonly AgentChatEvent[] = [],
|
|
@@ -9,6 +9,7 @@ import { fileURLToPath } from "url";
|
|
|
9
9
|
import * as Sentry from "@sentry/node";
|
|
10
10
|
|
|
11
11
|
import { resolveDeployPostBuildInvocation } from "./deploy-build.js";
|
|
12
|
+
import { shouldTrackCliRun } from "./telemetry-routing.js";
|
|
12
13
|
import { createCliTelemetry } from "./telemetry.js";
|
|
13
14
|
|
|
14
15
|
// Resolve version once at module scope — used by both --version and --help
|
|
@@ -604,7 +605,7 @@ function runBuildStep(
|
|
|
604
605
|
});
|
|
605
606
|
}
|
|
606
607
|
|
|
607
|
-
trackCli("cli.run");
|
|
608
|
+
if (shouldTrackCliRun(command, args)) trackCli("cli.run");
|
|
608
609
|
|
|
609
610
|
switch (command) {
|
|
610
611
|
case "dev": {
|
|
@@ -92,6 +92,15 @@ export interface ScreenMemoryStoreResolutionOptions {
|
|
|
92
92
|
homeDir?: string;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
function existingScreenMemoryStore(candidate: string): string | undefined {
|
|
96
|
+
const resolved = path.resolve(candidate);
|
|
97
|
+
try {
|
|
98
|
+
return fs.statSync(resolved).isDirectory() ? resolved : undefined;
|
|
99
|
+
} catch {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
95
104
|
/**
|
|
96
105
|
* Resolve the active Clips store without asking people to find an app-data
|
|
97
106
|
* path. Environment overrides remain the unambiguous escape hatch; otherwise
|
|
@@ -100,11 +109,12 @@ export interface ScreenMemoryStoreResolutionOptions {
|
|
|
100
109
|
export function resolveScreenMemoryStoreDir(
|
|
101
110
|
options: ScreenMemoryStoreResolutionOptions = {},
|
|
102
111
|
): string | undefined {
|
|
103
|
-
if (options.explicitDir)
|
|
112
|
+
if (options.explicitDir)
|
|
113
|
+
return existingScreenMemoryStore(options.explicitDir);
|
|
104
114
|
const env = options.env ?? process.env;
|
|
105
115
|
const override =
|
|
106
116
|
env.CLIPS_SCREEN_MEMORY_DIR || env.AGENT_NATIVE_SCREEN_MEMORY_DIR;
|
|
107
|
-
if (override) return
|
|
117
|
+
if (override) return existingScreenMemoryStore(override);
|
|
108
118
|
|
|
109
119
|
const platform = options.platform ?? process.platform;
|
|
110
120
|
const home = options.homeDir ?? os.homedir();
|
|
@@ -116,7 +126,7 @@ export function resolveScreenMemoryStoreDir(
|
|
|
116
126
|
: env.XDG_DATA_HOME || path.join(home, ".local", "share");
|
|
117
127
|
return ["com.clips.tray", "com.clips.tray.alpha"]
|
|
118
128
|
.map((bundleId) => path.join(appDataRoot, bundleId, "screen-memory"))
|
|
119
|
-
.filter((candidate) =>
|
|
129
|
+
.filter((candidate) => existingScreenMemoryStore(candidate))
|
|
120
130
|
.map((candidate) => ({
|
|
121
131
|
candidate,
|
|
122
132
|
modifiedAt: Math.max(
|
|
@@ -13,6 +13,38 @@ metadata:
|
|
|
13
13
|
Use Clips Rewind as local screen memory. Start broad enough to find the right
|
|
14
14
|
moment, then read only the smallest relevant range.
|
|
15
15
|
|
|
16
|
+
## First-Run Setup
|
|
17
|
+
|
|
18
|
+
Call \`screen_memory_status\` before assuming Rewind is ready. If the tool is
|
|
19
|
+
unavailable, do not stop at a missing-tool error and do not silently install
|
|
20
|
+
anything:
|
|
21
|
+
|
|
22
|
+
1. Explain that Rewind requires the signed Clips Desktop app on macOS plus a
|
|
23
|
+
local agent connection.
|
|
24
|
+
2. Ask whether Clips is installed, or use a non-mutating native application
|
|
25
|
+
lookup when the host supports one. Do not inspect Clips' app-data folders.
|
|
26
|
+
If Clips is absent or its presence cannot be confirmed, ask permission
|
|
27
|
+
before opening or downloading anything: “Clips Desktop is required for
|
|
28
|
+
Rewind. Would you like me to open the official installer and guide you
|
|
29
|
+
through setup?”
|
|
30
|
+
3. Only after affirmative permission, open
|
|
31
|
+
\`https://clips.agent-native.com/download\` in the user's browser. Complete
|
|
32
|
+
native installation steps only when the current host can safely do so and
|
|
33
|
+
the user explicitly permitted them. Never bypass Gatekeeper, accept macOS
|
|
34
|
+
permission prompts, or enable screen/audio capture on the user's behalf.
|
|
35
|
+
4. If native UI control is unavailable, return the download link and wait for
|
|
36
|
+
the user to confirm that Clips is installed and running.
|
|
37
|
+
5. Ask the user to enable Rewind in the Clips tray and choose the intended
|
|
38
|
+
capture mode. Then configure the local connection with:
|
|
39
|
+
|
|
40
|
+
\`npx -y @agent-native/core@latest skills add rewind --client <client> --scope user --yes\`
|
|
41
|
+
|
|
42
|
+
Replace \`<client>\` with the current compatible host: \`codex\`,
|
|
43
|
+
\`claude-code\`, \`cursor\`, \`opencode\`, \`github-copilot\`, or \`cowork\`.
|
|
44
|
+
6. Restart the host only if it cannot reload MCP servers in place, then retry
|
|
45
|
+
\`screen_memory_status\`. Do not claim setup succeeded until it reports
|
|
46
|
+
Rewind enabled and unpaused.
|
|
47
|
+
|
|
16
48
|
## Retrieval Flow
|
|
17
49
|
|
|
18
50
|
1. Call \`screen_memory_status\` first. If the newest segment is still open,
|
|
@@ -41,12 +73,12 @@ moment, then read only the smallest relevant range.
|
|
|
41
73
|
bypass the Screen Memory MCP broker.
|
|
42
74
|
- Do not upload frames returned by local Screen Memory tools.
|
|
43
75
|
- Treat foreground apps and chapter labels as evidence, not proof of intent.
|
|
44
|
-
- If
|
|
45
|
-
|
|
76
|
+
- If Clips is installed and Rewind is enabled but the Screen Memory MCP is
|
|
77
|
+
missing, explain that only the agent connection needs repair with:
|
|
46
78
|
|
|
47
79
|
\`npx -y @agent-native/core@latest skills add rewind --client <client> --scope user --yes\`
|
|
48
80
|
|
|
49
|
-
Replace \`<client>\` with the current compatible host: \`codex\`,
|
|
50
|
-
\`claude-code\`, \`cursor\`, \`opencode\`, \`github-copilot\`, or \`cowork\`.
|
|
51
81
|
Ask the user to restart the host if it cannot reload MCP servers in place.
|
|
82
|
+
- Never conflate installing Clips Desktop with installing the skill/MCP
|
|
83
|
+
connection, and never claim either succeeded without direct evidence.
|
|
52
84
|
`;
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
CONTEXT_XRAY_SKILL_MD,
|
|
33
33
|
installLocalContextXray,
|
|
34
34
|
} from "./context-xray-local.js";
|
|
35
|
-
import { CLIENTS, type ClientId } from "./mcp-config-writers.js";
|
|
35
|
+
import { CLIENTS, configPathFor, type ClientId } from "./mcp-config-writers.js";
|
|
36
36
|
import {
|
|
37
37
|
installScreenMemoryForClient,
|
|
38
38
|
resolveScreenMemoryStoreDir,
|
|
@@ -800,6 +800,7 @@ export interface RunSkillsOptions {
|
|
|
800
800
|
* browser/device OAuth round-trip.
|
|
801
801
|
*/
|
|
802
802
|
runConnect?: (args: string[]) => Promise<void>;
|
|
803
|
+
installScreenMemory?: typeof installScreenMemoryForClient;
|
|
803
804
|
/**
|
|
804
805
|
* Best-effort install-funnel telemetry. Created once per `runSkills` run and
|
|
805
806
|
* threaded through resolution/install/connect so each `track` is fire-and-
|
|
@@ -850,6 +851,50 @@ function isKnownSkill(value: string | undefined): boolean {
|
|
|
850
851
|
return Boolean(normalizeKnownSkillTarget(value));
|
|
851
852
|
}
|
|
852
853
|
|
|
854
|
+
function explicitlyTargetsRewind(parsed: ParsedSkillsArgs): boolean {
|
|
855
|
+
return (
|
|
856
|
+
normalizeKnownSkillTarget(parsed.target ?? "assets") === "rewind" ||
|
|
857
|
+
Boolean(
|
|
858
|
+
parsed.plainSkillNames?.some(
|
|
859
|
+
(skillName) => normalizeKnownSkillTarget(skillName) === "rewind",
|
|
860
|
+
),
|
|
861
|
+
)
|
|
862
|
+
);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
const REWIND_MISSING_STORE_ERROR =
|
|
866
|
+
"No local Clips Screen Memory store was found. Clips Desktop is required for Rewind. Download and launch the signed app from https://clips.agent-native.com/download, turn Rewind on, then run the setup again. Clips Desktop was not installed or enabled automatically.";
|
|
867
|
+
|
|
868
|
+
function preflightRewindStore(parsed: ParsedSkillsArgs): string | undefined {
|
|
869
|
+
if (parsed.command !== "add" || !explicitlyTargetsRewind(parsed))
|
|
870
|
+
return undefined;
|
|
871
|
+
if (!parsed.mcp) {
|
|
872
|
+
throw new Error(
|
|
873
|
+
"Rewind requires the local Clips Screen Memory MCP and cannot be installed with --no-mcp.",
|
|
874
|
+
);
|
|
875
|
+
}
|
|
876
|
+
if (parsed.mcpUrl) {
|
|
877
|
+
throw new Error(
|
|
878
|
+
"Rewind uses the local Clips Screen Memory MCP and does not accept --mcp-url.",
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
if (parsed.dryRun) return undefined;
|
|
882
|
+
const screenMemoryDir = resolveScreenMemoryStoreDir();
|
|
883
|
+
if (!screenMemoryDir) throw new Error(REWIND_MISSING_STORE_ERROR);
|
|
884
|
+
return screenMemoryDir;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
function preflightResolvedRewindTargets(
|
|
888
|
+
parsed: ParsedSkillsArgs,
|
|
889
|
+
targets: string[],
|
|
890
|
+
): void {
|
|
891
|
+
preflightRewindStore({
|
|
892
|
+
...parsed,
|
|
893
|
+
target: undefined,
|
|
894
|
+
plainSkillNames: [...(parsed.plainSkillNames ?? []), ...targets],
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
|
|
853
898
|
function isLocalOnlyBuiltInSkill(
|
|
854
899
|
entry: (typeof BUILT_IN_APP_SKILLS)[BuiltInAppSkillId] | null | undefined,
|
|
855
900
|
): boolean {
|
|
@@ -1382,7 +1427,7 @@ $ARGUMENTS
|
|
|
1382
1427
|
* there is no need to shell out to the separate @agent-native/skills installer
|
|
1383
1428
|
* (which would have to be published to npm first). Returns the written folders.
|
|
1384
1429
|
*/
|
|
1385
|
-
|
|
1430
|
+
type BuiltInInstructionInstallInput = {
|
|
1386
1431
|
appSkillId: BuiltInAppSkillId;
|
|
1387
1432
|
onlySkillNames?: string[];
|
|
1388
1433
|
skillsAgents: string[];
|
|
@@ -1391,7 +1436,11 @@ function installBuiltInInstructions(input: {
|
|
|
1391
1436
|
dryRun?: boolean;
|
|
1392
1437
|
planMode?: PlanInstallMode;
|
|
1393
1438
|
mcpUrl?: string;
|
|
1394
|
-
}
|
|
1439
|
+
};
|
|
1440
|
+
|
|
1441
|
+
function builtInInstructionPaths(
|
|
1442
|
+
input: BuiltInInstructionInstallInput,
|
|
1443
|
+
): string[] {
|
|
1395
1444
|
const bundles = Object.values(
|
|
1396
1445
|
skillFilesForBuiltIn(input.appSkillId, {
|
|
1397
1446
|
planMode: input.planMode,
|
|
@@ -1411,15 +1460,10 @@ function installBuiltInInstructions(input: {
|
|
|
1411
1460
|
);
|
|
1412
1461
|
for (const bundle of bundles) {
|
|
1413
1462
|
const dir = path.join(root, bundle.skillName);
|
|
1414
|
-
if (!input.dryRun) writeSkillFolder(dir, bundle);
|
|
1415
1463
|
written.push(dir);
|
|
1416
1464
|
const command = slashCommandForBuiltInSkill(bundle.skillName);
|
|
1417
1465
|
if (command) {
|
|
1418
1466
|
const commandPath = path.join(commandsRoot, `${bundle.skillName}.md`);
|
|
1419
|
-
if (!input.dryRun) {
|
|
1420
|
-
fs.mkdirSync(path.dirname(commandPath), { recursive: true });
|
|
1421
|
-
fs.writeFileSync(commandPath, command, "utf-8");
|
|
1422
|
-
}
|
|
1423
1467
|
written.push(commandPath);
|
|
1424
1468
|
}
|
|
1425
1469
|
}
|
|
@@ -1427,6 +1471,87 @@ function installBuiltInInstructions(input: {
|
|
|
1427
1471
|
return written;
|
|
1428
1472
|
}
|
|
1429
1473
|
|
|
1474
|
+
function installBuiltInInstructions(
|
|
1475
|
+
input: BuiltInInstructionInstallInput,
|
|
1476
|
+
): string[] {
|
|
1477
|
+
const bundles = Object.values(
|
|
1478
|
+
skillFilesForBuiltIn(input.appSkillId, {
|
|
1479
|
+
planMode: input.planMode,
|
|
1480
|
+
mcpUrl: input.mcpUrl,
|
|
1481
|
+
}),
|
|
1482
|
+
).filter(
|
|
1483
|
+
(bundle) =>
|
|
1484
|
+
!input.onlySkillNames || input.onlySkillNames.includes(bundle.skillName),
|
|
1485
|
+
);
|
|
1486
|
+
const written = builtInInstructionPaths(input);
|
|
1487
|
+
if (input.dryRun) return written;
|
|
1488
|
+
|
|
1489
|
+
for (const agent of input.skillsAgents) {
|
|
1490
|
+
const root = builtInSkillsRootForAgent(agent, input.scope, input.baseDir);
|
|
1491
|
+
const commandsRoot = builtInCommandsRootForAgent(
|
|
1492
|
+
agent,
|
|
1493
|
+
input.scope,
|
|
1494
|
+
input.baseDir,
|
|
1495
|
+
);
|
|
1496
|
+
for (const bundle of bundles) {
|
|
1497
|
+
writeSkillFolder(path.join(root, bundle.skillName), bundle);
|
|
1498
|
+
const command = slashCommandForBuiltInSkill(bundle.skillName);
|
|
1499
|
+
if (command) {
|
|
1500
|
+
const commandPath = path.join(commandsRoot, `${bundle.skillName}.md`);
|
|
1501
|
+
fs.mkdirSync(path.dirname(commandPath), { recursive: true });
|
|
1502
|
+
fs.writeFileSync(commandPath, command, "utf-8");
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
return written;
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
interface InstallPathSnapshot {
|
|
1510
|
+
target: string;
|
|
1511
|
+
backup: string;
|
|
1512
|
+
existed: boolean;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
function snapshotInstallPaths(
|
|
1516
|
+
targets: string[],
|
|
1517
|
+
backupRoot: string,
|
|
1518
|
+
): InstallPathSnapshot[] {
|
|
1519
|
+
return [...new Set(targets)].map((target, index) => {
|
|
1520
|
+
const backup = path.join(backupRoot, `snapshot-${index}`);
|
|
1521
|
+
const existed = fs.existsSync(target);
|
|
1522
|
+
if (existed) fs.cpSync(target, backup, { recursive: true });
|
|
1523
|
+
return { target, backup, existed };
|
|
1524
|
+
});
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1527
|
+
function removeEmptyParents(start: string, boundary: string): void {
|
|
1528
|
+
let current = path.resolve(start);
|
|
1529
|
+
const stop = path.resolve(boundary);
|
|
1530
|
+
while (current !== stop && current.startsWith(`${stop}${path.sep}`)) {
|
|
1531
|
+
if (!fs.existsSync(current) || fs.readdirSync(current).length > 0) return;
|
|
1532
|
+
fs.rmdirSync(current);
|
|
1533
|
+
current = path.dirname(current);
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
|
|
1537
|
+
function restoreInstallPaths(
|
|
1538
|
+
snapshots: InstallPathSnapshot[],
|
|
1539
|
+
boundary: string,
|
|
1540
|
+
): void {
|
|
1541
|
+
for (const snapshot of snapshots.toReversed()) {
|
|
1542
|
+
fs.rmSync(snapshot.target, { recursive: true, force: true });
|
|
1543
|
+
if (snapshot.existed) {
|
|
1544
|
+
fs.mkdirSync(path.dirname(snapshot.target), { recursive: true });
|
|
1545
|
+
fs.cpSync(snapshot.backup, snapshot.target, { recursive: true });
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
for (const snapshot of snapshots) {
|
|
1549
|
+
if (!snapshot.existed) {
|
|
1550
|
+
removeEmptyParents(path.dirname(snapshot.target), boundary);
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1430
1555
|
function listSkillFolderFiles(dir: string): Record<string, string> {
|
|
1431
1556
|
const out: Record<string, string> = {};
|
|
1432
1557
|
const walk = (current: string, prefix = "") => {
|
|
@@ -3376,6 +3501,11 @@ export async function addAgentNativeSkill(
|
|
|
3376
3501
|
const knownBuiltIn = knownTarget ? BUILT_IN_APP_SKILLS[knownTarget] : null;
|
|
3377
3502
|
const installsScreenMemoryMcp = isScreenMemoryMcpBuiltInSkill(knownBuiltIn);
|
|
3378
3503
|
const baseDir = options.baseDir ?? process.cwd();
|
|
3504
|
+
if (installsScreenMemoryMcp && !parsed.mcp) {
|
|
3505
|
+
throw new Error(
|
|
3506
|
+
"Rewind requires the local Clips Screen Memory MCP and cannot be installed with --no-mcp.",
|
|
3507
|
+
);
|
|
3508
|
+
}
|
|
3379
3509
|
if (installsScreenMemoryMcp && parsed.mcpUrl) {
|
|
3380
3510
|
throw new Error(
|
|
3381
3511
|
"Rewind uses the local Clips Screen Memory MCP and does not accept --mcp-url.",
|
|
@@ -3487,7 +3617,7 @@ export async function addAgentNativeSkill(
|
|
|
3487
3617
|
}
|
|
3488
3618
|
installTarget = preserveMcpUrlAppPathOverride(installTarget, parsed.mcpUrl);
|
|
3489
3619
|
const skillsAgents = installsScreenMemoryMcp
|
|
3490
|
-
? clients
|
|
3620
|
+
? clients.filter((client) => client !== "cowork")
|
|
3491
3621
|
: skillsAgentsForClients(clients);
|
|
3492
3622
|
if (parsed.dryRun) {
|
|
3493
3623
|
try {
|
|
@@ -3537,6 +3667,7 @@ export async function addAgentNativeSkill(
|
|
|
3537
3667
|
}
|
|
3538
3668
|
}
|
|
3539
3669
|
const commands: string[] = [];
|
|
3670
|
+
const screenMemoryDir = preflightRewindStore(parsed);
|
|
3540
3671
|
const tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), "an-skills-add-"));
|
|
3541
3672
|
let instructionSource: string | undefined;
|
|
3542
3673
|
let instructionsWritten: string[] | undefined;
|
|
@@ -3544,6 +3675,36 @@ export async function addAgentNativeSkill(
|
|
|
3544
3675
|
let connectCommand: string | undefined;
|
|
3545
3676
|
let registeredMcpClients: ClientId[] = shouldRegisterMcp ? mcpClients : [];
|
|
3546
3677
|
let localManifestPath: string | undefined;
|
|
3678
|
+
const builtInInstructionInput: BuiltInInstructionInstallInput | undefined =
|
|
3679
|
+
knownTarget
|
|
3680
|
+
? {
|
|
3681
|
+
appSkillId: knownTarget,
|
|
3682
|
+
onlySkillNames,
|
|
3683
|
+
skillsAgents,
|
|
3684
|
+
scope: parsed.scope as "project" | "user",
|
|
3685
|
+
baseDir,
|
|
3686
|
+
dryRun: parsed.dryRun,
|
|
3687
|
+
planMode,
|
|
3688
|
+
mcpUrl: installTarget.loaded.manifest.hosted.mcpUrl,
|
|
3689
|
+
}
|
|
3690
|
+
: undefined;
|
|
3691
|
+
const rewindSnapshots = installsScreenMemoryMcp
|
|
3692
|
+
? snapshotInstallPaths(
|
|
3693
|
+
[
|
|
3694
|
+
...(parsed.instructions && builtInInstructionInput
|
|
3695
|
+
? builtInInstructionPaths(builtInInstructionInput)
|
|
3696
|
+
: []),
|
|
3697
|
+
...(shouldRegisterMcp
|
|
3698
|
+
? mcpClients.map((client) =>
|
|
3699
|
+
configPathFor(client, baseDir, parsed.scope),
|
|
3700
|
+
)
|
|
3701
|
+
: []),
|
|
3702
|
+
],
|
|
3703
|
+
tmpRoot,
|
|
3704
|
+
)
|
|
3705
|
+
: undefined;
|
|
3706
|
+
const rollbackBoundary =
|
|
3707
|
+
parsed.scope === "user" ? os.homedir() : path.resolve(baseDir);
|
|
3547
3708
|
|
|
3548
3709
|
try {
|
|
3549
3710
|
if (parsed.instructions) {
|
|
@@ -3553,21 +3714,14 @@ export async function addAgentNativeSkill(
|
|
|
3553
3714
|
"Skill instructions use shared .agents for Codex, Pi, Cursor, OpenCode, Copilot, and similar agents, or Claude Code's native files. Use an MCP-capable client or omit --instructions-only.",
|
|
3554
3715
|
);
|
|
3555
3716
|
}
|
|
3556
|
-
} else if (knownTarget) {
|
|
3717
|
+
} else if (knownTarget && builtInInstructionInput) {
|
|
3557
3718
|
// Built-in skills ship their instructions inside this package, so copy
|
|
3558
3719
|
// the skill folders straight into each client's skills directory. This
|
|
3559
3720
|
// avoids shelling out to the separate @agent-native/skills installer
|
|
3560
3721
|
// (which would need to be published to npm to run via npx).
|
|
3561
|
-
instructionsWritten = installBuiltInInstructions(
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
skillsAgents,
|
|
3565
|
-
scope: parsed.scope as "project" | "user",
|
|
3566
|
-
baseDir,
|
|
3567
|
-
dryRun: parsed.dryRun,
|
|
3568
|
-
planMode,
|
|
3569
|
-
mcpUrl: installTarget.loaded.manifest.hosted.mcpUrl,
|
|
3570
|
-
});
|
|
3722
|
+
instructionsWritten = installBuiltInInstructions(
|
|
3723
|
+
builtInInstructionInput,
|
|
3724
|
+
);
|
|
3571
3725
|
instructionSource = instructionsWritten[0];
|
|
3572
3726
|
commands.push(...instructionsWritten.map((dir) => `write ${dir}`));
|
|
3573
3727
|
} else {
|
|
@@ -3611,29 +3765,24 @@ export async function addAgentNativeSkill(
|
|
|
3611
3765
|
commands.push(`write ${localManifestPath}`);
|
|
3612
3766
|
}
|
|
3613
3767
|
|
|
3614
|
-
//
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3768
|
+
// Rewind reports completion only after both local writes succeed.
|
|
3769
|
+
if (!installsScreenMemoryMcp) {
|
|
3770
|
+
options.telemetry?.track("skills_cli install completed", {
|
|
3771
|
+
skills: installTarget.skillNames.join(","),
|
|
3772
|
+
clients: clients.join(","),
|
|
3773
|
+
scope: parsed.scope,
|
|
3774
|
+
dryRun: Boolean(parsed.dryRun),
|
|
3775
|
+
});
|
|
3776
|
+
}
|
|
3622
3777
|
|
|
3623
3778
|
if (shouldRegisterMcp && installsScreenMemoryMcp) {
|
|
3624
|
-
const screenMemoryDir = resolveScreenMemoryStoreDir();
|
|
3625
|
-
if (!screenMemoryDir) {
|
|
3626
|
-
throw new Error(
|
|
3627
|
-
"No local Clips Screen Memory store was found. Turn Rewind on in Clips, then run the setup again.",
|
|
3628
|
-
);
|
|
3629
|
-
}
|
|
3630
3779
|
registeredMcpClients = mcpClients.map((client) => {
|
|
3631
3780
|
commands.push(
|
|
3632
3781
|
`npx @agent-native/core@latest mcp install-screen-memory --client ${client} --scope ${parsed.scope}`,
|
|
3633
3782
|
);
|
|
3634
|
-
installScreenMemoryForClient(
|
|
3783
|
+
(options.installScreenMemory ?? installScreenMemoryForClient)(
|
|
3635
3784
|
client,
|
|
3636
|
-
screenMemoryDir
|
|
3785
|
+
screenMemoryDir!,
|
|
3637
3786
|
baseDir,
|
|
3638
3787
|
parsed.scope,
|
|
3639
3788
|
);
|
|
@@ -3642,6 +3791,12 @@ export async function addAgentNativeSkill(
|
|
|
3642
3791
|
options.telemetry?.track("skills_cli mcp registered", {
|
|
3643
3792
|
skills: installTarget.skillNames.join(","),
|
|
3644
3793
|
});
|
|
3794
|
+
options.telemetry?.track("skills_cli install completed", {
|
|
3795
|
+
skills: installTarget.skillNames.join(","),
|
|
3796
|
+
clients: clients.join(","),
|
|
3797
|
+
scope: parsed.scope,
|
|
3798
|
+
dryRun: false,
|
|
3799
|
+
});
|
|
3645
3800
|
} else if (shouldRegisterMcp) {
|
|
3646
3801
|
commands.push(
|
|
3647
3802
|
`npx @agent-native/core@latest app-skill ensure --manifest ${installTarget.loaded.file} --client ${parsed.client} --scope ${parsed.scope} --yes`,
|
|
@@ -3769,6 +3924,18 @@ export async function addAgentNativeSkill(
|
|
|
3769
3924
|
githubActionExisted,
|
|
3770
3925
|
githubActionSuggestedCommand,
|
|
3771
3926
|
};
|
|
3927
|
+
} catch (error) {
|
|
3928
|
+
if (rewindSnapshots) {
|
|
3929
|
+
try {
|
|
3930
|
+
restoreInstallPaths(rewindSnapshots, rollbackBoundary);
|
|
3931
|
+
} catch (rollbackError) {
|
|
3932
|
+
throw new AggregateError(
|
|
3933
|
+
[error, rollbackError],
|
|
3934
|
+
"Rewind setup failed and its partial installation could not be fully rolled back.",
|
|
3935
|
+
);
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
throw error;
|
|
3772
3939
|
} finally {
|
|
3773
3940
|
fs.rmSync(tmpRoot, { recursive: true, force: true });
|
|
3774
3941
|
installTarget.cleanup?.();
|
|
@@ -4046,6 +4213,41 @@ function readCliVersion(): string {
|
|
|
4046
4213
|
}
|
|
4047
4214
|
}
|
|
4048
4215
|
|
|
4216
|
+
function deferCliTelemetry(target: CliTelemetry): {
|
|
4217
|
+
telemetry: CliTelemetry;
|
|
4218
|
+
commit: () => void;
|
|
4219
|
+
} {
|
|
4220
|
+
type TrackCall = Parameters<CliTelemetry["track"]>;
|
|
4221
|
+
type ExceptionCall = Parameters<CliTelemetry["captureException"]>;
|
|
4222
|
+
const trackCalls: TrackCall[] = [];
|
|
4223
|
+
const exceptionCalls: ExceptionCall[] = [];
|
|
4224
|
+
let committed = false;
|
|
4225
|
+
|
|
4226
|
+
return {
|
|
4227
|
+
telemetry: {
|
|
4228
|
+
track(...args) {
|
|
4229
|
+
if (committed) target.track(...args);
|
|
4230
|
+
else trackCalls.push(args);
|
|
4231
|
+
},
|
|
4232
|
+
captureException(...args) {
|
|
4233
|
+
if (committed) target.captureException(...args);
|
|
4234
|
+
else exceptionCalls.push(args);
|
|
4235
|
+
},
|
|
4236
|
+
async flush() {
|
|
4237
|
+
if (committed) await target.flush();
|
|
4238
|
+
},
|
|
4239
|
+
},
|
|
4240
|
+
commit() {
|
|
4241
|
+
if (committed) return;
|
|
4242
|
+
committed = true;
|
|
4243
|
+
for (const args of trackCalls) target.track(...args);
|
|
4244
|
+
for (const args of exceptionCalls) target.captureException(...args);
|
|
4245
|
+
trackCalls.length = 0;
|
|
4246
|
+
exceptionCalls.length = 0;
|
|
4247
|
+
},
|
|
4248
|
+
};
|
|
4249
|
+
}
|
|
4250
|
+
|
|
4049
4251
|
export async function runSkills(
|
|
4050
4252
|
argv: string[],
|
|
4051
4253
|
options: RunSkillsOptions = {},
|
|
@@ -4054,6 +4256,7 @@ export async function runSkills(
|
|
|
4054
4256
|
if (parsed.baseDir) {
|
|
4055
4257
|
options = { ...options, baseDir: path.resolve(parsed.baseDir) };
|
|
4056
4258
|
}
|
|
4259
|
+
preflightRewindStore(parsed);
|
|
4057
4260
|
const clackForLog = parsed.printJson
|
|
4058
4261
|
? undefined
|
|
4059
4262
|
: await import("@clack/prompts");
|
|
@@ -4089,7 +4292,7 @@ export async function runSkills(
|
|
|
4089
4292
|
// finally so events send on success, error, and cancellation — the CLI is
|
|
4090
4293
|
// short-lived, so flushing before exit is essential or the events never send.
|
|
4091
4294
|
const startedAt = Date.now();
|
|
4092
|
-
const
|
|
4295
|
+
const telemetryTarget =
|
|
4093
4296
|
options.telemetry ??
|
|
4094
4297
|
createCliTelemetry({
|
|
4095
4298
|
cli: "core",
|
|
@@ -4097,6 +4300,13 @@ export async function runSkills(
|
|
|
4097
4300
|
command: parsed.command,
|
|
4098
4301
|
interactive: shouldPrompt(parsed, options),
|
|
4099
4302
|
});
|
|
4303
|
+
const deferredTelemetry = deferCliTelemetry(telemetryTarget);
|
|
4304
|
+
const telemetry = deferredTelemetry.telemetry;
|
|
4305
|
+
const deferUntilSkillSelection =
|
|
4306
|
+
parsed.command === "add" &&
|
|
4307
|
+
!parsed.target &&
|
|
4308
|
+
!(parsed.plainSkillNames?.length ?? 0);
|
|
4309
|
+
if (!deferUntilSkillSelection) deferredTelemetry.commit();
|
|
4100
4310
|
const optionsWithTelemetry: RunSkillsOptions = {
|
|
4101
4311
|
...options,
|
|
4102
4312
|
telemetry,
|
|
@@ -4137,9 +4347,12 @@ export async function runSkills(
|
|
|
4137
4347
|
|
|
4138
4348
|
const targets = await resolveSkillTargets(parsed, optionsWithTelemetry);
|
|
4139
4349
|
if (!targets) {
|
|
4350
|
+
deferredTelemetry.commit();
|
|
4140
4351
|
telemetry.track("skills_cli cancelled", { step: "skills" });
|
|
4141
4352
|
return;
|
|
4142
4353
|
}
|
|
4354
|
+
preflightResolvedRewindTargets(parsed, targets);
|
|
4355
|
+
deferredTelemetry.commit();
|
|
4143
4356
|
const preselected = Boolean(parsed.target);
|
|
4144
4357
|
telemetry.track("skills_cli skills selected", {
|
|
4145
4358
|
selected: targets.join(","),
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
const REWIND_SKILL_TARGETS = new Set([
|
|
2
|
+
"rewind",
|
|
3
|
+
"screen-memory",
|
|
4
|
+
"clips-rewind",
|
|
5
|
+
"agent-native-rewind",
|
|
6
|
+
]);
|
|
7
|
+
|
|
8
|
+
function isRewindSkillTarget(value: string | undefined): boolean {
|
|
9
|
+
return REWIND_SKILL_TARGETS.has(value?.trim().toLowerCase() ?? "");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const SKILLS_VALUE_FLAGS = new Set([
|
|
13
|
+
"--client",
|
|
14
|
+
"--agent",
|
|
15
|
+
"-a",
|
|
16
|
+
"--scope",
|
|
17
|
+
"--cwd",
|
|
18
|
+
"--mcp-url",
|
|
19
|
+
"--mode",
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
function explicitSkillTargets(args: string[]): string[] {
|
|
23
|
+
const targets: string[] = [];
|
|
24
|
+
const start = args[0] === "add" ? 1 : 0;
|
|
25
|
+
for (let index = start; index < args.length; index++) {
|
|
26
|
+
const arg = args[index];
|
|
27
|
+
if (arg === "--skill" || arg === "-s") {
|
|
28
|
+
if (args[index + 1]) targets.push(args[++index]);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (arg.startsWith("--skill=")) {
|
|
32
|
+
targets.push(arg.slice("--skill=".length));
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (SKILLS_VALUE_FLAGS.has(arg)) {
|
|
36
|
+
index++;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (arg.startsWith("-")) continue;
|
|
40
|
+
targets.push(arg);
|
|
41
|
+
}
|
|
42
|
+
return targets;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function shouldTrackCliRun(command: string | undefined, args: string[]) {
|
|
46
|
+
if (command !== "skills") return true;
|
|
47
|
+
if (
|
|
48
|
+
["list", "status", "update", "help", "--help", "-h"].includes(args[0] ?? "")
|
|
49
|
+
)
|
|
50
|
+
return true;
|
|
51
|
+
|
|
52
|
+
const targets = explicitSkillTargets(args);
|
|
53
|
+
if (targets.length === 0) return false;
|
|
54
|
+
|
|
55
|
+
const explicitlyTargetsRewind = targets.some(isRewindSkillTarget);
|
|
56
|
+
return !explicitlyTargetsRewind;
|
|
57
|
+
}
|