@evalops/maestro 0.10.11 → 0.10.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/agent/transport/tool-execution-bridge.d.ts.map +1 -1
  2. package/dist/agent/transport/tool-execution-bridge.js +4 -0
  3. package/dist/agent/transport/tool-execution-bridge.js.map +1 -1
  4. package/dist/audit/logger.d.ts +1 -1
  5. package/dist/cli/args.d.ts.map +1 -1
  6. package/dist/cli/args.js +5 -1
  7. package/dist/cli/args.js.map +1 -1
  8. package/dist/cli/commands/config.d.ts.map +1 -1
  9. package/dist/cli/commands/config.js +3 -2
  10. package/dist/cli/commands/config.js.map +1 -1
  11. package/dist/cli/commands/evalops.d.ts +2 -1
  12. package/dist/cli/commands/evalops.d.ts.map +1 -1
  13. package/dist/cli/commands/evalops.js +9 -29
  14. package/dist/cli/commands/evalops.js.map +1 -1
  15. package/dist/cli/commands/init.d.ts +3 -1
  16. package/dist/cli/commands/init.d.ts.map +1 -1
  17. package/dist/cli/commands/init.js +61 -21
  18. package/dist/cli/commands/init.js.map +1 -1
  19. package/dist/cli/commands/status.d.ts +2 -0
  20. package/dist/cli/commands/status.d.ts.map +1 -0
  21. package/dist/cli/commands/status.js +11 -0
  22. package/dist/cli/commands/status.js.map +1 -0
  23. package/dist/cli/help.d.ts.map +1 -1
  24. package/dist/cli/help.js +3 -0
  25. package/dist/cli/help.js.map +1 -1
  26. package/dist/cli-tui/tui-renderer/attachment-controller.d.ts.map +1 -1
  27. package/dist/cli-tui/tui-renderer/attachment-controller.js +18 -1
  28. package/dist/cli-tui/tui-renderer/attachment-controller.js.map +1 -1
  29. package/dist/cli.js +2316 -1716
  30. package/dist/evalops/agent-bootstrap.d.ts +9 -0
  31. package/dist/evalops/agent-bootstrap.d.ts.map +1 -1
  32. package/dist/evalops/agent-bootstrap.js +254 -36
  33. package/dist/evalops/agent-bootstrap.js.map +1 -1
  34. package/dist/evalops/managed-context.d.ts +34 -0
  35. package/dist/evalops/managed-context.d.ts.map +1 -0
  36. package/dist/evalops/managed-context.js +183 -0
  37. package/dist/evalops/managed-context.js.map +1 -0
  38. package/dist/main.d.ts.map +1 -1
  39. package/dist/main.js +6 -1
  40. package/dist/main.js.map +1 -1
  41. package/dist/memory/auto-extraction.d.ts.map +1 -1
  42. package/dist/memory/auto-extraction.js +58 -0
  43. package/dist/memory/auto-extraction.js.map +1 -1
  44. package/dist/memory/backend.d.ts +1 -0
  45. package/dist/memory/backend.d.ts.map +1 -1
  46. package/dist/memory/backend.js.map +1 -1
  47. package/dist/memory/service-client.d.ts +1 -0
  48. package/dist/memory/service-client.d.ts.map +1 -1
  49. package/dist/memory/service-client.js +32 -8
  50. package/dist/memory/service-client.js.map +1 -1
  51. package/dist/models/builtin.d.ts.map +1 -1
  52. package/dist/models/builtin.js +2 -3
  53. package/dist/models/builtin.js.map +1 -1
  54. package/dist/oauth/evalops.d.ts.map +1 -1
  55. package/dist/oauth/evalops.js +2 -1
  56. package/dist/oauth/evalops.js.map +1 -1
  57. package/dist/oauth/storage.d.ts +1 -0
  58. package/dist/oauth/storage.d.ts.map +1 -1
  59. package/dist/oauth/storage.js +6 -0
  60. package/dist/oauth/storage.js.map +1 -1
  61. package/dist/platform/client.d.ts.map +1 -1
  62. package/dist/platform/client.js +3 -0
  63. package/dist/platform/client.js.map +1 -1
  64. package/dist/platform/core-services.d.ts +1 -0
  65. package/dist/platform/core-services.d.ts.map +1 -1
  66. package/dist/platform/core-services.js +1 -0
  67. package/dist/platform/core-services.js.map +1 -1
  68. package/dist/platform/tool-execution-client.d.ts.map +1 -1
  69. package/dist/platform/tool-execution-client.js +3 -0
  70. package/dist/platform/tool-execution-client.js.map +1 -1
  71. package/dist/providers/auth.d.ts +1 -1
  72. package/dist/providers/auth.d.ts.map +1 -1
  73. package/dist/providers/auth.js +30 -2
  74. package/dist/providers/auth.js.map +1 -1
  75. package/dist/providers/evalops-managed.d.ts +1 -0
  76. package/dist/providers/evalops-managed.d.ts.map +1 -1
  77. package/dist/providers/evalops-managed.js +1 -0
  78. package/dist/providers/evalops-managed.js.map +1 -1
  79. package/dist/telemetry/maestro-event-bus.d.ts.map +1 -1
  80. package/dist/telemetry/maestro-event-bus.js +16 -47
  81. package/dist/telemetry/maestro-event-bus.js.map +1 -1
  82. package/dist/telemetry.d.ts.map +1 -1
  83. package/dist/telemetry.js +98 -2
  84. package/dist/telemetry.js.map +1 -1
  85. package/dist/version.json +2 -2
  86. package/node_modules/@evalops/contracts/package.json +1 -1
  87. package/node_modules/@evalops/tui/package.json +1 -1
  88. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from \"chalk\";\nimport {\n\ttype EvalOpsInitOptions,\n\tbootstrapEvalOpsAgent,\n} from \"../../evalops/agent-bootstrap.js\";\n\nfunction readValue(args: string[], index: number, flag: string): string {\n\tconst value = args[index + 1];\n\tif (!value || value.startsWith(\"-\")) {\n\t\tthrow new Error(`${flag} requires a value`);\n\t}\n\treturn value;\n}\n\nfunction parsePositiveInteger(value: string, flag: string): number {\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isInteger(parsed) || parsed <= 0) {\n\t\tthrow new Error(`${flag} must be a positive integer`);\n\t}\n\treturn parsed;\n}\n\nfunction appendScopes(existing: string[] | undefined, value: string): string[] {\n\treturn [\n\t\t...(existing ?? []),\n\t\t...value\n\t\t\t.split(\",\")\n\t\t\t.map((entry) => entry.trim())\n\t\t\t.filter((entry) => entry.length > 0),\n\t];\n}\n\nexport function parseInitArgs(args: string[]): EvalOpsInitOptions {\n\tconst options: EvalOpsInitOptions = {};\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\t\tswitch (arg) {\n\t\t\tcase \"--agent-mcp-url\":\n\t\t\tcase \"--mcp-url\":\n\t\t\t\toptions.mcpUrl = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--agent-type\":\n\t\t\t\toptions.agentType = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--api-key-scope\":\n\t\t\tcase \"--key-scope\":\n\t\t\t\toptions.apiKeyScopes = appendScopes(\n\t\t\t\t\toptions.apiKeyScopes,\n\t\t\t\t\treadValue(args, i, arg),\n\t\t\t\t);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--expires-in-days\":\n\t\t\t\toptions.expiresInDays = parsePositiveInteger(\n\t\t\t\t\treadValue(args, i, arg),\n\t\t\t\t\targ,\n\t\t\t\t);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--force-login\":\n\t\t\t\toptions.forceLogin = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--json\":\n\t\t\t\toptions.json = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--key-name\":\n\t\t\t\toptions.keyName = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--manifest-url\":\n\t\t\t\toptions.manifestUrl = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--register-scope\":\n\t\t\tcase \"--scope\":\n\t\t\t\toptions.registerScopes = appendScopes(\n\t\t\t\t\toptions.registerScopes,\n\t\t\t\t\treadValue(args, i, arg),\n\t\t\t\t);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--rotate-key\":\n\t\t\t\toptions.rotateKey = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--surface\":\n\t\t\t\toptions.surface = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--ttl-seconds\":\n\t\t\t\toptions.ttlSeconds = parsePositiveInteger(readValue(args, i, arg), arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--workspace\":\n\t\t\tcase \"--workspace-id\":\n\t\t\t\toptions.workspaceId = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (arg?.startsWith(\"-\")) {\n\t\t\t\t\tthrow new Error(`Unknown maestro init option: ${arg}`);\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Unexpected maestro init argument: ${arg}`);\n\t\t}\n\t}\n\treturn options;\n}\n\nexport async function handleInitCommand(args: string[] = []): Promise<void> {\n\tlet options: EvalOpsInitOptions;\n\ttry {\n\t\toptions = parseInitArgs(args);\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\tchalk.red(error instanceof Error ? error.message : String(error)),\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tif (!options.json) {\n\t\tconsole.log(chalk.bold(\"Maestro EvalOps Init\"));\n\t}\n\n\tconst result = await bootstrapEvalOpsAgent(options, {\n\t\tonAuthUrl: (url) => {\n\t\t\tif (options.json) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t\"Open this URL in your browser to authenticate with EvalOps:\",\n\t\t\t\t),\n\t\t\t);\n\t\t\tconsole.log(chalk.underline(url));\n\t\t},\n\t\tonStatus: (status) => {\n\t\t\tif (!options.json) {\n\t\t\t\tconsole.log(chalk.dim(status.message));\n\t\t\t}\n\t\t},\n\t});\n\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\treturn;\n\t}\n\n\tconsole.log(chalk.green(\"EvalOps agent bootstrap complete.\"));\n\tconsole.log(chalk.dim(`MCP endpoint: ${result.endpoint}`));\n\tif (result.organizationId) {\n\t\tconsole.log(chalk.dim(`Organization: ${result.organizationId}`));\n\t}\n\tif (result.agentId) {\n\t\tconsole.log(chalk.dim(`Agent: ${result.agentId}`));\n\t}\n\tif (result.runId) {\n\t\tconsole.log(chalk.dim(`Run: ${result.runId}`));\n\t}\n\tif (result.keyPrefix) {\n\t\tconst keyMode = result.apiKeyCreated ? \"created\" : \"reused\";\n\t\tconsole.log(chalk.dim(`API key ${keyMode}: ${result.keyPrefix}`));\n\t}\n\tconsole.log(\n\t\tchalk.dim(\n\t\t\t\"Stored EvalOps MCP credentials locally for future Maestro sessions.\",\n\t\t),\n\t);\n}\n"]}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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","sourcesContent":["import chalk from \"chalk\";\nimport {\n\ttype EvalOpsInitOptions,\n\tbootstrapEvalOpsAgent,\n} from \"../../evalops/agent-bootstrap.js\";\nimport { muted, sectionHeading } from \"../../style/theme.js\";\n\nexport function formatInitHelp(): string {\n\treturn `${sectionHeading(\"maestro init\")}${muted(\n\t\t` maestro init Login, create or reuse an API key, and register this agent\n maestro init --rotate-key Replace the stored agent MCP API key\n maestro init --mcp-url <url> Override the EvalOps agent MCP endpoint\n maestro init --json Emit machine-readable bootstrap output\n\nOptions\n --agent-type <type> Agent type to register, defaults to maestro\n --surface <surface> Surface to register, defaults to cli\n --workspace, --workspace-id <id> Workspace to associate with the registration\n --scope <scope[,scope...]> Registration scopes to request\n --key-scope <scope[,scope...]> API key scopes to request\n --expires-in-days <days> API key TTL in days\n --force-login Re-run EvalOps OAuth before bootstrapping\n --manifest-url <url> Override the agent MCP manifest URL\n --ttl-seconds <seconds> Registration TTL in seconds`,\n\t)}`;\n}\n\nfunction readValue(args: string[], index: number, flag: string): string {\n\tconst value = args[index + 1];\n\tif (!value || value.startsWith(\"-\")) {\n\t\tthrow new Error(`${flag} requires a value`);\n\t}\n\treturn value;\n}\n\nfunction parsePositiveInteger(value: string, flag: string): number {\n\tconst parsed = Number.parseInt(value, 10);\n\tif (!Number.isInteger(parsed) || parsed <= 0) {\n\t\tthrow new Error(`${flag} must be a positive integer`);\n\t}\n\treturn parsed;\n}\n\nfunction appendScopes(existing: string[] | undefined, value: string): string[] {\n\treturn [\n\t\t...(existing ?? []),\n\t\t...value\n\t\t\t.split(\",\")\n\t\t\t.map((entry) => entry.trim())\n\t\t\t.filter((entry) => entry.length > 0),\n\t];\n}\n\nexport function parseInitArgs(args: string[]): EvalOpsInitOptions {\n\tconst options: EvalOpsInitOptions = {};\n\tfor (let i = 0; i < args.length; i++) {\n\t\tconst arg = args[i];\n\t\tswitch (arg) {\n\t\t\tcase \"--agent-mcp-url\":\n\t\t\tcase \"--mcp-url\":\n\t\t\t\toptions.mcpUrl = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--agent-type\":\n\t\t\t\toptions.agentType = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--api-key-scope\":\n\t\t\tcase \"--key-scope\":\n\t\t\t\toptions.apiKeyScopes = appendScopes(\n\t\t\t\t\toptions.apiKeyScopes,\n\t\t\t\t\treadValue(args, i, arg),\n\t\t\t\t);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--expires-in-days\":\n\t\t\t\toptions.expiresInDays = parsePositiveInteger(\n\t\t\t\t\treadValue(args, i, arg),\n\t\t\t\t\targ,\n\t\t\t\t);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--force-login\":\n\t\t\t\toptions.forceLogin = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--json\":\n\t\t\t\toptions.json = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--key-name\":\n\t\t\t\toptions.keyName = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--manifest-url\":\n\t\t\t\toptions.manifestUrl = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--register-scope\":\n\t\t\tcase \"--scope\":\n\t\t\t\toptions.registerScopes = appendScopes(\n\t\t\t\t\toptions.registerScopes,\n\t\t\t\t\treadValue(args, i, arg),\n\t\t\t\t);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--rotate-key\":\n\t\t\t\toptions.rotateKey = true;\n\t\t\t\tbreak;\n\t\t\tcase \"--surface\":\n\t\t\t\toptions.surface = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--ttl-seconds\":\n\t\t\t\toptions.ttlSeconds = parsePositiveInteger(readValue(args, i, arg), arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tcase \"--workspace\":\n\t\t\tcase \"--workspace-id\":\n\t\t\t\toptions.workspaceId = readValue(args, i, arg);\n\t\t\t\ti++;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tif (arg?.startsWith(\"-\")) {\n\t\t\t\t\tthrow new Error(`Unknown maestro init option: ${arg}`);\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Unexpected maestro init argument: ${arg}`);\n\t\t}\n\t}\n\treturn options;\n}\n\nfunction checkLine(text: string): string {\n\treturn `${chalk.green(\"✓\")} ${text}`;\n}\n\nexport function formatInitSuccess(\n\tresult: Awaited<ReturnType<typeof bootstrapEvalOpsAgent>>,\n): string {\n\tconst keyMode = result.apiKeyCreated ? \"Created\" : \"Reused\";\n\tconst authenticatedAs = result.authenticatedAs ?? \"EvalOps\";\n\tconst governedActions = result.governedActionsLoaded ?? 0;\n\tconst lines = [\n\t\tchalk.bold(\"EvalOps Maestro bootstrap\"),\n\t\t\"\",\n\t\tcheckLine(`Authenticated as ${authenticatedAs}`),\n\t\tcheckLine(`${keyMode} managed inference key`),\n\t\tcheckLine(\"Registered local agent runtime\"),\n\t\tcheckLine(`Loaded ${governedActions} governed actions`),\n\t\tcheckLine(\n\t\t\tresult.approvalPolicyAttached\n\t\t\t\t? \"Attached default approval policy\"\n\t\t\t\t: \"Queued approval policy review\",\n\t\t),\n\t\tcheckLine(\n\t\t\tresult.traceIngestionStarted\n\t\t\t\t? \"Started trace ingestion\"\n\t\t\t\t: \"Requested trace ingestion\",\n\t\t),\n\t\tcheckLine(\n\t\t\tresult.governedInferenceCheckRan\n\t\t\t\t? \"Ran first governed inference check\"\n\t\t\t\t: \"Queued first governed inference check\",\n\t\t),\n\t\tcheckLine(\n\t\t\tresult.evidenceEventPublished\n\t\t\t\t? \"Published evidence event\"\n\t\t\t\t: \"Queued evidence event\",\n\t\t),\n\t\t\"\",\n\t\t\"Open console:\",\n\t\tresult.consoleUrl ?? \"https://app.evalops.dev/overview?env=production\",\n\t];\n\treturn lines.join(\"\\n\");\n}\n\nexport async function handleInitCommand(args: string[] = []): Promise<void> {\n\tif (args.includes(\"--help\") || args.includes(\"-h\")) {\n\t\tconsole.log(formatInitHelp());\n\t\treturn;\n\t}\n\n\tlet options: EvalOpsInitOptions;\n\ttry {\n\t\toptions = parseInitArgs(args);\n\t} catch (error) {\n\t\tconsole.error(\n\t\t\tchalk.red(error instanceof Error ? error.message : String(error)),\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tconst result = await bootstrapEvalOpsAgent(options, {\n\t\tonAuthUrl: (url) => {\n\t\t\tif (options.json) {\n\t\t\t\tconsole.error(\n\t\t\t\t\t\"Open this URL in your browser to authenticate with EvalOps:\",\n\t\t\t\t);\n\t\t\t\tconsole.error(url);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconsole.log(\n\t\t\t\tchalk.yellow(\n\t\t\t\t\t\"Open this URL in your browser to authenticate with EvalOps:\",\n\t\t\t\t),\n\t\t\t);\n\t\t\tconsole.log(chalk.underline(url));\n\t\t},\n\t\tonStatus: (status) => {\n\t\t\tif (options.json) {\n\t\t\t\tconsole.error(status.message);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconsole.log(chalk.dim(status.message));\n\t\t},\n\t});\n\n\tif (options.json) {\n\t\tconsole.log(JSON.stringify(result, null, 2));\n\t\treturn;\n\t}\n\n\tconsole.log(formatInitSuccess(result));\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export declare function handleStatusCommand(): Promise<void>;
