@myagentroam/node 0.9.9 → 0.9.10
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/capabilities.js +2 -92
- package/dist/claude-agent-sdk.js +2 -330
- package/dist/claude-channel.js +2 -44
- package/dist/codex-app-server.js +2 -503
- package/dist/config.js +2 -56
- package/dist/connector/node-connector-options.js +2 -1
- package/dist/connector/node-operation-router.js +2 -22
- package/dist/connector.js +2 -845
- package/dist/control-outbound-scheduler.js +2 -154
- package/dist/database.js +2 -1418
- package/dist/event-buffer.js +2 -19
- package/dist/fake-runner.js +2 -129
- package/dist/health.js +2 -3
- package/dist/main.js +2 -54
- package/dist/migrations/v001.js +3 -144
- package/dist/migrations/v002.js +2 -143
- package/dist/migrations/v003.js +2 -44
- package/dist/migrations/v004.js +34 -30
- package/dist/native-jsonl-reader.js +2 -186
- package/dist/native-session-history.js +2 -1119
- package/dist/opencode-runtime.js +2 -80
- package/dist/opencode-server.js +2 -263
- package/dist/operational.js +2 -122
- package/dist/process-tree.js +2 -18
- package/dist/rotating-log.js +2 -67
- package/dist/runner/abstract-runner.js +2 -232
- package/dist/runner/claude/managed-run-controller.js +2 -345
- package/dist/runner/claude-code-runner.js +2 -303
- package/dist/runner/codex/composer-image-markers.js +2 -0
- package/dist/runner/codex/conversation-parser.js +2 -861
- package/dist/runner/codex/managed-run-controller.js +2 -460
- package/dist/runner/codex-runner.js +2 -628
- package/dist/runner/fake-test-runner.js +2 -47
- package/dist/runner/opencode/conversation-parser.js +2 -221
- package/dist/runner/opencode/managed-run-controller.js +2 -537
- package/dist/runner/opencode-runner.js +2 -448
- package/dist/runner/runner-registry.js +2 -90
- package/dist/runner-command-engine.js +2 -70
- package/dist/runner-profiles.js +2 -215
- package/dist/runner-usage.js +2 -190
- package/dist/runtime-command-detector.js +2 -73
- package/dist/runtime-state.js +2 -982
- package/dist/service/attachment-domain-state.js +2 -7
- package/dist/service/conversation-history-service.js +2 -457
- package/dist/service/conversation-segment-service.js +2 -162
- package/dist/service/external-session-resume-service.js +2 -118
- package/dist/service/fake-managed-run-service.js +2 -60
- package/dist/service/managed-runner-session-service.js +2 -35
- package/dist/service/mcp-installation-verifier.js +2 -87
- package/dist/service/mcp-node-operation-service.js +2 -90
- package/dist/service/mcp-package-installer.js +2 -136
- package/dist/service/native-session-projection-service.js +2 -280
- package/dist/service/native-session-watch-service.js +2 -383
- package/dist/service/node-connection-lifecycle-service.js +2 -84
- package/dist/service/node-control-channel.js +2 -85
- package/dist/service/node-control-message-service.js +2 -107
- package/dist/service/node-request-service.js +2 -52
- package/dist/service/node-run-event-bridge.js +2 -83
- package/dist/service/node-terminal-channel.js +2 -182
- package/dist/service/node-upgrade-coordinator.js +2 -137
- package/dist/service/node-workspace-coordinator.js +2 -70
- package/dist/service/recent-run-projection-service.js +2 -78
- package/dist/service/run-attachment-service.js +2 -194
- package/dist/service/run-domain-state.js +2 -4
- package/dist/service/run-event-service.js +2 -193
- package/dist/service/run-workbench-service.js +2 -104
- package/dist/service/runner-channel-message-service.js +2 -20
- package/dist/service/runner-interaction-service.js +2 -243
- package/dist/service/runner-service.js +2 -71
- package/dist/service/session-catalog-service.js +2 -224
- package/dist/service/session-command-service.js +2 -76
- package/dist/service/session-context-service.js +2 -101
- package/dist/service/session-domain-state.js +2 -9
- package/dist/service/session-identity-service.js +2 -86
- package/dist/service/session-lifecycle-service.js +2 -240
- package/dist/service/session-message-service.js +2 -173
- package/dist/service/session-presentation-service.js +2 -43
- package/dist/service/session-query-service.js +2 -82
- package/dist/service/skill-directory-service.js +2 -238
- package/dist/service/skill-install-service.js +2 -434
- package/dist/service/skill-node-operation-service.js +2 -206
- package/dist/service/terminal-relay-state.js +2 -3
- package/dist/service/terminal-service.js +2 -52
- package/dist/service/workbench-event-service.js +2 -19
- package/dist/service/workbench-manifest-service.js +2 -69
- package/dist/service/workspace-change-service.js +2 -86
- package/dist/service/workspace-content-search-service.js +2 -477
- package/dist/service/workspace-domain-state.js +2 -41
- package/dist/service/workspace-file-service.js +2 -122
- package/dist/service/workspace-git-exclude-service.js +2 -119
- package/dist/service/workspace-queue-workbench-service.js +2 -304
- package/dist/service/workspace-service.js +2 -69
- package/dist/service/workspace-session-service.js +2 -139
- package/dist/service/workspace-upload-service.js +2 -262
- package/dist/service/workspace-watch-service.js +2 -146
- package/dist/service/workspace-workbench-service.js +2 -405
- package/dist/service.js +2 -38
- package/dist/storage.js +2 -32
- package/dist/supervisor.js +2 -136
- package/dist/terminal.js +2 -416
- package/dist/util/node-operation-parsers.js +2 -382
- package/dist/util/personal-instructions.js +2 -31
- package/dist/util/runner-error.js +2 -52
- package/dist/util/runner-native-session-parsers.js +2 -490
- package/dist/util/safe-error.js +2 -5
- package/dist/util/secret-environment.js +2 -25
- package/dist/workspace.js +2 -1519
- package/package.json +3 -3
- package/dist/capabilities.d.ts +0 -12
- package/dist/claude-agent-sdk.d.ts +0 -92
- package/dist/claude-channel.d.ts +0 -28
- package/dist/codex-app-server.d.ts +0 -133
- package/dist/config.d.ts +0 -18
- package/dist/connector/node-connector-options.d.ts +0 -27
- package/dist/connector/node-operation-router.d.ts +0 -9
- package/dist/connector.d.ts +0 -94
- package/dist/control-outbound-scheduler.d.ts +0 -29
- package/dist/database.d.ts +0 -305
- package/dist/event-buffer.d.ts +0 -9
- package/dist/fake-runner.d.ts +0 -42
- package/dist/health.d.ts +0 -4
- package/dist/main.d.ts +0 -2
- package/dist/migrations/v001.d.ts +0 -3
- package/dist/migrations/v002.d.ts +0 -4
- package/dist/migrations/v003.d.ts +0 -4
- package/dist/migrations/v004.d.ts +0 -4
- package/dist/native-jsonl-reader.d.ts +0 -35
- package/dist/native-session-history.d.ts +0 -126
- package/dist/opencode-runtime.d.ts +0 -33
- package/dist/opencode-server.d.ts +0 -49
- package/dist/operational.d.ts +0 -39
- package/dist/process-tree.d.ts +0 -9
- package/dist/rotating-log.d.ts +0 -17
- package/dist/runner/abstract-runner.d.ts +0 -172
- package/dist/runner/claude/managed-run-controller.d.ts +0 -51
- package/dist/runner/claude-code-runner.d.ts +0 -72
- package/dist/runner/codex/conversation-parser.d.ts +0 -59
- package/dist/runner/codex/managed-run-controller.d.ts +0 -90
- package/dist/runner/codex-runner.d.ts +0 -103
- package/dist/runner/fake-test-runner.d.ts +0 -26
- package/dist/runner/opencode/conversation-parser.d.ts +0 -31
- package/dist/runner/opencode/managed-run-controller.d.ts +0 -82
- package/dist/runner/opencode-runner.d.ts +0 -71
- package/dist/runner/runner-registry.d.ts +0 -19
- package/dist/runner-command-engine.d.ts +0 -28
- package/dist/runner-profiles.d.ts +0 -15
- package/dist/runner-usage.d.ts +0 -33
- package/dist/runtime-command-detector.d.ts +0 -3
- package/dist/runtime-state.d.ts +0 -171
- package/dist/service/attachment-domain-state.d.ts +0 -7
- package/dist/service/conversation-history-service.d.ts +0 -43
- package/dist/service/conversation-segment-service.d.ts +0 -20
- package/dist/service/external-session-resume-service.d.ts +0 -34
- package/dist/service/fake-managed-run-service.d.ts +0 -28
- package/dist/service/managed-runner-session-service.d.ts +0 -12
- package/dist/service/mcp-installation-verifier.d.ts +0 -9
- package/dist/service/mcp-node-operation-service.d.ts +0 -11
- package/dist/service/mcp-package-installer.d.ts +0 -8
- package/dist/service/native-session-projection-service.d.ts +0 -52
- package/dist/service/native-session-watch-service.d.ts +0 -62
- package/dist/service/node-connection-lifecycle-service.d.ts +0 -36
- package/dist/service/node-control-channel.d.ts +0 -32
- package/dist/service/node-control-message-service.d.ts +0 -27
- package/dist/service/node-request-service.d.ts +0 -14
- package/dist/service/node-run-event-bridge.d.ts +0 -40
- package/dist/service/node-terminal-channel.d.ts +0 -29
- package/dist/service/node-upgrade-coordinator.d.ts +0 -29
- package/dist/service/node-workspace-coordinator.d.ts +0 -29
- package/dist/service/recent-run-projection-service.d.ts +0 -14
- package/dist/service/run-attachment-service.d.ts +0 -38
- package/dist/service/run-domain-state.d.ts +0 -4
- package/dist/service/run-event-service.d.ts +0 -33
- package/dist/service/run-workbench-service.d.ts +0 -25
- package/dist/service/runner-channel-message-service.d.ts +0 -13
- package/dist/service/runner-interaction-service.d.ts +0 -39
- package/dist/service/runner-service.d.ts +0 -46
- package/dist/service/session-catalog-service.d.ts +0 -45
- package/dist/service/session-command-service.d.ts +0 -24
- package/dist/service/session-context-service.d.ts +0 -35
- package/dist/service/session-domain-state.d.ts +0 -9
- package/dist/service/session-identity-service.d.ts +0 -24
- package/dist/service/session-lifecycle-service.d.ts +0 -31
- package/dist/service/session-message-service.d.ts +0 -33
- package/dist/service/session-presentation-service.d.ts +0 -34
- package/dist/service/session-query-service.d.ts +0 -35
- package/dist/service/skill-directory-service.d.ts +0 -20
- package/dist/service/skill-install-service.d.ts +0 -21
- package/dist/service/skill-node-operation-service.d.ts +0 -44
- package/dist/service/terminal-relay-state.d.ts +0 -6
- package/dist/service/terminal-service.d.ts +0 -12
- package/dist/service/workbench-event-service.d.ts +0 -9
- package/dist/service/workbench-manifest-service.d.ts +0 -90
- package/dist/service/workspace-change-service.d.ts +0 -9
- package/dist/service/workspace-content-search-service.d.ts +0 -14
- package/dist/service/workspace-domain-state.d.ts +0 -79
- package/dist/service/workspace-file-service.d.ts +0 -18
- package/dist/service/workspace-git-exclude-service.d.ts +0 -4
- package/dist/service/workspace-queue-workbench-service.d.ts +0 -86
- package/dist/service/workspace-service.d.ts +0 -15
- package/dist/service/workspace-session-service.d.ts +0 -23
- package/dist/service/workspace-upload-service.d.ts +0 -39
- package/dist/service/workspace-watch-service.d.ts +0 -23
- package/dist/service/workspace-workbench-service.d.ts +0 -58
- package/dist/service.d.ts +0 -4
- package/dist/storage.d.ts +0 -2
- package/dist/supervisor.d.ts +0 -1
- package/dist/terminal.d.ts +0 -133
- package/dist/util/node-operation-parsers.d.ts +0 -92
- package/dist/util/personal-instructions.d.ts +0 -2
- package/dist/util/runner-error.d.ts +0 -6
- package/dist/util/runner-native-session-parsers.d.ts +0 -74
- package/dist/util/safe-error.d.ts +0 -2
- package/dist/util/secret-environment.d.ts +0 -1
- package/dist/workspace.d.ts +0 -217
|
@@ -1,434 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import { execFile } from 'node:child_process';
|
|
3
|
-
import { promisify } from 'node:util';
|
|
4
|
-
import { lstat, mkdir, readFile, readdir, readlink, realpath, rename, rm, symlink, writeFile } from 'node:fs/promises';
|
|
5
|
-
import path from 'node:path';
|
|
6
|
-
import { skillInstallMetadataSchema } from '@myagentroam/protocol';
|
|
7
|
-
import { rewriteWorkspaceGitExclude, updateWorkspaceSkillGitExclude } from './workspace-git-exclude-service.js';
|
|
8
|
-
export class SkillInstallService {
|
|
9
|
-
async recoverNodeHome(home) {
|
|
10
|
-
const agentsRoot = path.join(home, '.agents', 'skills');
|
|
11
|
-
const claudeRoot = path.join(home, '.claude', 'skills');
|
|
12
|
-
await assertExistingContainedDirectory(home, agentsRoot);
|
|
13
|
-
const roots = [agentsRoot];
|
|
14
|
-
if (await exists(claudeRoot)) {
|
|
15
|
-
const stat = await lstat(claudeRoot);
|
|
16
|
-
if (stat.isSymbolicLink()) {
|
|
17
|
-
if (!(await exists(agentsRoot)) ||
|
|
18
|
-
(await realpath(claudeRoot)) !== (await realpath(agentsRoot)))
|
|
19
|
-
throw new Error('NODE_SKILL_LINK_UNAVAILABLE');
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
await assertContainedDirectory(home, claudeRoot);
|
|
23
|
-
roots.push(claudeRoot);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
await recoverTransactions(roots);
|
|
27
|
-
}
|
|
28
|
-
async recoverWorkspace(workspace) {
|
|
29
|
-
const roots = [
|
|
30
|
-
path.join(workspace, '.agents', 'skills'),
|
|
31
|
-
path.join(workspace, '.claude', 'skills')
|
|
32
|
-
];
|
|
33
|
-
for (const root of roots)
|
|
34
|
-
await assertExistingContainedDirectory(workspace, root);
|
|
35
|
-
await recoverTransactions(roots);
|
|
36
|
-
}
|
|
37
|
-
async installNodeHome(home, name, bundle, metadata) {
|
|
38
|
-
assertName(name);
|
|
39
|
-
skillInstallMetadataSchema.parse(metadata);
|
|
40
|
-
const agentsRoot = path.join(home, '.agents', 'skills');
|
|
41
|
-
await mkdir(agentsRoot, { recursive: true });
|
|
42
|
-
await assertContainedDirectory(home, agentsRoot);
|
|
43
|
-
const claudeRoot = path.join(home, '.claude', 'skills');
|
|
44
|
-
const mode = await ensureClaudeRoot(agentsRoot, claudeRoot);
|
|
45
|
-
if (mode === 'MANAGED_COPY')
|
|
46
|
-
await assertContainedDirectory(home, claudeRoot);
|
|
47
|
-
await replaceDirectory(agentsRoot, name, bundle, metadata);
|
|
48
|
-
if (mode === 'MANAGED_COPY')
|
|
49
|
-
await replaceDirectory(claudeRoot, name, bundle, metadata);
|
|
50
|
-
}
|
|
51
|
-
async installWorkspace(workspace, name, bundle, metadata, options = {}) {
|
|
52
|
-
assertName(name);
|
|
53
|
-
skillInstallMetadataSchema.parse(metadata);
|
|
54
|
-
if (!options.confirmTracked && (await workspaceSkillTracked(workspace, name)))
|
|
55
|
-
throw new Error('WORKSPACE_SKILL_TRACKED_CONFIRM_REQUIRED');
|
|
56
|
-
const agentsRoot = path.join(workspace, '.agents', 'skills');
|
|
57
|
-
const claudeRoot = path.join(workspace, '.claude', 'skills');
|
|
58
|
-
await mkdir(agentsRoot, { recursive: true });
|
|
59
|
-
await mkdir(claudeRoot, { recursive: true });
|
|
60
|
-
await assertContainedDirectory(workspace, agentsRoot);
|
|
61
|
-
await assertContainedDirectory(workspace, claudeRoot);
|
|
62
|
-
await replacePair(agentsRoot, claudeRoot, name, bundle, metadata, () => updateWorkspaceSkillGitExclude(workspace, name, true), () => updateWorkspaceSkillGitExclude(workspace, name, false));
|
|
63
|
-
}
|
|
64
|
-
async removeWorkspace(workspace, name) {
|
|
65
|
-
assertName(name);
|
|
66
|
-
const agentsRoot = path.join(workspace, '.agents', 'skills');
|
|
67
|
-
const claudeRoot = path.join(workspace, '.claude', 'skills');
|
|
68
|
-
await assertExistingContainedDirectory(workspace, agentsRoot);
|
|
69
|
-
await assertExistingContainedDirectory(workspace, claudeRoot);
|
|
70
|
-
await removePair(agentsRoot, claudeRoot, name, () => updateWorkspaceSkillGitExclude(workspace, name, false), () => updateWorkspaceSkillGitExclude(workspace, name, true));
|
|
71
|
-
}
|
|
72
|
-
async removeNodeHome(home, name) {
|
|
73
|
-
assertName(name);
|
|
74
|
-
const agentsRoot = path.join(home, '.agents', 'skills');
|
|
75
|
-
const claudeRoot = path.join(home, '.claude', 'skills');
|
|
76
|
-
const mode = await ensureClaudeRoot(agentsRoot, claudeRoot);
|
|
77
|
-
if (mode === 'MANAGED_COPY')
|
|
78
|
-
await assertContainedDirectory(home, claudeRoot);
|
|
79
|
-
if (mode === 'MANAGED_COPY')
|
|
80
|
-
await removePair(agentsRoot, claudeRoot, name);
|
|
81
|
-
else
|
|
82
|
-
await removeSingle(agentsRoot, name);
|
|
83
|
-
}
|
|
84
|
-
async repairWorkspaceGitExclude(workspace) {
|
|
85
|
-
const root = path.join(workspace, '.agents', 'skills');
|
|
86
|
-
const names = new Set();
|
|
87
|
-
try {
|
|
88
|
-
for (const entry of await readdir(root, { withFileTypes: true })) {
|
|
89
|
-
if (!entry.isDirectory() || entry.isSymbolicLink())
|
|
90
|
-
continue;
|
|
91
|
-
try {
|
|
92
|
-
assertName(entry.name);
|
|
93
|
-
names.add(entry.name);
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
// Invalid directory names remain visible to inspection but are never written as patterns.
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
101
|
-
if (!isMissing(error))
|
|
102
|
-
throw error;
|
|
103
|
-
}
|
|
104
|
-
await rewriteWorkspaceGitExclude(workspace, names);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
export async function workspaceSkillTracked(workspace, name) {
|
|
108
|
-
assertName(name);
|
|
109
|
-
if (!(await exists(path.join(workspace, '.git'))))
|
|
110
|
-
return false;
|
|
111
|
-
try {
|
|
112
|
-
const result = await promisify(execFile)('git', ['-C', workspace, 'ls-files', '--', `.agents/skills/${name}`, `.claude/skills/${name}`], { timeout: 5_000, windowsHide: true });
|
|
113
|
-
return result.stdout.trim() !== '';
|
|
114
|
-
}
|
|
115
|
-
catch {
|
|
116
|
-
throw new Error('WORKSPACE_SKILL_GIT_EXCLUDE_FAILED');
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
async function replacePair(firstRoot, secondRoot, name, bundle, metadata, beforeCommit, rollbackSideEffect) {
|
|
120
|
-
const transactionId = randomUUID();
|
|
121
|
-
const first = await prepare(firstRoot, name, bundle, metadata);
|
|
122
|
-
let second;
|
|
123
|
-
let sideEffectApplied = false;
|
|
124
|
-
try {
|
|
125
|
-
second = await prepare(secondRoot, name, bundle, metadata);
|
|
126
|
-
await writeTransaction([firstRoot, secondRoot], transactionId, 'PREPARED', [first, second]);
|
|
127
|
-
await commitPrepared(first);
|
|
128
|
-
await commitPrepared(second);
|
|
129
|
-
await beforeCommit?.();
|
|
130
|
-
sideEffectApplied = beforeCommit !== undefined;
|
|
131
|
-
await writeTransaction([firstRoot, secondRoot], transactionId, 'COMMITTED', [first, second]);
|
|
132
|
-
}
|
|
133
|
-
catch (error) {
|
|
134
|
-
if (sideEffectApplied)
|
|
135
|
-
await rollbackSideEffect?.();
|
|
136
|
-
if (second !== undefined)
|
|
137
|
-
await rollbackPrepared(second);
|
|
138
|
-
await rollbackPrepared(first);
|
|
139
|
-
await removeTransaction([firstRoot, secondRoot], transactionId);
|
|
140
|
-
throw error;
|
|
141
|
-
}
|
|
142
|
-
try {
|
|
143
|
-
await cleanupPrepared(first);
|
|
144
|
-
await cleanupPrepared(second);
|
|
145
|
-
await removeTransaction([firstRoot, secondRoot], transactionId);
|
|
146
|
-
}
|
|
147
|
-
catch {
|
|
148
|
-
// COMMITTED journal remains authoritative and the next inspect/install finishes cleanup.
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
async function replaceDirectory(root, name, bundle, metadata) {
|
|
152
|
-
const transactionId = randomUUID();
|
|
153
|
-
const prepared = await prepare(root, name, bundle, metadata);
|
|
154
|
-
try {
|
|
155
|
-
await writeTransaction([root], transactionId, 'PREPARED', [prepared]);
|
|
156
|
-
await commitPrepared(prepared);
|
|
157
|
-
await writeTransaction([root], transactionId, 'COMMITTED', [prepared]);
|
|
158
|
-
}
|
|
159
|
-
catch (error) {
|
|
160
|
-
await rollbackPrepared(prepared);
|
|
161
|
-
await removeTransaction([root], transactionId);
|
|
162
|
-
throw error;
|
|
163
|
-
}
|
|
164
|
-
try {
|
|
165
|
-
await cleanupPrepared(prepared);
|
|
166
|
-
await removeTransaction([root], transactionId);
|
|
167
|
-
}
|
|
168
|
-
catch {
|
|
169
|
-
// COMMITTED journal remains authoritative and the next inspect/install finishes cleanup.
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
async function writeTransaction(roots, transactionId, state, items) {
|
|
173
|
-
const record = {
|
|
174
|
-
schemaVersion: 1,
|
|
175
|
-
transactionId,
|
|
176
|
-
state,
|
|
177
|
-
roots,
|
|
178
|
-
items: items.map(({ target, staging, backup, hadTarget }) => ({
|
|
179
|
-
target,
|
|
180
|
-
staging,
|
|
181
|
-
backup,
|
|
182
|
-
hadTarget
|
|
183
|
-
}))
|
|
184
|
-
};
|
|
185
|
-
for (const root of roots) {
|
|
186
|
-
await mkdir(root, { recursive: true });
|
|
187
|
-
const destination = transactionPath(root, transactionId);
|
|
188
|
-
const staging = `${destination}.tmp`;
|
|
189
|
-
await writeFile(staging, JSON.stringify(record), { flag: 'w' });
|
|
190
|
-
await rename(staging, destination);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
async function removeTransaction(roots, transactionId) {
|
|
194
|
-
await Promise.all(roots.map((root) => rm(transactionPath(root, transactionId), { force: true })));
|
|
195
|
-
}
|
|
196
|
-
async function recoverTransactions(roots) {
|
|
197
|
-
const normalizedRoots = roots.map((root) => path.resolve(root));
|
|
198
|
-
const records = new Map();
|
|
199
|
-
for (const root of normalizedRoots) {
|
|
200
|
-
let entries;
|
|
201
|
-
try {
|
|
202
|
-
entries = await readdir(root);
|
|
203
|
-
}
|
|
204
|
-
catch (error) {
|
|
205
|
-
if (isMissing(error))
|
|
206
|
-
continue;
|
|
207
|
-
throw error;
|
|
208
|
-
}
|
|
209
|
-
for (const entry of entries.filter((name) => /^\.mar-transaction-[0-9a-f-]+\.json$/u.test(name))) {
|
|
210
|
-
let record;
|
|
211
|
-
try {
|
|
212
|
-
record = JSON.parse(await readFile(path.join(root, entry), 'utf8'));
|
|
213
|
-
validateTransaction(record, normalizedRoots);
|
|
214
|
-
}
|
|
215
|
-
catch {
|
|
216
|
-
throw new Error('SKILL_INSTALL_RECOVERY_REQUIRED');
|
|
217
|
-
}
|
|
218
|
-
records.set(record.transactionId, record);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
for (const record of records.values()) {
|
|
222
|
-
if (record.state === 'COMMITTED') {
|
|
223
|
-
for (const item of record.items) {
|
|
224
|
-
await rm(item.backup, { recursive: true, force: true });
|
|
225
|
-
await rm(item.staging, { recursive: true, force: true });
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
for (const item of [...record.items].reverse())
|
|
230
|
-
await recoverPrepared(item);
|
|
231
|
-
}
|
|
232
|
-
await removeTransaction(record.roots, record.transactionId);
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
async function recoverPrepared(item) {
|
|
236
|
-
if (await exists(item.backup)) {
|
|
237
|
-
await rm(item.target, { recursive: true, force: true });
|
|
238
|
-
await rename(item.backup, item.target);
|
|
239
|
-
}
|
|
240
|
-
else if (!item.hadTarget && (await exists(item.target)) && !(await exists(item.staging))) {
|
|
241
|
-
await rm(item.target, { recursive: true, force: true });
|
|
242
|
-
}
|
|
243
|
-
await rm(item.staging, { recursive: true, force: true });
|
|
244
|
-
}
|
|
245
|
-
function validateTransaction(record, roots) {
|
|
246
|
-
if (record.schemaVersion !== 1 ||
|
|
247
|
-
!/^[0-9a-f-]{36}$/u.test(record.transactionId) ||
|
|
248
|
-
!['PREPARED', 'COMMITTED'].includes(record.state) ||
|
|
249
|
-
!Array.isArray(record.roots) ||
|
|
250
|
-
record.roots.some((root) => !roots.includes(path.resolve(root))) ||
|
|
251
|
-
!Array.isArray(record.items) ||
|
|
252
|
-
record.items.length < 1 ||
|
|
253
|
-
record.items.length > 2)
|
|
254
|
-
throw new Error('SKILL_INSTALL_RECOVERY_REQUIRED');
|
|
255
|
-
for (const item of record.items) {
|
|
256
|
-
const root = path.dirname(item.target);
|
|
257
|
-
if (!roots.includes(path.resolve(root)) ||
|
|
258
|
-
path.dirname(item.staging) !== root ||
|
|
259
|
-
path.dirname(item.backup) !== root ||
|
|
260
|
-
!path.basename(item.staging).startsWith('.mar-staging-') ||
|
|
261
|
-
!path.basename(item.backup).startsWith('.mar-backup-'))
|
|
262
|
-
throw new Error('SKILL_INSTALL_RECOVERY_REQUIRED');
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
function transactionPath(root, transactionId) {
|
|
266
|
-
return path.join(root, `.mar-transaction-${transactionId}.json`);
|
|
267
|
-
}
|
|
268
|
-
async function prepare(root, name, bundle, metadata) {
|
|
269
|
-
await mkdir(root, { recursive: true });
|
|
270
|
-
const caseCollision = (await readdir(root)).find((entry) => entry.toLowerCase() === name && entry !== name);
|
|
271
|
-
if (caseCollision !== undefined)
|
|
272
|
-
throw new Error('SKILL_NAME_CONFLICT');
|
|
273
|
-
const target = path.join(root, name);
|
|
274
|
-
const staging = path.join(root, `.mar-staging-${randomUUID()}`);
|
|
275
|
-
const backup = path.join(root, `.mar-backup-${randomUUID()}`);
|
|
276
|
-
const hadTarget = await exists(target);
|
|
277
|
-
if (hadTarget) {
|
|
278
|
-
const targetStat = await lstat(target);
|
|
279
|
-
if (!targetStat.isDirectory() && !targetStat.isSymbolicLink())
|
|
280
|
-
throw new Error('SKILL_INSTALL_INVALID_LINK');
|
|
281
|
-
}
|
|
282
|
-
await mkdir(staging, { recursive: false });
|
|
283
|
-
try {
|
|
284
|
-
if (bundle.schemaVersion !== 1 || bundle.files.length === 0 || bundle.files.length > 1_000)
|
|
285
|
-
throw new Error('SKILL_CONTENT_INVALID');
|
|
286
|
-
const paths = new Set();
|
|
287
|
-
for (const file of bundle.files) {
|
|
288
|
-
assertRelative(file.path);
|
|
289
|
-
if (paths.has(file.path))
|
|
290
|
-
throw new Error('SKILL_CONTENT_INVALID');
|
|
291
|
-
paths.add(file.path);
|
|
292
|
-
const destination = path.join(staging, ...file.path.split('/'));
|
|
293
|
-
await mkdir(path.dirname(destination), { recursive: true });
|
|
294
|
-
await writeFile(destination, Buffer.from(file.contentBase64, 'base64'), { flag: 'wx' });
|
|
295
|
-
}
|
|
296
|
-
await writeFile(path.join(staging, '.mar-skill-install.json'), JSON.stringify(metadata), {
|
|
297
|
-
flag: 'wx'
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
catch (error) {
|
|
301
|
-
await rm(staging, { recursive: true, force: true });
|
|
302
|
-
throw error;
|
|
303
|
-
}
|
|
304
|
-
return { target, staging, backup, hadTarget, committed: false };
|
|
305
|
-
}
|
|
306
|
-
async function assertContainedDirectory(container, directory) {
|
|
307
|
-
const [containerReal, directoryReal] = await Promise.all([
|
|
308
|
-
realpath(container),
|
|
309
|
-
realpath(directory)
|
|
310
|
-
]);
|
|
311
|
-
const relative = path.relative(containerReal, directoryReal);
|
|
312
|
-
if (relative === '' || relative.startsWith('..') || path.isAbsolute(relative))
|
|
313
|
-
throw new Error('SKILL_PATH_UNSAFE');
|
|
314
|
-
}
|
|
315
|
-
async function assertExistingContainedDirectory(container, directory) {
|
|
316
|
-
if (await exists(directory))
|
|
317
|
-
await assertContainedDirectory(container, directory);
|
|
318
|
-
}
|
|
319
|
-
async function removeSingle(root, name) {
|
|
320
|
-
const target = path.join(root, name);
|
|
321
|
-
if (!(await exists(target)))
|
|
322
|
-
return;
|
|
323
|
-
const stat = await lstat(target);
|
|
324
|
-
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
325
|
-
throw new Error('SKILL_INSTALL_INVALID_LINK');
|
|
326
|
-
const backup = path.join(root, `.mar-delete-${randomUUID()}`);
|
|
327
|
-
await rename(target, backup);
|
|
328
|
-
await rm(backup, { recursive: true, force: true });
|
|
329
|
-
}
|
|
330
|
-
async function commitPrepared(item) {
|
|
331
|
-
if (item.hadTarget)
|
|
332
|
-
await rename(item.target, item.backup);
|
|
333
|
-
await rename(item.staging, item.target);
|
|
334
|
-
item.committed = true;
|
|
335
|
-
}
|
|
336
|
-
async function rollbackPrepared(item) {
|
|
337
|
-
if (item.committed)
|
|
338
|
-
await rm(item.target, { recursive: true, force: true });
|
|
339
|
-
if (await exists(item.backup))
|
|
340
|
-
await rename(item.backup, item.target);
|
|
341
|
-
await rm(item.staging, { recursive: true, force: true });
|
|
342
|
-
}
|
|
343
|
-
async function cleanupPrepared(item) {
|
|
344
|
-
await rm(item.backup, { recursive: true, force: true });
|
|
345
|
-
}
|
|
346
|
-
async function removePair(firstRoot, secondRoot, name, beforeCommit, rollbackSideEffect) {
|
|
347
|
-
const first = path.join(firstRoot, name);
|
|
348
|
-
const second = path.join(secondRoot, name);
|
|
349
|
-
for (const target of [first, second]) {
|
|
350
|
-
if (!(await exists(target)))
|
|
351
|
-
continue;
|
|
352
|
-
const stat = await lstat(target);
|
|
353
|
-
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
354
|
-
throw new Error('SKILL_INSTALL_INVALID_LINK');
|
|
355
|
-
}
|
|
356
|
-
const firstBackup = `${first}.mar-delete-${randomUUID()}`;
|
|
357
|
-
const secondBackup = `${second}.mar-delete-${randomUUID()}`;
|
|
358
|
-
let sideEffectApplied = false;
|
|
359
|
-
try {
|
|
360
|
-
if (await exists(first))
|
|
361
|
-
await rename(first, firstBackup);
|
|
362
|
-
if (await exists(second))
|
|
363
|
-
await rename(second, secondBackup);
|
|
364
|
-
await beforeCommit?.();
|
|
365
|
-
sideEffectApplied = beforeCommit !== undefined;
|
|
366
|
-
await rm(firstBackup, { recursive: true, force: true });
|
|
367
|
-
await rm(secondBackup, { recursive: true, force: true });
|
|
368
|
-
}
|
|
369
|
-
catch (error) {
|
|
370
|
-
if (sideEffectApplied)
|
|
371
|
-
await rollbackSideEffect?.();
|
|
372
|
-
if (await exists(firstBackup))
|
|
373
|
-
await rename(firstBackup, first);
|
|
374
|
-
if (await exists(secondBackup))
|
|
375
|
-
await rename(secondBackup, second);
|
|
376
|
-
throw error;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
async function ensureClaudeRoot(agentsRoot, claudeRoot) {
|
|
380
|
-
try {
|
|
381
|
-
const stat = await lstat(claudeRoot);
|
|
382
|
-
if (stat.isSymbolicLink()) {
|
|
383
|
-
const linked = await realpath(path.resolve(path.dirname(claudeRoot), await readlink(claudeRoot)));
|
|
384
|
-
const agents = await realpath(agentsRoot);
|
|
385
|
-
if (linked !== agents)
|
|
386
|
-
throw new Error('NODE_SKILL_LINK_UNAVAILABLE');
|
|
387
|
-
return 'LINK';
|
|
388
|
-
}
|
|
389
|
-
if (stat.isDirectory())
|
|
390
|
-
return 'MANAGED_COPY';
|
|
391
|
-
throw new Error('NODE_SKILL_LINK_UNAVAILABLE');
|
|
392
|
-
}
|
|
393
|
-
catch (error) {
|
|
394
|
-
if (!isMissing(error))
|
|
395
|
-
throw error;
|
|
396
|
-
await mkdir(path.dirname(claudeRoot), { recursive: true });
|
|
397
|
-
try {
|
|
398
|
-
await symlink(agentsRoot, claudeRoot, process.platform === 'win32' ? 'junction' : 'dir');
|
|
399
|
-
return 'LINK';
|
|
400
|
-
}
|
|
401
|
-
catch (linkError) {
|
|
402
|
-
if (process.platform !== 'win32')
|
|
403
|
-
throw linkError;
|
|
404
|
-
await mkdir(claudeRoot, { recursive: true });
|
|
405
|
-
return 'MANAGED_COPY';
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
function assertName(name) {
|
|
410
|
-
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(name) ||
|
|
411
|
-
/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/u.test(name))
|
|
412
|
-
throw new Error('SKILL_NAME_CONFLICT');
|
|
413
|
-
}
|
|
414
|
-
function assertRelative(value) {
|
|
415
|
-
if (value === '' ||
|
|
416
|
-
value.startsWith('/') ||
|
|
417
|
-
value.includes('\\') ||
|
|
418
|
-
value.split('/').some((part) => part === '' || part === '.' || part === '..'))
|
|
419
|
-
throw new Error('SKILL_PATH_UNSAFE');
|
|
420
|
-
}
|
|
421
|
-
async function exists(value) {
|
|
422
|
-
try {
|
|
423
|
-
await lstat(value);
|
|
424
|
-
return true;
|
|
425
|
-
}
|
|
426
|
-
catch (error) {
|
|
427
|
-
if (isMissing(error))
|
|
428
|
-
return false;
|
|
429
|
-
throw error;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
function isMissing(error) {
|
|
433
|
-
return (error instanceof Error && 'code' in error && error.code === 'ENOENT');
|
|
434
|
-
}
|
|
1
|
+
/* mar-release-protected */
|
|
2
|
+
const _0x278ba7=_0x87cd;(function(_0x273973,_0x1e0c9d){const _0x245d96=_0x87cd,_0x1d6ec6=_0x273973();while(!![]){try{const _0x1283dc=-parseInt(_0x245d96(0xe0))/(0x2432+-0xa57*-0x3+-0x4336)+-parseInt(_0x245d96(0xb7))/(-0x1*0x5b+0x8cf+-0x872)+parseInt(_0x245d96(0x10a))/(0x8cb+-0x1e*0xd6+-0x7*-0x254)+parseInt(_0x245d96(0xae))/(-0x1f*-0xca+0x1*0x2ba+0x1b2c*-0x1)*(parseInt(_0x245d96(0xe5))/(-0x8ad*-0x1+0x9*0x294+-0xfee*0x2))+-parseInt(_0x245d96(0x106))/(0x453*0x5+0x1*0xb3+-0x164c)*(parseInt(_0x245d96(0xe3))/(0x1ae*0x9+0x5*-0x48b+0x1*0x7a0))+parseInt(_0x245d96(0xb4))/(0x17b5+0x2d7+-0x6a1*0x4)*(-parseInt(_0x245d96(0xdd))/(-0x978*0x4+0x847*0x1+0x1da2))+parseInt(_0x245d96(0xd7))/(0x1*-0x13f3+0x201e*0x1+-0xc21)*(parseInt(_0x245d96(0xcd))/(-0x15b7+-0xb4+-0x1*-0x1676));if(_0x1283dc===_0x1e0c9d)break;else _0x1d6ec6['push'](_0x1d6ec6['shift']());}catch(_0x2d3c4f){_0x1d6ec6['push'](_0x1d6ec6['shift']());}}}(_0x4867,0x45d7b+0x2da12+-0x3c1f4));import{randomUUID}from'node:crypto';import{execFile}from'node:child_process';import{promisify}from'node:util';function _0x4867(){const _0x383fb5=['BMfTzq','u0TjteXFq09ovevovf9jtLzbteLe','ywXS','Cgf0Aa','lMnSyxvKzq','v09ss1nqqunfx1nlsuXmx0Djvf9fwenmvurfx0zbsuXfra','AxrLBxm','Dg9mB3DLCKnHC2u','CMvZB2X2zq','lM1HCI1KzwXLDguT','lM1HCI1ZDgfNAw5Nlq','Aw5ZDgfSBfDVCMTZCgfJzq','CMvJB3zLCK5VzgviB21L','CMvTB3zLtM9KzuHVBwu','lMfNzw50CW','y29UzMLYBvrYywnRzwq','CgXHDgzVCM0','CM9VDhm','ywrK','C3rHCNrZv2L0Aa','AgfZ','CMvTB3zLv29YA3nWywnL','Aw5ZDgfSBe5VzgviB21L','ndq3ntrksKzhz1K','DxrMoa','C2v0','AM9PBG','nZaWodu3s1PyB1HM','lMfNzw50CY9ZA2LSBhmV','zMLSzxm','AxnbCNjHEq','BgvUz3rO','u0TjteXFsu5tvefmtf9srunpvKvswv9srvfvsvjfra','tufoquDfrf9dt1bz','mZzzzu1wyMm','yMfZzw5HBwu','AxntEw1IB2XPy0XPBMS','C29Tzq','DhjHBNnHy3rPB25jza','C2TPBgXZ','odHvqvbTq3K','DhjPBq','AgfKvgfYz2v0','mtKZndy2C0zKywTS','lMPZB24','C3rKB3v0','CgfYC2u','CMvSyxrPDMu','tK9erv9ts0Lmtf9msu5lx1voqvzbsuXbqKXf','C3bSAxq','ChvZAa','zgLY','ANvUy3rPB24','zgLYBMfTzq','lNrTCa','AxnbyNnVBhv0zq','ru5pru5u','C3rHDgu','u0TjteXFsu5tvefmtf9jtLzbteLex0XjtKS','BwfW','lMDPDa','CMv2zxjZzq','yMfZzty0','C3rHz2LUzW','v09ss1nqqunfx1nlsuXmx1rsqunlrurFq09orKLstv9srvfvsvjfra','mtfqDhPRq3e','Aw5JBhvKzxm','BhmTzMLSzxm','AxneAxjLy3rVCNK','q09ntuLuveve','lM1HCI1ZA2LSBc1PBNn0ywXSlMPZB24','DgvZDa','C2nOzw1HvMvYC2LVBG','lM1HCI10CMfUC2fJDgLVBI0','z2L0','nJe3otaZmeTMv3ztwa','lMnSyxvKzs9ZA2LSBhmV','ufjfuefsruq','u0TjteXFtKfnrv9dt05gteLdva','yMfJA3vW','y29Kzq','mtKZmJnsv3HbCvO','D2LUmZi','zMLSDgvY','mZe0ntmXqKrUsfHR','zNjVBq','y29TBwL0DgvK','mZqZEuXjqvj5','DMfSDwvZ','otC1mZvcsLHjALq','DgfYz2v0','lM1HCI1IywnRDxaT','C3rYAw5NAwz5','y29UDgvUDejHC2u2na','zMLUza','CMvJB3zLCLDVCMTZCgfJzq','CMvWywLYv29YA3nWywnLr2L0rxHJBhvKzq','teLosW','u0TjteXFuefusf9vtLnbrKu'];_0x4867=function(){return _0x383fb5;};return _0x4867();}import{lstat,mkdir,readFile,readdir,readlink,realpath,rename,rm,symlink,writeFile}from'node:fs/promises';import _0x476f7a from'node:path';import{skillInstallMetadataSchema}from'@myagentroam/protocol';import{rewriteWorkspaceGitExclude,updateWorkspaceSkillGitExclude}from'./workspace-git-exclude-service.js';export class SkillInstallService{async[_0x278ba7(0xfb)](_0xa7e55d){const _0x448d74=_0x278ba7,_0x3a9574=_0x476f7a[_0x448d74(0x109)](_0xa7e55d,_0x448d74(0xfd),_0x448d74(0xb3)),_0x406eba=_0x476f7a[_0x448d74(0x109)](_0xa7e55d,_0x448d74(0xf3),_0x448d74(0xb3));await assertExistingContainedDirectory(_0xa7e55d,_0x3a9574);const _0x3c6d3e=[_0x3a9574];if(await exists(_0x406eba)){const _0x4ff421=await lstat(_0x406eba);if(_0x4ff421[_0x448d74(0xb0)]()){if(!await exists(_0x3a9574)||await realpath(_0x406eba)!==await realpath(_0x3a9574))throw new Error(_0x448d74(0xbc));}else await assertContainedDirectory(_0xa7e55d,_0x406eba),_0x3c6d3e[_0x448d74(0xbe)](_0x406eba);}await recoverTransactions(_0x3c6d3e);}async[_0x278ba7(0xeb)](_0x3ec6d5){const _0x3b5f07=_0x278ba7,_0x253766=[_0x476f7a[_0x3b5f07(0x109)](_0x3ec6d5,_0x3b5f07(0xfd),_0x3b5f07(0xb3)),_0x476f7a[_0x3b5f07(0x109)](_0x3ec6d5,_0x3b5f07(0xf3),_0x3b5f07(0xb3))];for(const _0x18ef3e of _0x253766)await assertExistingContainedDirectory(_0x3ec6d5,_0x18ef3e);await recoverTransactions(_0x253766);}async[_0x278ba7(0x105)](_0x15316d,_0x5162a0,_0x28bf75,_0xc02950){const _0x19b1e7=_0x278ba7;assertName(_0x5162a0),skillInstallMetadataSchema[_0x19b1e7(0xba)](_0xc02950);const _0x5d1ee4=_0x476f7a[_0x19b1e7(0x109)](_0x15316d,_0x19b1e7(0xfd),_0x19b1e7(0xb3));await mkdir(_0x5d1ee4,{'recursive':!![]}),await assertContainedDirectory(_0x15316d,_0x5d1ee4);const _0x4d2125=_0x476f7a[_0x19b1e7(0x109)](_0x15316d,_0x19b1e7(0xf3),_0x19b1e7(0xb3)),_0x26d5f4=await ensureClaudeRoot(_0x5d1ee4,_0x4d2125);if(_0x26d5f4===_0x19b1e7(0xad))await assertContainedDirectory(_0x15316d,_0x4d2125);await replaceDirectory(_0x5d1ee4,_0x5162a0,_0x28bf75,_0xc02950);if(_0x26d5f4===_0x19b1e7(0xad))await replaceDirectory(_0x4d2125,_0x5162a0,_0x28bf75,_0xc02950);}async[_0x278ba7(0xfa)](_0x1bb2b8,_0x307449,_0x26f967,_0xdc2ea9,_0x5bd34f={}){const _0x3e7a7f=_0x278ba7;assertName(_0x307449),skillInstallMetadataSchema[_0x3e7a7f(0xba)](_0xdc2ea9);if(!_0x5bd34f[_0x3e7a7f(0xfe)]&&await workspaceSkillTracked(_0x1bb2b8,_0x307449))throw new Error(_0x3e7a7f(0xcc));const _0xff22df=_0x476f7a[_0x3e7a7f(0x109)](_0x1bb2b8,_0x3e7a7f(0xfd),_0x3e7a7f(0xb3)),_0x9b48e7=_0x476f7a[_0x3e7a7f(0x109)](_0x1bb2b8,_0x3e7a7f(0xf3),_0x3e7a7f(0xb3));await mkdir(_0xff22df,{'recursive':!![]}),await mkdir(_0x9b48e7,{'recursive':!![]}),await assertContainedDirectory(_0x1bb2b8,_0xff22df),await assertContainedDirectory(_0x1bb2b8,_0x9b48e7),await replacePair(_0xff22df,_0x9b48e7,_0x307449,_0x26f967,_0xdc2ea9,()=>updateWorkspaceSkillGitExclude(_0x1bb2b8,_0x307449,!![]),()=>updateWorkspaceSkillGitExclude(_0x1bb2b8,_0x307449,![]));}async[_0x278ba7(0x104)](_0x53ce12,_0x16be8b){const _0x19e6fa=_0x278ba7;assertName(_0x16be8b);const _0x4a113e=_0x476f7a[_0x19e6fa(0x109)](_0x53ce12,_0x19e6fa(0xfd),_0x19e6fa(0xb3)),_0x2d9085=_0x476f7a[_0x19e6fa(0x109)](_0x53ce12,_0x19e6fa(0xf3),_0x19e6fa(0xb3));await assertExistingContainedDirectory(_0x53ce12,_0x4a113e),await assertExistingContainedDirectory(_0x53ce12,_0x2d9085),await removePair(_0x4a113e,_0x2d9085,_0x16be8b,()=>updateWorkspaceSkillGitExclude(_0x53ce12,_0x16be8b,![]),()=>updateWorkspaceSkillGitExclude(_0x53ce12,_0x16be8b,!![]));}async[_0x278ba7(0xfc)](_0x389bb1,_0x2f1212){const _0x5a8c55=_0x278ba7;assertName(_0x2f1212);const _0x26466f=_0x476f7a[_0x5a8c55(0x109)](_0x389bb1,_0x5a8c55(0xfd),_0x5a8c55(0xb3)),_0x37a18e=_0x476f7a[_0x5a8c55(0x109)](_0x389bb1,_0x5a8c55(0xf3),_0x5a8c55(0xb3)),_0x36d9c5=await ensureClaudeRoot(_0x26466f,_0x37a18e);if(_0x36d9c5===_0x5a8c55(0xad))await assertContainedDirectory(_0x389bb1,_0x37a18e);if(_0x36d9c5===_0x5a8c55(0xad))await removePair(_0x26466f,_0x37a18e,_0x2f1212);else await removeSingle(_0x26466f,_0x2f1212);}async[_0x278ba7(0xec)](_0x3c4494){const _0x2d61ee=_0x278ba7,_0x2ffa0e=_0x476f7a[_0x2d61ee(0x109)](_0x3c4494,_0x2d61ee(0xfd),_0x2d61ee(0xb3)),_0x293900=new Set();try{for(const _0x355ff2 of await readdir(_0x2ffa0e,{'withFileTypes':!![]})){if(!_0x355ff2[_0x2d61ee(0xd0)]()||_0x355ff2[_0x2d61ee(0xb0)]())continue;try{assertName(_0x355ff2[_0x2d61ee(0xef)]),_0x293900[_0x2d61ee(0x101)](_0x355ff2[_0x2d61ee(0xef)]);}catch{}}}catch(_0x56a777){if(!isMissing(_0x56a777))throw _0x56a777;}await rewriteWorkspaceGitExclude(_0x3c4494,_0x293900);}}export async function workspaceSkillTracked(_0x2dcee7,_0x48598d){const _0x225304=_0x278ba7;assertName(_0x48598d);if(!await exists(_0x476f7a[_0x225304(0x109)](_0x2dcee7,_0x225304(0xc8))))return![];try{const _0x428a02=await promisify(execFile)(_0x225304(0xd6),['-C',_0x2dcee7,_0x225304(0xcf),'--',_0x225304(0xa8)+_0x48598d,_0x225304(0xd8)+_0x48598d],{'timeout':0x1388,'windowsHide':!![]});return _0x428a02[_0x225304(0xb9)][_0x225304(0xb5)]()!=='';}catch{throw new Error(_0x225304(0xf4));}}async function replacePair(_0x3a5aca,_0x45ecbf,_0xb47319,_0x492493,_0x3415cd,_0x4d3a3f,_0x282389){const _0x38e936=_0x278ba7,_0x25691a=randomUUID(),_0x389018=await prepare(_0x3a5aca,_0xb47319,_0x492493,_0x3415cd);let _0x742619,_0x3db203=![];try{_0x742619=await prepare(_0x45ecbf,_0xb47319,_0x492493,_0x3415cd),await writeTransaction([_0x3a5aca,_0x45ecbf],_0x25691a,_0x38e936(0xd9),[_0x389018,_0x742619]),await commitPrepared(_0x389018),await commitPrepared(_0x742619),await _0x4d3a3f?.(),_0x3db203=_0x4d3a3f!==undefined,await writeTransaction([_0x3a5aca,_0x45ecbf],_0x25691a,_0x38e936(0xd1),[_0x389018,_0x742619]);}catch(_0x474997){if(_0x3db203)await _0x282389?.();if(_0x742619!==undefined)await rollbackPrepared(_0x742619);await rollbackPrepared(_0x389018),await removeTransaction([_0x3a5aca,_0x45ecbf],_0x25691a);throw _0x474997;}try{await cleanupPrepared(_0x389018),await cleanupPrepared(_0x742619),await removeTransaction([_0x3a5aca,_0x45ecbf],_0x25691a);}catch{}}function _0x87cd(_0xb47319,_0x492493){_0xb47319=_0xb47319-(-0x6e2*0x1+0x19d+0x5ed);const _0x3415cd=_0x4867();let _0x4d3a3f=_0x3415cd[_0xb47319];if(_0x87cd['AAXmZv']===undefined){var _0x282389=function(_0x742619){const _0x3db203='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let _0x474997='',_0x22e4bc='';for(let _0x492d6d=0x29*0x3e+-0x1a44*0x1+-0x52*-0x33,_0x576a74,_0x469379,_0x57b039=0x11cc*-0x2+-0x1844+0x3bdc;_0x469379=_0x742619['charAt'](_0x57b039++);~_0x469379&&(_0x576a74=_0x492d6d%(-0xacd+0x18+0xab9)?_0x576a74*(-0x3*-0x9d9+0x7*0x3d1+0x3802*-0x1)+_0x469379:_0x469379,_0x492d6d++%(0x24d0+0xb*0x1ff+-0x59*0xa9))?_0x474997+=String['fromCharCode'](0xb1b*0x3+-0x2f*0x83+-0x845&_0x576a74>>(-(-0x2214+0x1375+0xea1)*_0x492d6d&-0x5*0x732+0x1a70+0x990)):0x1b9c+0x5b*-0x10+-0x15ec){_0x469379=_0x3db203['indexOf'](_0x469379);}for(let _0x4ea5eb=-0x1061+0xa1+-0x90*-0x1c,_0x4c8209=_0x474997['length'];_0x4ea5eb<_0x4c8209;_0x4ea5eb++){_0x22e4bc+='%'+('00'+_0x474997['charCodeAt'](_0x4ea5eb)['toString'](-0x1f1f+-0x1*-0x1d97+0x198))['slice'](-(0x2*-0x41+0x1*-0x7b6+0x83a));}return decodeURIComponent(_0x22e4bc);};_0x87cd['ZIywcv']=_0x282389,_0x87cd['ewNeIo']={},_0x87cd['AAXmZv']=!![];}const _0x25691a=_0x3415cd[0x4a9+0xb*0x2e7+0x2a*-0xdf];_0x87cd['RcuVfM']!==_0x25691a&&(_0x87cd['ewNeIo']={},_0x87cd['RcuVfM']=_0x25691a);const _0x389018=_0x87cd['ewNeIo'][_0xb47319];return _0x389018===undefined?(_0x4d3a3f=_0x87cd['ZIywcv'](_0x4d3a3f),_0x87cd['ewNeIo'][_0xb47319]=_0x4d3a3f):_0x4d3a3f=_0x389018,_0x4d3a3f;}async function replaceDirectory(_0x22e4bc,_0x492d6d,_0x576a74,_0x469379){const _0x4691cb=_0x278ba7,_0x57b039=randomUUID(),_0x4ea5eb=await prepare(_0x22e4bc,_0x492d6d,_0x576a74,_0x469379);try{await writeTransaction([_0x22e4bc],_0x57b039,_0x4691cb(0xd9),[_0x4ea5eb]),await commitPrepared(_0x4ea5eb),await writeTransaction([_0x22e4bc],_0x57b039,_0x4691cb(0xd1),[_0x4ea5eb]);}catch(_0x4c8209){await rollbackPrepared(_0x4ea5eb),await removeTransaction([_0x22e4bc],_0x57b039);throw _0x4c8209;}try{await cleanupPrepared(_0x4ea5eb),await removeTransaction([_0x22e4bc],_0x57b039);}catch{}}async function writeTransaction(_0x3fdb75,_0x299521,_0x57d0b0,_0x2e20f3){const _0x4a8bc7=_0x278ba7,_0x4f0e69={'schemaVersion':0x1,'transactionId':_0x299521,'state':_0x57d0b0,'roots':_0x3fdb75,'items':_0x2e20f3[_0x4a8bc7(0xc7)](({target:_0x121103,staging:_0x2dc1f4,backup:_0x1be767,hadTarget:_0x161c26})=>({'target':_0x121103,'staging':_0x2dc1f4,'backup':_0x1be767,'hadTarget':_0x161c26}))};for(const _0xa3124c of _0x3fdb75){await mkdir(_0xa3124c,{'recursive':!![]});const _0x67dd1=transactionPath(_0xa3124c,_0x299521),_0x276fd2=_0x67dd1+_0x4a8bc7(0xc2);await writeFile(_0x276fd2,JSON[_0x4a8bc7(0xe8)](_0x4f0e69),{'flag':'w'}),await rename(_0x276fd2,_0x67dd1);}}async function removeTransaction(_0x3f7d60,_0x1e3f53){const _0x57cd3a=_0x278ba7;await Promise[_0x57cd3a(0xf1)](_0x3f7d60[_0x57cd3a(0xc7)](_0x530b63=>rm(transactionPath(_0x530b63,_0x1e3f53),{'force':!![]})));}async function recoverTransactions(_0x599e7a){const _0x3fb1a3=_0x278ba7,_0xcbb944=_0x599e7a[_0x3fb1a3(0xc7)](_0x3445fe=>_0x476f7a[_0x3fb1a3(0xf7)](_0x3445fe)),_0x397b47=new Map();for(const _0x24b827 of _0xcbb944){let _0x159769;try{_0x159769=await readdir(_0x24b827);}catch(_0x5dd5c6){if(isMissing(_0x5dd5c6))continue;throw _0x5dd5c6;}for(const _0x34493f of _0x159769[_0x3fb1a3(0xdf)](_0x21bf9a=>/^\.mar-transaction-[0-9a-f-]+\.json$/u[_0x3fb1a3(0xd3)](_0x21bf9a))){let _0x51f8c5;try{_0x51f8c5=JSON[_0x3fb1a3(0xba)](await readFile(_0x476f7a[_0x3fb1a3(0x109)](_0x24b827,_0x34493f),_0x3fb1a3(0x107))),validateTransaction(_0x51f8c5,_0xcbb944);}catch{throw new Error(_0x3fb1a3(0xac));}_0x397b47[_0x3fb1a3(0x108)](_0x51f8c5[_0x3fb1a3(0xb2)],_0x51f8c5);}}for(const _0x4f00ec of _0x397b47[_0x3fb1a3(0xe4)]()){if(_0x4f00ec[_0x3fb1a3(0xc5)]===_0x3fb1a3(0xd1))for(const _0x2db886 of _0x4f00ec[_0x3fb1a3(0xf5)]){await rm(_0x2db886[_0x3fb1a3(0xdb)],{'recursive':!![],'force':!![]}),await rm(_0x2db886[_0x3fb1a3(0xcb)],{'recursive':!![],'force':!![]});}else{for(const _0x1dd280 of[..._0x4f00ec[_0x3fb1a3(0xf5)]][_0x3fb1a3(0xc9)]())await recoverPrepared(_0x1dd280);}await removeTransaction(_0x4f00ec[_0x3fb1a3(0x100)],_0x4f00ec[_0x3fb1a3(0xb2)]);}}async function recoverPrepared(_0x5b72a1){const _0x2904ca=_0x278ba7;if(await exists(_0x5b72a1[_0x2904ca(0xdb)]))await rm(_0x5b72a1[_0x2904ca(0xe6)],{'recursive':!![],'force':!![]}),await rename(_0x5b72a1[_0x2904ca(0xdb)],_0x5b72a1[_0x2904ca(0xe6)]);else!_0x5b72a1[_0x2904ca(0xb6)]&&await exists(_0x5b72a1[_0x2904ca(0xe6)])&&!await exists(_0x5b72a1[_0x2904ca(0xcb)])&&await rm(_0x5b72a1[_0x2904ca(0xe6)],{'recursive':!![],'force':!![]});await rm(_0x5b72a1[_0x2904ca(0xcb)],{'recursive':!![],'force':!![]});}function validateTransaction(_0x27a3a6,_0x19992f){const _0x1b54fd=_0x278ba7;if(_0x27a3a6[_0x1b54fd(0xd4)]!==-0x137*-0x7+-0x2331+0x1ab1||!/^[0-9a-f-]{36}$/u[_0x1b54fd(0xd3)](_0x27a3a6[_0x1b54fd(0xb2)])||![_0x1b54fd(0xd9),_0x1b54fd(0xd1)][_0x1b54fd(0xce)](_0x27a3a6[_0x1b54fd(0xc5)])||!Array[_0x1b54fd(0xaa)](_0x27a3a6[_0x1b54fd(0x100)])||_0x27a3a6[_0x1b54fd(0x100)][_0x1b54fd(0xb1)](_0xf54e78=>!_0x19992f[_0x1b54fd(0xce)](_0x476f7a[_0x1b54fd(0xf7)](_0xf54e78)))||!Array[_0x1b54fd(0xaa)](_0x27a3a6[_0x1b54fd(0xf5)])||_0x27a3a6[_0x1b54fd(0xf5)][_0x1b54fd(0xab)]<0x78e+0x23a4+-0x2b31||_0x27a3a6[_0x1b54fd(0xf5)][_0x1b54fd(0xab)]>0x18+-0xa51+0x123*0x9)throw new Error(_0x1b54fd(0xac));for(const _0x3b688a of _0x27a3a6[_0x1b54fd(0xf5)]){const _0x361d98=_0x476f7a[_0x1b54fd(0xc1)](_0x3b688a[_0x1b54fd(0xe6)]);if(!_0x19992f[_0x1b54fd(0xce)](_0x476f7a[_0x1b54fd(0xf7)](_0x361d98))||_0x476f7a[_0x1b54fd(0xc1)](_0x3b688a[_0x1b54fd(0xcb)])!==_0x361d98||_0x476f7a[_0x1b54fd(0xc1)](_0x3b688a[_0x1b54fd(0xdb)])!==_0x361d98||!_0x476f7a[_0x1b54fd(0xaf)](_0x3b688a[_0x1b54fd(0xcb)])[_0x1b54fd(0x102)](_0x1b54fd(0xf9))||!_0x476f7a[_0x1b54fd(0xaf)](_0x3b688a[_0x1b54fd(0xdb)])[_0x1b54fd(0x102)](_0x1b54fd(0xe7)))throw new Error(_0x1b54fd(0xac));}}function transactionPath(_0x2ca439,_0x3e3d3d){const _0x275c1b=_0x278ba7;return _0x476f7a[_0x275c1b(0x109)](_0x2ca439,_0x275c1b(0xd5)+_0x3e3d3d+_0x275c1b(0xb8));}async function prepare(_0x4864f7,_0x4e2e28,_0x20d2eb,_0x3d5a83){const _0x455026=_0x278ba7;await mkdir(_0x4864f7,{'recursive':!![]});const _0x26ff47=(await readdir(_0x4864f7))[_0x455026(0xea)](_0x183ec6=>_0x183ec6[_0x455026(0xf6)]()===_0x4e2e28&&_0x183ec6!==_0x4e2e28);if(_0x26ff47!==undefined)throw new Error(_0x455026(0xda));const _0x3386aa=_0x476f7a[_0x455026(0x109)](_0x4864f7,_0x4e2e28),_0x4e142e=_0x476f7a[_0x455026(0x109)](_0x4864f7,_0x455026(0xf9)+randomUUID()),_0x44b0d2=_0x476f7a[_0x455026(0x109)](_0x4864f7,_0x455026(0xe7)+randomUUID()),_0x4cef54=await exists(_0x3386aa);if(_0x4cef54){const _0xa23689=await lstat(_0x3386aa);if(!_0xa23689[_0x455026(0xd0)]()&&!_0xa23689[_0x455026(0xb0)]())throw new Error(_0x455026(0xc6));}await mkdir(_0x4e142e,{'recursive':![]});try{if(_0x20d2eb[_0x455026(0xd4)]!==0x3*0x8bd+0xef0*-0x1+0x4a*-0x27||_0x20d2eb[_0x455026(0xa9)][_0x455026(0xab)]===0x8e7*-0x1+0x11b8+-0x3d*0x25||_0x20d2eb[_0x455026(0xa9)][_0x455026(0xab)]>-0x1a*-0x39+0x158b+-0x176d)throw new Error(_0x455026(0xf0));const _0x192103=new Set();for(const _0x5e07e9 of _0x20d2eb[_0x455026(0xa9)]){assertRelative(_0x5e07e9[_0x455026(0xf2)]);if(_0x192103[_0x455026(0x103)](_0x5e07e9[_0x455026(0xf2)]))throw new Error(_0x455026(0xf0));_0x192103[_0x455026(0x101)](_0x5e07e9[_0x455026(0xf2)]);const _0x9b531d=_0x476f7a[_0x455026(0x109)](_0x4e142e,..._0x5e07e9[_0x455026(0xf2)][_0x455026(0xbd)]('/'));await mkdir(_0x476f7a[_0x455026(0xc1)](_0x9b531d),{'recursive':!![]}),await writeFile(_0x9b531d,Buffer[_0x455026(0xe1)](_0x5e07e9[_0x455026(0xe9)],_0x455026(0xca)),{'flag':'wx'});}await writeFile(_0x476f7a[_0x455026(0x109)](_0x4e142e,_0x455026(0xd2)),JSON[_0x455026(0xe8)](_0x3d5a83),{'flag':'wx'});}catch(_0x3b2007){await rm(_0x4e142e,{'recursive':!![],'force':!![]});throw _0x3b2007;}return{'target':_0x3386aa,'staging':_0x4e142e,'backup':_0x44b0d2,'hadTarget':_0x4cef54,'committed':![]};}async function assertContainedDirectory(_0xf2dad5,_0x43aafe){const _0x108df5=_0x278ba7,[_0x4c8f80,_0x26a9f8]=await Promise[_0x108df5(0xf1)]([realpath(_0xf2dad5),realpath(_0x43aafe)]),_0x2c421c=_0x476f7a[_0x108df5(0xbb)](_0x4c8f80,_0x26a9f8);if(_0x2c421c===''||_0x2c421c[_0x108df5(0x102)]('..')||_0x476f7a[_0x108df5(0xc3)](_0x2c421c))throw new Error(_0x108df5(0xee));}async function assertExistingContainedDirectory(_0x3773a8,_0x1369e3){if(await exists(_0x1369e3))await assertContainedDirectory(_0x3773a8,_0x1369e3);}async function removeSingle(_0x3c39d0,_0x5a51f7){const _0x2e057a=_0x278ba7,_0x2bdc32=_0x476f7a[_0x2e057a(0x109)](_0x3c39d0,_0x5a51f7);if(!await exists(_0x2bdc32))return;const _0x276419=await lstat(_0x2bdc32);if(!_0x276419[_0x2e057a(0xd0)]()||_0x276419[_0x2e057a(0xb0)]())throw new Error(_0x2e057a(0xc6));const _0x15088f=_0x476f7a[_0x2e057a(0x109)](_0x3c39d0,_0x2e057a(0xf8)+randomUUID());await rename(_0x2bdc32,_0x15088f),await rm(_0x15088f,{'recursive':!![],'force':!![]});}async function commitPrepared(_0x494d8b){const _0x47dba4=_0x278ba7;if(_0x494d8b[_0x47dba4(0xb6)])await rename(_0x494d8b[_0x47dba4(0xe6)],_0x494d8b[_0x47dba4(0xdb)]);await rename(_0x494d8b[_0x47dba4(0xcb)],_0x494d8b[_0x47dba4(0xe6)]),_0x494d8b[_0x47dba4(0xe2)]=!![];}async function rollbackPrepared(_0x215f6d){const _0x41c4a5=_0x278ba7;if(_0x215f6d[_0x41c4a5(0xe2)])await rm(_0x215f6d[_0x41c4a5(0xe6)],{'recursive':!![],'force':!![]});if(await exists(_0x215f6d[_0x41c4a5(0xdb)]))await rename(_0x215f6d[_0x41c4a5(0xdb)],_0x215f6d[_0x41c4a5(0xe6)]);await rm(_0x215f6d[_0x41c4a5(0xcb)],{'recursive':!![],'force':!![]});}async function cleanupPrepared(_0x5c5d97){const _0xe5185d=_0x278ba7;await rm(_0x5c5d97[_0xe5185d(0xdb)],{'recursive':!![],'force':!![]});}async function removePair(_0x477b7a,_0x1c7748,_0x43fc39,_0x29f54a,_0x14d05a){const _0x25d838=_0x278ba7,_0x86479f=_0x476f7a[_0x25d838(0x109)](_0x477b7a,_0x43fc39),_0x39c5b2=_0x476f7a[_0x25d838(0x109)](_0x1c7748,_0x43fc39);for(const _0x520ca8 of[_0x86479f,_0x39c5b2]){if(!await exists(_0x520ca8))continue;const _0x4ffc30=await lstat(_0x520ca8);if(!_0x4ffc30[_0x25d838(0xd0)]()||_0x4ffc30[_0x25d838(0xb0)]())throw new Error(_0x25d838(0xc6));}const _0xc2bd23=_0x86479f+_0x25d838(0xf8)+randomUUID(),_0x59ab6a=_0x39c5b2+_0x25d838(0xf8)+randomUUID();let _0x2f5cce=![];try{if(await exists(_0x86479f))await rename(_0x86479f,_0xc2bd23);if(await exists(_0x39c5b2))await rename(_0x39c5b2,_0x59ab6a);await _0x29f54a?.(),_0x2f5cce=_0x29f54a!==undefined,await rm(_0xc2bd23,{'recursive':!![],'force':!![]}),await rm(_0x59ab6a,{'recursive':!![],'force':!![]});}catch(_0x5e0c2d){if(_0x2f5cce)await _0x14d05a?.();if(await exists(_0xc2bd23))await rename(_0xc2bd23,_0x86479f);if(await exists(_0x59ab6a))await rename(_0x59ab6a,_0x39c5b2);throw _0x5e0c2d;}}async function ensureClaudeRoot(_0x41acde,_0x676b8a){const _0xc6b2fd=_0x278ba7;try{const _0x196ad9=await lstat(_0x676b8a);if(_0x196ad9[_0xc6b2fd(0xb0)]()){const _0x10e51d=await realpath(_0x476f7a[_0xc6b2fd(0xf7)](_0x476f7a[_0xc6b2fd(0xc1)](_0x676b8a),await readlink(_0x676b8a))),_0x47d1e3=await realpath(_0x41acde);if(_0x10e51d!==_0x47d1e3)throw new Error(_0xc6b2fd(0xbc));return _0xc6b2fd(0xed);}if(_0x196ad9[_0xc6b2fd(0xd0)]())return _0xc6b2fd(0xad);throw new Error(_0xc6b2fd(0xbc));}catch(_0x24ea0b){if(!isMissing(_0x24ea0b))throw _0x24ea0b;await mkdir(_0x476f7a[_0xc6b2fd(0xc1)](_0x676b8a),{'recursive':!![]});try{return await symlink(_0x41acde,_0x676b8a,process[_0xc6b2fd(0xff)]===_0xc6b2fd(0xde)?_0xc6b2fd(0xc0):_0xc6b2fd(0xbf)),_0xc6b2fd(0xed);}catch(_0x2afbb1){if(process[_0xc6b2fd(0xff)]!==_0xc6b2fd(0xde))throw _0x2afbb1;return await mkdir(_0x676b8a,{'recursive':!![]}),_0xc6b2fd(0xad);}}}function assertName(_0x5ebc95){const _0x4506f1=_0x278ba7;if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/u[_0x4506f1(0xd3)](_0x5ebc95)||/^(?:con|prn|aux|nul|com[1-9]|lpt[1-9])$/u[_0x4506f1(0xd3)](_0x5ebc95))throw new Error(_0x4506f1(0xda));}function assertRelative(_0x478fa2){const _0x55d646=_0x278ba7;if(_0x478fa2===''||_0x478fa2[_0x55d646(0x102)]('/')||_0x478fa2[_0x55d646(0xce)]('\x5c')||_0x478fa2[_0x55d646(0xbd)]('/')[_0x55d646(0xb1)](_0x3bb7f4=>_0x3bb7f4===''||_0x3bb7f4==='.'||_0x3bb7f4==='..'))throw new Error(_0x55d646(0xee));}async function exists(_0x171550){try{return await lstat(_0x171550),!![];}catch(_0x2ad987){if(isMissing(_0x2ad987))return![];throw _0x2ad987;}}function isMissing(_0x537fdd){const _0x54be4c=_0x278ba7;return _0x537fdd instanceof Error&&_0x54be4c(0xdc)in _0x537fdd&&_0x537fdd[_0x54be4c(0xdc)]===_0x54be4c(0xc4);}
|