@alexkroman1/aai-cli 6.5.0 → 6.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{_agent-vGW5SBnX.mjs → _agent-DpH2pBJd.mjs} +1 -5
- package/dist/{_bundler-BapCUUJN.mjs → _bundler-C2BDwU7r.mjs} +5 -7
- package/dist/{_dev-server-DQ1t9sbw.mjs → _dev-server-LLLWnFBs.mjs} +3 -3
- package/dist/_e2e-test-utils.d.ts +17 -17
- package/dist/{_init-CpISqoR8.mjs → _init-C57bWAQ8.mjs} +2 -2
- package/dist/{_slug-api-D2heILuC.mjs → _slug-api-BxrsJXVI.mjs} +3 -3
- package/dist/_slug-api.d.ts +1 -1
- package/dist/{_api-client-LgLksMhN.mjs → _studio-U3jhKlA3.mjs} +105 -2
- package/dist/_studio.d.ts +11 -0
- package/dist/{_templates-iDGjGiPf.mjs → _templates-Dxb_P2Wz.mjs} +1 -1
- package/dist/bin.d.mts +2 -0
- package/dist/{build-BO1Ni6oJ.mjs → build-Dfza2pRI.mjs} +2 -2
- package/dist/cli.mjs +43 -42
- package/dist/{client-bundler-B8Q9F8gJ.mjs → client-bundler-BEIqgOtd.mjs} +2 -2
- package/dist/client-bundler.mjs +1 -1
- package/dist/{delete-4I0uNR4a.mjs → delete-vbpjGzqs.mjs} +3 -3
- package/dist/{deploy-DJ3HRcia.mjs → deploy-B8lubiRT.mjs} +3 -4
- package/dist/{dev-C6SWaAZP.mjs → dev-Uq5ujP8a.mjs} +1 -1
- package/dist/{eject-Zrzk5KV3.mjs → eject-31gjtaHF.mjs} +2 -2
- package/dist/{init-BTRGiPQr.mjs → init-l6xfU4xX.mjs} +3 -3
- package/dist/{login-k0Z3VQu9.mjs → login-C71-qz8F.mjs} +1 -1
- package/dist/scaffold/package.json +3 -3
- package/dist/{secret-DzSQx1Ds.mjs → secret-BuMuFR4B.mjs} +2 -2
- package/dist/{storage-C-Do0mIA.mjs → storage-DzRZ-eCw.mjs} +2 -2
- package/dist/{studio-BGVmCA2G.mjs → studio-BCNUpDgP.mjs} +4 -5
- package/dist/templates/retail/resolve.ts +16 -0
- package/dist/templates/retail/store.ts +20 -0
- package/dist/templates/retail/tools/cancel_pending_order.ts +2 -5
- package/dist/templates/retail/tools/exchange_delivered_order_items.ts +2 -5
- package/dist/templates/retail/tools/get_order_details.ts +4 -6
- package/dist/templates/retail/tools/get_user_details.ts +2 -7
- package/dist/templates/retail/tools/modify_pending_order_address.ts +2 -5
- package/dist/templates/retail/tools/modify_pending_order_items.ts +2 -5
- package/dist/templates/retail/tools/modify_pending_order_payment.ts +2 -5
- package/dist/templates/retail/tools/modify_user_address.ts +2 -7
- package/dist/templates/retail/tools/return_delivered_order_items.ts +2 -5
- package/dist/templates/transcription-workflow/agent.test.ts +2 -3
- package/dist/templates/transcription-workflow/workflows/batch.ts +2 -13
- package/dist/templates/transcription-workflow/workflows/stream.ts +1 -10
- package/dist/templates/transcription-workflow/workflows/sync-api.ts +8 -2
- package/dist/templates/transcription-workflow/workflows/transcribe.ts +8 -2
- package/dist/{test-B6ZBxSpk.mjs → test-9kPKJI-w.mjs} +1 -3
- package/dist/typecheck.mjs +4 -5
- package/dist/{worker-bundler-CIdDhZ0c.mjs → worker-bundler-CGD4r8Kc.mjs} +25 -11
- package/dist/worker-bundler.mjs +1 -1
- package/dist/{workflow-B-O97AqI.mjs → workflow-CFpxOFfQ.mjs} +1 -1
- package/package.json +4 -4
- package/dist/_studio-zAJycZ8j.mjs +0 -94
|
@@ -12,7 +12,7 @@ import { styleText } from "node:util";
|
|
|
12
12
|
async function executeDev(opts) {
|
|
13
13
|
const port = parsePort(opts.port);
|
|
14
14
|
const agentName = path.basename(path.resolve(opts.cwd));
|
|
15
|
-
const { startDevServer } = await import("./_dev-server-
|
|
15
|
+
const { startDevServer } = await import("./_dev-server-LLLWnFBs.mjs");
|
|
16
16
|
let cleanup;
|
|
17
17
|
let shuttingDown = false;
|
|
18
18
|
const onSignal = () => {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { a as ok, t as CliError } from "./_output-CKkmWs7i.mjs";
|
|
3
3
|
import { n as log } from "./_ui-u7T4YooX.mjs";
|
|
4
4
|
import { l as readJson, o as errorMessage, p as writeJson, s as fileExists } from "./_utils-B8QmtFhK.mjs";
|
|
5
|
-
import { scaffoldDir } from "./_templates-
|
|
5
|
+
import { scaffoldDir } from "./_templates-Dxb_P2Wz.mjs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import fs from "node:fs/promises";
|
|
8
8
|
//#region eject.ts
|
|
@@ -69,7 +69,7 @@ async function ensureStartScript(cwd) {
|
|
|
69
69
|
const existing = manifest.scripts?.start;
|
|
70
70
|
if (existing === START_SCRIPT && manifest.scripts?.prestart === "aai build --skip-tests") return false;
|
|
71
71
|
if (existing !== void 0 && existing !== START_SCRIPT) {
|
|
72
|
-
log.warn(`Kept your existing "start" script (${existing}) — run \`${PRESTART_SCRIPT}\` then
|
|
72
|
+
log.warn(`Kept your existing "start" script (${existing}) — run \`${PRESTART_SCRIPT}\` then \`${START_SCRIPT}\`.`);
|
|
73
73
|
return false;
|
|
74
74
|
}
|
|
75
75
|
manifest.scripts = {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { a as ok } from "./_output-CKkmWs7i.mjs";
|
|
3
3
|
import { n as log, s as unwrapCancel } from "./_ui-u7T4YooX.mjs";
|
|
4
4
|
import { d as resolveCwd, l as readJson, o as errorMessage, s as fileExists, t as AGENT_ENTRY } from "./_utils-B8QmtFhK.mjs";
|
|
5
|
-
import { r as isDevMode, t as getMonorepoRoot } from "./_agent-
|
|
5
|
+
import { r as isDevMode, t as getMonorepoRoot } from "./_agent-DpH2pBJd.mjs";
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import { styleText } from "node:util";
|
|
8
8
|
import * as p from "@clack/prompts";
|
|
@@ -105,7 +105,7 @@ function collectWarnings() {
|
|
|
105
105
|
}
|
|
106
106
|
/** Publish after init and return deploy metadata if successful. */
|
|
107
107
|
async function tryPublish(cwd, server, warn) {
|
|
108
|
-
const { executePublish } = await import("./studio-
|
|
108
|
+
const { executePublish } = await import("./studio-BCNUpDgP.mjs");
|
|
109
109
|
try {
|
|
110
110
|
const result = await executePublish({
|
|
111
111
|
cwd,
|
|
@@ -126,7 +126,7 @@ async function tryPublish(cwd, server, warn) {
|
|
|
126
126
|
}
|
|
127
127
|
/** Scaffold the project, optionally showing a spinner. */
|
|
128
128
|
async function scaffoldProject(dir, cwd, template, silent) {
|
|
129
|
-
const { runInit } = await import("./_init-
|
|
129
|
+
const { runInit } = await import("./_init-C57bWAQ8.mjs");
|
|
130
130
|
await withSpinner(silent, {
|
|
131
131
|
start: `Creating ${dir}`,
|
|
132
132
|
done: "Project created",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { a as ok, t as CliError } from "./_output-CKkmWs7i.mjs";
|
|
3
3
|
import { n as log } from "./_ui-u7T4YooX.mjs";
|
|
4
4
|
import { o as updateGlobalConfig, r as readGlobalConfig, t as approveServer } from "./_config-D_s09e7g.mjs";
|
|
5
|
-
import { o as resolveServerUrl } from "./_agent-
|
|
5
|
+
import { o as resolveServerUrl } from "./_agent-DpH2pBJd.mjs";
|
|
6
6
|
import { linkConfirmationCode } from "@alexkroman1/aai/utils";
|
|
7
7
|
import { spawn } from "node:child_process";
|
|
8
8
|
import { sleep } from "@alexkroman1/aai/internal";
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"publish:agent": "aai publish"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@alexkroman1/aai": "^6.5.
|
|
17
|
-
"@alexkroman1/aai-ui": "^6.5.
|
|
16
|
+
"@alexkroman1/aai": "^6.5.1",
|
|
17
|
+
"@alexkroman1/aai-ui": "^6.5.1",
|
|
18
18
|
"@workflow/world-postgres": "4.3.3",
|
|
19
19
|
"react": "^19.2.8",
|
|
20
20
|
"react-dom": "^19.2.8",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"zod": "^4.4.3"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@alexkroman1/aai-cli": "^6.5.
|
|
26
|
+
"@alexkroman1/aai-cli": "^6.5.1",
|
|
27
27
|
"@tailwindcss/vite": "^4.3.3",
|
|
28
28
|
"@types/node": "^26.2.0",
|
|
29
29
|
"@types/react": "^19.2.18",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { a as ok, n as fail } from "./_output-CKkmWs7i.mjs";
|
|
3
3
|
import { n as log, s as unwrapCancel } from "./_ui-u7T4YooX.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { t as secretRequest } from "./_slug-api-
|
|
4
|
+
import { f as checkedResponse, p as isStringArray } from "./_studio-U3jhKlA3.mjs";
|
|
5
|
+
import { t as secretRequest } from "./_slug-api-BxrsJXVI.mjs";
|
|
6
6
|
import { isRecord } from "@alexkroman1/aai/utils";
|
|
7
7
|
import * as p from "@clack/prompts";
|
|
8
8
|
import { text } from "node:stream/consumers";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { a as ok, n as fail } from "./_output-CKkmWs7i.mjs";
|
|
3
3
|
import { n as log } from "./_ui-u7T4YooX.mjs";
|
|
4
|
-
import {
|
|
5
|
-
import { n as slugRequest } from "./_slug-api-
|
|
4
|
+
import { f as checkedResponse } from "./_studio-U3jhKlA3.mjs";
|
|
5
|
+
import { n as slugRequest } from "./_slug-api-BxrsJXVI.mjs";
|
|
6
6
|
import { isRecord } from "@alexkroman1/aai/utils";
|
|
7
7
|
import * as p from "@clack/prompts";
|
|
8
8
|
//#region storage.ts
|
|
@@ -3,10 +3,9 @@ import { a as ok, t as CliError } from "./_output-CKkmWs7i.mjs";
|
|
|
3
3
|
import { n as log, t as fmtUrl } from "./_ui-u7T4YooX.mjs";
|
|
4
4
|
import { s as updateProjectConfig } from "./_config-D_s09e7g.mjs";
|
|
5
5
|
import { t as resolveServerEnv } from "./_server-common-6e0QI4mq.mjs";
|
|
6
|
-
import { a as resolveDeployTarget } from "./_agent-
|
|
7
|
-
import { layerScaffold } from "./_templates-
|
|
8
|
-
import {
|
|
9
|
-
import { a as publishStudioProject, i as projectNameFromDir, n as fetchStudioProject, o as pushStudioSource, r as listStudioProjects, s as studioProjectUrl, t as collectSourceFiles } from "./_studio-zAJycZ8j.mjs";
|
|
6
|
+
import { a as resolveDeployTarget } from "./_agent-DpH2pBJd.mjs";
|
|
7
|
+
import { layerScaffold } from "./_templates-Dxb_P2Wz.mjs";
|
|
8
|
+
import { a as publishStudioProject, c as studioProjectUrl, f as checkedResponse, i as projectNameFromDir, n as fetchStudioProject, o as pushStudioSource, r as listStudioProjects, s as studioProjectApiUrl, t as collectSourceFiles, u as apiRequest } from "./_studio-U3jhKlA3.mjs";
|
|
10
9
|
import path from "node:path";
|
|
11
10
|
import { isRecord } from "@alexkroman1/aai/utils";
|
|
12
11
|
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
@@ -148,7 +147,7 @@ async function syncEnvSecrets(cwd, serverUrl, apiKey, project) {
|
|
|
148
147
|
const env = await resolveServerEnv(cwd);
|
|
149
148
|
const names = Object.keys(env);
|
|
150
149
|
if (names.length === 0) return [];
|
|
151
|
-
await apiRequest(`${serverUrl
|
|
150
|
+
await apiRequest(`${studioProjectApiUrl(serverUrl, project)}/secret`, {
|
|
152
151
|
apiKey,
|
|
153
152
|
action: "secret",
|
|
154
153
|
method: "PUT",
|
|
@@ -10,9 +10,25 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { isToolFailure, resolveOne, spokenDigits, type ToolFailure } from "@alexkroman1/aai";
|
|
13
|
+
import { z } from "zod";
|
|
13
14
|
import type { Order, OrderStatus, Product, RetailState } from "./shared.ts";
|
|
14
15
|
import { authenticatedUser } from "./store.ts";
|
|
15
16
|
|
|
17
|
+
/**
|
|
18
|
+
* The `order_id` parameter, for the seven tools that take one.
|
|
19
|
+
*
|
|
20
|
+
* Same reasoning as `AddressFields` in `address.ts`, and here the stakes are the
|
|
21
|
+
* DESCRIPTION: it is the sentence that tells the model a spoken reference is
|
|
22
|
+
* acceptable, so a copy that lost the second half would quietly make one tool
|
|
23
|
+
* demand a literal id while its six siblings accept "the last one". It belongs in
|
|
24
|
+
* this module because "what an order id looks like when a caller reads it aloud"
|
|
25
|
+
* is exactly what {@link resolveOrder} implements.
|
|
26
|
+
*/
|
|
27
|
+
export const OrderIdField = z
|
|
28
|
+
.string()
|
|
29
|
+
.max(120)
|
|
30
|
+
.describe("Order id such as '#W0000000', or a spoken reference to one of their orders");
|
|
31
|
+
|
|
16
32
|
/** `#W5866402` from anything STT plausibly produces for it. */
|
|
17
33
|
export function normalizeOrderId(spoken: string): string {
|
|
18
34
|
const compact = spoken.toUpperCase().replace(/[^A-Z0-9]/g, "");
|
|
@@ -158,6 +158,26 @@ export function requireOwnOrder(state: RetailState, orderId: string): Order | To
|
|
|
158
158
|
return order;
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
/**
|
|
162
|
+
* The authenticated customer, when `userId` names them.
|
|
163
|
+
*
|
|
164
|
+
* The wrapper's auth gate says a customer is on the call; a tool whose schema
|
|
165
|
+
* takes a `user_id` also needs to know the caller named THAT customer, and only
|
|
166
|
+
* one message is right for the second. Two tools had the pair of guards written
|
|
167
|
+
* out, so the message was maintained in two places — the same reason
|
|
168
|
+
* {@link requireOwnOrder} exists one rule up.
|
|
169
|
+
*/
|
|
170
|
+
export function requireOwnUser(state: RetailState, userId: string): User | ToolFailure {
|
|
171
|
+
const user = authenticatedUser(state);
|
|
172
|
+
if (isToolFailure(user)) return user;
|
|
173
|
+
if (user.user_id !== userId) {
|
|
174
|
+
return {
|
|
175
|
+
error: `${userId} is not the customer on this call. You can help only one customer per conversation.`,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return user;
|
|
179
|
+
}
|
|
180
|
+
|
|
161
181
|
// ─── The tool wrapper ────────────────────────────────────────────────────────
|
|
162
182
|
|
|
163
183
|
interface RetailToolSpec<S extends z.ZodType<Record<string, unknown>>, R> {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isToolFailure } from "@alexkroman1/aai";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { creditRefund, REFUND_DELAY_NOTE, REFUND_IMMEDIATE_NOTE } from "../refund.ts";
|
|
4
|
-
import { resolveOrder } from "../resolve.ts";
|
|
4
|
+
import { OrderIdField, resolveOrder } from "../resolve.ts";
|
|
5
5
|
import { authenticatedUser, retailTool, setFocus } from "../store.ts";
|
|
6
6
|
|
|
7
7
|
/** tau2 accepts exactly these two. Anything else is refused. */
|
|
@@ -15,10 +15,7 @@ export default retailTool({
|
|
|
15
15
|
"State the order, its total and the refund destination to the caller and get an explicit yes " +
|
|
16
16
|
"before calling this.",
|
|
17
17
|
inputSchema: z.object({
|
|
18
|
-
order_id:
|
|
19
|
-
.string()
|
|
20
|
-
.max(120)
|
|
21
|
-
.describe("Order id such as '#W0000000', or a spoken reference to one of their orders"),
|
|
18
|
+
order_id: OrderIdField,
|
|
22
19
|
reason: z
|
|
23
20
|
.enum(CANCEL_REASONS)
|
|
24
21
|
.describe("Either 'no longer needed' or 'ordered by mistake' — no other reason is accepted"),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isToolFailure } from "@alexkroman1/aai";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { resolveOrder } from "../resolve.ts";
|
|
3
|
+
import { OrderIdField, resolveOrder } from "../resolve.ts";
|
|
4
4
|
import { authenticatedUser, money, retailTool, setFocus } from "../store.ts";
|
|
5
5
|
import { assertCanCoverDiff, planItemSwap } from "../swap.ts";
|
|
6
6
|
|
|
@@ -13,10 +13,7 @@ export default retailTool({
|
|
|
13
13
|
"back, and get an explicit yes. No new order is needed — the customer gets an email explaining " +
|
|
14
14
|
"how to send the originals back.",
|
|
15
15
|
inputSchema: z.object({
|
|
16
|
-
order_id:
|
|
17
|
-
.string()
|
|
18
|
-
.max(120)
|
|
19
|
-
.describe("Order id such as '#W0000000', or a spoken reference to one of their orders"),
|
|
16
|
+
order_id: OrderIdField,
|
|
20
17
|
item_ids: z
|
|
21
18
|
.array(z.string().max(60))
|
|
22
19
|
.max(20)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { isToolFailure } from "@alexkroman1/aai";
|
|
2
|
+
import { omitUndefined } from "@alexkroman1/aai/utils";
|
|
2
3
|
import { z } from "zod";
|
|
3
|
-
import { resolveOrder } from "../resolve.ts";
|
|
4
|
+
import { OrderIdField, resolveOrder } from "../resolve.ts";
|
|
4
5
|
import { retailTool, setFocus } from "../store.ts";
|
|
5
6
|
|
|
6
7
|
export default retailTool({
|
|
@@ -10,10 +11,7 @@ export default retailTool({
|
|
|
10
11
|
"order id (e.g. '#W0000000' — note the leading '#'), or a spoken reference such as " +
|
|
11
12
|
"'my pending order', 'the delivered one', or 'the second pending order'.",
|
|
12
13
|
inputSchema: z.object({
|
|
13
|
-
order_id:
|
|
14
|
-
.string()
|
|
15
|
-
.max(120)
|
|
16
|
-
.describe("Order id such as '#W0000000', or a spoken reference to one of their orders"),
|
|
14
|
+
order_id: OrderIdField,
|
|
17
15
|
}),
|
|
18
16
|
execute: (args, state) => {
|
|
19
17
|
const order = resolveOrder(state, args.order_id);
|
|
@@ -31,7 +29,7 @@ export default retailTool({
|
|
|
31
29
|
options: item.options,
|
|
32
30
|
})),
|
|
33
31
|
payment_history: order.payment_history,
|
|
34
|
-
...(
|
|
32
|
+
...omitUndefined({ fulfillments: order.fulfillments }),
|
|
35
33
|
...(order.cancel_reason ? { cancel_reason: order.cancel_reason } : {}),
|
|
36
34
|
};
|
|
37
35
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isToolFailure } from "@alexkroman1/aai";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import {
|
|
3
|
+
import { requireOwnUser, retailTool } from "../store.ts";
|
|
4
4
|
|
|
5
5
|
export default retailTool({
|
|
6
6
|
name: "get_user_details",
|
|
@@ -11,13 +11,8 @@ export default retailTool({
|
|
|
11
11
|
user_id: z.string().max(100).describe("The user id, e.g. 'sara_doe_496'"),
|
|
12
12
|
}),
|
|
13
13
|
execute: (args, state) => {
|
|
14
|
-
const user =
|
|
14
|
+
const user = requireOwnUser(state, args.user_id);
|
|
15
15
|
if (isToolFailure(user)) return user;
|
|
16
|
-
if (user.user_id !== args.user_id) {
|
|
17
|
-
return {
|
|
18
|
-
error: `${args.user_id} is not the customer on this call. You can help only one customer per conversation.`,
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
16
|
return {
|
|
22
17
|
user_id: user.user_id,
|
|
23
18
|
name: `${user.name.first_name} ${user.name.last_name}`,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isToolFailure } from "@alexkroman1/aai";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { AddressFields, formatAddress, toAddress } from "../address.ts";
|
|
4
|
-
import { resolveOrder } from "../resolve.ts";
|
|
4
|
+
import { OrderIdField, resolveOrder } from "../resolve.ts";
|
|
5
5
|
import { retailTool, setFocus } from "../store.ts";
|
|
6
6
|
|
|
7
7
|
export default retailTool({
|
|
@@ -10,10 +10,7 @@ export default retailTool({
|
|
|
10
10
|
"Change the shipping address of a pending order. Read the new address back to the caller and " +
|
|
11
11
|
"get an explicit yes before calling this. This does not change the customer's default address.",
|
|
12
12
|
inputSchema: z.object({
|
|
13
|
-
order_id:
|
|
14
|
-
.string()
|
|
15
|
-
.max(120)
|
|
16
|
-
.describe("Order id such as '#W0000000', or a spoken reference to one of their orders"),
|
|
13
|
+
order_id: OrderIdField,
|
|
17
14
|
...AddressFields,
|
|
18
15
|
}),
|
|
19
16
|
execute: (args, state) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isToolFailure } from "@alexkroman1/aai";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { resolveOrder } from "../resolve.ts";
|
|
3
|
+
import { OrderIdField, resolveOrder } from "../resolve.ts";
|
|
4
4
|
import { authenticatedUser, isGiftCard, money, retailTool, setFocus } from "../store.ts";
|
|
5
5
|
import { applySwap, assertCanCoverDiff, planItemSwap } from "../swap.ts";
|
|
6
6
|
|
|
@@ -13,10 +13,7 @@ export default retailTool({
|
|
|
13
13
|
"list and the price difference back, and get an explicit yes first. The item and replacement " +
|
|
14
14
|
"lists are positional and must be the same length.",
|
|
15
15
|
inputSchema: z.object({
|
|
16
|
-
order_id:
|
|
17
|
-
.string()
|
|
18
|
-
.max(120)
|
|
19
|
-
.describe("Order id such as '#W0000000', or a spoken reference to one of their orders"),
|
|
16
|
+
order_id: OrderIdField,
|
|
20
17
|
item_ids: z
|
|
21
18
|
.array(z.string().max(60))
|
|
22
19
|
.max(20)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isToolFailure } from "@alexkroman1/aai";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { resolveOrder } from "../resolve.ts";
|
|
3
|
+
import { OrderIdField, resolveOrder } from "../resolve.ts";
|
|
4
4
|
import {
|
|
5
5
|
authenticatedUser,
|
|
6
6
|
findPaymentMethod,
|
|
@@ -17,10 +17,7 @@ export default retailTool({
|
|
|
17
17
|
"from the current one, and a gift card must hold enough to cover the whole order. The original " +
|
|
18
18
|
"method is refunded. Read the change back and get an explicit yes before calling this.",
|
|
19
19
|
inputSchema: z.object({
|
|
20
|
-
order_id:
|
|
21
|
-
.string()
|
|
22
|
-
.max(120)
|
|
23
|
-
.describe("Order id such as '#W0000000', or a spoken reference to one of their orders"),
|
|
20
|
+
order_id: OrderIdField,
|
|
24
21
|
payment_method_id: z
|
|
25
22
|
.string()
|
|
26
23
|
.max(80)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isToolFailure } from "@alexkroman1/aai";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { AddressFields, formatAddress, toAddress } from "../address.ts";
|
|
4
|
-
import {
|
|
4
|
+
import { requireOwnUser, retailTool } from "../store.ts";
|
|
5
5
|
|
|
6
6
|
export default retailTool({
|
|
7
7
|
name: "modify_user_address",
|
|
@@ -14,13 +14,8 @@ export default retailTool({
|
|
|
14
14
|
...AddressFields,
|
|
15
15
|
}),
|
|
16
16
|
execute: (args, state) => {
|
|
17
|
-
const user =
|
|
17
|
+
const user = requireOwnUser(state, args.user_id);
|
|
18
18
|
if (isToolFailure(user)) return user;
|
|
19
|
-
if (user.user_id !== args.user_id) {
|
|
20
|
-
return {
|
|
21
|
-
error: `${args.user_id} is not the customer on this call. You can help only one customer per conversation.`,
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
19
|
|
|
25
20
|
user.address = toAddress(args);
|
|
26
21
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isToolFailure } from "@alexkroman1/aai";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { resolveOrder } from "../resolve.ts";
|
|
3
|
+
import { OrderIdField, resolveOrder } from "../resolve.ts";
|
|
4
4
|
import {
|
|
5
5
|
authenticatedUser,
|
|
6
6
|
findPaymentMethod,
|
|
@@ -18,10 +18,7 @@ export default retailTool({
|
|
|
18
18
|
"explicit yes before calling this. The customer gets an email explaining how to send the " +
|
|
19
19
|
"items back.",
|
|
20
20
|
inputSchema: z.object({
|
|
21
|
-
order_id:
|
|
22
|
-
.string()
|
|
23
|
-
.max(120)
|
|
24
|
-
.describe("Order id such as '#W0000000', or a spoken reference to one of their orders"),
|
|
21
|
+
order_id: OrderIdField,
|
|
25
22
|
item_ids: z
|
|
26
23
|
.array(z.string().max(60))
|
|
27
24
|
.max(20)
|
|
@@ -18,14 +18,13 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { stubReporter, stubStepFetch, stubUploads } from "@alexkroman1/aai/testing";
|
|
21
|
-
import { readUpload } from "@alexkroman1/aai/utils";
|
|
21
|
+
import { omitUndefined, readUpload } from "@alexkroman1/aai/utils";
|
|
22
22
|
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
23
23
|
import { FatalError, RetryableError } from "workflow";
|
|
24
24
|
import { z } from "zod";
|
|
25
25
|
import agentDef, { transcribe, transcribeBatch, transcribeStream } from "./agent.ts";
|
|
26
26
|
import { createJob, pollTranscript, readTranscript, uploadToProvider } from "./workflows/batch.ts";
|
|
27
27
|
import { planStreamed, probeUpload } from "./workflows/stream.ts";
|
|
28
|
-
|
|
29
28
|
import {
|
|
30
29
|
clock,
|
|
31
30
|
mergeTranscript,
|
|
@@ -539,7 +538,7 @@ describe("transcribeSegment", () => {
|
|
|
539
538
|
const stub = stubStepFetch(() => ({
|
|
540
539
|
status: sync.status ?? 200,
|
|
541
540
|
body: sync.body ?? { text: "hello there" },
|
|
542
|
-
...(
|
|
541
|
+
...omitUndefined({ headers: sync.headers }),
|
|
543
542
|
}));
|
|
544
543
|
stubs.push(stub.restore);
|
|
545
544
|
return stub.calls;
|
|
@@ -45,8 +45,9 @@
|
|
|
45
45
|
*/
|
|
46
46
|
|
|
47
47
|
import { throwFatalStepError, toStepError } from "@alexkroman1/aai/step-errors";
|
|
48
|
-
import { readUpload, report,
|
|
48
|
+
import { readUpload, report, stepFetch, uploadInfo } from "@alexkroman1/aai/utils";
|
|
49
49
|
import { sleep } from "workflow";
|
|
50
|
+
import { apiKeyOrFatal } from "./sync-api.ts";
|
|
50
51
|
import { countWords, startClock, type Transcript } from "./transcribe.ts";
|
|
51
52
|
|
|
52
53
|
/** The async API's base. */
|
|
@@ -66,9 +67,6 @@ const API = "https://api.assemblyai.com";
|
|
|
66
67
|
*/
|
|
67
68
|
const MODELS = ["universal-3-5-pro"];
|
|
68
69
|
|
|
69
|
-
/** The key a step reads out of the agent env. Declared in `agent.ts`'s `requiredEnv`. */
|
|
70
|
-
const API_KEY_ENV = "ASSEMBLYAI_API_KEY";
|
|
71
|
-
|
|
72
70
|
/** How much of our stored upload one outbound window carries. */
|
|
73
71
|
const UPLOAD_WINDOW_BYTES = 4 * 1024 * 1024;
|
|
74
72
|
|
|
@@ -277,15 +275,6 @@ async function* windows(uploadId: string, size: number): AsyncGenerator<Uint8Arr
|
|
|
277
275
|
}
|
|
278
276
|
}
|
|
279
277
|
|
|
280
|
-
/** The API key, or a terminal failure — three more attempts find the same gap. */
|
|
281
|
-
function apiKeyOrFatal(): string {
|
|
282
|
-
try {
|
|
283
|
-
return requireStepEnv(API_KEY_ENV);
|
|
284
|
-
} catch (err: unknown) {
|
|
285
|
-
return throwFatalStepError(err);
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
|
|
289
278
|
/** A failed call, classified for the DevKit — see `sync-api.ts` for the three-way rule. */
|
|
290
279
|
async function failure(res: Response, what: string): Promise<Error> {
|
|
291
280
|
const body = (await res.json().catch(() => ({}))) as { error?: string };
|
|
@@ -123,6 +123,7 @@ import { mapConcurrent, readUpload, report, uploadInfo } from "@alexkroman1/aai/
|
|
|
123
123
|
import { sleep } from "workflow";
|
|
124
124
|
import {
|
|
125
125
|
clock,
|
|
126
|
+
fatalOnUnsupported,
|
|
126
127
|
mergeTranscript,
|
|
127
128
|
type SegmentTranscript,
|
|
128
129
|
segmentConcurrency,
|
|
@@ -323,16 +324,6 @@ function expectedSegments(plan: StreamPlan, size: number): number {
|
|
|
323
324
|
return plan.segments.filter((segment) => segment.start < size).length;
|
|
324
325
|
}
|
|
325
326
|
|
|
326
|
-
/** Run a `wav.ts` helper, turning its "cannot cut this" into a terminal failure. */
|
|
327
|
-
function fatalOnUnsupported<T>(read: () => T): T {
|
|
328
|
-
try {
|
|
329
|
-
return read();
|
|
330
|
-
} catch (err: unknown) {
|
|
331
|
-
if (err instanceof UnsupportedRecordingError) return throwFatalStepError(err);
|
|
332
|
-
throw err;
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
327
|
/**
|
|
337
328
|
* Give up on an upload that stopped arriving.
|
|
338
329
|
*
|
|
@@ -104,8 +104,14 @@ export async function transcribeWav(
|
|
|
104
104
|
return (body.text ?? "").trim();
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
/**
|
|
108
|
-
|
|
107
|
+
/**
|
|
108
|
+
* The API key, or a terminal failure — three more attempts find the same gap.
|
|
109
|
+
*
|
|
110
|
+
* Exported because `batch.ts` calls the same provider on the same key and had
|
|
111
|
+
* written this, and its own `API_KEY_ENV`, again. The key belongs to the
|
|
112
|
+
* PROVIDER; only the endpoint and its failure shapes belong to this module.
|
|
113
|
+
*/
|
|
114
|
+
export function apiKeyOrFatal(): string {
|
|
109
115
|
try {
|
|
110
116
|
return requireStepEnv(API_KEY_ENV);
|
|
111
117
|
} catch (err: unknown) {
|
|
@@ -422,8 +422,14 @@ export {
|
|
|
422
422
|
|
|
423
423
|
// ---- I/O helpers ------------------------------------------------------------
|
|
424
424
|
|
|
425
|
-
/**
|
|
426
|
-
|
|
425
|
+
/**
|
|
426
|
+
* Run a `wav.ts` helper, turning its "cannot cut this" into a terminal failure.
|
|
427
|
+
*
|
|
428
|
+
* Exported for the same reason `countWords` is: `stream.ts` plans with the same
|
|
429
|
+
* `wav.ts` helpers and owes the same classification, and it had this byte for
|
|
430
|
+
* byte.
|
|
431
|
+
*/
|
|
432
|
+
export function fatalOnUnsupported<T>(read: () => T): T {
|
|
427
433
|
try {
|
|
428
434
|
return read();
|
|
429
435
|
} catch (err: unknown) {
|
|
@@ -38,9 +38,7 @@ function resolveVitestCommand(cwd, resolve = createRequire(path.join(cwd, "packa
|
|
|
38
38
|
* Throws on test failure.
|
|
39
39
|
*/
|
|
40
40
|
function runVitest(cwd) {
|
|
41
|
-
|
|
42
|
-
if (existsSync(path.join(cwd, "agent.test.ts"))) testFile = "agent.test.ts";
|
|
43
|
-
else if (existsSync(path.join(cwd, "agent.test.js"))) testFile = "agent.test.js";
|
|
41
|
+
const testFile = ["agent.test.ts", "agent.test.js"].find((name) => existsSync(path.join(cwd, name)));
|
|
44
42
|
if (!testFile) return false;
|
|
45
43
|
const { cmd, args } = resolveVitestCommand(cwd);
|
|
46
44
|
execaSync(cmd, [
|
package/dist/typecheck.mjs
CHANGED
|
@@ -155,12 +155,11 @@ async function typecheckProject(cwd) {
|
|
|
155
155
|
});
|
|
156
156
|
let output = "";
|
|
157
157
|
const keep = (s) => s.length > OUTPUT_CAP ? `…${s.slice(-16e3)}` : s;
|
|
158
|
-
|
|
158
|
+
const append = (chunk) => {
|
|
159
159
|
output = keep(output + chunk.toString());
|
|
160
|
-
}
|
|
161
|
-
child.
|
|
162
|
-
|
|
163
|
-
});
|
|
160
|
+
};
|
|
161
|
+
child.stdout.on("data", append);
|
|
162
|
+
child.stderr.on("data", append);
|
|
164
163
|
child.on("error", reject);
|
|
165
164
|
child.on("close", (code, signal) => {
|
|
166
165
|
if (signal) {
|
|
@@ -145,8 +145,19 @@ var AaiWorkflowBuilder = class extends BaseBuilder {
|
|
|
145
145
|
* repo's `erasableSyntaxOnly`, so the fields are declared the long way too.
|
|
146
146
|
*/
|
|
147
147
|
output;
|
|
148
|
-
|
|
148
|
+
/**
|
|
149
|
+
* The two bundles `build()` reads back.
|
|
150
|
+
*
|
|
151
|
+
* Held as fields because `super()` is also told where to write them: derived
|
|
152
|
+
* a second time inside `build()`, the two spellings of each path were free to
|
|
153
|
+
* disagree, and a `build()` reading a file the builder never wrote is a
|
|
154
|
+
* "produced nothing" failure that names neither path.
|
|
155
|
+
*/
|
|
156
|
+
flowFile;
|
|
157
|
+
stepFile;
|
|
149
158
|
constructor(cwd, outDir) {
|
|
159
|
+
const flowFile = path.join(outDir, "flow.mjs");
|
|
160
|
+
const stepFile = path.join(outDir, "step.mjs");
|
|
150
161
|
super({
|
|
151
162
|
buildTarget: "standalone",
|
|
152
163
|
dirs: [`./${WORKFLOWS_DIR}`],
|
|
@@ -154,31 +165,30 @@ var AaiWorkflowBuilder = class extends BaseBuilder {
|
|
|
154
165
|
projectRoot: cwd,
|
|
155
166
|
moduleSpecifierRoot: cwd,
|
|
156
167
|
externalPackages: [...WDK_EXTERNAL],
|
|
157
|
-
stepsBundlePath:
|
|
158
|
-
workflowsBundlePath:
|
|
168
|
+
stepsBundlePath: stepFile,
|
|
169
|
+
workflowsBundlePath: flowFile,
|
|
159
170
|
webhookBundlePath: path.join(outDir, "webhook.mjs"),
|
|
160
171
|
suppressCreateWorkflowsBundleLogs: true,
|
|
161
172
|
suppressCreateWebhookBundleLogs: true,
|
|
162
173
|
suppressCreateManifestLogs: true
|
|
163
174
|
});
|
|
164
|
-
this.
|
|
175
|
+
this.flowFile = flowFile;
|
|
176
|
+
this.stepFile = stepFile;
|
|
165
177
|
}
|
|
166
178
|
async build() {
|
|
167
179
|
const inputFiles = await this.getInputFiles();
|
|
168
|
-
const flowFile = path.join(this.outDir, "flow.mjs");
|
|
169
|
-
const stepFile = path.join(this.outDir, "step.mjs");
|
|
170
180
|
const { manifest } = await this.createWorkflowsBundle({
|
|
171
181
|
inputFiles,
|
|
172
182
|
format: "esm",
|
|
173
|
-
outfile: flowFile,
|
|
183
|
+
outfile: this.flowFile,
|
|
174
184
|
bundleFinalOutput: false
|
|
175
185
|
});
|
|
176
186
|
await this.createStepsBundle({
|
|
177
187
|
inputFiles,
|
|
178
188
|
format: "esm",
|
|
179
|
-
outfile: stepFile
|
|
189
|
+
outfile: this.stepFile
|
|
180
190
|
});
|
|
181
|
-
const [workflowCode, stepCode] = await Promise.all([fs.readFile(flowFile, "utf-8"), fs.readFile(stepFile, "utf-8")]);
|
|
191
|
+
const [workflowCode, stepCode] = await Promise.all([fs.readFile(this.flowFile, "utf-8"), fs.readFile(this.stepFile, "utf-8")]);
|
|
182
192
|
this.output = {
|
|
183
193
|
workflowCode,
|
|
184
194
|
stepCode: STEP_REQUIRE_SHIM + stepCode,
|
|
@@ -358,8 +368,12 @@ export const __aaiStepCode = ${JSON.stringify(workflows.stepCode)};
|
|
|
358
368
|
*/
|
|
359
369
|
async function buildWorker(cwd, opts = {}) {
|
|
360
370
|
const wrapperPath = path.join(cwd, WRAPPER_ENTRY_REL);
|
|
361
|
-
|
|
362
|
-
|
|
371
|
+
const [, toolFiles, systemPromptFile] = await Promise.all([
|
|
372
|
+
fs.mkdir(path.dirname(wrapperPath), { recursive: true }),
|
|
373
|
+
discoverToolFiles(cwd),
|
|
374
|
+
hasSystemPromptFile(cwd)
|
|
375
|
+
]);
|
|
376
|
+
await fs.writeFile(wrapperPath, wrapperEntrySource(opts.runtime !== false, opts.workflows, toolFiles, systemPromptFile), "utf-8");
|
|
363
377
|
const plugins = [...opts.plugins ?? [], ...opts.workflows ? [workflowClientPlugin(cwd, opts.workflows.inputFiles)] : []];
|
|
364
378
|
let result;
|
|
365
379
|
try {
|
package/dist/worker-bundler.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { a as ok, n as fail } from "./_output-CKkmWs7i.mjs";
|
|
3
3
|
import { n as log } from "./_ui-u7T4YooX.mjs";
|
|
4
|
-
import { n as getServerInfo } from "./_agent-
|
|
4
|
+
import { n as getServerInfo } from "./_agent-DpH2pBJd.mjs";
|
|
5
5
|
import { errorMessage, omitUndefined } from "@alexkroman1/aai/utils";
|
|
6
6
|
import { createWorkflowApiClient } from "@alexkroman1/aai/workflow-api";
|
|
7
7
|
//#region workflow.ts
|