2
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAMA,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CASzD"}
@@ -0,0 +1,11 @@
1
+ import chalk from "chalk";
2
+ import { formatManagedEvalOpsStatus, resolveManagedEvalOpsContext, } from "../../evalops/managed-context.js";
3
+ export async function handleStatusCommand() {
4
+ const context = resolveManagedEvalOpsContext();
5
+ console.log(chalk.bold("Maestro status"));
6
+ console.log(formatManagedEvalOpsStatus(context));
7
+ if (!context.authenticated) {
8
+ console.log(chalk.dim('Run "maestro init" to bring EvalOps managed mode online.'));
9
+ }
10
+ }
11
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EACN,0BAA0B,EAC1B,4BAA4B,GAC5B,MAAM,kCAAkC,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACxC,MAAM,OAAO,GAAG,4BAA4B,EAAE,CAAC;IAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,OAAO,CAAC,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CACV,KAAK,CAAC,GAAG,CAAC,0DAA0D,CAAC,CACrE,CAAC;IACH,CAAC;AACF,CAAC","sourcesContent":["import chalk from \"chalk\";\nimport {\n\tformatManagedEvalOpsStatus,\n\tresolveManagedEvalOpsContext,\n} from \"../../evalops/managed-context.js\";\n\nexport async function handleStatusCommand(): Promise<void> {\n\tconst context = resolveManagedEvalOpsContext();\n\tconsole.log(chalk.bold(\"Maestro status\"));\n\tconsole.log(formatManagedEvalOpsStatus(context));\n\tif (!context.authenticated) {\n\t\tconsole.log(\n\t\t\tchalk.dim('Run \"maestro init\" to bring EvalOps managed mode online.'),\n\t\t);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAyBA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,QAsNxC"}
1
+ {"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAyBA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,QAyNxC"}
package/dist/cli/help.js CHANGED
@@ -92,6 +92,9 @@ export function printHelp(version) {
92
92
  # Use EvalOps managed gateway models after \`maestro init\`
93
93
  maestro --provider evalops --model gpt-4o-mini "Say hello in one sentence"
94
94
 
95
+ # Confirm managed mode sinks and EvalOps org identity
96
+ maestro status
97
+
95
98
  # Export a portable session log
96
99
  maestro export <session-id> ./session.jsonl --format jsonl
97
100
 
@@ -1 +1 @@
1
- {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @fileoverview CLI Help Output Module\n *\n * This module generates and displays the `--help` output for the Maestro CLI.\n * It provides a comprehensive overview of:\n *\n * - **Usage syntax** and common invocation patterns\n * - **Command-line options** for provider, model, session management, etc.\n * - **Environment variables** for API keys and configuration\n * - **Available tools** and their capabilities\n * - **Subcommands** like `maestro exec` for headless execution\n * - **Session management** commands and workflows\n *\n * ## Styling\n *\n * The output uses the application's theme system for consistent terminal styling:\n * - `heading()` - Main title styling\n * - `sectionHeading()` - Section headers\n * - `muted()` - De-emphasized text for descriptions\n * - `badge()` - Highlighted tips and hints\n *\n * @module cli/help\n */\nimport { badge, heading, muted, sectionHeading } from \"../style/theme.js\";\n\n/**\n * Prints the complete CLI help message to stdout.\n *\n * This function is invoked when the user runs `maestro --help` or `maestro -h`.\n * It formats and displays all available options, commands, and usage examples\n * using the terminal theme for consistent styling.\n *\n * @param version - The current Maestro version string (e.g., \"1.2.3\")\n *\n * @example\n * ```typescript\n * import { printHelp } from \"./help.js\";\n * import { version } from \"../../package.json\";\n *\n * if (args.includes(\"--help\")) {\n * printHelp(version);\n * process.exit(0);\n * }\n * ```\n */\nexport function printHelp(version: string) {\n\tconst header = `${heading(\"Maestro\")} ${muted(\n\t\t`v${version} by EvalOps — AI coding assistant with read, list, search, diff, bash, edit, write, todo tools`,\n\t)}`;\n\tconst usage = `${sectionHeading(\"Usage\")}${muted(\n\t\t\"maestro [options] [messages...]\",\n\t)}`;\n\tconst options = `${sectionHeading(\"Options\")}${[\n\t\t\"--provider <name> Provider name (default: anthropic)\",\n\t\t\"-m, --model <id> Model ID (default: claude-sonnet-4-5)\",\n\t\t\"--task-budget <tokens> API-side Anthropic task budget in tokens\",\n\t\t\"--models <patterns> Comma-separated patterns for Ctrl+P model cycling\",\n\t\t\"--tools <names> Comma-separated tool names to enable (e.g., read,search,list,find)\",\n\t\t\"--api-key <key> API key (defaults to env vars)\",\n\t\t\"--system-prompt <text> System prompt (default: coding assistant prompt)\",\n\t\t\"--append-system-prompt <text> Append instructions to the system prompt\",\n\t\t\"--mode <mode> Output mode: text (default), json, or rpc\",\n\t\t\"--auth <mode> Credential mode: auto (default), api-key, claude\",\n\t\t\"--approval-mode <mode> Action approvals: prompt (default in TUI), auto, fail\",\n\t\t\"--sandbox <mode> Sandbox mode: docker, local, none (see docs/SAFETY.md)\",\n\t\t\"--port <n> Port for `maestro web` (defaults to PORT env or 8080)\",\n\t\t\"--continue, -c Continue previous session\",\n\t\t\"--resume, -r Select a session to resume\",\n\t\t\"--session <path> Use specific session file\",\n\t\t\"--no-session Don't save session (ephemeral)\",\n\t\t\"--safe-mode Enable extra safety restrictions\",\n\t\t\"--help, -h Show this help\",\n\t]\n\t\t.map((line) => ` ${muted(line)}`)\n\t\t.join(\"\\n\")}`;\n\tconst examples = `${sectionHeading(\"Examples\")}${muted(\n\t\t` # Interactive mode (no messages = interactive TUI)\n maestro\n\n # Single message\n maestro \"List all .ts files in src/\"\n\n # Multiple messages\n maestro \"Read package.json\" \"What dependencies do we have?\"\n\n # Continue previous session\n maestro --continue \"What did we discuss?\"\n\n # Use different model\n maestro --provider openai --model gpt-4o-mini \"Help me refactor this code\"\n\n # Use Codex subscription models after \\`maestro codex login\\`\n maestro --provider openai-codex --model gpt-5.5 \"Plan this migration\"\n\n # Bootstrap EvalOps login, API key, and agent registration in one flow\n maestro init\n\n # Use EvalOps managed gateway models after \\`maestro init\\`\n maestro --provider evalops --model gpt-4o-mini \"Say hello in one sentence\"\n\n # Export a portable session log\n maestro export <session-id> ./session.jsonl --format jsonl\n\n # Export a portable JSON archive with secret redaction\n maestro export <session-id> ./session.json --format json --redact-secrets\n\n # Import a portable session log into this workspace\n maestro import ./session.json\n\n # Start a hosted EvalOps runner session and wait for attach readiness\n maestro remote start --workspace ws_123 --repo evalops/foo --branch main --ttl 90m --wait --verify\n\n # Run a single-session hosted runtime pod entrypoint\n maestro hosted-runner --runner-session-id mrs_abc --workspace-root /workspace --listen 0.0.0.0:8080\n\n # Show usage analytics for the last 7 days\n maestro stats\n\n # Show usage analytics for one session\n maestro stats --session <session-id>`,\n\t)}`;\n\tconst env = `${sectionHeading(\"Environment Variables:\")}${muted(\n\t\t` GEMINI_API_KEY - Google Gemini API key\n OPENAI_API_KEY - OpenAI API key\n OPENAI_CODEX_TOKEN - OpenAI Codex ChatGPT access token\n OPENAI_CODEX_ACCOUNT_ID - ChatGPT account id when using a raw Codex token\n ANTHROPIC_API_KEY - Anthropic API key\n CLAUDE_CODE_TOKEN - Claude Code access token for --auth claude\n ANTHROPIC_OAUTH_TOKEN - Alternate env for Claude Code bearer tokens\n MAESTRO_AGENT_DIR - Session storage directory (default: ~/.maestro/agent)\n MAESTRO_SANDBOX_MODE - Sandbox mode: docker, local, none (default: none)\n MAESTRO_CHANGELOG - Set to off/false/hide/hidden/skip/0 to hide startup changelog banner\n MAESTRO_TUI_MINIMAL - Set to 1/true to disable animations and reduce TUI effects (SSH-friendly)\n MAESTRO_TUI_TOOL_MAX_CHARS - Max chars shown per tool output panel (0 = unlimited)\n MAESTRO_TUI_TOOL_MAX_LINES - Max lines shown per tool output panel (0 = unlimited)\n MAESTRO_MEMORY_BASE - Durable memory service base URL\n MAESTRO_MEMORY_ACCESS_TOKEN - Override bearer token for durable memory service\n MAESTRO_MEMORY_TEAM_ID - Optional team scope for durable memory service\n MAESTRO_SHARED_MEMORY_BASE - Shared memory base URL (Cloudflare Durable Objects worker)\n MAESTRO_SHARED_MEMORY_API_KEY - API key for shared memory service\n MAESTRO_REMOTE_RUNNER_URL - Hosted runner control-plane URL (default: https://runner.evalops.dev)\n MAESTRO_REMOTE_RUNNER_TOKEN - Hosted runner bearer token override\n MAESTRO_REMOTE_RUNNER_ORG_ID - EvalOps organization id for hosted runner sessions\n MAESTRO_REMOTE_RUNNER_WORKSPACE_ID - EvalOps workspace id for hosted runner sessions\n CODING_AGENT_DIR - Legacy session directory override (fallback)`,\n\t)}`;\n\tconst execSection = `${sectionHeading(\"maestro exec\")}${muted(\n\t\t` maestro exec \"Summarize recent changes\" --json\n\n Flags:\n --json Stream JSONL thread/turn events\n --output-schema <file|json> Validate final assistant JSON against a schema\n --output-last-message <path> Write the final assistant message to disk\n --full-auto | --read-only Force approval policy (auto or fail)\n --sandbox <mode> Run in sandbox: docker, local, none\n --resume <sessionId> Resume a prior exec session by id\n --last Resume the most recent exec session`,\n\t)}`;\n\tconst webSection = `${sectionHeading(\"maestro web\")}${muted(\n\t\t` # Start the bundled web UI + API server\n maestro web\n\n # Use a custom port\n maestro web --port 3000`,\n\t)}`;\n\tconst portabilitySection = `${sectionHeading(\"Session Portability\")}${muted(\n\t\t` maestro export <session-id> [output-path] --format json|jsonl [--redact-secrets]\n maestro import <file.json|file.jsonl>\n\n Notes:\n - json preserves the full session in a portable wrapper object\n - jsonl preserves the append-only session log verbatim unless redaction is requested\n - --redact-secrets scrubs detected credentials from exported payloads\n - import restores the session into the current workspace session directory`,\n\t)}`;\n\tconst memorySection = `${sectionHeading(\"maestro memory\")}${muted(\n\t\t` maestro memory [status] Show shared memory service status\n maestro memory session <id> Show per-session metrics\n maestro memory audit <id> [n] Show recent sync audit entries\n maestro memory export <id> Export metrics log as JSONL\n maestro memory watch [id] [ms] Poll status/metrics continuously`,\n\t)}`;\n\tconst remoteSection = `${sectionHeading(\"maestro remote\")}${muted(\n\t\t` maestro remote start --workspace <id> --repo <repo> --branch <branch> [--ttl 90m] [--wait] [--verify]\n maestro remote list --workspace <id> [--state running]\n maestro remote attach <session-id> [--verify] [--print-env]\n maestro remote extend <session-id> --ttl 2h\n maestro remote stop <session-id> [--reason <text>]`,\n\t)}`;\n\tconst initSection = `${sectionHeading(\"maestro init\")}${muted(\n\t\t` maestro init Login, create or reuse an API key, and register this agent\n maestro init --rotate-key Replace the stored agent MCP API key\n maestro init --mcp-url <url> Override the EvalOps agent MCP endpoint\n maestro init --json Emit machine-readable bootstrap output`,\n\t)}`;\n\tconst hostedRunnerSection = `${sectionHeading(\"maestro hosted-runner\")}${muted(\n\t\t` maestro hosted-runner --runner-session-id <id> --workspace-root <path> [--listen 0.0.0.0:8080]\n\n Env mode:\n MAESTRO_RUNNER_SESSION_ID=mrs_abc MAESTRO_WORKSPACE_ROOT=/workspace maestro hosted-runner`,\n\t)}`;\n\tconst sessionsSection = `${sectionHeading(\"Session Metadata\")}${muted(\n\t\t` /session favorite|unfavorite Toggle favorite for current session\n /session summary \"<text>\" Save a manual summary for current session\n /sessions summarize <id> Auto-summarize a saved session`,\n\t)}`;\n\tconst sessionsDiscovery = `${sectionHeading(\"Session Commands\")}${muted(\n\t\t` /session [info|favorite|unfavorite|summary \"<text>\"]\n /sessions [list|load <id>|favorite <id>|unfavorite <id>|summarize <id>]\n (Also available via TUI command palette)`,\n\t)}`;\n\tconst tools = `${sectionHeading(\"Available Tools\")}${muted(\n\t\t` read - Read file contents\n list - List files in a directory\n find - Fast file search using fd (glob patterns)\n search - Search files with ripgrep-style filtering\n parallel_ripgrep - Run multiple ripgrep patterns in parallel and merge line ranges\n diff - Show git diffs (workspace, staged, or ranges)\n bash - Execute bash commands\n edit - Edit files with find/replace\n write - Write files (creates/overwrites)\n todo - Create TodoWrite-style checklists\n\n Read-only tools: read,list,find,search,parallel_ripgrep,diff,status\n Example: maestro --tools read,list,find,search,parallel_ripgrep,diff \"Analyze this code\"`,\n\t)}`;\n\n\tconst frameworkSection = `${sectionHeading(\"Framework Preference\")}${muted(\n\t\t` /framework <id> Set default stack (fastapi, express, node)\n /framework <id> --workspace Set workspace-scoped default\n /framework list Show available options\n Precedence: policy (locked) > policy > env override > env default > workspace > user file > none`,\n\t)}`;\n\n\tconsole.log(\n\t\t[\n\t\t\theader,\n\t\t\tusage,\n\t\t\toptions,\n\t\t\texamples,\n\t\t\tenv,\n\t\t\texecSection,\n\t\t\twebSection,\n\t\t\tportabilitySection,\n\t\t\tmemorySection,\n\t\t\tinitSection,\n\t\t\tremoteSection,\n\t\t\thostedRunnerSection,\n\t\t\tsessionsSection,\n\t\t\tsessionsDiscovery,\n\t\t\t`${sectionHeading(\"Tips\")}${badge(\n\t\t\t\t\"Need models?\",\n\t\t\t\t\"maestro models list\",\n\t\t\t\t\"info\",\n\t\t\t)}`,\n\t\t\tframeworkSection,\n\t\t\ttools,\n\t\t].join(\"\\n\\n\"),\n\t);\n}\n"]}
1
+ {"version":3,"file":"help.js","sourceRoot":"","sources":["../../src/cli/help.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACxC,MAAM,MAAM,GAAG,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,KAAK,CAC5C,IAAI,OAAO,gGAAgG,CAC3G,EAAE,CAAC;IACJ,MAAM,KAAK,GAAG,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,KAAK,CAC/C,iCAAiC,CACjC,EAAE,CAAC;IACJ,MAAM,OAAO,GAAG,GAAG,cAAc,CAAC,SAAS,CAAC,GAAG;QAC9C,4DAA4D;QAC5D,+DAA+D;QAC/D,iEAAiE;QACjE,2EAA2E;QAC3E,4FAA4F;QAC5F,wDAAwD;QACxD,0EAA0E;QAC1E,yEAAyE;QACzE,mEAAmE;QACnE,0EAA0E;QAC1E,+EAA+E;QAC/E,gFAAgF;QAChF,+EAA+E;QAC/E,mDAAmD;QACnD,oDAAoD;QACpD,mDAAmD;QACnD,wDAAwD;QACxD,0DAA0D;QAC1D,wCAAwC;KACxC;SACC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;SACjC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;IACf,MAAM,QAAQ,GAAG,GAAG,cAAc,CAAC,UAAU,CAAC,GAAG,KAAK,CACrD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uCA8CqC,CACrC,EAAE,CAAC;IACJ,MAAM,GAAG,GAAG,GAAG,cAAc,CAAC,wBAAwB,CAAC,GAAG,KAAK,CAC9D;;;;;;;;;;;;;;;;;;;;;;yEAsBuE,CACvE,EAAE,CAAC;IACJ,MAAM,WAAW,GAAG,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG,KAAK,CAC5D;;;;;;;;;oEASkE,CAClE,EAAE,CAAC;IACJ,MAAM,UAAU,GAAG,GAAG,cAAc,CAAC,aAAa,CAAC,GAAG,KAAK,CAC1D;;;;0BAIwB,CACxB,EAAE,CAAC;IACJ,MAAM,kBAAkB,GAAG,GAAG,cAAc,CAAC,qBAAqB,CAAC,GAAG,KAAK,CAC1E;;;;;;;+EAO6E,CAC7E,EAAE,CAAC;IACJ,MAAM,aAAa,GAAG,GAAG,cAAc,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAChE;;;;mEAIiE,CACjE,EAAE,CAAC;IACJ,MAAM,aAAa,GAAG,GAAG,cAAc,CAAC,gBAAgB,CAAC,GAAG,KAAK,CAChE;;;;qDAImD,CACnD,EAAE,CAAC;IACJ,MAAM,WAAW,GAAG,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG,KAAK,CAC5D;;;6EAG2E,CAC3E,EAAE,CAAC;IACJ,MAAM,mBAAmB,GAAG,GAAG,cAAc,CAAC,uBAAuB,CAAC,GAAG,KAAK,CAC7E;;;8FAG4F,CAC5F,EAAE,CAAC;IACJ,MAAM,eAAe,GAAG,GAAG,cAAc,CAAC,kBAAkB,CAAC,GAAG,KAAK,CACpE;;mEAEiE,CACjE,EAAE,CAAC;IACJ,MAAM,iBAAiB,GAAG,GAAG,cAAc,CAAC,kBAAkB,CAAC,GAAG,KAAK,CACtE;;2CAEyC,CACzC,EAAE,CAAC;IACJ,MAAM,KAAK,GAAG,GAAG,cAAc,CAAC,iBAAiB,CAAC,GAAG,KAAK,CACzD;;;;;;;;;;;;2FAYyF,CACzF,EAAE,CAAC;IAEJ,MAAM,gBAAgB,GAAG,GAAG,cAAc,CAAC,sBAAsB,CAAC,GAAG,KAAK,CACzE;;;mGAGiG,CACjG,EAAE,CAAC;IAEJ,OAAO,CAAC,GAAG,CACV;QACC,MAAM;QACN,KAAK;QACL,OAAO;QACP,QAAQ;QACR,GAAG;QACH,WAAW;QACX,UAAU;QACV,kBAAkB;QAClB,aAAa;QACb,WAAW;QACX,aAAa;QACb,mBAAmB;QACnB,eAAe;QACf,iBAAiB;QACjB,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG,KAAK,CAChC,cAAc,EACd,qBAAqB,EACrB,MAAM,CACN,EAAE;QACH,gBAAgB;QAChB,KAAK;KACL,CAAC,IAAI,CAAC,MAAM,CAAC,CACd,CAAC;AACH,CAAC","sourcesContent":["/**\n * @fileoverview CLI Help Output Module\n *\n * This module generates and displays the `--help` output for the Maestro CLI.\n * It provides a comprehensive overview of:\n *\n * - **Usage syntax** and common invocation patterns\n * - **Command-line options** for provider, model, session management, etc.\n * - **Environment variables** for API keys and configuration\n * - **Available tools** and their capabilities\n * - **Subcommands** like `maestro exec` for headless execution\n * - **Session management** commands and workflows\n *\n * ## Styling\n *\n * The output uses the application's theme system for consistent terminal styling:\n * - `heading()` - Main title styling\n * - `sectionHeading()` - Section headers\n * - `muted()` - De-emphasized text for descriptions\n * - `badge()` - Highlighted tips and hints\n *\n * @module cli/help\n */\nimport { badge, heading, muted, sectionHeading } from \"../style/theme.js\";\n\n/**\n * Prints the complete CLI help message to stdout.\n *\n * This function is invoked when the user runs `maestro --help` or `maestro -h`.\n * It formats and displays all available options, commands, and usage examples\n * using the terminal theme for consistent styling.\n *\n * @param version - The current Maestro version string (e.g., \"1.2.3\")\n *\n * @example\n * ```typescript\n * import { printHelp } from \"./help.js\";\n * import { version } from \"../../package.json\";\n *\n * if (args.includes(\"--help\")) {\n * printHelp(version);\n * process.exit(0);\n * }\n * ```\n */\nexport function printHelp(version: string) {\n\tconst header = `${heading(\"Maestro\")} ${muted(\n\t\t`v${version} by EvalOps — AI coding assistant with read, list, search, diff, bash, edit, write, todo tools`,\n\t)}`;\n\tconst usage = `${sectionHeading(\"Usage\")}${muted(\n\t\t\"maestro [options] [messages...]\",\n\t)}`;\n\tconst options = `${sectionHeading(\"Options\")}${[\n\t\t\"--provider <name> Provider name (default: anthropic)\",\n\t\t\"-m, --model <id> Model ID (default: claude-sonnet-4-5)\",\n\t\t\"--task-budget <tokens> API-side Anthropic task budget in tokens\",\n\t\t\"--models <patterns> Comma-separated patterns for Ctrl+P model cycling\",\n\t\t\"--tools <names> Comma-separated tool names to enable (e.g., read,search,list,find)\",\n\t\t\"--api-key <key> API key (defaults to env vars)\",\n\t\t\"--system-prompt <text> System prompt (default: coding assistant prompt)\",\n\t\t\"--append-system-prompt <text> Append instructions to the system prompt\",\n\t\t\"--mode <mode> Output mode: text (default), json, or rpc\",\n\t\t\"--auth <mode> Credential mode: auto (default), api-key, claude\",\n\t\t\"--approval-mode <mode> Action approvals: prompt (default in TUI), auto, fail\",\n\t\t\"--sandbox <mode> Sandbox mode: docker, local, none (see docs/SAFETY.md)\",\n\t\t\"--port <n> Port for `maestro web` (defaults to PORT env or 8080)\",\n\t\t\"--continue, -c Continue previous session\",\n\t\t\"--resume, -r Select a session to resume\",\n\t\t\"--session <path> Use specific session file\",\n\t\t\"--no-session Don't save session (ephemeral)\",\n\t\t\"--safe-mode Enable extra safety restrictions\",\n\t\t\"--help, -h Show this help\",\n\t]\n\t\t.map((line) => ` ${muted(line)}`)\n\t\t.join(\"\\n\")}`;\n\tconst examples = `${sectionHeading(\"Examples\")}${muted(\n\t\t` # Interactive mode (no messages = interactive TUI)\n maestro\n\n # Single message\n maestro \"List all .ts files in src/\"\n\n # Multiple messages\n maestro \"Read package.json\" \"What dependencies do we have?\"\n\n # Continue previous session\n maestro --continue \"What did we discuss?\"\n\n # Use different model\n maestro --provider openai --model gpt-4o-mini \"Help me refactor this code\"\n\n # Use Codex subscription models after \\`maestro codex login\\`\n maestro --provider openai-codex --model gpt-5.5 \"Plan this migration\"\n\n # Bootstrap EvalOps login, API key, and agent registration in one flow\n maestro init\n\n # Use EvalOps managed gateway models after \\`maestro init\\`\n maestro --provider evalops --model gpt-4o-mini \"Say hello in one sentence\"\n\n # Confirm managed mode sinks and EvalOps org identity\n maestro status\n\n # Export a portable session log\n maestro export <session-id> ./session.jsonl --format jsonl\n\n # Export a portable JSON archive with secret redaction\n maestro export <session-id> ./session.json --format json --redact-secrets\n\n # Import a portable session log into this workspace\n maestro import ./session.json\n\n # Start a hosted EvalOps runner session and wait for attach readiness\n maestro remote start --workspace ws_123 --repo evalops/foo --branch main --ttl 90m --wait --verify\n\n # Run a single-session hosted runtime pod entrypoint\n maestro hosted-runner --runner-session-id mrs_abc --workspace-root /workspace --listen 0.0.0.0:8080\n\n # Show usage analytics for the last 7 days\n maestro stats\n\n # Show usage analytics for one session\n maestro stats --session <session-id>`,\n\t)}`;\n\tconst env = `${sectionHeading(\"Environment Variables:\")}${muted(\n\t\t` GEMINI_API_KEY - Google Gemini API key\n OPENAI_API_KEY - OpenAI API key\n OPENAI_CODEX_TOKEN - OpenAI Codex ChatGPT access token\n OPENAI_CODEX_ACCOUNT_ID - ChatGPT account id when using a raw Codex token\n ANTHROPIC_API_KEY - Anthropic API key\n CLAUDE_CODE_TOKEN - Claude Code access token for --auth claude\n ANTHROPIC_OAUTH_TOKEN - Alternate env for Claude Code bearer tokens\n MAESTRO_AGENT_DIR - Session storage directory (default: ~/.maestro/agent)\n MAESTRO_SANDBOX_MODE - Sandbox mode: docker, local, none (default: none)\n MAESTRO_CHANGELOG - Set to off/false/hide/hidden/skip/0 to hide startup changelog banner\n MAESTRO_TUI_MINIMAL - Set to 1/true to disable animations and reduce TUI effects (SSH-friendly)\n MAESTRO_TUI_TOOL_MAX_CHARS - Max chars shown per tool output panel (0 = unlimited)\n MAESTRO_TUI_TOOL_MAX_LINES - Max lines shown per tool output panel (0 = unlimited)\n MAESTRO_MEMORY_BASE - Durable memory service base URL\n MAESTRO_MEMORY_ACCESS_TOKEN - Override bearer token for durable memory service\n MAESTRO_MEMORY_TEAM_ID - Optional team scope for durable memory service\n MAESTRO_SHARED_MEMORY_BASE - Shared memory base URL (Cloudflare Durable Objects worker)\n MAESTRO_SHARED_MEMORY_API_KEY - API key for shared memory service\n MAESTRO_REMOTE_RUNNER_URL - Hosted runner control-plane URL (default: https://runner.evalops.dev)\n MAESTRO_REMOTE_RUNNER_TOKEN - Hosted runner bearer token override\n MAESTRO_REMOTE_RUNNER_ORG_ID - EvalOps organization id for hosted runner sessions\n MAESTRO_REMOTE_RUNNER_WORKSPACE_ID - EvalOps workspace id for hosted runner sessions\n CODING_AGENT_DIR - Legacy session directory override (fallback)`,\n\t)}`;\n\tconst execSection = `${sectionHeading(\"maestro exec\")}${muted(\n\t\t` maestro exec \"Summarize recent changes\" --json\n\n Flags:\n --json Stream JSONL thread/turn events\n --output-schema <file|json> Validate final assistant JSON against a schema\n --output-last-message <path> Write the final assistant message to disk\n --full-auto | --read-only Force approval policy (auto or fail)\n --sandbox <mode> Run in sandbox: docker, local, none\n --resume <sessionId> Resume a prior exec session by id\n --last Resume the most recent exec session`,\n\t)}`;\n\tconst webSection = `${sectionHeading(\"maestro web\")}${muted(\n\t\t` # Start the bundled web UI + API server\n maestro web\n\n # Use a custom port\n maestro web --port 3000`,\n\t)}`;\n\tconst portabilitySection = `${sectionHeading(\"Session Portability\")}${muted(\n\t\t` maestro export <session-id> [output-path] --format json|jsonl [--redact-secrets]\n maestro import <file.json|file.jsonl>\n\n Notes:\n - json preserves the full session in a portable wrapper object\n - jsonl preserves the append-only session log verbatim unless redaction is requested\n - --redact-secrets scrubs detected credentials from exported payloads\n - import restores the session into the current workspace session directory`,\n\t)}`;\n\tconst memorySection = `${sectionHeading(\"maestro memory\")}${muted(\n\t\t` maestro memory [status] Show shared memory service status\n maestro memory session <id> Show per-session metrics\n maestro memory audit <id> [n] Show recent sync audit entries\n maestro memory export <id> Export metrics log as JSONL\n maestro memory watch [id] [ms] Poll status/metrics continuously`,\n\t)}`;\n\tconst remoteSection = `${sectionHeading(\"maestro remote\")}${muted(\n\t\t` maestro remote start --workspace <id> --repo <repo> --branch <branch> [--ttl 90m] [--wait] [--verify]\n maestro remote list --workspace <id> [--state running]\n maestro remote attach <session-id> [--verify] [--print-env]\n maestro remote extend <session-id> --ttl 2h\n maestro remote stop <session-id> [--reason <text>]`,\n\t)}`;\n\tconst initSection = `${sectionHeading(\"maestro init\")}${muted(\n\t\t` maestro init Login, create or reuse an API key, and register this agent\n maestro init --rotate-key Replace the stored agent MCP API key\n maestro init --mcp-url <url> Override the EvalOps agent MCP endpoint\n maestro init --json Emit machine-readable bootstrap output`,\n\t)}`;\n\tconst hostedRunnerSection = `${sectionHeading(\"maestro hosted-runner\")}${muted(\n\t\t` maestro hosted-runner --runner-session-id <id> --workspace-root <path> [--listen 0.0.0.0:8080]\n\n Env mode:\n MAESTRO_RUNNER_SESSION_ID=mrs_abc MAESTRO_WORKSPACE_ROOT=/workspace maestro hosted-runner`,\n\t)}`;\n\tconst sessionsSection = `${sectionHeading(\"Session Metadata\")}${muted(\n\t\t` /session favorite|unfavorite Toggle favorite for current session\n /session summary \"<text>\" Save a manual summary for current session\n /sessions summarize <id> Auto-summarize a saved session`,\n\t)}`;\n\tconst sessionsDiscovery = `${sectionHeading(\"Session Commands\")}${muted(\n\t\t` /session [info|favorite|unfavorite|summary \"<text>\"]\n /sessions [list|load <id>|favorite <id>|unfavorite <id>|summarize <id>]\n (Also available via TUI command palette)`,\n\t)}`;\n\tconst tools = `${sectionHeading(\"Available Tools\")}${muted(\n\t\t` read - Read file contents\n list - List files in a directory\n find - Fast file search using fd (glob patterns)\n search - Search files with ripgrep-style filtering\n parallel_ripgrep - Run multiple ripgrep patterns in parallel and merge line ranges\n diff - Show git diffs (workspace, staged, or ranges)\n bash - Execute bash commands\n edit - Edit files with find/replace\n write - Write files (creates/overwrites)\n todo - Create TodoWrite-style checklists\n\n Read-only tools: read,list,find,search,parallel_ripgrep,diff,status\n Example: maestro --tools read,list,find,search,parallel_ripgrep,diff \"Analyze this code\"`,\n\t)}`;\n\n\tconst frameworkSection = `${sectionHeading(\"Framework Preference\")}${muted(\n\t\t` /framework <id> Set default stack (fastapi, express, node)\n /framework <id> --workspace Set workspace-scoped default\n /framework list Show available options\n Precedence: policy (locked) > policy > env override > env default > workspace > user file > none`,\n\t)}`;\n\n\tconsole.log(\n\t\t[\n\t\t\theader,\n\t\t\tusage,\n\t\t\toptions,\n\t\t\texamples,\n\t\t\tenv,\n\t\t\texecSection,\n\t\t\twebSection,\n\t\t\tportabilitySection,\n\t\t\tmemorySection,\n\t\t\tinitSection,\n\t\t\tremoteSection,\n\t\t\thostedRunnerSection,\n\t\t\tsessionsSection,\n\t\t\tsessionsDiscovery,\n\t\t\t`${sectionHeading(\"Tips\")}${badge(\n\t\t\t\t\"Need models?\",\n\t\t\t\t\"maestro models list\",\n\t\t\t\t\"info\",\n\t\t\t)}`,\n\t\t\tframeworkSection,\n\t\t\ttools,\n\t\t].join(\"\\n\\n\"),\n\t);\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-controller.d.ts","sourceRoot":"","sources":["../../../src/cli-tui/tui-renderer/attachment-controller.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAItE,MAAM,WAAW,6BAA6B;IAC7C,iCAAiC;IACjC,aAAa,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACxC,iDAAiD;IACjD,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,gCAAgC;IAChC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,2BAA2B;IAC3C,IAAI,EAAE,wBAAwB,CAAC;IAC/B,SAAS,EAAE,6BAA6B,CAAC;CACzC;AAID,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2B;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,kBAAkB,CAAiC;IAC3D,OAAO,CAAC,wBAAwB,CAAK;gBAEzB,OAAO,EAAE,2BAA2B;IAKhD,4DAA4D;IAC5D,uBAAuB,IAAI,IAAI;IAK/B,iEAAiE;IACjE,qBAAqB,IAAI,OAAO;IAIhC;;;OAGG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAS/C;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAShD;;;OAGG;IACG,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IA4BhD;;;OAGG;IACH,wBAAwB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI;IAuCvD,OAAO,CAAC,+BAA+B;CA0BvC;AAID,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,2BAA2B,GAClC,oBAAoB,CAEtB"}
1
+ {"version":3,"file":"attachment-controller.d.ts","sourceRoot":"","sources":["../../../src/cli-tui/tui-renderer/attachment-controller.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAStE,MAAM,WAAW,6BAA6B;IAC7C,iCAAiC;IACjC,aAAa,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,wBAAwB;IACxC,iDAAiD;IACjD,gBAAgB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,gCAAgC;IAChC,aAAa,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,2BAA2B;IAC3C,IAAI,EAAE,wBAAwB,CAAC;IAC/B,SAAS,EAAE,6BAA6B,CAAC;CACzC;AAID,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA2B;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;IAC1D,OAAO,CAAC,kBAAkB,CAAiC;IAC3D,OAAO,CAAC,wBAAwB,CAAK;gBAEzB,OAAO,EAAE,2BAA2B;IAKhD,4DAA4D;IAC5D,uBAAuB,IAAI,IAAI;IAK/B,iEAAiE;IACjE,qBAAqB,IAAI,OAAO;IAIhC;;;OAGG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAS/C;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa;IAShD;;;OAGG;IACG,yBAAyB,IAAI,OAAO,CAAC,IAAI,CAAC;IAgChD;;;OAGG;IACH,wBAAwB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,IAAI;IAuCvD,OAAO,CAAC,+BAA+B;CA0BvC;AAID,wBAAgB,0BAA0B,CACzC,OAAO,EAAE,2BAA2B,GAClC,oBAAoB,CAEtB"}
@@ -5,7 +5,6 @@
5
5
  * and resolves them into Attachment objects when the user submits a prompt.
6
6
  */
7
7
  import { randomUUID } from "node:crypto";
8
- import Clipboard from "@crosscopy/clipboard";
9
8
  // ─── Controller ──────────────────────────────────────────────────────────────
10
9
  export class AttachmentController {
11
10
  constructor(options) {
@@ -50,6 +49,10 @@ export class AttachmentController {
50
49
  */
51
50
  async handleClipboardImagePaste() {
52
51
  try {
52
+ const Clipboard = await loadClipboardApi();
53
+ if (!Clipboard) {
54
+ return;
55
+ }
53
56
  if (!Clipboard.hasImage()) {
54
57
  return;
55
58
  }
@@ -140,4 +143,18 @@ export class AttachmentController {
140
143
  export function createAttachmentController(options) {
141
144
  return new AttachmentController(options);
142
145
  }
146
+ async function loadClipboardApi() {
147
+ try {
148
+ const module = await import("@crosscopy/clipboard");
149
+ const api = module.default ?? module;
150
+ if (typeof api.hasImage !== "function" ||
151
+ typeof api.getImageBinary !== "function") {
152
+ return undefined;
153
+ }
154
+ return api;
155
+ }
156
+ catch {
157
+ return undefined;
158
+ }
159
+ }
143
160
  //# sourceMappingURL=attachment-controller.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"attachment-controller.js","sourceRoot":"","sources":["../../../src/cli-tui/tui-renderer/attachment-controller.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,SAAS,MAAM,sBAAsB,CAAC;AAuB7C,gFAAgF;AAEhF,MAAM,OAAO,oBAAoB;IAMhC,YAAY,OAAoC;QAHxC,uBAAkB,GAAG,IAAI,GAAG,EAAsB,CAAC;QACnD,6BAAwB,GAAG,CAAC,CAAC;QAGpC,IAAI,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IACpC,CAAC;IAED,4DAA4D;IAC5D,uBAAuB;QACtB,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;QAChC,IAAI,CAAC,wBAAwB,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,iEAAiE;IACjE,qBAAqB;QACpB,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,GAAG,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,kBAAkB,CAAC,IAAY;QAC9B,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,GACvC,IAAI,CAAC,+BAA+B,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/D,OAAO;YACN,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;SAC7D,CAAC;IACH,CAAC;IAED;;OAEG;IACH,mBAAmB,CAAC,IAAY;QAC/B,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,GACvC,IAAI,CAAC,+BAA+B,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,OAAO;YACN,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;SAC7D,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,yBAAyB;QAC9B,IAAI,CAAC;YACJ,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC;gBAC3B,OAAO;YACR,CAAC;YACD,MAAM,SAAS,GAAG,MAAM,SAAS,CAAC,cAAc,EAAE,CAAC;YACnD,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1C,OAAO;YACR,CAAC;YACD,MAAM,YAAY,GAAG,OAAO,UAAU,EAAE,EAAE,CAAC;YAC3C,MAAM,QAAQ,GAAG,mBAAmB,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YACjE,MAAM,UAAU,GAAe;gBAC9B,EAAE,EAAE,YAAY;gBAChB,IAAI,EAAE,OAAO;gBACb,QAAQ;gBACR,QAAQ,EAAE,WAAW;gBACrB,IAAI,EAAE,SAAS,CAAC,MAAM;gBACtB,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;aAClD,CAAC;YACF,MAAM,QAAQ,GAAG,EAAE,IAAI,CAAC,wBAAwB,CAAC;YACjD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,QAAQ,GAAG,CAAC,CAAC;YACnD,IAAI,CAAC,SAAS,CAAC,aAAa,EAAE,CAAC;QAChC,CAAC;QAAC,MAAM,CAAC;YACR,+DAA+D;QAChE,CAAC;IACF,CAAC;IAED;;;OAGG;IACH,wBAAwB,CAAC,OAAuB;QAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAC5B,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CAC/C,CAAC;QACF,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,OAAO;QACR,CAAC;QACD,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAa,EAAE,CAAC;QAC9B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;YACzB,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC;YAC5C,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC5B,MAAM,OAAO,GAAa,EAAE,CAAC;gBAC7B,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;oBACtC,MAAM,QAAQ,GAAG,EAAE,IAAI,CAAC,wBAAwB,CAAC;oBACjD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;oBAClD,OAAO,CAAC,IAAI,CAAC,WAAW,QAAQ,GAAG,CAAC,CAAC;gBACtC,CAAC;gBACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACxB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;oBAC/B,OAAO;wBACN,OAAO,CAAC,MAAM,GAAG,CAAC;4BACjB,CAAC,CAAC,GAAG,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;4BACpC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACvB,CAAC;YACF,CAAC;YACD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;QACD,MAAM,YAAY,GAAG,QAAQ;aAC3B,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;aAClC,IAAI,CAAC,MAAM,CAAC,CAAC;QACf,IAAI,YAAY,EAAE,CAAC;YAClB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QACvC,CAAC;IACF,CAAC;IAED,0EAA0E;IAElE,+BAA+B,CACtC,IAAY,EACZ,OAA6B;QAK7B,IAAI,IAAI,CAAC,kBAAkB,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;YACxC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;QAClC,CAAC;QACD,IAAI,OAAO,GAAG,IAAI,CAAC;QACnB,MAAM,WAAW,GAAiB,EAAE,CAAC;QACrC,KAAK,MAAM,CAAC,EAAE,EAAE,UAAU,CAAC,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACxD,MAAM,MAAM,GAAG,WAAW,EAAE,GAAG,CAAC;YAChC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/B,SAAS;YACV,CAAC;YACD,MAAM,WAAW,GAAG,gBAAgB,UAAU,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,GAAG,CAAC;YACnF,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAClD,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC;QACD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACrB,IAAI,CAAC,uBAAuB,EAAE,CAAC;QAChC,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IACvC,CAAC;CACD;AAED,gFAAgF;AAEhF,MAAM,UAAU,0BAA0B,CACzC,OAAoC;IAEpC,OAAO,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC1C,CAAC","sourcesContent":["/**\n * AttachmentController — Manages pending image/file attachments.\n *\n * Tracks clipboard-pasted images and their marker tokens in the editor,\n * and resolves them into Attachment objects when the user submits a prompt.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport Clipboard from \"@crosscopy/clipboard\";\nimport type { Attachment } from \"../../agent/types.js\";\nimport type { PromptPayload, QueuedPrompt } from \"../prompt-queue.js\";\n\n// ─── Callback & Dependency Interfaces ────────────────────────────────────────\n\nexport interface AttachmentControllerCallbacks {\n\t/** Request a UI render cycle. */\n\trequestRender: () => void;\n}\n\nexport interface AttachmentControllerDeps {\n\t/** Insert text at the editor cursor position. */\n\tinsertEditorText: (text: string) => void;\n\t/** Set the full editor text. */\n\tsetEditorText: (text: string) => void;\n}\n\nexport interface AttachmentControllerOptions {\n\tdeps: AttachmentControllerDeps;\n\tcallbacks: AttachmentControllerCallbacks;\n}\n\n// ─── Controller ──────────────────────────────────────────────────────────────\n\nexport class AttachmentController {\n\tprivate readonly deps: AttachmentControllerDeps;\n\tprivate readonly callbacks: AttachmentControllerCallbacks;\n\tprivate pendingAttachments = new Map<number, Attachment>();\n\tprivate pendingAttachmentCounter = 0;\n\n\tconstructor(options: AttachmentControllerOptions) {\n\t\tthis.deps = options.deps;\n\t\tthis.callbacks = options.callbacks;\n\t}\n\n\t/** Remove all pending attachments and reset the counter. */\n\tclearPendingAttachments(): void {\n\t\tthis.pendingAttachments.clear();\n\t\tthis.pendingAttachmentCounter = 0;\n\t}\n\n\t/** Whether there are pending attachments awaiting submission. */\n\thasPendingAttachments(): boolean {\n\t\treturn this.pendingAttachments.size > 0;\n\t}\n\n\t/**\n\t * Replace attachment markers in the submitted text with descriptive labels\n\t * and return the resolved attachments alongside the updated text.\n\t */\n\tconsumeAttachments(text: string): PromptPayload {\n\t\tconst { text: updatedText, attachments } =\n\t\t\tthis.resolvePendingAttachmentMarkers(text, { consume: true });\n\t\treturn {\n\t\t\ttext: updatedText,\n\t\t\tattachments: attachments.length > 0 ? attachments : undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Build the current prompt payload without consuming the editor markers.\n\t */\n\tsnapshotAttachments(text: string): PromptPayload {\n\t\tconst { text: updatedText, attachments } =\n\t\t\tthis.resolvePendingAttachmentMarkers(text, { consume: false });\n\t\treturn {\n\t\t\ttext: updatedText,\n\t\t\tattachments: attachments.length > 0 ? attachments : undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Read an image from the system clipboard and register it as a pending\n\t * attachment, inserting a marker into the editor.\n\t */\n\tasync handleClipboardImagePaste(): Promise<void> {\n\t\ttry {\n\t\t\tif (!Clipboard.hasImage()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst imageData = await Clipboard.getImageBinary();\n\t\t\tif (!imageData || imageData.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst attachmentId = `att_${randomUUID()}`;\n\t\t\tconst fileName = `clipboard-image-${attachmentId.slice(-6)}.png`;\n\t\t\tconst attachment: Attachment = {\n\t\t\t\tid: attachmentId,\n\t\t\t\ttype: \"image\",\n\t\t\t\tfileName,\n\t\t\t\tmimeType: \"image/png\",\n\t\t\t\tsize: imageData.length,\n\t\t\t\tcontent: Buffer.from(imageData).toString(\"base64\"),\n\t\t\t};\n\t\t\tconst markerId = ++this.pendingAttachmentCounter;\n\t\t\tthis.pendingAttachments.set(markerId, attachment);\n\t\t\tthis.deps.insertEditorText(`[image #${markerId}]`);\n\t\t\tthis.callbacks.requestRender();\n\t\t} catch {\n\t\t\t// Ignore clipboard errors (permissions, empty clipboard, etc.)\n\t\t}\n\t}\n\n\t/**\n\t * Re-register attachments from cancelled/restored queue entries so their\n\t * markers resolve correctly on resubmission.\n\t */\n\trestoreQueuedAttachments(entries: QueuedPrompt[]): void {\n\t\tconst restored = entries.some(\n\t\t\t(entry) => (entry.attachments?.length ?? 0) > 0,\n\t\t);\n\t\tif (!restored) {\n\t\t\treturn;\n\t\t}\n\t\tthis.clearPendingAttachments();\n\t\tconst segments: string[] = [];\n\t\tfor (const entry of entries) {\n\t\t\tlet segment = entry.text;\n\t\t\tconst attachments = entry.attachments ?? [];\n\t\t\tif (attachments.length > 0) {\n\t\t\t\tconst markers: string[] = [];\n\t\t\t\tfor (const attachment of attachments) {\n\t\t\t\t\tconst markerId = ++this.pendingAttachmentCounter;\n\t\t\t\t\tthis.pendingAttachments.set(markerId, attachment);\n\t\t\t\t\tmarkers.push(`[image #${markerId}]`);\n\t\t\t\t}\n\t\t\t\tif (markers.length > 0) {\n\t\t\t\t\tconst trimmed = segment.trim();\n\t\t\t\t\tsegment =\n\t\t\t\t\t\ttrimmed.length > 0\n\t\t\t\t\t\t\t? `${trimmed}\\n${markers.join(\" \")}`\n\t\t\t\t\t\t\t: markers.join(\" \");\n\t\t\t\t}\n\t\t\t}\n\t\t\tsegments.push(segment);\n\t\t}\n\t\tconst restoredText = segments\n\t\t\t.filter((s) => s.trim().length > 0)\n\t\t\t.join(\"\\n\\n\");\n\t\tif (restoredText) {\n\t\t\tthis.deps.setEditorText(restoredText);\n\t\t}\n\t}\n\n\t// ─── Internal ──────────────────────────────────────────────────────────\n\n\tprivate resolvePendingAttachmentMarkers(\n\t\ttext: string,\n\t\toptions: { consume: boolean },\n\t): {\n\t\ttext: string;\n\t\tattachments: Attachment[];\n\t} {\n\t\tif (this.pendingAttachments.size === 0) {\n\t\t\treturn { text, attachments: [] };\n\t\t}\n\t\tlet updated = text;\n\t\tconst attachments: Attachment[] = [];\n\t\tfor (const [id, attachment] of this.pendingAttachments) {\n\t\t\tconst marker = `[image #${id}]`;\n\t\t\tif (!updated.includes(marker)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst replacement = `[attachment] ${attachment.fileName} (${attachment.mimeType})`;\n\t\t\tupdated = updated.split(marker).join(replacement);\n\t\t\tattachments.push(attachment);\n\t\t}\n\t\tif (options.consume) {\n\t\t\tthis.clearPendingAttachments();\n\t\t}\n\t\treturn { text: updated, attachments };\n\t}\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────────────\n\nexport function createAttachmentController(\n\toptions: AttachmentControllerOptions,\n): AttachmentController {\n\treturn new AttachmentController(options);\n}\n"]}
1
+ {"version":3,"file":"attachment-controller.js","sourceRoot":"","sources":["../../../src/cli-tui/tui-renderer/attachment-controller.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AttachmentController — Manages pending image/file attachments.\n *\n * Tracks clipboard-pasted images and their marker tokens in the editor,\n * and resolves them into Attachment objects when the user submits a prompt.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type { Attachment } from \"../../agent/types.js\";\nimport type { PromptPayload, QueuedPrompt } from \"../prompt-queue.js\";\n\ntype ClipboardApi = {\n\thasImage: () => boolean;\n\tgetImageBinary: () => Promise<Array<number>>;\n};\n\n// ─── Callback & Dependency Interfaces ────────────────────────────────────────\n\nexport interface AttachmentControllerCallbacks {\n\t/** Request a UI render cycle. */\n\trequestRender: () => void;\n}\n\nexport interface AttachmentControllerDeps {\n\t/** Insert text at the editor cursor position. */\n\tinsertEditorText: (text: string) => void;\n\t/** Set the full editor text. */\n\tsetEditorText: (text: string) => void;\n}\n\nexport interface AttachmentControllerOptions {\n\tdeps: AttachmentControllerDeps;\n\tcallbacks: AttachmentControllerCallbacks;\n}\n\n// ─── Controller ──────────────────────────────────────────────────────────────\n\nexport class AttachmentController {\n\tprivate readonly deps: AttachmentControllerDeps;\n\tprivate readonly callbacks: AttachmentControllerCallbacks;\n\tprivate pendingAttachments = new Map<number, Attachment>();\n\tprivate pendingAttachmentCounter = 0;\n\n\tconstructor(options: AttachmentControllerOptions) {\n\t\tthis.deps = options.deps;\n\t\tthis.callbacks = options.callbacks;\n\t}\n\n\t/** Remove all pending attachments and reset the counter. */\n\tclearPendingAttachments(): void {\n\t\tthis.pendingAttachments.clear();\n\t\tthis.pendingAttachmentCounter = 0;\n\t}\n\n\t/** Whether there are pending attachments awaiting submission. */\n\thasPendingAttachments(): boolean {\n\t\treturn this.pendingAttachments.size > 0;\n\t}\n\n\t/**\n\t * Replace attachment markers in the submitted text with descriptive labels\n\t * and return the resolved attachments alongside the updated text.\n\t */\n\tconsumeAttachments(text: string): PromptPayload {\n\t\tconst { text: updatedText, attachments } =\n\t\t\tthis.resolvePendingAttachmentMarkers(text, { consume: true });\n\t\treturn {\n\t\t\ttext: updatedText,\n\t\t\tattachments: attachments.length > 0 ? attachments : undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Build the current prompt payload without consuming the editor markers.\n\t */\n\tsnapshotAttachments(text: string): PromptPayload {\n\t\tconst { text: updatedText, attachments } =\n\t\t\tthis.resolvePendingAttachmentMarkers(text, { consume: false });\n\t\treturn {\n\t\t\ttext: updatedText,\n\t\t\tattachments: attachments.length > 0 ? attachments : undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Read an image from the system clipboard and register it as a pending\n\t * attachment, inserting a marker into the editor.\n\t */\n\tasync handleClipboardImagePaste(): Promise<void> {\n\t\ttry {\n\t\t\tconst Clipboard = await loadClipboardApi();\n\t\t\tif (!Clipboard) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!Clipboard.hasImage()) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst imageData = await Clipboard.getImageBinary();\n\t\t\tif (!imageData || imageData.length === 0) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst attachmentId = `att_${randomUUID()}`;\n\t\t\tconst fileName = `clipboard-image-${attachmentId.slice(-6)}.png`;\n\t\t\tconst attachment: Attachment = {\n\t\t\t\tid: attachmentId,\n\t\t\t\ttype: \"image\",\n\t\t\t\tfileName,\n\t\t\t\tmimeType: \"image/png\",\n\t\t\t\tsize: imageData.length,\n\t\t\t\tcontent: Buffer.from(imageData).toString(\"base64\"),\n\t\t\t};\n\t\t\tconst markerId = ++this.pendingAttachmentCounter;\n\t\t\tthis.pendingAttachments.set(markerId, attachment);\n\t\t\tthis.deps.insertEditorText(`[image #${markerId}]`);\n\t\t\tthis.callbacks.requestRender();\n\t\t} catch {\n\t\t\t// Ignore clipboard errors (permissions, empty clipboard, etc.)\n\t\t}\n\t}\n\n\t/**\n\t * Re-register attachments from cancelled/restored queue entries so their\n\t * markers resolve correctly on resubmission.\n\t */\n\trestoreQueuedAttachments(entries: QueuedPrompt[]): void {\n\t\tconst restored = entries.some(\n\t\t\t(entry) => (entry.attachments?.length ?? 0) > 0,\n\t\t);\n\t\tif (!restored) {\n\t\t\treturn;\n\t\t}\n\t\tthis.clearPendingAttachments();\n\t\tconst segments: string[] = [];\n\t\tfor (const entry of entries) {\n\t\t\tlet segment = entry.text;\n\t\t\tconst attachments = entry.attachments ?? [];\n\t\t\tif (attachments.length > 0) {\n\t\t\t\tconst markers: string[] = [];\n\t\t\t\tfor (const attachment of attachments) {\n\t\t\t\t\tconst markerId = ++this.pendingAttachmentCounter;\n\t\t\t\t\tthis.pendingAttachments.set(markerId, attachment);\n\t\t\t\t\tmarkers.push(`[image #${markerId}]`);\n\t\t\t\t}\n\t\t\t\tif (markers.length > 0) {\n\t\t\t\t\tconst trimmed = segment.trim();\n\t\t\t\t\tsegment =\n\t\t\t\t\t\ttrimmed.length > 0\n\t\t\t\t\t\t\t? `${trimmed}\\n${markers.join(\" \")}`\n\t\t\t\t\t\t\t: markers.join(\" \");\n\t\t\t\t}\n\t\t\t}\n\t\t\tsegments.push(segment);\n\t\t}\n\t\tconst restoredText = segments\n\t\t\t.filter((s) => s.trim().length > 0)\n\t\t\t.join(\"\\n\\n\");\n\t\tif (restoredText) {\n\t\t\tthis.deps.setEditorText(restoredText);\n\t\t}\n\t}\n\n\t// ─── Internal ──────────────────────────────────────────────────────────\n\n\tprivate resolvePendingAttachmentMarkers(\n\t\ttext: string,\n\t\toptions: { consume: boolean },\n\t): {\n\t\ttext: string;\n\t\tattachments: Attachment[];\n\t} {\n\t\tif (this.pendingAttachments.size === 0) {\n\t\t\treturn { text, attachments: [] };\n\t\t}\n\t\tlet updated = text;\n\t\tconst attachments: Attachment[] = [];\n\t\tfor (const [id, attachment] of this.pendingAttachments) {\n\t\t\tconst marker = `[image #${id}]`;\n\t\t\tif (!updated.includes(marker)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst replacement = `[attachment] ${attachment.fileName} (${attachment.mimeType})`;\n\t\t\tupdated = updated.split(marker).join(replacement);\n\t\t\tattachments.push(attachment);\n\t\t}\n\t\tif (options.consume) {\n\t\t\tthis.clearPendingAttachments();\n\t\t}\n\t\treturn { text: updated, attachments };\n\t}\n}\n\n// ─── Factory ─────────────────────────────────────────────────────────────────\n\nexport function createAttachmentController(\n\toptions: AttachmentControllerOptions,\n): AttachmentController {\n\treturn new AttachmentController(options);\n}\n\nasync function loadClipboardApi(): Promise<ClipboardApi | undefined> {\n\ttry {\n\t\tconst module = await import(\"@crosscopy/clipboard\");\n\t\tconst api = module.default ?? module;\n\t\tif (\n\t\t\ttypeof api.hasImage !== \"function\" ||\n\t\t\ttypeof api.getImageBinary !== \"function\"\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn api;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n"]}