@senior-skills/core 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/application/agent-selection.d.ts +42 -0
- package/dist/application/agent-selection.d.ts.map +1 -0
- package/dist/application/agent-selection.js +143 -0
- package/dist/application/agent-selection.js.map +1 -0
- package/dist/application/apply-skill-updates.d.ts +10 -0
- package/dist/application/apply-skill-updates.d.ts.map +1 -0
- package/dist/application/apply-skill-updates.js +75 -0
- package/dist/application/apply-skill-updates.js.map +1 -0
- package/dist/application/check-updates.d.ts +40 -0
- package/dist/application/check-updates.d.ts.map +1 -0
- package/dist/application/check-updates.js +130 -0
- package/dist/application/check-updates.js.map +1 -0
- package/dist/application/context.d.ts +28 -0
- package/dist/application/context.d.ts.map +1 -0
- package/dist/application/context.js +2 -0
- package/dist/application/context.js.map +1 -0
- package/dist/application/create-skill.d.ts +33 -0
- package/dist/application/create-skill.d.ts.map +1 -0
- package/dist/application/create-skill.js +58 -0
- package/dist/application/create-skill.js.map +1 -0
- package/dist/application/diagnose.d.ts +44 -0
- package/dist/application/diagnose.d.ts.map +1 -0
- package/dist/application/diagnose.js +228 -0
- package/dist/application/diagnose.js.map +1 -0
- package/dist/application/install-skills.d.ts +59 -0
- package/dist/application/install-skills.d.ts.map +1 -0
- package/dist/application/install-skills.js +191 -0
- package/dist/application/install-skills.js.map +1 -0
- package/dist/application/list-installed.d.ts +39 -0
- package/dist/application/list-installed.d.ts.map +1 -0
- package/dist/application/list-installed.js +68 -0
- package/dist/application/list-installed.js.map +1 -0
- package/dist/application/package-loader.d.ts +42 -0
- package/dist/application/package-loader.d.ts.map +1 -0
- package/dist/application/package-loader.js +320 -0
- package/dist/application/package-loader.js.map +1 -0
- package/dist/application/publish-skill.d.ts +41 -0
- package/dist/application/publish-skill.d.ts.map +1 -0
- package/dist/application/publish-skill.js +112 -0
- package/dist/application/publish-skill.js.map +1 -0
- package/dist/application/remove-skills.d.ts +34 -0
- package/dist/application/remove-skills.d.ts.map +1 -0
- package/dist/application/remove-skills.js +95 -0
- package/dist/application/remove-skills.js.map +1 -0
- package/dist/application/resolution-source.d.ts +25 -0
- package/dist/application/resolution-source.d.ts.map +1 -0
- package/dist/application/resolution-source.js +60 -0
- package/dist/application/resolution-source.js.map +1 -0
- package/dist/application/resolve-suggestions.d.ts +17 -0
- package/dist/application/resolve-suggestions.d.ts.map +1 -0
- package/dist/application/resolve-suggestions.js +77 -0
- package/dist/application/resolve-suggestions.js.map +1 -0
- package/dist/application/search-skills.d.ts +36 -0
- package/dist/application/search-skills.d.ts.map +1 -0
- package/dist/application/search-skills.js +78 -0
- package/dist/application/search-skills.js.map +1 -0
- package/dist/application/update-skills.d.ts +55 -0
- package/dist/application/update-skills.d.ts.map +1 -0
- package/dist/application/update-skills.js +115 -0
- package/dist/application/update-skills.js.map +1 -0
- package/dist/application/validate-package.d.ts +27 -0
- package/dist/application/validate-package.d.ts.map +1 -0
- package/dist/application/validate-package.js +165 -0
- package/dist/application/validate-package.js.map +1 -0
- package/dist/application/workspace.d.ts +22 -0
- package/dist/application/workspace.d.ts.map +1 -0
- package/dist/application/workspace.js +66 -0
- package/dist/application/workspace.js.map +1 -0
- package/dist/domain/agent.d.ts +89 -0
- package/dist/domain/agent.d.ts.map +1 -0
- package/dist/domain/agent.js +20 -0
- package/dist/domain/agent.js.map +1 -0
- package/dist/domain/errors.d.ts +91 -0
- package/dist/domain/errors.d.ts.map +1 -0
- package/dist/domain/errors.js +121 -0
- package/dist/domain/errors.js.map +1 -0
- package/dist/domain/integrity.d.ts +19 -0
- package/dist/domain/integrity.d.ts.map +1 -0
- package/dist/domain/integrity.js +0 -0
- package/dist/domain/integrity.js.map +1 -0
- package/dist/domain/js-literal.d.ts +22 -0
- package/dist/domain/js-literal.d.ts.map +1 -0
- package/dist/domain/js-literal.js +221 -0
- package/dist/domain/js-literal.js.map +1 -0
- package/dist/domain/lockfile.d.ts +36 -0
- package/dist/domain/lockfile.d.ts.map +1 -0
- package/dist/domain/lockfile.js +148 -0
- package/dist/domain/lockfile.js.map +1 -0
- package/dist/domain/manifest.d.ts +96 -0
- package/dist/domain/manifest.d.ts.map +1 -0
- package/dist/domain/manifest.js +448 -0
- package/dist/domain/manifest.js.map +1 -0
- package/dist/domain/path-safety.d.ts +19 -0
- package/dist/domain/path-safety.d.ts.map +1 -0
- package/dist/domain/path-safety.js +125 -0
- package/dist/domain/path-safety.js.map +1 -0
- package/dist/domain/posix-path.d.ts +28 -0
- package/dist/domain/posix-path.d.ts.map +1 -0
- package/dist/domain/posix-path.js +84 -0
- package/dist/domain/posix-path.js.map +1 -0
- package/dist/domain/receipt.d.ts +41 -0
- package/dist/domain/receipt.d.ts.map +1 -0
- package/dist/domain/receipt.js +93 -0
- package/dist/domain/receipt.js.map +1 -0
- package/dist/domain/registry-index.d.ts +41 -0
- package/dist/domain/registry-index.d.ts.map +1 -0
- package/dist/domain/registry-index.js +150 -0
- package/dist/domain/registry-index.js.map +1 -0
- package/dist/domain/resolver.d.ts +54 -0
- package/dist/domain/resolver.d.ts.map +1 -0
- package/dist/domain/resolver.js +238 -0
- package/dist/domain/resolver.js.map +1 -0
- package/dist/domain/skill-document.d.ts +16 -0
- package/dist/domain/skill-document.d.ts.map +1 -0
- package/dist/domain/skill-document.js +60 -0
- package/dist/domain/skill-document.js.map +1 -0
- package/dist/domain/skill-package.d.ts +43 -0
- package/dist/domain/skill-package.d.ts.map +1 -0
- package/dist/domain/skill-package.js +63 -0
- package/dist/domain/skill-package.js.map +1 -0
- package/dist/domain/skill-ref.d.ts +30 -0
- package/dist/domain/skill-ref.d.ts.map +1 -0
- package/dist/domain/skill-ref.js +119 -0
- package/dist/domain/skill-ref.js.map +1 -0
- package/dist/domain/validation.d.ts +30 -0
- package/dist/domain/validation.d.ts.map +1 -0
- package/dist/domain/validation.js +32 -0
- package/dist/domain/validation.js.map +1 -0
- package/dist/domain/version.d.ts +23 -0
- package/dist/domain/version.d.ts.map +1 -0
- package/dist/domain/version.js +81 -0
- package/dist/domain/version.js.map +1 -0
- package/dist/domain/workflow-document.d.ts +23 -0
- package/dist/domain/workflow-document.d.ts.map +1 -0
- package/dist/domain/workflow-document.js +56 -0
- package/dist/domain/workflow-document.js.map +1 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +45 -0
- package/dist/index.js.map +1 -0
- package/dist/ports/agent-adapter.d.ts +65 -0
- package/dist/ports/agent-adapter.d.ts.map +1 -0
- package/dist/ports/agent-adapter.js +28 -0
- package/dist/ports/agent-adapter.js.map +1 -0
- package/dist/ports/config-store.d.ts +27 -0
- package/dist/ports/config-store.d.ts.map +1 -0
- package/dist/ports/config-store.js +2 -0
- package/dist/ports/config-store.js.map +1 -0
- package/dist/ports/infrastructure.d.ts +123 -0
- package/dist/ports/infrastructure.d.ts.map +1 -0
- package/dist/ports/infrastructure.js +9 -0
- package/dist/ports/infrastructure.js.map +1 -0
- package/dist/ports/installation.d.ts +86 -0
- package/dist/ports/installation.d.ts.map +1 -0
- package/dist/ports/installation.js +2 -0
- package/dist/ports/installation.js.map +1 -0
- package/dist/ports/skill-registry.d.ts +74 -0
- package/dist/ports/skill-registry.d.ts.map +1 -0
- package/dist/ports/skill-registry.js +2 -0
- package/dist/ports/skill-registry.js.map +1 -0
- package/dist/ports/updates.d.ts +31 -0
- package/dist/ports/updates.d.ts.map +1 -0
- package/dist/ports/updates.js +4 -0
- package/dist/ports/updates.js.map +1 -0
- package/dist/testing/doubles.d.ts +127 -0
- package/dist/testing/doubles.d.ts.map +1 -0
- package/dist/testing/doubles.js +299 -0
- package/dist/testing/doubles.js.map +1 -0
- package/dist/testing/in-memory-file-system.d.ts +61 -0
- package/dist/testing/in-memory-file-system.d.ts.map +1 -0
- package/dist/testing/in-memory-file-system.js +297 -0
- package/dist/testing/in-memory-file-system.js.map +1 -0
- package/dist/testing/index.d.ts +10 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +10 -0
- package/dist/testing/index.js.map +1 -0
- package/package.json +37 -0
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { INTEGRITY_PREFIX } from "../domain/integrity.js";
|
|
2
|
+
import { MANIFEST_FILENAME, entrypointFor, parseManifest, } from "../domain/manifest.js";
|
|
3
|
+
import { buildSkillPackage, encodeText, } from "../domain/skill-package.js";
|
|
4
|
+
import { AgentSkillsError, ErrorCode } from "../domain/errors.js";
|
|
5
|
+
/** Fixed clock, so anything that records a timestamp is assertable. */
|
|
6
|
+
export class FixedClock {
|
|
7
|
+
current;
|
|
8
|
+
constructor(iso = '2026-01-01T00:00:00.000Z') {
|
|
9
|
+
this.current = new Date(iso);
|
|
10
|
+
}
|
|
11
|
+
now() {
|
|
12
|
+
return this.current;
|
|
13
|
+
}
|
|
14
|
+
advance(milliseconds) {
|
|
15
|
+
this.current = new Date(this.current.getTime() + milliseconds);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export class FakeEnvironment {
|
|
19
|
+
options;
|
|
20
|
+
constructor(options = {}) {
|
|
21
|
+
this.options = {
|
|
22
|
+
homeDir: options.homeDir ?? '/home/dev',
|
|
23
|
+
cwd: options.cwd ?? '/work/project',
|
|
24
|
+
tempDir: options.tempDir ?? '/tmp',
|
|
25
|
+
platform: options.platform ?? 'linux',
|
|
26
|
+
env: { ...(options.env ?? {}) },
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
homeDir() {
|
|
30
|
+
return this.options.homeDir;
|
|
31
|
+
}
|
|
32
|
+
cwd() {
|
|
33
|
+
return this.options.cwd;
|
|
34
|
+
}
|
|
35
|
+
tempDir() {
|
|
36
|
+
return this.options.tempDir;
|
|
37
|
+
}
|
|
38
|
+
platform() {
|
|
39
|
+
return this.options.platform;
|
|
40
|
+
}
|
|
41
|
+
env() {
|
|
42
|
+
return this.options.env;
|
|
43
|
+
}
|
|
44
|
+
setEnv(key, value) {
|
|
45
|
+
this.options.env[key] = value;
|
|
46
|
+
}
|
|
47
|
+
setCwd(cwd) {
|
|
48
|
+
this.options.cwd = cwd;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Deterministic content hash. Not cryptographic — tests need a hash that changes when content
|
|
53
|
+
* changes and is stable across runs, and a real SHA-256 makes expected values unreadable.
|
|
54
|
+
*/
|
|
55
|
+
export class FakeHasher {
|
|
56
|
+
files = new Map();
|
|
57
|
+
hash(data) {
|
|
58
|
+
let value = 2166136261;
|
|
59
|
+
for (const byte of data) {
|
|
60
|
+
value ^= byte;
|
|
61
|
+
value = Math.imul(value, 16777619) >>> 0;
|
|
62
|
+
}
|
|
63
|
+
return `${INTEGRITY_PREFIX}${value.toString(16).padStart(8, '0')}`;
|
|
64
|
+
}
|
|
65
|
+
async hashFile(path) {
|
|
66
|
+
const bytes = this.files.get(path);
|
|
67
|
+
if (bytes === undefined)
|
|
68
|
+
throw new AgentSkillsError(ErrorCode.IO_ERROR, `Unknown file: ${path}`);
|
|
69
|
+
return this.hash(bytes);
|
|
70
|
+
}
|
|
71
|
+
register(path, bytes) {
|
|
72
|
+
this.files.set(path, bytes);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/** Hashes through a filesystem, so `hashFile` works against the in-memory double. */
|
|
76
|
+
export function hasherOver(fs) {
|
|
77
|
+
const base = new FakeHasher();
|
|
78
|
+
return {
|
|
79
|
+
hash: (data) => base.hash(data),
|
|
80
|
+
hashFile: async (path) => base.hash(await fs.readFile(path)),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export class RecordingLogger {
|
|
84
|
+
lines = [];
|
|
85
|
+
debug(message) {
|
|
86
|
+
this.lines.push({ level: 'debug', message });
|
|
87
|
+
}
|
|
88
|
+
info(message) {
|
|
89
|
+
this.lines.push({ level: 'info', message });
|
|
90
|
+
}
|
|
91
|
+
warn(message) {
|
|
92
|
+
this.lines.push({ level: 'warn', message });
|
|
93
|
+
}
|
|
94
|
+
error(message) {
|
|
95
|
+
this.lines.push({ level: 'error', message });
|
|
96
|
+
}
|
|
97
|
+
messages(level) {
|
|
98
|
+
return this.lines
|
|
99
|
+
.filter((line) => level === undefined || line.level === level)
|
|
100
|
+
.map((line) => line.message);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
export class FakeCommandRunner {
|
|
104
|
+
calls = [];
|
|
105
|
+
available;
|
|
106
|
+
results;
|
|
107
|
+
constructor(options = {}) {
|
|
108
|
+
this.available = new Set(options.available ?? []);
|
|
109
|
+
this.results = new Map(Object.entries(options.results ?? {}));
|
|
110
|
+
}
|
|
111
|
+
async run(command, args, _options) {
|
|
112
|
+
this.calls.push({ command, args });
|
|
113
|
+
return this.results.get(`${command} ${args.join(' ')}`) ?? { code: 0, stdout: '', stderr: '' };
|
|
114
|
+
}
|
|
115
|
+
async which(command) {
|
|
116
|
+
return this.available.has(command) ? `/usr/bin/${command}` : undefined;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export class FakeHttpClient {
|
|
120
|
+
requests = [];
|
|
121
|
+
responses;
|
|
122
|
+
constructor(responses = {}) {
|
|
123
|
+
this.responses = new Map(Object.entries(responses).map(([url, response]) => [
|
|
124
|
+
url,
|
|
125
|
+
typeof response === 'string'
|
|
126
|
+
? { status: 200, headers: {}, body: encodeText(response) }
|
|
127
|
+
: response,
|
|
128
|
+
]));
|
|
129
|
+
}
|
|
130
|
+
async get(url, _options) {
|
|
131
|
+
this.requests.push(url);
|
|
132
|
+
return this.responses.get(url) ?? { status: 404, headers: {}, body: new Uint8Array() };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/** Builds a valid in-memory package. Keeps every test from hand-writing YAML. */
|
|
136
|
+
export function buildPackage(options) {
|
|
137
|
+
const kind = options.kind ?? 'skill';
|
|
138
|
+
const entrypoint = entrypointFor(kind);
|
|
139
|
+
const description = options.description ??
|
|
140
|
+
`A test ${kind} named ${options.name}. Use it when testing ${options.name}.`;
|
|
141
|
+
const manifestYaml = [
|
|
142
|
+
'schemaVersion: 1',
|
|
143
|
+
`name: ${options.name}`,
|
|
144
|
+
...(kind === 'skill' ? [] : [`kind: ${kind}`]),
|
|
145
|
+
`version: ${options.version}`,
|
|
146
|
+
`description: ${JSON.stringify(description)}`,
|
|
147
|
+
'license: Apache-2.0',
|
|
148
|
+
...(options.agents === undefined
|
|
149
|
+
? []
|
|
150
|
+
: ['compatibility:', ' agents:', ...options.agents.map((agent) => ` - id: ${agent}`)]),
|
|
151
|
+
'files:',
|
|
152
|
+
` - ${entrypoint}`,
|
|
153
|
+
' - skill.yaml',
|
|
154
|
+
...Object.keys(options.extraFiles ?? {}).map((path) => ` - ${path}`),
|
|
155
|
+
...(options.dependencies === undefined
|
|
156
|
+
? []
|
|
157
|
+
: [
|
|
158
|
+
'dependencies:',
|
|
159
|
+
...Object.entries(options.dependencies).flatMap(([name, range]) => [
|
|
160
|
+
` - name: ${name}`,
|
|
161
|
+
` version: "${range}"`,
|
|
162
|
+
]),
|
|
163
|
+
]),
|
|
164
|
+
...(options.optionalDependencies === undefined
|
|
165
|
+
? []
|
|
166
|
+
: [
|
|
167
|
+
'optionalDependencies:',
|
|
168
|
+
...Object.entries(options.optionalDependencies).flatMap(([name, range]) => [
|
|
169
|
+
` - name: ${name}`,
|
|
170
|
+
` version: "${range}"`,
|
|
171
|
+
]),
|
|
172
|
+
]),
|
|
173
|
+
...(options.manifestExtras === undefined ? [] : [options.manifestExtras]),
|
|
174
|
+
'',
|
|
175
|
+
].join('\n');
|
|
176
|
+
const skillMd = [
|
|
177
|
+
'---',
|
|
178
|
+
`name: ${options.name}`,
|
|
179
|
+
`description: ${JSON.stringify(description)}`,
|
|
180
|
+
'---',
|
|
181
|
+
'',
|
|
182
|
+
options.body ??
|
|
183
|
+
[
|
|
184
|
+
`# ${options.name}`,
|
|
185
|
+
'',
|
|
186
|
+
'This is a test package body long enough to satisfy the minimum-content check.',
|
|
187
|
+
].join('\n'),
|
|
188
|
+
'',
|
|
189
|
+
].join('\n');
|
|
190
|
+
const workflowJs = [
|
|
191
|
+
'export const meta = {',
|
|
192
|
+
` name: ${JSON.stringify(options.name)},`,
|
|
193
|
+
` description: ${JSON.stringify(description)},`,
|
|
194
|
+
...Object.entries(options.meta ?? {}).map(([key, value]) => ` ${key}: ${JSON.stringify(value)},`),
|
|
195
|
+
'};',
|
|
196
|
+
'',
|
|
197
|
+
options.body ??
|
|
198
|
+
[
|
|
199
|
+
"phase('Only');",
|
|
200
|
+
"log('A test workflow body long enough to satisfy the minimum-content check.');",
|
|
201
|
+
].join('\n'),
|
|
202
|
+
'',
|
|
203
|
+
].join('\n');
|
|
204
|
+
const entrypointText = kind === 'workflow' ? workflowJs : skillMd;
|
|
205
|
+
const files = [
|
|
206
|
+
{ path: entrypoint, bytes: encodeText(entrypointText) },
|
|
207
|
+
{ path: MANIFEST_FILENAME, bytes: encodeText(manifestYaml) },
|
|
208
|
+
...Object.entries(options.extraFiles ?? {}).map(([path, content]) => ({
|
|
209
|
+
path,
|
|
210
|
+
bytes: encodeText(content),
|
|
211
|
+
})),
|
|
212
|
+
];
|
|
213
|
+
const { manifest } = parseManifest(manifestYaml, { source: `${options.name}/skill.yaml` });
|
|
214
|
+
return buildSkillPackage(manifest, files);
|
|
215
|
+
}
|
|
216
|
+
/** An in-memory {@link SkillRegistry}, sufficient for every resolver and federation test. */
|
|
217
|
+
export class FakeRegistry {
|
|
218
|
+
name;
|
|
219
|
+
kind;
|
|
220
|
+
trusted;
|
|
221
|
+
fetches = [];
|
|
222
|
+
packages;
|
|
223
|
+
deprecated;
|
|
224
|
+
offline;
|
|
225
|
+
constructor(options) {
|
|
226
|
+
this.name = options.name;
|
|
227
|
+
this.kind = options.kind ?? 'local';
|
|
228
|
+
this.trusted = options.trusted ?? true;
|
|
229
|
+
this.packages = options.packages;
|
|
230
|
+
this.deprecated = new Set(options.deprecated ?? []);
|
|
231
|
+
this.offline = options.offline ?? false;
|
|
232
|
+
}
|
|
233
|
+
async refresh() {
|
|
234
|
+
this.assertOnline();
|
|
235
|
+
}
|
|
236
|
+
async search(query) {
|
|
237
|
+
this.assertOnline();
|
|
238
|
+
const text = query.text.toLowerCase();
|
|
239
|
+
const names = [...new Set(this.packages.map((pkg) => pkg.manifest.name))].sort();
|
|
240
|
+
return names
|
|
241
|
+
.filter((name) => text === '' || name.toLowerCase().includes(text))
|
|
242
|
+
.map((name) => {
|
|
243
|
+
const newest = this.newest(name);
|
|
244
|
+
return {
|
|
245
|
+
name,
|
|
246
|
+
description: newest.manifest.description,
|
|
247
|
+
keywords: newest.manifest.keywords,
|
|
248
|
+
latest: newest.manifest.version,
|
|
249
|
+
registry: this.name,
|
|
250
|
+
};
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
async has(name) {
|
|
254
|
+
this.assertOnline();
|
|
255
|
+
return this.packages.some((pkg) => pkg.manifest.name === name);
|
|
256
|
+
}
|
|
257
|
+
async versions(name) {
|
|
258
|
+
this.assertOnline();
|
|
259
|
+
return this.packages
|
|
260
|
+
.filter((pkg) => pkg.manifest.name === name)
|
|
261
|
+
.map((pkg) => ({
|
|
262
|
+
version: pkg.manifest.version,
|
|
263
|
+
path: `skills/${name}`,
|
|
264
|
+
deprecated: this.deprecated.has(`${name}@${pkg.manifest.version}`),
|
|
265
|
+
}))
|
|
266
|
+
.sort((a, b) => (a.version < b.version ? 1 : -1));
|
|
267
|
+
}
|
|
268
|
+
async manifest(name, version) {
|
|
269
|
+
return this.require(name, version).manifest;
|
|
270
|
+
}
|
|
271
|
+
async fetch(name, version) {
|
|
272
|
+
this.fetches.push(`${name}@${version}`);
|
|
273
|
+
const pkg = this.require(name, version);
|
|
274
|
+
return {
|
|
275
|
+
pkg,
|
|
276
|
+
registry: this.name,
|
|
277
|
+
resolved: `fake://${this.name}/${name}@${version}`,
|
|
278
|
+
integrity: `${INTEGRITY_PREFIX}${name}-${version}`,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
newest(name) {
|
|
282
|
+
return this.packages
|
|
283
|
+
.filter((pkg) => pkg.manifest.name === name)
|
|
284
|
+
.sort((a, b) => (a.manifest.version < b.manifest.version ? 1 : -1))[0];
|
|
285
|
+
}
|
|
286
|
+
require(name, version) {
|
|
287
|
+
const found = this.packages.find((pkg) => pkg.manifest.name === name && pkg.manifest.version === version);
|
|
288
|
+
if (found === undefined) {
|
|
289
|
+
throw new AgentSkillsError(ErrorCode.VERSION_NOT_FOUND, `${name}@${version} not in ${this.name}`);
|
|
290
|
+
}
|
|
291
|
+
return found;
|
|
292
|
+
}
|
|
293
|
+
assertOnline() {
|
|
294
|
+
if (this.offline) {
|
|
295
|
+
throw new AgentSkillsError(ErrorCode.REGISTRY_UNAVAILABLE, `Registry "${this.name}" is offline`);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
//# sourceMappingURL=doubles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doubles.js","sourceRoot":"","sources":["../../src/testing/doubles.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { DirEntry, FileStat, FileSystem } from '../ports/infrastructure.ts';
|
|
2
|
+
export interface InMemoryFileSystemOptions {
|
|
3
|
+
/** `/` by default; set to `\\` to reproduce Windows path handling in a test. */
|
|
4
|
+
readonly separator?: string;
|
|
5
|
+
/** Root the filesystem is anchored at, e.g. `/` or `C:\\`. */
|
|
6
|
+
readonly root?: string;
|
|
7
|
+
/** Paths under which writes fail with a permission error. */
|
|
8
|
+
readonly readOnlyPaths?: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A complete in-memory {@link FileSystem}.
|
|
12
|
+
*
|
|
13
|
+
* Exported from the package (rather than living in a test folder) so adapter authors outside
|
|
14
|
+
* this repository can test their own adapters against the same double the built-in ones use.
|
|
15
|
+
*
|
|
16
|
+
* It models the things that actually cause cross-platform bugs: separator handling, symlinks,
|
|
17
|
+
* and non-writable directories.
|
|
18
|
+
*/
|
|
19
|
+
export declare class InMemoryFileSystem implements FileSystem {
|
|
20
|
+
readonly separator: string;
|
|
21
|
+
private readonly nodes;
|
|
22
|
+
private readonly root;
|
|
23
|
+
private readonly readOnlyPaths;
|
|
24
|
+
private tempCounter;
|
|
25
|
+
private clock;
|
|
26
|
+
constructor(options?: InMemoryFileSystemOptions);
|
|
27
|
+
/** Seeds files in one call: `{ '/a/b.txt': 'hello' }`. Parent directories are created. */
|
|
28
|
+
seed(files: Readonly<Record<string, string | Uint8Array>>): this;
|
|
29
|
+
symlink(from: string, to: string): this;
|
|
30
|
+
/** Every path currently present, sorted. Useful for asserting on a whole tree at once. */
|
|
31
|
+
snapshot(): readonly string[];
|
|
32
|
+
textAt(path: string): string | undefined;
|
|
33
|
+
readFile(path: string): Promise<Uint8Array>;
|
|
34
|
+
readTextFile(path: string): Promise<string>;
|
|
35
|
+
writeFile(path: string, data: Uint8Array | string): Promise<void>;
|
|
36
|
+
exists(path: string): Promise<boolean>;
|
|
37
|
+
lstat(path: string): Promise<FileStat>;
|
|
38
|
+
stat(path: string): Promise<FileStat>;
|
|
39
|
+
readDir(path: string): Promise<readonly DirEntry[]>;
|
|
40
|
+
mkdirp(path: string): Promise<void>;
|
|
41
|
+
remove(path: string): Promise<void>;
|
|
42
|
+
rename(from: string, to: string): Promise<void>;
|
|
43
|
+
copyFile(from: string, to: string): Promise<void>;
|
|
44
|
+
realpath(path: string): Promise<string>;
|
|
45
|
+
readlink(path: string): Promise<string>;
|
|
46
|
+
makeTempDir(parent: string, prefix: string): Promise<string>;
|
|
47
|
+
isWritable(path: string): Promise<boolean>;
|
|
48
|
+
join(...parts: readonly string[]): string;
|
|
49
|
+
resolve(...parts: readonly string[]): string;
|
|
50
|
+
dirname(path: string): string;
|
|
51
|
+
basename(path: string): string;
|
|
52
|
+
relative(from: string, to: string): string;
|
|
53
|
+
isAbsolute(path: string): boolean;
|
|
54
|
+
private normalize;
|
|
55
|
+
private parts;
|
|
56
|
+
private key;
|
|
57
|
+
private require;
|
|
58
|
+
private assertWritable;
|
|
59
|
+
private mkdirpSync;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=in-memory-file-system.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-memory-file-system.d.ts","sourceRoot":"","sources":["../../src/testing/in-memory-file-system.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
import { AgentSkillsError, ErrorCode } from "../domain/errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* A complete in-memory {@link FileSystem}.
|
|
4
|
+
*
|
|
5
|
+
* Exported from the package (rather than living in a test folder) so adapter authors outside
|
|
6
|
+
* this repository can test their own adapters against the same double the built-in ones use.
|
|
7
|
+
*
|
|
8
|
+
* It models the things that actually cause cross-platform bugs: separator handling, symlinks,
|
|
9
|
+
* and non-writable directories.
|
|
10
|
+
*/
|
|
11
|
+
export class InMemoryFileSystem {
|
|
12
|
+
separator;
|
|
13
|
+
nodes = new Map();
|
|
14
|
+
root;
|
|
15
|
+
readOnlyPaths;
|
|
16
|
+
tempCounter = 0;
|
|
17
|
+
clock = 1_000_000;
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
this.separator = options.separator ?? '/';
|
|
20
|
+
this.root = options.root ?? (this.separator === '\\' ? 'C:\\' : '/');
|
|
21
|
+
this.readOnlyPaths = options.readOnlyPaths ?? [];
|
|
22
|
+
this.nodes.set(this.key(this.root), { kind: 'dir', mtimeMs: this.clock, mode: 0o755 });
|
|
23
|
+
}
|
|
24
|
+
// --- Test helpers ---------------------------------------------------------------------
|
|
25
|
+
/** Seeds files in one call: `{ '/a/b.txt': 'hello' }`. Parent directories are created. */
|
|
26
|
+
seed(files) {
|
|
27
|
+
for (const [path, content] of Object.entries(files)) {
|
|
28
|
+
const absolute = this.resolve(path);
|
|
29
|
+
this.mkdirpSync(this.dirname(absolute));
|
|
30
|
+
this.nodes.set(this.key(absolute), {
|
|
31
|
+
kind: 'file',
|
|
32
|
+
bytes: typeof content === 'string' ? new TextEncoder().encode(content) : content,
|
|
33
|
+
mtimeMs: (this.clock += 1),
|
|
34
|
+
mode: 0o644,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
symlink(from, to) {
|
|
40
|
+
const absolute = this.resolve(from);
|
|
41
|
+
this.mkdirpSync(this.dirname(absolute));
|
|
42
|
+
this.nodes.set(this.key(absolute), {
|
|
43
|
+
kind: 'link',
|
|
44
|
+
target: this.resolve(to),
|
|
45
|
+
mtimeMs: (this.clock += 1),
|
|
46
|
+
mode: 0o777,
|
|
47
|
+
});
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
/** Every path currently present, sorted. Useful for asserting on a whole tree at once. */
|
|
51
|
+
snapshot() {
|
|
52
|
+
return [...this.nodes.keys()].sort();
|
|
53
|
+
}
|
|
54
|
+
textAt(path) {
|
|
55
|
+
const node = this.nodes.get(this.key(this.resolve(path)));
|
|
56
|
+
return node?.bytes === undefined ? undefined : new TextDecoder().decode(node.bytes);
|
|
57
|
+
}
|
|
58
|
+
// --- FileSystem -----------------------------------------------------------------------
|
|
59
|
+
async readFile(path) {
|
|
60
|
+
const node = this.require(path);
|
|
61
|
+
if (node.kind !== 'file' || node.bytes === undefined) {
|
|
62
|
+
throw new AgentSkillsError(ErrorCode.IO_ERROR, `Not a file: ${path}`);
|
|
63
|
+
}
|
|
64
|
+
return node.bytes;
|
|
65
|
+
}
|
|
66
|
+
async readTextFile(path) {
|
|
67
|
+
return new TextDecoder().decode(await this.readFile(path));
|
|
68
|
+
}
|
|
69
|
+
async writeFile(path, data) {
|
|
70
|
+
const absolute = this.resolve(path);
|
|
71
|
+
this.assertWritable(absolute);
|
|
72
|
+
this.mkdirpSync(this.dirname(absolute));
|
|
73
|
+
this.nodes.set(this.key(absolute), {
|
|
74
|
+
kind: 'file',
|
|
75
|
+
bytes: typeof data === 'string' ? new TextEncoder().encode(data) : data,
|
|
76
|
+
mtimeMs: (this.clock += 1),
|
|
77
|
+
mode: 0o644,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
async exists(path) {
|
|
81
|
+
return this.nodes.has(this.key(this.resolve(path)));
|
|
82
|
+
}
|
|
83
|
+
async lstat(path) {
|
|
84
|
+
const node = this.require(path);
|
|
85
|
+
return {
|
|
86
|
+
isFile: node.kind === 'file',
|
|
87
|
+
isDirectory: node.kind === 'dir',
|
|
88
|
+
isSymbolicLink: node.kind === 'link',
|
|
89
|
+
size: node.bytes?.byteLength ?? 0,
|
|
90
|
+
mtimeMs: node.mtimeMs,
|
|
91
|
+
mode: node.mode,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
async stat(path) {
|
|
95
|
+
return this.lstat(await this.realpath(path));
|
|
96
|
+
}
|
|
97
|
+
async readDir(path) {
|
|
98
|
+
const absolute = this.resolve(path);
|
|
99
|
+
const prefix = this.key(absolute) + this.separator;
|
|
100
|
+
const names = new Set();
|
|
101
|
+
for (const key of this.nodes.keys()) {
|
|
102
|
+
if (!key.startsWith(prefix))
|
|
103
|
+
continue;
|
|
104
|
+
const rest = key.slice(prefix.length);
|
|
105
|
+
const name = rest.split(this.separator)[0];
|
|
106
|
+
if (name !== undefined && name !== '')
|
|
107
|
+
names.add(name);
|
|
108
|
+
}
|
|
109
|
+
return [...names].sort().map((name) => {
|
|
110
|
+
const node = this.nodes.get(this.key(this.join(absolute, name)));
|
|
111
|
+
return {
|
|
112
|
+
name,
|
|
113
|
+
isFile: node?.kind === 'file',
|
|
114
|
+
isDirectory: node?.kind === 'dir',
|
|
115
|
+
isSymbolicLink: node?.kind === 'link',
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
async mkdirp(path) {
|
|
120
|
+
const absolute = this.resolve(path);
|
|
121
|
+
this.assertWritable(absolute);
|
|
122
|
+
this.mkdirpSync(absolute);
|
|
123
|
+
}
|
|
124
|
+
async remove(path) {
|
|
125
|
+
const absolute = this.resolve(path);
|
|
126
|
+
this.assertWritable(absolute);
|
|
127
|
+
const key = this.key(absolute);
|
|
128
|
+
const prefix = key + this.separator;
|
|
129
|
+
for (const candidate of [...this.nodes.keys()]) {
|
|
130
|
+
if (candidate === key || candidate.startsWith(prefix))
|
|
131
|
+
this.nodes.delete(candidate);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async rename(from, to) {
|
|
135
|
+
const source = this.resolve(from);
|
|
136
|
+
const destination = this.resolve(to);
|
|
137
|
+
this.assertWritable(destination);
|
|
138
|
+
if (!this.nodes.has(this.key(source))) {
|
|
139
|
+
throw new AgentSkillsError(ErrorCode.IO_ERROR, `No such file or directory: ${from}`);
|
|
140
|
+
}
|
|
141
|
+
if (this.nodes.has(this.key(destination))) {
|
|
142
|
+
throw new AgentSkillsError(ErrorCode.IO_ERROR, `Destination exists: ${to}`);
|
|
143
|
+
}
|
|
144
|
+
this.mkdirpSync(this.dirname(destination));
|
|
145
|
+
const sourceKey = this.key(source);
|
|
146
|
+
const prefix = sourceKey + this.separator;
|
|
147
|
+
for (const [key, node] of [...this.nodes.entries()]) {
|
|
148
|
+
if (key !== sourceKey && !key.startsWith(prefix))
|
|
149
|
+
continue;
|
|
150
|
+
const suffix = key.slice(sourceKey.length);
|
|
151
|
+
this.nodes.delete(key);
|
|
152
|
+
this.nodes.set(this.key(destination) + suffix, node);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
async copyFile(from, to) {
|
|
156
|
+
await this.writeFile(to, await this.readFile(from));
|
|
157
|
+
}
|
|
158
|
+
async realpath(path) {
|
|
159
|
+
let current = this.resolve(path);
|
|
160
|
+
for (let hops = 0; hops < 16; hops += 1) {
|
|
161
|
+
const node = this.nodes.get(this.key(current));
|
|
162
|
+
if (node?.kind !== 'link' || node.target === undefined)
|
|
163
|
+
return current;
|
|
164
|
+
current = this.resolve(node.target);
|
|
165
|
+
}
|
|
166
|
+
throw new AgentSkillsError(ErrorCode.IO_ERROR, `Too many symbolic links: ${path}`);
|
|
167
|
+
}
|
|
168
|
+
async readlink(path) {
|
|
169
|
+
const node = this.require(path);
|
|
170
|
+
if (node.kind !== 'link' || node.target === undefined) {
|
|
171
|
+
throw new AgentSkillsError(ErrorCode.IO_ERROR, `Not a symlink: ${path}`);
|
|
172
|
+
}
|
|
173
|
+
return node.target;
|
|
174
|
+
}
|
|
175
|
+
async makeTempDir(parent, prefix) {
|
|
176
|
+
this.tempCounter += 1;
|
|
177
|
+
const path = this.join(this.resolve(parent), `${prefix}${this.tempCounter}`);
|
|
178
|
+
await this.mkdirp(path);
|
|
179
|
+
return path;
|
|
180
|
+
}
|
|
181
|
+
async isWritable(path) {
|
|
182
|
+
return !this.readOnlyPaths.some((readOnly) => this.resolve(path).startsWith(this.resolve(readOnly)));
|
|
183
|
+
}
|
|
184
|
+
join(...parts) {
|
|
185
|
+
const filtered = parts.filter((part) => part !== '');
|
|
186
|
+
if (filtered.length === 0)
|
|
187
|
+
return '.';
|
|
188
|
+
const joined = filtered.join(this.separator);
|
|
189
|
+
return this.normalize(joined);
|
|
190
|
+
}
|
|
191
|
+
resolve(...parts) {
|
|
192
|
+
let current = this.root;
|
|
193
|
+
for (const part of parts) {
|
|
194
|
+
if (part === '')
|
|
195
|
+
continue;
|
|
196
|
+
current = this.isAbsolute(part) ? part : `${current}${this.separator}${part}`;
|
|
197
|
+
}
|
|
198
|
+
return this.normalize(current);
|
|
199
|
+
}
|
|
200
|
+
dirname(path) {
|
|
201
|
+
const normalized = this.normalize(path);
|
|
202
|
+
const index = normalized.lastIndexOf(this.separator);
|
|
203
|
+
if (index <= 0)
|
|
204
|
+
return this.root;
|
|
205
|
+
const parent = normalized.slice(0, index);
|
|
206
|
+
return parent === '' || (this.separator === '\\' && /^[a-zA-Z]:$/.test(parent))
|
|
207
|
+
? this.root
|
|
208
|
+
: parent;
|
|
209
|
+
}
|
|
210
|
+
basename(path) {
|
|
211
|
+
const normalized = this.normalize(path);
|
|
212
|
+
const index = normalized.lastIndexOf(this.separator);
|
|
213
|
+
return index === -1 ? normalized : normalized.slice(index + 1);
|
|
214
|
+
}
|
|
215
|
+
relative(from, to) {
|
|
216
|
+
const fromParts = this.parts(this.resolve(from));
|
|
217
|
+
const toParts = this.parts(this.resolve(to));
|
|
218
|
+
let shared = 0;
|
|
219
|
+
while (shared < fromParts.length &&
|
|
220
|
+
shared < toParts.length &&
|
|
221
|
+
fromParts[shared] === toParts[shared]) {
|
|
222
|
+
shared += 1;
|
|
223
|
+
}
|
|
224
|
+
return [...Array(fromParts.length - shared).fill('..'), ...toParts.slice(shared)].join(this.separator);
|
|
225
|
+
}
|
|
226
|
+
isAbsolute(path) {
|
|
227
|
+
return this.separator === '\\' ? /^[a-zA-Z]:[\\/]/.test(path) : path.startsWith('/');
|
|
228
|
+
}
|
|
229
|
+
// --- Internals ------------------------------------------------------------------------
|
|
230
|
+
normalize(path) {
|
|
231
|
+
const unified = path.replace(/[\\/]+/g, this.separator === '\\' ? '\\' : '/');
|
|
232
|
+
const absolute = this.isAbsolute(unified);
|
|
233
|
+
const prefix = absolute ? (this.separator === '\\' ? `${unified.slice(0, 2)}\\` : '/') : '';
|
|
234
|
+
const body = absolute ? unified.slice(prefix.length) : unified;
|
|
235
|
+
const segments = [];
|
|
236
|
+
for (const segment of body.split(this.separator)) {
|
|
237
|
+
if (segment === '' || segment === '.')
|
|
238
|
+
continue;
|
|
239
|
+
if (segment === '..') {
|
|
240
|
+
if (segments.length > 0)
|
|
241
|
+
segments.pop();
|
|
242
|
+
else if (!absolute)
|
|
243
|
+
segments.push('..');
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
segments.push(segment);
|
|
247
|
+
}
|
|
248
|
+
const joined = segments.join(this.separator);
|
|
249
|
+
if (absolute)
|
|
250
|
+
return joined === '' ? prefix : prefix + joined;
|
|
251
|
+
return joined === '' ? '.' : joined;
|
|
252
|
+
}
|
|
253
|
+
parts(path) {
|
|
254
|
+
return this.normalize(path)
|
|
255
|
+
.split(this.separator)
|
|
256
|
+
.filter((part) => part !== '' && !/^[a-zA-Z]:$/.test(part));
|
|
257
|
+
}
|
|
258
|
+
key(path) {
|
|
259
|
+
return this.normalize(path);
|
|
260
|
+
}
|
|
261
|
+
require(path) {
|
|
262
|
+
const node = this.nodes.get(this.key(this.resolve(path)));
|
|
263
|
+
if (node === undefined) {
|
|
264
|
+
throw new AgentSkillsError(ErrorCode.IO_ERROR, `No such file or directory: ${path}`);
|
|
265
|
+
}
|
|
266
|
+
return node;
|
|
267
|
+
}
|
|
268
|
+
assertWritable(path) {
|
|
269
|
+
for (const readOnly of this.readOnlyPaths) {
|
|
270
|
+
if (this.normalize(path).startsWith(this.normalize(this.resolve(readOnly)))) {
|
|
271
|
+
throw new AgentSkillsError(ErrorCode.PERMISSION_DENIED, `Permission denied: ${path}`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
mkdirpSync(path) {
|
|
276
|
+
const absolute = this.normalize(path);
|
|
277
|
+
const segments = this.parts(absolute);
|
|
278
|
+
let current = this.isAbsolute(absolute)
|
|
279
|
+
? this.separator === '\\'
|
|
280
|
+
? `${absolute.slice(0, 2)}\\`
|
|
281
|
+
: '/'
|
|
282
|
+
: '';
|
|
283
|
+
this.nodes.set(this.key(current === '' ? this.root : current), {
|
|
284
|
+
kind: 'dir',
|
|
285
|
+
mtimeMs: this.clock,
|
|
286
|
+
mode: 0o755,
|
|
287
|
+
});
|
|
288
|
+
for (const segment of segments) {
|
|
289
|
+
current = current === '' ? segment : this.join(current, segment);
|
|
290
|
+
const key = this.key(current);
|
|
291
|
+
if (!this.nodes.has(key)) {
|
|
292
|
+
this.nodes.set(key, { kind: 'dir', mtimeMs: (this.clock += 1), mode: 0o755 });
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=in-memory-file-system.js.map
|