@agentxm/extension-authoring 0.28.12 → 0.28.13
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/src/adopt/adopt-extension.d.ts +71 -0
- package/dist/src/adopt/adopt-extension.js +174 -0
- package/dist/src/authored-declaration.d.ts +49 -0
- package/dist/src/authored-declaration.js +86 -0
- package/dist/src/authored-package-errors.d.ts +91 -0
- package/dist/src/authored-package-errors.js +36 -0
- package/dist/src/create/authoring-owner.d.ts +54 -0
- package/dist/src/create/authoring-owner.js +93 -0
- package/dist/src/create/create-extension.d.ts +127 -0
- package/dist/src/create/create-extension.js +440 -0
- package/dist/src/create/errors.d.ts +59 -0
- package/dist/src/create/errors.js +54 -0
- package/dist/src/create/scaffold-name.d.ts +15 -0
- package/dist/src/create/scaffold-name.js +16 -0
- package/dist/src/create/scaffolds/hook.d.ts +19 -0
- package/dist/src/create/scaffolds/hook.js +118 -0
- package/dist/src/create/scaffolds/knowledge.d.ts +14 -0
- package/dist/src/create/scaffolds/knowledge.js +45 -0
- package/dist/src/create/scaffolds/mcp-server.d.ts +17 -0
- package/dist/src/create/scaffolds/mcp-server.js +57 -0
- package/dist/src/create/scaffolds/pack.d.ts +13 -0
- package/dist/src/create/scaffolds/pack.js +37 -0
- package/dist/src/create/scaffolds/rule.d.ts +14 -0
- package/dist/src/create/scaffolds/rule.js +46 -0
- package/dist/src/create/scaffolds/scaffold.d.ts +51 -0
- package/dist/src/create/scaffolds/scaffold.js +45 -0
- package/dist/src/create/scaffolds/skill.d.ts +12 -0
- package/dist/src/create/scaffolds/skill.js +47 -0
- package/dist/src/create/scaffolds/subagent.d.ts +12 -0
- package/dist/src/create/scaffolds/subagent.js +47 -0
- package/dist/src/create-preflight.d.ts +3 -2
- package/dist/src/create-preflight.js +2 -1
- package/dist/src/errors.d.ts +1 -1
- package/dist/src/errors.js +1 -1
- package/dist/src/fork/fork-extension.d.ts +87 -0
- package/dist/src/fork/fork-extension.js +253 -0
- package/dist/src/fork-package.d.ts +2 -2
- package/dist/src/fork-package.js +4 -4
- package/dist/src/import/import-native-extension.d.ts +119 -0
- package/dist/src/import/import-native-extension.js +310 -0
- package/dist/src/import-native-package.d.ts +2 -2
- package/dist/src/import-native-package.js +4 -4
- package/dist/src/index.d.ts +20 -11
- package/dist/src/index.js +26 -13
- package/dist/src/packs/add-to-pack.d.ts +2 -2
- package/dist/src/packs/add-to-pack.js +4 -3
- package/dist/src/packs/change-pack-membership.d.ts +56 -0
- package/dist/src/packs/change-pack-membership.js +246 -0
- package/dist/src/packs/configured-pack-selector.d.ts +24 -0
- package/dist/src/packs/configured-pack-selector.js +53 -0
- package/dist/src/packs/glob.d.ts +14 -0
- package/dist/src/packs/glob.js +44 -0
- package/dist/src/packs/membership-errors.d.ts +122 -0
- package/dist/src/packs/membership-errors.js +47 -0
- package/dist/src/packs/remove-from-pack.d.ts +2 -2
- package/dist/src/packs/remove-from-pack.js +4 -3
- package/dist/src/step-failure.d.ts +31 -0
- package/dist/src/step-failure.js +253 -0
- package/dist/src/testing.d.ts +68 -0
- package/dist/src/testing.js +135 -0
- package/dist/src/version/change-authored-version.d.ts +73 -0
- package/dist/src/version/change-authored-version.js +224 -0
- package/dist/src/version/errors.d.ts +65 -0
- package/dist/src/version/errors.js +73 -0
- package/package.json +23 -8
- package/dist/src/desired-identity.d.ts +0 -19
- package/dist/src/desired-identity.js +0 -26
- package/dist/src/failure-adapter.d.ts +0 -31
- package/dist/src/failure-adapter.js +0 -23
- package/dist/src/hooks/new-hook.d.ts +0 -46
- package/dist/src/hooks/new-hook.js +0 -164
- package/dist/src/packs/new-pack.d.ts +0 -37
- package/dist/src/packs/new-pack.js +0 -90
- package/dist/src/skills/new-skill.d.ts +0 -38
- package/dist/src/skills/new-skill.js +0 -102
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Changing which extensions an authored pack declares.
|
|
3
|
+
*
|
|
4
|
+
* A pack's membership is a manifest an author owns, so both directions share
|
|
5
|
+
* one use case: find the pack the selector names, confirm the workspace
|
|
6
|
+
* authors it, read the manifest under a plan-time hash, decide which members
|
|
7
|
+
* the selector resolves to, and reduce that to a delta. An empty delta is a
|
|
8
|
+
* settled outcome, not a failure.
|
|
9
|
+
*
|
|
10
|
+
* @experimental This API is unstable and may change without notice.
|
|
11
|
+
*/
|
|
12
|
+
import * as Effect from "effect/Effect";
|
|
13
|
+
import * as FileSystem from "effect/FileSystem";
|
|
14
|
+
import * as Option from "effect/Option";
|
|
15
|
+
import * as Path from "effect/Path";
|
|
16
|
+
import * as Schema from "effect/Schema";
|
|
17
|
+
import { isCatalogExtensionType, } from "@agentxm/extension-model/unstable/extension-types";
|
|
18
|
+
import { decodeExtensionNameSync, formatFqn, parseExtensionFqnParts, } from "@agentxm/extension-model/unstable/extensions";
|
|
19
|
+
import { PACK_MANIFEST_FILENAME, PackManifestSchema, } from "@agentxm/extension-model/unstable/packs/manifest-schema";
|
|
20
|
+
import { isWorkspaceSourceLocator } from "@agentxm/extension-model/unstable/sources/workspace";
|
|
21
|
+
import { operationPresentation, prepareExecutionCandidate, resolveExecutionCandidate, } from "@agentxm/workspace-operations";
|
|
22
|
+
import { WorkspaceMutations, computePackPathsForLayout, configuredRowsByName, resolveWorkspaceExtensionRef, usableAcceptedCanonical, } from "@agentxm/workspace-state";
|
|
23
|
+
import { settingsRelativePath } from "../create/authoring-owner.js";
|
|
24
|
+
import { addToPack } from "./add-to-pack.js";
|
|
25
|
+
import { resolveConfiguredPackSelector } from "./configured-pack-selector.js";
|
|
26
|
+
import { hashContent } from "./hash-content.js";
|
|
27
|
+
import { isSelectorPattern, selectorMatches } from "./glob.js";
|
|
28
|
+
import { PackGraphInvalid, PackManifestUnavailable, PackMemberAmbiguous, PackMemberNotDeclared, PackMemberNotFound, PackMemberUnmanaged, PackNotAuthored, PackOwnerUnconfigured, PackSourceMissing, } from "./membership-errors.js";
|
|
29
|
+
import { removeFromPack } from "./remove-from-pack.js";
|
|
30
|
+
// -----------------------------------------------------------------------------
|
|
31
|
+
// Member candidates
|
|
32
|
+
// -----------------------------------------------------------------------------
|
|
33
|
+
/**
|
|
34
|
+
* Derive a lower-bound range from a resolved version.
|
|
35
|
+
*
|
|
36
|
+
* A lower bound tracks the latest published member while recording the
|
|
37
|
+
* version observed when the member was added. A caret would pin pre-1.0
|
|
38
|
+
* members to their current minor (`^0.4.2` stops before `0.5.0`), stranding
|
|
39
|
+
* every later release.
|
|
40
|
+
*/
|
|
41
|
+
const toVersionRange = (version) => `>=${version}`;
|
|
42
|
+
/** Every managed, versioned extension in the workspace a pack may depend on. */
|
|
43
|
+
const memberCandidates = Effect.fn("ChangePackMembership.memberCandidates")(function* () {
|
|
44
|
+
const ws = yield* WorkspaceMutations;
|
|
45
|
+
const graph = yield* ws.getDesiredStateGraph();
|
|
46
|
+
const candidates = [];
|
|
47
|
+
for (const node of graph.nodes) {
|
|
48
|
+
if (!isCatalogExtensionType(node.type))
|
|
49
|
+
continue;
|
|
50
|
+
if (node.source === undefined)
|
|
51
|
+
continue;
|
|
52
|
+
const ref = node.identity.startsWith("workspace:")
|
|
53
|
+
? yield* resolveWorkspaceExtensionRef({
|
|
54
|
+
settingsName: node.name,
|
|
55
|
+
source: node.source,
|
|
56
|
+
expectedType: node.type,
|
|
57
|
+
layout: ws.layout,
|
|
58
|
+
scope: ws.scope,
|
|
59
|
+
}).pipe(Effect.map(Option.some))
|
|
60
|
+
: yield* usableAcceptedCanonical({ workspace: ws, type: node.type, name: node.name }).pipe(Effect.map(Option.map((canonical) => canonical.ref)));
|
|
61
|
+
if (Option.isNone(ref) ||
|
|
62
|
+
(ref.value.refType !== "registry" && ref.value.refType !== "workspace")) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const acceptedIdentity = node.identity.startsWith("workspace:")
|
|
66
|
+
? node.identity.slice("workspace:".length)
|
|
67
|
+
: node.identity;
|
|
68
|
+
const parsed = parseExtensionFqnParts(acceptedIdentity);
|
|
69
|
+
if (parsed === undefined || parsed.type !== node.type)
|
|
70
|
+
continue;
|
|
71
|
+
const packageName = decodeExtensionNameSync(parsed.name);
|
|
72
|
+
candidates.push({
|
|
73
|
+
type: node.type,
|
|
74
|
+
name: node.name,
|
|
75
|
+
owner: parsed.owner,
|
|
76
|
+
packageName,
|
|
77
|
+
fqn: formatFqn({ owner: parsed.owner, type: node.type, name: packageName }),
|
|
78
|
+
versionRange: toVersionRange(ref.value.version),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return { graph, candidates };
|
|
82
|
+
});
|
|
83
|
+
// -----------------------------------------------------------------------------
|
|
84
|
+
// prepare
|
|
85
|
+
// -----------------------------------------------------------------------------
|
|
86
|
+
/** Settle a membership change without writing anything. */
|
|
87
|
+
export const preparePackMembership = Effect.fn("ChangePackMembership.prepare")(function* (request) {
|
|
88
|
+
const ws = yield* WorkspaceMutations;
|
|
89
|
+
const fs = yield* FileSystem.FileSystem;
|
|
90
|
+
const path = yield* Path.Path;
|
|
91
|
+
const configuredPacks = yield* ws.records
|
|
92
|
+
.rows("pack")
|
|
93
|
+
.pipe(Effect.map((rows) => Object.values(configuredRowsByName(rows))));
|
|
94
|
+
const configuredOwner = yield* ws.getConfiguredOwner();
|
|
95
|
+
const selection = yield* resolveConfiguredPackSelector({
|
|
96
|
+
configured: configuredPacks,
|
|
97
|
+
...(Option.isNone(configuredOwner) ? {} : { configuredOwner: configuredOwner.value }),
|
|
98
|
+
selector: request.pack,
|
|
99
|
+
});
|
|
100
|
+
const pack = selection.configuredName;
|
|
101
|
+
const source = selection.entry.source;
|
|
102
|
+
if (source === undefined)
|
|
103
|
+
return yield* new PackSourceMissing({ pack });
|
|
104
|
+
if (!isWorkspaceSourceLocator(source))
|
|
105
|
+
return yield* new PackNotAuthored({ pack });
|
|
106
|
+
if (Option.isNone(configuredOwner)) {
|
|
107
|
+
return yield* new PackOwnerUnconfigured({ pack, settingsPath: settingsRelativePath(path, ws) });
|
|
108
|
+
}
|
|
109
|
+
const packOwner = configuredOwner.value;
|
|
110
|
+
const manifestPath = path.join(computePackPathsForLayout(path.join, ws.layout, "workspace", packOwner, pack).canonicalPath, PACK_MANIFEST_FILENAME);
|
|
111
|
+
const manifestContent = yield* fs
|
|
112
|
+
.readFileString(manifestPath)
|
|
113
|
+
.pipe(Effect.mapError((cause) => new PackManifestUnavailable({ path: manifestPath, reason: "unreadable", cause })));
|
|
114
|
+
const manifestHash = hashContent(manifestContent);
|
|
115
|
+
const json = yield* Effect.try({
|
|
116
|
+
try: () => JSON.parse(manifestContent),
|
|
117
|
+
catch: (cause) => new PackManifestUnavailable({ path: manifestPath, reason: "unparsable", cause }),
|
|
118
|
+
});
|
|
119
|
+
const manifest = yield* Schema.decodeUnknownEffect(PackManifestSchema)(json).pipe(Effect.mapError((cause) => new PackManifestUnavailable({ path: manifestPath, reason: "invalid", cause })));
|
|
120
|
+
const pattern = isSelectorPattern(request.selector);
|
|
121
|
+
const members = yield* request.change === "add"
|
|
122
|
+
? additions({ pack, packOwner, request, pattern, manifest })
|
|
123
|
+
: removals({ manifest, request, pattern });
|
|
124
|
+
if (members.length === 0) {
|
|
125
|
+
const unchanged = { _tag: "NoChange", change: request.change, pack };
|
|
126
|
+
return unchanged;
|
|
127
|
+
}
|
|
128
|
+
const step = {
|
|
129
|
+
readiness: "ready",
|
|
130
|
+
label: pack,
|
|
131
|
+
run: request.change === "add"
|
|
132
|
+
? addToPack({
|
|
133
|
+
name: "add-to-pack",
|
|
134
|
+
args: {
|
|
135
|
+
packName: pack,
|
|
136
|
+
packOwner,
|
|
137
|
+
additions: Object.fromEntries(members.map((member) => [member.fqn, member.range])),
|
|
138
|
+
manifestHash,
|
|
139
|
+
},
|
|
140
|
+
})
|
|
141
|
+
: removeFromPack({
|
|
142
|
+
name: "remove-from-pack",
|
|
143
|
+
args: {
|
|
144
|
+
packName: pack,
|
|
145
|
+
packOwner,
|
|
146
|
+
removals: members.map((member) => member.fqn),
|
|
147
|
+
manifestHash,
|
|
148
|
+
},
|
|
149
|
+
}),
|
|
150
|
+
};
|
|
151
|
+
const memberCount = members.length;
|
|
152
|
+
const plan = {
|
|
153
|
+
_tag: "Plan",
|
|
154
|
+
name: packMembershipPlanName(request.change),
|
|
155
|
+
description: Option.some(request.change === "add"
|
|
156
|
+
? `Add ${memberCount} ${memberCount === 1 ? "extension" : "extensions"} to ${pack}`
|
|
157
|
+
: `Remove ${memberCount} ${memberCount === 1 ? "extension" : "extensions"} from ${pack}`),
|
|
158
|
+
presentation: operationPresentation(request.change === "add"
|
|
159
|
+
? { imperative: "add", past: "Added", gerund: "Adding" }
|
|
160
|
+
: { imperative: "remove", past: "Removed", gerund: "Removing" }, "pack"),
|
|
161
|
+
jobs: [{ concurrency: 1, steps: [step] }],
|
|
162
|
+
};
|
|
163
|
+
const change = {
|
|
164
|
+
_tag: "Change",
|
|
165
|
+
change: request.change,
|
|
166
|
+
pack,
|
|
167
|
+
members: members.map((member) => member.fqn),
|
|
168
|
+
execution: yield* prepareExecutionCandidate(plan),
|
|
169
|
+
};
|
|
170
|
+
return change;
|
|
171
|
+
});
|
|
172
|
+
const additions = Effect.fn("ChangePackMembership.additions")(function* (args) {
|
|
173
|
+
const { candidates, graph } = yield* memberCandidates();
|
|
174
|
+
const packFqn = formatFqn({
|
|
175
|
+
owner: args.packOwner,
|
|
176
|
+
type: "pack",
|
|
177
|
+
name: decodeExtensionNameSync(args.pack),
|
|
178
|
+
});
|
|
179
|
+
const targetPackProblems = graph.problems.filter((problem) => "pack" in problem && (problem.pack === packFqn || problem.pack === `workspace:${packFqn}`));
|
|
180
|
+
if (targetPackProblems.length > 0)
|
|
181
|
+
return yield* new PackGraphInvalid({ packFqn });
|
|
182
|
+
const requestedFqn = parseExtensionFqnParts(args.request.selector);
|
|
183
|
+
const matched = args.pattern
|
|
184
|
+
? candidates.filter((candidate) => selectorMatches(args.request.selector, candidate.name))
|
|
185
|
+
: requestedFqn !== undefined
|
|
186
|
+
? candidates.filter((candidate) => candidate.type === requestedFqn.type &&
|
|
187
|
+
candidate.owner === requestedFqn.owner &&
|
|
188
|
+
candidate.packageName === requestedFqn.name)
|
|
189
|
+
: candidates.filter((candidate) => candidate.name === args.request.selector);
|
|
190
|
+
// A bare name installed under more than one type is ambiguous: adding the
|
|
191
|
+
// wrong one would silently pin an extension the author did not mean.
|
|
192
|
+
if (!args.pattern && requestedFqn === undefined) {
|
|
193
|
+
const matchedTypes = [...new Set(matched.map((candidate) => candidate.type))];
|
|
194
|
+
if (matchedTypes.length > 1) {
|
|
195
|
+
return yield* new PackMemberAmbiguous({
|
|
196
|
+
selector: args.request.selector,
|
|
197
|
+
pack: args.pack,
|
|
198
|
+
matches: matched.map((candidate) => ({ type: candidate.type, fqn: candidate.fqn })),
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (matched.length === 0) {
|
|
203
|
+
if (args.pattern) {
|
|
204
|
+
return yield* new PackMemberNotFound({ selector: args.request.selector, pattern: true });
|
|
205
|
+
}
|
|
206
|
+
const installed = graph.nodes.some((node) => node.type !== "pack" && node.name === args.request.selector);
|
|
207
|
+
return yield* installed
|
|
208
|
+
? new PackMemberUnmanaged({ selector: args.request.selector })
|
|
209
|
+
: new PackMemberNotFound({ selector: args.request.selector, pattern: false });
|
|
210
|
+
}
|
|
211
|
+
const resolved = [];
|
|
212
|
+
for (const candidate of matched) {
|
|
213
|
+
if (args.manifest.dependencies[candidate.fqn] === candidate.versionRange)
|
|
214
|
+
continue;
|
|
215
|
+
resolved.push({ fqn: candidate.fqn, range: candidate.versionRange });
|
|
216
|
+
}
|
|
217
|
+
return resolved;
|
|
218
|
+
});
|
|
219
|
+
const removals = Effect.fn("ChangePackMembership.removals")(function* (args) {
|
|
220
|
+
const declared = Object.keys(args.manifest.dependencies);
|
|
221
|
+
const matched = args.pattern
|
|
222
|
+
? declared.filter((fqn) => selectorMatches(args.request.selector, fqn))
|
|
223
|
+
: declared.includes(args.request.selector)
|
|
224
|
+
? [args.request.selector]
|
|
225
|
+
: [];
|
|
226
|
+
if (matched.length === 0) {
|
|
227
|
+
return yield* new PackMemberNotDeclared({
|
|
228
|
+
selector: args.request.selector,
|
|
229
|
+
pattern: args.pattern,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
return matched.map((fqn) => ({ fqn, range: "" }));
|
|
233
|
+
});
|
|
234
|
+
/** The plan a membership change of this direction resolves. */
|
|
235
|
+
export const packMembershipPlanName = (change) => change === "add" ? "Add to pack" : "Remove from pack";
|
|
236
|
+
// -----------------------------------------------------------------------------
|
|
237
|
+
// previewOrApply
|
|
238
|
+
// -----------------------------------------------------------------------------
|
|
239
|
+
/** Preview or apply a settled membership change. */
|
|
240
|
+
export const previewOrApplyPackMembership = (candidate, execution) => resolveExecutionCandidate(candidate.execution, execution);
|
|
241
|
+
/** The pack-membership use case: settle a request, then preview or apply it. */
|
|
242
|
+
export const ChangePackMembership = {
|
|
243
|
+
prepare: preparePackMembership,
|
|
244
|
+
previewOrApply: previewOrApplyPackMembership,
|
|
245
|
+
};
|
|
246
|
+
//# sourceMappingURL=change-pack-membership.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which configured pack a selector names.
|
|
3
|
+
*
|
|
4
|
+
* A person edits a pack by the name their workspace configured it under, or
|
|
5
|
+
* by its owner-qualified identity. The local name wins when both could match,
|
|
6
|
+
* because that is the name the workspace itself uses.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
import * as Effect from "effect/Effect";
|
|
11
|
+
import type { ConfiguredRecordRow } from "@agentxm/workspace-state";
|
|
12
|
+
import { PackNotConfigured, PackSelectorAmbiguous, PackSelectorNotAPack } from "./membership-errors.js";
|
|
13
|
+
export interface ConfiguredPackSelection {
|
|
14
|
+
readonly configuredName: string;
|
|
15
|
+
readonly entry: ConfiguredRecordRow;
|
|
16
|
+
readonly match: "local-name" | "fqn";
|
|
17
|
+
}
|
|
18
|
+
export interface ResolveConfiguredPackSelectorArgs {
|
|
19
|
+
readonly configured: ReadonlyArray<ConfiguredRecordRow>;
|
|
20
|
+
readonly configuredOwner?: string;
|
|
21
|
+
readonly selector: string;
|
|
22
|
+
}
|
|
23
|
+
export declare const resolveConfiguredPackSelector: (args: ResolveConfiguredPackSelectorArgs) => Effect.Effect<ConfiguredPackSelection, PackSelectorNotAPack | PackNotConfigured | PackSelectorAmbiguous>;
|
|
24
|
+
//# sourceMappingURL=configured-pack-selector.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which configured pack a selector names.
|
|
3
|
+
*
|
|
4
|
+
* A person edits a pack by the name their workspace configured it under, or
|
|
5
|
+
* by its owner-qualified identity. The local name wins when both could match,
|
|
6
|
+
* because that is the name the workspace itself uses.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
import * as Effect from "effect/Effect";
|
|
11
|
+
import { parseRegistrySourcePatternParts, parseSourceQualifiedRegistrySourcePatternParts, } from "@agentxm/extension-model/unstable/extensions";
|
|
12
|
+
import { isWorkspaceSourceLocator } from "@agentxm/extension-model/unstable/sources/workspace";
|
|
13
|
+
import { PackNotConfigured, PackSelectorAmbiguous, PackSelectorNotAPack, } from "./membership-errors.js";
|
|
14
|
+
const configuredPackFqn = (entry, configuredOwner) => {
|
|
15
|
+
if (entry.source === undefined)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (entry.source === "registry" || isWorkspaceSourceLocator(entry.source)) {
|
|
18
|
+
return configuredOwner === undefined ? undefined : `${configuredOwner}/packs/${entry.name}`;
|
|
19
|
+
}
|
|
20
|
+
const parsed = parseSourceQualifiedRegistrySourcePatternParts(entry.source);
|
|
21
|
+
return parsed?.type === "packs" && parsed.name !== undefined
|
|
22
|
+
? `${parsed.owner}/packs/${parsed.name}`
|
|
23
|
+
: undefined;
|
|
24
|
+
};
|
|
25
|
+
export const resolveConfiguredPackSelector = (args) => {
|
|
26
|
+
const local = args.configured.find((entry) => entry.name === args.selector);
|
|
27
|
+
if (local !== undefined) {
|
|
28
|
+
return Effect.succeed({ configuredName: local.name, entry: local, match: "local-name" });
|
|
29
|
+
}
|
|
30
|
+
const parsed = parseRegistrySourcePatternParts(args.selector);
|
|
31
|
+
if (parsed?.type !== undefined && parsed.type !== "packs") {
|
|
32
|
+
return Effect.fail(new PackSelectorNotAPack({ selector: args.selector }));
|
|
33
|
+
}
|
|
34
|
+
if (parsed?.type !== "packs" || parsed.name === undefined || parsed.versionRange !== undefined) {
|
|
35
|
+
return Effect.fail(new PackNotConfigured({ selector: args.selector }));
|
|
36
|
+
}
|
|
37
|
+
const fqn = `${parsed.owner}/packs/${parsed.name}`;
|
|
38
|
+
const matches = args.configured.filter((entry) => configuredPackFqn(entry, args.configuredOwner) === fqn);
|
|
39
|
+
const [selected, ...rest] = matches;
|
|
40
|
+
if (selected === undefined) {
|
|
41
|
+
return Effect.fail(new PackNotConfigured({ selector: args.selector }));
|
|
42
|
+
}
|
|
43
|
+
if (rest.length > 0) {
|
|
44
|
+
return Effect.fail(new PackSelectorAmbiguous({
|
|
45
|
+
selector: args.selector,
|
|
46
|
+
configuredNames: matches
|
|
47
|
+
.map((entry) => entry.name)
|
|
48
|
+
.sort((left, right) => left.localeCompare(right)),
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
return Effect.succeed({ configuredName: selected.name, entry: selected, match: "fqn" });
|
|
52
|
+
};
|
|
53
|
+
//# sourceMappingURL=configured-pack-selector.js.map
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Matching a member selector that carries a `*` wildcard.
|
|
3
|
+
*
|
|
4
|
+
* Only `*` is a wildcard; every other character, `?` and `[` included, is a
|
|
5
|
+
* literal, so an owner-qualified identity matches itself. Matching is
|
|
6
|
+
* case-sensitive.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
/** Whether a selector carries a wildcard rather than naming one member. */
|
|
11
|
+
export declare const isSelectorPattern: (selector: string) => boolean;
|
|
12
|
+
/** Whether a selector matches this name. */
|
|
13
|
+
export declare const selectorMatches: (selector: string, name: string) => boolean;
|
|
14
|
+
//# sourceMappingURL=glob.d.ts.map
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Matching a member selector that carries a `*` wildcard.
|
|
3
|
+
*
|
|
4
|
+
* Only `*` is a wildcard; every other character, `?` and `[` included, is a
|
|
5
|
+
* literal, so an owner-qualified identity matches itself. Matching is
|
|
6
|
+
* case-sensitive.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
const matches = (pattern, name) => {
|
|
11
|
+
let patternIndex = 0;
|
|
12
|
+
let nameIndex = 0;
|
|
13
|
+
let wildcardIndex = -1;
|
|
14
|
+
let wildcardNameIndex = 0;
|
|
15
|
+
while (nameIndex < name.length) {
|
|
16
|
+
const token = pattern[patternIndex];
|
|
17
|
+
if (token !== undefined && token !== "*" && token === name[nameIndex]) {
|
|
18
|
+
patternIndex += 1;
|
|
19
|
+
nameIndex += 1;
|
|
20
|
+
}
|
|
21
|
+
else if (token === "*") {
|
|
22
|
+
wildcardIndex = patternIndex;
|
|
23
|
+
wildcardNameIndex = nameIndex;
|
|
24
|
+
patternIndex += 1;
|
|
25
|
+
}
|
|
26
|
+
else if (wildcardIndex >= 0) {
|
|
27
|
+
patternIndex = wildcardIndex + 1;
|
|
28
|
+
wildcardNameIndex += 1;
|
|
29
|
+
nameIndex = wildcardNameIndex;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
while (pattern[patternIndex] === "*") {
|
|
36
|
+
patternIndex += 1;
|
|
37
|
+
}
|
|
38
|
+
return patternIndex === pattern.length;
|
|
39
|
+
};
|
|
40
|
+
/** Whether a selector carries a wildcard rather than naming one member. */
|
|
41
|
+
export const isSelectorPattern = (selector) => selector.includes("*");
|
|
42
|
+
/** Whether a selector matches this name. */
|
|
43
|
+
export const selectorMatches = (selector, name) => matches(selector, name);
|
|
44
|
+
//# sourceMappingURL=glob.js.map
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed refusals for editing an authored pack's membership.
|
|
3
|
+
*
|
|
4
|
+
* Each one carries the facts the boundary needs to name a recovery — the
|
|
5
|
+
* selector that did not resolve, the packs it matched, the types a bare name
|
|
6
|
+
* is installed as — and none of them carries rendered prose.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
declare const PackSelectorNotAPack_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
11
|
+
readonly _tag: "PackSelectorNotAPack";
|
|
12
|
+
} & Readonly<A>;
|
|
13
|
+
/** The selector names an extension type other than a pack. */
|
|
14
|
+
export declare class PackSelectorNotAPack extends PackSelectorNotAPack_base<{
|
|
15
|
+
readonly selector: string;
|
|
16
|
+
}> {
|
|
17
|
+
}
|
|
18
|
+
declare const PackNotConfigured_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
19
|
+
readonly _tag: "PackNotConfigured";
|
|
20
|
+
} & Readonly<A>;
|
|
21
|
+
/** No configured pack answers to the selector. */
|
|
22
|
+
export declare class PackNotConfigured extends PackNotConfigured_base<{
|
|
23
|
+
readonly selector: string;
|
|
24
|
+
}> {
|
|
25
|
+
}
|
|
26
|
+
declare const PackSelectorAmbiguous_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
27
|
+
readonly _tag: "PackSelectorAmbiguous";
|
|
28
|
+
} & Readonly<A>;
|
|
29
|
+
/** More than one configured pack answers to the same identity. */
|
|
30
|
+
export declare class PackSelectorAmbiguous extends PackSelectorAmbiguous_base<{
|
|
31
|
+
readonly selector: string;
|
|
32
|
+
/** Configured local names that resolve to the selector, sorted. */
|
|
33
|
+
readonly configuredNames: ReadonlyArray<string>;
|
|
34
|
+
}> {
|
|
35
|
+
}
|
|
36
|
+
declare const PackSourceMissing_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
37
|
+
readonly _tag: "PackSourceMissing";
|
|
38
|
+
} & Readonly<A>;
|
|
39
|
+
/** The configured pack declares no source, so its authorship is unknown. */
|
|
40
|
+
export declare class PackSourceMissing extends PackSourceMissing_base<{
|
|
41
|
+
readonly pack: string;
|
|
42
|
+
}> {
|
|
43
|
+
}
|
|
44
|
+
declare const PackNotAuthored_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
45
|
+
readonly _tag: "PackNotAuthored";
|
|
46
|
+
} & Readonly<A>;
|
|
47
|
+
/** The pack resolves to a source this workspace does not author. */
|
|
48
|
+
export declare class PackNotAuthored extends PackNotAuthored_base<{
|
|
49
|
+
readonly pack: string;
|
|
50
|
+
}> {
|
|
51
|
+
}
|
|
52
|
+
declare const PackOwnerUnconfigured_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
53
|
+
readonly _tag: "PackOwnerUnconfigured";
|
|
54
|
+
} & Readonly<A>;
|
|
55
|
+
/** The pack is workspace-authored but the workspace records no owner. */
|
|
56
|
+
export declare class PackOwnerUnconfigured extends PackOwnerUnconfigured_base<{
|
|
57
|
+
readonly pack: string;
|
|
58
|
+
/** Workspace-relative settings file that records the owner. */
|
|
59
|
+
readonly settingsPath: string;
|
|
60
|
+
}> {
|
|
61
|
+
}
|
|
62
|
+
declare const PackManifestUnavailable_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
63
|
+
readonly _tag: "PackManifestUnavailable";
|
|
64
|
+
} & Readonly<A>;
|
|
65
|
+
/** The pack manifest could not be read, parsed, or decoded. */
|
|
66
|
+
export declare class PackManifestUnavailable extends PackManifestUnavailable_base<{
|
|
67
|
+
readonly path: string;
|
|
68
|
+
readonly reason: "unreadable" | "unparsable" | "invalid";
|
|
69
|
+
readonly cause: unknown;
|
|
70
|
+
}> {
|
|
71
|
+
}
|
|
72
|
+
declare const PackGraphInvalid_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
73
|
+
readonly _tag: "PackGraphInvalid";
|
|
74
|
+
} & Readonly<A>;
|
|
75
|
+
/** The desired-state graph reports problems with this exact pack. */
|
|
76
|
+
export declare class PackGraphInvalid extends PackGraphInvalid_base<{
|
|
77
|
+
readonly packFqn: string;
|
|
78
|
+
}> {
|
|
79
|
+
}
|
|
80
|
+
declare const PackMemberAmbiguous_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
81
|
+
readonly _tag: "PackMemberAmbiguous";
|
|
82
|
+
} & Readonly<A>;
|
|
83
|
+
/** A bare member name is installed under more than one extension type. */
|
|
84
|
+
export declare class PackMemberAmbiguous extends PackMemberAmbiguous_base<{
|
|
85
|
+
readonly selector: string;
|
|
86
|
+
readonly pack: string;
|
|
87
|
+
readonly matches: ReadonlyArray<{
|
|
88
|
+
readonly type: string;
|
|
89
|
+
readonly fqn: string;
|
|
90
|
+
}>;
|
|
91
|
+
}> {
|
|
92
|
+
}
|
|
93
|
+
declare const PackMemberUnmanaged_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
94
|
+
readonly _tag: "PackMemberUnmanaged";
|
|
95
|
+
} & Readonly<A>;
|
|
96
|
+
/** The named extension exists in the workspace but carries no resolved version. */
|
|
97
|
+
export declare class PackMemberUnmanaged extends PackMemberUnmanaged_base<{
|
|
98
|
+
readonly selector: string;
|
|
99
|
+
}> {
|
|
100
|
+
}
|
|
101
|
+
declare const PackMemberNotFound_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
102
|
+
readonly _tag: "PackMemberNotFound";
|
|
103
|
+
} & Readonly<A>;
|
|
104
|
+
/** Nothing in the workspace answers to the member selector. */
|
|
105
|
+
export declare class PackMemberNotFound extends PackMemberNotFound_base<{
|
|
106
|
+
readonly selector: string;
|
|
107
|
+
readonly pattern: boolean;
|
|
108
|
+
}> {
|
|
109
|
+
}
|
|
110
|
+
declare const PackMemberNotDeclared_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
111
|
+
readonly _tag: "PackMemberNotDeclared";
|
|
112
|
+
} & Readonly<A>;
|
|
113
|
+
/** Nothing in the pack manifest answers to the member selector. */
|
|
114
|
+
export declare class PackMemberNotDeclared extends PackMemberNotDeclared_base<{
|
|
115
|
+
readonly selector: string;
|
|
116
|
+
readonly pattern: boolean;
|
|
117
|
+
}> {
|
|
118
|
+
}
|
|
119
|
+
/** Every refusal the pack-membership use case constructs. */
|
|
120
|
+
export type PackMembershipError = PackSelectorNotAPack | PackNotConfigured | PackSelectorAmbiguous | PackSourceMissing | PackNotAuthored | PackOwnerUnconfigured | PackManifestUnavailable | PackGraphInvalid | PackMemberAmbiguous | PackMemberUnmanaged | PackMemberNotFound | PackMemberNotDeclared;
|
|
121
|
+
export {};
|
|
122
|
+
//# sourceMappingURL=membership-errors.d.ts.map
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed refusals for editing an authored pack's membership.
|
|
3
|
+
*
|
|
4
|
+
* Each one carries the facts the boundary needs to name a recovery — the
|
|
5
|
+
* selector that did not resolve, the packs it matched, the types a bare name
|
|
6
|
+
* is installed as — and none of them carries rendered prose.
|
|
7
|
+
*
|
|
8
|
+
* @experimental This API is unstable and may change without notice.
|
|
9
|
+
*/
|
|
10
|
+
import * as Data from "effect/Data";
|
|
11
|
+
/** The selector names an extension type other than a pack. */
|
|
12
|
+
export class PackSelectorNotAPack extends Data.TaggedError("PackSelectorNotAPack") {
|
|
13
|
+
}
|
|
14
|
+
/** No configured pack answers to the selector. */
|
|
15
|
+
export class PackNotConfigured extends Data.TaggedError("PackNotConfigured") {
|
|
16
|
+
}
|
|
17
|
+
/** More than one configured pack answers to the same identity. */
|
|
18
|
+
export class PackSelectorAmbiguous extends Data.TaggedError("PackSelectorAmbiguous") {
|
|
19
|
+
}
|
|
20
|
+
/** The configured pack declares no source, so its authorship is unknown. */
|
|
21
|
+
export class PackSourceMissing extends Data.TaggedError("PackSourceMissing") {
|
|
22
|
+
}
|
|
23
|
+
/** The pack resolves to a source this workspace does not author. */
|
|
24
|
+
export class PackNotAuthored extends Data.TaggedError("PackNotAuthored") {
|
|
25
|
+
}
|
|
26
|
+
/** The pack is workspace-authored but the workspace records no owner. */
|
|
27
|
+
export class PackOwnerUnconfigured extends Data.TaggedError("PackOwnerUnconfigured") {
|
|
28
|
+
}
|
|
29
|
+
/** The pack manifest could not be read, parsed, or decoded. */
|
|
30
|
+
export class PackManifestUnavailable extends Data.TaggedError("PackManifestUnavailable") {
|
|
31
|
+
}
|
|
32
|
+
/** The desired-state graph reports problems with this exact pack. */
|
|
33
|
+
export class PackGraphInvalid extends Data.TaggedError("PackGraphInvalid") {
|
|
34
|
+
}
|
|
35
|
+
/** A bare member name is installed under more than one extension type. */
|
|
36
|
+
export class PackMemberAmbiguous extends Data.TaggedError("PackMemberAmbiguous") {
|
|
37
|
+
}
|
|
38
|
+
/** The named extension exists in the workspace but carries no resolved version. */
|
|
39
|
+
export class PackMemberUnmanaged extends Data.TaggedError("PackMemberUnmanaged") {
|
|
40
|
+
}
|
|
41
|
+
/** Nothing in the workspace answers to the member selector. */
|
|
42
|
+
export class PackMemberNotFound extends Data.TaggedError("PackMemberNotFound") {
|
|
43
|
+
}
|
|
44
|
+
/** Nothing in the pack manifest answers to the member selector. */
|
|
45
|
+
export class PackMemberNotDeclared extends Data.TaggedError("PackMemberNotDeclared") {
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=membership-errors.js.map
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import * as FileSystem from "effect/FileSystem";
|
|
9
9
|
import * as Path from "effect/Path";
|
|
10
|
-
import { AuthoringFailureAdapter } from "../failure-adapter.js";
|
|
11
10
|
import type { Handle } from "@agentxm/extension-model/unstable/extensions";
|
|
12
11
|
import type { OperationHandler } from "@agentxm/workspace-operations";
|
|
13
12
|
import type { Operation } from "@agentxm/workspace-operations";
|
|
14
13
|
import { WorkspaceMutations } from "@agentxm/workspace-state";
|
|
14
|
+
import { WorkspaceTransactionScope } from "@agentxm/workspace-transactions";
|
|
15
15
|
/**
|
|
16
16
|
* Args for the remove-from-pack operation.
|
|
17
17
|
*/
|
|
@@ -40,5 +40,5 @@ export type RemoveFromPackOperation = Operation<"remove-from-pack", RemoveFromPa
|
|
|
40
40
|
* 4. Apply removals to manifest
|
|
41
41
|
* 5. Write updated manifest
|
|
42
42
|
*/
|
|
43
|
-
export declare const removeFromPack: OperationHandler<RemoveFromPackOperation, FileSystem.FileSystem | Path.Path | WorkspaceMutations |
|
|
43
|
+
export declare const removeFromPack: OperationHandler<RemoveFromPackOperation, FileSystem.FileSystem | Path.Path | WorkspaceMutations | WorkspaceTransactionScope>;
|
|
44
44
|
//# sourceMappingURL=remove-from-pack.d.ts.map
|
|
@@ -10,8 +10,9 @@ import * as Path from "effect/Path";
|
|
|
10
10
|
import * as Effect from "effect/Effect";
|
|
11
11
|
import * as Schema from "effect/Schema";
|
|
12
12
|
import { AuthoringFailed } from "../errors.js";
|
|
13
|
-
import {
|
|
13
|
+
import { authoringStepFailure } from "../step-failure.js";
|
|
14
14
|
import { WorkspaceMutations } from "@agentxm/workspace-state";
|
|
15
|
+
import { WorkspaceTransactionScope, runWorkspaceTransaction, } from "@agentxm/workspace-transactions";
|
|
15
16
|
import { isWorkspaceSourceLocator } from "@agentxm/extension-model/unstable/sources/workspace";
|
|
16
17
|
import { PACK_MANIFEST_FILENAME, PackManifestSchema, } from "@agentxm/extension-model/unstable/packs/manifest-schema";
|
|
17
18
|
import { packManifestArtifact } from "./artifact.js";
|
|
@@ -53,7 +54,7 @@ export const removeFromPack = (op) => Effect.gen(function* () {
|
|
|
53
54
|
}
|
|
54
55
|
// 2. Read current manifest
|
|
55
56
|
const manifestPath = path.join(ws.layout.authoredRoot("pack"), packName, PACK_MANIFEST_FILENAME);
|
|
56
|
-
yield*
|
|
57
|
+
yield* runWorkspaceTransaction({
|
|
57
58
|
targets: [manifestPath],
|
|
58
59
|
transition: Effect.gen(function* () {
|
|
59
60
|
const manifestContent = yield* fs.readFileString(manifestPath).pipe(Effect.mapError((e) => new AuthoringFailed({
|
|
@@ -141,5 +142,5 @@ export const removeFromPack = (op) => Effect.gen(function* () {
|
|
|
141
142
|
fileCount: 1,
|
|
142
143
|
}),
|
|
143
144
|
};
|
|
144
|
-
}).pipe(
|
|
145
|
+
}).pipe(Effect.mapError(authoringStepFailure));
|
|
145
146
|
//# sourceMappingURL=remove-from-pack.js.map
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How an authoring closure serializes a failure into the plan-step vocabulary.
|
|
3
|
+
*
|
|
4
|
+
* The feature owns this: an authoring step that failed must report the same
|
|
5
|
+
* category, sentence, and recovery whether the failure came from authoring's
|
|
6
|
+
* own policy, from the canonical-materialization machinery underneath it, or
|
|
7
|
+
* from the workspace transaction around it. Nothing is supplied by the
|
|
8
|
+
* application, so no authoring operation carries a failure adapter in its
|
|
9
|
+
* requirements.
|
|
10
|
+
*
|
|
11
|
+
* Categories and detail sentences are the serialized contract of machine
|
|
12
|
+
* output; they are reproduced here verbatim from the families that construct
|
|
13
|
+
* them.
|
|
14
|
+
*
|
|
15
|
+
* @experimental This API is unstable and may change without notice.
|
|
16
|
+
*/
|
|
17
|
+
import { StepFailure } from "@agentxm/workspace-operations";
|
|
18
|
+
import { NativeMcpEntryRetirementFailed, type ExtensionManagerFailure } from "@agentxm/extension-materialization";
|
|
19
|
+
import { AuthoringFailed } from "./errors.js";
|
|
20
|
+
import { type AuthoredPackageError } from "./authored-package-errors.js";
|
|
21
|
+
/** Every failure an authoring closure can settle a plan step with. */
|
|
22
|
+
export type AuthoringStepFailure = ExtensionManagerFailure | AuthoredPackageError | AuthoringFailed | NativeMcpEntryRetirementFailed | StepFailure;
|
|
23
|
+
/**
|
|
24
|
+
* Serialize one authoring-closure failure into the plan-step vocabulary.
|
|
25
|
+
*
|
|
26
|
+
* Families this feature or the machinery beneath it constructs are rendered
|
|
27
|
+
* exactly; families the kernel already serializes are delegated to it; and
|
|
28
|
+
* anything else carries its producer's own category and sentence through.
|
|
29
|
+
*/
|
|
30
|
+
export declare const authoringStepFailure: (failure: AuthoringStepFailure) => StepFailure;
|
|
31
|
+
//# sourceMappingURL=step-failure.d.ts.map
|