@nseng-ai/areg 0.1.1 → 0.1.2
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/package.json +7 -6
- package/src/cli.ts +0 -33
- package/src/context.ts +3 -29
- package/src/fake-gateways.ts +108 -380
- package/src/gateways/errors.ts +2 -2
- package/src/gateways/fs-utils.ts +2 -2
- package/src/gateways/project-fs.ts +29 -41
- package/src/gateways/project-gateway.ts +98 -31
- package/src/gateways.ts +34 -150
- package/src/index.ts +2 -28
- package/src/operations/check.ts +33 -20
- package/src/operations/doctor-skills.ts +71 -7
- package/src/operations/file-state.ts +4 -4
- package/src/operations/manifest-source-findings.ts +45 -0
- package/src/operations/manifest-sources.ts +119 -0
- package/src/operations/pi-settings.ts +2 -5
- package/src/operations/project-inspection.ts +32 -28
- package/src/operations/project-mutations.ts +5 -21
- package/src/operations/project-resolution.ts +2 -2
- package/src/operations/skill-find.ts +23 -3
- package/src/operations/skill-kind-apply-plan.ts +2 -2
- package/src/operations/skill-kind-frontmatter.ts +1 -1
- package/src/operations/skill-kind-inference.ts +30 -14
- package/src/operations/skill-kind.ts +34 -12
- package/src/sort.ts +3 -3
- package/src/gateways/command-constants.ts +0 -1
- package/src/gateways/github-gateway.ts +0 -111
- package/src/gateways/host-gateway.ts +0 -35
- package/src/gateways/mutation-policy.ts +0 -94
- package/src/gateways/npx-skills-gateway.ts +0 -53
- package/src/gateways/prompt-gateway.ts +0 -21
- package/src/gateways/skillx-workspace-gateway.ts +0 -220
- package/src/operations/frontmatter.ts +0 -151
- package/src/operations/init.ts +0 -548
- package/src/operations/lockfile.ts +0 -107
- package/src/operations/managed-markdown-block.ts +0 -47
- package/src/operations/project-agents.ts +0 -115
- package/src/operations/skill-mirror-conventions.ts +0 -126
- package/src/operations/skillx.ts +0 -305
- package/src/operations/toml-section.ts +0 -53
- package/src/operations/update-skills.ts +0 -325
- package/src/real-gateways.ts +0 -6
- package/src/skill-lookup.ts +0 -254
package/src/fake-gateways.ts
CHANGED
|
@@ -1,28 +1,17 @@
|
|
|
1
1
|
import { optionalEntry } from "@nseng-ai/foundation/primitives";
|
|
2
|
-
import { resultErr, resultOk } from "@nseng-ai/foundation/result";
|
|
3
2
|
import {
|
|
4
3
|
skillLookupBaseRelativePath,
|
|
5
4
|
skillLookupDescriptorForRoot,
|
|
6
5
|
skillLookupDescriptorForSourceType,
|
|
7
6
|
type SkillLookupRoot,
|
|
8
7
|
type SkillLookupSourceType,
|
|
9
|
-
} from "
|
|
8
|
+
} from "@nseng-ai/foundation/skill-lookup";
|
|
10
9
|
|
|
11
10
|
import { missingCheckSkillInspection } from "./gateways.ts";
|
|
12
11
|
import type {
|
|
13
12
|
AregCheckPairingDirectory,
|
|
14
13
|
AregCheckSkillInspection,
|
|
15
14
|
AregErrorInfo,
|
|
16
|
-
AregGithubGateway,
|
|
17
|
-
AregGithubSkillFileResult,
|
|
18
|
-
AregGithubSkillListResult,
|
|
19
|
-
AregHostGateway,
|
|
20
|
-
AregHostToolName,
|
|
21
|
-
AregNpxSkillsAddRequest,
|
|
22
|
-
AregNpxSkillsAddResult,
|
|
23
|
-
AregNpxSkillsGateway,
|
|
24
|
-
AregOperationResult,
|
|
25
|
-
AregPathState,
|
|
26
15
|
AregPiSkillInventoryInspection,
|
|
27
16
|
AregProjectBaseInspection,
|
|
28
17
|
AregProjectDirRequest,
|
|
@@ -34,7 +23,6 @@ import type {
|
|
|
34
23
|
AregProjectRemoveEmptyDirResult,
|
|
35
24
|
AregProjectSymlinkDeleteRequest,
|
|
36
25
|
AregProjectTextWriteRequest,
|
|
37
|
-
AregPromptGateway,
|
|
38
26
|
AregSkillFindRootsInspection,
|
|
39
27
|
AregSkillFindSkillInspection,
|
|
40
28
|
AregSkillInspectionRequest,
|
|
@@ -42,26 +30,25 @@ import type {
|
|
|
42
30
|
AregSkillKindResolveResult,
|
|
43
31
|
AregSkillKindSkillInspection,
|
|
44
32
|
AregSkillKindSourceType,
|
|
45
|
-
AregSkillxInstallRequest,
|
|
46
|
-
AregSkillxInstallResult,
|
|
47
|
-
AregSkillxInstalledSkill,
|
|
48
|
-
AregSkillxWorkspaceCleanupRequest,
|
|
49
|
-
AregSkillxWorkspaceGateway,
|
|
50
|
-
AregTextFileState,
|
|
51
|
-
AregToolCheckResult,
|
|
52
33
|
} from "./gateways.ts";
|
|
34
|
+
import type {
|
|
35
|
+
AregManifestSkillSourceInspection,
|
|
36
|
+
AregManifestSkillSourcesInspection,
|
|
37
|
+
} from "./operations/manifest-sources.ts";
|
|
53
38
|
import { classifyResolvedSkillKindInspection } from "./gateways/skill-kind-classification.ts";
|
|
54
39
|
import {
|
|
55
40
|
classifySkillMirrorSymlinkState,
|
|
56
41
|
parseSkillMirrorRelativePath,
|
|
57
|
-
|
|
42
|
+
type PathState,
|
|
43
|
+
type TextFileState,
|
|
44
|
+
} from "@nseng-ai/harness-artifacts/api";
|
|
58
45
|
|
|
59
46
|
export type FakeAregProjectOperation =
|
|
60
47
|
| { type: "inspect-project-base"; cwd: string; projectPath: string }
|
|
61
|
-
| { type: "inspect-instruction-files"; projectDir: string }
|
|
62
48
|
| { type: "inspect-pi-artifacts"; projectDir: string }
|
|
63
49
|
| { type: "inspect-pi-skill-inventory"; projectDir: string }
|
|
64
50
|
| { type: "inspect-skill-name-inventory"; projectDir: string }
|
|
51
|
+
| { type: "inspect-manifest-skill-sources"; projectDir: string }
|
|
65
52
|
| { type: "inspect-skill-find-roots"; projectDir: string }
|
|
66
53
|
| { type: "inspect-check-skill"; projectDir: string; skillName: string }
|
|
67
54
|
| { type: "inspect-skill-kind-skill"; projectDir: string; skillName: string }
|
|
@@ -79,23 +66,36 @@ export type FakeAregProjectOperation =
|
|
|
79
66
|
|
|
80
67
|
export interface FakeAregCheckSkillOptions {
|
|
81
68
|
name: string;
|
|
82
|
-
skillsPath?:
|
|
83
|
-
agentsPath?:
|
|
84
|
-
claudePath?:
|
|
85
|
-
localSkillMd?:
|
|
86
|
-
remoteSkillMd?:
|
|
87
|
-
openaiPolicy?:
|
|
69
|
+
skillsPath?: PathState;
|
|
70
|
+
agentsPath?: PathState;
|
|
71
|
+
claudePath?: PathState;
|
|
72
|
+
localSkillMd?: TextFileState | string;
|
|
73
|
+
remoteSkillMd?: TextFileState | string;
|
|
74
|
+
openaiPolicy?: TextFileState | string;
|
|
88
75
|
}
|
|
89
76
|
|
|
90
77
|
export interface FakeAregSkillKindSkillOptions {
|
|
91
78
|
name: string;
|
|
92
79
|
sourceType?: AregSkillKindSourceType;
|
|
93
80
|
baseRelativePath?: string;
|
|
94
|
-
skillDir?:
|
|
95
|
-
skillMd?:
|
|
96
|
-
openaiPolicy?:
|
|
97
|
-
agentsPath?:
|
|
98
|
-
claudePath?:
|
|
81
|
+
skillDir?: PathState;
|
|
82
|
+
skillMd?: TextFileState | string;
|
|
83
|
+
openaiPolicy?: TextFileState | string;
|
|
84
|
+
agentsPath?: PathState;
|
|
85
|
+
claudePath?: PathState;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface FakeAregManifestSkillSourceOptions {
|
|
89
|
+
skillName: string;
|
|
90
|
+
harness?: AregManifestSkillSourceInspection["harness"];
|
|
91
|
+
scope?: AregManifestSkillSourceInspection["scope"];
|
|
92
|
+
manifestPath?: string;
|
|
93
|
+
manifestKey?: string;
|
|
94
|
+
provenance?: Partial<AregManifestSkillSourceInspection["provenance"]>;
|
|
95
|
+
targetRootRelativePath?: string;
|
|
96
|
+
targetSkillRelativePath?: string;
|
|
97
|
+
skillDir?: PathState;
|
|
98
|
+
skillMd?: TextFileState | string;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
export interface FakeAregSkillFindSkillOptions {
|
|
@@ -103,23 +103,19 @@ export interface FakeAregSkillFindSkillOptions {
|
|
|
103
103
|
root?: SkillLookupRoot;
|
|
104
104
|
sourceType?: SkillLookupSourceType;
|
|
105
105
|
baseRelativePath?: string;
|
|
106
|
-
skillDir?:
|
|
107
|
-
skillMd?:
|
|
106
|
+
skillDir?: PathState;
|
|
107
|
+
skillMd?: TextFileState | string;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
export interface FakeAregProjectGatewayOptions {
|
|
111
111
|
projectDir?: string;
|
|
112
|
-
projectPathState?:
|
|
113
|
-
targetPathState?:
|
|
114
|
-
lockfile?:
|
|
115
|
-
nsToml?:
|
|
116
|
-
aregJson?:
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
claudeDir?: AregPathState;
|
|
120
|
-
claudeSettings?: AregTextFileState | string;
|
|
121
|
-
piDir?: AregPathState;
|
|
122
|
-
piSettings?: AregTextFileState | object | string;
|
|
112
|
+
projectPathState?: PathState;
|
|
113
|
+
targetPathState?: PathState;
|
|
114
|
+
lockfile?: TextFileState | object | string;
|
|
115
|
+
nsToml?: TextFileState | string;
|
|
116
|
+
aregJson?: TextFileState | object | string;
|
|
117
|
+
piDir?: PathState;
|
|
118
|
+
piSettings?: TextFileState | object | string;
|
|
123
119
|
replacementSurfaces?: readonly string[];
|
|
124
120
|
piSkillInventory?: Partial<AregPiSkillInventoryInspection>;
|
|
125
121
|
skillsDirectoryNames?: readonly string[];
|
|
@@ -129,6 +125,8 @@ export interface FakeAregProjectGatewayOptions {
|
|
|
129
125
|
checkSkills?: readonly FakeAregCheckSkillOptions[];
|
|
130
126
|
localSkills?: readonly FakeAregSkillKindSkillOptions[];
|
|
131
127
|
findSkills?: readonly FakeAregSkillFindSkillOptions[];
|
|
128
|
+
manifestSkillSources?: readonly FakeAregManifestSkillSourceOptions[];
|
|
129
|
+
manifestErrors?: readonly AregManifestSkillSourcesInspection["errors"][number][];
|
|
132
130
|
pairingDirectories?: readonly AregCheckPairingDirectory[];
|
|
133
131
|
resolveFailures?: Readonly<Record<string, AregErrorInfo>>;
|
|
134
132
|
preflightFailures?: Readonly<Record<string, AregErrorInfo>>;
|
|
@@ -138,10 +136,9 @@ export interface FakeAregProjectGatewayOptions {
|
|
|
138
136
|
|
|
139
137
|
export class FakeAregProjectGateway implements AregProjectGateway {
|
|
140
138
|
private readonly projectDir: string;
|
|
141
|
-
private readonly projectPathState:
|
|
142
|
-
private readonly files: Map<string,
|
|
143
|
-
private readonly
|
|
144
|
-
private readonly piDir: AregPathState;
|
|
139
|
+
private readonly projectPathState: PathState;
|
|
140
|
+
private readonly files: Map<string, TextFileState>;
|
|
141
|
+
private readonly piDir: PathState;
|
|
145
142
|
private readonly replacementSurfaces: readonly string[];
|
|
146
143
|
private readonly piSkillInventory: AregPiSkillInventoryInspection | undefined;
|
|
147
144
|
private readonly skillsDirectoryNames: readonly string[];
|
|
@@ -151,6 +148,7 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
151
148
|
private readonly checkSkills: AregCheckSkillInspection[];
|
|
152
149
|
private readonly localSkills: AregSkillKindSkillInspection[];
|
|
153
150
|
private readonly explicitFindSkills: AregSkillFindSkillInspection[] | undefined;
|
|
151
|
+
private readonly manifestSkillSources: AregManifestSkillSourcesInspection;
|
|
154
152
|
private readonly pairingDirectories: readonly AregCheckPairingDirectory[];
|
|
155
153
|
private readonly resolveFailures: ReadonlyMap<string, AregErrorInfo>;
|
|
156
154
|
private readonly preflightFailures: ReadonlyMap<string, AregErrorInfo>;
|
|
@@ -166,15 +164,8 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
166
164
|
["skills-lock.json", normalizeTextFileState(options.lockfile ?? { version: 1, skills: {} })],
|
|
167
165
|
["ns.toml", normalizeTextFileState(options.nsToml ?? { type: "missing" })],
|
|
168
166
|
["areg.json", normalizeTextFileState(options.aregJson ?? { type: "missing" })],
|
|
169
|
-
["AGENTS.md", normalizeTextFileState(options.agentsMd ?? { type: "missing" })],
|
|
170
|
-
["CLAUDE.md", normalizeTextFileState(options.claudeMd ?? { type: "missing" })],
|
|
171
|
-
[
|
|
172
|
-
".claude/settings.local.json",
|
|
173
|
-
normalizeTextFileState(options.claudeSettings ?? { type: "missing" }),
|
|
174
|
-
],
|
|
175
167
|
[".pi/settings.json", normalizeTextFileState(options.piSettings ?? { type: "missing" })],
|
|
176
168
|
]);
|
|
177
|
-
this.claudeDir = copyPathState(options.claudeDir ?? { type: "missing" });
|
|
178
169
|
this.piDir = copyPathState(options.piDir ?? { type: "missing" });
|
|
179
170
|
this.replacementSurfaces = [...(options.replacementSurfaces ?? [])];
|
|
180
171
|
this.piSkillInventory =
|
|
@@ -189,6 +180,10 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
189
180
|
this.localSkills = (options.localSkills ?? []).map(copyFakeSkillKindSkill);
|
|
190
181
|
this.explicitFindSkills =
|
|
191
182
|
options.findSkills === undefined ? undefined : options.findSkills.map(copyFakeSkillFindSkill);
|
|
183
|
+
this.manifestSkillSources = {
|
|
184
|
+
sources: (options.manifestSkillSources ?? []).map(copyFakeManifestSkillSource),
|
|
185
|
+
errors: (options.manifestErrors ?? []).map((error) => ({ ...error })),
|
|
186
|
+
};
|
|
192
187
|
this.pairingDirectories = (options.pairingDirectories ?? []).map(copyPairingDirectory);
|
|
193
188
|
this.resolveFailures = new Map(
|
|
194
189
|
Object.entries(options.resolveFailures ?? {}).map(([key, value]) => [
|
|
@@ -228,16 +223,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
228
223
|
};
|
|
229
224
|
}
|
|
230
225
|
|
|
231
|
-
async inspectInstructionFiles(request: AregProjectDirRequest) {
|
|
232
|
-
this.log.push({ type: "inspect-instruction-files", projectDir: request.projectDir });
|
|
233
|
-
return {
|
|
234
|
-
agentsMd: this.fileState("AGENTS.md"),
|
|
235
|
-
claudeMd: this.fileState("CLAUDE.md"),
|
|
236
|
-
claudeDir: copyPathState(this.claudeDir),
|
|
237
|
-
claudeSettings: this.fileState(".claude/settings.local.json"),
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
226
|
async inspectPiArtifacts(request: AregProjectDirRequest) {
|
|
242
227
|
this.log.push({ type: "inspect-pi-artifacts", projectDir: request.projectDir });
|
|
243
228
|
return {
|
|
@@ -271,6 +256,16 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
271
256
|
};
|
|
272
257
|
}
|
|
273
258
|
|
|
259
|
+
async inspectManifestSkillSources(
|
|
260
|
+
request: AregProjectDirRequest,
|
|
261
|
+
): Promise<AregManifestSkillSourcesInspection> {
|
|
262
|
+
this.log.push({ type: "inspect-manifest-skill-sources", projectDir: request.projectDir });
|
|
263
|
+
return {
|
|
264
|
+
sources: this.manifestSkillSources.sources.map(copyManifestSkillSource),
|
|
265
|
+
errors: this.manifestSkillSources.errors.map((error) => ({ ...error })),
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
|
|
274
269
|
async inspectSkillFindRoots(
|
|
275
270
|
request: AregProjectDirRequest,
|
|
276
271
|
): Promise<AregSkillFindRootsInspection> {
|
|
@@ -348,7 +343,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
348
343
|
content: request.content,
|
|
349
344
|
description: request.description,
|
|
350
345
|
createParent: request.createParent,
|
|
351
|
-
policy: request.policy,
|
|
352
346
|
});
|
|
353
347
|
const failure = this.preflightFailure(request.relativePath);
|
|
354
348
|
return failure === undefined ? { ok: true } : { ok: false, error: failure };
|
|
@@ -362,7 +356,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
362
356
|
projectDir: request.projectDir,
|
|
363
357
|
relativePath: request.relativePath,
|
|
364
358
|
description: request.description,
|
|
365
|
-
policy: request.policy,
|
|
366
359
|
});
|
|
367
360
|
const failure = this.preflightFailure(request.relativePath);
|
|
368
361
|
return failure === undefined ? { ok: true } : { ok: false, error: failure };
|
|
@@ -376,7 +369,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
376
369
|
projectDir: request.projectDir,
|
|
377
370
|
relativePath: request.relativePath,
|
|
378
371
|
description: request.description,
|
|
379
|
-
policy: request.policy,
|
|
380
372
|
});
|
|
381
373
|
const failure =
|
|
382
374
|
this.preflightFailure(request.relativePath) ??
|
|
@@ -392,7 +384,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
392
384
|
projectDir: request.projectDir,
|
|
393
385
|
relativePath: request.relativePath,
|
|
394
386
|
description: request.description,
|
|
395
|
-
policy: request.policy,
|
|
396
387
|
});
|
|
397
388
|
const failure = this.preflightFailure(request.relativePath);
|
|
398
389
|
return failure === undefined ? { ok: true } : { ok: false, error: failure };
|
|
@@ -406,7 +397,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
406
397
|
content: request.content,
|
|
407
398
|
description: request.description,
|
|
408
399
|
createParent: request.createParent,
|
|
409
|
-
policy: request.policy,
|
|
410
400
|
});
|
|
411
401
|
const failure = this.mutationFailure(request.relativePath);
|
|
412
402
|
if (failure !== undefined) return { ok: false, error: failure };
|
|
@@ -425,7 +415,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
425
415
|
projectDir: request.projectDir,
|
|
426
416
|
relativePath: request.relativePath,
|
|
427
417
|
description: request.description,
|
|
428
|
-
policy: request.policy,
|
|
429
418
|
});
|
|
430
419
|
const failure = this.mutationFailure(request.relativePath);
|
|
431
420
|
if (failure !== undefined) return { ok: false, error: failure };
|
|
@@ -444,7 +433,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
444
433
|
projectDir: request.projectDir,
|
|
445
434
|
relativePath: request.relativePath,
|
|
446
435
|
description: request.description,
|
|
447
|
-
policy: request.policy,
|
|
448
436
|
});
|
|
449
437
|
const failure =
|
|
450
438
|
this.mutationFailure(request.relativePath) ??
|
|
@@ -467,7 +455,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
467
455
|
projectDir: request.projectDir,
|
|
468
456
|
relativePath: request.relativePath,
|
|
469
457
|
description: request.description,
|
|
470
|
-
policy: request.policy,
|
|
471
458
|
});
|
|
472
459
|
const failure = this.mutationFailure(request.relativePath);
|
|
473
460
|
if (failure !== undefined) return { ok: false, error: failure };
|
|
@@ -483,7 +470,7 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
483
470
|
return this.log.map(copyProjectOperation);
|
|
484
471
|
}
|
|
485
472
|
|
|
486
|
-
private fileState(relativePath: string):
|
|
473
|
+
private fileState(relativePath: string): TextFileState {
|
|
487
474
|
return copyTextFileState(this.files.get(relativePath) ?? { type: "missing" });
|
|
488
475
|
}
|
|
489
476
|
|
|
@@ -522,267 +509,6 @@ export class FakeAregProjectGateway implements AregProjectGateway {
|
|
|
522
509
|
}
|
|
523
510
|
}
|
|
524
511
|
|
|
525
|
-
export type FakeAregHostOperation = { type: "check-tool"; tool: AregHostToolName; cwd: string };
|
|
526
|
-
|
|
527
|
-
export interface FakeAregHostGatewayOptions {
|
|
528
|
-
tools?: Partial<Record<AregHostToolName, string | null>>;
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
export class FakeAregHostGateway implements AregHostGateway {
|
|
532
|
-
private readonly tools: ReadonlyMap<AregHostToolName, string | null>;
|
|
533
|
-
private readonly log: FakeAregHostOperation[] = [];
|
|
534
|
-
|
|
535
|
-
constructor(options: FakeAregHostGatewayOptions = {}) {
|
|
536
|
-
this.tools = new Map(
|
|
537
|
-
Object.entries(options.tools ?? {}) as Array<[AregHostToolName, string | null]>,
|
|
538
|
-
);
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
async checkTool(options: {
|
|
542
|
-
tool: AregHostToolName;
|
|
543
|
-
cwd: string;
|
|
544
|
-
env: NodeJS.ProcessEnv;
|
|
545
|
-
}): Promise<AregToolCheckResult> {
|
|
546
|
-
this.log.push({ type: "check-tool", tool: options.tool, cwd: options.cwd });
|
|
547
|
-
const path = this.tools.get(options.tool);
|
|
548
|
-
if (path === null)
|
|
549
|
-
return {
|
|
550
|
-
type: "missing",
|
|
551
|
-
tool: options.tool,
|
|
552
|
-
message: `Required host tool is missing: ${options.tool}`,
|
|
553
|
-
};
|
|
554
|
-
return { type: "found", tool: options.tool, path: path ?? `/fake/bin/${options.tool}` };
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
operations(): readonly FakeAregHostOperation[] {
|
|
558
|
-
return this.log.map((operation) => ({ ...operation }));
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
export type FakeAregGithubOperation =
|
|
563
|
-
| {
|
|
564
|
-
type: "list-skill-directory-names";
|
|
565
|
-
repo: string;
|
|
566
|
-
ref?: string;
|
|
567
|
-
}
|
|
568
|
-
| {
|
|
569
|
-
type: "check-skill-file";
|
|
570
|
-
repo: string;
|
|
571
|
-
path: string;
|
|
572
|
-
ref?: string;
|
|
573
|
-
};
|
|
574
|
-
|
|
575
|
-
export interface FakeAregGithubGatewayOptions {
|
|
576
|
-
repos?: Record<string, readonly string[] | "missing" | "auth-error" | AregErrorInfo>;
|
|
577
|
-
files?: Record<string, "found" | "missing" | "auth-error" | AregErrorInfo>;
|
|
578
|
-
}
|
|
579
|
-
|
|
580
|
-
export class FakeAregGithubGateway implements AregGithubGateway {
|
|
581
|
-
private readonly repos: ReadonlyMap<
|
|
582
|
-
string,
|
|
583
|
-
readonly string[] | "missing" | "auth-error" | AregErrorInfo
|
|
584
|
-
>;
|
|
585
|
-
private readonly files: ReadonlyMap<string, "found" | "missing" | "auth-error" | AregErrorInfo>;
|
|
586
|
-
private readonly log: FakeAregGithubOperation[] = [];
|
|
587
|
-
|
|
588
|
-
constructor(options: FakeAregGithubGatewayOptions = {}) {
|
|
589
|
-
this.repos = new Map(
|
|
590
|
-
Object.entries(options.repos ?? {}).map(([repo, value]) => [repo, copyGithubState(value)]),
|
|
591
|
-
);
|
|
592
|
-
this.files = new Map(
|
|
593
|
-
Object.entries(options.files ?? {}).map(([path, value]) => [
|
|
594
|
-
path,
|
|
595
|
-
copyGithubFileState(value),
|
|
596
|
-
]),
|
|
597
|
-
);
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
async listSkillDirectoryNames(options: {
|
|
601
|
-
repo: string;
|
|
602
|
-
ref?: string;
|
|
603
|
-
env: NodeJS.ProcessEnv;
|
|
604
|
-
}): Promise<AregGithubSkillListResult> {
|
|
605
|
-
this.log.push({
|
|
606
|
-
type: "list-skill-directory-names",
|
|
607
|
-
repo: options.repo,
|
|
608
|
-
...optionalEntry("ref", options.ref),
|
|
609
|
-
});
|
|
610
|
-
const state = this.repos.get(options.repo);
|
|
611
|
-
if (state === undefined || state === "missing")
|
|
612
|
-
return { type: "missing", message: `Skill source not found: ${options.repo}` };
|
|
613
|
-
if (state === "auth-error")
|
|
614
|
-
return { type: "auth-error", message: `GitHub authentication failed for ${options.repo}` };
|
|
615
|
-
if (isReadonlyStringArray(state)) return { type: "ok", skillNames: [...state] };
|
|
616
|
-
return { type: "error", error: copyErrorInfo(state) };
|
|
617
|
-
}
|
|
618
|
-
|
|
619
|
-
async checkSkillFile(options: {
|
|
620
|
-
repo: string;
|
|
621
|
-
path: string;
|
|
622
|
-
ref?: string;
|
|
623
|
-
env: NodeJS.ProcessEnv;
|
|
624
|
-
}): Promise<AregGithubSkillFileResult> {
|
|
625
|
-
this.log.push({
|
|
626
|
-
type: "check-skill-file",
|
|
627
|
-
repo: options.repo,
|
|
628
|
-
path: options.path,
|
|
629
|
-
...optionalEntry("ref", options.ref),
|
|
630
|
-
});
|
|
631
|
-
const state = this.files.get(githubFileKey(options.repo, options.path, options.ref));
|
|
632
|
-
if (state === undefined || state === "found") return { type: "found" };
|
|
633
|
-
if (state === "missing")
|
|
634
|
-
return { type: "missing", message: `Skill file not found: ${options.repo}/${options.path}` };
|
|
635
|
-
if (state === "auth-error")
|
|
636
|
-
return { type: "auth-error", message: `GitHub authentication failed for ${options.repo}` };
|
|
637
|
-
return { type: "error", error: copyErrorInfo(state) };
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
operations(): readonly FakeAregGithubOperation[] {
|
|
641
|
-
return this.log.map((operation) => ({ ...operation }));
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
export type FakeAregNpxSkillsOperation = { type: "add-skills" } & Omit<
|
|
646
|
-
AregNpxSkillsAddRequest,
|
|
647
|
-
"env"
|
|
648
|
-
>;
|
|
649
|
-
|
|
650
|
-
export interface FakeAregNpxSkillsGatewayOptions {
|
|
651
|
-
failure?: AregErrorInfo;
|
|
652
|
-
failures?: Readonly<Record<string, AregErrorInfo>>;
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
export class FakeAregNpxSkillsGateway implements AregNpxSkillsGateway {
|
|
656
|
-
private readonly failure: AregErrorInfo | undefined;
|
|
657
|
-
private readonly failures: ReadonlyMap<string, AregErrorInfo>;
|
|
658
|
-
private readonly log: FakeAregNpxSkillsOperation[] = [];
|
|
659
|
-
|
|
660
|
-
constructor(options: FakeAregNpxSkillsGatewayOptions = {}) {
|
|
661
|
-
this.failure = options.failure === undefined ? undefined : copyErrorInfo(options.failure);
|
|
662
|
-
this.failures = new Map(
|
|
663
|
-
Object.entries(options.failures ?? {}).map(([key, value]) => [key, copyErrorInfo(value)]),
|
|
664
|
-
);
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
async addSkills(request: AregNpxSkillsAddRequest): Promise<AregNpxSkillsAddResult> {
|
|
668
|
-
this.log.push({
|
|
669
|
-
type: "add-skills",
|
|
670
|
-
sourceRepo: request.sourceRepo,
|
|
671
|
-
skillNames: [...request.skillNames],
|
|
672
|
-
targetAgents: [...request.targetAgents],
|
|
673
|
-
cwd: request.cwd,
|
|
674
|
-
});
|
|
675
|
-
if (this.failure !== undefined) return { type: "error", error: copyErrorInfo(this.failure) };
|
|
676
|
-
const keyedFailure = this.failures.get(failureKey(request.sourceRepo, request.skillNames));
|
|
677
|
-
if (keyedFailure !== undefined) return { type: "error", error: copyErrorInfo(keyedFailure) };
|
|
678
|
-
return { type: "ok" };
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
operations(): readonly FakeAregNpxSkillsOperation[] {
|
|
682
|
-
return this.log.map((operation) => ({
|
|
683
|
-
...operation,
|
|
684
|
-
skillNames: [...operation.skillNames],
|
|
685
|
-
targetAgents: [...operation.targetAgents],
|
|
686
|
-
}));
|
|
687
|
-
}
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
export type FakeAregPromptOperation = {
|
|
691
|
-
type: "confirm";
|
|
692
|
-
message: string;
|
|
693
|
-
defaultValue: boolean;
|
|
694
|
-
response: boolean;
|
|
695
|
-
};
|
|
696
|
-
|
|
697
|
-
export interface FakeAregPromptGatewayOptions {
|
|
698
|
-
responses?: readonly boolean[];
|
|
699
|
-
shouldConfirmByDefault?: boolean;
|
|
700
|
-
}
|
|
701
|
-
|
|
702
|
-
export class FakeAregPromptGateway implements AregPromptGateway {
|
|
703
|
-
private readonly responses: boolean[];
|
|
704
|
-
private readonly shouldConfirmByDefault: boolean;
|
|
705
|
-
private readonly log: FakeAregPromptOperation[] = [];
|
|
706
|
-
|
|
707
|
-
constructor(options: FakeAregPromptGatewayOptions = {}) {
|
|
708
|
-
this.responses = [...(options.responses ?? [])];
|
|
709
|
-
this.shouldConfirmByDefault = options.shouldConfirmByDefault ?? false;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
async confirm(request: { message: string; defaultValue: boolean }): Promise<boolean> {
|
|
713
|
-
const response = this.responses.shift() ?? this.shouldConfirmByDefault;
|
|
714
|
-
this.log.push({
|
|
715
|
-
type: "confirm",
|
|
716
|
-
message: request.message,
|
|
717
|
-
defaultValue: request.defaultValue,
|
|
718
|
-
response,
|
|
719
|
-
});
|
|
720
|
-
return response;
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
operations(): readonly FakeAregPromptOperation[] {
|
|
724
|
-
return this.log.map((operation) => ({ ...operation }));
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
|
|
728
|
-
export type FakeAregSkillxOperation =
|
|
729
|
-
| ({ type: "install-into-workspace" } & Omit<AregSkillxInstallRequest, "env">)
|
|
730
|
-
| ({ type: "cleanup-workspace" } & AregSkillxWorkspaceCleanupRequest);
|
|
731
|
-
|
|
732
|
-
export interface FakeAregSkillxWorkspaceGatewayOptions {
|
|
733
|
-
workspaceRoot?: string;
|
|
734
|
-
installedSkills?: readonly AregSkillxInstalledSkill[];
|
|
735
|
-
failure?: AregErrorInfo;
|
|
736
|
-
cleanupFailure?: AregErrorInfo;
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
export class FakeAregSkillxWorkspaceGateway implements AregSkillxWorkspaceGateway {
|
|
740
|
-
private readonly workspaceRoot: string;
|
|
741
|
-
private readonly installedSkills: readonly AregSkillxInstalledSkill[];
|
|
742
|
-
private readonly failure: AregErrorInfo | undefined;
|
|
743
|
-
private readonly cleanupFailure: AregErrorInfo | undefined;
|
|
744
|
-
private readonly log: FakeAregSkillxOperation[] = [];
|
|
745
|
-
|
|
746
|
-
constructor(options: FakeAregSkillxWorkspaceGatewayOptions = {}) {
|
|
747
|
-
this.workspaceRoot = options.workspaceRoot ?? "/tmp/areg-skillx";
|
|
748
|
-
this.installedSkills = (options.installedSkills ?? []).map(copyInstalledSkill);
|
|
749
|
-
this.failure = options.failure === undefined ? undefined : copyErrorInfo(options.failure);
|
|
750
|
-
this.cleanupFailure =
|
|
751
|
-
options.cleanupFailure === undefined ? undefined : copyErrorInfo(options.cleanupFailure);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
async installIntoWorkspace(request: AregSkillxInstallRequest): Promise<AregSkillxInstallResult> {
|
|
755
|
-
this.log.push({
|
|
756
|
-
type: "install-into-workspace",
|
|
757
|
-
sourceRepo: request.sourceRepo,
|
|
758
|
-
...optionalEntry("skillName", request.skillName),
|
|
759
|
-
cwd: request.cwd,
|
|
760
|
-
});
|
|
761
|
-
if (this.failure !== undefined) return { type: "error", error: copyErrorInfo(this.failure) };
|
|
762
|
-
return {
|
|
763
|
-
type: "ok",
|
|
764
|
-
workspace: {
|
|
765
|
-
workspaceRoot: this.workspaceRoot,
|
|
766
|
-
installedSkills: this.installedSkills.map(copyInstalledSkill),
|
|
767
|
-
},
|
|
768
|
-
};
|
|
769
|
-
}
|
|
770
|
-
|
|
771
|
-
async cleanupWorkspace(request: AregSkillxWorkspaceCleanupRequest): Promise<AregOperationResult> {
|
|
772
|
-
this.log.push({ type: "cleanup-workspace", workspaceRoot: request.workspaceRoot });
|
|
773
|
-
if (this.cleanupFailure !== undefined) return resultErr(copyErrorInfo(this.cleanupFailure));
|
|
774
|
-
return resultOk(undefined);
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
operations(): readonly FakeAregSkillxOperation[] {
|
|
778
|
-
return this.log.map((operation) => ({ ...operation }));
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
function failureKey(sourceRepo: string, skillNames: readonly string[]): string {
|
|
783
|
-
return `${sourceRepo}:${skillNames.join(",")}`;
|
|
784
|
-
}
|
|
785
|
-
|
|
786
512
|
function copyProjectOperation(operation: FakeAregProjectOperation): FakeAregProjectOperation {
|
|
787
513
|
switch (operation.type) {
|
|
788
514
|
case "write-text-file":
|
|
@@ -825,6 +551,33 @@ function copyFakeSkillFindSkill(
|
|
|
825
551
|
};
|
|
826
552
|
}
|
|
827
553
|
|
|
554
|
+
function copyFakeManifestSkillSource(
|
|
555
|
+
source: FakeAregManifestSkillSourceOptions,
|
|
556
|
+
): AregManifestSkillSourceInspection {
|
|
557
|
+
const manifestKey = source.manifestKey ?? `skill:${source.skillName}:pi:project`;
|
|
558
|
+
const targetSkillRelativePath =
|
|
559
|
+
source.targetSkillRelativePath ?? `.pi/skills/${source.skillName}`;
|
|
560
|
+
return {
|
|
561
|
+
skillName: source.skillName,
|
|
562
|
+
harness: source.harness ?? "pi",
|
|
563
|
+
scope: source.scope ?? "project",
|
|
564
|
+
manifestPath: source.manifestPath ?? "/repo/.pi/skills/.ns-harness-artifacts-manifest.json",
|
|
565
|
+
manifestKey,
|
|
566
|
+
provenance: {
|
|
567
|
+
type: source.provenance?.type ?? "npm-module",
|
|
568
|
+
packageName: source.provenance?.packageName ?? "@example/skills",
|
|
569
|
+
relativePath: source.provenance?.relativePath ?? `skills/${source.skillName}`,
|
|
570
|
+
version: source.provenance?.version ?? "1.0.0",
|
|
571
|
+
},
|
|
572
|
+
targetRootRelativePath: source.targetRootRelativePath ?? ".pi/skills",
|
|
573
|
+
targetSkillRelativePath,
|
|
574
|
+
skillDir: copyPathState(source.skillDir ?? { type: "directory" }),
|
|
575
|
+
skillMd: normalizeTextFileState(
|
|
576
|
+
source.skillMd ?? `---\nname: ${source.skillName}\ndescription: ${source.skillName}\n---\n`,
|
|
577
|
+
),
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
|
|
828
581
|
function copyFakeSkillKindSkill(
|
|
829
582
|
skill: FakeAregSkillKindSkillOptions,
|
|
830
583
|
): AregSkillKindSkillInspection {
|
|
@@ -860,8 +613,8 @@ function copyCheckSkill(skill: AregCheckSkillInspection): AregCheckSkillInspecti
|
|
|
860
613
|
interface SkillInspectionCore {
|
|
861
614
|
name: string;
|
|
862
615
|
baseRelativePath: string;
|
|
863
|
-
skillDir:
|
|
864
|
-
skillMd:
|
|
616
|
+
skillDir: PathState;
|
|
617
|
+
skillMd: TextFileState;
|
|
865
618
|
}
|
|
866
619
|
|
|
867
620
|
function copySkillInspectionCore(skill: SkillInspectionCore): SkillInspectionCore {
|
|
@@ -891,6 +644,17 @@ function copySkillFindSkill(skill: AregSkillFindSkillInspection): AregSkillFindS
|
|
|
891
644
|
};
|
|
892
645
|
}
|
|
893
646
|
|
|
647
|
+
function copyManifestSkillSource(
|
|
648
|
+
source: AregManifestSkillSourceInspection,
|
|
649
|
+
): AregManifestSkillSourceInspection {
|
|
650
|
+
return {
|
|
651
|
+
...source,
|
|
652
|
+
provenance: { ...source.provenance },
|
|
653
|
+
skillDir: copyPathState(source.skillDir),
|
|
654
|
+
skillMd: copyTextFileState(source.skillMd),
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
|
|
894
658
|
function skillKindSkillToFindSkill(
|
|
895
659
|
skill: AregSkillKindSkillInspection,
|
|
896
660
|
): AregSkillFindSkillInspection {
|
|
@@ -935,13 +699,13 @@ function skillForRelativePath(
|
|
|
935
699
|
return skills.find((skill) => relativePath.startsWith(`${skill.baseRelativePath}/`));
|
|
936
700
|
}
|
|
937
701
|
|
|
938
|
-
function normalizeTextFileState(value:
|
|
702
|
+
function normalizeTextFileState(value: TextFileState | object | string): TextFileState {
|
|
939
703
|
if (typeof value === "string") return { type: "file", text: value };
|
|
940
|
-
if ("type" in value) return copyTextFileState(value as
|
|
704
|
+
if ("type" in value) return copyTextFileState(value as TextFileState);
|
|
941
705
|
return { type: "file", text: `${JSON.stringify(value, null, 2)}\n` };
|
|
942
706
|
}
|
|
943
707
|
|
|
944
|
-
function copyTextFileState(state:
|
|
708
|
+
function copyTextFileState(state: TextFileState): TextFileState {
|
|
945
709
|
return { ...state };
|
|
946
710
|
}
|
|
947
711
|
|
|
@@ -955,7 +719,7 @@ function copyPiSkillInventory(
|
|
|
955
719
|
};
|
|
956
720
|
}
|
|
957
721
|
|
|
958
|
-
function copyPathState(state:
|
|
722
|
+
function copyPathState(state: PathState): PathState {
|
|
959
723
|
return { ...state };
|
|
960
724
|
}
|
|
961
725
|
|
|
@@ -968,42 +732,6 @@ function copyPairingDirectory(directory: AregCheckPairingDirectory): AregCheckPa
|
|
|
968
732
|
};
|
|
969
733
|
}
|
|
970
734
|
|
|
971
|
-
function copyGithubState(
|
|
972
|
-
value: readonly string[] | "missing" | "auth-error" | AregErrorInfo,
|
|
973
|
-
): readonly string[] | "missing" | "auth-error" | AregErrorInfo {
|
|
974
|
-
if (isReadonlyStringArray(value)) return [...value];
|
|
975
|
-
if (value === "missing" || value === "auth-error") return value;
|
|
976
|
-
return copyErrorInfo(value);
|
|
977
|
-
}
|
|
978
|
-
|
|
979
|
-
function copyGithubFileState(
|
|
980
|
-
value: "found" | "missing" | "auth-error" | AregErrorInfo,
|
|
981
|
-
): "found" | "missing" | "auth-error" | AregErrorInfo {
|
|
982
|
-
if (value === "found" || value === "missing" || value === "auth-error") return value;
|
|
983
|
-
return copyErrorInfo(value);
|
|
984
|
-
}
|
|
985
|
-
|
|
986
|
-
function githubFileKey(repo: string, path: string, ref: string | undefined): string {
|
|
987
|
-
return ref === undefined ? `${repo}:${path}` : `${repo}:${path}@${ref}`;
|
|
988
|
-
}
|
|
989
|
-
|
|
990
|
-
function isReadonlyStringArray(
|
|
991
|
-
value: readonly string[] | "missing" | "auth-error" | AregErrorInfo,
|
|
992
|
-
): value is readonly string[] {
|
|
993
|
-
return Array.isArray(value);
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
function copyInstalledSkill(skill: AregSkillxInstalledSkill): AregSkillxInstalledSkill {
|
|
997
|
-
return {
|
|
998
|
-
name: skill.name,
|
|
999
|
-
directory: skill.directory,
|
|
1000
|
-
skillFile: skill.skillFile,
|
|
1001
|
-
relativeFiles: [...skill.relativeFiles],
|
|
1002
|
-
};
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
735
|
function copyErrorInfo(error: AregErrorInfo): AregErrorInfo {
|
|
1006
|
-
return error.
|
|
1007
|
-
? { code: error.code, message: error.message }
|
|
1008
|
-
: { code: error.code, message: error.message, displayCommand: error.displayCommand };
|
|
736
|
+
return { code: error.code, message: error.message };
|
|
1009
737
|
}
|