@warlock.js/ai 4.5.0 → 4.6.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 (159) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/cjs/index.cjs +20 -1
  3. package/cjs/{src-DFibP2FQ.cjs → src-Bmajk4Qg.cjs} +1 -1
  4. package/cjs/{src-C02yzsLs.cjs → src-OZyDYHxm.cjs} +2789 -691
  5. package/cjs/src-OZyDYHxm.cjs.map +1 -0
  6. package/esm/agent/agent-config.type.d.mts +29 -0
  7. package/esm/agent/agent-config.type.d.mts.map +1 -1
  8. package/esm/agent/agent.d.mts.map +1 -1
  9. package/esm/agent/agent.mjs +126 -7
  10. package/esm/agent/agent.mjs.map +1 -1
  11. package/esm/agent/signature.mjs +57 -0
  12. package/esm/agent/signature.mjs.map +1 -0
  13. package/esm/agent/snapshot.mjs +101 -0
  14. package/esm/agent/snapshot.mjs.map +1 -0
  15. package/esm/ai-openai/src/image.mjs +5 -0
  16. package/esm/ai-openai/src/index.mjs +3 -0
  17. package/esm/ai-openai/src/sdk.mjs +3 -0
  18. package/esm/ai-openai/src/speech.mjs +5 -0
  19. package/esm/ai-openai/src/transcription.mjs +6 -0
  20. package/esm/ai-openai/src/utils/index.mjs +1 -0
  21. package/esm/ai-openai/src/utils/to-openai-messages.mjs +3 -0
  22. package/esm/ai.d.mts +45 -0
  23. package/esm/ai.d.mts.map +1 -1
  24. package/esm/ai.mjs +37 -1
  25. package/esm/ai.mjs.map +1 -1
  26. package/esm/contracts/agent/agent-options.type.d.mts +22 -2
  27. package/esm/contracts/agent/agent-options.type.d.mts.map +1 -1
  28. package/esm/contracts/agent/agent-snapshot.type.d.mts +90 -0
  29. package/esm/contracts/agent/agent-snapshot.type.d.mts.map +1 -0
  30. package/esm/contracts/agent/agent.contract.d.mts +29 -1
  31. package/esm/contracts/agent/agent.contract.d.mts.map +1 -1
  32. package/esm/contracts/agent/index.d.mts +2 -1
  33. package/esm/contracts/image-model.contract.d.mts +156 -0
  34. package/esm/contracts/image-model.contract.d.mts.map +1 -0
  35. package/esm/contracts/index.d.mts +8 -3
  36. package/esm/contracts/planner/index.d.mts +3 -2
  37. package/esm/contracts/planner/planner-config.type.d.mts +30 -0
  38. package/esm/contracts/planner/planner-config.type.d.mts.map +1 -1
  39. package/esm/contracts/planner/planner-execute-options.type.d.mts +13 -1
  40. package/esm/contracts/planner/planner-execute-options.type.d.mts.map +1 -1
  41. package/esm/contracts/planner/planner-snapshot.type.d.mts +77 -0
  42. package/esm/contracts/planner/planner-snapshot.type.d.mts.map +1 -0
  43. package/esm/contracts/planner/planner.contract.d.mts +21 -1
  44. package/esm/contracts/planner/planner.contract.d.mts.map +1 -1
  45. package/esm/contracts/result/base-report.type.d.mts +1 -1
  46. package/esm/contracts/result/base-report.type.d.mts.map +1 -1
  47. package/esm/contracts/result/base-report.type.mjs.map +1 -1
  48. package/esm/contracts/sdk-adapter.contract.d.mts +37 -0
  49. package/esm/contracts/sdk-adapter.contract.d.mts.map +1 -1
  50. package/esm/contracts/speech-model.contract.d.mts +97 -0
  51. package/esm/contracts/speech-model.contract.d.mts.map +1 -0
  52. package/esm/contracts/transcription-model.contract.d.mts +101 -0
  53. package/esm/contracts/transcription-model.contract.d.mts.map +1 -0
  54. package/esm/errors/agent-drift-error.d.mts +32 -0
  55. package/esm/errors/agent-drift-error.d.mts.map +1 -0
  56. package/esm/errors/agent-drift-error.mjs +31 -0
  57. package/esm/errors/agent-drift-error.mjs.map +1 -0
  58. package/esm/errors/error-code.type.d.mts +1 -1
  59. package/esm/errors/index.d.mts +2 -0
  60. package/esm/errors/index.mjs +2 -0
  61. package/esm/errors/planner-drift-error.d.mts +34 -0
  62. package/esm/errors/planner-drift-error.d.mts.map +1 -0
  63. package/esm/errors/planner-drift-error.mjs +33 -0
  64. package/esm/errors/planner-drift-error.mjs.map +1 -0
  65. package/esm/image/image-cost.d.mts +32 -0
  66. package/esm/image/image-cost.d.mts.map +1 -0
  67. package/esm/image/image-cost.mjs +55 -0
  68. package/esm/image/image-cost.mjs.map +1 -0
  69. package/esm/image/image.d.mts +92 -0
  70. package/esm/image/image.d.mts.map +1 -0
  71. package/esm/image/image.mjs +113 -0
  72. package/esm/image/image.mjs.map +1 -0
  73. package/esm/image/index.mjs +4 -0
  74. package/esm/index.d.mts +26 -4
  75. package/esm/index.mjs +20 -1
  76. package/esm/mock/index.d.mts +3 -0
  77. package/esm/mock/index.mjs +3 -0
  78. package/esm/mock/mock-config.type.d.mts +22 -0
  79. package/esm/mock/mock-config.type.d.mts.map +1 -1
  80. package/esm/mock/mock-image-model.d.mts +41 -0
  81. package/esm/mock/mock-image-model.d.mts.map +1 -0
  82. package/esm/mock/mock-image-model.mjs +52 -0
  83. package/esm/mock/mock-image-model.mjs.map +1 -0
  84. package/esm/mock/mock-sdk.d.mts +7 -1
  85. package/esm/mock/mock-sdk.d.mts.map +1 -1
  86. package/esm/mock/mock-sdk.mjs +27 -0
  87. package/esm/mock/mock-sdk.mjs.map +1 -1
  88. package/esm/mock/mock-speech-model.d.mts +31 -0
  89. package/esm/mock/mock-speech-model.d.mts.map +1 -0
  90. package/esm/mock/mock-speech-model.mjs +39 -0
  91. package/esm/mock/mock-speech-model.mjs.map +1 -0
  92. package/esm/mock/mock-transcription-model.d.mts +32 -0
  93. package/esm/mock/mock-transcription-model.d.mts.map +1 -0
  94. package/esm/mock/mock-transcription-model.mjs +36 -0
  95. package/esm/mock/mock-transcription-model.mjs.map +1 -0
  96. package/esm/planner/planner-run.d.mts +8 -0
  97. package/esm/planner/planner-run.d.mts.map +1 -1
  98. package/esm/planner/planner-run.mjs +161 -6
  99. package/esm/planner/planner-run.mjs.map +1 -1
  100. package/esm/planner/planner.d.mts.map +1 -1
  101. package/esm/planner/planner.mjs +25 -1
  102. package/esm/planner/planner.mjs.map +1 -1
  103. package/esm/planner/snapshot.mjs +95 -0
  104. package/esm/planner/snapshot.mjs.map +1 -0
  105. package/esm/rag/index.d.mts +7 -0
  106. package/esm/rag/index.mjs +7 -0
  107. package/esm/rag/loaders/errors.d.mts +19 -0
  108. package/esm/rag/loaders/errors.d.mts.map +1 -0
  109. package/esm/rag/loaders/errors.mjs +25 -0
  110. package/esm/rag/loaders/errors.mjs.map +1 -0
  111. package/esm/rag/loaders/index.mjs +7 -0
  112. package/esm/rag/loaders/load-html.d.mts +26 -0
  113. package/esm/rag/loaders/load-html.d.mts.map +1 -0
  114. package/esm/rag/loaders/load-html.mjs +138 -0
  115. package/esm/rag/loaders/load-html.mjs.map +1 -0
  116. package/esm/rag/loaders/load-pdf.d.mts +38 -0
  117. package/esm/rag/loaders/load-pdf.d.mts.map +1 -0
  118. package/esm/rag/loaders/load-pdf.mjs +150 -0
  119. package/esm/rag/loaders/load-pdf.mjs.map +1 -0
  120. package/esm/rag/loaders/load-text.d.mts +47 -0
  121. package/esm/rag/loaders/load-text.d.mts.map +1 -0
  122. package/esm/rag/loaders/load-text.mjs +60 -0
  123. package/esm/rag/loaders/load-text.mjs.map +1 -0
  124. package/esm/rag/loaders/load-web.d.mts +42 -0
  125. package/esm/rag/loaders/load-web.d.mts.map +1 -0
  126. package/esm/rag/loaders/load-web.mjs +89 -0
  127. package/esm/rag/loaders/load-web.mjs.map +1 -0
  128. package/esm/rag/loaders/loader.type.d.mts +89 -0
  129. package/esm/rag/loaders/loader.type.d.mts.map +1 -0
  130. package/esm/rag/store/pg-vector-store.d.mts +139 -0
  131. package/esm/rag/store/pg-vector-store.d.mts.map +1 -0
  132. package/esm/rag/store/pg-vector-store.mjs +328 -0
  133. package/esm/rag/store/pg-vector-store.mjs.map +1 -0
  134. package/esm/speech/index.mjs +3 -0
  135. package/esm/speech/speech.d.mts +65 -0
  136. package/esm/speech/speech.d.mts.map +1 -0
  137. package/esm/speech/speech.mjs +123 -0
  138. package/esm/speech/speech.mjs.map +1 -0
  139. package/esm/supervisor/entries.mjs +2 -2
  140. package/esm/supervisor/entries.mjs.map +1 -1
  141. package/esm/transcribe/audio-input.d.mts +47 -0
  142. package/esm/transcribe/audio-input.d.mts.map +1 -0
  143. package/esm/transcribe/audio-input.mjs +84 -0
  144. package/esm/transcribe/audio-input.mjs.map +1 -0
  145. package/esm/transcribe/index.mjs +4 -0
  146. package/esm/transcribe/transcribe.d.mts +64 -0
  147. package/esm/transcribe/transcribe.d.mts.map +1 -0
  148. package/esm/transcribe/transcribe.mjs +128 -0
  149. package/esm/transcribe/transcribe.mjs.map +1 -0
  150. package/llms-full.txt +753 -0
  151. package/llms.txt +5 -0
  152. package/package.json +3 -3
  153. package/skills/README.md +4 -0
  154. package/skills/durable-agent-runs/SKILL.md +135 -0
  155. package/skills/generate-images/SKILL.md +138 -0
  156. package/skills/generate-speech/SKILL.md +139 -0
  157. package/skills/rag-loaders-and-stores/SKILL.md +164 -0
  158. package/skills/transcribe-audio/SKILL.md +157 -0
  159. package/cjs/src-C02yzsLs.cjs.map +0 -1
