@alexkroman1/aai-cli 13.2.0 → 14.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/bin.mjs +1 -1
  2. package/dist/{_agent-BTwZJu4P.mjs → _agent-BzUeqOdj.mjs} +33 -10
  3. package/dist/_agent.d.ts +23 -0
  4. package/dist/{_bundler-C31rlcYz.mjs → _bundler-DolUCMxu.mjs} +9 -8
  5. package/dist/_cli-common.d.ts +45 -6
  6. package/dist/{_config-CmJOFsAP.mjs → _config-DYzC6WMD.mjs} +7 -4
  7. package/dist/_config.d.ts +25 -1
  8. package/dist/_dev-env.d.ts +1 -1
  9. package/dist/{_dev-server-DWvkNoIS.mjs → _dev-server-CSMqF8PN.mjs} +28 -30
  10. package/dist/_dev-vite-config.d.ts +3 -3
  11. package/dist/_e2e-test-utils.d.ts +15 -7
  12. package/dist/{_init-BURbdHNM.mjs → _init-CQ8idAwo.mjs} +64 -30
  13. package/dist/{_output-CKkmWs7i.mjs → _output-DBP9Op_d.mjs} +43 -3
  14. package/dist/_output.d.ts +24 -7
  15. package/dist/{_preflight-Co1G9Jww.mjs → _preflight-CcAR577V.mjs} +3 -3
  16. package/dist/_resource-commands.d.ts +9 -9
  17. package/dist/{_server-common-6e0QI4mq.mjs → _server-common-vILJp3it.mjs} +3 -3
  18. package/dist/{_slug-api-CfGQq1Tt.mjs → _slug-api-CGvc2YSQ.mjs} +19 -10
  19. package/dist/_slug-api.d.ts +19 -0
  20. package/dist/{_studio-B1waXMuR.mjs → _studio-DnR_BqFp.mjs} +9 -5
  21. package/dist/_studio-commands.d.ts +13 -13
  22. package/dist/{_templates-0Zr2z6yA.mjs → _templates-CK4oKoeX.mjs} +3 -3
  23. package/dist/{_typecheck-gate-BXvUNnfs.mjs → _typecheck-gate-U3jcil8L.mjs} +5 -4
  24. package/dist/_typecheck-gate.d.ts +3 -1
  25. package/dist/{_ui-u7T4YooX.mjs → _ui-DCt4qZrk.mjs} +1 -1
  26. package/dist/{_utils-B8QmtFhK.mjs → _utils-D5JGcjiW.mjs} +44 -2
  27. package/dist/_utils.d.ts +35 -0
  28. package/dist/{_vite-env-D9Qj6KPX.mjs → _vite-env-kejF0p2L.mjs} +1 -1
  29. package/dist/{_workflow-determinism-f9J-5Zlj.mjs → _workflow-determinism-CvpqMpdh.mjs} +19 -27
  30. package/dist/_workflow-determinism.d.ts +3 -3
  31. package/dist/build-Mxk8gWvX.mjs +108 -0
  32. package/dist/build.d.ts +5 -0
  33. package/dist/cli.mjs +172 -116
  34. package/dist/{client-bundler-j5c46x0G.mjs → client-bundler-BJgREAh6.mjs} +4 -4
  35. package/dist/client-bundler.mjs +1 -1
  36. package/dist/{delete-X_CRgCf6.mjs → delete-BdFnbnVR.mjs} +6 -6
  37. package/dist/{deploy-BzZ-r4iM.mjs → deploy-uAJ4NukN.mjs} +14 -14
  38. package/dist/{dev-BDykFvcc.mjs → dev-DApPSaE_.mjs} +5 -5
  39. package/dist/{eval-0qEOdm0l.mjs → eval-BK47A_K5.mjs} +27 -11
  40. package/dist/eval.d.ts +2 -0
  41. package/dist/{init-BtJI306C.mjs → init-DukDxECd.mjs} +13 -21
  42. package/dist/{login-DeUETobb.mjs → login-DaLrPOFg.mjs} +6 -8
  43. package/dist/{logs-hWnJ66Bl.mjs → logs-7BRwq0cG.mjs} +22 -15
  44. package/dist/project-config.mjs +1 -1
  45. package/dist/scaffold/.env.example +17 -1
  46. package/dist/scaffold/CLAUDE.md +84 -56
  47. package/dist/scaffold/package.json +6 -5
  48. package/dist/scaffold/server.mjs +129 -25
  49. package/dist/secret-Cjp912yF.mjs +162 -0
  50. package/dist/secret.d.ts +48 -13
  51. package/dist/{studio-BxAS_FQQ.mjs → studio-CpHlNHUZ.mjs} +15 -17
  52. package/dist/templates/briefing-desk/agent.test.ts +7 -3
  53. package/dist/templates/call-audit/agent.test.ts +25 -9
  54. package/dist/templates/call-audit/agent.ts +2 -2
  55. package/dist/templates/call-audit/client.tsx +40 -58
  56. package/dist/templates/call-audit/workflows/audit.ts +7 -5
  57. package/dist/templates/call-audit/workflows/ingest.ts +7 -7
  58. package/dist/templates/call-audit/workflows/media.ts +12 -37
  59. package/dist/templates/call-audit/workflows/summarize.ts +8 -8
  60. package/dist/templates/call-audit/workflows/sync-api.ts +3 -3
  61. package/dist/templates/dispatch-center/agent.test.ts +7 -7
  62. package/dist/templates/dispatch-center/client.tsx +53 -61
  63. package/dist/templates/dispatch-center/shared.ts +0 -8
  64. package/dist/templates/dispatch-center/tools/ops_dashboard.ts +4 -1
  65. package/dist/templates/embedded-assets/agent.eval.test.ts +4 -2
  66. package/dist/templates/embedded-assets/agent.test.ts +7 -1
  67. package/dist/templates/health-assistant/agent.eval.test.ts +4 -2
  68. package/dist/templates/health-assistant/agent.test.ts +8 -4
  69. package/dist/templates/infocom-adventure/client.tsx +40 -36
  70. package/dist/templates/link-digest/agent.test.ts +10 -4
  71. package/dist/templates/link-digest/agent.ts +2 -2
  72. package/dist/templates/link-digest/client.tsx +42 -36
  73. package/dist/templates/link-digest/workflows/digest.ts +13 -16
  74. package/dist/templates/night-owl/agent.eval.test.ts +4 -2
  75. package/dist/templates/night-owl/agent.test.ts +6 -1
  76. package/dist/templates/night-owl/client.tsx +8 -2
  77. package/dist/templates/pipeline-simple/agent.test.ts +33 -16
  78. package/dist/templates/pizza-ordering/client.tsx +5 -4
  79. package/dist/templates/pizza-ordering/shared.ts +3 -8
  80. package/dist/templates/pizza-ordering/tools/add_pizza.ts +3 -2
  81. package/dist/templates/pizza-ordering/tools/place_order.ts +3 -2
  82. package/dist/templates/pizza-ordering/tools/remove_pizza.ts +3 -2
  83. package/dist/templates/pizza-ordering/tools/update_pizza.ts +3 -2
  84. package/dist/templates/pizza-ordering/tools/view_order.ts +3 -2
  85. package/dist/templates/plan-and-execute/agent.test.ts +10 -5
  86. package/dist/templates/plan-and-execute/client.tsx +2 -2
  87. package/dist/templates/podcast-digest/agent.test.ts +33 -14
  88. package/dist/templates/podcast-digest/client.tsx +27 -36
  89. package/dist/templates/podcast-digest/workflows/digest.ts +21 -19
  90. package/dist/templates/podcast-digest/workflows/feeds.ts +61 -33
  91. package/dist/templates/podcast-digest/workflows/slack.ts +7 -7
  92. package/dist/templates/recap-workflow/agent.eval.test.ts +21 -13
  93. package/dist/templates/recap-workflow/agent.test.ts +49 -32
  94. package/dist/templates/recap-workflow/workflows/recap.ts +24 -28
  95. package/dist/templates/redline/agent.eval.test.ts +5 -8
  96. package/dist/templates/redline/agent.test.ts +8 -2
  97. package/dist/templates/redline/client.tsx +47 -48
  98. package/dist/templates/redline/workflows/redline.ts +17 -17
  99. package/dist/templates/research-workflow/agent.eval.test.ts +5 -5
  100. package/dist/templates/research-workflow/agent.test.ts +17 -8
  101. package/dist/templates/research-workflow/workflows/research.ts +28 -30
  102. package/dist/templates/retail/agent.test.ts +17 -15
  103. package/dist/templates/retail/cancel.ts +7 -6
  104. package/dist/templates/retail/client.tsx +39 -58
  105. package/dist/templates/retail/payment.ts +4 -3
  106. package/dist/templates/retail/pending.test.ts +19 -19
  107. package/dist/templates/retail/registry.test.ts +99 -58
  108. package/dist/templates/retail/store.test.ts +5 -5
  109. package/dist/templates/retail/swap.ts +8 -11
  110. package/dist/templates/simple/agent.test.ts +39 -6
  111. package/dist/templates/solo-rpg/agent.eval.test.ts +2 -16
  112. package/dist/templates/solo-rpg/agent.test.ts +12 -12
  113. package/dist/templates/solo-rpg/client.tsx +3 -3
  114. package/dist/templates/spoken-summary/agent.test.ts +21 -12
  115. package/dist/templates/spoken-summary/agent.ts +3 -3
  116. package/dist/templates/spoken-summary/client.tsx +36 -47
  117. package/dist/templates/spoken-summary/workflows/summarize.ts +11 -11
  118. package/dist/templates/spoken-summary/workflows/transcribe.ts +14 -14
  119. package/dist/templates/support-line/client.tsx +4 -3
  120. package/dist/templates/support-line/prompts.ts +0 -2
  121. package/dist/templates/transcription-workflow/agent.test.ts +36 -20
  122. package/dist/templates/transcription-workflow/agent.ts +2 -2
  123. package/dist/templates/transcription-workflow/client.tsx +34 -40
  124. package/dist/templates/transcription-workflow/recover.ts +1 -1
  125. package/dist/templates/transcription-workflow/run-panel.tsx +34 -14
  126. package/dist/templates/transcription-workflow/total-latency.tsx +46 -20
  127. package/dist/templates/transcription-workflow/workflows/batch.ts +15 -15
  128. package/dist/templates/transcription-workflow/workflows/downsample.ts +1 -1
  129. package/dist/templates/transcription-workflow/workflows/normalize.ts +15 -19
  130. package/dist/templates/transcription-workflow/workflows/stream.ts +12 -12
  131. package/dist/templates/transcription-workflow/workflows/sync-api.ts +3 -3
  132. package/dist/templates/transcription-workflow/workflows/transcribe.ts +23 -34
  133. package/dist/templates/travel-concierge/agent.eval.test.ts +2 -2
  134. package/dist/templates/travel-concierge/agent.test.ts +15 -7
  135. package/dist/templates/travel-concierge/client.tsx +2 -2
  136. package/dist/templates/travel-concierge/shared.ts +10 -14
  137. package/dist/templates/travel-concierge/tools/lookup_booking.ts +4 -3
  138. package/dist/templates/travel-concierge/tools/search_car_rentals.ts +3 -2
  139. package/dist/templates/travel-concierge/tools/search_excursions.ts +3 -2
  140. package/dist/templates/travel-concierge/tools/search_flights.ts +3 -2
  141. package/dist/templates/travel-concierge/tools/search_hotels.ts +3 -2
  142. package/dist/test-D032V2cA.mjs +242 -0
  143. package/dist/test.d.ts +97 -31
  144. package/dist/typecheck.mjs +2 -2
  145. package/dist/worker-bundler.mjs +3 -3
  146. package/dist/{workflow-BBu5oEDw.mjs → workflow-CVioyO3V.mjs} +8 -7
  147. package/package.json +10 -10
  148. package/dist/bin.d.mts +0 -2
  149. package/dist/build-BLlLOrng.mjs +0 -66
  150. package/dist/secret-B-3T5tvr.mjs +0 -61
  151. package/dist/test-CiLab-AA.mjs +0 -182
  152. package/dist/tsdown.config.d.ts +0 -2
