agentplane 0.3.4 → 0.3.6
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/README.md +103 -75
- package/assets/AGENTS.md +4 -2
- package/bin/dist-guard.js +13 -3
- package/bin/runtime-watch.d.ts +1 -0
- package/bin/runtime-watch.js +22 -5
- package/bin/stale-dist-policy.js +9 -2
- package/dist/.build-manifest.json +220 -790
- package/dist/adapters/task-backend/task-backend-adapter.d.ts +1 -1
- package/dist/adapters/task-backend/task-backend-adapter.d.ts.map +1 -1
- package/dist/adapters/task-backend/task-backend-adapter.js +5 -2
- package/dist/backends/task-backend/local-backend.d.ts +13 -0
- package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/local-backend.js +17 -0
- package/dist/backends/task-backend/redmine-backend.d.ts +18 -0
- package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine-backend.js +35 -25
- package/dist/backends/task-backend/shared/types.d.ts +20 -0
- package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
- package/dist/backends/task-backend/shared.d.ts +1 -1
- package/dist/backends/task-backend/shared.d.ts.map +1 -1
- package/dist/backends/task-backend.d.ts +1 -1
- package/dist/backends/task-backend.d.ts.map +1 -1
- package/dist/backends/task-backend.test-helpers.d.ts +4 -0
- package/dist/backends/task-backend.test-helpers.d.ts.map +1 -0
- package/dist/backends/task-backend.test-helpers.js +33 -0
- package/dist/cli/bootstrap-guide.d.ts.map +1 -1
- package/dist/cli/bootstrap-guide.js +1 -0
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +3 -2
- package/dist/cli/reason-codes.d.ts.map +1 -1
- package/dist/cli/reason-codes.js +30 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/core.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/core.js +137 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/lifecycle.js +52 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/project.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/project.js +78 -0
- package/dist/cli/run-cli/command-catalog/shared.d.ts +19 -0
- package/dist/cli/run-cli/command-catalog/shared.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/shared.js +9 -0
- package/dist/cli/run-cli/command-catalog/task.d.ts +3 -0
- package/dist/cli/run-cli/command-catalog/task.d.ts.map +1 -0
- package/dist/cli/run-cli/command-catalog/task.js +85 -0
- package/dist/cli/run-cli/command-catalog.d.ts +3 -18
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog.js +8 -337
- package/dist/cli/run-cli/commands/ide.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/ide.js +64 -2
- package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/ui.js +33 -13
- package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts +3 -0
- package/dist/cli/run-cli.core.pr-flow.test-helpers.d.ts.map +1 -0
- package/dist/cli/run-cli.core.pr-flow.test-helpers.js +41 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.d.ts +2 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.d.ts.map +1 -0
- package/dist/cli/run-cli.core.tasks.test-helpers.js +6 -0
- package/dist/cli/run-cli.test-helpers.d.ts +3 -0
- package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/cli/run-cli.test-helpers.js +138 -6
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +2 -2
- package/dist/commands/doctor/runtime.d.ts.map +1 -1
- package/dist/commands/doctor/runtime.js +3 -6
- package/dist/commands/doctor/workspace.d.ts +4 -1
- package/dist/commands/doctor/workspace.d.ts.map +1 -1
- package/dist/commands/doctor/workspace.js +87 -4
- package/dist/commands/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +8 -1
- package/dist/commands/guard/commit.command.js +1 -1
- package/dist/commands/guard/impl/allow.d.ts +5 -0
- package/dist/commands/guard/impl/allow.d.ts.map +1 -1
- package/dist/commands/guard/impl/allow.js +15 -10
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +137 -18
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +2 -0
- package/dist/commands/hooks/index.d.ts.map +1 -1
- package/dist/commands/hooks/index.js +8 -35
- package/dist/commands/recipes/impl/apply.d.ts +4 -0
- package/dist/commands/recipes/impl/apply.d.ts.map +1 -1
- package/dist/commands/recipes/impl/apply.js +34 -0
- package/dist/commands/recipes/impl/commands/explain.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/explain.js +70 -11
- package/dist/commands/recipes/impl/commands/info.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/info.js +24 -12
- package/dist/commands/recipes/impl/commands/install.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/install.js +32 -36
- package/dist/commands/recipes/impl/commands/list.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/list.js +7 -4
- package/dist/commands/recipes/impl/commands/remove.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/remove.js +9 -11
- package/dist/commands/recipes/impl/constants.d.ts +2 -0
- package/dist/commands/recipes/impl/constants.d.ts.map +1 -1
- package/dist/commands/recipes/impl/constants.js +2 -0
- package/dist/commands/recipes/impl/manifest.d.ts.map +1 -1
- package/dist/commands/recipes/impl/manifest.js +219 -23
- package/dist/commands/recipes/impl/normalize.d.ts +3 -0
- package/dist/commands/recipes/impl/normalize.d.ts.map +1 -1
- package/dist/commands/recipes/impl/normalize.js +28 -24
- package/dist/commands/recipes/impl/paths.d.ts +9 -0
- package/dist/commands/recipes/impl/paths.d.ts.map +1 -1
- package/dist/commands/recipes/impl/paths.js +10 -1
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts +7 -0
- package/dist/commands/recipes/impl/project-installed-recipes.d.ts.map +1 -0
- package/dist/commands/recipes/impl/project-installed-recipes.js +102 -0
- package/dist/commands/recipes/impl/resolver.d.ts +20 -0
- package/dist/commands/recipes/impl/resolver.d.ts.map +1 -0
- package/dist/commands/recipes/impl/resolver.js +220 -0
- package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
- package/dist/commands/recipes/impl/scenario.js +40 -11
- package/dist/commands/recipes/impl/types.d.ts +145 -16
- package/dist/commands/recipes/impl/types.d.ts.map +1 -1
- package/dist/commands/recipes/install.spec.d.ts.map +1 -1
- package/dist/commands/recipes/install.spec.js +3 -2
- package/dist/commands/recipes.d.ts +6 -4
- package/dist/commands/recipes.d.ts.map +1 -1
- package/dist/commands/recipes.js +5 -3
- package/dist/commands/recipes.test-helpers.d.ts +185 -0
- package/dist/commands/recipes.test-helpers.d.ts.map +1 -0
- package/dist/commands/recipes.test-helpers.js +339 -0
- package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
- package/dist/commands/scenario/impl/commands.js +192 -336
- package/dist/commands/scenario/info.command.d.ts.map +1 -1
- package/dist/commands/scenario/info.command.js +7 -2
- package/dist/commands/scenario/list.command.js +2 -2
- package/dist/commands/scenario/run.command.d.ts.map +1 -1
- package/dist/commands/scenario/run.command.js +7 -2
- package/dist/commands/shared/git-context.d.ts +1 -0
- package/dist/commands/shared/git-context.d.ts.map +1 -1
- package/dist/commands/shared/git-context.js +4 -0
- package/dist/commands/shared/reconcile-check.d.ts.map +1 -1
- package/dist/commands/shared/reconcile-check.js +77 -2
- package/dist/commands/shared/task-backend.d.ts +5 -0
- package/dist/commands/shared/task-backend.d.ts.map +1 -1
- package/dist/commands/shared/task-backend.js +24 -0
- package/dist/commands/shared/task-store.d.ts +32 -1
- package/dist/commands/shared/task-store.d.ts.map +1 -1
- package/dist/commands/shared/task-store.js +166 -42
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +46 -29
- package/dist/commands/task/close-duplicate.d.ts.map +1 -1
- package/dist/commands/task/close-duplicate.js +12 -37
- package/dist/commands/task/close-noop.d.ts.map +1 -1
- package/dist/commands/task/close-noop.js +12 -30
- package/dist/commands/task/close-shared.d.ts +14 -0
- package/dist/commands/task/close-shared.d.ts.map +1 -0
- package/dist/commands/task/close-shared.js +76 -0
- package/dist/commands/task/comment.d.ts.map +1 -1
- package/dist/commands/task/comment.js +35 -17
- package/dist/commands/task/doc-set.command.d.ts +2 -1
- package/dist/commands/task/doc-set.command.d.ts.map +1 -1
- package/dist/commands/task/doc-set.command.js +36 -4
- package/dist/commands/task/doc-template.d.ts.map +1 -1
- package/dist/commands/task/doc-template.js +2 -7
- package/dist/commands/task/doc.command.js +1 -1
- package/dist/commands/task/doc.d.ts +2 -1
- package/dist/commands/task/doc.d.ts.map +1 -1
- package/dist/commands/task/doc.js +123 -71
- package/dist/commands/task/export.d.ts.map +1 -1
- package/dist/commands/task/export.js +4 -4
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +141 -78
- package/dist/commands/task/migrate-doc.d.ts.map +1 -1
- package/dist/commands/task/migrate-doc.js +15 -11
- package/dist/commands/task/plan-set.command.js +1 -1
- package/dist/commands/task/plan.command.d.ts +8 -0
- package/dist/commands/task/plan.command.d.ts.map +1 -0
- package/dist/commands/task/plan.command.js +37 -0
- package/dist/commands/task/plan.d.ts.map +1 -1
- package/dist/commands/task/plan.js +190 -93
- package/dist/commands/task/set-status.command.d.ts.map +1 -1
- package/dist/commands/task/set-status.command.js +1 -1
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +40 -3
- package/dist/commands/task/shared/docs.d.ts +1 -0
- package/dist/commands/task/shared/docs.d.ts.map +1 -1
- package/dist/commands/task/shared/docs.js +7 -0
- package/dist/commands/task/shared/transitions.d.ts +0 -2
- package/dist/commands/task/shared/transitions.d.ts.map +1 -1
- package/dist/commands/task/shared/transitions.js +0 -6
- package/dist/commands/task/shared.d.ts +2 -2
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +2 -2
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +88 -63
- package/dist/commands/task/task.command.d.ts +8 -0
- package/dist/commands/task/task.command.d.ts.map +1 -0
- package/dist/commands/task/task.command.js +71 -0
- package/dist/commands/task/verify-command-shared.d.ts +16 -0
- package/dist/commands/task/verify-command-shared.d.ts.map +1 -0
- package/dist/commands/task/verify-command-shared.js +53 -0
- package/dist/commands/task/verify-ok.command.d.ts +2 -6
- package/dist/commands/task/verify-ok.command.d.ts.map +1 -1
- package/dist/commands/task/verify-ok.command.js +8 -50
- package/dist/commands/task/verify-record.d.ts.map +1 -1
- package/dist/commands/task/verify-record.js +119 -140
- package/dist/commands/task/verify-rework.command.d.ts +2 -6
- package/dist/commands/task/verify-rework.command.d.ts.map +1 -1
- package/dist/commands/task/verify-rework.command.js +8 -50
- package/dist/commands/verify.spec.d.ts.map +1 -1
- package/dist/commands/verify.spec.js +3 -12
- package/dist/policy/rules/allowlist.d.ts.map +1 -1
- package/dist/policy/rules/allowlist.js +13 -4
- package/dist/policy/rules/protected-paths.d.ts.map +1 -1
- package/dist/policy/rules/protected-paths.js +6 -1
- package/dist/ports/task-backend-port.d.ts +1 -1
- package/dist/ports/task-backend-port.d.ts.map +1 -1
- package/dist/shared/agent-emoji.d.ts.map +1 -1
- package/dist/shared/protected-paths.d.ts +7 -0
- package/dist/shared/protected-paths.d.ts.map +1 -1
- package/dist/shared/protected-paths.js +26 -10
- package/dist/shared/repo-cli-version.d.ts.map +1 -1
- package/dist/shared/repo-cli-version.js +9 -3
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cp, mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { defaultConfig, loadConfig } from "@agentplaneorg/core";
|
|
4
|
+
import { defaultConfig, loadConfig, resolveProject } from "@agentplaneorg/core";
|
|
5
5
|
import { extractArchive } from "../../../../cli/archive.js";
|
|
6
6
|
import { sha256File } from "../../../../cli/checksum.js";
|
|
7
7
|
import { mapCoreError } from "../../../../cli/error-map.js";
|
|
@@ -12,26 +12,27 @@ import { getBundledRecipeEntry, resolveBundledRecipeSourcePath, } from "../../..
|
|
|
12
12
|
import { CliError } from "../../../../shared/errors.js";
|
|
13
13
|
import { ensureNetworkApproved } from "../../../shared/network-approval.js";
|
|
14
14
|
import { resolvePathFallback } from "../../../shared/path.js";
|
|
15
|
-
import {
|
|
15
|
+
import { moveRecipeDir, validateRecipeAssets } from "../apply.js";
|
|
16
16
|
import { resolveRecipeRoot } from "../archive.js";
|
|
17
|
-
import { DEFAULT_RECIPES_INDEX_URL } from "../constants.js";
|
|
17
|
+
import { DEFAULT_RECIPES_INDEX_URL, RECIPE_RUNS_DIR_NAME } from "../constants.js";
|
|
18
18
|
import { loadRecipesRemoteIndex, willFetchRemoteRecipesIndex } from "../index.js";
|
|
19
|
-
import { readInstalledRecipesFile, writeInstalledRecipesFile } from "../installed-recipes.js";
|
|
20
19
|
import { readRecipeManifest } from "../manifest.js";
|
|
21
20
|
import { normalizeRecipeTags } from "../normalize.js";
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
21
|
+
import { writeRecipeInstallMetadata } from "../project-installed-recipes.js";
|
|
22
|
+
import { resolveProjectInstalledRecipeDir, resolveProjectRecipeInstallMetaPath, resolveProjectRecipesDir, resolveRecipesIndexCachePath, } from "../paths.js";
|
|
24
23
|
function isHttpUrl(value) {
|
|
25
24
|
return value.startsWith("http://") || value.startsWith("https://");
|
|
26
25
|
}
|
|
27
26
|
export async function cmdRecipeInstall(opts) {
|
|
27
|
+
void opts.onConflict;
|
|
28
28
|
try {
|
|
29
|
-
const project = await
|
|
29
|
+
const project = await resolveProject({
|
|
30
|
+
cwd: opts.cwd,
|
|
31
|
+
rootOverride: opts.rootOverride ?? null,
|
|
32
|
+
});
|
|
30
33
|
let config = defaultConfig();
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
config = loaded.config;
|
|
34
|
-
}
|
|
34
|
+
const loaded = await loadConfig(project.agentplaneDir);
|
|
35
|
+
config = loaded.config;
|
|
35
36
|
let networkApproved = false;
|
|
36
37
|
const ensureApproved = async (reason) => {
|
|
37
38
|
if (networkApproved)
|
|
@@ -173,7 +174,8 @@ export async function cmdRecipeInstall(opts) {
|
|
|
173
174
|
const manifest = await readRecipeManifest(path.join(recipeRoot, "manifest.json"));
|
|
174
175
|
const resolvedTags = manifest.tags && manifest.tags.length > 0 ? manifest.tags : normalizeRecipeTags(indexTags);
|
|
175
176
|
const manifestWithTags = resolvedTags.length > 0 ? { ...manifest, tags: resolvedTags } : manifest;
|
|
176
|
-
|
|
177
|
+
await validateRecipeAssets({ manifest: manifestWithTags, recipeDir: recipeRoot });
|
|
178
|
+
const installDir = resolveProjectInstalledRecipeDir(project, manifestWithTags.id);
|
|
177
179
|
const installKind = await getPathKind(installDir);
|
|
178
180
|
if (installKind && installKind !== "dir") {
|
|
179
181
|
throw new CliError({
|
|
@@ -183,21 +185,31 @@ export async function cmdRecipeInstall(opts) {
|
|
|
183
185
|
});
|
|
184
186
|
}
|
|
185
187
|
const hadExisting = Boolean(installKind);
|
|
188
|
+
const existingRunsDir = path.join(installDir, RECIPE_RUNS_DIR_NAME);
|
|
189
|
+
const preservedRunsDir = path.join(tempRoot, RECIPE_RUNS_DIR_NAME);
|
|
186
190
|
if (installKind) {
|
|
191
|
+
if ((await getPathKind(existingRunsDir)) === "dir") {
|
|
192
|
+
await cp(existingRunsDir, preservedRunsDir, { recursive: true });
|
|
193
|
+
}
|
|
187
194
|
await rm(installDir, { recursive: true, force: true });
|
|
188
195
|
}
|
|
189
|
-
await mkdir(
|
|
196
|
+
await mkdir(resolveProjectRecipesDir(project), { recursive: true });
|
|
190
197
|
await moveRecipeDir({ from: recipeRoot, to: installDir });
|
|
191
198
|
try {
|
|
192
|
-
if (
|
|
193
|
-
await
|
|
194
|
-
|
|
195
|
-
recipeDir: installDir,
|
|
196
|
-
agentplaneDir: project.agentplaneDir,
|
|
197
|
-
onConflict: opts.onConflict,
|
|
199
|
+
if ((await getPathKind(preservedRunsDir)) === "dir") {
|
|
200
|
+
await cp(preservedRunsDir, path.join(installDir, RECIPE_RUNS_DIR_NAME), {
|
|
201
|
+
recursive: true,
|
|
198
202
|
});
|
|
199
203
|
}
|
|
200
|
-
await
|
|
204
|
+
await writeRecipeInstallMetadata(resolveProjectRecipeInstallMetaPath(project, manifestWithTags.id), {
|
|
205
|
+
schema_version: 1,
|
|
206
|
+
id: manifestWithTags.id,
|
|
207
|
+
version: manifestWithTags.version,
|
|
208
|
+
source: sourceLabel,
|
|
209
|
+
installed_at: new Date().toISOString(),
|
|
210
|
+
tags: resolvedTags,
|
|
211
|
+
install_mode: "project-local",
|
|
212
|
+
});
|
|
201
213
|
}
|
|
202
214
|
catch (err) {
|
|
203
215
|
if (!hadExisting) {
|
|
@@ -205,22 +217,6 @@ export async function cmdRecipeInstall(opts) {
|
|
|
205
217
|
}
|
|
206
218
|
throw err;
|
|
207
219
|
}
|
|
208
|
-
const recipesPath = resolveInstalledRecipesPath();
|
|
209
|
-
const installed = await readInstalledRecipesFile(recipesPath);
|
|
210
|
-
const updated = installed.recipes.filter((entry) => entry.id !== manifestWithTags.id);
|
|
211
|
-
updated.push({
|
|
212
|
-
id: manifestWithTags.id,
|
|
213
|
-
version: manifestWithTags.version,
|
|
214
|
-
source: sourceLabel,
|
|
215
|
-
installed_at: new Date().toISOString(),
|
|
216
|
-
tags: resolvedTags,
|
|
217
|
-
manifest: manifestWithTags,
|
|
218
|
-
});
|
|
219
|
-
await writeInstalledRecipesFile(recipesPath, {
|
|
220
|
-
schema_version: 1,
|
|
221
|
-
updated_at: installed.updated_at,
|
|
222
|
-
recipes: updated,
|
|
223
|
-
});
|
|
224
220
|
process.stdout.write(`Installed recipe ${manifestWithTags.id}@${manifestWithTags.version}\n`);
|
|
225
221
|
return 0;
|
|
226
222
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/list.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/list.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,eAAe,CAAC;CACxB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkDlB"}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
+
import { resolveProject } from "@agentplaneorg/core";
|
|
1
2
|
import { mapCoreError } from "../../../../cli/error-map.js";
|
|
2
3
|
import { emptyStateMessage } from "../../../../cli/output.js";
|
|
3
4
|
import { CliError } from "../../../../shared/errors.js";
|
|
4
|
-
import {
|
|
5
|
-
import { resolveInstalledRecipesPath } from "../paths.js";
|
|
5
|
+
import { readProjectInstalledRecipes } from "../project-installed-recipes.js";
|
|
6
6
|
export async function cmdRecipeListParsed(opts) {
|
|
7
7
|
const flags = opts.flags;
|
|
8
8
|
try {
|
|
9
|
-
const
|
|
10
|
-
|
|
9
|
+
const resolved = await resolveProject({
|
|
10
|
+
cwd: opts.cwd,
|
|
11
|
+
rootOverride: opts.rootOverride ?? null,
|
|
12
|
+
});
|
|
13
|
+
const installed = await readProjectInstalledRecipes(resolved);
|
|
11
14
|
let recipes = installed.recipes;
|
|
12
15
|
if (flags.tag) {
|
|
13
16
|
const needle = flags.tag.toLowerCase();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/remove.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"remove.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/remove.ts"],"names":[],"mappings":"AAYA,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,EAAE,EAAE,MAAM,CAAC;CACZ,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBlB"}
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import { resolveProject } from "@agentplaneorg/core";
|
|
1
2
|
import { rm } from "node:fs/promises";
|
|
2
3
|
import { mapCoreError } from "../../../../cli/error-map.js";
|
|
3
4
|
import { exitCodeForError } from "../../../../cli/exit-codes.js";
|
|
4
5
|
import { successMessage } from "../../../../cli/output.js";
|
|
5
6
|
import { CliError } from "../../../../shared/errors.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
7
|
+
import { readProjectInstalledRecipes } from "../project-installed-recipes.js";
|
|
8
|
+
import { resolveProjectInstalledRecipeDir } from "../paths.js";
|
|
8
9
|
export async function cmdRecipeRemoveParsed(opts) {
|
|
9
10
|
try {
|
|
10
|
-
const
|
|
11
|
-
|
|
11
|
+
const resolved = await resolveProject({
|
|
12
|
+
cwd: opts.cwd,
|
|
13
|
+
rootOverride: opts.rootOverride ?? null,
|
|
14
|
+
});
|
|
15
|
+
const installed = await readProjectInstalledRecipes(resolved);
|
|
12
16
|
const entry = installed.recipes.find((recipe) => recipe.id === opts.id);
|
|
13
17
|
if (!entry) {
|
|
14
18
|
throw new CliError({
|
|
@@ -17,14 +21,8 @@ export async function cmdRecipeRemoveParsed(opts) {
|
|
|
17
21
|
message: `Recipe not installed: ${opts.id}`,
|
|
18
22
|
});
|
|
19
23
|
}
|
|
20
|
-
const recipeDir =
|
|
24
|
+
const recipeDir = resolveProjectInstalledRecipeDir(resolved, entry.id);
|
|
21
25
|
await rm(recipeDir, { recursive: true, force: true });
|
|
22
|
-
const updated = installed.recipes.filter((recipe) => recipe.id !== opts.id);
|
|
23
|
-
await writeInstalledRecipesFile(recipesPath, {
|
|
24
|
-
schema_version: 1,
|
|
25
|
-
updated_at: installed.updated_at,
|
|
26
|
-
recipes: updated,
|
|
27
|
-
});
|
|
28
26
|
process.stdout.write(`${successMessage("removed recipe", `${entry.id}@${entry.version}`)}\n`);
|
|
29
27
|
return 0;
|
|
30
28
|
}
|
|
@@ -2,6 +2,8 @@ export declare const INSTALLED_RECIPES_NAME = "recipes.json";
|
|
|
2
2
|
export declare const RECIPES_DIR_NAME = "recipes";
|
|
3
3
|
export declare const RECIPES_SCENARIOS_DIR_NAME = "scenarios";
|
|
4
4
|
export declare const RECIPES_SCENARIOS_INDEX_NAME = "scenarios.json";
|
|
5
|
+
export declare const RECIPE_INSTALL_META_NAME = ".install.json";
|
|
6
|
+
export declare const RECIPE_RUNS_DIR_NAME = "runs";
|
|
5
7
|
export declare const AGENTPLANE_HOME_ENV = "AGENTPLANE_HOME";
|
|
6
8
|
export declare const GLOBAL_RECIPES_DIR_NAME = "recipes";
|
|
7
9
|
export declare const PROJECT_RECIPES_CACHE_DIR_NAME = "recipes-cache";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,iBAAiB,CAAC;AACrD,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAC1C,eAAO,MAAM,0BAA0B,cAAc,CAAC;AACtD,eAAO,MAAM,4BAA4B,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,sBAAsB,iBAAiB,CAAC;AACrD,eAAO,MAAM,gBAAgB,YAAY,CAAC;AAC1C,eAAO,MAAM,0BAA0B,cAAc,CAAC;AACtD,eAAO,MAAM,4BAA4B,mBAAmB,CAAC;AAC7D,eAAO,MAAM,wBAAwB,kBAAkB,CAAC;AACxD,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAE3C,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAErD,eAAO,MAAM,uBAAuB,YAAY,CAAC;AACjD,eAAO,MAAM,8BAA8B,kBAAkB,CAAC;AAE9D,eAAO,MAAM,yBAAyB,uBAAuB,CAAC;AAC9D,eAAO,MAAM,6BAA6B,2BAA2B,CAAC;AAEtE,eAAO,MAAM,yBAAyB,uFACgD,CAAC;AAEvF,eAAO,MAAM,6BAA6B,yCAAyC,CAAC;AAEpF,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAI5D,CAAC"}
|
|
@@ -2,6 +2,8 @@ export const INSTALLED_RECIPES_NAME = "recipes.json";
|
|
|
2
2
|
export const RECIPES_DIR_NAME = "recipes";
|
|
3
3
|
export const RECIPES_SCENARIOS_DIR_NAME = "scenarios";
|
|
4
4
|
export const RECIPES_SCENARIOS_INDEX_NAME = "scenarios.json";
|
|
5
|
+
export const RECIPE_INSTALL_META_NAME = ".install.json";
|
|
6
|
+
export const RECIPE_RUNS_DIR_NAME = "runs";
|
|
5
7
|
export const AGENTPLANE_HOME_ENV = "AGENTPLANE_HOME";
|
|
6
8
|
export const GLOBAL_RECIPES_DIR_NAME = "recipes";
|
|
7
9
|
export const PROJECT_RECIPES_CACHE_DIR_NAME = "recipes-cache";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"manifest.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/manifest.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAGV,cAAc,EAKf,MAAM,YAAY,CAAC;AAyPpB,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAsDnE;AAED,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAGtF"}
|
|
@@ -1,40 +1,236 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { invalidFieldMessage, requiredFieldMessage } from "../../../cli/output.js";
|
|
3
3
|
import { isRecord } from "../../../shared/guards.js";
|
|
4
|
-
import {
|
|
4
|
+
import { dedupeStrings } from "../../../shared/strings.js";
|
|
5
|
+
import { normalizeAgentId, normalizeRecipeId, normalizeRecipeRelativePath, normalizeRecipeTags, normalizeScenarioId, normalizeSkillId, normalizeToolId, } from "./normalize.js";
|
|
6
|
+
function normalizeRequiredString(raw, field) {
|
|
7
|
+
if (typeof raw !== "string")
|
|
8
|
+
throw new Error(invalidFieldMessage(field, "string"));
|
|
9
|
+
const value = raw.trim();
|
|
10
|
+
if (!value)
|
|
11
|
+
throw new Error(requiredFieldMessage(field));
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
function normalizeOptionalString(raw, field) {
|
|
15
|
+
if (raw === undefined)
|
|
16
|
+
return undefined;
|
|
17
|
+
if (typeof raw !== "string")
|
|
18
|
+
throw new Error(invalidFieldMessage(field, "string"));
|
|
19
|
+
const value = raw.trim();
|
|
20
|
+
return value || undefined;
|
|
21
|
+
}
|
|
22
|
+
function normalizeStringList(raw, field, opts) {
|
|
23
|
+
if (!Array.isArray(raw))
|
|
24
|
+
throw new Error(invalidFieldMessage(field, "string[]"));
|
|
25
|
+
const values = raw.map((value) => {
|
|
26
|
+
if (typeof value !== "string")
|
|
27
|
+
throw new Error(invalidFieldMessage(field, "string[]"));
|
|
28
|
+
const trimmed = value.trim();
|
|
29
|
+
if (!trimmed)
|
|
30
|
+
throw new Error(invalidFieldMessage(field, "string[]"));
|
|
31
|
+
return trimmed;
|
|
32
|
+
});
|
|
33
|
+
const deduped = dedupeStrings(values);
|
|
34
|
+
if ((opts?.minLength ?? 0) > 0 && deduped.length < (opts?.minLength ?? 0)) {
|
|
35
|
+
throw new Error(invalidFieldMessage(field, `string[${opts?.minLength ?? 0}+]`));
|
|
36
|
+
}
|
|
37
|
+
return deduped;
|
|
38
|
+
}
|
|
39
|
+
function normalizeOptionalStringList(raw, field) {
|
|
40
|
+
if (raw === undefined)
|
|
41
|
+
return undefined;
|
|
42
|
+
return normalizeStringList(raw, field);
|
|
43
|
+
}
|
|
44
|
+
function normalizeBoolean(raw, field) {
|
|
45
|
+
if (raw === undefined)
|
|
46
|
+
return undefined;
|
|
47
|
+
if (typeof raw !== "boolean")
|
|
48
|
+
throw new Error(invalidFieldMessage(field, "boolean"));
|
|
49
|
+
return raw;
|
|
50
|
+
}
|
|
51
|
+
function normalizeNumber(raw, field) {
|
|
52
|
+
if (raw === undefined)
|
|
53
|
+
return undefined;
|
|
54
|
+
if (typeof raw !== "number" || Number.isNaN(raw)) {
|
|
55
|
+
throw new Error(invalidFieldMessage(field, "number"));
|
|
56
|
+
}
|
|
57
|
+
return raw;
|
|
58
|
+
}
|
|
59
|
+
function normalizeCompatibility(raw) {
|
|
60
|
+
if (raw === undefined)
|
|
61
|
+
return undefined;
|
|
62
|
+
if (!isRecord(raw))
|
|
63
|
+
throw new Error(invalidFieldMessage("manifest.compatibility", "object"));
|
|
64
|
+
return {
|
|
65
|
+
min_agentplane_version: normalizeOptionalString(raw.min_agentplane_version, "manifest.compatibility.min_agentplane_version"),
|
|
66
|
+
manifest_api_version: normalizeOptionalString(raw.manifest_api_version, "manifest.compatibility.manifest_api_version"),
|
|
67
|
+
scenario_api_version: normalizeOptionalString(raw.scenario_api_version, "manifest.compatibility.scenario_api_version"),
|
|
68
|
+
runtime_api_version: normalizeOptionalString(raw.runtime_api_version, "manifest.compatibility.runtime_api_version"),
|
|
69
|
+
platforms: normalizeOptionalStringList(raw.platforms, "manifest.compatibility.platforms"),
|
|
70
|
+
repo_types: normalizeOptionalStringList(raw.repo_types, "manifest.compatibility.repo_types"),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function normalizeRunProfile(raw, field) {
|
|
74
|
+
if (!isRecord(raw))
|
|
75
|
+
throw new Error(invalidFieldMessage(field, "object"));
|
|
76
|
+
return {
|
|
77
|
+
mode: normalizeRequiredString(raw.mode, `${field}.mode`),
|
|
78
|
+
sandbox: normalizeOptionalString(raw.sandbox, `${field}.sandbox`),
|
|
79
|
+
network: normalizeBoolean(raw.network, `${field}.network`),
|
|
80
|
+
requires_human_approval: normalizeBoolean(raw.requires_human_approval, `${field}.requires_human_approval`),
|
|
81
|
+
writes_artifacts_to: normalizeOptionalStringList(raw.writes_artifacts_to, `${field}.writes_artifacts_to`),
|
|
82
|
+
expected_exit_contract: normalizeOptionalString(raw.expected_exit_contract, `${field}.expected_exit_contract`),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function normalizeSkills(raw) {
|
|
86
|
+
if (raw === undefined)
|
|
87
|
+
return undefined;
|
|
88
|
+
if (!Array.isArray(raw))
|
|
89
|
+
throw new Error(invalidFieldMessage("manifest.skills", "array"));
|
|
90
|
+
return raw.map((entry, index) => {
|
|
91
|
+
if (!isRecord(entry))
|
|
92
|
+
throw new Error(invalidFieldMessage(`manifest.skills[${index}]`, "object"));
|
|
93
|
+
return {
|
|
94
|
+
id: normalizeSkillId(normalizeRequiredString(entry.id, `manifest.skills[${index}].id`)),
|
|
95
|
+
summary: normalizeRequiredString(entry.summary, `manifest.skills[${index}].summary`),
|
|
96
|
+
kind: normalizeRequiredString(entry.kind, `manifest.skills[${index}].kind`),
|
|
97
|
+
file: normalizeRecipeRelativePath(`manifest.skills[${index}].file`, normalizeRequiredString(entry.file, `manifest.skills[${index}].file`)),
|
|
98
|
+
};
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
function normalizeTools(raw) {
|
|
102
|
+
if (raw === undefined)
|
|
103
|
+
return undefined;
|
|
104
|
+
if (!Array.isArray(raw))
|
|
105
|
+
throw new Error(invalidFieldMessage("manifest.tools", "array"));
|
|
106
|
+
return raw.map((entry, index) => {
|
|
107
|
+
if (!isRecord(entry))
|
|
108
|
+
throw new Error(invalidFieldMessage(`manifest.tools[${index}]`, "object"));
|
|
109
|
+
const runtime = normalizeRequiredString(entry.runtime, `manifest.tools[${index}].runtime`);
|
|
110
|
+
if (runtime !== "node" && runtime !== "bash") {
|
|
111
|
+
throw new Error(invalidFieldMessage(`manifest.tools[${index}].runtime`, '"node" | "bash"'));
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
id: normalizeToolId(normalizeRequiredString(entry.id, `manifest.tools[${index}].id`)),
|
|
115
|
+
summary: normalizeRequiredString(entry.summary, `manifest.tools[${index}].summary`),
|
|
116
|
+
runtime,
|
|
117
|
+
entrypoint: normalizeRecipeRelativePath(`manifest.tools[${index}].entrypoint`, normalizeRequiredString(entry.entrypoint, `manifest.tools[${index}].entrypoint`)),
|
|
118
|
+
permissions: normalizeOptionalStringList(entry.permissions, `manifest.tools[${index}].permissions`),
|
|
119
|
+
timeout_ms: normalizeNumber(entry.timeout_ms, `manifest.tools[${index}].timeout_ms`),
|
|
120
|
+
cwd_policy: normalizeOptionalString(entry.cwd_policy, `manifest.tools[${index}].cwd_policy`),
|
|
121
|
+
};
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
function normalizeAgents(raw) {
|
|
125
|
+
if (raw === undefined)
|
|
126
|
+
return undefined;
|
|
127
|
+
if (!Array.isArray(raw))
|
|
128
|
+
throw new Error(invalidFieldMessage("manifest.agents", "array"));
|
|
129
|
+
return raw.map((entry, index) => {
|
|
130
|
+
if (!isRecord(entry))
|
|
131
|
+
throw new Error(invalidFieldMessage(`manifest.agents[${index}]`, "object"));
|
|
132
|
+
return {
|
|
133
|
+
id: normalizeAgentId(normalizeRequiredString(entry.id, `manifest.agents[${index}].id`)),
|
|
134
|
+
display_name: normalizeRequiredString(entry.display_name, `manifest.agents[${index}].display_name`),
|
|
135
|
+
role: normalizeRequiredString(entry.role, `manifest.agents[${index}].role`),
|
|
136
|
+
summary: normalizeRequiredString(entry.summary, `manifest.agents[${index}].summary`),
|
|
137
|
+
skills: normalizeOptionalStringList(entry.skills, `manifest.agents[${index}].skills`),
|
|
138
|
+
tools: normalizeOptionalStringList(entry.tools, `manifest.agents[${index}].tools`),
|
|
139
|
+
file: normalizeRecipeRelativePath(`manifest.agents[${index}].file`, normalizeRequiredString(entry.file, `manifest.agents[${index}].file`)),
|
|
140
|
+
};
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
function normalizeScenarios(raw) {
|
|
144
|
+
if (!Array.isArray(raw) || raw.length === 0) {
|
|
145
|
+
throw new Error(invalidFieldMessage("manifest.scenarios", "non-empty array"));
|
|
146
|
+
}
|
|
147
|
+
return raw.map((entry, index) => {
|
|
148
|
+
if (!isRecord(entry)) {
|
|
149
|
+
throw new Error(invalidFieldMessage(`manifest.scenarios[${index}]`, "object"));
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
id: normalizeScenarioId(normalizeRequiredString(entry.id, `manifest.scenarios[${index}].id`)),
|
|
153
|
+
name: normalizeRequiredString(entry.name, `manifest.scenarios[${index}].name`),
|
|
154
|
+
summary: normalizeRequiredString(entry.summary, `manifest.scenarios[${index}].summary`),
|
|
155
|
+
description: normalizeOptionalString(entry.description, `manifest.scenarios[${index}].description`),
|
|
156
|
+
use_when: normalizeStringList(entry.use_when, `manifest.scenarios[${index}].use_when`, {
|
|
157
|
+
minLength: 1,
|
|
158
|
+
}),
|
|
159
|
+
avoid_when: normalizeOptionalStringList(entry.avoid_when, `manifest.scenarios[${index}].avoid_when`),
|
|
160
|
+
required_inputs: normalizeStringList(entry.required_inputs, `manifest.scenarios[${index}].required_inputs`),
|
|
161
|
+
outputs: normalizeStringList(entry.outputs, `manifest.scenarios[${index}].outputs`),
|
|
162
|
+
permissions: normalizeStringList(Array.isArray(entry.permissions) ? entry.permissions : [], `manifest.scenarios[${index}].permissions`),
|
|
163
|
+
artifacts: normalizeStringList(Array.isArray(entry.artifacts) ? entry.artifacts : [], `manifest.scenarios[${index}].artifacts`),
|
|
164
|
+
agents_involved: normalizeStringList(entry.agents_involved, `manifest.scenarios[${index}].agents_involved`, { minLength: 1 }),
|
|
165
|
+
skills_used: normalizeStringList(Array.isArray(entry.skills_used) ? entry.skills_used : [], `manifest.scenarios[${index}].skills_used`),
|
|
166
|
+
tools_used: normalizeStringList(Array.isArray(entry.tools_used) ? entry.tools_used : [], `manifest.scenarios[${index}].tools_used`),
|
|
167
|
+
run_profile: normalizeRunProfile(entry.run_profile, `manifest.scenarios[${index}].run_profile`),
|
|
168
|
+
file: normalizeRecipeRelativePath(`manifest.scenarios[${index}].file`, normalizeRequiredString(entry.file, `manifest.scenarios[${index}].file`)),
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
function assertUniqueIds(field, items) {
|
|
173
|
+
const seen = new Set();
|
|
174
|
+
for (const item of items) {
|
|
175
|
+
if (seen.has(item.id)) {
|
|
176
|
+
throw new Error(invalidFieldMessage(field, `unique ids (duplicate: ${item.id})`));
|
|
177
|
+
}
|
|
178
|
+
seen.add(item.id);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function assertKnownReferences(field, refs, known) {
|
|
182
|
+
if (!refs || refs.length === 0)
|
|
183
|
+
return;
|
|
184
|
+
const missing = refs.filter((ref) => !known.has(ref));
|
|
185
|
+
if (missing.length > 0) {
|
|
186
|
+
throw new Error(invalidFieldMessage(field, `known ids (missing: ${missing.join(", ")})`));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
5
189
|
export function validateRecipeManifest(raw) {
|
|
6
190
|
if (!isRecord(raw))
|
|
7
191
|
throw new Error(invalidFieldMessage("manifest", "object"));
|
|
8
192
|
if (raw.schema_version !== "1")
|
|
9
193
|
throw new Error(invalidFieldMessage("manifest.schema_version", '"1"'));
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
if (typeof raw.version !== "string")
|
|
13
|
-
throw new Error(invalidFieldMessage("manifest.version", "string"));
|
|
14
|
-
if (typeof raw.name !== "string")
|
|
15
|
-
throw new Error(invalidFieldMessage("manifest.name", "string"));
|
|
16
|
-
if (typeof raw.summary !== "string")
|
|
17
|
-
throw new Error(invalidFieldMessage("manifest.summary", "string"));
|
|
18
|
-
if (typeof raw.description !== "string")
|
|
19
|
-
throw new Error(invalidFieldMessage("manifest.description", "string"));
|
|
20
|
-
const id = normalizeRecipeId(raw.id);
|
|
21
|
-
const version = raw.version.trim();
|
|
22
|
-
if (!version)
|
|
23
|
-
throw new Error(requiredFieldMessage("manifest.version"));
|
|
194
|
+
const id = normalizeRecipeId(normalizeRequiredString(raw.id, "manifest.id"));
|
|
195
|
+
const version = normalizeRequiredString(raw.version, "manifest.version");
|
|
24
196
|
const tags = normalizeRecipeTags(raw.tags);
|
|
197
|
+
const compatibility = normalizeCompatibility(raw.compatibility);
|
|
198
|
+
const skills = normalizeSkills(raw.skills);
|
|
199
|
+
const tools = normalizeTools(raw.tools);
|
|
200
|
+
const agents = normalizeAgents(raw.agents);
|
|
201
|
+
const scenarios = normalizeScenarios(raw.scenarios);
|
|
202
|
+
if (skills)
|
|
203
|
+
assertUniqueIds("manifest.skills", skills);
|
|
204
|
+
if (tools)
|
|
205
|
+
assertUniqueIds("manifest.tools", tools);
|
|
206
|
+
if (agents)
|
|
207
|
+
assertUniqueIds("manifest.agents", agents);
|
|
208
|
+
assertUniqueIds("manifest.scenarios", scenarios);
|
|
209
|
+
const skillIds = new Set((skills ?? []).map((skill) => skill.id));
|
|
210
|
+
const toolIds = new Set((tools ?? []).map((tool) => tool.id));
|
|
211
|
+
const agentIds = new Set((agents ?? []).map((agent) => agent.id));
|
|
212
|
+
for (const [index, agent] of (agents ?? []).entries()) {
|
|
213
|
+
assertKnownReferences(`manifest.agents[${index}].skills`, agent.skills, skillIds);
|
|
214
|
+
assertKnownReferences(`manifest.agents[${index}].tools`, agent.tools, toolIds);
|
|
215
|
+
}
|
|
216
|
+
for (const [index, scenario] of scenarios.entries()) {
|
|
217
|
+
assertKnownReferences(`manifest.scenarios[${index}].agents_involved`, scenario.agents_involved, agentIds);
|
|
218
|
+
assertKnownReferences(`manifest.scenarios[${index}].skills_used`, scenario.skills_used, skillIds);
|
|
219
|
+
assertKnownReferences(`manifest.scenarios[${index}].tools_used`, scenario.tools_used, toolIds);
|
|
220
|
+
}
|
|
25
221
|
return {
|
|
26
222
|
schema_version: "1",
|
|
27
223
|
id,
|
|
28
224
|
version,
|
|
29
|
-
name: raw.name.
|
|
30
|
-
summary: raw.summary.
|
|
31
|
-
description: raw.description.
|
|
225
|
+
name: normalizeRequiredString(raw.name, "manifest.name"),
|
|
226
|
+
summary: normalizeRequiredString(raw.summary, "manifest.summary"),
|
|
227
|
+
description: normalizeRequiredString(raw.description, "manifest.description"),
|
|
32
228
|
tags: tags.length > 0 ? tags : undefined,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
229
|
+
compatibility,
|
|
230
|
+
skills,
|
|
231
|
+
agents,
|
|
232
|
+
tools,
|
|
233
|
+
scenarios,
|
|
38
234
|
};
|
|
39
235
|
}
|
|
40
236
|
export async function readRecipeManifest(manifestPath) {
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export declare function normalizeRecipeId(value: string): string;
|
|
2
2
|
export declare function normalizeAgentId(value: string): string;
|
|
3
|
+
export declare function normalizeSkillId(value: string): string;
|
|
4
|
+
export declare function normalizeToolId(value: string): string;
|
|
3
5
|
export declare function normalizeScenarioId(value: string): string;
|
|
4
6
|
export declare function normalizeRecipeTags(value: unknown): string[];
|
|
7
|
+
export declare function normalizeRecipeRelativePath(field: string, value: string): string;
|
|
5
8
|
//# sourceMappingURL=normalize.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/normalize.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/normalize.ts"],"names":[],"mappings":"AAmBA,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAErD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAQ5D;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAWhF"}
|
|
@@ -1,40 +1,31 @@
|
|
|
1
1
|
import { invalidPathMessage, requiredFieldMessage, invalidFieldMessage, } from "../../../cli/output.js";
|
|
2
2
|
import { dedupeStrings } from "../../../shared/strings.js";
|
|
3
|
-
|
|
3
|
+
function normalizeScopedId(field, value) {
|
|
4
4
|
const trimmed = value.trim();
|
|
5
5
|
if (!trimmed)
|
|
6
|
-
throw new Error(requiredFieldMessage(
|
|
6
|
+
throw new Error(requiredFieldMessage(field));
|
|
7
7
|
if (trimmed.includes("/") || trimmed.includes("\\")) {
|
|
8
|
-
throw new Error(invalidPathMessage(
|
|
8
|
+
throw new Error(invalidPathMessage(field, "must not contain path separators"));
|
|
9
9
|
}
|
|
10
10
|
if (trimmed === "." || trimmed === "..") {
|
|
11
|
-
throw new Error(invalidPathMessage(
|
|
11
|
+
throw new Error(invalidPathMessage(field, "must not be '.' or '..'"));
|
|
12
12
|
}
|
|
13
13
|
return trimmed;
|
|
14
14
|
}
|
|
15
|
+
export function normalizeRecipeId(value) {
|
|
16
|
+
return normalizeScopedId("manifest.id", value);
|
|
17
|
+
}
|
|
15
18
|
export function normalizeAgentId(value) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
throw new Error(invalidPathMessage("agent.id", "must not be '.' or '..'"));
|
|
24
|
-
}
|
|
25
|
-
return trimmed;
|
|
19
|
+
return normalizeScopedId("agent.id", value);
|
|
20
|
+
}
|
|
21
|
+
export function normalizeSkillId(value) {
|
|
22
|
+
return normalizeScopedId("skill.id", value);
|
|
23
|
+
}
|
|
24
|
+
export function normalizeToolId(value) {
|
|
25
|
+
return normalizeScopedId("tool.id", value);
|
|
26
26
|
}
|
|
27
27
|
export function normalizeScenarioId(value) {
|
|
28
|
-
|
|
29
|
-
if (!trimmed)
|
|
30
|
-
throw new Error(requiredFieldMessage("scenario.id"));
|
|
31
|
-
if (trimmed.includes("/") || trimmed.includes("\\")) {
|
|
32
|
-
throw new Error(invalidPathMessage("scenario.id", "must not contain path separators"));
|
|
33
|
-
}
|
|
34
|
-
if (trimmed === "." || trimmed === "..") {
|
|
35
|
-
throw new Error(invalidPathMessage("scenario.id", "must not be '.' or '..'"));
|
|
36
|
-
}
|
|
37
|
-
return trimmed;
|
|
28
|
+
return normalizeScopedId("scenario.id", value);
|
|
38
29
|
}
|
|
39
30
|
export function normalizeRecipeTags(value) {
|
|
40
31
|
if (value === undefined)
|
|
@@ -48,3 +39,16 @@ export function normalizeRecipeTags(value) {
|
|
|
48
39
|
});
|
|
49
40
|
return dedupeStrings(tags);
|
|
50
41
|
}
|
|
42
|
+
export function normalizeRecipeRelativePath(field, value) {
|
|
43
|
+
const trimmed = value.trim().replaceAll("\\", "/");
|
|
44
|
+
if (!trimmed)
|
|
45
|
+
throw new Error(requiredFieldMessage(field));
|
|
46
|
+
if (trimmed.startsWith("/")) {
|
|
47
|
+
throw new Error(invalidPathMessage(field, "must be relative"));
|
|
48
|
+
}
|
|
49
|
+
const segments = trimmed.split("/");
|
|
50
|
+
if (segments.some((segment) => !segment || segment === "." || segment === "..")) {
|
|
51
|
+
throw new Error(invalidPathMessage(field, "must stay within the recipe root"));
|
|
52
|
+
}
|
|
53
|
+
return trimmed;
|
|
54
|
+
}
|
|
@@ -7,6 +7,15 @@ export declare function resolveInstalledRecipeDir(entry: {
|
|
|
7
7
|
id: string;
|
|
8
8
|
version: string;
|
|
9
9
|
}): string;
|
|
10
|
+
export declare function resolveProjectRecipesDir(resolved: {
|
|
11
|
+
agentplaneDir: string;
|
|
12
|
+
}): string;
|
|
13
|
+
export declare function resolveProjectInstalledRecipeDir(resolved: {
|
|
14
|
+
agentplaneDir: string;
|
|
15
|
+
}, recipeId: string): string;
|
|
16
|
+
export declare function resolveProjectRecipeInstallMetaPath(resolved: {
|
|
17
|
+
agentplaneDir: string;
|
|
18
|
+
}, recipeId: string): string;
|
|
10
19
|
export declare function resolveProjectRecipesCacheDir(resolved: {
|
|
11
20
|
agentplaneDir: string;
|
|
12
21
|
}): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/paths.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/paths.ts"],"names":[],"mappings":"AAcA,wBAAgB,qBAAqB,IAAI,MAAM,CAI9C;AAED,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAED,wBAAgB,2BAA2B,IAAI,MAAM,CAEpD;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD;AAED,wBAAgB,+BAA+B,IAAI,MAAM,CAExD;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAExF;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEpF;AAED,wBAAgB,gCAAgC,CAC9C,QAAQ,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,EACnC,QAAQ,EAAE,MAAM,GACf,MAAM,CAER;AAED,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,EACnC,QAAQ,EAAE,MAAM,GACf,MAAM,CAER;AAED,wBAAgB,6BAA6B,CAAC,QAAQ,EAAE;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEzF"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import os from "node:os";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { AGENTPLANE_HOME_ENV, GLOBAL_RECIPES_DIR_NAME, INSTALLED_RECIPES_NAME, PROJECT_RECIPES_CACHE_DIR_NAME, RECIPES_REMOTE_INDEX_NAME, RECIPES_REMOTE_INDEX_SIG_NAME, } from "./constants.js";
|
|
3
|
+
import { AGENTPLANE_HOME_ENV, GLOBAL_RECIPES_DIR_NAME, INSTALLED_RECIPES_NAME, RECIPE_INSTALL_META_NAME, PROJECT_RECIPES_CACHE_DIR_NAME, RECIPES_DIR_NAME, RECIPES_REMOTE_INDEX_NAME, RECIPES_REMOTE_INDEX_SIG_NAME, } from "./constants.js";
|
|
4
4
|
export function resolveAgentplaneHome() {
|
|
5
5
|
const overridden = process.env[AGENTPLANE_HOME_ENV]?.trim();
|
|
6
6
|
if (overridden)
|
|
@@ -22,6 +22,15 @@ export function resolveRecipesIndexCacheSigPath() {
|
|
|
22
22
|
export function resolveInstalledRecipeDir(entry) {
|
|
23
23
|
return path.join(resolveGlobalRecipesDir(), entry.id, entry.version);
|
|
24
24
|
}
|
|
25
|
+
export function resolveProjectRecipesDir(resolved) {
|
|
26
|
+
return path.join(resolved.agentplaneDir, RECIPES_DIR_NAME);
|
|
27
|
+
}
|
|
28
|
+
export function resolveProjectInstalledRecipeDir(resolved, recipeId) {
|
|
29
|
+
return path.join(resolveProjectRecipesDir(resolved), recipeId);
|
|
30
|
+
}
|
|
31
|
+
export function resolveProjectRecipeInstallMetaPath(resolved, recipeId) {
|
|
32
|
+
return path.join(resolveProjectInstalledRecipeDir(resolved, recipeId), RECIPE_INSTALL_META_NAME);
|
|
33
|
+
}
|
|
25
34
|
export function resolveProjectRecipesCacheDir(resolved) {
|
|
26
35
|
return path.join(resolved.agentplaneDir, PROJECT_RECIPES_CACHE_DIR_NAME);
|
|
27
36
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { InstalledRecipesFile, RecipeInstallMetadata } from "./types.js";
|
|
2
|
+
export declare function readRecipeInstallMetadata(filePath: string): Promise<RecipeInstallMetadata | null>;
|
|
3
|
+
export declare function writeRecipeInstallMetadata(filePath: string, metadata: RecipeInstallMetadata): Promise<void>;
|
|
4
|
+
export declare function readProjectInstalledRecipes(opts: {
|
|
5
|
+
agentplaneDir: string;
|
|
6
|
+
}): Promise<InstalledRecipesFile>;
|
|
7
|
+
//# sourceMappingURL=project-installed-recipes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-installed-recipes.d.ts","sourceRoot":"","sources":["../../../../src/commands/recipes/impl/project-installed-recipes.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAwB,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAuCpG,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CASvC;AAED,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,qBAAqB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAGf;AAED,wBAAsB,2BAA2B,CAAC,IAAI,EAAE;IACtD,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA0DhC"}
|