@@ -0,0 +1,101 @@
1
+ import { Usage } from "./result/usage.type.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/contracts/transcription-model.contract.d.ts
4
+ /**
5
+ * USD pricing for a speech-to-text (transcription) model. STT providers
6
+ * meter one of two ways; this single shape covers both so the cost
7
+ * folds into the same `Usage.cost` rollup as text / image / speech:
8
+ *
9
+ * - **Per-minute** (OpenAI `whisper-1`): billed per minute of input
10
+ * audio. Set `perMinute` (USD per audio-minute).
11
+ * - **Token-metered** (OpenAI `gpt-4o-transcribe`): billed per
12
+ * input/output token. Set `input` / `output` (USD per 1M tokens).
13
+ *
14
+ * Per-minute wins when both are set. Nothing set → `Usage.cost` stays
15
+ * `undefined`.
16
+ *
17
+ * @example
18
+ * const pricing: TranscriptionModelPricing = { perMinute: 0.006 }; // whisper-1
19
+ */
20
+ type TranscriptionModelPricing = {
21
+ /** USD per minute of input audio — per-minute-metered STT. */perMinute?: number; /** USD per 1M input (audio) tokens — token-metered STT. */
22
+ input?: number; /** USD per 1M output (text) tokens — token-metered STT. */
23
+ output?: number;
24
+ };
25
+ /** One timestamped segment of a transcription (when the provider returns segments). */
26
+ type TranscriptionSegment = {
27
+ text: string; /** Segment start time in seconds. */
28
+ start?: number; /** Segment end time in seconds. */
29
+ end?: number;
30
+ };
31
+ /**
32
+ * The audio to transcribe — inlined base64 bytes with an explicit IANA
33
+ * media type, plus an optional filename (some providers infer the codec
34
+ * from the extension). Read a file to base64 before calling, or pass
35
+ * in-memory bytes; this keeps the verb provider-neutral and
36
+ * serializable (no `fs` coupling in core).
37
+ *
38
+ * @example
39
+ * const audio: AudioInput = { base64: buf.toString("base64"), mediaType: "audio/mpeg", filename: "note.mp3" };
40
+ */
41
+ type AudioInput = {
42
+ base64: string;
43
+ mediaType: string;
44
+ filename?: string;
45
+ };
46
+ /** Options for a single {@link TranscriptionModelContract.transcribe} request. */
47
+ type TranscribeOptions = {
48
+ /** BCP-47 language hint (e.g. `"en"`) — improves accuracy + latency. */language?: string; /** Optional priming prompt (spelling/style hints). */
49
+ prompt?: string; /** Provider response format override (e.g. `"verbose_json"` for segments + duration). */
50
+ format?: string; /** Cancellation handle wired into the provider request where supported. */
51
+ signal?: AbortSignal; /** Provider-specific escape hatch — forwarded verbatim. */
52
+ [key: string]: unknown;
53
+ };
54
+ /**
55
+ * Raw result of a {@link TranscriptionModelContract.transcribe} call —
56
+ * low-level (throws a typed `AIError` on failure). The never-throws
57
+ * envelope is added by the `ai.transcribe()` facade verb.
58
+ */
59
+ type TranscriptionResponse = {
60
+ /** The full transcript text. */text: string; /** Timestamped segments when the provider returns them (verbose mode). */
61
+ segments?: TranscriptionSegment[]; /** Input audio duration in seconds — drives per-minute cost when present. */
62
+ durationSeconds?: number;
63
+ /**
64
+ * Token usage when the provider meters per token (gpt-4o-transcribe);
65
+ * `{ input: 0, output: 0, total: 0 }` for per-minute-metered models,
66
+ * whose spend is priced from {@link durationSeconds}.
67
+ */
68
+ usage: Usage;
69
+ };
70
+ /**
71
+ * Provider-neutral contract for a speech-to-text model — the inverse of
72
+ * {@link SpeechModelContract}. Produced by an adapter's optional
73
+ * `transcribe?(config)` factory and consumed by `ai.transcribe()`.
74
+ *
75
+ * @example
76
+ * const stt = openai.transcribe({ name: "whisper-1" });
77
+ * const { text } = await stt.transcribe({ base64, mediaType: "audio/mpeg" });
78
+ */
79
+ interface TranscriptionModelContract {
80
+ /** Model identifier (e.g. `"whisper-1"`, `"gpt-4o-transcribe"`). */
81
+ readonly name: string;
82
+ /** Provider this model belongs to (e.g. `"openai"`). */
83
+ readonly provider: string;
84
+ /** Per-minute or per-token USD pricing; folded into `Usage.cost` by `ai.transcribe()`. */
85
+ readonly pricing?: TranscriptionModelPricing;
86
+ /** Transcribe audio to text. Throws a typed `AIError` on failure. */
87
+ transcribe(audio: AudioInput, options?: TranscribeOptions): Promise<TranscriptionResponse>;
88
+ }
89
+ /**
90
+ * Configuration passed to an adapter's `transcribe()` factory. Mirrors
91
+ * {@link SpeechModelConfig}: `name` + an optional per-model `pricing`
92
+ * override, with provider-specific keys on the index signature.
93
+ */
94
+ type TranscriptionModelConfig = {
95
+ name: string; /** Per-model USD pricing override; wins over the SDK-level registry. */
96
+ pricing?: TranscriptionModelPricing;
97
+ [key: string]: unknown;
98
+ };
99
+ //#endregion
100
+ export { AudioInput, TranscribeOptions, TranscriptionModelConfig, TranscriptionModelContract, TranscriptionModelPricing, TranscriptionResponse, TranscriptionSegment };
101
+ //# sourceMappingURL=transcription-model.contract.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcription-model.contract.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/contracts/transcription-model.contract.ts"],"mappings":";;;;;AAkBA;;;;;;;;AAMQ;AAIR;;;;;KAVY,yBAAA;EAeV,8DAbA,SAAA,WAaG;EAXH,KAAA,WAwBoB;EAtBpB,MAAA;AAAA;;KAIU,oBAAA;EACV,IAAA,UAoBQ;EAlBR,KAAA,WAsBU;EApBV,GAAA;AAAA;;;;;;;;;AA8BY;AAQd;KAzBY,UAAA;EACV,MAAA;EACA,SAAA;EACA,QAAA;AAAA;;KAIU,iBAAA;EA8BV,wEA5BA,QAAA,WA4BY;EA1BZ,MAAA,WAsCe;EApCf,MAAA;EAEA,MAAA,GAAS,WAAW,EA2CF;EAAA,CAzCjB,GAAA;AAAA;;;;;;KAQS,qBAAA;EA8BS,gCA5BnB,IAAA,UA+BkB;EA7BlB,QAAA,GAAW,oBAAA,IA6B6B;EA3BxC,eAAA;EA2B4D;;;AAA6B;AAQ3F;EA7BE,KAAA,EAAO,KAAK;AAAA;;;;;;;AAiCA;;;UArBG,0BAAA;;WAEN,IAAA;;WAEA,QAAA;;WAEA,OAAA,GAAU,yBAAA;;EAGnB,UAAA,CAAW,KAAA,EAAO,UAAA,EAAY,OAAA,GAAU,iBAAA,GAAoB,OAAA,CAAQ,qBAAA;AAAA;;;;;;KAQ1D,wBAAA;EACV,IAAA;EAEA,OAAA,GAAU,yBAAyB;EAAA,CAClC,GAAA;AAAA"}
@@ -0,0 +1,32 @@
1
+ import { ErrorCategory } from "./error-category.type.mjs";
2
+ import { AIErrorOptions } from "./ai-error.mjs";
3
+ import { AgentExecutionError } from "./agent-execution-error.mjs";
4
+
5
+ //#region ../@warlock.js/ai/src/errors/agent-drift-error.d.ts
6
+ type AgentDriftErrorOptions = AIErrorOptions & {
7
+ /** Signature recorded on the snapshot being resumed. */savedSignature: string; /** Signature computed from the current agent definition. */
8
+ currentSignature: string;
9
+ runId: string;
10
+ };
11
+ /**
12
+ * `agent.resume(runId)` loaded a durable snapshot whose structural
13
+ * fingerprint does not match the current agent definition (model +
14
+ * provider + sorted tool names + maxTrips + output presence + version).
15
+ * The resume is refused — no trip runs — and the user decides how to
16
+ * recover: discard the snapshot, migrate manually, or call
17
+ * `resume(runId, { force: true })` to bypass the check.
18
+ *
19
+ * Mirrors `SupervisorDriftError` / `WorkflowDriftError` — same rationale,
20
+ * different primitive. Thrown (not returned on `result.error`) because a
21
+ * drifted resume never produces a valid run.
22
+ */
23
+ declare class AgentDriftError extends AgentExecutionError {
24
+ static readonly defaultCategory: ErrorCategory;
25
+ readonly savedSignature: string;
26
+ readonly currentSignature: string;
27
+ readonly runId: string;
28
+ constructor(message: string, options: AgentDriftErrorOptions);
29
+ }
30
+ //#endregion
31
+ export { AgentDriftError, AgentDriftErrorOptions };
32
+ //# sourceMappingURL=agent-drift-error.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-drift-error.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/errors/agent-drift-error.ts"],"mappings":";;;;;KAIY,sBAAA,GAAyB,cAAc;0DAEjD,cAAA,UAFgC;EAIhC,gBAAA;EACA,KAAA;AAAA;;;;;AAAK;AAeP;;;;;;;cAAa,eAAA,SAAwB,mBAAA;EAAA,gBACZ,eAAA,EAAiB,aAAA;EAAA,SAExB,cAAA;EAAA,SACA,gBAAA;EAAA,SACA,KAAA;cAEG,OAAA,UAAiB,OAAA,EAAS,sBAAA;AAAA"}
@@ -0,0 +1,31 @@
1
+ import { AgentExecutionError } from "./agent-execution-error.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/errors/agent-drift-error.ts
4
+ /**
5
+ * `agent.resume(runId)` loaded a durable snapshot whose structural
6
+ * fingerprint does not match the current agent definition (model +
7
+ * provider + sorted tool names + maxTrips + output presence + version).
8
+ * The resume is refused — no trip runs — and the user decides how to
9
+ * recover: discard the snapshot, migrate manually, or call
10
+ * `resume(runId, { force: true })` to bypass the check.
11
+ *
12
+ * Mirrors `SupervisorDriftError` / `WorkflowDriftError` — same rationale,
13
+ * different primitive. Thrown (not returned on `result.error`) because a
14
+ * drifted resume never produces a valid run.
15
+ */
16
+ var AgentDriftError = class extends AgentExecutionError {
17
+ static {
18
+ this.defaultCategory = "drift";
19
+ }
20
+ constructor(message, options) {
21
+ super(message, options, "AGENT_DRIFT");
22
+ this.name = "AgentDriftError";
23
+ this.savedSignature = options.savedSignature;
24
+ this.currentSignature = options.currentSignature;
25
+ this.runId = options.runId;
26
+ }
27
+ };
28
+
29
+ //#endregion
30
+ export { AgentDriftError };
31
+ //# sourceMappingURL=agent-drift-error.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-drift-error.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/errors/agent-drift-error.ts"],"sourcesContent":["import type { AIErrorOptions } from \"./ai-error\";\nimport { AgentExecutionError } from \"./agent-execution-error\";\nimport type { ErrorCategory } from \"./error-category.type\";\n\nexport type AgentDriftErrorOptions = AIErrorOptions & {\n /** Signature recorded on the snapshot being resumed. */\n savedSignature: string;\n /** Signature computed from the current agent definition. */\n currentSignature: string;\n runId: string;\n};\n\n/**\n * `agent.resume(runId)` loaded a durable snapshot whose structural\n * fingerprint does not match the current agent definition (model +\n * provider + sorted tool names + maxTrips + output presence + version).\n * The resume is refused — no trip runs — and the user decides how to\n * recover: discard the snapshot, migrate manually, or call\n * `resume(runId, { force: true })` to bypass the check.\n *\n * Mirrors `SupervisorDriftError` / `WorkflowDriftError` — same rationale,\n * different primitive. Thrown (not returned on `result.error`) because a\n * drifted resume never produces a valid run.\n */\nexport class AgentDriftError extends AgentExecutionError {\n public static readonly defaultCategory: ErrorCategory = \"drift\";\n\n public readonly savedSignature: string;\n public readonly currentSignature: string;\n public readonly runId: string;\n\n public constructor(message: string, options: AgentDriftErrorOptions) {\n super(message, options, \"AGENT_DRIFT\");\n this.name = \"AgentDriftError\";\n this.savedSignature = options.savedSignature;\n this.currentSignature = options.currentSignature;\n this.runId = options.runId;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AAwBA,IAAa,kBAAb,cAAqC,oBAAoB;;yBACC;;CAMxD,AAAO,YAAY,SAAiB,SAAiC;EACnE,MAAM,SAAS,SAAS,aAAa;EACrC,KAAK,OAAO;EACZ,KAAK,iBAAiB,QAAQ;EAC9B,KAAK,mBAAmB,QAAQ;EAChC,KAAK,QAAQ,QAAQ;CACvB;AACF"}
@@ -13,7 +13,7 @@
13
13
  * return agent.execute(input);