package/bin.mjs CHANGED
@@ -25,7 +25,7 @@ enableCompileCache();
25
25
  // Source wins when present: a checkout that has also been built must keep
26
26
  // running `cli.ts`, or `pnpm link --global` would silently serve a stale
27
27
  // `dist/` instead of the working tree.
28
- const source = new URL("./cli.ts", import.meta.url);
28
+ const source = new URL("./src/cli.ts", import.meta.url);
29
29
  const entry = existsSync(fileURLToPath(source))
30
30
  ? source
31
31
  : new URL("./dist/cli.mjs", import.meta.url);
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { a as serverOrigin, i as readProjectConfig, n as ensureApiKey, r as readGlobalConfig, t as approveServer } from "./_config-CmJOFsAP.mjs";
2
+ import { m as stripTrailingSlash } from "./_utils-D5JGcjiW.mjs";
3
+ import { a as serverOrigin, i as readProjectConfig, n as ensureApiKey, r as readGlobalConfig, t as approveServer } from "./_config-DYzC6WMD.mjs";
3
4
  import { existsSync } from "node:fs";
4
5
  import path from "node:path";
5
6
  import { fileURLToPath } from "node:url";
6
7
  import { VALID_SLUG_RE } from "@alexkroman1/aai/internal";
7
- //#region _agent.ts
8
+ //#region src/_agent.ts
8
9
  const DEFAULT_SERVER = "https://alexkroman--aai-server-web-server.modal.run";
