diff --git a/packages/cli/src/commands.ts b/packages/cli/src/commands.ts index e52ce30..764015a 100644 --- a/packages/cli/src/commands.ts +++ b/packages/cli/src/commands.ts @@ -139,14 +139,18 @@ import { managedAgentPlan, managedAgentApply, managedAgentDestroy, - managedAgentWorkbench, managedAgentPlayground, - managedAgentVersionEnable, - managedAgentVersionDisable, - managedAgentVersionStatus, - managedAgentVersionList, - managedAgentVersionPreview, - managedAgentVersionRestore, + managedAgentProjectInit, + managedAgentProjectValidate, + managedAgentProjectBuild, + managedAgentProjectPublish, + managedAgentProjectWorkbench, + managedAgentProjectVersionEnable, + managedAgentProjectVersionDisable, + managedAgentProjectVersionStatus, + managedAgentProjectVersionList, + managedAgentProjectVersionPreview, + managedAgentProjectVersionRestore, managedAgentStateList, managedAgentStateShow, managedAgentStateRm, @@ -308,14 +312,18 @@ export const commands: Record = { "managed-agent plan": managedAgentPlan, "managed-agent apply": managedAgentApply, "managed-agent destroy": managedAgentDestroy, - "managed-agent workbench": managedAgentWorkbench, "managed-agent playground": managedAgentPlayground, - "managed-agent version enable": managedAgentVersionEnable, - "managed-agent version disable": managedAgentVersionDisable, - "managed-agent version status": managedAgentVersionStatus, - "managed-agent version list": managedAgentVersionList, - "managed-agent version preview": managedAgentVersionPreview, - "managed-agent version restore": managedAgentVersionRestore, + "managed-agent project init": managedAgentProjectInit, + "managed-agent project validate": managedAgentProjectValidate, + "managed-agent project build": managedAgentProjectBuild, + "managed-agent project publish": managedAgentProjectPublish, + "managed-agent project workbench": managedAgentProjectWorkbench, + "managed-agent project version enable": managedAgentProjectVersionEnable, + "managed-agent project version disable": managedAgentProjectVersionDisable, + "managed-agent project version status": managedAgentProjectVersionStatus, + "managed-agent project version list": managedAgentProjectVersionList, + "managed-agent project version preview": managedAgentProjectVersionPreview, + "managed-agent project version restore": managedAgentProjectVersionRestore, "managed-agent state list": managedAgentStateList, "managed-agent state show": managedAgentStateShow, "managed-agent state rm": managedAgentStateRm, diff --git a/packages/commands/package.json b/packages/commands/package.json index 6e2f6ae..f784ec2 100644 --- a/packages/commands/package.json +++ b/packages/commands/package.json @@ -40,7 +40,7 @@ "check": "vp check" }, "dependencies": { - "@openagentpack/project-versions": "0.4.0", + "@openagentpack/project-workspace": "0.4.0", "@openagentpack/sdk": "0.4.0", "bailian-cli-core": "workspace:*", "bailian-cli-runtime": "workspace:*", diff --git a/packages/commands/src/commands/managed-agent/_engine/playground-launcher.ts b/packages/commands/src/commands/managed-agent/_engine/playground-launcher.ts index 37198a3..69c83a2 100644 --- a/packages/commands/src/commands/managed-agent/_engine/playground-launcher.ts +++ b/packages/commands/src/commands/managed-agent/_engine/playground-launcher.ts @@ -13,7 +13,8 @@ const PLAYGROUND_URL_PATTERN = /running at http:\/\/localhost:(\d+)/i; export interface PlaygroundLaunchOptions { port?: number; open: boolean; - file: string; + file?: string; + project?: string; agent?: string; surface: "preview" | "workbench"; client: Client; @@ -51,8 +52,10 @@ export async function launchManagedAgentPlayground( if (!Number.isInteger(port) || port <= 0 || port > 65_535) { throw new BailianError(`Invalid --port '${port}'.`, ExitCode.USAGE); } - const configPath = resolve(options.file); - const projectId = createHash("sha256").update(configPath).digest("hex").slice(0, 16); + const sourcePath = resolve( + options.surface === "workbench" ? (options.project ?? ".") : (options.file ?? "agents.yaml"), + ); + const projectId = createHash("sha256").update(sourcePath).digest("hex").slice(0, 16); const launcher = resolveLauncher(); const existing = await probeExistingPlayground(port); if (existing) { @@ -74,7 +77,7 @@ export async function launchManagedAgentPlayground( } } - const environment = buildPlaygroundEnvironment(options, port, configPath); + const environment = buildPlaygroundEnvironment(options, port, sourcePath); if (launcher.fetched) { emitBare(`Fetching ${PLAYGROUND_PACKAGE} (first run may take a moment)...`); } @@ -214,15 +217,21 @@ function findLocalPlaygroundBin(startDirectory: string): string | undefined { function buildPlaygroundEnvironment( options: PlaygroundLaunchOptions, port: number, - configPath: string, + sourcePath: string, ): NodeJS.ProcessEnv { const credential = options.client.exportApiCredential(); const environment: NodeJS.ProcessEnv = { ...process.env, PORT: String(port), - AGENTS_CONFIG_PATH: configPath, AGENTS_PLAYGROUND_TOKEN: randomBytes(32).toString("hex"), }; + if (options.surface === "workbench") { + delete environment.AGENTS_CONFIG_PATH; + environment.AGENTS_PROJECT_ROOT = sourcePath; + } else { + delete environment.AGENTS_PROJECT_ROOT; + environment.AGENTS_CONFIG_PATH = sourcePath; + } if (credential) environment.DASHSCOPE_API_KEY = credential.token; const baseUrl = options.client.baseUrl.replace(/\/+$/, ""); environment.BAILIAN_BASE_URL = baseUrl.endsWith("/api/v1/agentstudio") diff --git a/packages/commands/src/commands/managed-agent/apply.ts b/packages/commands/src/commands/managed-agent/apply.ts index 884a2b8..3f81d02 100644 --- a/packages/commands/src/commands/managed-agent/apply.ts +++ b/packages/commands/src/commands/managed-agent/apply.ts @@ -16,13 +16,6 @@ import { import { withStdoutProtected } from "./_engine/console-capture.ts"; import { withAgentErrors } from "./_engine/errors.ts"; import { renderAgentFeedback } from "./_engine/feedback.ts"; -import { - commitPreparedProjectVersion, - type PreparedProjectVersion, - prepareProjectVersion, - readProjectVersionSource, - releasePreparedProjectVersion, -} from "@openagentpack/project-versions"; const APPLY_FLAGS = { file: { @@ -105,9 +98,7 @@ export default defineCommand({ return; } - const versionSource = await readProjectVersionSource(file); - - const { planned, runtime } = await withAgentErrors(() => + const planned = await withAgentErrors(() => withStdoutProtected(async () => { const runtime = await buildAgentRuntime(ctx, file); assertProviderConfigured(runtime, flags.provider); @@ -117,7 +108,7 @@ export default defineCommand({ quiet: true, onFeedback: renderAgentFeedback, }); - return { planned, runtime }; + return planned; }), ); @@ -137,13 +128,6 @@ export default defineCommand({ const actionable = plan.actions.filter((action) => action.action !== "no-op"); if (actionable.length === 0) { - if (!flags.refreshOnly) { - const preparedVersion = await prepareProjectVersion( - runtime.configPath, - versionSource.source, - ); - await commitSuccessfulApplyVersion(preparedVersion, format); - } if (format === "json") emitResult({ succeeded: 0, failed: 0, skipped: 0, results: [] }, format); else emitBare("No changes. Infrastructure is up-to-date."); @@ -184,50 +168,31 @@ export default defineCommand({ ); } - const preparedVersion = await prepareProjectVersion(runtime.configPath, versionSource.source); - let versionCommitted = false; - try { - const result = await withAgentErrors(() => - withStdoutProtected(() => - executePlannedProject(planned, { - onFeedback: renderAgentFeedback, - policy: "force", - concurrency: flags.concurrency, - }), - ), + const result = await withAgentErrors(() => + withStdoutProtected(() => + executePlannedProject(planned, { + onFeedback: renderAgentFeedback, + policy: "force", + concurrency: flags.concurrency, + }), + ), + ); + + const succeeded = result.results.filter((entry) => entry.status === "success").length; + const failed = result.results.filter((entry) => entry.status === "failed").length; + const skipped = result.results.filter((entry) => entry.status === "skipped").length; + + if (format === "json") { + emitResult({ succeeded, failed, skipped, results: result.results }, format); + } else { + emitBare(`\nApply finished: ${succeeded} succeeded, ${failed} failed, ${skipped} skipped.`); + } + + if (failed > 0 || skipped > 0) { + throw new BailianError( + failed > 0 ? "Apply failed." : "Apply incomplete: one or more actions were skipped.", + ExitCode.GENERAL, ); - - const succeeded = result.results.filter((entry) => entry.status === "success").length; - const failed = result.results.filter((entry) => entry.status === "failed").length; - const skipped = result.results.filter((entry) => entry.status === "skipped").length; - - if (format === "json") { - emitResult({ succeeded, failed, skipped, results: result.results }, format); - } else { - emitBare(`\nApply finished: ${succeeded} succeeded, ${failed} failed, ${skipped} skipped.`); - } - - if (failed > 0 || skipped > 0) { - throw new BailianError( - failed > 0 ? "Apply failed." : "Apply incomplete: one or more actions were skipped.", - ExitCode.GENERAL, - ); - } - await commitSuccessfulApplyVersion(preparedVersion, format); - versionCommitted = true; - } finally { - if (!versionCommitted) await releasePreparedProjectVersion(preparedVersion); } }, }); - -async function commitSuccessfulApplyVersion( - prepared: PreparedProjectVersion | null, - format: "text" | "json", -): Promise { - if (!prepared) return; - const version = await commitPreparedProjectVersion(prepared); - if (version && format !== "json") { - emitBare(`Created local version ${version.short_version} (${version.message}).`); - } -} diff --git a/packages/commands/src/commands/managed-agent/project.ts b/packages/commands/src/commands/managed-agent/project.ts new file mode 100644 index 0000000..50e1070 --- /dev/null +++ b/packages/commands/src/commands/managed-agent/project.ts @@ -0,0 +1,443 @@ +import { + BailianError, + defineCommand, + detectOutputFormat, + ExitCode, + type FlagsDef, +} from "bailian-cli-core"; +import { confirmDangerousAction, emitBare, emitResult } from "bailian-cli-runtime"; +import { + commitProjectBuild, + createDirectoryWorkspaceVersionService, + executeProjectPublish, + initializeDirectoryProject, + planProjectPublish, + previewProjectBuild, + validateDirectoryProject, +} from "@openagentpack/project-workspace"; +import { CREDENTIALS_NOTE, resolveAgentProjectConfig } from "./_engine/config-loader.ts"; +import { withStdoutProtected } from "./_engine/console-capture.ts"; +import { withAgentErrors } from "./_engine/errors.ts"; +import { renderAgentFeedback } from "./_engine/feedback.ts"; +import { launchManagedAgentPlayground } from "./_engine/playground-launcher.ts"; +import { installSdkTransport } from "./_engine/transport.ts"; +import { formatResourceLabel } from "./_engine/address-utils.ts"; + +const PROJECT_FLAG = { + project: { + type: "string", + valueHint: "", + description: { + "en-US": "Directory project root (default: current directory)", + "zh-CN": "目录项目根路径(默认:当前目录)", + }, + }, +} satisfies FlagsDef; + +const JSON_FORMAT = "json" as const; + +export const managedAgentProjectInit = defineCommand({ + description: { + "en-US": "Create a directory project or convert the local agents.yaml", + "zh-CN": "创建目录项目,或转换当前 agents.yaml", + }, + auth: "none", + usageArgs: "[--project ] [--provider bailian]", + flags: { + ...PROJECT_FLAG, + provider: { + type: "string", + valueHint: "", + description: { "en-US": "Provider for a new project", "zh-CN": "新项目使用的 Provider" }, + }, + }, + exampleArgs: ["", "--project ./my-agent", "--provider bailian"], + async run(ctx) { + if (ctx.settings.dryRun) { + emitResult( + { would_initialize_project: ctx.flags.project ?? "." }, + detectOutputFormat(ctx.settings.output), + ); + return; + } + const result = await initializeDirectoryProject({ + projectRoot: ctx.flags.project ?? ".", + provider: ctx.flags.provider ?? "bailian", + }); + emitResult(result, detectOutputFormat(ctx.settings.output)); + }, +}); + +export const managedAgentProjectValidate = defineCommand({ + description: { "en-US": "Validate a directory Agent project", "zh-CN": "校验目录式 Agent 项目" }, + auth: "none", + usageArgs: "[--project ]", + flags: PROJECT_FLAG, + exampleArgs: ["", "--project ./my-agent"], + async run(ctx) { + const result = await validateDirectoryProject(ctx.flags.project ?? "."); + const format = detectOutputFormat(ctx.settings.output); + if (format === JSON_FORMAT) emitResult(safeInspection(result), format); + else { + for (const diagnostic of [...result.diagnostics, ...result.warnings]) { + emitBare(`${diagnostic.severity}: ${diagnostic.code}: ${diagnostic.message}`); + } + if (!result.diagnostics.some((diagnostic) => diagnostic.severity === "error")) { + emitBare(`Project is valid (${result.project_revision.slice(0, 12)}).`); + } + } + if (result.diagnostics.some((diagnostic) => diagnostic.severity === "error")) { + throw new BailianError("Directory project validation failed.", ExitCode.GENERAL); + } + }, +}); + +export const managedAgentProjectBuild = defineCommand({ + description: { + "en-US": "Organize directory source and generate the immutable Publish Build", + "zh-CN": "整理目录源文件并生成不可变的发布 Build", + }, + auth: "none", + usageArgs: "[--project ] [--yes]", + flags: { + ...PROJECT_FLAG, + yes: { + type: "switch", + description: { "en-US": "Write the previewed Build", "zh-CN": "写入已预览的 Build" }, + }, + }, + exampleArgs: ["--dry-run", "--yes", "--project ./my-agent --yes"], + async run(ctx) { + const root = ctx.flags.project ?? "."; + const preview = await previewProjectBuild(root); + const format = detectOutputFormat(ctx.settings.output); + if (ctx.settings.dryRun) { + emitResult(safeInspection(preview), format); + return; + } + if (!preview.can_build) + throw new BailianError("Directory project is invalid and cannot be built.", ExitCode.GENERAL); + if (!ctx.flags.yes) { + throw new BailianError( + "Build requires confirmation before it organizes shared skills and writes generated YAML.", + ExitCode.USAGE, + "Preview with --dry-run, then rerun with --yes.", + ); + } + const built = await commitProjectBuild({ + projectRoot: root, + baseRevision: preview.project_revision, + }); + emitResult( + { manifest: built.manifest, organization_moves: preview.organization_moves }, + format, + ); + }, +}); + +export const managedAgentProjectPublish = defineCommand({ + description: { + "en-US": "Publish the current directory-project Build and record a version", + "zh-CN": "发布当前目录项目 Build 并记录版本", + }, + auth: "apiKey", + usageArgs: + "[--project ] [--provider ] [--yes] [--no-refresh] [--concurrency ]", + flags: { + ...PROJECT_FLAG, + provider: { + type: "string", + valueHint: "", + description: { "en-US": "Target provider", "zh-CN": "目标 Provider" }, + }, + yes: { + type: "switch", + description: { "en-US": "Confirm remote Publish", "zh-CN": "确认执行远端发布" }, + }, + noRefresh: { + type: "switch", + description: { + "en-US": "Skip remote refresh before planning", + "zh-CN": "规划前跳过远端刷新", + }, + }, + concurrency: { + type: "number", + valueHint: "", + description: { + "en-US": "Maximum parallel resource operations", + "zh-CN": "最大并行资源操作数", + }, + }, + }, + exampleArgs: ["--yes", "--project ./my-agent --yes", "--provider bailian --yes"], + notes: CREDENTIALS_NOTE, + async run(ctx) { + installSdkTransport(ctx); + const root = ctx.flags.project ?? "."; + const resolveBuild = (buildPath: string) => resolveAgentProjectConfig(ctx, buildPath); + const planned = await withAgentErrors(() => + withStdoutProtected(() => + planProjectPublish(root, { + provider: ctx.flags.provider, + refresh: !ctx.flags.noRefresh, + quiet: true, + onFeedback: renderAgentFeedback, + resolveBuild, + }), + ), + ); + const actions = planned.planned.plan.actions.filter((action) => action.action !== "no-op"); + if (ctx.settings.dryRun) { + emitResult( + { + project_revision: planned.project_revision, + build_manifest: planned.build_manifest, + plan: planned.planned.plan, + }, + detectOutputFormat(ctx.settings.output), + ); + return; + } + for (const action of actions) { + const marker = action.action === "create" ? "+" : action.action === "update" ? "~" : "-"; + emitBare(`${marker} ${formatResourceLabel(action.address)}`); + } + if (!ctx.flags.yes) { + throw new BailianError( + `Refusing to Publish ${actions.length} remote change(s) without confirmation.`, + ExitCode.USAGE, + "Review with project publish --dry-run, then rerun with --yes.", + ); + } + const result = await withAgentErrors(() => + withStdoutProtected(() => + executeProjectPublish({ + projectRoot: planned.project_root, + expectedProjectRevision: planned.project_revision, + expectedYamlHash: planned.build_manifest.yaml_hash, + provider: ctx.flags.provider, + refresh: !ctx.flags.noRefresh, + concurrency: ctx.flags.concurrency, + policy: "force", + onFeedback: renderAgentFeedback, + resolveBuild, + }), + ), + ); + emitResult(result, detectOutputFormat(ctx.settings.output)); + }, +}); + +export const managedAgentProjectWorkbench = defineCommand({ + description: { + "en-US": "Launch the directory project Workbench", + "zh-CN": "启动目录项目 Workbench", + }, + auth: "apiKey", + usageArgs: "[--project ] [--port ] [--no-open]", + flags: { + ...PROJECT_FLAG, + port: { + type: "number", + valueHint: "", + description: { "en-US": "Local port (default: 4848)", "zh-CN": "本地端口(默认:4848)" }, + }, + noOpen: { + type: "switch", + description: { "en-US": "Do not open a browser", "zh-CN": "不自动打开浏览器" }, + }, + }, + exampleArgs: ["", "--project ./my-agent --no-open"], + notes: CREDENTIALS_NOTE, + async run(ctx) { + const root = ctx.flags.project ?? "."; + if (ctx.settings.dryRun) { + emitResult( + { would_launch: "workbench", project_root: root, port: ctx.flags.port ?? 4848 }, + detectOutputFormat(ctx.settings.output), + ); + return; + } + await launchManagedAgentPlayground({ + project: root, + port: ctx.flags.port ?? 4848, + open: !ctx.flags.noOpen, + surface: "workbench", + client: ctx.client, + settings: ctx.settings, + }); + }, +}); + +export const managedAgentProjectVersionEnable = versionToggleCommand(true); +export const managedAgentProjectVersionDisable = versionToggleCommand(false); + +function versionToggleCommand(enabled: boolean) { + return defineCommand({ + description: enabled + ? { "en-US": "Enable directory project versions", "zh-CN": "启用目录项目版本管理" } + : { "en-US": "Disable directory project versions", "zh-CN": "关闭目录项目版本管理" }, + auth: "none", + usageArgs: "[--project ]", + flags: PROJECT_FLAG, + exampleArgs: ["", "--project ./my-agent"], + async run(ctx) { + const service = createDirectoryWorkspaceVersionService(ctx.flags.project ?? "."); + if (ctx.settings.dryRun) { + emitResult( + { would_set_enabled: enabled, status: await service.status() }, + detectOutputFormat(ctx.settings.output), + ); + return; + } + const result = enabled + ? await service.enable("Enable project versions") + : await service.disable(); + emitResult(result, detectOutputFormat(ctx.settings.output)); + }, + }); +} + +export const managedAgentProjectVersionStatus = defineCommand({ + description: { + "en-US": "Show directory project version status", + "zh-CN": "显示目录项目版本状态", + }, + auth: "none", + usageArgs: "[--project ]", + flags: PROJECT_FLAG, + exampleArgs: ["", "--project ./my-agent --output json"], + async run(ctx) { + emitResult( + await createDirectoryWorkspaceVersionService(ctx.flags.project ?? ".").status(), + detectOutputFormat(ctx.settings.output), + ); + }, +}); + +export const managedAgentProjectVersionList = defineCommand({ + description: { "en-US": "List directory project versions", "zh-CN": "列出目录项目版本" }, + auth: "none", + usageArgs: "[--project ] [--limit ] [--cursor ]", + flags: { + ...PROJECT_FLAG, + limit: { + type: "number", + valueHint: "", + description: { "en-US": "Maximum versions to return", "zh-CN": "最多返回的版本数" }, + }, + cursor: { + type: "string", + valueHint: "", + description: { "en-US": "Pagination cursor", "zh-CN": "分页游标" }, + }, + }, + exampleArgs: ["", "--limit 20 --output json"], + async run(ctx) { + emitResult( + await createDirectoryWorkspaceVersionService(ctx.flags.project ?? ".").listVersions({ + limit: ctx.flags.limit, + cursor: ctx.flags.cursor, + }), + detectOutputFormat(ctx.settings.output), + ); + }, +}); + +const VERSION_ID_FLAG = { + versionId: { + type: "string", + valueHint: "", + required: true, + description: { "en-US": "Full project version ID", "zh-CN": "完整的项目版本 ID" }, + }, +} satisfies FlagsDef; + +export const managedAgentProjectVersionPreview = defineCommand({ + description: { "en-US": "Preview a directory project version", "zh-CN": "预览目录项目历史版本" }, + auth: "none", + usageArgs: "--version-id [--project ]", + flags: { ...PROJECT_FLAG, ...VERSION_ID_FLAG }, + exampleArgs: ["--version-id "], + async run(ctx) { + emitResult( + await createDirectoryWorkspaceVersionService(ctx.flags.project ?? ".").previewVersion( + ctx.flags.versionId, + ), + detectOutputFormat(ctx.settings.output), + ); + }, +}); + +export const managedAgentProjectVersionRestore = defineCommand({ + description: { + "en-US": "Restore a version to the project working directory", + "zh-CN": "将历史版本恢复到项目工作目录", + }, + auth: "none", + usageArgs: "--version-id [--project ] [--yes]", + flags: { + ...PROJECT_FLAG, + ...VERSION_ID_FLAG, + yes: { + type: "switch", + description: { + "en-US": "Restore without interactive confirmation", + "zh-CN": "无需交互确认直接恢复", + }, + }, + }, + exampleArgs: ["--version-id ", "--version-id --yes"], + async run(ctx) { + const service = createDirectoryWorkspaceVersionService(ctx.flags.project ?? "."); + const preview = await service.previewVersion(ctx.flags.versionId); + if (!preview.can_restore) + throw new BailianError( + preview.blockers[0] ?? preview.diagnostics[0]?.message ?? "Version cannot be restored.", + ExitCode.GENERAL, + ); + if (ctx.settings.dryRun) { + emitResult( + { would_restore: ctx.flags.versionId, preview }, + detectOutputFormat(ctx.settings.output), + ); + return; + } + await confirmDangerousAction( + "Restore the full directory source? Version history and remote State will not move.", + ctx.flags.yes, + ); + const restored = await service.restoreVersion(ctx.flags.versionId, { + headVersion: preview.base_head_version, + projectRevision: preview.base_project_revision, + }); + emitResult(restored, detectOutputFormat(ctx.settings.output)); + }, +}); + +function safeInspection(result: { + project_root: string; + project_revision: string; + source_manifest_hash: string; + yaml_hash: string; + diagnostics: unknown[]; + warnings: unknown[]; + organization_moves: unknown[]; + canonical_yaml: string; + before_yaml?: string; + can_build?: boolean; +}) { + return { + project_root: result.project_root, + project_revision: result.project_revision, + source_manifest_hash: result.source_manifest_hash, + yaml_hash: result.yaml_hash, + diagnostics: result.diagnostics, + warnings: result.warnings, + organization_moves: result.organization_moves, + before_yaml: "before_yaml" in result ? result.before_yaml : undefined, + after_yaml: result.canonical_yaml, + can_build: "can_build" in result ? result.can_build : undefined, + }; +} diff --git a/packages/commands/src/commands/managed-agent/version.ts b/packages/commands/src/commands/managed-agent/version.ts deleted file mode 100644 index 5ca51e2..0000000 --- a/packages/commands/src/commands/managed-agent/version.ts +++ /dev/null @@ -1,362 +0,0 @@ -import { - BailianError, - defineCommand, - detectOutputFormat, - ExitCode, - type FlagsDef, -} from "bailian-cli-core"; -import { confirmDangerousAction, emitBare, emitResult } from "bailian-cli-runtime"; -import chalk from "chalk"; -import { - disableProjectVersioning, - enableProjectVersioning, - getProjectVersionStatus, - type ProjectVersion, - type ProjectVersionPreview, - type ProjectVersionStatus, - listProjectVersions, - previewProjectVersion, - restoreProjectVersion, -} from "@openagentpack/project-versions"; - -const FILE_FLAG = { - file: { - type: "string", - valueHint: "", - description: { - "en-US": "Config file path (default: agents.yaml)", - "zh-CN": "配置文件路径(默认:agents.yaml)", - }, - }, -} satisfies FlagsDef; - -const VERSION_FLAG = { - versionId: { - type: "string", - valueHint: "", - required: true, - description: { - "en-US": "Full local version ID", - "zh-CN": "完整的本地版本 ID", - }, - }, -} satisfies FlagsDef; - -export const managedAgentVersionEnable = defineCommand({ - description: { - "en-US": "Enable Apply-time local snapshots for agents.yaml", - "zh-CN": "为 agents.yaml 启用 Apply 后自动本地快照", - }, - auth: "none", - usageArgs: "[--file ]", - flags: FILE_FLAG, - exampleArgs: ["", "--file agents.yaml"], - async run(ctx) { - const file = ctx.flags.file ?? "agents.yaml"; - const format = detectOutputFormat(ctx.settings.output); - if (ctx.settings.dryRun) { - emitResult({ would_enable: file, versioning: await getProjectVersionStatus(file) }, format); - return; - } - const result = await enableProjectVersioning(file, "Enable Bailian CLI versioning"); - if (format === "json") { - emitResult(result, format); - return; - } - if (result.version) { - emitBare( - `Created baseline version ${result.version.short_version} ${result.version.message}`, - ); - } else { - emitBare("Current agents.yaml is already versioned; no snapshot was created."); - } - emitBare("Automatic versioning is enabled for this agents.yaml."); - renderStatus(result.versioning); - }, -}); - -export const managedAgentVersionDisable = defineCommand({ - description: { - "en-US": "Disable Apply-time local snapshots without removing history", - "zh-CN": "关闭 Apply 后自动本地快照,但保留历史", - }, - auth: "none", - usageArgs: "[--file ]", - flags: FILE_FLAG, - exampleArgs: ["", "--file agents.yaml"], - async run(ctx) { - const file = ctx.flags.file ?? "agents.yaml"; - const format = detectOutputFormat(ctx.settings.output); - if (ctx.settings.dryRun) { - emitResult({ would_disable: file, versioning: await getProjectVersionStatus(file) }, format); - return; - } - const status = await disableProjectVersioning(file); - if (format === "json") { - emitResult(status, format); - return; - } - emitBare("Automatic versioning is disabled for this agents.yaml."); - renderStatus(status); - }, -}); - -export const managedAgentVersionStatus = defineCommand({ - description: { - "en-US": "Show local snapshot versioning status for agents.yaml", - "zh-CN": "显示 agents.yaml 的本地快照版本管理状态", - }, - auth: "none", - usageArgs: "[--file ]", - flags: FILE_FLAG, - exampleArgs: ["", "--file agents.yaml --output json"], - async run(ctx) { - const status = await getProjectVersionStatus(ctx.flags.file ?? "agents.yaml"); - const format = detectOutputFormat(ctx.settings.output); - if (format === "json") emitResult(status, format); - else renderStatus(status); - }, -}); - -const LIST_FLAGS = { - ...FILE_FLAG, - limit: { - type: "number", - valueHint: "", - description: { - "en-US": "Maximum versions to return (default: 50, max: 100)", - "zh-CN": "最多返回的版本数(默认:50,最大:100)", - }, - }, - cursor: { - type: "string", - valueHint: "", - description: { - "en-US": "Pagination cursor returned by the previous page", - "zh-CN": "上一页返回的分页游标", - }, - }, -} satisfies FlagsDef; - -export const managedAgentVersionList = defineCommand({ - description: { - "en-US": "List local snapshots of agents.yaml", - "zh-CN": "列出 agents.yaml 的本地快照", - }, - auth: "none", - usageArgs: "[--file ] [--limit ] [--cursor ]", - flags: LIST_FLAGS, - exampleArgs: ["", "--limit 20 --output json"], - async run(ctx) { - const page = await listProjectVersions(ctx.flags.file ?? "agents.yaml", { - limit: ctx.flags.limit, - cursor: ctx.flags.cursor, - }); - const format = detectOutputFormat(ctx.settings.output); - if (format === "json") { - emitResult(page, format); - return; - } - if (page.versions.length === 0) { - emitBare("No local versions of agents.yaml exist."); - return; - } - for (const version of page.versions) emitBare(formatVersion(version)); - if (page.next_cursor) emitBare(chalk.dim(`Next cursor: ${page.next_cursor}`)); - }, -}); - -const PREVIEW_FLAGS = { - ...FILE_FLAG, - ...VERSION_FLAG, -} satisfies FlagsDef; - -export const managedAgentVersionPreview = defineCommand({ - description: { - "en-US": "Preview a historical agents.yaml version", - "zh-CN": "预览 agents.yaml 的历史版本", - }, - auth: "none", - usageArgs: "--version-id [--file ]", - flags: PREVIEW_FLAGS, - exampleArgs: ["--version-id ", "--version-id --output json"], - async run(ctx) { - const preview = await previewProjectVersion( - ctx.flags.file ?? "agents.yaml", - ctx.flags.versionId, - ); - const format = detectOutputFormat(ctx.settings.output); - if (format === "json") emitResult(preview, format); - else renderPreview(preview); - }, -}); - -const RESTORE_FLAGS = { - ...PREVIEW_FLAGS, - yes: { - type: "switch", - description: { - "en-US": "Restore without an interactive confirmation", - "zh-CN": "无需交互确认直接恢复", - }, - }, -} satisfies FlagsDef; - -export const managedAgentVersionRestore = defineCommand({ - description: { - "en-US": "Restore a historical agents.yaml version to the working tree", - "zh-CN": "将 agents.yaml 历史版本恢复到工作区", - }, - auth: "none", - usageArgs: "--version-id [--file ] [--yes]", - flags: RESTORE_FLAGS, - exampleArgs: ["--version-id ", "--version-id --yes --output json"], - async run(ctx) { - const file = ctx.flags.file ?? "agents.yaml"; - const preview = await previewProjectVersion(file, ctx.flags.versionId); - const format = detectOutputFormat(ctx.settings.output); - if (format !== "json") renderPreview(preview); - if (!preview.can_restore) { - throw new BailianError( - preview.diagnostics.find((diagnostic) => diagnostic.severity === "error")?.message ?? - preview.blockers[0] ?? - "This version cannot be restored.", - ExitCode.GENERAL, - ); - } - if (ctx.settings.dryRun) { - emitResult({ would_restore: ctx.flags.versionId, preview }, format); - return; - } - await confirmDangerousAction( - "Restore this version to the agents.yaml working tree? Version history and agents.state.json will not change.", - ctx.flags.yes, - ); - const restored = await restoreProjectVersion(file, ctx.flags.versionId, { - headVersion: preview.base_head_version, - sourceRevision: preview.base_source_revision, - }); - if (format === "json") { - emitResult({ restored: ctx.flags.versionId, preview: restored }, format); - } else { - emitBare( - `Restored ${ctx.flags.versionId.slice(0, 12)} to the working tree. Version history was not changed.`, - ); - } - }, -}); - -function renderStatus(status: ProjectVersionStatus): void { - emitBare(`Automatic versioning: ${status.enabled ? "enabled" : "disabled"}`); - emitBare(`Version store: ${status.initialized ? status.store_root : "not initialized"}`); - emitBare(`Config path: ${status.config_path}`); - emitBare(`Current version: ${status.head_version ?? "none"}`); - emitBare( - `agents.yaml: ${status.source_status}${status.source_versioned ? ", versioned" : ", unversioned"}`, - ); - const blockers = [...new Set([...status.write_blockers, ...status.restore_blockers])]; - for (const blocker of blockers) emitBare(chalk.yellow(`Blocker: ${blocker}`)); -} - -function formatVersion(version: ProjectVersion): string { - return `${chalk.yellow(version.short_version)} ${version.created_at} ${version.message} ${chalk.dim(`(${version.created_by})`)}`; -} - -function renderPreview(preview: ProjectVersionPreview): void { - emitBare(chalk.bold(`Version ${preview.version_id}`)); - emitBare(chalk.red("--- working tree")); - emitBare(chalk.green(`+++ ${preview.version_id}`)); - for (const line of buildLineDiff(preview.before_yaml, preview.after_yaml)) { - if (line.kind === "deletion") emitBare(chalk.red(`-${line.text}`)); - else if (line.kind === "addition") emitBare(chalk.green(`+${line.text}`)); - else emitBare(chalk.dim(` ${line.text}`)); - } - for (const diagnostic of preview.diagnostics) { - const color = - diagnostic.severity === "error" - ? chalk.red - : diagnostic.severity === "warning" - ? chalk.yellow - : chalk.dim; - emitBare(color(`${diagnostic.severity}: ${diagnostic.code}: ${diagnostic.message}`)); - } - for (const blocker of preview.blockers) emitBare(chalk.yellow(`blocker: ${blocker}`)); - emitBare(`Can restore: ${preview.can_restore ? "yes" : "no"}`); -} - -type DiffLine = { kind: "context" | "addition" | "deletion"; text: string }; - -function buildLineDiff(beforeSource: string, afterSource: string): DiffLine[] { - const beforeLines = yamlLines(beforeSource); - const afterLines = yamlLines(afterSource); - const maximumDistance = beforeLines.length + afterLines.length; - const frontier = new Map([[1, 0]]); - const traces: Array> = []; - - for (let editDistance = 0; editDistance <= maximumDistance; editDistance += 1) { - traces.push(new Map(frontier)); - for (let diagonal = -editDistance; diagonal <= editDistance; diagonal += 2) { - const deletionStart = frontier.get(diagonal - 1) ?? Number.NEGATIVE_INFINITY; - const additionStart = frontier.get(diagonal + 1) ?? Number.NEGATIVE_INFINITY; - const startsWithAddition = - diagonal === -editDistance || (diagonal !== editDistance && deletionStart < additionStart); - let beforeIndex = startsWithAddition ? (frontier.get(diagonal + 1) ?? 0) : deletionStart + 1; - let afterIndex = beforeIndex - diagonal; - while ( - beforeIndex < beforeLines.length && - afterIndex < afterLines.length && - beforeLines[beforeIndex] === afterLines[afterIndex] - ) { - beforeIndex += 1; - afterIndex += 1; - } - frontier.set(diagonal, beforeIndex); - if (beforeIndex >= beforeLines.length && afterIndex >= afterLines.length) { - return backtrackDiff(beforeLines, afterLines, traces, editDistance); - } - } - } - return []; -} - -function backtrackDiff( - beforeLines: string[], - afterLines: string[], - traces: Array>, - finalDistance: number, -): DiffLine[] { - let beforeIndex = beforeLines.length; - let afterIndex = afterLines.length; - const reversedLines: DiffLine[] = []; - for (let editDistance = finalDistance; editDistance >= 0; editDistance -= 1) { - const frontier = traces[editDistance]!; - const diagonal = beforeIndex - afterIndex; - const deletionStart = frontier.get(diagonal - 1) ?? Number.NEGATIVE_INFINITY; - const additionStart = frontier.get(diagonal + 1) ?? Number.NEGATIVE_INFINITY; - const cameFromAddition = - diagonal === -editDistance || (diagonal !== editDistance && deletionStart < additionStart); - const previousDiagonal = cameFromAddition ? diagonal + 1 : diagonal - 1; - const previousBeforeIndex = frontier.get(previousDiagonal) ?? 0; - const previousAfterIndex = previousBeforeIndex - previousDiagonal; - while (beforeIndex > previousBeforeIndex && afterIndex > previousAfterIndex) { - reversedLines.push({ kind: "context", text: beforeLines[beforeIndex - 1]! }); - beforeIndex -= 1; - afterIndex -= 1; - } - if (editDistance === 0) break; - if (beforeIndex === previousBeforeIndex) { - reversedLines.push({ kind: "addition", text: afterLines[afterIndex - 1]! }); - afterIndex -= 1; - } else { - reversedLines.push({ kind: "deletion", text: beforeLines[beforeIndex - 1]! }); - beforeIndex -= 1; - } - } - return reversedLines.reverse(); -} - -function yamlLines(source: string): string[] { - const lines = source.split("\n"); - if (lines[lines.length - 1] === "") lines.pop(); - return lines; -} diff --git a/packages/commands/src/commands/managed-agent/workbench.ts b/packages/commands/src/commands/managed-agent/workbench.ts index 08f806c..7c3ed00 100644 --- a/packages/commands/src/commands/managed-agent/workbench.ts +++ b/packages/commands/src/commands/managed-agent/workbench.ts @@ -3,7 +3,7 @@ import { emitResult } from "bailian-cli-runtime"; import { CREDENTIALS_NOTE } from "./_engine/config-loader.ts"; import { launchManagedAgentPlayground } from "./_engine/playground-launcher.ts"; -const WORKBENCH_FLAGS = { +const PLAYGROUND_BASE_FLAGS = { file: { type: "string", valueHint: "", @@ -30,7 +30,7 @@ const WORKBENCH_FLAGS = { } satisfies FlagsDef; const PLAYGROUND_FLAGS = { - ...WORKBENCH_FLAGS, + ...PLAYGROUND_BASE_FLAGS, agent: { type: "string", valueHint: "", @@ -41,52 +41,16 @@ const PLAYGROUND_FLAGS = { }, } satisfies FlagsDef; -const WORKBENCH_NOTES = [ +const PLAYGROUND_NOTES = [ ...CREDENTIALS_NOTE, { "en-US": - "Workbench requires Node.js 22+ and starts the shared @openagentpack/playground package locally. Local versions use the shared .openagentpack/versions project store and do not require Git.", + "Session Preview requires Node.js 22+ and keeps using an agents.yaml source. Directory Workbench is available under managed-agent project workbench.", "zh-CN": - "Workbench 需要 Node.js 22+,并在本地启动共享的 @openagentpack/playground 包;本地版本使用共享的 .openagentpack/versions 项目版本存储,不依赖 Git。", + "会话预览需要 Node.js 22+,并继续使用 agents.yaml;目录 Workbench 位于 managed-agent project workbench。", }, ]; -export const managedAgentWorkbench = defineCommand({ - description: { - "en-US": "Launch the agents.yaml project Workbench", - "zh-CN": "启动 agents.yaml 项目 Workbench", - }, - auth: "apiKey", - usageArgs: "[--file ] [--port ] [--no-open]", - flags: WORKBENCH_FLAGS, - exampleArgs: ["", "--file agents.yaml --no-open", "--port 4949"], - notes: WORKBENCH_NOTES, - async run(ctx) { - const file = ctx.flags.file ?? "agents.yaml"; - const port = ctx.flags.port ?? 4848; - if (ctx.settings.dryRun) { - emitResult( - { - would_launch: "workbench", - config_file: file, - port, - open_browser: !ctx.flags.noOpen, - }, - detectOutputFormat(ctx.settings.output), - ); - return; - } - await launchManagedAgentPlayground({ - file, - port, - open: !ctx.flags.noOpen, - surface: "workbench", - client: ctx.client, - settings: ctx.settings, - }); - }, -}); - export const managedAgentPlayground = defineCommand({ description: { "en-US": "Launch a Session Preview for an agents.yaml Agent", @@ -96,7 +60,7 @@ export const managedAgentPlayground = defineCommand({ usageArgs: "[--file ] [--agent ] [--port ] [--no-open]", flags: PLAYGROUND_FLAGS, exampleArgs: ["", "--agent assistant", "--file agents.yaml --no-open"], - notes: WORKBENCH_NOTES, + notes: PLAYGROUND_NOTES, async run(ctx) { const file = ctx.flags.file ?? "agents.yaml"; const port = ctx.flags.port ?? 4848; diff --git a/packages/commands/src/index.ts b/packages/commands/src/index.ts index abf3587..074928f 100644 --- a/packages/commands/src/index.ts +++ b/packages/commands/src/index.ts @@ -136,18 +136,20 @@ export { default as managedAgentValidate } from "./commands/managed-agent/valida export { default as managedAgentPlan } from "./commands/managed-agent/plan.ts"; export { default as managedAgentApply } from "./commands/managed-agent/apply.ts"; export { default as managedAgentDestroy } from "./commands/managed-agent/destroy.ts"; +export { managedAgentPlayground } from "./commands/managed-agent/workbench.ts"; export { - managedAgentPlayground, - managedAgentWorkbench, -} from "./commands/managed-agent/workbench.ts"; -export { - managedAgentVersionDisable, - managedAgentVersionEnable, - managedAgentVersionList, - managedAgentVersionPreview, - managedAgentVersionRestore, - managedAgentVersionStatus, -} from "./commands/managed-agent/version.ts"; + managedAgentProjectBuild, + managedAgentProjectInit, + managedAgentProjectPublish, + managedAgentProjectValidate, + managedAgentProjectVersionDisable, + managedAgentProjectVersionEnable, + managedAgentProjectVersionList, + managedAgentProjectVersionPreview, + managedAgentProjectVersionRestore, + managedAgentProjectVersionStatus, + managedAgentProjectWorkbench, +} from "./commands/managed-agent/project.ts"; export { default as managedAgentStateList } from "./commands/managed-agent/state-list.ts"; export { default as managedAgentStateShow } from "./commands/managed-agent/state-show.ts"; export { default as managedAgentStateRm } from "./commands/managed-agent/state-rm.ts"; diff --git a/packages/commands/tests/e2e/managed-agent.e2e.test.ts b/packages/commands/tests/e2e/managed-agent.e2e.test.ts index fffd535..d1ebc6c 100644 --- a/packages/commands/tests/e2e/managed-agent.e2e.test.ts +++ b/packages/commands/tests/e2e/managed-agent.e2e.test.ts @@ -1,5 +1,7 @@ +import { mkdtemp, readFile, rm, stat } from "node:fs/promises"; +import { tmpdir } from "node:os"; import { join } from "node:path"; -import { describe, expect, test } from "vite-plus/test"; +import { afterEach, describe, expect, test } from "vite-plus/test"; import { e2eFixturesDir, parseStdoutJson, runCommandE2e } from "./helpers.ts"; import { MANAGED_AGENT_ROUTES } from "./topic-routes.ts"; @@ -15,6 +17,13 @@ const DEPLOYMENT_SAFETY_DIAGNOSTIC_CODES = [ "bailian.deployment.file.mount_path.required", "bailian.deployment.file.mount_path.duplicate", ]; +const projectDirectories: string[] = []; + +afterEach(async () => { + for (const directory of projectDirectories.splice(0)) { + await rm(directory, { recursive: true, force: true }); + } +}); /** * managed-agent:help / 缺参不依赖密钥;所有 mutation 命令的 --dry-run @@ -143,19 +152,83 @@ describe("e2e: managed-agent", () => { expect(stderr).not.toContain("--git"); }); - test("managed-agent version 暴露共享版本管理子命令", async () => { + test("managed-agent project 暴露目录项目与共享版本管理子命令", async () => { const { stderr, exitCode } = await runCommandE2e(MANAGED_AGENT_ROUTES, [ "managed-agent", - "version", + "project", "--help", ]); expect(exitCode, stderr).toBe(0); - expect(stderr).toMatch(/enable|disable|status|list|preview|restore/i); + expect(stderr).toMatch(/init|validate|build|publish|workbench|version/i); }); - test("managed-agent version preview 缺少 --version-id 时退出为用法错误 (2)", async () => { + test("managed-agent project 完成 init、validate、build 与 version status 本地闭环", async () => { + const projectRoot = await mkdtemp(join(tmpdir(), "bailian-managed-agent-project-")); + projectDirectories.push(projectRoot); + const initialized = await runCommandE2e(MANAGED_AGENT_ROUTES, [ + "managed-agent", + "project", + "init", + "--project", + projectRoot, + "--provider", + "bailian", + "--output", + "json", + ]); + expect(initialized.exitCode, initialized.stderr).toBe(0); + expect( + parseStdoutJson<{ baseline_version?: string }>(initialized.stdout).baseline_version, + ).toMatch(/^[a-f0-9]{64}$/); + + const validated = await runCommandE2e(MANAGED_AGENT_ROUTES, [ + "managed-agent", + "project", + "validate", + "--project", + projectRoot, + "--output", + "json", + ]); + expect(validated.exitCode, validated.stderr).toBe(0); + expect( + parseStdoutJson<{ diagnostics?: Array<{ severity?: string }> }>(validated.stdout).diagnostics, + ).not.toContainEqual(expect.objectContaining({ severity: "error" })); + + const built = await runCommandE2e(MANAGED_AGENT_ROUTES, [ + "managed-agent", + "project", + "build", + "--project", + projectRoot, + "--yes", + "--output", + "json", + ]); + expect(built.exitCode, built.stderr).toBe(0); + expect(await readFile(join(projectRoot, ".openagentpack/build/agents.yaml"), "utf8")).toContain( + "assistant", + ); + + const status = await runCommandE2e(MANAGED_AGENT_ROUTES, [ + "managed-agent", + "project", + "version", + "status", + "--project", + projectRoot, + "--output", + "json", + ]); + expect(status.exitCode, status.stderr).toBe(0); + expect(parseStdoutJson<{ enabled?: boolean }>(status.stdout).enabled).toBe(true); + expect(await stat(join(projectRoot, ".openagentpack/state.json")).catch(() => null)).toBeNull(); + }); + + test("managed-agent project version preview 缺少 --version-id 时退出为用法错误 (2)", async () => { const { stderr, exitCode } = await runCommandE2e(MANAGED_AGENT_ROUTES, [ "managed-agent", + "project", "version", "preview", "--quiet", @@ -250,11 +323,14 @@ describe("e2e: managed-agent(--dry-run 短路,不联网不写盘)", () => expect(data.provider).toBe("bailian"); }); - test("workbench --dry-run 仅输出启动计划", async () => { + test("project workbench --dry-run 仅输出目录项目启动计划", async () => { const { stdout, stderr, exitCode } = await runCommandE2e(MANAGED_AGENT_ROUTES, [ "managed-agent", + "project", "workbench", "--dry-run", + "--project", + "./agent-project", "--no-open", "--output", "json", @@ -262,10 +338,12 @@ describe("e2e: managed-agent(--dry-run 短路,不联网不写盘)", () => expect(exitCode, stderr).toBe(0); const data = parseStdoutJson<{ would_launch?: string; - open_browser?: boolean; + project_root?: string; + port?: number; }>(stdout); expect(data.would_launch).toBe("workbench"); - expect(data.open_browser).toBe(false); + expect(data.project_root).toBe("./agent-project"); + expect(data.port).toBe(4848); }); test("apply --dry-run 仅输出计划", async () => { diff --git a/packages/commands/tests/e2e/topic-routes.ts b/packages/commands/tests/e2e/topic-routes.ts index df8bf3c..af7ba2b 100644 --- a/packages/commands/tests/e2e/topic-routes.ts +++ b/packages/commands/tests/e2e/topic-routes.ts @@ -186,14 +186,18 @@ export const MANAGED_AGENT_ROUTES: E2eRouteExports = { "managed-agent plan": "managedAgentPlan", "managed-agent apply": "managedAgentApply", "managed-agent destroy": "managedAgentDestroy", - "managed-agent workbench": "managedAgentWorkbench", "managed-agent playground": "managedAgentPlayground", - "managed-agent version enable": "managedAgentVersionEnable", - "managed-agent version disable": "managedAgentVersionDisable", - "managed-agent version status": "managedAgentVersionStatus", - "managed-agent version list": "managedAgentVersionList", - "managed-agent version preview": "managedAgentVersionPreview", - "managed-agent version restore": "managedAgentVersionRestore", + "managed-agent project init": "managedAgentProjectInit", + "managed-agent project validate": "managedAgentProjectValidate", + "managed-agent project build": "managedAgentProjectBuild", + "managed-agent project publish": "managedAgentProjectPublish", + "managed-agent project workbench": "managedAgentProjectWorkbench", + "managed-agent project version enable": "managedAgentProjectVersionEnable", + "managed-agent project version disable": "managedAgentProjectVersionDisable", + "managed-agent project version status": "managedAgentProjectVersionStatus", + "managed-agent project version list": "managedAgentProjectVersionList", + "managed-agent project version preview": "managedAgentProjectVersionPreview", + "managed-agent project version restore": "managedAgentProjectVersionRestore", "managed-agent state list": "managedAgentStateList", "managed-agent state rm": "managedAgentStateRm", "managed-agent state import": "managedAgentStateImport", diff --git a/skills/bailian-managed-agent/SKILL.md b/skills/bailian-managed-agent/SKILL.md index 7317565..a91a2ef 100644 --- a/skills/bailian-managed-agent/SKILL.md +++ b/skills/bailian-managed-agent/SKILL.md @@ -37,21 +37,24 @@ description: >- 5. Destroy bl managed-agent destroy --yes # only after user confirmation ``` -## Workbench and local versions +## Directory projects, Workbench, and local versions -| Intent | Command | -| ---------------------------------------- | ---------------------------------------------- | -| Launch project resource editing | `bl managed-agent workbench` | -| Launch one Agent Session Preview | `bl managed-agent playground --agent ` | -| Enable/disable shared automatic versions | `bl managed-agent version enable` / `disable` | -| Inspect local version state and history | `bl managed-agent version status` / `list` | -| Preview or restore a historical YAML | `bl managed-agent version preview` / `restore` | +| Intent | Command | +| --------------------------------------- | ------------------------------------------------------ | +| Create or convert a directory project | `bl managed-agent project init` | +| Validate and Build directory source | `bl managed-agent project validate` / `build` | +| Publish the current immutable Build | `bl managed-agent project publish --yes` | +| Launch project resource editing | `bl managed-agent project workbench` | +| Launch one Agent Session Preview | `bl managed-agent playground --agent ` | +| Enable/disable project versions | `bl managed-agent project version enable` / `disable` | +| Inspect local version state and history | `bl managed-agent project version status` / `list` | +| Preview or restore project source | `bl managed-agent project version preview` / `restore` | -- Bailian CLI and Workbench use the same `.openagentpack/versions` store and enable switch for the same `agents.yaml`. Git is not required. -- `store.json` contains only the switch and head metadata. Immutable linked entries live under `entries/`, while complete YAML is stored as content-addressed blobs under `blobs/`. Neither `agents.state.json` nor referenced files are versioned. -- When enabled, a fully successful Apply creates a local snapshot only when `agents.yaml` changed. Failed, partial, cancelled, and `--refresh-only` Apply runs do not create one. -- `version restore` writes the historical YAML to the working tree. It does not move version history, restore `agents.state.json`, create a new snapshot, or Apply remote changes. -- Workbench can edit local drafts while Apply is running, but saving/version mutations are blocked until Apply completes. External file edits are detected through revision checks. +- Bailian CLI and Workbench use the same `.openagentpack/versions/project` store and enable switch. Git is not required. +- Build is local-only. Publish never runs Build implicitly and consumes only a current `.openagentpack/build/agents.yaml` plus manifest. +- A successful Publish versions the canonical YAML and the complete project source tree, including Skill scripts/assets and binary files. Remote State is never versioned or restored. +- `project version restore` restores source files to the working directory, invalidates Build, and does not move version history or remote State. +- `managed-agent playground` remains the standalone `agents.yaml` Session Preview path; directory Workbench is only under `managed-agent project workbench`. ## Deployment as IaC diff --git a/skills/bailian-managed-agent/reference/index.md b/skills/bailian-managed-agent/reference/index.md index a79519a..d0604bd 100644 --- a/skills/bailian-managed-agent/reference/index.md +++ b/skills/bailian-managed-agent/reference/index.md @@ -9,39 +9,43 @@ Use this index for the skill-scoped quick index and global flags. ## Quick index -| Command | Authentication | Description | Detail | -| ---------------------------------- | -------------- | ------------------------------------------------------------- | ------------------------------------ | -| `bl managed-agent apply` | API Key | Apply planned changes to create/update/delete agent resources | [managed-agent.md](managed-agent.md) | -| `bl managed-agent destroy` | API Key | Destroy all managed agent resources tracked in state | [managed-agent.md](managed-agent.md) | -| `bl managed-agent init` | No Auth | Create an agents.yaml template | [managed-agent.md](managed-agent.md) | -| `bl managed-agent plan` | API Key | Show what changes would be applied to agent infrastructure | [managed-agent.md](managed-agent.md) | -| `bl managed-agent playground` | API Key | Launch a Session Preview for an agents.yaml Agent | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session create` | API Key | Create a new session for an agent | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session delete` | API Key | Delete a session | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session events` | API Key | List event history for a session | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session get` | API Key | Get details of a session | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session list` | API Key | List sessions from the provider | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session run` | API Key | Create a session, send a message, and stream the response | [managed-agent.md](managed-agent.md) | -| `bl managed-agent session send` | API Key | Send a message to an existing session and stream the response | [managed-agent.md](managed-agent.md) | -| `bl managed-agent skill-list` | API Key | List skills from the provider's skill catalog | [managed-agent.md](managed-agent.md) | -| `bl managed-agent state import` | API Key | Import an existing remote resource into agents state | [managed-agent.md](managed-agent.md) | -| `bl managed-agent state list` | No Auth | List resources tracked in agents state | [managed-agent.md](managed-agent.md) | -| `bl managed-agent state rm` | No Auth | Remove a resource from state without destroying it remotely | [managed-agent.md](managed-agent.md) | -| `bl managed-agent state show` | No Auth | Show details of a resource in agents state | [managed-agent.md](managed-agent.md) | -| `bl managed-agent validate` | No Auth | Validate an agents.yaml configuration (offline) | [managed-agent.md](managed-agent.md) | -| `bl managed-agent version disable` | No Auth | Disable Apply-time local snapshots without removing history | [managed-agent.md](managed-agent.md) | -| `bl managed-agent version enable` | No Auth | Enable Apply-time local snapshots for agents.yaml | [managed-agent.md](managed-agent.md) | -| `bl managed-agent version list` | No Auth | List local snapshots of agents.yaml | [managed-agent.md](managed-agent.md) | -| `bl managed-agent version preview` | No Auth | Preview a historical agents.yaml version | [managed-agent.md](managed-agent.md) | -| `bl managed-agent version restore` | No Auth | Restore a historical agents.yaml version to the working tree | [managed-agent.md](managed-agent.md) | -| `bl managed-agent version status` | No Auth | Show local snapshot versioning status for agents.yaml | [managed-agent.md](managed-agent.md) | -| `bl managed-agent workbench` | API Key | Launch the agents.yaml project Workbench | [managed-agent.md](managed-agent.md) | +| Command | Authentication | Description | Detail | +| ------------------------------------------ | -------------- | ------------------------------------------------------------------ | ------------------------------------ | +| `bl managed-agent apply` | API Key | Apply planned changes to create/update/delete agent resources | [managed-agent.md](managed-agent.md) | +| `bl managed-agent destroy` | API Key | Destroy all managed agent resources tracked in state | [managed-agent.md](managed-agent.md) | +| `bl managed-agent init` | No Auth | Create an agents.yaml template | [managed-agent.md](managed-agent.md) | +| `bl managed-agent plan` | API Key | Show what changes would be applied to agent infrastructure | [managed-agent.md](managed-agent.md) | +| `bl managed-agent playground` | API Key | Launch a Session Preview for an agents.yaml Agent | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project build` | No Auth | Organize directory source and generate the immutable Publish Build | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project init` | No Auth | Create a directory project or convert the local agents.yaml | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project publish` | API Key | Publish the current directory-project Build and record a version | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project validate` | No Auth | Validate a directory Agent project | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project version disable` | No Auth | Disable directory project versions | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project version enable` | No Auth | Enable directory project versions | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project version list` | No Auth | List directory project versions | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project version preview` | No Auth | Preview a directory project version | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project version restore` | No Auth | Restore a version to the project working directory | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project version status` | No Auth | Show directory project version status | [managed-agent.md](managed-agent.md) | +| `bl managed-agent project workbench` | API Key | Launch the directory project Workbench | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session create` | API Key | Create a new session for an agent | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session delete` | API Key | Delete a session | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session events` | API Key | List event history for a session | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session get` | API Key | Get details of a session | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session list` | API Key | List sessions from the provider | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session run` | API Key | Create a session, send a message, and stream the response | [managed-agent.md](managed-agent.md) | +| `bl managed-agent session send` | API Key | Send a message to an existing session and stream the response | [managed-agent.md](managed-agent.md) | +| `bl managed-agent skill-list` | API Key | List skills from the provider's skill catalog | [managed-agent.md](managed-agent.md) | +| `bl managed-agent state import` | API Key | Import an existing remote resource into agents state | [managed-agent.md](managed-agent.md) | +| `bl managed-agent state list` | No Auth | List resources tracked in agents state | [managed-agent.md](managed-agent.md) | +| `bl managed-agent state rm` | No Auth | Remove a resource from state without destroying it remotely | [managed-agent.md](managed-agent.md) | +| `bl managed-agent state show` | No Auth | Show details of a resource in agents state | [managed-agent.md](managed-agent.md) | +| `bl managed-agent validate` | No Auth | Validate an agents.yaml configuration (offline) | [managed-agent.md](managed-agent.md) | ## By group -| Group | Commands | Reference | -| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | -| `managed-agent` | `apply`, `destroy`, `init`, `plan`, `playground`, `session create`, `session delete`, `session events`, `session get`, `session list`, `session run`, `session send`, `skill-list`, `state import`, `state list`, `state rm`, `state show`, `validate`, `version disable`, `version enable`, `version list`, `version preview`, `version restore`, `version status`, `workbench` | [managed-agent.md](managed-agent.md) | +| Group | Commands | Reference | +| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | +| `managed-agent` | `apply`, `destroy`, `init`, `plan`, `playground`, `project build`, `project init`, `project publish`, `project validate`, `project version disable`, `project version enable`, `project version list`, `project version preview`, `project version restore`, `project version status`, `project workbench`, `session create`, `session delete`, `session events`, `session get`, `session list`, `session run`, `session send`, `skill-list`, `state import`, `state list`, `state rm`, `state show`, `validate` | [managed-agent.md](managed-agent.md) | ## Global flags diff --git a/skills/bailian-managed-agent/reference/managed-agent.md b/skills/bailian-managed-agent/reference/managed-agent.md index 5bf4004..d06f9c4 100644 --- a/skills/bailian-managed-agent/reference/managed-agent.md +++ b/skills/bailian-managed-agent/reference/managed-agent.md @@ -7,33 +7,37 @@ Index: [index.md](index.md) ## Commands in this group -| Command | Authentication | Description | -| ---------------------------------- | -------------- | ------------------------------------------------------------- | -| `bl managed-agent apply` | API Key | Apply planned changes to create/update/delete agent resources | -| `bl managed-agent destroy` | API Key | Destroy all managed agent resources tracked in state | -| `bl managed-agent init` | No Auth | Create an agents.yaml template | -| `bl managed-agent plan` | API Key | Show what changes would be applied to agent infrastructure | -| `bl managed-agent playground` | API Key | Launch a Session Preview for an agents.yaml Agent | -| `bl managed-agent session create` | API Key | Create a new session for an agent | -| `bl managed-agent session delete` | API Key | Delete a session | -| `bl managed-agent session events` | API Key | List event history for a session | -| `bl managed-agent session get` | API Key | Get details of a session | -| `bl managed-agent session list` | API Key | List sessions from the provider | -| `bl managed-agent session run` | API Key | Create a session, send a message, and stream the response | -| `bl managed-agent session send` | API Key | Send a message to an existing session and stream the response | -| `bl managed-agent skill-list` | API Key | List skills from the provider's skill catalog | -| `bl managed-agent state import` | API Key | Import an existing remote resource into agents state | -| `bl managed-agent state list` | No Auth | List resources tracked in agents state | -| `bl managed-agent state rm` | No Auth | Remove a resource from state without destroying it remotely | -| `bl managed-agent state show` | No Auth | Show details of a resource in agents state | -| `bl managed-agent validate` | No Auth | Validate an agents.yaml configuration (offline) | -| `bl managed-agent version disable` | No Auth | Disable Apply-time local snapshots without removing history | -| `bl managed-agent version enable` | No Auth | Enable Apply-time local snapshots for agents.yaml | -| `bl managed-agent version list` | No Auth | List local snapshots of agents.yaml | -| `bl managed-agent version preview` | No Auth | Preview a historical agents.yaml version | -| `bl managed-agent version restore` | No Auth | Restore a historical agents.yaml version to the working tree | -| `bl managed-agent version status` | No Auth | Show local snapshot versioning status for agents.yaml | -| `bl managed-agent workbench` | API Key | Launch the agents.yaml project Workbench | +| Command | Authentication | Description | +| ------------------------------------------ | -------------- | ------------------------------------------------------------------ | +| `bl managed-agent apply` | API Key | Apply planned changes to create/update/delete agent resources | +| `bl managed-agent destroy` | API Key | Destroy all managed agent resources tracked in state | +| `bl managed-agent init` | No Auth | Create an agents.yaml template | +| `bl managed-agent plan` | API Key | Show what changes would be applied to agent infrastructure | +| `bl managed-agent playground` | API Key | Launch a Session Preview for an agents.yaml Agent | +| `bl managed-agent project build` | No Auth | Organize directory source and generate the immutable Publish Build | +| `bl managed-agent project init` | No Auth | Create a directory project or convert the local agents.yaml | +| `bl managed-agent project publish` | API Key | Publish the current directory-project Build and record a version | +| `bl managed-agent project validate` | No Auth | Validate a directory Agent project | +| `bl managed-agent project version disable` | No Auth | Disable directory project versions | +| `bl managed-agent project version enable` | No Auth | Enable directory project versions | +| `bl managed-agent project version list` | No Auth | List directory project versions | +| `bl managed-agent project version preview` | No Auth | Preview a directory project version | +| `bl managed-agent project version restore` | No Auth | Restore a version to the project working directory | +| `bl managed-agent project version status` | No Auth | Show directory project version status | +| `bl managed-agent project workbench` | API Key | Launch the directory project Workbench | +| `bl managed-agent session create` | API Key | Create a new session for an agent | +| `bl managed-agent session delete` | API Key | Delete a session | +| `bl managed-agent session events` | API Key | List event history for a session | +| `bl managed-agent session get` | API Key | Get details of a session | +| `bl managed-agent session list` | API Key | List sessions from the provider | +| `bl managed-agent session run` | API Key | Create a session, send a message, and stream the response | +| `bl managed-agent session send` | API Key | Send a message to an existing session and stream the response | +| `bl managed-agent skill-list` | API Key | List skills from the provider's skill catalog | +| `bl managed-agent state import` | API Key | Import an existing remote resource into agents state | +| `bl managed-agent state list` | No Auth | List resources tracked in agents state | +| `bl managed-agent state rm` | No Auth | Remove a resource from state without destroying it remotely | +| `bl managed-agent state show` | No Auth | Show details of a resource in agents state | +| `bl managed-agent validate` | No Auth | Validate an agents.yaml configuration (offline) | ## Command details @@ -204,7 +208,7 @@ bl managed-agent plan --no-refresh - Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). - Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. - Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. -- Workbench requires Node.js 22+ and starts the shared @openagentpack/playground package locally. Local versions use the shared .openagentpack/versions project store and do not require Git. +- Session Preview requires Node.js 22+ and keeps using an agents.yaml source. Directory Workbench is available under managed-agent project workbench. #### Examples @@ -220,6 +224,318 @@ bl managed-agent playground --agent assistant bl managed-agent playground --file agents.yaml --no-open ``` +### `bl managed-agent project build` + +| Field | Value | +| ------------------ | ------------------------------------------------------------------ | +| **Name** | `managed-agent project build` | +| **Description** | Organize directory source and generate the immutable Publish Build | +| **Authentication** | No Auth | +| **Usage** | `bl managed-agent project build [--project ] [--yes]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | +| `--yes` | switch | no | Write the previewed Build | + +#### Examples + +```bash +bl managed-agent project build --dry-run +``` + +```bash +bl managed-agent project build --yes +``` + +```bash +bl managed-agent project build --project ./my-agent --yes +``` + +### `bl managed-agent project init` + +| Field | Value | +| ------------------ | ---------------------------------------------------------------------------- | +| **Name** | `managed-agent project init` | +| **Description** | Create a directory project or convert the local agents.yaml | +| **Authentication** | No Auth | +| **Usage** | `bl managed-agent project init [--project ] [--provider bailian]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | +| `--provider ` | string | no | Provider for a new project | + +#### Examples + +```bash +bl managed-agent project init +``` + +```bash +bl managed-agent project init --project ./my-agent +``` + +```bash +bl managed-agent project init --provider bailian +``` + +### `bl managed-agent project publish` + +| Field | Value | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------- | +| **Name** | `managed-agent project publish` | +| **Description** | Publish the current directory-project Build and record a version | +| **Authentication** | API Key | +| **Usage** | `bl managed-agent project publish [--project ] [--provider ] [--yes] [--no-refresh] [--concurrency ]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | +| `--provider ` | string | no | Target provider | +| `--yes` | switch | no | Confirm remote Publish | +| `--no-refresh` | switch | no | Skip remote refresh before planning | +| `--concurrency ` | number | no | Maximum parallel resource operations | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | + +#### Notes + +- Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. +- Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. + +#### Examples + +```bash +bl managed-agent project publish --yes +``` + +```bash +bl managed-agent project publish --project ./my-agent --yes +``` + +```bash +bl managed-agent project publish --provider bailian --yes +``` + +### `bl managed-agent project validate` + +| Field | Value | +| ------------------ | ----------------------------------------------------------- | +| **Name** | `managed-agent project validate` | +| **Description** | Validate a directory Agent project | +| **Authentication** | No Auth | +| **Usage** | `bl managed-agent project validate [--project ]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | + +#### Examples + +```bash +bl managed-agent project validate +``` + +```bash +bl managed-agent project validate --project ./my-agent +``` + +### `bl managed-agent project version disable` + +| Field | Value | +| ------------------ | ------------------------------------------------------------------ | +| **Name** | `managed-agent project version disable` | +| **Description** | Disable directory project versions | +| **Authentication** | No Auth | +| **Usage** | `bl managed-agent project version disable [--project ]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | + +#### Examples + +```bash +bl managed-agent project version disable +``` + +```bash +bl managed-agent project version disable --project ./my-agent +``` + +### `bl managed-agent project version enable` + +| Field | Value | +| ------------------ | ----------------------------------------------------------------- | +| **Name** | `managed-agent project version enable` | +| **Description** | Enable directory project versions | +| **Authentication** | No Auth | +| **Usage** | `bl managed-agent project version enable [--project ]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | + +#### Examples + +```bash +bl managed-agent project version enable +``` + +```bash +bl managed-agent project version enable --project ./my-agent +``` + +### `bl managed-agent project version list` + +| Field | Value | +| ------------------ | ------------------------------------------------------------------------------------------------- | +| **Name** | `managed-agent project version list` | +| **Description** | List directory project versions | +| **Authentication** | No Auth | +| **Usage** | `bl managed-agent project version list [--project ] [--limit ] [--cursor ]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | +| `--limit ` | number | no | Maximum versions to return | +| `--cursor ` | string | no | Pagination cursor | + +#### Examples + +```bash +bl managed-agent project version list +``` + +```bash +bl managed-agent project version list --limit 20 --output json +``` + +### `bl managed-agent project version preview` + +| Field | Value | +| ------------------ | ---------------------------------------------------------------------------------------------- | +| **Name** | `managed-agent project version preview` | +| **Description** | Preview a directory project version | +| **Authentication** | No Auth | +| **Usage** | `bl managed-agent project version preview --version-id [--project ]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | +| `--version-id ` | string | yes | Full project version ID | + +#### Examples + +```bash +bl managed-agent project version preview --version-id +``` + +### `bl managed-agent project version restore` + +| Field | Value | +| ------------------ | ------------------------------------------------------------------------------------------------------ | +| **Name** | `managed-agent project version restore` | +| **Description** | Restore a version to the project working directory | +| **Authentication** | No Auth | +| **Usage** | `bl managed-agent project version restore --version-id [--project ] [--yes]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | +| `--version-id ` | string | yes | Full project version ID | +| `--yes` | switch | no | Restore without interactive confirmation | + +#### Examples + +```bash +bl managed-agent project version restore --version-id +``` + +```bash +bl managed-agent project version restore --version-id --yes +``` + +### `bl managed-agent project version status` + +| Field | Value | +| ------------------ | ----------------------------------------------------------------- | +| **Name** | `managed-agent project version status` | +| **Description** | Show directory project version status | +| **Authentication** | No Auth | +| **Usage** | `bl managed-agent project version status [--project ]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | + +#### Examples + +```bash +bl managed-agent project version status +``` + +```bash +bl managed-agent project version status --project ./my-agent --output json +``` + +### `bl managed-agent project workbench` + +| Field | Value | +| ------------------ | ------------------------------------------------------------------------------------- | +| **Name** | `managed-agent project workbench` | +| **Description** | Launch the directory project Workbench | +| **Authentication** | API Key | +| **Usage** | `bl managed-agent project workbench [--project ] [--port ] [--no-open]` | + +#### Flags + +| Flag | Type | Required | Description | +| ----------------------- | ------ | -------- | --------------------------------------------------- | +| `--project ` | string | no | Directory project root (default: current directory) | +| `--port ` | number | no | Local port (default: 4848) | +| `--no-open` | switch | no | Do not open a browser | +| `--api-key ` | string | no | API key | +| `--base-url ` | string | no | API base URL | + +#### Notes + +- Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). +- Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. +- Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. + +#### Examples + +```bash +bl managed-agent project workbench +``` + +```bash +bl managed-agent project workbench --project ./my-agent --no-open +``` + ### `bl managed-agent session create` | Field | Value | @@ -664,198 +980,3 @@ bl managed-agent validate ```bash bl managed-agent validate --file agents.yaml ``` - -### `bl managed-agent version disable` - -| Field | Value | -| ------------------ | ----------------------------------------------------------- | -| **Name** | `managed-agent version disable` | -| **Description** | Disable Apply-time local snapshots without removing history | -| **Authentication** | No Auth | -| **Usage** | `bl managed-agent version disable [--file ]` | - -#### Flags - -| Flag | Type | Required | Description | -| --------------- | ------ | -------- | --------------------------------------- | -| `--file ` | string | no | Config file path (default: agents.yaml) | - -#### Examples - -```bash -bl managed-agent version disable -``` - -```bash -bl managed-agent version disable --file agents.yaml -``` - -### `bl managed-agent version enable` - -| Field | Value | -| ------------------ | ------------------------------------------------- | -| **Name** | `managed-agent version enable` | -| **Description** | Enable Apply-time local snapshots for agents.yaml | -| **Authentication** | No Auth | -| **Usage** | `bl managed-agent version enable [--file ]` | - -#### Flags - -| Flag | Type | Required | Description | -| --------------- | ------ | -------- | --------------------------------------- | -| `--file ` | string | no | Config file path (default: agents.yaml) | - -#### Examples - -```bash -bl managed-agent version enable -``` - -```bash -bl managed-agent version enable --file agents.yaml -``` - -### `bl managed-agent version list` - -| Field | Value | -| ------------------ | --------------------------------------------------------------------------------- | -| **Name** | `managed-agent version list` | -| **Description** | List local snapshots of agents.yaml | -| **Authentication** | No Auth | -| **Usage** | `bl managed-agent version list [--file ] [--limit ] [--cursor ]` | - -#### Flags - -| Flag | Type | Required | Description | -| ------------------- | ------ | -------- | -------------------------------------------------- | -| `--file ` | string | no | Config file path (default: agents.yaml) | -| `--limit ` | number | no | Maximum versions to return (default: 50, max: 100) | -| `--cursor ` | string | no | Pagination cursor returned by the previous page | - -#### Examples - -```bash -bl managed-agent version list -``` - -```bash -bl managed-agent version list --limit 20 --output json -``` - -### `bl managed-agent version preview` - -| Field | Value | -| ------------------ | ------------------------------------------------------------------------------ | -| **Name** | `managed-agent version preview` | -| **Description** | Preview a historical agents.yaml version | -| **Authentication** | No Auth | -| **Usage** | `bl managed-agent version preview --version-id [--file ]` | - -#### Flags - -| Flag | Type | Required | Description | -| ----------------------------- | ------ | -------- | --------------------------------------- | -| `--file ` | string | no | Config file path (default: agents.yaml) | -| `--version-id ` | string | yes | Full local version ID | - -#### Examples - -```bash -bl managed-agent version preview --version-id -``` - -```bash -bl managed-agent version preview --version-id --output json -``` - -### `bl managed-agent version restore` - -| Field | Value | -| ------------------ | -------------------------------------------------------------------------------------- | -| **Name** | `managed-agent version restore` | -| **Description** | Restore a historical agents.yaml version to the working tree | -| **Authentication** | No Auth | -| **Usage** | `bl managed-agent version restore --version-id [--file ] [--yes]` | - -#### Flags - -| Flag | Type | Required | Description | -| ----------------------------- | ------ | -------- | ------------------------------------------- | -| `--file ` | string | no | Config file path (default: agents.yaml) | -| `--version-id ` | string | yes | Full local version ID | -| `--yes` | switch | no | Restore without an interactive confirmation | - -#### Examples - -```bash -bl managed-agent version restore --version-id -``` - -```bash -bl managed-agent version restore --version-id --yes --output json -``` - -### `bl managed-agent version status` - -| Field | Value | -| ------------------ | ----------------------------------------------------- | -| **Name** | `managed-agent version status` | -| **Description** | Show local snapshot versioning status for agents.yaml | -| **Authentication** | No Auth | -| **Usage** | `bl managed-agent version status [--file ]` | - -#### Flags - -| Flag | Type | Required | Description | -| --------------- | ------ | -------- | --------------------------------------- | -| `--file ` | string | no | Config file path (default: agents.yaml) | - -#### Examples - -```bash -bl managed-agent version status -``` - -```bash -bl managed-agent version status --file agents.yaml --output json -``` - -### `bl managed-agent workbench` - -| Field | Value | -| ------------------ | --------------------------------------------------------------------- | -| **Name** | `managed-agent workbench` | -| **Description** | Launch the agents.yaml project Workbench | -| **Authentication** | API Key | -| **Usage** | `bl managed-agent workbench [--file ] [--port ] [--no-open]` | - -#### Flags - -| Flag | Type | Required | Description | -| ------------------ | ------ | -------- | --------------------------------------- | -| `--file ` | string | no | Config file path (default: agents.yaml) | -| `--port ` | number | no | Local port (default: 4848) | -| `--no-open` | switch | no | Do not open a browser automatically | -| `--api-key ` | string | no | API key | -| `--base-url ` | string | no | API base URL | - -#### Notes - -- Bailian credentials come from bl's auth chain: --api-key > DASHSCOPE_API_KEY > `bl auth login` (active config profile). -- Other providers read the env vars referenced in agents.yaml (e.g. ${ANTHROPIC_API_KEY}), including .env and ~/.agents/config.json. -- Resolved credentials are injected into the SDK in-memory and cleared from the environment; they never persist in process env. -- Workbench requires Node.js 22+ and starts the shared @openagentpack/playground package locally. Local versions use the shared .openagentpack/versions project store and do not require Git. - -#### Examples - -```bash -bl managed-agent workbench -``` - -```bash -bl managed-agent workbench --file agents.yaml --no-open -``` - -```bash -bl managed-agent workbench --port 4949 -```