14
14
  * }
15
15
  */
16
- type AIErrorCode = "AGENT_EXEC_FAILED" | "AGENT_CANCELLED" | "AGENT_MAX_TRIPS" | "SCHEMA_VALIDATION_FAILED" | "TOOL_EXEC_FAILED" | "PROVIDER_ERROR" | "PROVIDER_RATE_LIMIT" | "PROVIDER_QUOTA_EXCEEDED" | "PROVIDER_TIMEOUT" | "CONTEXT_LENGTH_EXCEEDED" | "CONTENT_FILTER" | "PROVIDER_INVALID_REQUEST" | "PROVIDER_AUTH" | "BUDGET_EXCEEDED" | "GUARDRAIL_VIOLATION" | "WORKFLOW_ERROR" | "STEP_FAILED" | "WORKFLOW_DRIFT" | "WORKFLOW_CANCELLED" | "WORKFLOW_MAX_STEPS" | "WORKFLOW_INVALID_GOTO" | "SUPERVISOR_FAILED" | "SUPERVISOR_MAX_ITERATIONS" | "SUPERVISOR_INVALID_ROUTE" | "SUPERVISOR_CANCELLED" | "SUPERVISOR_DRIFT" | "SUPERVISOR_INTENT_DESCRIPTION_REQUIRED" | "SUPERVISOR_INTENT_MIXED_DISPATCH" | "SUPERVISOR_INTENT_STREAM_AND_OUTPUT" | "SUPERVISOR_INTENT_STREAM_TO_REQUIRED" | "SUPERVISOR_INTENT_STREAM_ON_WORKFLOW" | "SUPERVISOR_DISPATCH_CYCLE" | "ORCHESTRATOR_FAILED" | "ORCHESTRATOR_DRIFT" | "ORCHESTRATOR_CONFIG" | "ORCHESTRATOR_CANCELLED" | "PLANNER_FAILED" | "PLANNER_PLAN_INVALID" | "PLANNER_CANCELLED" | "VCR_CASSETTE_MISS" | "OUTBOUND_POLICY_BLOCKED";
16
+ type AIErrorCode = "AGENT_EXEC_FAILED" | "AGENT_CANCELLED" | "AGENT_MAX_TRIPS" | "AGENT_DRIFT" | "SCHEMA_VALIDATION_FAILED" | "TOOL_EXEC_FAILED" | "PROVIDER_ERROR" | "PROVIDER_RATE_LIMIT" | "PROVIDER_QUOTA_EXCEEDED" | "PROVIDER_TIMEOUT" | "CONTEXT_LENGTH_EXCEEDED" | "CONTENT_FILTER" | "PROVIDER_INVALID_REQUEST" | "PROVIDER_AUTH" | "BUDGET_EXCEEDED" | "GUARDRAIL_VIOLATION" | "WORKFLOW_ERROR" | "STEP_FAILED" | "WORKFLOW_DRIFT" | "WORKFLOW_CANCELLED" | "WORKFLOW_MAX_STEPS" | "WORKFLOW_INVALID_GOTO" | "SUPERVISOR_FAILED" | "SUPERVISOR_MAX_ITERATIONS" | "SUPERVISOR_INVALID_ROUTE" | "SUPERVISOR_CANCELLED" | "SUPERVISOR_DRIFT" | "SUPERVISOR_INTENT_DESCRIPTION_REQUIRED" | "SUPERVISOR_INTENT_MIXED_DISPATCH" | "SUPERVISOR_INTENT_STREAM_AND_OUTPUT" | "SUPERVISOR_INTENT_STREAM_TO_REQUIRED" | "SUPERVISOR_INTENT_STREAM_ON_WORKFLOW" | "SUPERVISOR_DISPATCH_CYCLE" | "ORCHESTRATOR_FAILED" | "ORCHESTRATOR_DRIFT" | "ORCHESTRATOR_CONFIG" | "ORCHESTRATOR_CANCELLED" | "PLANNER_FAILED" | "PLANNER_PLAN_INVALID" | "PLANNER_CANCELLED" | "PLANNER_DRIFT" | "VCR_CASSETTE_MISS" | "OUTBOUND_POLICY_BLOCKED";
17
17
  //#endregion