9
10
  const DEFAULT_DEV_SERVER = "http://localhost:8080";
10
11
  let _cachedMonorepoRoot;
@@ -18,9 +19,6 @@ function isDevMode() {
18
19
  if (process.env.AAI_NO_DEV === "1") return false;
19
20
  return getMonorepoRoot() !== null;
20
21
  }
21
- function stripTrailingSlash(url) {
22
- return url.replace(/\/+$/, "");
23
- }
24
22
  /**
25
23
  * Whether `origin` may receive a credential without prior user approval.
26
24
  *
@@ -82,14 +80,39 @@ function assertValidConfigSlug(slug) {
82
80
  throw new Error(`Invalid slug in .aai/project.json: ${JSON.stringify(slug)}\n Expected lowercase letters, digits, \`-\`, \`_\` (2-64 chars). Fix or delete the file — \`aai publish\` will create a fresh deployment.`);
83
81
  }
84
82
  /**
85
- * Resolve everything needed to talk to the platform: project config (null if
86
- * the project has never been deployed), server URL, and API key.
83
+ * Everything `resolveDeployTarget` decides BEFORE a credential is involved:
84
+ * the project config (null when never deployed, or when `cwd` is null), the
85
+ * user's global config, and the trust-checked, approved server URL.
87
86
  */
