@ninemind/agentgem 0.1.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.
@@ -0,0 +1,518 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ // src/gem.controller.ts
3
+ import { existsSync } from "node:fs";
4
+ import { basename } from "node:path";
5
+ import { api, get, post } from "@agentback/openapi";
6
+ import { introspectConfig, introspectProject } from "./gem/introspect.js";
7
+ import { buildGem } from "./gem/buildGem.js";
8
+ import { scaffoldChecks } from "./gem/checks.js";
9
+ import { materialize, compatibility } from "./gem/targets.js";
10
+ import { DEPLOY_REGISTRY, deployTargetList } from "./gem/deploy.js";
11
+ import { createWorkspace, listWorkspaces, readWorkspace, renderTarget, deleteWorkspace } from "./gem/workspaces.js";
12
+ import { writeGemArchive, readGemArchive } from "./gem/archive.js";
13
+ import { writeArchiveDir, readArchiveDir } from "./gem/archiveFs.js";
14
+ import { packTar } from "./gem/archiveTar.js";
15
+ import { readDeployRecord, writeDeployRecord, clearDeployRecord } from "./gem/deployRecord.js";
16
+ import { undeployManagedAgent, anthropicPublishClient } from "./publish.js";
17
+ import { undeployAgentcoreHarness, realAgentcoreControlClient } from "./gem/agentcorePublish.js";
18
+ import { InventorySchema, GemSchema, GemRequestSchema, DirQuerySchema, PickQuerySchema, PickFolderSchema, ScaffoldChecksRequestSchema, ScaffoldChecksResponseSchema, MaterializeRequestSchema, MaterializeResponseSchema, PublishPreviewRequestSchema, PublishRequestSchema, PublishPreviewResponseSchema, PublishReadyResponseSchema, PublishResultSchema, DeployTargetsResponseSchema, DeployReadyQuerySchema, ArchiveRequestSchema, ArchiveResponseSchema, CreateWorkspaceRequestSchema, WorkspaceQuerySchema, RenderRequestSchema, WorkspaceNameRequestSchema, WorkspaceSummarySchema, WorkspaceDetailSchema, RenderResultSchema, ListWorkspacesResponseSchema, DeleteWorkspaceResponseSchema, RunReadyQuerySchema, RunReadyResponseSchema, RunRequestSchema, RunStatusQuerySchema, RunStateSchema, RunStopRequestSchema, RunStopResponseSchema, CredentialRequestSchema, CredentialResponseSchema, TestbedDetectQuerySchema, TestbedDetectResponseSchema, TestbedSuggestionQuerySchema, TestbedSuggestionResponseSchema, TestbedRecentsResponseSchema, TestbedProjectsQuerySchema, TestbedProjectsResponseSchema, TestbedScaffoldRequestSchema, TestbedScaffoldResponseSchema, TestbedImportRequestSchema, TestbedImportResponseSchema, AgentcoreReadyResponseSchema, AgentcoreDeployRequestSchema, AgentcoreStatusQuerySchema, AgentcoreDeployStateSchema, RegistryReadyResponseSchema, RegistryIndexResponseSchema, RegistryResolveRequestSchema, RegistryResolveResponseSchema, RegistryInstallRequestSchema, RegistryInstallResponseSchema, RegistryPublishRequestSchema, RegistryPublishResponseSchema, UndeployRequestSchema, UndeployResponseSchema, DeployRecordQuerySchema, DeployRecordResponseSchema, } from "./schemas.js";
19
+ import { runReadiness, startLocal, stopLocal, getRunStatus, deployVercel, deployCloudflare, undeployVercel, undeployCloudflare } from "./gem/run.js";
20
+ import { setCredential } from "./gem/credentials.js";
21
+ import { agentcoreReadiness, deployAgentcore, getAgentcoreStatus } from "./gem/agentcoreRun.js";
22
+ import { scaffoldTestbed, importArtifacts } from "./gem/testbed.js";
23
+ import { detectFlavor, suggestTestbed, discoverProjects } from "./gem/testbedFlavors.js";
24
+ import { readRecents, upsertRecent } from "./gem/recents.js";
25
+ import { resolveInstall, publishGem } from "./gem/registry.js";
26
+ import { githubRegistrySource, githubRegistryPublisher, registryConfigFromEnv, registryReady } from "./gem/registryGithub.js";
27
+ import { resolveDirs, resolveProject, agentgemHome } from "./resolveDir.js";
28
+ import { pickFolder } from "./pickFolder.js";
29
+ let GemController = class GemController {
30
+ async inventory(input) {
31
+ return introspectAll(input.query.dir, parseProjectsQuery(input.query.projects));
32
+ }
33
+ async gem(input) {
34
+ const dirs = resolveDirs(input.body.dir);
35
+ const inventory = introspectAll(input.body.dir, input.body.projects);
36
+ return buildGem(inventory, input.body.selection, {
37
+ name: input.body.name ?? "gem",
38
+ createdFrom: dirs.claudeDir,
39
+ checks: input.body.checks,
40
+ });
41
+ }
42
+ async scaffoldChecks(input) {
43
+ const dirs = resolveDirs(input.body.dir);
44
+ const inventory = introspectAll(input.body.dir, input.body.projects);
45
+ const gem = buildGem(inventory, input.body.selection, { name: input.body.name ?? "gem", createdFrom: dirs.claudeDir });
46
+ return { checks: scaffoldChecks(gem) };
47
+ }
48
+ async materialize(input) {
49
+ const target = input.body.target;
50
+ let gem;
51
+ if (input.body.archivePath) {
52
+ gem = readGemArchive(readArchiveDir(input.body.archivePath));
53
+ }
54
+ else {
55
+ const dirs = resolveDirs(input.body.dir);
56
+ const inventory = introspectAll(input.body.dir, input.body.projects);
57
+ gem = buildGem(inventory, input.body.selection, { name: input.body.name ?? "gem", createdFrom: dirs.claudeDir });
58
+ }
59
+ return { target, ...materialize(gem, target), compatibility: compatibility(gem) };
60
+ }
61
+ async archive(input) {
62
+ const dirs = resolveDirs(input.body.dir);
63
+ const inventory = introspectAll(input.body.dir, input.body.projects);
64
+ const gem = buildGem(inventory, input.body.selection, { name: input.body.name ?? "gem", createdFrom: dirs.claudeDir });
65
+ const { files, skipped } = writeGemArchive(gem, { version: input.body.version });
66
+ const lock = JSON.parse(files["gem.lock"]);
67
+ let path = null;
68
+ if (input.body.outDir) {
69
+ writeArchiveDir(input.body.outDir, files);
70
+ path = input.body.outDir;
71
+ }
72
+ const tarGz = input.body.tar ? packTar(files).toString("base64") : null;
73
+ return { files, lock, skipped, path, tarGz };
74
+ }
75
+ async createWorkspace(input) {
76
+ const dirs = resolveDirs(input.body.dir);
77
+ const inventory = introspectAll(input.body.dir, input.body.projects);
78
+ const gem = buildGem(inventory, input.body.selection, { name: input.body.name, createdFrom: dirs.claudeDir });
79
+ return createWorkspace(input.body.name, gem, { version: input.body.version });
80
+ }
81
+ async listWorkspaces(_input) {
82
+ return { workspaces: listWorkspaces() };
83
+ }
84
+ async readWorkspace(input) {
85
+ return readWorkspace(input.query.name);
86
+ }
87
+ async renderWorkspace(input) {
88
+ return renderTarget(input.body.name, input.body.target);
89
+ }
90
+ async deleteWorkspace(input) {
91
+ deleteWorkspace(input.body.name);
92
+ return { deleted: input.body.name };
93
+ }
94
+ // Whether the server is configured to run/deploy the rendered eve project. Booleans only.
95
+ async runReady(_input) {
96
+ return runReadiness();
97
+ }
98
+ // OUTWARD-FACING (local machine): set + persist a server-side deploy/publish credential
99
+ // (allowlisted keys only) to ~/.agentgem/.env. The value is never logged or returned.
100
+ async credential(input) {
101
+ setCredential(input.body.key, input.body.value);
102
+ return { ok: true };
103
+ }
104
+ // OUTWARD-FACING (local machine): run the rendered eve project locally or deploy it to Vercel.
105
+ async run(input) {
106
+ const { name, mode } = input.body;
107
+ const state = mode === "cloudflare" ? await deployCloudflare(name) : mode === "vercel" ? await deployVercel(name, undefined, { eveAuth: input.body.eveAuth }) : await startLocal(name);
108
+ return state;
109
+ }
110
+ async runStatus(input) {
111
+ return getRunStatus(input.query.name, input.query.target);
112
+ }
113
+ async runStop(input) {
114
+ return stopLocal(input.body.name, input.body.target);
115
+ }
116
+ async agentcoreDeployReady(_input) {
117
+ return agentcoreReadiness();
118
+ }
119
+ // OUTWARD-FACING: shells the agentcore CLI to deploy the workspace's rendered project to AWS.
120
+ async agentcoreDeploy(input) {
121
+ return deployAgentcore(input.body.name);
122
+ }
123
+ async agentcoreDeployStatus(input) {
124
+ return getAgentcoreStatus(input.query.name);
125
+ }
126
+ async deployTargets(_input) {
127
+ return { targets: deployTargetList() };
128
+ }
129
+ // Offline render of the deploy payload + skip/secret/skill lists. No network.
130
+ async publishPreview(input) {
131
+ const dirs = resolveDirs(input.body.dir);
132
+ const inventory = introspectAll(input.body.dir, input.body.projects);
133
+ const gem = buildGem(inventory, input.body.selection, { name: input.body.name ?? "gem", createdFrom: dirs.claudeDir });
134
+ const target = (input.body.target ?? "claude-managed");
135
+ return DEPLOY_REGISTRY[target].preview(gem);
136
+ }
137
+ // Whether the server is configured for the deploy backend (the UI gates on this). Boolean only.
138
+ async publishReady(input) {
139
+ const target = (input.query.target ?? "claude-managed");
140
+ return { ready: DEPLOY_REGISTRY[target].ready() };
141
+ }
142
+ // OUTWARD-FACING: gated network deploy through the selected backend. The key is read server-side
143
+ // (inside the registry's deploy) and never returned; only the redacted gem payload is sent.
144
+ async publish(input) {
145
+ const dirs = resolveDirs(input.body.dir);
146
+ const inventory = introspectAll(input.body.dir, input.body.projects);
147
+ const gem = buildGem(inventory, input.body.selection, { name: input.body.name ?? "gem", createdFrom: dirs.claudeDir });
148
+ const target = (input.body.target ?? "claude-managed");
149
+ const result = await DEPLOY_REGISTRY[target].deploy(gem, input.body.requestId);
150
+ if (input.body.wsName) {
151
+ const at = new Date().toISOString();
152
+ if (result.kind === "managed-agent") {
153
+ writeDeployRecord(input.body.wsName, {
154
+ backend: "claude-managed", at,
155
+ agentId: result.agentId, environmentId: result.environmentId,
156
+ skillIds: result.registeredSkills.map((s) => s.skillId),
157
+ });
158
+ }
159
+ else if (result.kind === "agentcore-harness") {
160
+ writeDeployRecord(input.body.wsName, { backend: "agentcore", at, harnessId: result.harnessId });
161
+ }
162
+ }
163
+ return result;
164
+ }
165
+ async undeploy(input) {
166
+ const { name, target } = input.body;
167
+ if (target === "eve") {
168
+ const r = await undeployVercel(name);
169
+ if (!r.removed)
170
+ throw new Error(`Vercel undeploy failed for "${name}". Check logs.`);
171
+ return { removed: true, logTail: r.logTail };
172
+ }
173
+ if (target === "flue") {
174
+ const r = await undeployCloudflare(name);
175
+ if (!r.removed)
176
+ throw new Error(`Cloudflare undeploy failed for "${name}". Check logs.`);
177
+ return { removed: true, logTail: r.logTail };
178
+ }
179
+ if (target === "claude-managed") {
180
+ const key = process.env.ANTHROPIC_API_KEY;
181
+ if (!key)
182
+ throw new Error("ANTHROPIC_API_KEY is not set — cannot undeploy from Claude Managed Agents.");
183
+ const rec = readDeployRecord(name, "claude-managed");
184
+ if (!rec)
185
+ throw new Error(`No claude-managed deploy record for workspace "${name}".`);
186
+ await undeployManagedAgent(rec, anthropicPublishClient(key));
187
+ clearDeployRecord(name, "claude-managed");
188
+ return { removed: true };
189
+ }
190
+ // agentcore
191
+ const rec = readDeployRecord(name, "agentcore");
192
+ if (!rec)
193
+ throw new Error(`No agentcore deploy record for workspace "${name}".`);
194
+ await undeployAgentcoreHarness(rec, realAgentcoreControlClient());
195
+ clearDeployRecord(name, "agentcore");
196
+ return { removed: true };
197
+ }
198
+ async deployRecord(input) {
199
+ const rec = readDeployRecord(input.query.name, input.query.backend);
200
+ return { record: rec };
201
+ }
202
+ async testbedDetect(input) {
203
+ return { flavor: detectFlavor(resolveProject(input.query.root)) };
204
+ }
205
+ async testbedSuggestion(input) {
206
+ const cwd = resolveProject(input.query.cwd ?? process.cwd());
207
+ const { looksLikeProject, flavor } = suggestTestbed(cwd);
208
+ return { cwd, looksLikeProject, flavor, name: basename(cwd) };
209
+ }
210
+ async testbedRecents(_input) {
211
+ const recents = readRecents(agentgemHome()).map((r) => ({ ...r, exists: existsSync(r.path) }));
212
+ return { recents };
213
+ }
214
+ // Cross-repo discovery from Claude/Codex session history. Ungated — the front door
215
+ // shows these under a "Discovered" section beneath the user's own recents.
216
+ async testbedProjects(input) {
217
+ return { projects: discoverProjects(resolveDirs(input.query.dir)) };
218
+ }
219
+ async scaffoldTestbed(input) {
220
+ const root = resolveProject(input.body.root);
221
+ const flavor = (input.body.flavor ?? "claude");
222
+ const res = scaffoldTestbed(root, input.body.name, flavor);
223
+ upsertRecent(agentgemHome(), { path: root, flavor, name: input.body.name });
224
+ return res;
225
+ }
226
+ async importTestbed(input) {
227
+ const rawInv = introspectConfig({ ...resolveDirs(input.body.dir), redact: false });
228
+ return importArtifacts(resolveProject(input.body.root), input.body.selection, rawInv, (input.body.flavor ?? "claude"));
229
+ }
230
+ // Resolve the configured registry source, or throw a clear error the UI can surface.
231
+ registrySource() {
232
+ const cfg = registryConfigFromEnv();
233
+ if (!cfg)
234
+ throw new Error("the registry is not configured — set AGENTGEM_REGISTRY_REPO");
235
+ return { cfg, source: githubRegistrySource(cfg) };
236
+ }
237
+ async registryReady(_input) {
238
+ return { ready: registryReady() };
239
+ }
240
+ async registryIndex(_input) {
241
+ return this.registrySource().source.getIndex();
242
+ }
243
+ async registryResolve(input) {
244
+ const { source } = this.registrySource();
245
+ const { plan } = await resolveInstall({ refs: input.body.refs, mode: input.body.mode, target: input.body.target, source });
246
+ return { plan };
247
+ }
248
+ // Apply: materialize into `dest`, or land the merged Gem in the workspace store.
249
+ async registryInstall(input) {
250
+ const { source } = this.registrySource();
251
+ const { plan, gem } = await resolveInstall({ refs: input.body.refs, mode: input.body.mode, target: input.body.target, source });
252
+ if (input.body.mode === "materialize") {
253
+ if (!input.body.dest)
254
+ throw new Error("materialize mode requires `dest`");
255
+ writeArchiveDir(input.body.dest, plan.materialize.files);
256
+ return { plan, applied: { mode: "materialize", dest: input.body.dest, written: Object.keys(plan.materialize.files) } };
257
+ }
258
+ const name = input.body.workspaceName ?? gem.name;
259
+ createWorkspace(name, gem);
260
+ return { plan, applied: { mode: "workspace", workspace: name } };
261
+ }
262
+ // OUTWARD-FACING: gated network publish. Reads a Gem from the workspace, writes its archive +
263
+ // updated index in one commit. Requires GITHUB_TOKEN (enforced by the publisher).
264
+ async registryPublish(input) {
265
+ const { cfg, source } = this.registrySource();
266
+ const gem = readGemArchive(readWorkspace(input.body.workspace).files); // WorkspaceDetail exposes .files, not .gem
267
+ const index = await source.getIndex();
268
+ return publishGem({
269
+ gem, scope: input.body.scope, name: input.body.name, version: input.body.version,
270
+ dependencies: input.body.dependencies, index, publisher: githubRegistryPublisher(cfg),
271
+ });
272
+ }
273
+ // Pop the OS-native folder picker and return the chosen absolute path (null if cancelled).
274
+ async pickFolder(_input) {
275
+ return { path: await pickFolder() };
276
+ }
277
+ };
278
+ __decorate([
279
+ get("/inventory", { query: DirQuerySchema, response: InventorySchema }),
280
+ __metadata("design:type", Function),
281
+ __metadata("design:paramtypes", [Object]),
282
+ __metadata("design:returntype", Promise)
283
+ ], GemController.prototype, "inventory", null);
284
+ __decorate([
285
+ post("/gem", { body: GemRequestSchema, response: GemSchema }),
286
+ __metadata("design:type", Function),
287
+ __metadata("design:paramtypes", [Object]),
288
+ __metadata("design:returntype", Promise)
289
+ ], GemController.prototype, "gem", null);
290
+ __decorate([
291
+ post("/scaffold-checks", { body: ScaffoldChecksRequestSchema, response: ScaffoldChecksResponseSchema }),
292
+ __metadata("design:type", Function),
293
+ __metadata("design:paramtypes", [Object]),
294
+ __metadata("design:returntype", Promise)
295
+ ], GemController.prototype, "scaffoldChecks", null);
296
+ __decorate([
297
+ post("/materialize", { body: MaterializeRequestSchema, response: MaterializeResponseSchema }),
298
+ __metadata("design:type", Function),
299
+ __metadata("design:paramtypes", [Object]),
300
+ __metadata("design:returntype", Promise)
301
+ ], GemController.prototype, "materialize", null);
302
+ __decorate([
303
+ post("/archive", { body: ArchiveRequestSchema, response: ArchiveResponseSchema }),
304
+ __metadata("design:type", Function),
305
+ __metadata("design:paramtypes", [Object]),
306
+ __metadata("design:returntype", Promise)
307
+ ], GemController.prototype, "archive", null);
308
+ __decorate([
309
+ post("/workspaces", { body: CreateWorkspaceRequestSchema, response: WorkspaceSummarySchema }),
310
+ __metadata("design:type", Function),
311
+ __metadata("design:paramtypes", [Object]),
312
+ __metadata("design:returntype", Promise)
313
+ ], GemController.prototype, "createWorkspace", null);
314
+ __decorate([
315
+ get("/workspaces", { query: PickQuerySchema, response: ListWorkspacesResponseSchema }),
316
+ __metadata("design:type", Function),
317
+ __metadata("design:paramtypes", [Object]),
318
+ __metadata("design:returntype", Promise)
319
+ ], GemController.prototype, "listWorkspaces", null);
320
+ __decorate([
321
+ get("/workspace", { query: WorkspaceQuerySchema, response: WorkspaceDetailSchema }),
322
+ __metadata("design:type", Function),
323
+ __metadata("design:paramtypes", [Object]),
324
+ __metadata("design:returntype", Promise)
325
+ ], GemController.prototype, "readWorkspace", null);
326
+ __decorate([
327
+ post("/workspace/render", { body: RenderRequestSchema, response: RenderResultSchema }),
328
+ __metadata("design:type", Function),
329
+ __metadata("design:paramtypes", [Object]),
330
+ __metadata("design:returntype", Promise)
331
+ ], GemController.prototype, "renderWorkspace", null);
332
+ __decorate([
333
+ post("/workspace/delete", { body: WorkspaceNameRequestSchema, response: DeleteWorkspaceResponseSchema }),
334
+ __metadata("design:type", Function),
335
+ __metadata("design:paramtypes", [Object]),
336
+ __metadata("design:returntype", Promise)
337
+ ], GemController.prototype, "deleteWorkspace", null);
338
+ __decorate([
339
+ get("/run-ready", { query: RunReadyQuerySchema, response: RunReadyResponseSchema }),
340
+ __metadata("design:type", Function),
341
+ __metadata("design:paramtypes", [Object]),
342
+ __metadata("design:returntype", Promise)
343
+ ], GemController.prototype, "runReady", null);
344
+ __decorate([
345
+ post("/credential", { body: CredentialRequestSchema, response: CredentialResponseSchema }),
346
+ __metadata("design:type", Function),
347
+ __metadata("design:paramtypes", [Object]),
348
+ __metadata("design:returntype", Promise)
349
+ ], GemController.prototype, "credential", null);
350
+ __decorate([
351
+ post("/run", { body: RunRequestSchema, response: RunStateSchema }),
352
+ __metadata("design:type", Function),
353
+ __metadata("design:paramtypes", [Object]),
354
+ __metadata("design:returntype", Promise)
355
+ ], GemController.prototype, "run", null);
356
+ __decorate([
357
+ get("/run-status", { query: RunStatusQuerySchema, response: RunStateSchema }),
358
+ __metadata("design:type", Function),
359
+ __metadata("design:paramtypes", [Object]),
360
+ __metadata("design:returntype", Promise)
361
+ ], GemController.prototype, "runStatus", null);
362
+ __decorate([
363
+ post("/run/stop", { body: RunStopRequestSchema, response: RunStopResponseSchema }),
364
+ __metadata("design:type", Function),
365
+ __metadata("design:paramtypes", [Object]),
366
+ __metadata("design:returntype", Promise)
367
+ ], GemController.prototype, "runStop", null);
368
+ __decorate([
369
+ get("/agentcore/deploy-ready", { query: PickQuerySchema, response: AgentcoreReadyResponseSchema }),
370
+ __metadata("design:type", Function),
371
+ __metadata("design:paramtypes", [Object]),
372
+ __metadata("design:returntype", Promise)
373
+ ], GemController.prototype, "agentcoreDeployReady", null);
374
+ __decorate([
375
+ post("/agentcore/deploy", { body: AgentcoreDeployRequestSchema, response: AgentcoreDeployStateSchema }),
376
+ __metadata("design:type", Function),
377
+ __metadata("design:paramtypes", [Object]),
378
+ __metadata("design:returntype", Promise)
379
+ ], GemController.prototype, "agentcoreDeploy", null);
380
+ __decorate([
381
+ get("/agentcore/deploy-status", { query: AgentcoreStatusQuerySchema, response: AgentcoreDeployStateSchema }),
382
+ __metadata("design:type", Function),
383
+ __metadata("design:paramtypes", [Object]),
384
+ __metadata("design:returntype", Promise)
385
+ ], GemController.prototype, "agentcoreDeployStatus", null);
386
+ __decorate([
387
+ get("/deploy-targets", { query: PickQuerySchema, response: DeployTargetsResponseSchema }),
388
+ __metadata("design:type", Function),
389
+ __metadata("design:paramtypes", [Object]),
390
+ __metadata("design:returntype", Promise)
391
+ ], GemController.prototype, "deployTargets", null);
392
+ __decorate([
393
+ post("/publish-preview", { body: PublishPreviewRequestSchema, response: PublishPreviewResponseSchema }),
394
+ __metadata("design:type", Function),
395
+ __metadata("design:paramtypes", [Object]),
396
+ __metadata("design:returntype", Promise)
397
+ ], GemController.prototype, "publishPreview", null);
398
+ __decorate([
399
+ get("/publish-ready", { query: DeployReadyQuerySchema, response: PublishReadyResponseSchema }),
400
+ __metadata("design:type", Function),
401
+ __metadata("design:paramtypes", [Object]),
402
+ __metadata("design:returntype", Promise)
403
+ ], GemController.prototype, "publishReady", null);
404
+ __decorate([
405
+ post("/publish", { body: PublishRequestSchema, response: PublishResultSchema }),
406
+ __metadata("design:type", Function),
407
+ __metadata("design:paramtypes", [Object]),
408
+ __metadata("design:returntype", Promise)
409
+ ], GemController.prototype, "publish", null);
410
+ __decorate([
411
+ post("/undeploy", { body: UndeployRequestSchema, response: UndeployResponseSchema }),
412
+ __metadata("design:type", Function),
413
+ __metadata("design:paramtypes", [Object]),
414
+ __metadata("design:returntype", Promise)
415
+ ], GemController.prototype, "undeploy", null);
416
+ __decorate([
417
+ get("/deploy-record", { query: DeployRecordQuerySchema, response: DeployRecordResponseSchema }),
418
+ __metadata("design:type", Function),
419
+ __metadata("design:paramtypes", [Object]),
420
+ __metadata("design:returntype", Promise)
421
+ ], GemController.prototype, "deployRecord", null);
422
+ __decorate([
423
+ get("/testbed/detect", { query: TestbedDetectQuerySchema, response: TestbedDetectResponseSchema }),
424
+ __metadata("design:type", Function),
425
+ __metadata("design:paramtypes", [Object]),
426
+ __metadata("design:returntype", Promise)
427
+ ], GemController.prototype, "testbedDetect", null);
428
+ __decorate([
429
+ get("/testbed/suggestion", { query: TestbedSuggestionQuerySchema, response: TestbedSuggestionResponseSchema }),
430
+ __metadata("design:type", Function),
431
+ __metadata("design:paramtypes", [Object]),
432
+ __metadata("design:returntype", Promise)
433
+ ], GemController.prototype, "testbedSuggestion", null);
434
+ __decorate([
435
+ get("/testbed/recents", { query: PickQuerySchema, response: TestbedRecentsResponseSchema }),
436
+ __metadata("design:type", Function),
437
+ __metadata("design:paramtypes", [Object]),
438
+ __metadata("design:returntype", Promise)
439
+ ], GemController.prototype, "testbedRecents", null);
440
+ __decorate([
441
+ get("/testbed/projects", { query: TestbedProjectsQuerySchema, response: TestbedProjectsResponseSchema }),
442
+ __metadata("design:type", Function),
443
+ __metadata("design:paramtypes", [Object]),
444
+ __metadata("design:returntype", Promise)
445
+ ], GemController.prototype, "testbedProjects", null);
446
+ __decorate([
447
+ post("/testbed/scaffold", { body: TestbedScaffoldRequestSchema, response: TestbedScaffoldResponseSchema }),
448
+ __metadata("design:type", Function),
449
+ __metadata("design:paramtypes", [Object]),
450
+ __metadata("design:returntype", Promise)
451
+ ], GemController.prototype, "scaffoldTestbed", null);
452
+ __decorate([
453
+ post("/testbed/import", { body: TestbedImportRequestSchema, response: TestbedImportResponseSchema }),
454
+ __metadata("design:type", Function),
455
+ __metadata("design:paramtypes", [Object]),
456
+ __metadata("design:returntype", Promise)
457
+ ], GemController.prototype, "importTestbed", null);
458
+ __decorate([
459
+ get("/registry/ready", { query: PickQuerySchema, response: RegistryReadyResponseSchema }),
460
+ __metadata("design:type", Function),
461
+ __metadata("design:paramtypes", [Object]),
462
+ __metadata("design:returntype", Promise)
463
+ ], GemController.prototype, "registryReady", null);
464
+ __decorate([
465
+ get("/registry/index", { query: PickQuerySchema, response: RegistryIndexResponseSchema }),
466
+ __metadata("design:type", Function),
467
+ __metadata("design:paramtypes", [Object]),
468
+ __metadata("design:returntype", Promise)
469
+ ], GemController.prototype, "registryIndex", null);
470
+ __decorate([
471
+ post("/registry/resolve", { body: RegistryResolveRequestSchema, response: RegistryResolveResponseSchema }),
472
+ __metadata("design:type", Function),
473
+ __metadata("design:paramtypes", [Object]),
474
+ __metadata("design:returntype", Promise)
475
+ ], GemController.prototype, "registryResolve", null);
476
+ __decorate([
477
+ post("/registry/install", { body: RegistryInstallRequestSchema, response: RegistryInstallResponseSchema }),
478
+ __metadata("design:type", Function),
479
+ __metadata("design:paramtypes", [Object]),
480
+ __metadata("design:returntype", Promise)
481
+ ], GemController.prototype, "registryInstall", null);
482
+ __decorate([
483
+ post("/registry/publish", { body: RegistryPublishRequestSchema, response: RegistryPublishResponseSchema }),
484
+ __metadata("design:type", Function),
485
+ __metadata("design:paramtypes", [Object]),
486
+ __metadata("design:returntype", Promise)
487
+ ], GemController.prototype, "registryPublish", null);
488
+ __decorate([
489
+ get("/pick-folder", { query: PickQuerySchema, response: PickFolderSchema }),
490
+ __metadata("design:type", Function),
491
+ __metadata("design:paramtypes", [Object]),
492
+ __metadata("design:returntype", Promise)
493
+ ], GemController.prototype, "pickFolder", null);
494
+ GemController = __decorate([
495
+ api({ basePath: "/api" })
496
+ ], GemController);
497
+ export { GemController };
498
+ // Query params can't carry arrays cleanly, so `projects` arrives JSON-encoded.
499
+ function parseProjectsQuery(s) {
500
+ if (!s)
501
+ return [];
502
+ try {
503
+ const v = JSON.parse(s);
504
+ return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
505
+ }
506
+ catch {
507
+ return [];
508
+ }
509
+ }
510
+ // Compose the global inventory with project sections. Each root is the user's explicit
511
+ // native-picker selection; we canonicalize to absolute paths and dedup.
512
+ function introspectAll(dir, projects) {
513
+ const inventory = introspectConfig(resolveDirs(dir));
514
+ const roots = (projects ?? []).map(resolveProject).filter((r, i, a) => r.length > 0 && a.indexOf(r) === i);
515
+ if (roots.length)
516
+ inventory.projects = roots.map(introspectProject);
517
+ return inventory;
518
+ }
@@ -0,0 +1,103 @@
1
+ import { __decorate, __metadata } from "tslib";
2
+ // src/gem.tools.ts
3
+ import { z } from "zod";
4
+ import { mcpServer, tool } from "@agentback/mcp";
5
+ import { introspectConfig, introspectProject } from "./gem/introspect.js";
6
+ import { buildGem } from "./gem/buildGem.js";
7
+ import { GemSelectionSchema } from "./schemas.js";
8
+ import { resolveDirs, resolveProject } from "./resolveDir.js";
9
+ import { resolveInstall, publishGem } from "./gem/registry.js";
10
+ import { githubRegistrySource, githubRegistryPublisher, registryConfigFromEnv } from "./gem/registryGithub.js";
11
+ import { readWorkspace } from "./gem/workspaces.js";
12
+ import { readGemArchive } from "./gem/archive.js";
13
+ const InventoryInput = z.object({ dir: z.string().optional(), projects: z.array(z.string()).optional() });
14
+ const GemInput = z.object({ selection: GemSelectionSchema, name: z.string().optional(), dir: z.string().optional(), projects: z.array(z.string()).optional() });
15
+ const RegistryRefsInput = z.object({ refs: z.array(z.string()).min(1), mode: z.enum(["materialize", "workspace"]), target: z.string().optional() });
16
+ const RegistryPublishInput = z.object({ workspace: z.string(), scope: z.string(), name: z.string().optional(), version: z.string(), dependencies: z.array(z.string()).optional() });
17
+ function registrySourceOrThrow() {
18
+ const cfg = registryConfigFromEnv();
19
+ if (!cfg)
20
+ throw new Error("the registry is not configured — set AGENTGEM_REGISTRY_REPO");
21
+ return { cfg, source: githubRegistrySource(cfg) };
22
+ }
23
+ function introspectAll(dir, projects) {
24
+ const inventory = introspectConfig(resolveDirs(dir));
25
+ const roots = (projects ?? []).map(resolveProject).filter((r, i, a) => r.length > 0 && a.indexOf(r) === i);
26
+ if (roots.length)
27
+ inventory.projects = roots.map(introspectProject);
28
+ return inventory;
29
+ }
30
+ let GemTools = class GemTools {
31
+ async inventory(input) {
32
+ return introspectAll(input.dir, input.projects);
33
+ }
34
+ async gem(input) {
35
+ const dirs = resolveDirs(input.dir);
36
+ return buildGem(introspectAll(input.dir, input.projects), input.selection, { name: input.name ?? "gem", createdFrom: dirs.claudeDir });
37
+ }
38
+ async registryIndex(_input) {
39
+ return registrySourceOrThrow().source.getIndex();
40
+ }
41
+ async registryResolve(input) {
42
+ const { source } = registrySourceOrThrow();
43
+ const { plan } = await resolveInstall({ refs: input.refs, mode: input.mode, target: input.target, source });
44
+ return plan;
45
+ }
46
+ async registryInstall(input) {
47
+ const { source } = registrySourceOrThrow();
48
+ const { plan, gem } = await resolveInstall({ refs: input.refs, mode: input.mode, target: input.target, source });
49
+ return { plan, gem };
50
+ }
51
+ async registryPublish(input) {
52
+ const { cfg, source } = registrySourceOrThrow();
53
+ const gem = readGemArchive(readWorkspace(input.workspace).files);
54
+ const index = await source.getIndex();
55
+ return publishGem({ gem, scope: input.scope, name: input.name, version: input.version, dependencies: input.dependencies, index, publisher: githubRegistryPublisher(cfg) });
56
+ }
57
+ };
58
+ __decorate([
59
+ tool("inventory", {
60
+ description: "Introspect the local coding-agent config (skills, MCP servers, CLAUDE.md). Pass project roots to also include project-level artifacts. Secrets are redacted.",
61
+ input: InventoryInput,
62
+ }),
63
+ __metadata("design:type", Function),
64
+ __metadata("design:paramtypes", [Object]),
65
+ __metadata("design:returntype", Promise)
66
+ ], GemTools.prototype, "inventory", null);
67
+ __decorate([
68
+ tool("build_gem", {
69
+ description: "Build a redacted Gem from a selection of the introspected config artifacts.",
70
+ input: GemInput,
71
+ }),
72
+ __metadata("design:type", Function),
73
+ __metadata("design:paramtypes", [Object]),
74
+ __metadata("design:returntype", Promise)
75
+ ], GemTools.prototype, "gem", null);
76
+ __decorate([
77
+ tool("registry_index", { description: "List the gems available in the configured registry (names, versions, dependencies).", input: z.object({}) }),
78
+ __metadata("design:type", Function),
79
+ __metadata("design:paramtypes", [Object]),
80
+ __metadata("design:returntype", Promise)
81
+ ], GemTools.prototype, "registryIndex", null);
82
+ __decorate([
83
+ tool("registry_resolve", { description: "Resolve registry refs into an install plan (items, artifacts, required secrets, and a materialize preview for a target). No writes.", input: RegistryRefsInput }),
84
+ __metadata("design:type", Function),
85
+ __metadata("design:paramtypes", [Object]),
86
+ __metadata("design:returntype", Promise)
87
+ ], GemTools.prototype, "registryResolve", null);
88
+ __decorate([
89
+ tool("registry_install", { description: "Resolve + merge registry refs, returning the merged Gem and install plan. (Disk/workspace placement is performed via the REST /registry/install endpoint.)", input: RegistryRefsInput }),
90
+ __metadata("design:type", Function),
91
+ __metadata("design:paramtypes", [Object]),
92
+ __metadata("design:returntype", Promise)
93
+ ], GemTools.prototype, "registryInstall", null);
94
+ __decorate([
95
+ tool("registry_publish", { description: "Publish a workspace Gem to the registry as @scope/name@version (requires GITHUB_TOKEN).", input: RegistryPublishInput }),
96
+ __metadata("design:type", Function),
97
+ __metadata("design:paramtypes", [Object]),
98
+ __metadata("design:returntype", Promise)
99
+ ], GemTools.prototype, "registryPublish", null);
100
+ GemTools = __decorate([
101
+ mcpServer()
102
+ ], GemTools);
103
+ export { GemTools };