18
18
  export { AIErrorCode };
19
19
  //# sourceMappingURL=error-code.type.d.mts.map
@@ -3,6 +3,7 @@ import { AIErrorCode } from "./error-code.type.mjs";
3
3
  import { AIError, AIErrorOptions } from "./ai-error.mjs";
4
4
  import { AgentExecutionError } from "./agent-execution-error.mjs";
5
5
  import { AgentCancelledError, AgentCancelledErrorOptions } from "./agent-cancelled-error.mjs";
6
+ import { AgentDriftError, AgentDriftErrorOptions } from "./agent-drift-error.mjs";
6
7
  import { AgentMaxTripsError, AgentMaxTripsErrorOptions } from "./agent-max-trips-error.mjs";
7
8
  import { BudgetExceededError, BudgetExceededErrorOptions, BudgetUnit } from "./budget-exceeded-error.mjs";
8
9
  import { ProviderError } from "./provider-error.mjs";
@@ -21,6 +22,7 @@ import { OrchestratorDriftError, OrchestratorDriftErrorOptions } from "./orchest
21
22
  import { OutboundPolicyError } from "./outbound-policy-error.mjs";
22
23
  import { PlannerFailedError } from "./planner-failed-error.mjs";
23
24
  import { PlannerCancelledError, PlannerCancelledErrorOptions } from "./planner-cancelled-error.mjs";
25
+ import { PlannerDriftError, PlannerDriftErrorOptions } from "./planner-drift-error.mjs";
24
26
  import { PlannerPlanInvalidError } from "./planner-plan-invalid-error.mjs";
25
27
  import { ProviderAuthError } from "./provider-auth-error.mjs";
26
28
  import { ProviderRateLimitError, ProviderRateLimitErrorOptions } from "./provider-rate-limit-error.mjs";
@@ -1,6 +1,7 @@
1
1
  import { AIError } from "./ai-error.mjs";
2
2
  import { AgentExecutionError } from "./agent-execution-error.mjs";
3
3
  import { AgentCancelledError } from "./agent-cancelled-error.mjs";
4
+ import { AgentDriftError } from "./agent-drift-error.mjs";
4
5
  import { AgentMaxTripsError } from "./agent-max-trips-error.mjs";
5
6
  import { BudgetExceededError } from "./budget-exceeded-error.mjs";
6
7
  import { ProviderError } from "./provider-error.mjs";
@@ -19,6 +20,7 @@ import { OrchestratorDriftError } from "./orchestrator-drift-error.mjs";
19
20
  import { OutboundPolicyError } from "./outbound-policy-error.mjs";
20
21
  import { PlannerFailedError } from "./planner-failed-error.mjs";
21
22
  import { PlannerCancelledError } from "./planner-cancelled-error.mjs";
23
+ import { PlannerDriftError } from "./planner-drift-error.mjs";
22
24
  import { PlannerPlanInvalidError } from "./planner-plan-invalid-error.mjs";
23
25
  import { ProviderAuthError } from "./provider-auth-error.mjs";
24
26
  import { ProviderRateLimitError } from "./provider-rate-limit-error.mjs";