88
- async function resolveDeployTarget(cwd, explicitServer) {
89
- const [config, globalConfig] = await Promise.all([readProjectConfig(cwd), readGlobalConfig()]);
87
+ async function resolveApprovedServer(cwd, explicitServer) {
88
+ const [config, globalConfig] = await Promise.all([cwd === null ? null : readProjectConfig(cwd), readGlobalConfig()]);
90
89
  const serverUrl = resolveServerUrl(explicitServer, config?.serverUrl, globalConfig.approvedServers ?? []);
91
90
  if (explicitServer) await approveServer(serverUrl);
92
91
  assertValidConfigSlug(config?.slug);
92
+ return {
93
+ config,
94
+ globalConfig,
95
+ serverUrl
96
+ };
97
+ }
98
+ /**
99
+ * Resolve everything needed to talk to the platform: project config (null if
100
+ * the project has never been deployed), server URL, and API key.
101
+ *
102
+ * `resolveApprovedServer` plus the key, rather than one function, because
103
+ * `aai login` needs the first half and cannot have the second — it is the
104
+ * command that PUTS the key on disk. It had its own copy of the
105
+ * read → `resolveServerUrl` → `approveServer` sequence, which is security
106
+ * policy ("passing `--server` is what approves an origin"), so a change to that
107
+ * policy landed here and silently missed the one command whose whole job is to
108
+ * write a credential for the origin in question. Same shape as the slug-guard
109
+ * incident `assertValidConfigSlug` was moved down here for.
110
+ *
111
+ * The key comes from the config document already in hand — `ensureApiKey` would
112
+ * read and parse the same file a second time, on every platform command.
113
+ */
114
+ async function resolveDeployTarget(cwd, explicitServer) {
115
+ const { config, serverUrl } = await resolveApprovedServer(cwd, explicitServer);
93
116
  return {
94
117
  config,
95
118
  serverUrl,
@@ -126,4 +149,4 @@ async function getServerInfo(cwd, explicitServer) {
126
149
  };
127
150
  }
128
151
  //#endregion
129
- export { resolveDeployTarget as a, requireDeployedSlug as i, getServerInfo as n, resolveServerUrl as o, isDevMode as r, getMonorepoRoot as t };
152
+ export { resolveApprovedServer as a, requireDeployedSlug as i, getServerInfo as n, resolveDeployTarget as o, isDevMode as r, getMonorepoRoot as t };
package/dist/_agent.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { type GlobalConfig, type ProjectConfig } from "./_config.ts";
1
2
  export declare const DEFAULT_SERVER = "https://alexkroman--aai-server-web-server.modal.run";
2
3
  export declare const DEFAULT_DEV_SERVER = "http://localhost:8080";
3
4
  export declare function getMonorepoRoot(): string | null;
@@ -19,9 +20,31 @@ export declare function isDevMode(): boolean;
19
20
  * @param approvedOrigins - Origins from the user-owned global config.
20
21
  */
21
22
  export declare function resolveServerUrl(explicit?: string, configUrl?: string, approvedOrigins?: readonly string[]): string;
23
+ /**
24
+ * Everything `resolveDeployTarget` decides BEFORE a credential is involved:
25
+ * the project config (null when never deployed, or when `cwd` is null), the
26
+ * user's global config, and the trust-checked, approved server URL.
27
+ */
28
+ export declare function resolveApprovedServer(cwd: string | null, explicitServer?: string): Promise<{
29
+ config: ProjectConfig | null;
30
+ globalConfig: GlobalConfig;
31
+ serverUrl: string;
32
+ }>;
22
33
  /**
23
34
  * Resolve everything needed to talk to the platform: project config (null if
24
35
  * the project has never been deployed), server URL, and API key.
36
+ *
37
+ * `resolveApprovedServer` plus the key, rather than one function, because
38
+ * `aai login` needs the first half and cannot have the second — it is the
39
+ * command that PUTS the key on disk. It had its own copy of the
40
+ * read → `resolveServerUrl` → `approveServer` sequence, which is security
41
+ * policy ("passing `--server` is what approves an origin"), so a change to that
42
+ * policy landed here and silently missed the one command whose whole job is to
43
+ * write a credential for the origin in question. Same shape as the slug-guard
44
+ * incident `assertValidConfigSlug` was moved down here for.
45
+ *
46
+ * The key comes from the config document already in hand — `ensureApiKey` would
47
+ * read and parse the same file a second time, on every platform command.
25
48
  */
26
49
  export declare function resolveDeployTarget(cwd: string, explicitServer?: string): Promise<{
27
50
  config: {
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import { f as validateAgentExport } from "./_utils-B8QmtFhK.mjs";
3
- import { t as buildClient } from "./client-bundler-j5c46x0G.mjs";
2
+ import { h as validateAgentExport } from "./_utils-D5JGcjiW.mjs";
3
+ import { t as buildClient } from "./client-bundler-BJgREAh6.mjs";
4
4
  import { buildWorker } from "./worker-bundler.mjs";
5
5
  import path from "node:path";
6
6
  import { pathToFileURL } from "node:url";
7
7
  import { mkdtemp, rm, writeFile } from "node:fs/promises";
8
8
  import { tmpdir } from "node:os";
9
9
  import { hash } from "node:crypto";
10
- //#region _bundler.ts
10
+ //#region src/_bundler.ts
11
11
  /**
12
12
  * Bundle an agent directory: build agent.ts into worker ESM + client files.
13
13
  *
@@ -86,14 +86,15 @@ async function evalWorkerConfig(code) {
86
86
  * distinct-build leak is accepted for the reasons documented there.
87
87
  */
88
88
  function createWorkerEvaluator() {
89
- let lastHash;
90
- let lastWorker;
89
+ let last;
91
90
  return async (code) => {
92
91
  const codeHash = hash("sha256", code);
93
- if (lastWorker && codeHash === lastHash) return lastWorker;
92
+ if (last?.hash === codeHash) return last.worker;
94
93
  const worker = await evalWorkerBundle(code);
95
- lastHash = codeHash;
96
- lastWorker = worker;
94
+ last = {
95
+ hash: codeHash,
96
+ worker
97
+ };
97
98
  return worker;
98
99
  };
99
100
  }
@@ -17,6 +17,26 @@ export declare const sharedArgs: {
17
17
  readonly description: "Output JSON (auto-detected in non-TTY)";
18
18
  };
19
19
  };
20
+ /**
21
+ * What every PLATFORM command accepts — the pair, as a group to spread.
22
+ *
23
+ * `sharedArgs` supplies the field VALUES, so each of the twelve credentialed
24
+ * commands still restated the shape (`server: sharedArgs.server, json:
25
+ * sharedArgs.json`). A flag all of them should take is then twelve edits, and
26
+ * `assertKnownArgv` refuses the flag on whichever one was missed — after
27
+ * release. `cli-workflow.ts`'s `workflowArgs` is the same pattern for its group.
28
+ */
29
+ export declare const platformArgs: {
30
+ readonly server: {
31
+ readonly type: "string";
32
+ readonly alias: "s";
33
+ readonly description: "Platform server URL";
34
+ };
35
+ readonly json: {
36
+ readonly type: "boolean";
37
+ readonly description: "Output JSON (auto-detected in non-TTY)";
38
+ };
39
+ };
20
40
  /**
21
41
  * Flags in `rawArgs` that `argsDef` doesn't declare, in the form the user
22
42
  * typed them.
@@ -44,15 +64,34 @@ type AnyCommandDef = CommandDef<ArgsDef>;
44
64
  * the narrowing.
45
65
  */
46
66
  export declare function commandPath<T extends ArgsDef>(cmd: CommandDef<T>, parent?: CommandDef<T>): string;
67
+ /** What {@link resolveArgv} learned by walking the command tree once. */
68
+ export type ArgvSelection = {
69
+ /** `["aai", "secret", "put"]` — the path walked, for a `--help` sentence. */
70
+ named: string[];
71
+ /**
72
+ * The first non-flag token that named no subcommand where one was expected,
73
+ * i.e. a mistyped command. `undefined` when the walk reached a real command.
74
+ */
75
+ unknownCommand?: string;
76
+ /** Args declared by the command the argv selected. */
77
+ argsDef: ArgsDef;
78
+ /** argv from the first token that is not a subcommand — flags and positionals. */
79
+ rest: string[];
80
+ };
47
81
  /**
48
- * Unknown flags in `argv` for whichever (possibly nested) subcommand it
49
- * selects `[]` when everything is declared.
82
+ * Walk the real command tree for `argv` and report everything the pre-parse
83
+ * guards in `cli.ts` need: which command it selects, what that command
84
+ * declares, and whether a token mistyped a subcommand.
50
85
  *
51
- * Walks the real command tree rather than re-listing flags, so this cannot
52
- * drift from what the commands accept. An unknown SUBCOMMAND is not reported:
53
- * citty already answers that with usage text and a non-zero exit.
86
+ * ONE walk, because there used to be two this one and a copy in `cli.ts`,
87
+ * each with its own `Resolvable` narrowing, whose only difference was the
88
+ * terminal action. The copies also had an ORDERING dependency nothing
89
+ * enforced: the flag guard reports nothing for a mistyped subcommand (the
90
+ * flags would be matched against the wrong command's definition), which is
91
+ * only safe because the command guard ran first. Answering both from one
92
+ * result removes the ordering rather than documenting it.
54
93
  */
55
- export declare function unknownFlagsForArgv(root: AnyCommandDef, argv: string[]): Promise<string[]>;
94
+ export declare function resolveArgv(root: AnyCommandDef, argv: string[]): Promise<ArgvSelection>;
56
95
  /** Shared command setup: resolve cwd, optionally require agent.ts. */
57
96
  export declare function setup(opts?: {
58
97
  agent?: boolean;
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
- import { t as CliError } from "./_output-CKkmWs7i.mjs";
3
- import { c as isEexist, l as readJson, o as errorMessage, p as writeJson } from "./_utils-B8QmtFhK.mjs";
2
+ import { t as CliError } from "./_output-DBP9Op_d.mjs";
3
+ import { d as readJson, g as writeJson, s as errorMessage, u as isEexist } from "./_utils-D5JGcjiW.mjs";
4
4
  import { mkdtempSync } from "node:fs";
5
5
  import path from "node:path";
6
6
  import fs from "node:fs/promises";
@@ -8,7 +8,7 @@ import { sleep } from "@alexkroman1/aai/internal";
8
8
  import { tmpdir } from "node:os";
9
9
  import envPaths from "env-paths";
10
10
  import { z } from "zod";
11
- //#region _config.ts
11
+ //#region src/_config.ts
12
12
  /**
13
13
  * `.aai/project.json` lives in the working tree, so everything in it is
14
14
  * untrusted input — a cloned repo can supply any value.
@@ -230,6 +230,8 @@ async function readGlobalConfig(configDir) {
230
230
  async function writeGlobalConfig(configDir, data) {
231
231
  await writeJson(path.join(configDir, "config.json"), data, { mode: 384 });
232
232
  }
233
+ /** Local-session remedies FIRST — the two that need no account at all. */
234
+ const LOCAL_SESSION_HINT = "Any ONE of these is enough, and the first two need no aai account:\n 1. Put ASSEMBLYAI_API_KEY=<your key> in this project's .env — the same file `aai publish` uploads.\n 2. Or export it in your shell: export ASSEMBLYAI_API_KEY=<your key>\n 3. Or run `aai login`, and `aai dev` will use your account's key.\nGet a key at https://www.assemblyai.com/dashboard.";
233
235
  /**
234
236
  * The credential every platform command runs on.
235
237
  *
@@ -251,9 +253,10 @@ async function writeGlobalConfig(configDir, data) {
251
253
  * pointing `AAI_CONFIG_DIR` at a config dir holding a key from an interactive
252
254
  * `aai login`.
253
255
  */
254
- async function ensureApiKey(configDir) {
256
+ async function ensureApiKey(configDir, use = "platform") {
255
257
  const config = await readGlobalConfig(configDir ?? getConfigDir());
256
258
  if (config.apiKey) return config.apiKey;
259
+ if (use === "local-session") throw new CliError("missing_assemblyai_key", "ASSEMBLYAI_API_KEY is not set, and this agent's pipeline needs it to start a session.", LOCAL_SESSION_HINT);
257
260
  throw new CliError("not_logged_in", "You're not logged in.", "Run `aai login` to link your account. Non-interactive setups can point AAI_CONFIG_DIR at a config dir holding a logged-in key.");
258
261
  }
259
262
  //#endregion
package/dist/_config.d.ts CHANGED
@@ -73,6 +73,30 @@ export declare function updateGlobalConfig(update: (current: GlobalConfig) => Gl
73
73
  export declare function approveServer(url: string, configDir?: string): Promise<void>;
74
74
  export declare function readGlobalConfig(configDir?: string): Promise<GlobalConfig>;
75
75
  export declare function writeGlobalConfig(configDir: string, data: GlobalConfig): Promise<void>;
76
+ /**
77
+ * Why the caller wants the key, which is what the FAILURE has to answer.
78
+ *
79
+ * One source, two questions. `"platform"` asks "who is this CLI logged in
80
+ * as?" — for `publish`/`push`/`logs`/`secret` a platform account genuinely IS
81
+ * the requirement, so the refusal is account-shaped and points at
82
+ * `aai login`. `"local-session"` is `aai dev` asking for a PROVIDER
83
+ * credential that the logged-in account merely happens to be able to supply:
84
+ * `ASSEMBLYAI_API_KEY` in `.env`, or exported in the shell, starts the same
85
+ * server with no account anywhere (see `resolveAgentEnv` in `_dev-server.ts`,
86
+ * which reaches here only when neither carries one).
87
+ *
88
+ * Answering the second question with the first's sentence is the defect this
89
+ * parameter exists to fix: `not_logged_in` names only account remedies
90
+ * (`aai login`, `AAI_CONFIG_DIR`), so `aai dev` read as "local development is
91
+ * gated on a cloud account" — and most of a twenty-persona DX audit believed
92
+ * it and abandoned the documented primary feedback loop, which was never
93
+ * gated at all.
94
+ *
95
+ * A PARAMETER rather than a second exported function because the source is
96
+ * shared: both answers must keep reading the one slot `aai login` writes, and
97
+ * a sibling function is how the two come to disagree about where a key lives.
98
+ */
99
+ export type ApiKeyUse = "platform" | "local-session";
76
100
  /**
77
101
  * The credential every platform command runs on.
78
102
  *
@@ -94,5 +118,5 @@ export declare function writeGlobalConfig(configDir: string, data: GlobalConfig)
94
118
  * pointing `AAI_CONFIG_DIR` at a config dir holding a key from an interactive
95
119
  * `aai login`.
96
120
  */
97
- export declare function ensureApiKey(configDir?: string): Promise<string>;
121
+ export declare function ensureApiKey(configDir?: string, use?: ApiKeyUse): Promise<string>;
98
122
  export {};
@@ -17,7 +17,7 @@
17
17
  */
18
18
  import type { Logger } from "@alexkroman1/aai-runtime";
19
19
  /**
20
- * The env handed to `createServer` for host-mode connections: provider
20
+ * The env handed to `createRuntimeServer` for host-mode connections: provider
21
21
  * credentials plus the `AAI_ALLOW_HOST` gate read straight from the shell
22
22
  * (it is a control variable, not something an agent declares in `.env`).
23
23
  */
@@ -1,27 +1,27 @@
1
1
  #!/usr/bin/env node
2
- import { i as outputSilenced, r as notify } from "./_ui-u7T4YooX.mjs";
3
- import { i as errorCode, o as errorMessage$1 } from "./_utils-B8QmtFhK.mjs";
4
- import { n as fallbackHtmlPlugin } from "./client-bundler-j5c46x0G.mjs";
5
- import { t as DEDUPED_PEERS } from "./_vite-env-D9Qj6KPX.mjs";
2
+ import { i as outputSilenced, r as notify } from "./_ui-DCt4qZrk.mjs";
3
+ import { a as errorCode, s as errorMessage$1 } from "./_utils-D5JGcjiW.mjs";
4
+ import { n as fallbackHtmlPlugin } from "./client-bundler-BJgREAh6.mjs";
5
+ import { t as DEDUPED_PEERS } from "./_vite-env-kejF0p2L.mjs";
6
6
  import { buildWorker } from "./worker-bundler.mjs";
7
7
  import { typecheckProject } from "./typecheck.mjs";
8
- import { n as ensureApiKey } from "./_config-CmJOFsAP.mjs";
9
- import { n as createWorkerEvaluator } from "./_bundler-C31rlcYz.mjs";
10
- import { t as resolveServerEnv } from "./_server-common-6e0QI4mq.mjs";
8
+ import { n as ensureApiKey } from "./_config-DYzC6WMD.mjs";
9
+ import { n as createWorkerEvaluator } from "./_bundler-DolUCMxu.mjs";
10
+ import { t as resolveServerEnv } from "./_server-common-vILJp3it.mjs";
11
11
  import { existsSync, statSync } from "node:fs";
12
12
  import path from "node:path";
13
- import { omitUndefined } from "@alexkroman1/aai/utils";
13
+ import { omitUndefined, plural } from "@alexkroman1/aai/utils";
14
14
  import { createCoalescingRunner, requestPath, sleep } from "@alexkroman1/aai/internal";
15
15
  import { agentConfigWarnings } from "@alexkroman1/aai/manifest";
16
- import { DEFAULT_LISTEN_HOST, WORKFLOW_API_PREFIX, createRuntime, createServer, ensureSessionStateSchema, ensureWorkflowJournalSchema, requiredProviderEnvVars, withHostCredentialFallback } from "@alexkroman1/aai-runtime";
17
- import { WORKFLOW_DATA_DIR_ENV, consoleLogger, createMemoryJournal, handleWorkflowRequest, publishStepEnv } from "@alexkroman1/aai-runtime/internal";
16
+ import { DEFAULT_LISTEN_HOST, WORKFLOW_API_PREFIX, createRuntime, createRuntimeServer, ensureSessionStateSchema, ensureWorkflowJournalSchema, requiredProviderEnvVars, withHostCredentialFallback } from "@alexkroman1/aai-runtime";
17
+ import { WORKFLOW_DATA_DIR_ENV, consoleLogger, createMemoryJournal, handleWorkflowRequest, isPathInside, publishStepEnv } from "@alexkroman1/aai-runtime/internal";
18
18
  import { defaultClientDir } from "@alexkroman1/aai-ui/client-dir";
19
19
  import { watch } from "chokidar";
20
20
  import getPort, { portNumbers } from "get-port";
21
21
  import pDebounce from "p-debounce";
22
- //#region _dev-env.ts
22
+ //#region src/_dev-env.ts
23
23
  /**
24
- * The env handed to `createServer` for host-mode connections: provider
24
+ * The env handed to `createRuntimeServer` for host-mode connections: provider
25
25
  * credentials plus the `AAI_ALLOW_HOST` gate read straight from the shell
26
26
  * (it is a control variable, not something an agent declares in `.env`).
27
27
  */
@@ -97,7 +97,7 @@ function createDevLogger(silenced) {
97
97
  };
98
98
  }
99
99
  //#endregion
100
- //#region _dev-restart.ts
100
+ //#region src/_dev-restart.ts
101
101
  /**
102
102
  * Restart supervision for `aai dev`.
103
103
  *
@@ -230,7 +230,7 @@ function createRestartSupervisor(ops) {
230
230
  };
231
231
  }
232
232
  //#endregion
233
- //#region _dev-typecheck.ts
233
+ //#region src/_dev-typecheck.ts
234
234
  /**
235
235
  * The background typecheck under `aai dev`.
236
236
  *
@@ -276,7 +276,7 @@ function createDevTypecheck(cwd, report = notify) {
276
276
  } };
277
277
  }
278
278
  //#endregion
279
- //#region _dev-vite-config.ts
279
+ //#region src/_dev-vite-config.ts
280
280
  /**
281
281
  * The Vite dev server's config for a project with a `client.tsx`.
282
282
  *
@@ -338,7 +338,7 @@ function createDevTypecheck(cwd, report = notify) {
338
338
  * send `..` where a browser would normalize it — and a malformed percent-escape
339
339
  * is left to the API, which is where a path we cannot resolve belongs.
340
340
  */
341
- function workflowPathServedByVite(root, rawUrl) {
341
+ function workflowPathServedByVite(base, rawUrl) {
342
342
  if (rawUrl === void 0) return void 0;
343
343
  let decoded;
344
344
  try {
@@ -346,9 +346,8 @@ function workflowPathServedByVite(root, rawUrl) {
346
346
  } catch {
347
347
  return;
348
348
  }
349
- const base = path.resolve(root);
350
349
  const resolved = path.resolve(base, `.${decoded}`);
351
- if (resolved !== base && !resolved.startsWith(base + path.sep)) return void 0;
350
+ if (!isPathInside(base, resolved)) return void 0;
352
351
  try {
353
352
  if (!statSync(resolved).isFile()) return void 0;
354
353
  } catch {
@@ -362,13 +361,13 @@ function workflowPathServedByVite(root, rawUrl) {
362
361
  * with a `client.tsx` serves a page whose WebSocket never connects.
363
362
  *
364
363
  * **This table is the whole agent API as the browser can see it**, which is
365
- * the thing to hold in mind before adding a route to `createServer`. Vite owns
364
+ * the thing to hold in mind before adding a route to `createRuntimeServer`. Vite owns
366
365
  * the port the user is told to open and answers everything not listed here
367
366
  * itself — with a bare 404 carrying none of the agent server's headers, so the
368
367
  * failure looks like a missing route rather than a missing proxy entry.
369
368
  *
370
369
  * `/workflows` is why that matters beyond voice. A WORKFLOW APP
371
- * (`workflowApp()`) has no session and no socket: `page()` mounts a
370
+ * (`workflowApp()`) has no session and no socket: `mountPage()` mounts a
372
371
  * form and every single thing it does — listing workflows, starting a run,
373
372
  * polling it, streaming its events — is a same-origin `fetch` under that
374
373
  * prefix. Unproxied, the two workflow-app templates were dead on arrival under
@@ -396,7 +395,7 @@ function workflowPathServedByVite(root, rawUrl) {
396
395
  * `http://localhost:<port>` either way — a caller that resolves IPv4-only, or
397
396
  * dials the literal, gets a connection refused against a server that is up.
398
397
  *
399
- * The two halves of `aai dev` also disagreed: `createServer` binds
398
+ * The two halves of `aai dev` also disagreed: `createRuntimeServer` binds
400
399
  * {@link DEFAULT_LISTEN_HOST} explicitly, Vite took its own default, and only a
401
400
  * set `AAI_DEV_HOST` brought them back together. Taking the same constant is
402
401
  * what makes them agree by construction rather than by two matching literals.
@@ -444,6 +443,7 @@ function workflowPathServedByVite(root, rawUrl) {
444
443
  */
445
444
  function viteDevConfig(cwd, vitePort, backendPort) {
446
445
  const target = `http://127.0.0.1:${backendPort}`;
446
+ const viteRoot = path.resolve(cwd);
447
447
  return {
448
448
  root: cwd,
449
449
  plugins: [fallbackHtmlPlugin(cwd)],
@@ -461,14 +461,14 @@ function viteDevConfig(cwd, vitePort, backendPort) {
461
461
  },
462
462
  [WORKFLOW_API_PREFIX]: {
463
463
  target,
464
- bypass: (req) => workflowPathServedByVite(cwd, req.url)
464
+ bypass: (req) => workflowPathServedByVite(viteRoot, req.url)
465
465
  }
466
466
  }
467
467
  }
468
468
  };
469
469
  }
470
470
  //#endregion
471
- //#region _dev-server.ts
471
+ //#region src/_dev-server.ts
472
472
  /**
473
473
  * Dev server for directory-based agents.
474
474
  *
@@ -491,23 +491,21 @@ function viteDevConfig(cwd, vitePort, backendPort) {
491
491
  * can't mask one that would be missing both here and after deploy.
492
492
  */
493
493
  function agentEnvWarnings(agentDef, env, shellEnv = process.env) {
494
- const s = (names) => names.length > 1 ? "s" : "";
495
- const them = (names) => names.length > 1 ? "them" : "it";
496
494
  const required = requiredProviderEnvVars(agentDef);
497
495
  const warnings = [];
498
496
  const missing = required.filter((name) => !(env[name] || shellEnv[name]));
499
- if (missing.length > 0) warnings.push(`Missing provider credential${s(missing)}: ${missing.join(", ")}. Set ${them(missing)} in .env or the environment.`);
497
+ if (missing.length > 0) warnings.push(`Missing provider ${plural(missing.length, "credential")}: ${missing.join(", ")}. Set ${plural(missing.length, "it", "them")} in .env or the environment.`);
500
498
  const shellOnly = required.filter((name) => !env[name] && shellEnv[name]);
501
- if (shellOnly.length > 0) warnings.push(`${shellOnly.join(", ")} resolved from your shell, not .env — deployed agents won't have ${them(shellOnly)}. Declare ${them(shellOnly)} in .env before \`aai publish\`.`);
499
+ if (shellOnly.length > 0) warnings.push(`${shellOnly.join(", ")} resolved from your shell, not .env — deployed agents won't have ${plural(shellOnly.length, "it", "them")}. Declare ${plural(shellOnly.length, "it", "them")} in .env before \`aai publish\`.`);
502
500
  const declared = (agentDef.requiredEnv ?? []).filter((name) => !env[name]);
503
- if (declared.length > 0) warnings.push(`Missing requiredEnv key${s(declared)} declared by the agent: ${declared.join(", ")}. Set ${them(declared)} in .env — ctx.env will not contain ${them(declared)} otherwise.`);
501
+ if (declared.length > 0) warnings.push(`Missing requiredEnv ${plural(declared.length, "key")} declared by the agent: ${declared.join(", ")}. Set ${plural(declared.length, "it", "them")} in .env — ctx.env will not contain ${plural(declared.length, "it", "them")} otherwise.`);
504
502
  return warnings;
505
503
  }
506
504
  async function resolveAgentEnv(root, agentDef) {
507
505
  const env = await resolveServerEnv(root);
508
506
  const required = requiredProviderEnvVars(agentDef);
509
507
  const hasShellKey = Boolean(process.env.ASSEMBLYAI_API_KEY);
510
- if (required.includes("ASSEMBLYAI_API_KEY") && !env.ASSEMBLYAI_API_KEY && !hasShellKey) env.ASSEMBLYAI_API_KEY = await ensureApiKey();
508
+ if (required.includes("ASSEMBLYAI_API_KEY") && !env.ASSEMBLYAI_API_KEY && !hasShellKey) env.ASSEMBLYAI_API_KEY = await ensureApiKey(void 0, "local-session");
511
509
  for (const warning of agentEnvWarnings(agentDef, env)) notify("warn", warning);
512
510
  for (const warning of agentConfigWarnings(agentDef)) notify("warn", warning);
513
511
  return env;
@@ -634,7 +632,7 @@ async function startDevServer(opts) {
634
632
  journal,
635
633
  publicUrl: process.env.PUBLIC_URL?.trim() || `http://localhost:${backendPort}`
636
634
  });
637
- return createServer({
635
+ return createRuntimeServer({
638
636
  runtime,
639
637
  name: agentDef.name,
640
638
  env: hostModeEnv(providerEnv),
@@ -12,13 +12,13 @@
12
12
  * with a `client.tsx` serves a page whose WebSocket never connects.
13
13
  *
14
14
  * **This table is the whole agent API as the browser can see it**, which is
15
- * the thing to hold in mind before adding a route to `createServer`. Vite owns
15
+ * the thing to hold in mind before adding a route to `createRuntimeServer`. Vite owns
16
16
  * the port the user is told to open and answers everything not listed here
17
17
  * itself — with a bare 404 carrying none of the agent server's headers, so the
18
18
  * failure looks like a missing route rather than a missing proxy entry.
19
19
  *
20
20
  * `/workflows` is why that matters beyond voice. A WORKFLOW APP
21
- * (`workflowApp()`) has no session and no socket: `page()` mounts a
21
+ * (`workflowApp()`) has no session and no socket: `mountPage()` mounts a
22
22
  * form and every single thing it does — listing workflows, starting a run,
23
23
  * polling it, streaming its events — is a same-origin `fetch` under that
24
24
  * prefix. Unproxied, the two workflow-app templates were dead on arrival under
@@ -46,7 +46,7 @@
46
46
  * `http://localhost:<port>` either way — a caller that resolves IPv4-only, or
47
47
  * dials the literal, gets a connection refused against a server that is up.
48
48
  *
49
- * The two halves of `aai dev` also disagreed: `createServer` binds
49
+ * The two halves of `aai dev` also disagreed: `createRuntimeServer` binds
50
50
  * {@link DEFAULT_LISTEN_HOST} explicitly, Vite took its own default, and only a
51
51
  * set `AAI_DEV_HOST` brought them back together. Taking the same constant is
52
52
  * what makes them agree by construction rather than by two matching literals.
@@ -5,22 +5,30 @@
5
5
  */
6
6
  import { type ChildProcess } from "node:child_process";
7
7
  import type { MockRegistry } from "./_mock-registry.ts";
8
- export declare const dir: string;
8
+ export declare const packageDir: string;
9
9
  export declare const packagesDir: string;
10
10
  export declare const pm: "pnpm" | "npm" | "yarn";
11
11
  export declare function aaiEnv(): NodeJS.ProcessEnv;
12
12
  export declare function aai(aaiBin: string, args: string[], cwd: string, timeoutMs?: number): void;
13
13
  /**
14
- * {@link aai}, but CAPTURING for the cases whose subject is what the CLI
15
- * SAID rather than that it exited 0.
14
+ * {@link aai}, but CAPTURING and expecting the CLI to FAIL for the cases
15
+ * whose subject is what it SAID on its way to a non-zero exit.
16
16
  *
17
- * Separate rather than a flag, because `stdio: "inherit"` is load-bearing for
18
- * every other call: an e2e failure's only diagnosis trail is the child's output
19
- * in the run log, and capturing it by default would take that away.
17
+ * Capturing is separate from {@link aai} rather than a flag on it, because
18
+ * `stdio: "inherit"` is load-bearing for every other call: an e2e failure's
19
+ * only diagnosis trail is the child's output in the run log, and capturing it
20
+ * by default would take that away.
21
+ *
22
+ * The exit code is asserted HERE rather than left to the caller. `execaSync`
23
+ * throws on a non-zero exit, so the capturing helper this replaced could only
24
+ * be pointed at commands that succeed — and a `try`/`catch` around it would
25
+ * pass just as happily on a zero exit, which is the bug the one caller exists
26
+ * to catch (`aai test` named its unrun specs and exited 0 anyway).
20
27
  */
21
- export declare function aaiOutput(aaiBin: string, args: string[], cwd: string, timeoutMs?: number): {
28
+ export declare function aaiOutputFailing(aaiBin: string, args: string[], cwd: string, timeoutMs?: number): {
22
29
  stdout: string;
23
30
  stderr: string;
31
+ exitCode: number;
24
32
  };
25
33
  /**
26
34
  * Build the CLI and return the path to the built binary.