@alexkroman1/aai-cli 5.14.0 → 6.1.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.
- package/dist/{_agent-C8Jk-ZcP.mjs → _agent-vGW5SBnX.mjs} +23 -5
- package/dist/_agent.d.ts +18 -0
- package/dist/{_api-client-BX8Qv51n.mjs → _api-client-LgLksMhN.mjs} +45 -8
- package/dist/_api-client.d.ts +39 -0
- package/dist/{_bundler-BuIyDdvs.mjs → _bundler-BapCUUJN.mjs} +42 -14
- package/dist/_bundler.d.ts +43 -5
- package/dist/_cli-common.d.ts +67 -3
- package/dist/{_config-CzwAWOWr.mjs → _config-D_s09e7g.mjs} +36 -18
- package/dist/_deploy.d.ts +2 -5
- package/dist/_dev-restart.d.ts +6 -1
- package/dist/{_dev-server-Ch7K8e8i.mjs → _dev-server-DQ1t9sbw.mjs} +94 -38
- package/dist/_dev-server.d.ts +30 -2
- package/dist/_e2e-test-utils.d.ts +80 -0
- package/dist/_fault-mode.d.ts +175 -0
- package/dist/{_init-CbkrE2wq.mjs → _init-CpISqoR8.mjs} +3 -3
- package/dist/{_output-CC300DzW.mjs → _output-CKkmWs7i.mjs} +8 -1
- package/dist/_output.d.ts +9 -2
- package/dist/{_server-common-61fL__39.mjs → _server-common-6e0QI4mq.mjs} +1 -1
- package/dist/{_slug-api-D30zPmsn.mjs → _slug-api-D2heILuC.mjs} +2 -2
- package/dist/{_studio-D2ciIhbi.mjs → _studio-zAJycZ8j.mjs} +3 -3
- package/dist/{_templates-B1kt3BGt.mjs → _templates-iDGjGiPf.mjs} +4 -6
- package/dist/{_typecheck-gate-4v9UBZHh.mjs → _typecheck-gate-BXvUNnfs.mjs} +1 -1
- package/dist/{_utils-0DHbcqUb.mjs → _utils-B8QmtFhK.mjs} +21 -7
- package/dist/_utils.d.ts +18 -2
- package/dist/{_vite-env-Dg_QlVv0.mjs → _vite-env-BNveawd1.mjs} +31 -1
- package/dist/_vite-env.d.ts +30 -0
- package/dist/build-BO1Ni6oJ.mjs +62 -0
- package/dist/build.d.ts +19 -0
- package/dist/cli-workflow.d.ts +10 -0
- package/dist/cli.d.ts +1 -2
- package/dist/cli.mjs +406 -224
- package/dist/{client-bundler-C9qXL8A2.mjs → client-bundler-B8Q9F8gJ.mjs} +3 -22
- package/dist/client-bundler.mjs +1 -1
- package/dist/{delete-DCRX3d96.mjs → delete-4I0uNR4a.mjs} +6 -7
- package/dist/delete.d.ts +2 -8
- package/dist/{deploy-DjsEV-40.mjs → deploy-DJ3HRcia.mjs} +13 -14
- package/dist/{dev-CvPH5dbF.mjs → dev-C6SWaAZP.mjs} +3 -3
- package/dist/{eject-LgBRfnbH.mjs → eject-Zrzk5KV3.mjs} +41 -15
- package/dist/eject.d.ts +30 -3
- package/dist/{init-BppxMR8r.mjs → init-BTRGiPQr.mjs} +61 -26
- package/dist/init.d.ts +11 -0
- package/dist/{login-BQQaxJhL.mjs → login-k0Z3VQu9.mjs} +5 -5
- package/dist/project-config.mjs +1 -1
- package/dist/scaffold/CLAUDE.md +498 -91
- package/dist/scaffold/package.json +11 -8
- package/dist/scaffold/pnpm-workspace.yaml +8 -0
- package/dist/scaffold/server.mjs +53 -57
- package/dist/{secret-Ds9dvqAj.mjs → secret-DzSQx1Ds.mjs} +6 -3
- package/dist/{storage-DbrQSHFk.mjs → storage-C-Do0mIA.mjs} +18 -6
- package/dist/{studio-GSFd4s5O.mjs → studio-BGVmCA2G.mjs} +10 -10
- package/dist/templates/code-interpreter/agent.ts +0 -2
- package/dist/templates/dispatch-center/agent.test.ts +17 -19
- package/dist/templates/dispatch-center/agent.ts +2 -29
- package/dist/templates/dispatch-center/client.tsx +33 -16
- package/dist/templates/dispatch-center/shared.ts +53 -19
- package/dist/templates/dispatch-center/tools/incident_add_note.ts +12 -14
- package/dist/templates/dispatch-center/tools/incident_create.ts +41 -44
- package/dist/templates/dispatch-center/tools/incident_escalate.ts +59 -61
- package/dist/templates/dispatch-center/tools/incident_get.ts +3 -4
- package/dist/templates/dispatch-center/tools/incident_triage.ts +43 -45
- package/dist/templates/dispatch-center/tools/incident_update_status.ts +39 -41
- package/dist/templates/dispatch-center/tools/ops_dashboard.ts +2 -5
- package/dist/templates/dispatch-center/tools/ops_protocols.ts +1 -1
- package/dist/templates/dispatch-center/tools/ops_run_scenario.ts +20 -23
- package/dist/templates/dispatch-center/tools/resources_dispatch.ts +52 -54
- package/dist/templates/dispatch-center/tools/resources_get_available.ts +2 -4
- package/dist/templates/dispatch-center/tools/resources_update_status.ts +39 -42
- package/dist/templates/embedded-assets/agent.test.ts +83 -0
- package/dist/templates/embedded-assets/agent.ts +1 -48
- package/dist/templates/embedded-assets/shared.ts +17 -0
- package/dist/templates/embedded-assets/system-prompt.md +13 -0
- package/dist/templates/embedded-assets/tools/list_topics.ts +9 -0
- package/dist/templates/embedded-assets/tools/search_knowledge.ts +26 -0
- package/dist/templates/health-assistant/agent.test.ts +169 -0
- package/dist/templates/health-assistant/agent.ts +1 -166
- package/dist/templates/health-assistant/fda.ts +100 -0
- package/dist/templates/health-assistant/tools/check_drug_interaction.ts +59 -0
- package/dist/templates/health-assistant/tools/medication_lookup.ts +31 -0
- package/dist/templates/infocom-adventure/agent.test.ts +205 -0
- package/dist/templates/infocom-adventure/agent.ts +3 -106
- package/dist/templates/infocom-adventure/client.tsx +28 -12
- package/dist/templates/infocom-adventure/shared.ts +28 -11
- package/dist/templates/infocom-adventure/tools/game_state_drop.ts +13 -0
- package/dist/templates/infocom-adventure/tools/game_state_flag.ts +13 -0
- package/dist/templates/infocom-adventure/tools/game_state_get.ts +16 -0
- package/dist/templates/infocom-adventure/tools/game_state_history.ts +14 -0
- package/dist/templates/infocom-adventure/tools/game_state_move.ts +14 -0
- package/dist/templates/infocom-adventure/tools/game_state_restart.ts +13 -0
- package/dist/templates/infocom-adventure/tools/game_state_score.ts +13 -0
- package/dist/templates/infocom-adventure/tools/game_state_take.ts +13 -0
- package/dist/templates/link-digest/agent.test.ts +223 -0
- package/dist/templates/link-digest/agent.ts +79 -0
- package/dist/templates/link-digest/client.tsx +146 -0
- package/dist/templates/link-digest/workflows/digest.ts +248 -0
- package/dist/templates/math-buddy/agent.ts +0 -2
- package/dist/templates/night-owl/agent.test.ts +80 -0
- package/dist/templates/night-owl/agent.ts +1 -68
- package/dist/templates/night-owl/system-prompt.md +10 -0
- package/dist/templates/night-owl/tools/recommend.ts +64 -0
- package/dist/templates/personal-finance/agent.ts +0 -2
- package/dist/templates/pizza-ordering/agent.test.ts +52 -47
- package/dist/templates/pizza-ordering/agent.ts +9 -158
- package/dist/templates/pizza-ordering/shared.ts +35 -12
- package/dist/templates/pizza-ordering/tools/add_pizza.ts +31 -0
- package/dist/templates/pizza-ordering/tools/place_order.ts +22 -0
- package/dist/templates/pizza-ordering/tools/remove_pizza.ts +22 -0
- package/dist/templates/pizza-ordering/tools/set_customer_name.ts +13 -0
- package/dist/templates/pizza-ordering/tools/update_pizza.ts +28 -0
- package/dist/templates/pizza-ordering/tools/view_order.ts +21 -0
- package/dist/templates/plan-and-execute/agent.test.ts +411 -0
- package/dist/templates/plan-and-execute/agent.ts +23 -0
- package/dist/templates/plan-and-execute/client.tsx +115 -0
- package/dist/templates/plan-and-execute/graph.ts +178 -0
- package/dist/templates/plan-and-execute/prompts.ts +110 -0
- package/dist/templates/plan-and-execute/shared.ts +161 -0
- package/dist/templates/plan-and-execute/system-prompt.md +18 -0
- package/dist/templates/plan-and-execute/tools/plan_status.ts +20 -0
- package/dist/templates/plan-and-execute/tools/revise_plan.ts +63 -0
- package/dist/templates/plan-and-execute/tools/start_plan.ts +51 -0
- package/dist/templates/plan-and-execute/tools/work_next_step.ts +101 -0
- package/dist/templates/recap-workflow/agent.test.ts +762 -0
- package/dist/templates/recap-workflow/agent.ts +95 -0
- package/dist/templates/recap-workflow/shared.ts +43 -0
- package/dist/templates/recap-workflow/tools/cancel_recap.ts +23 -0
- package/dist/templates/recap-workflow/tools/keep_transcript.ts +31 -0
- package/dist/templates/recap-workflow/tools/recap_progress.ts +27 -0
- package/dist/templates/recap-workflow/tools/recap_status.ts +46 -0
- package/dist/templates/recap-workflow/tools/request_recap.ts +43 -0
- package/dist/templates/recap-workflow/workflows/recap.ts +544 -0
- package/dist/templates/recap-workflow/workflows/tokens.ts +26 -0
- package/dist/templates/redline/agent.test.ts +222 -0
- package/dist/templates/redline/agent.ts +89 -0
- package/dist/templates/redline/client.tsx +184 -0
- package/dist/templates/redline/workflows/prompts.ts +68 -0
- package/dist/templates/redline/workflows/redline.ts +258 -0
- package/dist/templates/research-workflow/agent.test.ts +525 -0
- package/dist/templates/research-workflow/agent.ts +94 -0
- package/dist/templates/research-workflow/shared.ts +35 -0
- package/dist/templates/research-workflow/tools/file_it_now.ts +22 -0
- package/dist/templates/research-workflow/tools/request_research.ts +33 -0
- package/dist/templates/research-workflow/tools/research_progress.ts +26 -0
- package/dist/templates/research-workflow/tools/research_status.ts +40 -0
- package/dist/templates/research-workflow/workflows/prompts.ts +143 -0
- package/dist/templates/research-workflow/workflows/research.ts +558 -0
- package/dist/templates/retail/agent.test.ts +236 -172
- package/dist/templates/retail/agent.ts +5 -42
- package/dist/templates/retail/client.tsx +33 -11
- package/dist/templates/retail/registry.test.ts +31 -16
- package/dist/templates/retail/resolve.ts +28 -64
- package/dist/templates/retail/shared.test.ts +4 -3
- package/dist/templates/retail/shared.ts +24 -7
- package/dist/templates/retail/store.test.ts +12 -10
- package/dist/templates/retail/store.ts +69 -30
- package/dist/templates/retail/tools/cancel_pending_order.ts +4 -9
- package/dist/templates/retail/tools/exchange_delivered_order_items.ts +22 -11
- package/dist/templates/retail/tools/find_user_id_by_email.ts +5 -9
- package/dist/templates/retail/tools/find_user_id_by_name_zip.ts +5 -7
- package/dist/templates/retail/tools/get_item_details.ts +5 -7
- package/dist/templates/retail/tools/get_order_details.ts +5 -7
- package/dist/templates/retail/tools/get_product_details.ts +4 -7
- package/dist/templates/retail/tools/get_user_details.ts +4 -7
- package/dist/templates/retail/tools/list_all_product_types.ts +5 -7
- package/dist/templates/retail/tools/modify_pending_order_address.ts +4 -9
- package/dist/templates/retail/tools/modify_pending_order_items.ts +4 -16
- package/dist/templates/retail/tools/modify_pending_order_payment.ts +3 -9
- package/dist/templates/retail/tools/modify_user_address.ts +4 -9
- package/dist/templates/retail/tools/return_delivered_order_items.ts +3 -9
- package/dist/templates/retail/tools/transfer_to_human_agents.ts +1 -1
- package/dist/templates/solo-rpg/agent.test.ts +152 -29
- package/dist/templates/solo-rpg/agent.ts +3 -21
- package/dist/templates/solo-rpg/client.tsx +19 -6
- package/dist/templates/solo-rpg/shared.ts +19 -11
- package/dist/templates/solo-rpg/tools/action_roll.ts +2 -4
- package/dist/templates/solo-rpg/tools/burn_momentum.ts +2 -4
- package/dist/templates/solo-rpg/tools/check_state.ts +6 -6
- package/dist/templates/solo-rpg/tools/load_game.ts +1 -1
- package/dist/templates/solo-rpg/tools/oracle.ts +18 -11
- package/dist/templates/solo-rpg/tools/save_game.ts +10 -7
- package/dist/templates/solo-rpg/tools/setup_character.ts +1 -1
- package/dist/templates/solo-rpg/tools/update_state.ts +3 -4
- package/dist/templates/support-line/agent.test.ts +343 -0
- package/dist/templates/support-line/agent.ts +27 -0
- package/dist/templates/support-line/client.tsx +122 -0
- package/dist/templates/support-line/graph.ts +224 -0
- package/dist/templates/support-line/knowledge.json +65 -0
- package/dist/templates/support-line/prompts.ts +95 -0
- package/dist/templates/support-line/shared.ts +240 -0
- package/dist/templates/support-line/system-prompt.md +17 -0
- package/dist/templates/support-line/tools/answer_question.ts +72 -0
- package/dist/templates/support-line/tools/list_topics.ts +22 -0
- package/dist/templates/support-line/tools/log_ticket.ts +30 -0
- package/dist/templates/transcription-workflow/agent.test.ts +563 -0
- package/dist/templates/transcription-workflow/agent.ts +92 -0
- package/dist/templates/transcription-workflow/client.tsx +234 -0
- package/dist/templates/transcription-workflow/workflows/transcribe.ts +416 -0
- package/dist/templates/transcription-workflow/workflows/wav.ts +314 -0
- package/dist/templates/travel-concierge/agent.test.ts +338 -0
- package/dist/templates/travel-concierge/agent.ts +29 -0
- package/dist/templates/travel-concierge/client.tsx +161 -0
- package/dist/templates/travel-concierge/routing.ts +138 -0
- package/dist/templates/travel-concierge/shared.ts +547 -0
- package/dist/templates/travel-concierge/system-prompt.md +24 -0
- package/dist/templates/travel-concierge/tools/book_car_rental.ts +20 -0
- package/dist/templates/travel-concierge/tools/book_excursion.ts +18 -0
- package/dist/templates/travel-concierge/tools/book_hotel.ts +20 -0
- package/dist/templates/travel-concierge/tools/cancel_action.ts +7 -0
- package/dist/templates/travel-concierge/tools/cancel_ticket.ts +16 -0
- package/dist/templates/travel-concierge/tools/complete_or_escalate.ts +7 -0
- package/dist/templates/travel-concierge/tools/confirm_action.ts +7 -0
- package/dist/templates/travel-concierge/tools/lookup_booking.ts +35 -0
- package/dist/templates/travel-concierge/tools/search_car_rentals.ts +33 -0
- package/dist/templates/travel-concierge/tools/search_excursions.ts +37 -0
- package/dist/templates/travel-concierge/tools/search_flights.ts +43 -0
- package/dist/templates/travel-concierge/tools/search_hotels.ts +36 -0
- package/dist/templates/travel-concierge/tools/to_car_rental_assistant.ts +11 -0
- package/dist/templates/travel-concierge/tools/to_excursion_assistant.ts +11 -0
- package/dist/templates/travel-concierge/tools/to_flight_assistant.ts +11 -0
- package/dist/templates/travel-concierge/tools/to_hotel_assistant.ts +11 -0
- package/dist/templates/travel-concierge/tools/update_ticket.ts +22 -0
- package/dist/templates/web-researcher/agent.ts +0 -2
- package/dist/templates/web-researcher/system-prompt.md +10 -0
- package/dist/{test-2LWBcXvY.mjs → test-B6ZBxSpk.mjs} +2 -2
- package/dist/typecheck.mjs +17 -15
- package/dist/worker-bundler-CIdDhZ0c.mjs +398 -0
- package/dist/worker-bundler.d.ts +14 -0
- package/dist/worker-bundler.mjs +1 -108
- package/dist/workflow-B-O97AqI.mjs +125 -0
- package/dist/workflow-bundler.d.ts +133 -0
- package/dist/workflow.d.ts +67 -0
- package/package.json +13 -9
- package/dist/build-DQJ1ZSm9.mjs +0 -39
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The durable half of the redline desk: write, critique, revise — in a loop
|
|
3
|
+
* whose length the CRITIC decides.
|
|
4
|
+
*
|
|
5
|
+
* The rules a `"use workflow"` body lives under are spelled out in
|
|
6
|
+
* `research-workflow/workflows/research.ts` and `link-digest/workflows/digest.ts`:
|
|
7
|
+
* the body is replayed from the top on every resume, so it holds no live handle
|
|
8
|
+
* and makes no undurable decision, and a step's arguments and result cross a
|
|
9
|
+
* queue. Read those first. What THIS one adds is the shape neither of them has:
|
|
10
|
+
* **a loop whose exit is decided at run time**.
|
|
11
|
+
*
|
|
12
|
+
* ## A journaled result is what makes a data-dependent loop legal
|
|
13
|
+
*
|
|
14
|
+
* `transcription-workflow` derives its fan-out's WIDTH from a step's journaled
|
|
15
|
+
* result, and its module doc gives the rule. This is the same rule spent on a
|
|
16
|
+
* different thing: `critique` returns a verdict, the body breaks on it, and a
|
|
17
|
+
* replay reads that verdict back out of the journal and takes the same branch.
|
|
18
|
+
* Deciding it any other way — a clock, a random draw, a re-read of something
|
|
19
|
+
* outside the run — would let a replay diverge, and the DevKit correlates
|
|
20
|
+
* journal entries to step calls by issue order, so a divergent branch is a
|
|
21
|
+
* `ReplayDivergenceError` rather than a slightly different essay.
|
|
22
|
+
*
|
|
23
|
+
* ## Why durability earns its keep here, specifically
|
|
24
|
+
*
|
|
25
|
+
* A three-round redline is up to seven model calls in sequence, each of them
|
|
26
|
+
* long-form. That is minutes, not seconds — nobody is going to sit on a phone
|
|
27
|
+
* for it, which is why this is a workflow app rather than a voice agent — and
|
|
28
|
+
* it is exactly the work you do not want to redo: a rate limit in round three
|
|
29
|
+
* replays rounds one and two from the journal for free and re-issues only the
|
|
30
|
+
* call that failed. Each stage is its own step for that reason, not because
|
|
31
|
+
* three functions read more tidily than one.
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
import { throwStepError } from "@alexkroman1/aai/step-errors";
|
|
35
|
+
import { report, stepGenerate, stepGenerateJson } from "@alexkroman1/aai/utils";
|
|
36
|
+
import { FatalError } from "workflow";
|
|
37
|
+
import { z } from "zod";
|
|
38
|
+
import { CRITIC_SYSTEM, REVISER_SYSTEM, WRITER_SYSTEM } from "./prompts.ts";
|
|
39
|
+
|
|
40
|
+
/** Shortest brief worth writing from. Below this the piece would be invention. */
|
|
41
|
+
export const MIN_BRIEF_CHARS = 20;
|
|
42
|
+
|
|
43
|
+
/** Notes one critique may return — their prompt asks for three at most. */
|
|
44
|
+
export const MAX_NOTES = 3;
|
|
45
|
+
|
|
46
|
+
/** What the form collects, once the page has mapped its fields. */
|
|
47
|
+
export interface RedlineInput {
|
|
48
|
+
brief: string;
|
|
49
|
+
audience: string;
|
|
50
|
+
/** Critique-and-revise rounds this run may spend. Their `should_continue` cap. */
|
|
51
|
+
rounds: number;
|
|
52
|
+
/** Points the piece must cover. An ARRAY, which is why the page writes that
|
|
53
|
+
* field by hand — `<WorkflowFields>` renders scalars only. */
|
|
54
|
+
mustCover: string[];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface Critique {
|
|
58
|
+
verdict: "ship" | "revise";
|
|
59
|
+
/** 1–10, for the page. Nothing branches on it — the verdict is the decision. */
|
|
60
|
+
score: number;
|
|
61
|
+
notes: string[];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* What the critic is asked to reply with, as something that CHECKS.
|
|
66
|
+
*
|
|
67
|
+
* `stepGenerateJson` validates against this, so a reply that missed is a plain
|
|
68
|
+
* throw and therefore a retry — where the hand-written `isCritique` guard this
|
|
69
|
+
* replaces had to restate every field's type by hand. The VERDICT is strict
|
|
70
|
+
* because the body branches on it; the score is deliberately not, and is
|
|
71
|
+
* clamped at the call site instead (see `critiqueDraft`).
|
|
72
|
+
*/
|
|
73
|
+
const CritiqueReply = z.object({
|
|
74
|
+
verdict: z.enum(["ship", "revise"]),
|
|
75
|
+
score: z.number(),
|
|
76
|
+
notes: z.array(z.string()),
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
/** One round, as the page renders it and the journal records it. */
|
|
80
|
+
export interface Round {
|
|
81
|
+
round: number;
|
|
82
|
+
critique: Critique;
|
|
83
|
+
/** Absent on the round that shipped: nothing was revised after it. */
|
|
84
|
+
revisedWords?: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Write, then critique and revise until the critic ships it or the rounds run
|
|
89
|
+
* out.
|
|
90
|
+
*
|
|
91
|
+
* Whatever this returns is what a completed run reports as `output`, so it is
|
|
92
|
+
* the page's render model — and `WorkflowOutputOf<typeof redline>` in
|
|
93
|
+
* `client.tsx` is that type, derived rather than restated.
|
|
94
|
+
*/
|
|
95
|
+
export async function redlineFlow(input: RedlineInput) {
|
|
96
|
+
"use workflow";
|
|
97
|
+
|
|
98
|
+
let draft = await writeDraft(input);
|
|
99
|
+
const rounds: Round[] = [];
|
|
100
|
+
let shipped = false;
|
|
101
|
+
|
|
102
|
+
for (let round = 1; round <= input.rounds; round++) {
|
|
103
|
+
const critique = await critiqueDraft(draft, input, round);
|
|
104
|
+
|
|
105
|
+
if (critique.verdict === "ship") {
|
|
106
|
+
// The break is decided by a STEP'S JOURNALED RESULT, which is what makes
|
|
107
|
+
// it replay-stable — see the module doc.
|
|
108
|
+
rounds.push({ round, critique });
|
|
109
|
+
shipped = true;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
draft = await reviseDraft(draft, critique, input, round);
|
|
114
|
+
rounds.push({ round, critique, revisedWords: countWords(draft) });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return {
|
|
118
|
+
draft,
|
|
119
|
+
words: countWords(draft),
|
|
120
|
+
roundsRun: rounds.length,
|
|
121
|
+
/** True when the CRITIC stopped the loop, false when the budget did. */
|
|
122
|
+
shipped,
|
|
123
|
+
rounds,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Their `generation_node`, first pass. */
|
|
128
|
+
export async function writeDraft(input: RedlineInput): Promise<string> {
|
|
129
|
+
"use step";
|
|
130
|
+
|
|
131
|
+
if (input.brief.trim().length < MIN_BRIEF_CHARS) {
|
|
132
|
+
// Fatal rather than retryable: the same brief is the same brief on every
|
|
133
|
+
// attempt, and four more model calls will not make it longer.
|
|
134
|
+
//
|
|
135
|
+
// Not redundant with the schema's `.min(20)`, which counts CHARACTERS: a
|
|
136
|
+
// brief of twenty spaces passes validation at `start()` and arrives here
|
|
137
|
+
// as nothing to write from.
|
|
138
|
+
throw new FatalError(
|
|
139
|
+
`The brief is too short to write from — give at least ${MIN_BRIEF_CHARS} characters of it.`,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
await report(`Writing the first draft for ${input.audience}.`);
|
|
144
|
+
// No empty-reply guard here or in `reviseDraft`, and that is not an omission:
|
|
145
|
+
// `stepGenerate` already refuses an empty completion, as a RETRYABLE
|
|
146
|
+
// `StepGenerateError` — which is the right answer, and one a hand-written
|
|
147
|
+
// check would have to re-derive.
|
|
148
|
+
const draft = await ask(briefBlock(input), { system: WRITER_SYSTEM });
|
|
149
|
+
return draft.trim();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Their `reflection_node`: grade the draft against its brief.
|
|
154
|
+
*
|
|
155
|
+
* Its own step rather than part of the revision, because the two fail
|
|
156
|
+
* differently and because this one's RESULT is what the body branches on — a
|
|
157
|
+
* revision folded into the same step would put the decision and the expensive
|
|
158
|
+
* rewrite behind one journal entry.
|
|
159
|
+
*/
|
|
160
|
+
export async function critiqueDraft(
|
|
161
|
+
draft: string,
|
|
162
|
+
input: RedlineInput,
|
|
163
|
+
round: number,
|
|
164
|
+
): Promise<Critique> {
|
|
165
|
+
"use step";
|
|
166
|
+
|
|
167
|
+
await report(`Round ${round}: reading it back critically.`);
|
|
168
|
+
// `stepGenerateJson` owns the fence, the parse, the non-object case and the
|
|
169
|
+
// shape — and throws PLAINLY when any of them misses, unlike the fatal one
|
|
170
|
+
// above: a model that answered with prose may well obey on the next attempt.
|
|
171
|
+
const parsed = await stepGenerateJson(`${briefBlock(input)}\n\nThe submission:\n${draft}`, {
|
|
172
|
+
schema: CritiqueReply,
|
|
173
|
+
system: CRITIC_SYSTEM,
|
|
174
|
+
}).catch(throwStepError);
|
|
175
|
+
|
|
176
|
+
const critique: Critique = {
|
|
177
|
+
verdict: parsed.verdict,
|
|
178
|
+
// The SCORE is still clamped here rather than in the schema: a model that
|
|
179
|
+
// answered 11 has still answered, and the number is worth keeping at the
|
|
180
|
+
// edge of the range rather than costing a whole retry.
|
|
181
|
+
score: clampScore(parsed.score),
|
|
182
|
+
notes: parsed.notes.slice(0, MAX_NOTES),
|
|
183
|
+
};
|
|
184
|
+
await report(
|
|
185
|
+
critique.verdict === "ship"
|
|
186
|
+
? `Round ${round}: the critic would ship it (${critique.score}/10).`
|
|
187
|
+
: `Round ${round}: ${critique.notes.length} note(s) to address (${critique.score}/10).`,
|
|
188
|
+
);
|
|
189
|
+
return critique;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Their generation node re-entered with the critique. */
|
|
193
|
+
export async function reviseDraft(
|
|
194
|
+
draft: string,
|
|
195
|
+
critique: Critique,
|
|
196
|
+
input: RedlineInput,
|
|
197
|
+
round: number,
|
|
198
|
+
): Promise<string> {
|
|
199
|
+
"use step";
|
|
200
|
+
|
|
201
|
+
await report(`Round ${round}: revising.`);
|
|
202
|
+
const revised = await ask(
|
|
203
|
+
[
|
|
204
|
+
briefBlock(input),
|
|
205
|
+
`Your current draft:\n${draft}`,
|
|
206
|
+
`The critique:\n${critique.notes.map((note, index) => `${index + 1}. ${note}`).join("\n")}`,
|
|
207
|
+
].join("\n\n"),
|
|
208
|
+
{ system: REVISER_SYSTEM },
|
|
209
|
+
);
|
|
210
|
+
return revised.trim();
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ---- Pure helpers -----------------------------------------------------------
|
|
214
|
+
|
|
215
|
+
/** The brief as every stage restates it, so the three cannot drift apart. */
|
|
216
|
+
export function briefBlock(input: RedlineInput): string {
|
|
217
|
+
const must =
|
|
218
|
+
input.mustCover.length > 0
|
|
219
|
+
? `Must cover:\n${input.mustCover.map((point) => `- ${point}`).join("\n")}`
|
|
220
|
+
: "Must cover: nothing specific was named.";
|
|
221
|
+
return [`Brief: ${input.brief}`, `Audience: ${input.audience}`, must].join("\n\n");
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export function countWords(text: string): number {
|
|
225
|
+
const trimmed = text.trim();
|
|
226
|
+
return trimmed.length === 0 ? 0 : trimmed.split(/\s+/).length;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Scores arrive from a model, so they arrive out of range often enough. */
|
|
230
|
+
export function clampScore(score: number): number {
|
|
231
|
+
if (!Number.isFinite(score)) return 0;
|
|
232
|
+
return Math.min(10, Math.max(1, Math.round(score)));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// ---- The model call ---------------------------------------------------------
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* `stepGenerate`, with this desk's retry POLICY on top.
|
|
239
|
+
*
|
|
240
|
+
* The SDK classifies the gateway's failure (`StepGenerateError.retryable`) and
|
|
241
|
+
* stops there: whether a terminal failure should burn the step's remaining
|
|
242
|
+
* attempts is the caller's call. `throwStepError`
|
|
243
|
+
* (`@alexkroman1/aai/step-errors`) is that call made one way — terminal stays
|
|
244
|
+
* terminal, and a rate limit becomes a `RetryableError` carrying the delay the
|
|
245
|
+
* gateway itself named, which beats `RetryableError`'s own one-second default.
|
|
246
|
+
*
|
|
247
|
+
* This desk used to carry that mapping itself, as did `research-workflow` and
|
|
248
|
+
* `link-digest`; it is one import now, and the delay is no longer the one line
|
|
249
|
+
* only this template remembered.
|
|
250
|
+
*/
|
|
251
|
+
async function ask(prompt: string, opts: { system: string }): Promise<string> {
|
|
252
|
+
return await stepGenerate(prompt, opts).catch(throwStepError);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/** A rate limit — and a model that ignored the format — are both expected. */
|
|
256
|
+
critiqueDraft.maxRetries = 5;
|
|
257
|
+
writeDraft.maxRetries = 3;
|
|
258
|
+
reviseDraft.maxRetries = 3;
|