@@ -0,0 +1,34 @@
1
+ import { ErrorCategory } from "./error-category.type.mjs";
2
+ import { AIErrorOptions } from "./ai-error.mjs";
3
+ import { PlannerFailedError } from "./planner-failed-error.mjs";
4
+
5
+ //#region ../@warlock.js/ai/src/errors/planner-drift-error.d.ts
6
+ type PlannerDriftErrorOptions = AIErrorOptions & {
7
+ /** Signature recorded on the snapshot being resumed. */savedSignature: string; /** Signature computed from the current planner definition. */
8
+ currentSignature: string;
9
+ runId: string;
10
+ };
11
+ /**
12
+ * `planner.resume(runId)` loaded a durable snapshot whose structural
13
+ * fingerprint does not match the current planner definition (name +
14
+ * ordered capability names). The resume is refused — no node runs — and
15
+ * the user decides how to recover: discard the snapshot, migrate
16
+ * manually, or call `resume(runId, { force: true })` to bypass the check.
17
+ *
18
+ * A mid-run re-plan is NOT drift — the plan changed, not the definition;
19
+ * the persisted `replanCount` honors the replan budget across a resume.
20
+ *
21
+ * Mirrors `SupervisorDriftError` / `WorkflowDriftError` — same rationale,
22
+ * different primitive. Thrown (not returned on `result.error`) because a
23
+ * drifted resume never produces a valid run.
24
+ */
25
+ declare class PlannerDriftError extends PlannerFailedError {
26
+ static readonly defaultCategory: ErrorCategory;
27
+ readonly savedSignature: string;
28
+ readonly currentSignature: string;
29
+ readonly runId: string;
30
+ constructor(message: string, options: PlannerDriftErrorOptions);
31
+ }
32
+ //#endregion
33
+ export { PlannerDriftError, PlannerDriftErrorOptions };
34
+ //# sourceMappingURL=planner-drift-error.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner-drift-error.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/errors/planner-drift-error.ts"],"mappings":";;;;;KAIY,wBAAA,GAA2B,cAAc;0DAEnD,cAAA,UAFkC;EAIlC,gBAAA;EACA,KAAA;AAAA;;;;;AAAK;AAiBP;;;;;;;;;cAAa,iBAAA,SAA0B,kBAAA;EAAA,gBACd,eAAA,EAAiB,aAAA;EAAA,SAExB,cAAA;EAAA,SACA,gBAAA;EAAA,SACA,KAAA;cAEG,OAAA,UAAiB,OAAA,EAAS,wBAAA;AAAA"}
@@ -0,0 +1,33 @@
1
+ import { PlannerFailedError } from "./planner-failed-error.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/errors/planner-drift-error.ts
4
+ /**
5
+ * `planner.resume(runId)` loaded a durable snapshot whose structural
6
+ * fingerprint does not match the current planner definition (name +
7
+ * ordered capability names). The resume is refused — no node runs — and
8
+ * the user decides how to recover: discard the snapshot, migrate
9
+ * manually, or call `resume(runId, { force: true })` to bypass the check.
10
+ *
11
+ * A mid-run re-plan is NOT drift — the plan changed, not the definition;
12
+ * the persisted `replanCount` honors the replan budget across a resume.
13
+ *
14
+ * Mirrors `SupervisorDriftError` / `WorkflowDriftError` — same rationale,
15
+ * different primitive. Thrown (not returned on `result.error`) because a
16
+ * drifted resume never produces a valid run.
17
+ */
18
+ var PlannerDriftError = class extends PlannerFailedError {
19
+ static {
20
+ this.defaultCategory = "drift";
21
+ }
22
+ constructor(message, options) {
23
+ super(message, options, "PLANNER_DRIFT");
24
+ this.name = "PlannerDriftError";
25
+ this.savedSignature = options.savedSignature;
26
+ this.currentSignature = options.currentSignature;
27
+ this.runId = options.runId;
28
+ }
29
+ };
30
+
31
+ //#endregion
32
+ export { PlannerDriftError };
33
+ //# sourceMappingURL=planner-drift-error.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planner-drift-error.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/errors/planner-drift-error.ts"],"sourcesContent":["import type { AIErrorOptions } from \"./ai-error\";\nimport type { ErrorCategory } from \"./error-category.type\";\nimport { PlannerFailedError } from \"./planner-failed-error\";\n\nexport type PlannerDriftErrorOptions = AIErrorOptions & {\n /** Signature recorded on the snapshot being resumed. */\n savedSignature: string;\n /** Signature computed from the current planner definition. */\n currentSignature: string;\n runId: string;\n};\n\n/**\n * `planner.resume(runId)` loaded a durable snapshot whose structural\n * fingerprint does not match the current planner definition (name +\n * ordered capability names). The resume is refused — no node runs — and\n * the user decides how to recover: discard the snapshot, migrate\n * manually, or call `resume(runId, { force: true })` to bypass the check.\n *\n * A mid-run re-plan is NOT drift — the plan changed, not the definition;\n * the persisted `replanCount` honors the replan budget across a resume.\n *\n * Mirrors `SupervisorDriftError` / `WorkflowDriftError` — same rationale,\n * different primitive. Thrown (not returned on `result.error`) because a\n * drifted resume never produces a valid run.\n */\nexport class PlannerDriftError extends PlannerFailedError {\n public static readonly defaultCategory: ErrorCategory = \"drift\";\n\n public readonly savedSignature: string;\n public readonly currentSignature: string;\n public readonly runId: string;\n\n public constructor(message: string, options: PlannerDriftErrorOptions) {\n super(message, options, \"PLANNER_DRIFT\");\n this.name = \"PlannerDriftError\";\n this.savedSignature = options.savedSignature;\n this.currentSignature = options.currentSignature;\n this.runId = options.runId;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA0BA,IAAa,oBAAb,cAAuC,mBAAmB;;yBACA;;CAMxD,AAAO,YAAY,SAAiB,SAAmC;EACrE,MAAM,SAAS,SAAS,eAAe;EACvC,KAAK,OAAO;EACZ,KAAK,iBAAiB,QAAQ;EAC9B,KAAK,mBAAmB,QAAQ;EAChC,KAAK,QAAQ,QAAQ;CACvB;AACF"}
@@ -0,0 +1,32 @@
1
+ import { ModelPricing } from "../contracts/result/model-pricing.type.mjs";
2
+ import { Usage } from "../contracts/result/usage.type.mjs";
3
+ import { ImageModelPricing } from "../contracts/image-model.contract.mjs";
4
+
5
+ //#region ../@warlock.js/ai/src/image/image-cost.d.ts
6
+ /**
7
+ * Price one image-generation `Usage` against an
8
+ * {@link ImageModelPricing}, returning a `ModelPricing`-shaped USD
9
+ * breakdown so image spend folds into the exact same `Usage.cost`
10
+ * rollup the text path uses (`accumulateCost` / `mergeUsage`). There is
11
+ * no separate image-cost field anywhere downstream — only this one
12
+ * function, which knows the two metering models:
13
+ *
14
+ * - **Per-image** (DALL·E, Imagen): `perImageBySize[size]` (when the
15
+ * request `size` matches a tier) else flat `perImage`, times the
16
+ * number of images returned, attributed to `cost.output` (the image
17
+ * IS the output). Token channels stay 0.
18
+ * - **Token** (gpt-image-1): delegates to the standard
19
+ * {@link computeCost} against the prompt/image token `Usage`.
20
+ *
21
+ * Per-image wins when both shapes are configured (a provider is one or
22
+ * the other). Returns `undefined` when no usable pricing is present —
23
+ * the framework treats that as "cost unknown", never a false zero.
24
+ *
25
+ * @example
26
+ * computeImageCost({ input: 0, output: 0, total: 0 }, 2, "1024x1024", { perImage: 0.04 });
27
+ * // → { input: 0, output: 0.08 }
28
+ */
29
+ declare function computeImageCost(usage: Usage, imageCount: number, size: string | undefined, pricing: ImageModelPricing | undefined): ModelPricing | undefined;
30
+ //#endregion
31
+ export { computeImageCost };
32
+ //# sourceMappingURL=image-cost.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-cost.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/image/image-cost.ts"],"mappings":";;;;;;;AA4BA;;;;;;;;;;;;;;;;AAKe;;;;;iBALC,gBAAA,CACd,KAAA,EAAO,KAAA,EACP,UAAA,UACA,IAAA,sBACA,OAAA,EAAS,iBAAA,eACR,YAAA"}
@@ -0,0 +1,55 @@
1
+ import { computeCost } from "../utils/compute-cost.mjs";
2
+
3
+ //#region ../@warlock.js/ai/src/image/image-cost.ts
4
+ /**
5
+ * Price one image-generation `Usage` against an
6
+ * {@link ImageModelPricing}, returning a `ModelPricing`-shaped USD
7
+ * breakdown so image spend folds into the exact same `Usage.cost`
8
+ * rollup the text path uses (`accumulateCost` / `mergeUsage`). There is
9
+ * no separate image-cost field anywhere downstream — only this one
10
+ * function, which knows the two metering models:
11
+ *
12
+ * - **Per-image** (DALL·E, Imagen): `perImageBySize[size]` (when the
13
+ * request `size` matches a tier) else flat `perImage`, times the
14
+ * number of images returned, attributed to `cost.output` (the image
15
+ * IS the output). Token channels stay 0.
16
+ * - **Token** (gpt-image-1): delegates to the standard
17
+ * {@link computeCost} against the prompt/image token `Usage`.
18
+ *
19
+ * Per-image wins when both shapes are configured (a provider is one or
20
+ * the other). Returns `undefined` when no usable pricing is present —
21
+ * the framework treats that as "cost unknown", never a false zero.
22
+ *
23
+ * @example
24
+ * computeImageCost({ input: 0, output: 0, total: 0 }, 2, "1024x1024", { perImage: 0.04 });
25
+ * // → { input: 0, output: 0.08 }
26
+ */
27
+ function computeImageCost(usage, imageCount, size, pricing) {
28
+ if (!pricing) return;
29
+ if (pricing.perImage !== void 0 || pricing.perImageBySize !== void 0) {
30
+ const perImage = resolvePerImageRate(size, pricing);
31
+ if (perImage === void 0) return;
32
+ return {
33
+ input: 0,
34
+ output: perImage * imageCount
35
+ };
36
+ }
37
+ if (pricing.input !== void 0 && pricing.output !== void 0) return computeCost(usage, {
38
+ input: pricing.input,
39
+ output: pricing.output
40
+ });
41
+ }
42
+ /**
43
+ * Resolve the USD-per-image rate: a `perImageBySize` tier matching the
44
+ * requested `size` wins, otherwise the flat `perImage`. Returns
45
+ * `undefined` only when neither is set (the caller already gated on
46
+ * per-image metering being configured at all).
47
+ */
48
+ function resolvePerImageRate(size, pricing) {
49
+ if (size !== void 0 && pricing.perImageBySize?.[size] !== void 0) return pricing.perImageBySize[size];
50
+ return pricing.perImage;
51
+ }
52
+
53
+ //#endregion
54
+ export { computeImageCost };
55
+ //# sourceMappingURL=image-cost.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image-cost.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/image/image-cost.ts"],"sourcesContent":["import type { ImageModelPricing } from \"../contracts/image-model.contract\";\nimport type { ModelPricing } from \"../contracts/result/model-pricing.type\";\nimport type { Usage } from \"../contracts/result/usage.type\";\nimport { computeCost } from \"../utils/compute-cost\";\n\n/**\n * Price one image-generation `Usage` against an\n * {@link ImageModelPricing}, returning a `ModelPricing`-shaped USD\n * breakdown so image spend folds into the exact same `Usage.cost`\n * rollup the text path uses (`accumulateCost` / `mergeUsage`). There is\n * no separate image-cost field anywhere downstream — only this one\n * function, which knows the two metering models:\n *\n * - **Per-image** (DALL·E, Imagen): `perImageBySize[size]` (when the\n * request `size` matches a tier) else flat `perImage`, times the\n * number of images returned, attributed to `cost.output` (the image\n * IS the output). Token channels stay 0.\n * - **Token** (gpt-image-1): delegates to the standard\n * {@link computeCost} against the prompt/image token `Usage`.\n *\n * Per-image wins when both shapes are configured (a provider is one or\n * the other). Returns `undefined` when no usable pricing is present —\n * the framework treats that as \"cost unknown\", never a false zero.\n *\n * @example\n * computeImageCost({ input: 0, output: 0, total: 0 }, 2, \"1024x1024\", { perImage: 0.04 });\n * // → { input: 0, output: 0.08 }\n */\nexport function computeImageCost(\n usage: Usage,\n imageCount: number,\n size: string | undefined,\n pricing: ImageModelPricing | undefined,\n): ModelPricing | undefined {\n if (!pricing) {\n return undefined;\n }\n\n const perImageMetered = pricing.perImage !== undefined || pricing.perImageBySize !== undefined;\n\n if (perImageMetered) {\n const perImage = resolvePerImageRate(size, pricing);\n\n if (perImage === undefined) {\n return undefined;\n }\n\n return { input: 0, output: perImage * imageCount };\n }\n\n if (pricing.input !== undefined && pricing.output !== undefined) {\n return computeCost(usage, { input: pricing.input, output: pricing.output });\n }\n\n return undefined;\n}\n\n/**\n * Resolve the USD-per-image rate: a `perImageBySize` tier matching the\n * requested `size` wins, otherwise the flat `perImage`. Returns\n * `undefined` only when neither is set (the caller already gated on\n * per-image metering being configured at all).\n */\nfunction resolvePerImageRate(\n size: string | undefined,\n pricing: ImageModelPricing,\n): number | undefined {\n if (size !== undefined && pricing.perImageBySize?.[size] !== undefined) {\n return pricing.perImageBySize[size];\n }\n\n return pricing.perImage;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,iBACd,OACA,YACA,MACA,SAC0B;CAC1B,IAAI,CAAC,SACH;CAKF,IAFwB,QAAQ,aAAa,UAAa,QAAQ,mBAAmB,QAEhE;EACnB,MAAM,WAAW,oBAAoB,MAAM,OAAO;EAElD,IAAI,aAAa,QACf;EAGF,OAAO;GAAE,OAAO;GAAG,QAAQ,WAAW;EAAW;CACnD;CAEA,IAAI,QAAQ,UAAU,UAAa,QAAQ,WAAW,QACpD,OAAO,YAAY,OAAO;EAAE,OAAO,QAAQ;EAAO,QAAQ,QAAQ;CAAO,CAAC;AAI9E;;;;;;;AAQA,SAAS,oBACP,MACA,SACoB;CACpB,IAAI,SAAS,UAAa,QAAQ,iBAAiB,UAAU,QAC3D,OAAO,QAAQ,eAAe;CAGhC,OAAO,QAAQ;AACjB"}
@@ -0,0 +1,92 @@
1
+ import { BaseReport } from "../contracts/result/base-report.type.mjs";
2
+ import { ExecuteResult } from "../contracts/result/execute-result.type.mjs";
3
+ import { FlowObserveOption } from "../observe/resolve-observers.mjs";
4
+ import { GeneratedImage, ImageModelContract } from "../contracts/image-model.contract.mjs";
5
+
6
+ //#region ../@warlock.js/ai/src/image/image.d.ts
7
+ /**
8
+ * Parameters for {@link image}. `model` comes from an adapter's
9
+ * `image()` factory (`openai.image({ name })` / `google.image({ name })`);
10
+ * the rest are provider-neutral generation knobs plus the standard
11
+ * observability seam every verb shares.
12
+ */
13
+ type ImageParams = {
14
+ /** The image model to generate from (`sdk.image({ name })`). */model: ImageModelContract; /** Text description of the image(s) to generate. */
15
+ prompt: string; /** How many images to generate. Adapters clamp to the provider max. */
16
+ count?: number; /** Requested pixel size as `"WxH"` (e.g. `"1024x1024"`). */
17
+ size?: string; /** Quality tier (e.g. `"standard"` / `"hd"`). */
18
+ quality?: string; /** Aspect ratio (e.g. `"1:1"`, `"16:9"`) — ratio-based providers (Imagen). */
19
+ aspectRatio?: string; /** Concepts to steer away from (Imagen `negativePrompt`). */
20
+ negativePrompt?: string; /** Output container hint (`"png"` / `"jpeg"` / `"webp"`). */
21
+ format?: string; /** Cancellation handle, wired into the provider request where supported. */
22
+ signal?: AbortSignal;
23
+ /**
24
+ * Observability routing for this call — same `observe` seam as
25
+ * agents / workflows. `true` routes to the globally registered
26
+ * observers; an `Observer` object routes flow-locally; `false` opts
27
+ * out; omitted follows the global observe-all flag.
28
+ */
29
+ observe?: FlowObserveOption; /** Groups this call into a session for flat cost/trace queries. */
30
+ sessionId?: string; /** Report node name (defaults to `"image"`). */
31
+ name?: string; /** Provider-specific options forwarded verbatim to the adapter. */
32
+ options?: Record<string, unknown>;
33
+ };
34
+ /** Success payload of an {@link image} run. */
35
+ type ImageData = {
36
+ /** The generated images, normalized to the discriminated shape. */images: GeneratedImage[];
37
+ };
38
+ /**
39
+ * The report node an {@link image} run produces — a {@link BaseReport}
40
+ * (`type: "image"`) plus which model ran and how many images came back,
41
+ * so panoptic and any flat-row consumer attribute the cost/latency
42
+ * without special-casing.
43
+ */
44
+ type ImageReport = BaseReport & {
45
+ type: "image"; /** Identity of the image model this run used. */
46
+ model: {
47
+ name: string;
48
+ provider: string;
49
+ }; /** Number of images returned (0 on failure). */
50
+ imageCount: number;
51
+ };
52
+ /**
53
+ * Result envelope of {@link image} — the same uniform
54
+ * `{ data, error, usage, report }` every executable returns, narrowed
55
+ * with the `"image"` discriminant.
56
+ */
57
+ type ImageResult = ExecuteResult<ImageData> & {
58
+ type: "image";
59
+ report: ImageReport;
60
+ };
61
+ /**
62
+ * Generate one or more images from a text prompt — the image-output
63
+ * counterpart to `ai.agent`, and the first verb of the output-modality
64
+ * track (Theme I). Wraps an {@link ImageModelContract} (from
65
+ * `openai.image(...)` / `google.image(...)`) in the framework's uniform
66
+ * result contract:
67
+ *
68
+ * - **Never throws.** Provider failures (auth, rate-limit,
69
+ * content-filter, invalid request) surface as a typed `AIError` on
70
+ * `result.error`; `result.data` is then `undefined`.
71
+ * - **Cost-truth.** When the model carries pricing, `result.usage.cost`
72
+ * is filled in — per-token for gpt-image-1, per-image for
73
+ * DALL·E / Imagen — folding into the same `Usage.cost` rollup as text.
74
+ * - **Observable.** The completed {@link ImageReport} routes to any
75
+ * registered `Observer` (panoptic, OTel, …) via the shared `observe`
76
+ * seam, exactly like an agent run.
77
+ *
78
+ * @example
79
+ * const openai = new OpenAISDK({ apiKey });
80
+ * const { data, error, usage } = await ai.image({
81
+ * model: openai.image({ name: "gpt-image-1" }),
82
+ * prompt: "an isometric office desk, soft studio lighting",
83
+ * size: "1024x1024",
84
+ * });
85
+ *
86
+ * if (error) console.warn(error.code);
87
+ * else for (const img of data.images) save(img); // { type: "base64" | "url", ... }
88
+ */
89
+ declare function image(params: ImageParams): Promise<ImageResult>;
90
+ //#endregion
91
+ export { ImageData, ImageParams, ImageReport, ImageResult, image };
92
+ //# sourceMappingURL=image.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.d.mts","names":[],"sources":["../../../../../../../@warlock.js/ai/src/image/image.ts"],"mappings":";;;;;;;;AAsBA;;;;KAAY,WAAA;EAyBA,gEAvBV,KAAA,EAAO,kBAAA,EA6BS;EA3BhB,MAAA,UAFA;EAIA,KAAA,WAFA;EAIA,IAAA;EAEA,OAAA,WAEA;EAAA,WAAA,WAIA;EAFA,cAAA,WAIS;EAFT,MAAA,WASU;EAPV,MAAA,GAAS,WAAA;EAWT;;;;AAEgB;AAIlB;EAVE,OAAA,GAAU,iBAAA;EAEV,SAAA,WAUsB;EARtB,IAAA,WAiBqB;EAfrB,OAAA,GAAU,MAAA;AAAA;;KAIA,SAAA;EAcV,mEAZA,MAAA,EAAQ,cAAc;AAAA;;;AAcZ;AAQZ;;;KAbY,WAAA,GAAc,UAAU;EAClC,IAAA,WAcQ;EAZR,KAAA;IAAS,IAAA;IAAc,QAAA;EAAA,GAWvB;EATA,UAAA;AAAA;;AAUmB;AA+BrB;;;KAjCY,WAAA,GAAc,aAAA,CAAc,SAAA;EACtC,IAAA;EACA,MAAA,EAAQ,WAAA;AAAA;;;;;;;AA+B2D;;;;;;;;;;;;;;;;;;;;;;iBAA/C,KAAA,CAAM,MAAA,EAAQ,WAAA,GAAc,OAAA,CAAQ,WAAA"}
@@ -0,0 +1,113 @@
1
+ import { AIError } from "../errors/ai-error.mjs";
2
+ import { ProviderError } from "../errors/provider-error.mjs";
3
+ import { generateRunId } from "../utils/generate-run-id.mjs";
4
+ import { REPORT_SCHEMA_VERSION } from "../contracts/result/base-report.type.mjs";
5
+ import { stampReportLineage } from "../utils/stamp-report-lineage.mjs";
6
+ import { notifyObservers } from "../observe/resolve-observers.mjs";
7
+ import { computeImageCost } from "./image-cost.mjs";
8
+
9
+ //#region ../@warlock.js/ai/src/image/image.ts
10
+ /**
11
+ * Generate one or more images from a text prompt — the image-output
12
+ * counterpart to `ai.agent`, and the first verb of the output-modality
13
+ * track (Theme I). Wraps an {@link ImageModelContract} (from
14
+ * `openai.image(...)` / `google.image(...)`) in the framework's uniform
15
+ * result contract:
16
+ *
17
+ * - **Never throws.** Provider failures (auth, rate-limit,
18
+ * content-filter, invalid request) surface as a typed `AIError` on
19
+ * `result.error`; `result.data` is then `undefined`.
20
+ * - **Cost-truth.** When the model carries pricing, `result.usage.cost`
21
+ * is filled in — per-token for gpt-image-1, per-image for
22
+ * DALL·E / Imagen — folding into the same `Usage.cost` rollup as text.
23
+ * - **Observable.** The completed {@link ImageReport} routes to any
24
+ * registered `Observer` (panoptic, OTel, …) via the shared `observe`
25
+ * seam, exactly like an agent run.
26
+ *
27
+ * @example
28
+ * const openai = new OpenAISDK({ apiKey });
29
+ * const { data, error, usage } = await ai.image({
30
+ * model: openai.image({ name: "gpt-image-1" }),
31
+ * prompt: "an isometric office desk, soft studio lighting",
32
+ * size: "1024x1024",
33
+ * });
34
+ *
35
+ * if (error) console.warn(error.code);
36
+ * else for (const img of data.images) save(img); // { type: "base64" | "url", ... }
37
+ */
38
+ async function image(params) {
39
+ const { model, prompt } = params;
40
+ const runId = generateRunId("image");
41
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
42
+ const startPerf = performance.now();
43
+ const usage = {
44
+ input: 0,
45
+ output: 0,
46
+ total: 0
47
+ };
48
+ let data;
49
+ let error;
50
+ let status = "completed";
51
+ let imageCount = 0;
52
+ try {
53
+ const response = await model.generate(prompt, {
54
+ count: params.count,
55
+ size: params.size,
56
+ quality: params.quality,
57
+ aspectRatio: params.aspectRatio,
58
+ negativePrompt: params.negativePrompt,
59
+ format: params.format,
60
+ signal: params.signal,
61
+ ...params.options
62
+ });
63
+ Object.assign(usage, response.usage);
64
+ if (usage.cost === void 0) {
65
+ const cost = computeImageCost(usage, response.images.length, params.size, model.pricing);
66
+ if (cost !== void 0) usage.cost = cost;
67
+ }
68
+ data = { images: response.images };
69
+ imageCount = response.images.length;
70
+ } catch (thrown) {
71
+ error = thrown instanceof AIError ? thrown : new ProviderError(toMessage(thrown), { cause: thrown });
72
+ status = params.signal?.aborted ? "cancelled" : "failed";
73
+ }
74
+ const report = {
75
+ runId,
76
+ rootRunId: runId,
77
+ name: params.name ?? "image",
78
+ type: "image",
79
+ status,
80
+ error,
81
+ startedAt,
82
+ endedAt: (/* @__PURE__ */ new Date()).toISOString(),
83
+ duration: performance.now() - startPerf,
84
+ usage,
85
+ children: [],
86
+ model: {
87
+ name: model.name,
88
+ provider: model.provider
89
+ },
90
+ imageCount,
91
+ reportSchemaVersion: 1
92
+ };
93
+ stampReportLineage(report, {
94
+ rootRunId: runId,
95
+ sessionId: params.sessionId
96
+ });
97
+ await notifyObservers(params.observe, report);
98
+ return {
99
+ type: "image",
100
+ data,
101
+ error,
102
+ usage,
103
+ report
104
+ };
105
+ }
106
+ /** Best-effort message for a non-`AIError` thrown value. */
107
+ function toMessage(thrown) {
108
+ return thrown instanceof Error ? thrown.message : String(thrown);
109
+ }
110
+
111
+ //#endregion
112
+ export { image };
113
+ //# sourceMappingURL=image.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.mjs","names":[],"sources":["../../../../../../../@warlock.js/ai/src/image/image.ts"],"sourcesContent":["import type {\n GeneratedImage,\n ImageModelContract,\n} from \"../contracts/image-model.contract\";\nimport type { BaseReport } from \"../contracts/result/base-report.type\";\nimport { REPORT_SCHEMA_VERSION } from \"../contracts/result/base-report.type\";\nimport type { ExecuteResult } from \"../contracts/result/execute-result.type\";\nimport type { Usage } from \"../contracts/result/usage.type\";\nimport { AIError } from \"../errors/ai-error\";\nimport { ProviderError } from \"../errors/provider-error\";\nimport type { FlowObserveOption } from \"../observe/resolve-observers\";\nimport { notifyObservers } from \"../observe/resolve-observers\";\nimport { generateRunId } from \"../utils/generate-run-id\";\nimport { stampReportLineage } from \"../utils/stamp-report-lineage\";\nimport { computeImageCost } from \"./image-cost\";\n\n/**\n * Parameters for {@link image}. `model` comes from an adapter's\n * `image()` factory (`openai.image({ name })` / `google.image({ name })`);\n * the rest are provider-neutral generation knobs plus the standard\n * observability seam every verb shares.\n */\nexport type ImageParams = {\n /** The image model to generate from (`sdk.image({ name })`). */\n model: ImageModelContract;\n /** Text description of the image(s) to generate. */\n prompt: string;\n /** How many images to generate. Adapters clamp to the provider max. */\n count?: number;\n /** Requested pixel size as `\"WxH\"` (e.g. `\"1024x1024\"`). */\n size?: string;\n /** Quality tier (e.g. `\"standard\"` / `\"hd\"`). */\n quality?: string;\n /** Aspect ratio (e.g. `\"1:1\"`, `\"16:9\"`) — ratio-based providers (Imagen). */\n aspectRatio?: string;\n /** Concepts to steer away from (Imagen `negativePrompt`). */\n negativePrompt?: string;\n /** Output container hint (`\"png\"` / `\"jpeg\"` / `\"webp\"`). */\n format?: string;\n /** Cancellation handle, wired into the provider request where supported. */\n signal?: AbortSignal;\n /**\n * Observability routing for this call — same `observe` seam as\n * agents / workflows. `true` routes to the globally registered\n * observers; an `Observer` object routes flow-locally; `false` opts\n * out; omitted follows the global observe-all flag.\n */\n observe?: FlowObserveOption;\n /** Groups this call into a session for flat cost/trace queries. */\n sessionId?: string;\n /** Report node name (defaults to `\"image\"`). */\n name?: string;\n /** Provider-specific options forwarded verbatim to the adapter. */\n options?: Record<string, unknown>;\n};\n\n/** Success payload of an {@link image} run. */\nexport type ImageData = {\n /** The generated images, normalized to the discriminated shape. */\n images: GeneratedImage[];\n};\n\n/**\n * The report node an {@link image} run produces — a {@link BaseReport}\n * (`type: \"image\"`) plus which model ran and how many images came back,\n * so panoptic and any flat-row consumer attribute the cost/latency\n * without special-casing.\n */\nexport type ImageReport = BaseReport & {\n type: \"image\";\n /** Identity of the image model this run used. */\n model: { name: string; provider: string };\n /** Number of images returned (0 on failure). */\n imageCount: number;\n};\n\n/**\n * Result envelope of {@link image} — the same uniform\n * `{ data, error, usage, report }` every executable returns, narrowed\n * with the `\"image\"` discriminant.\n */\nexport type ImageResult = ExecuteResult<ImageData> & {\n type: \"image\";\n report: ImageReport;\n};\n\n/**\n * Generate one or more images from a text prompt — the image-output\n * counterpart to `ai.agent`, and the first verb of the output-modality\n * track (Theme I). Wraps an {@link ImageModelContract} (from\n * `openai.image(...)` / `google.image(...)`) in the framework's uniform\n * result contract:\n *\n * - **Never throws.** Provider failures (auth, rate-limit,\n * content-filter, invalid request) surface as a typed `AIError` on\n * `result.error`; `result.data` is then `undefined`.\n * - **Cost-truth.** When the model carries pricing, `result.usage.cost`\n * is filled in — per-token for gpt-image-1, per-image for\n * DALL·E / Imagen — folding into the same `Usage.cost` rollup as text.\n * - **Observable.** The completed {@link ImageReport} routes to any\n * registered `Observer` (panoptic, OTel, …) via the shared `observe`\n * seam, exactly like an agent run.\n *\n * @example\n * const openai = new OpenAISDK({ apiKey });\n * const { data, error, usage } = await ai.image({\n * model: openai.image({ name: \"gpt-image-1\" }),\n * prompt: \"an isometric office desk, soft studio lighting\",\n * size: \"1024x1024\",\n * });\n *\n * if (error) console.warn(error.code);\n * else for (const img of data.images) save(img); // { type: \"base64\" | \"url\", ... }\n */\nexport async function image(params: ImageParams): Promise<ImageResult> {\n const { model, prompt } = params;\n\n const runId = generateRunId(\"image\");\n const startedAt = new Date().toISOString();\n const startPerf = performance.now();\n\n const usage: Usage = { input: 0, output: 0, total: 0 };\n let data: ImageData | undefined;\n let error: AIError | undefined;\n let status: ImageReport[\"status\"] = \"completed\";\n let imageCount = 0;\n\n try {\n const response = await model.generate(prompt, {\n count: params.count,\n size: params.size,\n quality: params.quality,\n aspectRatio: params.aspectRatio,\n negativePrompt: params.negativePrompt,\n format: params.format,\n signal: params.signal,\n ...params.options,\n });\n\n // Preserve every usage channel the adapter reported (cached /\n // reasoning / cache-write, and any adapter-supplied `cost`), mirroring\n // how the agent path routes provider usage. Then honor a pre-priced\n // response or compute image cost — `usage.cost ??= …` precedence, same\n // as the agent path.\n Object.assign(usage, response.usage);\n\n if (usage.cost === undefined) {\n const cost = computeImageCost(usage, response.images.length, params.size, model.pricing);\n if (cost !== undefined) {\n usage.cost = cost;\n }\n }\n\n data = { images: response.images };\n imageCount = response.images.length;\n } catch (thrown) {\n error = thrown instanceof AIError ? thrown : new ProviderError(toMessage(thrown), { cause: thrown });\n // A caller-aborted run is \"cancelled\", not \"failed\" — keep the typed\n // cause but distinguish the terminal status for dashboards/retry policy.\n status = params.signal?.aborted ? \"cancelled\" : \"failed\";\n }\n\n const report: ImageReport = {\n runId,\n rootRunId: runId,\n name: params.name ?? \"image\",\n type: \"image\",\n status,\n error,\n startedAt,\n endedAt: new Date().toISOString(),\n duration: performance.now() - startPerf,\n usage,\n children: [],\n model: { name: model.name, provider: model.provider },\n imageCount,\n reportSchemaVersion: REPORT_SCHEMA_VERSION,\n };\n\n stampReportLineage(report, { rootRunId: runId, sessionId: params.sessionId });\n\n await notifyObservers(params.observe, report);\n\n return { type: \"image\", data, error, usage, report };\n}\n\n/** Best-effort message for a non-`AIError` thrown value. */\nfunction toMessage(thrown: unknown): string {\n return thrown instanceof Error ? thrown.message : String(thrown);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkHA,eAAsB,MAAM,QAA2C;CACrE,MAAM,EAAE,OAAO,WAAW;CAE1B,MAAM,QAAQ,cAAc,OAAO;CACnC,MAAM,6BAAY,IAAI,KAAK,EAAC,CAAC,YAAY;CACzC,MAAM,YAAY,YAAY,IAAI;CAElC,MAAM,QAAe;EAAE,OAAO;EAAG,QAAQ;EAAG,OAAO;CAAE;CACrD,IAAI;CACJ,IAAI;CACJ,IAAI,SAAgC;CACpC,IAAI,aAAa;CAEjB,IAAI;EACF,MAAM,WAAW,MAAM,MAAM,SAAS,QAAQ;GAC5C,OAAO,OAAO;GACd,MAAM,OAAO;GACb,SAAS,OAAO;GAChB,aAAa,OAAO;GACpB,gBAAgB,OAAO;GACvB,QAAQ,OAAO;GACf,QAAQ,OAAO;GACf,GAAG,OAAO;EACZ,CAAC;EAOD,OAAO,OAAO,OAAO,SAAS,KAAK;EAEnC,IAAI,MAAM,SAAS,QAAW;GAC5B,MAAM,OAAO,iBAAiB,OAAO,SAAS,OAAO,QAAQ,OAAO,MAAM,MAAM,OAAO;GACvF,IAAI,SAAS,QACX,MAAM,OAAO;EAEjB;EAEA,OAAO,EAAE,QAAQ,SAAS,OAAO;EACjC,aAAa,SAAS,OAAO;CAC/B,SAAS,QAAQ;EACf,QAAQ,kBAAkB,UAAU,SAAS,IAAI,cAAc,UAAU,MAAM,GAAG,EAAE,OAAO,OAAO,CAAC;EAGnG,SAAS,OAAO,QAAQ,UAAU,cAAc;CAClD;CAEA,MAAM,SAAsB;EAC1B;EACA,WAAW;EACX,MAAM,OAAO,QAAQ;EACrB,MAAM;EACN;EACA;EACA;EACA,0BAAS,IAAI,KAAK,EAAC,CAAC,YAAY;EAChC,UAAU,YAAY,IAAI,IAAI;EAC9B;EACA,UAAU,CAAC;EACX,OAAO;GAAE,MAAM,MAAM;GAAM,UAAU,MAAM;EAAS;EACpD;EACA;CACF;CAEA,mBAAmB,QAAQ;EAAE,WAAW;EAAO,WAAW,OAAO;CAAU,CAAC;CAE5E,MAAM,gBAAgB,OAAO,SAAS,MAAM;CAE5C,OAAO;EAAE,MAAM;EAAS;EAAM;EAAO;EAAO;CAAO;AACrD;;AAGA,SAAS,UAAU,QAAyB;CAC1C,OAAO,kBAAkB,QAAQ,OAAO,UAAU,OAAO,MAAM;AACjE"}