quantum-ai-sdk 0.5.0 → 0.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.
package/dist/chat.js CHANGED
@@ -92,12 +92,33 @@ export async function* chatStream(client, req, signal) {
92
92
  event.delta = raw.delta;
93
93
  break;
94
94
  case "tool_use":
95
+ // Legacy atomic event — kept for back-compat with backends
96
+ // that haven't yet shipped the triplet (v0.6+).
95
97
  event.tool_use = {
96
98
  id: String(raw.id ?? ""),
97
99
  name: String(raw.name ?? ""),
98
100
  input: raw.input ?? {},
99
101
  };
100
102
  break;
103
+ case "tool_use_start":
104
+ event.tool_use_start = {
105
+ id: String(raw.id ?? ""),
106
+ name: String(raw.name ?? ""),
107
+ };
108
+ break;
109
+ case "tool_use_input_delta":
110
+ event.tool_use_input_delta = {
111
+ id: String(raw.id ?? ""),
112
+ partial_json: String(raw.partial_json ?? ""),
113
+ };
114
+ break;
115
+ case "tool_use_complete":
116
+ event.tool_use_complete = {
117
+ id: String(raw.id ?? ""),
118
+ name: String(raw.name ?? ""),
119
+ input: raw.input ?? {},
120
+ };
121
+ break;
101
122
  case "usage":
102
123
  event.usage = {
103
124
  input_tokens: raw.input_tokens ?? 0,
package/dist/index.d.ts CHANGED
@@ -6,6 +6,9 @@ export type { RealtimeConfig, RealtimeEvent, RealtimeSession } from "./realtime.
6
6
  export { contact } from "./contact.js";
7
7
  export type { BillingRequest, BillingEntry, BillingResponse } from "./compute-billing.js";
8
8
  export type { ClientOptions, ResponseMeta, ChatRequest, ChatMessage, ChatTool, ContentBlock, ChatUsage, ChatResponse, StreamEvent, StreamDelta, StreamToolUse, SessionChatRequest, SessionChatResponse, SessionToolResult, ContextConfig, ContextMetadata, AgentRequest, AgentWorkerConfig, AgentEvent, MissionRequest, MissionWorkerConfig, MissionEvent, ImageRequest, ImageResponse, GeneratedImage, ImageEditRequest, ImageEditResponse, TTSRequest, TTSResponse, STTRequest, STTResponse, MusicRequest, MusicClip, MusicResponse, SoundEffectRequest, SoundEffectResponse, DialogueRequest, DialogueResponse, DialogueVoice, SpeechToSpeechRequest, SpeechToSpeechResponse, IsolateVoiceRequest, IsolateVoiceResponse, RemixVoiceRequest, RemixVoiceResponse, DubRequest, DubResponse, AlignRequest, AlignResponse, AlignedWord, VoiceDesignRequest, VoiceDesignResponse, VoicePreview, StarfishTTSRequest, StarfishTTSResponse, VideoRequest, VideoResponse, GeneratedVideo, VideoStudioRequest, VideoTranslateRequest, PhotoAvatarRequest, DigitalTwinRequest, AsyncJobResponse, AvatarsResponse, HeyGenAvatar, HeyGenTemplatesResponse, HeyGenTemplate, HeyGenVoicesResponse, HeyGenVoice, EmbedRequest, EmbedResponse, DocumentRequest, DocumentResponse, ChunkDocumentRequest, ChunkDocumentResponse, DocumentChunk, ProcessDocumentRequest, ProcessDocumentResponse, RAGSearchRequest, RAGSearchResponse, RAGResult, RAGCorpus, SurrealRAGSearchRequest, SurrealRAGSearchResponse, SurrealRAGResult, SurrealRAGProvidersResponse, SurrealRAGProviderInfo, ModelInfo, PricingInfo, BalanceResponse, UsageEntry, UsageResponse, UsageQuery, UsageSummaryMonth, UsageSummaryResponse, PricingEntry, AccountPricingResponse, JobCreateRequest, JobCreateResponse, JobStatusResponse, JobListResponse, JobStreamEvent, JobListItem, CreateKeyRequest, CreateKeyResponse, KeyDetails, ListKeysResponse, ComputeTemplate, TemplatesResponse, ProvisionRequest, ProvisionResponse, ComputeInstanceInfo, InstancesResponse, InstanceDetailInfo, InstanceResponse, SSHKeyRequest, DeleteResponse, VoiceInfo, VoicesResponse, CloneVoiceRequest, CloneVoiceResponse, ContactRequest, BatchJobInput, BatchSubmitRequest, BatchSubmitResponse, BatchJsonlResponse, BatchJobInfo, BatchJobsResponse, CreditPack, CreditPacksResponse, CreditPurchaseRequest, CreditPurchaseResponse, CreditBalanceResponse, CreditTier, CreditTiersResponse, DevProgramApplyRequest, DevProgramApplyResponse, AuthUser, AuthResponse, AuthAppleRequest, WebSearchRequest, WebSearchResponse, WebSearchResult, NewsResult, VideoSearchResult, LLMContextRequest, LLMContextResponse, ContentChunk, ContextSource, SearchAnswerRequest, SearchAnswerResponse, SearchAnswerChoice, SearchCitation, StatusResponse, Citation, CollectionsListResponse, CollectionDocumentsResponse, CollectionSearchResponse, CreateCollectionRequest, DeleteCollectionResponse, ModelsResponse, RagCorporaResponse, Infobox, Discussion, TextToSpeechRequest, TextToSpeechResponse, SpeechToTextRequest, SpeechToTextResponse, ContactResponse, ContextChunk, ContextOptions, HeyGenAvatarsResponse, JobAcceptedResponse, JobListEntry, PostProcess, RealtimeSessionResponse, SearchMessage, SearchOptions, ScrapeTarget, ScrapeRequest, ScrapeResponse, ScreenshotURL, ScreenshotRequest, ScreenshotResult, ScreenshotResponse, } from "./types.js";
9
+ export type { VisionRequest, VisionContext, VisionResponse, DetectedObject, QualityAssessment, RelevanceCheck, OcrResult, TextOverlay, } from "./vision.js";
10
+ export type { MissionCreateRequest, MissionChatRequest, MissionPlanUpdate, MissionConfirmStructure, MissionApproveRequest, MissionImportRequest, MissionCreateResponse, MissionDetail, MissionTask, MissionListResponse, MissionChatResponse, MissionChatUsage, MissionCheckpoint, MissionCheckpointsResponse, MissionStatusResponse, } from "./missions.js";
11
+ export type { SecurityScanUrlRequest, SecurityScanHtmlRequest, SecurityReportRequest, SecurityScanResponse, SecurityAssessment, SecurityFinding, SecurityCheckResponse, SecurityBlocklistResponse, SecurityBlocklistEntry, SecurityReportResponse, } from "./security.js";
9
12
  export { DEFAULT_BASE_URL, TICKS_PER_USD } from "./types.js";
10
13
  import type { ChatMessage } from "./types.js";
11
14
  /** Create a user message. */
@@ -0,0 +1,280 @@
1
+ import type { QuantumClient } from "./client.js";
2
+ /** Worker configuration within a mission. */
3
+ export interface MissionWorkerConfig {
4
+ /** Model to use for this worker. */
5
+ model: string;
6
+ /** Cost tier: "cheap", "mid", "expensive". */
7
+ tier: string;
8
+ /** Worker description / capabilities. */
9
+ description?: string;
10
+ }
11
+ /** Request body for creating a mission. */
12
+ export interface MissionCreateRequest {
13
+ /** High-level task description. */
14
+ goal: string;
15
+ /** Strategy: "wave" (default), "dag", "mapreduce", "refinement", "branch". */
16
+ strategy?: string;
17
+ /** Conductor model (default: claude-sonnet-4-6). */
18
+ conductorModel?: string;
19
+ /** Worker team configuration (keyed by worker name). */
20
+ workers?: Record<string, MissionWorkerConfig>;
21
+ /** Maximum orchestration steps (default: 25). */
22
+ maxSteps?: number;
23
+ /** Custom system prompt for the conductor. */
24
+ systemPrompt?: string;
25
+ /** Existing session ID for context continuity. */
26
+ sessionId?: string;
27
+ }
28
+ /** Request body for chatting with a mission's architect. */
29
+ export interface MissionChatRequest {
30
+ /** Message to send to the architect. */
31
+ message: string;
32
+ /** Enable streaming (not yet supported). */
33
+ stream?: boolean;
34
+ }
35
+ /** Request body for updating a mission plan. */
36
+ export interface MissionPlanUpdate {
37
+ /** Updated task list. */
38
+ tasks?: Record<string, unknown>[];
39
+ /** Updated worker configuration. */
40
+ workers?: Record<string, MissionWorkerConfig>;
41
+ /** Additional system prompt. */
42
+ systemPrompt?: string;
43
+ /** Updated max steps. */
44
+ maxSteps?: number;
45
+ /** Additional context to inject. */
46
+ context?: string;
47
+ }
48
+ /** Request body for confirming/rejecting a mission structure. */
49
+ export interface MissionConfirmStructure {
50
+ /** Whether the structure is approved. */
51
+ confirmed: boolean;
52
+ /** Rejection reason or modification notes. */
53
+ feedback?: string;
54
+ }
55
+ /** Request body for approving a completed mission. */
56
+ export interface MissionApproveRequest {
57
+ /** Git commit SHA associated with the mission output. */
58
+ commitSha?: string;
59
+ /** Approval comment. */
60
+ comment?: string;
61
+ }
62
+ /** Request body for importing a plan as a new mission. */
63
+ export interface MissionImportRequest {
64
+ /** Mission goal. */
65
+ goal: string;
66
+ /** Strategy. */
67
+ strategy?: string;
68
+ /** Conductor model. */
69
+ conductorModel?: string;
70
+ /** Worker configuration. */
71
+ workers?: Record<string, MissionWorkerConfig>;
72
+ /** Pre-defined tasks. */
73
+ tasks: Record<string, unknown>[];
74
+ /** System prompt. */
75
+ systemPrompt?: string;
76
+ /** Maximum steps. */
77
+ maxSteps?: number;
78
+ /** Auto-execute after import. */
79
+ autoExecute?: boolean;
80
+ }
81
+ /** Response from mission creation. */
82
+ export interface MissionCreateResponse {
83
+ /** Mission identifier. */
84
+ missionId: string;
85
+ /** Initial status. */
86
+ status: string;
87
+ /** Session ID for conversation context. */
88
+ sessionId?: string;
89
+ /** Conductor model used. */
90
+ conductorModel?: string;
91
+ /** Strategy used. */
92
+ strategy?: string;
93
+ /** Worker configuration. */
94
+ workers?: Record<string, MissionWorkerConfig>;
95
+ /** Creation timestamp. */
96
+ createdAt?: string;
97
+ /** Request identifier. */
98
+ requestId?: string;
99
+ }
100
+ /** A task within a mission. */
101
+ export interface MissionTask {
102
+ /** Task identifier. */
103
+ id?: string;
104
+ /** Task name. */
105
+ name?: string;
106
+ /** Task description. */
107
+ description?: string;
108
+ /** Assigned worker name. */
109
+ worker?: string;
110
+ /** Model used. */
111
+ model?: string;
112
+ /** Task status. */
113
+ status?: string;
114
+ /** Task result. */
115
+ result?: string;
116
+ /** Error message if failed. */
117
+ error?: string;
118
+ /** Step number. */
119
+ step: number;
120
+ /** Input tokens used. */
121
+ tokensIn: number;
122
+ /** Output tokens used. */
123
+ tokensOut: number;
124
+ }
125
+ /** Mission detail (from GET /missions/{id}). */
126
+ export interface MissionDetail {
127
+ /** Mission identifier. */
128
+ id?: string;
129
+ /** User who created the mission. */
130
+ userId?: string;
131
+ /** Mission goal. */
132
+ goal?: string;
133
+ /** Strategy. */
134
+ strategy?: string;
135
+ /** Conductor model. */
136
+ conductorModel?: string;
137
+ /** Current status. */
138
+ status?: string;
139
+ /** Creation timestamp. */
140
+ createdAt?: string;
141
+ /** Start timestamp. */
142
+ startedAt?: string;
143
+ /** Completion timestamp. */
144
+ completedAt?: string;
145
+ /** Error message if failed. */
146
+ error?: string;
147
+ /** Total cost in ticks. */
148
+ costTicks: number;
149
+ /** Number of steps executed. */
150
+ totalSteps: number;
151
+ /** Session ID. */
152
+ sessionId?: string;
153
+ /** Final result text. */
154
+ result?: string;
155
+ /** Tasks within the mission. */
156
+ tasks: MissionTask[];
157
+ /** Whether the mission was approved. */
158
+ approved: boolean;
159
+ /** Commit SHA (if approved). */
160
+ commitSha?: string;
161
+ }
162
+ /** Response from listing missions. */
163
+ export interface MissionListResponse {
164
+ /** List of missions. */
165
+ missions: MissionDetail[];
166
+ }
167
+ /** Token usage for a mission chat response. */
168
+ export interface MissionChatUsage {
169
+ inputTokens: number;
170
+ outputTokens: number;
171
+ }
172
+ /** Response from chatting with the architect. */
173
+ export interface MissionChatResponse {
174
+ /** Mission identifier. */
175
+ missionId?: string;
176
+ /** Architect's response content. */
177
+ content?: string;
178
+ /** Model used. */
179
+ model?: string;
180
+ /** Cost in ticks. */
181
+ costTicks: number;
182
+ /** Token usage. */
183
+ usage?: MissionChatUsage;
184
+ }
185
+ /** A git checkpoint within a mission. */
186
+ export interface MissionCheckpoint {
187
+ /** Checkpoint identifier. */
188
+ id?: string;
189
+ /** Commit SHA. */
190
+ commitSha?: string;
191
+ /** Checkpoint message. */
192
+ message?: string;
193
+ /** Creation timestamp. */
194
+ createdAt?: string;
195
+ }
196
+ /** Response from listing checkpoints. */
197
+ export interface MissionCheckpointsResponse {
198
+ missionId?: string;
199
+ checkpoints: MissionCheckpoint[];
200
+ }
201
+ /** Generic status response for mission operations. */
202
+ export interface MissionStatusResponse {
203
+ missionId?: string;
204
+ status?: string;
205
+ confirmed?: boolean;
206
+ approved?: boolean;
207
+ deleted?: boolean;
208
+ updated?: boolean;
209
+ commitSha?: string;
210
+ }
211
+ /**
212
+ * Create and execute a mission asynchronously.
213
+ * @internal
214
+ */
215
+ export declare function missionCreate(client: QuantumClient, req: MissionCreateRequest): Promise<MissionCreateResponse>;
216
+ /**
217
+ * List missions for the authenticated user.
218
+ * @internal
219
+ */
220
+ export declare function missionList(client: QuantumClient, status?: string): Promise<MissionListResponse>;
221
+ /**
222
+ * Get mission details including tasks.
223
+ * @internal
224
+ */
225
+ export declare function missionGet(client: QuantumClient, missionId: string): Promise<MissionDetail>;
226
+ /**
227
+ * Delete a mission.
228
+ * @internal
229
+ */
230
+ export declare function missionDelete(client: QuantumClient, missionId: string): Promise<MissionStatusResponse>;
231
+ /**
232
+ * Cancel a running mission.
233
+ * @internal
234
+ */
235
+ export declare function missionCancel(client: QuantumClient, missionId: string): Promise<MissionStatusResponse>;
236
+ /**
237
+ * Pause a running mission.
238
+ * @internal
239
+ */
240
+ export declare function missionPause(client: QuantumClient, missionId: string): Promise<MissionStatusResponse>;
241
+ /**
242
+ * Resume a paused mission.
243
+ * @internal
244
+ */
245
+ export declare function missionResume(client: QuantumClient, missionId: string): Promise<MissionStatusResponse>;
246
+ /**
247
+ * Chat with the mission's architect.
248
+ * @internal
249
+ */
250
+ export declare function missionChat(client: QuantumClient, missionId: string, req: MissionChatRequest): Promise<MissionChatResponse>;
251
+ /**
252
+ * Retry a failed task.
253
+ * @internal
254
+ */
255
+ export declare function missionRetryTask(client: QuantumClient, missionId: string, taskId: string): Promise<MissionStatusResponse>;
256
+ /**
257
+ * Approve a completed mission.
258
+ * @internal
259
+ */
260
+ export declare function missionApprove(client: QuantumClient, missionId: string, req: MissionApproveRequest): Promise<MissionStatusResponse>;
261
+ /**
262
+ * Update the mission plan.
263
+ * @internal
264
+ */
265
+ export declare function missionUpdatePlan(client: QuantumClient, missionId: string, req: MissionPlanUpdate): Promise<MissionStatusResponse>;
266
+ /**
267
+ * Confirm or reject the proposed execution structure.
268
+ * @internal
269
+ */
270
+ export declare function missionConfirmStructure(client: QuantumClient, missionId: string, req: MissionConfirmStructure): Promise<MissionStatusResponse>;
271
+ /**
272
+ * List git checkpoints for a mission.
273
+ * @internal
274
+ */
275
+ export declare function missionCheckpoints(client: QuantumClient, missionId: string): Promise<MissionCheckpointsResponse>;
276
+ /**
277
+ * Import an existing plan as a new mission.
278
+ * @internal
279
+ */
280
+ export declare function missionImport(client: QuantumClient, req: MissionImportRequest): Promise<MissionCreateResponse>;
@@ -0,0 +1,278 @@
1
+ // ── Wire format helpers ──────────────────────────────────────────
2
+ /** @internal */
3
+ function createReqToWire(req) {
4
+ const out = { goal: req.goal };
5
+ if (req.strategy !== undefined)
6
+ out.strategy = req.strategy;
7
+ if (req.conductorModel !== undefined)
8
+ out.conductor_model = req.conductorModel;
9
+ if (req.workers !== undefined)
10
+ out.workers = req.workers;
11
+ if (req.maxSteps !== undefined)
12
+ out.max_steps = req.maxSteps;
13
+ if (req.systemPrompt !== undefined)
14
+ out.system_prompt = req.systemPrompt;
15
+ if (req.sessionId !== undefined)
16
+ out.session_id = req.sessionId;
17
+ return out;
18
+ }
19
+ /** @internal */
20
+ function chatReqToWire(req) {
21
+ const out = { message: req.message };
22
+ if (req.stream !== undefined)
23
+ out.stream = req.stream;
24
+ return out;
25
+ }
26
+ /** @internal */
27
+ function planUpdateToWire(req) {
28
+ const out = {};
29
+ if (req.tasks !== undefined)
30
+ out.tasks = req.tasks;
31
+ if (req.workers !== undefined)
32
+ out.workers = req.workers;
33
+ if (req.systemPrompt !== undefined)
34
+ out.system_prompt = req.systemPrompt;
35
+ if (req.maxSteps !== undefined)
36
+ out.max_steps = req.maxSteps;
37
+ if (req.context !== undefined)
38
+ out.context = req.context;
39
+ return out;
40
+ }
41
+ /** @internal */
42
+ function approveReqToWire(req) {
43
+ const out = {};
44
+ if (req.commitSha !== undefined)
45
+ out.commit_sha = req.commitSha;
46
+ if (req.comment !== undefined)
47
+ out.comment = req.comment;
48
+ return out;
49
+ }
50
+ /** @internal */
51
+ function importReqToWire(req) {
52
+ const out = { goal: req.goal, tasks: req.tasks };
53
+ if (req.strategy !== undefined)
54
+ out.strategy = req.strategy;
55
+ if (req.conductorModel !== undefined)
56
+ out.conductor_model = req.conductorModel;
57
+ if (req.workers !== undefined)
58
+ out.workers = req.workers;
59
+ if (req.systemPrompt !== undefined)
60
+ out.system_prompt = req.systemPrompt;
61
+ if (req.maxSteps !== undefined)
62
+ out.max_steps = req.maxSteps;
63
+ if (req.autoExecute !== undefined)
64
+ out.auto_execute = req.autoExecute;
65
+ return out;
66
+ }
67
+ /** @internal */
68
+ function taskFromWire(raw) {
69
+ return {
70
+ id: raw.id,
71
+ name: raw.name,
72
+ description: raw.description,
73
+ worker: raw.worker,
74
+ model: raw.model,
75
+ status: raw.status,
76
+ result: raw.result,
77
+ error: raw.error,
78
+ step: raw.step ?? 0,
79
+ tokensIn: raw.tokens_in ?? 0,
80
+ tokensOut: raw.tokens_out ?? 0,
81
+ };
82
+ }
83
+ /** @internal */
84
+ function detailFromWire(raw) {
85
+ const tasks = (raw.tasks ?? []).map(taskFromWire);
86
+ return {
87
+ id: raw.id,
88
+ userId: raw.user_id,
89
+ goal: raw.goal,
90
+ strategy: raw.strategy,
91
+ conductorModel: raw.conductor_model,
92
+ status: raw.status,
93
+ createdAt: raw.created_at,
94
+ startedAt: raw.started_at,
95
+ completedAt: raw.completed_at,
96
+ error: raw.error,
97
+ costTicks: raw.cost_ticks ?? 0,
98
+ totalSteps: raw.total_steps ?? 0,
99
+ sessionId: raw.session_id,
100
+ result: raw.result,
101
+ tasks,
102
+ approved: raw.approved ?? false,
103
+ commitSha: raw.commit_sha,
104
+ };
105
+ }
106
+ /** @internal */
107
+ function createRespFromWire(raw) {
108
+ return {
109
+ missionId: raw.mission_id ?? "",
110
+ status: raw.status ?? "",
111
+ sessionId: raw.session_id,
112
+ conductorModel: raw.conductor_model,
113
+ strategy: raw.strategy,
114
+ workers: raw.workers,
115
+ createdAt: raw.created_at,
116
+ requestId: raw.request_id,
117
+ };
118
+ }
119
+ /** @internal */
120
+ function chatRespFromWire(raw) {
121
+ let usage;
122
+ if (raw.usage) {
123
+ const u = raw.usage;
124
+ usage = {
125
+ inputTokens: u.input_tokens ?? 0,
126
+ outputTokens: u.output_tokens ?? 0,
127
+ };
128
+ }
129
+ return {
130
+ missionId: raw.mission_id,
131
+ content: raw.content,
132
+ model: raw.model,
133
+ costTicks: raw.cost_ticks ?? 0,
134
+ usage,
135
+ };
136
+ }
137
+ /** @internal */
138
+ function statusRespFromWire(raw) {
139
+ return {
140
+ missionId: raw.mission_id,
141
+ status: raw.status,
142
+ confirmed: raw.confirmed,
143
+ approved: raw.approved,
144
+ deleted: raw.deleted,
145
+ updated: raw.updated,
146
+ commitSha: raw.commit_sha,
147
+ };
148
+ }
149
+ /** @internal */
150
+ function checkpointFromWire(raw) {
151
+ return {
152
+ id: raw.id,
153
+ commitSha: raw.commit_sha,
154
+ message: raw.message,
155
+ createdAt: raw.created_at,
156
+ };
157
+ }
158
+ // ── Client methods ───────────────────────────────────────────────
159
+ /**
160
+ * Create and execute a mission asynchronously.
161
+ * @internal
162
+ */
163
+ export async function missionCreate(client, req) {
164
+ const { data } = await client._doJSON("POST", "/qai/v1/missions/create", createReqToWire(req));
165
+ return createRespFromWire(data);
166
+ }
167
+ /**
168
+ * List missions for the authenticated user.
169
+ * @internal
170
+ */
171
+ export async function missionList(client, status) {
172
+ const path = status
173
+ ? `/qai/v1/missions/list?status=${encodeURIComponent(status)}`
174
+ : "/qai/v1/missions/list";
175
+ const { data } = await client._doJSON("GET", path, undefined);
176
+ const missions = (data.missions ?? []).map(detailFromWire);
177
+ return { missions };
178
+ }
179
+ /**
180
+ * Get mission details including tasks.
181
+ * @internal
182
+ */
183
+ export async function missionGet(client, missionId) {
184
+ const { data } = await client._doJSON("GET", `/qai/v1/missions/${encodeURIComponent(missionId)}`, undefined);
185
+ return detailFromWire(data);
186
+ }
187
+ /**
188
+ * Delete a mission.
189
+ * @internal
190
+ */
191
+ export async function missionDelete(client, missionId) {
192
+ const { data } = await client._doJSON("DELETE", `/qai/v1/missions/${encodeURIComponent(missionId)}`, undefined);
193
+ return statusRespFromWire(data);
194
+ }
195
+ /**
196
+ * Cancel a running mission.
197
+ * @internal
198
+ */
199
+ export async function missionCancel(client, missionId) {
200
+ const { data } = await client._doJSON("POST", `/qai/v1/missions/${encodeURIComponent(missionId)}/cancel`, undefined);
201
+ return statusRespFromWire(data);
202
+ }
203
+ /**
204
+ * Pause a running mission.
205
+ * @internal
206
+ */
207
+ export async function missionPause(client, missionId) {
208
+ const { data } = await client._doJSON("POST", `/qai/v1/missions/${encodeURIComponent(missionId)}/pause`, undefined);
209
+ return statusRespFromWire(data);
210
+ }
211
+ /**
212
+ * Resume a paused mission.
213
+ * @internal
214
+ */
215
+ export async function missionResume(client, missionId) {
216
+ const { data } = await client._doJSON("POST", `/qai/v1/missions/${encodeURIComponent(missionId)}/resume`, undefined);
217
+ return statusRespFromWire(data);
218
+ }
219
+ /**
220
+ * Chat with the mission's architect.
221
+ * @internal
222
+ */
223
+ export async function missionChat(client, missionId, req) {
224
+ const { data } = await client._doJSON("POST", `/qai/v1/missions/${encodeURIComponent(missionId)}/chat`, chatReqToWire(req));
225
+ return chatRespFromWire(data);
226
+ }
227
+ /**
228
+ * Retry a failed task.
229
+ * @internal
230
+ */
231
+ export async function missionRetryTask(client, missionId, taskId) {
232
+ const { data } = await client._doJSON("POST", `/qai/v1/missions/${encodeURIComponent(missionId)}/retry/${encodeURIComponent(taskId)}`, undefined);
233
+ return statusRespFromWire(data);
234
+ }
235
+ /**
236
+ * Approve a completed mission.
237
+ * @internal
238
+ */
239
+ export async function missionApprove(client, missionId, req) {
240
+ const { data } = await client._doJSON("POST", `/qai/v1/missions/${encodeURIComponent(missionId)}/approve`, approveReqToWire(req));
241
+ return statusRespFromWire(data);
242
+ }
243
+ /**
244
+ * Update the mission plan.
245
+ * @internal
246
+ */
247
+ export async function missionUpdatePlan(client, missionId, req) {
248
+ const { data } = await client._doJSON("PUT", `/qai/v1/missions/${encodeURIComponent(missionId)}/plan`, planUpdateToWire(req));
249
+ return statusRespFromWire(data);
250
+ }
251
+ /**
252
+ * Confirm or reject the proposed execution structure.
253
+ * @internal
254
+ */
255
+ export async function missionConfirmStructure(client, missionId, req) {
256
+ const { data } = await client._doJSON("POST", `/qai/v1/missions/${encodeURIComponent(missionId)}/confirm-structure`, req);
257
+ return statusRespFromWire(data);
258
+ }
259
+ /**
260
+ * List git checkpoints for a mission.
261
+ * @internal
262
+ */
263
+ export async function missionCheckpoints(client, missionId) {
264
+ const { data } = await client._doJSON("GET", `/qai/v1/missions/${encodeURIComponent(missionId)}/checkpoints`, undefined);
265
+ const checkpoints = (data.checkpoints ?? []).map(checkpointFromWire);
266
+ return {
267
+ missionId: data.mission_id,
268
+ checkpoints,
269
+ };
270
+ }
271
+ /**
272
+ * Import an existing plan as a new mission.
273
+ * @internal
274
+ */
275
+ export async function missionImport(client, req) {
276
+ const { data } = await client._doJSON("POST", "/qai/v1/missions/import", importReqToWire(req));
277
+ return createRespFromWire(data);
278
+ }
@@ -0,0 +1,158 @@
1
+ import type { QuantumClient } from "./client.js";
2
+ /** Request body for scanning a URL for prompt injection. */
3
+ export interface SecurityScanUrlRequest {
4
+ /** URL to scan. */
5
+ url: string;
6
+ }
7
+ /** Request body for scanning raw HTML content. */
8
+ export interface SecurityScanHtmlRequest {
9
+ /** Raw HTML to scan. */
10
+ html: string;
11
+ /** Rendered visible text (for structural analysis). */
12
+ visibleText?: string;
13
+ /** Source URL (for context). */
14
+ url?: string;
15
+ }
16
+ /** Request body for reporting a suspicious URL. */
17
+ export interface SecurityReportRequest {
18
+ /** URL to report. */
19
+ url: string;
20
+ /** Description of the suspected threat. */
21
+ description?: string;
22
+ /** Category of the suspected threat. */
23
+ category?: string;
24
+ }
25
+ /** A single detected injection pattern. */
26
+ export interface SecurityFinding {
27
+ /** Category: "instruction_override", "role_impersonation", "data_exfiltration", etc. */
28
+ category: string;
29
+ /** Pattern that matched. */
30
+ pattern: string;
31
+ /** Offending content (truncated). */
32
+ content: string;
33
+ /** Location in the page. */
34
+ location: string;
35
+ /** Threat level for this finding. */
36
+ threat: string;
37
+ /** Detection confidence (0.0 - 1.0). */
38
+ confidence: number;
39
+ /** Human-readable description. */
40
+ description: string;
41
+ }
42
+ /** Threat assessment for a scanned page. */
43
+ export interface SecurityAssessment {
44
+ /** Source URL. */
45
+ url: string;
46
+ /** Overall threat level: "none", "low", "medium", "high", "critical". */
47
+ threatLevel: string;
48
+ /** Numeric threat score (0.0 - 100.0). */
49
+ threatScore: number;
50
+ /** Individual findings. */
51
+ findings: SecurityFinding[];
52
+ /** Length of hidden text content detected. */
53
+ hiddenTextLength: number;
54
+ /** Length of visible text content. */
55
+ visibleTextLength: number;
56
+ /** Ratio of hidden to total content. */
57
+ hiddenRatio: number;
58
+ /** Human-readable summary. */
59
+ summary: string;
60
+ }
61
+ /** Response from a security scan. */
62
+ export interface SecurityScanResponse {
63
+ /** Full threat assessment. */
64
+ assessment: SecurityAssessment;
65
+ /** Request identifier. */
66
+ requestId: string;
67
+ }
68
+ /** Response from checking a URL against the registry. */
69
+ export interface SecurityCheckResponse {
70
+ /** URL that was checked. */
71
+ url: string;
72
+ /** Whether the URL is blocked. */
73
+ blocked: boolean;
74
+ /** Threat level (if blocked). */
75
+ threatLevel?: string;
76
+ /** Threat score (if blocked). */
77
+ threatScore?: number;
78
+ /** Detection categories (if blocked). */
79
+ categories?: string[];
80
+ /** First seen timestamp. */
81
+ firstSeen?: string;
82
+ /** Last seen timestamp. */
83
+ lastSeen?: string;
84
+ /** Number of reports. */
85
+ reportCount?: number;
86
+ /** Registry status: "confirmed", "suspected". */
87
+ status?: string;
88
+ /** Human-readable message. */
89
+ message?: string;
90
+ }
91
+ /** A single blocklist entry. */
92
+ export interface SecurityBlocklistEntry {
93
+ /** Entry identifier. */
94
+ id?: string;
95
+ /** Blocked URL. */
96
+ url: string;
97
+ /** Registry status. */
98
+ status: string;
99
+ /** Threat level. */
100
+ threatLevel: string;
101
+ /** Threat score. */
102
+ threatScore: number;
103
+ /** Detection categories. */
104
+ categories: string[];
105
+ /** Number of findings. */
106
+ findingsCount: number;
107
+ /** Hidden content ratio. */
108
+ hiddenRatio: number;
109
+ /** First seen timestamp. */
110
+ firstSeen?: string;
111
+ /** Summary. */
112
+ summary: string;
113
+ }
114
+ /** Response from the blocklist feed. */
115
+ export interface SecurityBlocklistResponse {
116
+ /** Blocklist entries. */
117
+ entries: SecurityBlocklistEntry[];
118
+ /** Total count. */
119
+ count: number;
120
+ /** Filter status used. */
121
+ status: string;
122
+ }
123
+ /** Response from reporting a URL. */
124
+ export interface SecurityReportResponse {
125
+ /** URL that was reported. */
126
+ url: string;
127
+ /** Report status: "existing" or "suspected". */
128
+ status: string;
129
+ /** Message. */
130
+ message: string;
131
+ /** Threat level (if already in registry). */
132
+ threatLevel?: string;
133
+ }
134
+ /**
135
+ * Scan a URL for prompt injection attacks.
136
+ * @internal
137
+ */
138
+ export declare function securityScanUrl(client: QuantumClient, url: string): Promise<SecurityScanResponse>;
139
+ /**
140
+ * Scan raw HTML content for prompt injection.
141
+ * @internal
142
+ */
143
+ export declare function securityScanHtml(client: QuantumClient, req: SecurityScanHtmlRequest): Promise<SecurityScanResponse>;
144
+ /**
145
+ * Check a URL against the injection registry.
146
+ * @internal
147
+ */
148
+ export declare function securityCheck(client: QuantumClient, url: string): Promise<SecurityCheckResponse>;
149
+ /**
150
+ * Get the injection blocklist feed.
151
+ * @internal
152
+ */
153
+ export declare function securityBlocklist(client: QuantumClient, status?: string): Promise<SecurityBlocklistResponse>;
154
+ /**
155
+ * Report a suspicious URL.
156
+ * @internal
157
+ */
158
+ export declare function securityReport(client: QuantumClient, req: SecurityReportRequest): Promise<SecurityReportResponse>;
@@ -0,0 +1,135 @@
1
+ // ── Wire format helpers ──────────────────────────────────────────
2
+ /** @internal */
3
+ function scanHtmlToWire(req) {
4
+ const out = { html: req.html };
5
+ if (req.visibleText !== undefined)
6
+ out.visible_text = req.visibleText;
7
+ if (req.url !== undefined)
8
+ out.url = req.url;
9
+ return out;
10
+ }
11
+ /** @internal */
12
+ function findingFromWire(raw) {
13
+ return {
14
+ category: raw.category ?? "",
15
+ pattern: raw.pattern ?? "",
16
+ content: raw.content ?? "",
17
+ location: raw.location ?? "",
18
+ threat: raw.threat ?? "",
19
+ confidence: raw.confidence ?? 0,
20
+ description: raw.description ?? "",
21
+ };
22
+ }
23
+ /** @internal */
24
+ function assessmentFromWire(raw) {
25
+ const findings = (raw.findings ?? []).map(findingFromWire);
26
+ return {
27
+ url: raw.url ?? "",
28
+ threatLevel: raw.threat_level ?? "",
29
+ threatScore: raw.threat_score ?? 0,
30
+ findings,
31
+ hiddenTextLength: raw.hidden_text_length ?? 0,
32
+ visibleTextLength: raw.visible_text_length ?? 0,
33
+ hiddenRatio: raw.hidden_ratio ?? 0,
34
+ summary: raw.summary ?? "",
35
+ };
36
+ }
37
+ /** @internal */
38
+ function scanRespFromWire(raw) {
39
+ return {
40
+ assessment: assessmentFromWire(raw.assessment ?? {}),
41
+ requestId: raw.request_id ?? "",
42
+ };
43
+ }
44
+ /** @internal */
45
+ function checkRespFromWire(raw) {
46
+ return {
47
+ url: raw.url ?? "",
48
+ blocked: raw.blocked ?? false,
49
+ threatLevel: raw.threat_level,
50
+ threatScore: raw.threat_score,
51
+ categories: raw.categories,
52
+ firstSeen: raw.first_seen,
53
+ lastSeen: raw.last_seen,
54
+ reportCount: raw.report_count,
55
+ status: raw.status,
56
+ message: raw.message,
57
+ };
58
+ }
59
+ /** @internal */
60
+ function blocklistEntryFromWire(raw) {
61
+ return {
62
+ id: raw.id,
63
+ url: raw.url ?? "",
64
+ status: raw.status ?? "",
65
+ threatLevel: raw.threat_level ?? "",
66
+ threatScore: raw.threat_score ?? 0,
67
+ categories: raw.categories ?? [],
68
+ findingsCount: raw.findings_count ?? 0,
69
+ hiddenRatio: raw.hidden_ratio ?? 0,
70
+ firstSeen: raw.first_seen,
71
+ summary: raw.summary ?? "",
72
+ };
73
+ }
74
+ /** @internal */
75
+ function blocklistRespFromWire(raw) {
76
+ const entries = (raw.entries ?? []).map(blocklistEntryFromWire);
77
+ return {
78
+ entries,
79
+ count: raw.count ?? 0,
80
+ status: raw.status ?? "",
81
+ };
82
+ }
83
+ /** @internal */
84
+ function reportRespFromWire(raw) {
85
+ return {
86
+ url: raw.url ?? "",
87
+ status: raw.status ?? "",
88
+ message: raw.message ?? "",
89
+ threatLevel: raw.threat_level,
90
+ };
91
+ }
92
+ // ── Client methods ───────────────────────────────────────────────
93
+ /**
94
+ * Scan a URL for prompt injection attacks.
95
+ * @internal
96
+ */
97
+ export async function securityScanUrl(client, url) {
98
+ const { data } = await client._doJSON("POST", "/qai/v1/security/scan-url", { url });
99
+ return scanRespFromWire(data);
100
+ }
101
+ /**
102
+ * Scan raw HTML content for prompt injection.
103
+ * @internal
104
+ */
105
+ export async function securityScanHtml(client, req) {
106
+ const { data } = await client._doJSON("POST", "/qai/v1/security/scan-html", scanHtmlToWire(req));
107
+ return scanRespFromWire(data);
108
+ }
109
+ /**
110
+ * Check a URL against the injection registry.
111
+ * @internal
112
+ */
113
+ export async function securityCheck(client, url) {
114
+ const { data } = await client._doJSON("GET", `/qai/v1/security/check?url=${encodeURIComponent(url)}`, undefined);
115
+ return checkRespFromWire(data);
116
+ }
117
+ /**
118
+ * Get the injection blocklist feed.
119
+ * @internal
120
+ */
121
+ export async function securityBlocklist(client, status) {
122
+ const path = status
123
+ ? `/qai/v1/security/blocklist?status=${encodeURIComponent(status)}`
124
+ : "/qai/v1/security/blocklist";
125
+ const { data } = await client._doJSON("GET", path, undefined);
126
+ return blocklistRespFromWire(data);
127
+ }
128
+ /**
129
+ * Report a suspicious URL.
130
+ * @internal
131
+ */
132
+ export async function securityReport(client, req) {
133
+ const { data } = await client._doJSON("POST", "/qai/v1/security/report", req);
134
+ return reportRespFromWire(data);
135
+ }
package/dist/types.d.ts CHANGED
@@ -84,12 +84,39 @@ export interface StreamToolUse {
84
84
  name: string;
85
85
  input: Record<string, unknown>;
86
86
  }
87
+ /** New since v0.6: tool-use streaming triplet. */
88
+ export interface StreamToolUseStart {
89
+ id: string;
90
+ name: string;
91
+ }
92
+ export interface StreamToolUseInputDelta {
93
+ id: string;
94
+ /** Raw JSON fragment — may not parse on its own; accumulate until tool_use_complete. */
95
+ partial_json: string;
96
+ }
97
+ export interface StreamToolUseComplete {
98
+ id: string;
99
+ name: string;
100
+ /** Server-accumulated, fully-parsed tool arguments. */
101
+ input: Record<string, unknown>;
102
+ }
87
103
  export interface StreamEvent {
88
104
  type: string;
89
- /** Event type (e.g. "content_delta", "thinking_delta", "tool_use", "usage", "error", "done"). */
105
+ /** Event type (e.g. "content_delta", "thinking_delta", "tool_use_start",
106
+ * "tool_use_input_delta", "tool_use_complete", "tool_use" (legacy),
107
+ * "usage", "error", "done"). */
90
108
  event_type?: string;
91
109
  delta?: StreamDelta;
110
+ /** Populated for the legacy atomic "tool_use" event. New code should
111
+ * prefer the triplet (tool_use_start / tool_use_input_delta /
112
+ * tool_use_complete). */
92
113
  tool_use?: StreamToolUse;
114
+ /** Populated for "tool_use_start" events. */
115
+ tool_use_start?: StreamToolUseStart;
116
+ /** Populated for "tool_use_input_delta" events. */
117
+ tool_use_input_delta?: StreamToolUseInputDelta;
118
+ /** Populated for "tool_use_complete" events. */
119
+ tool_use_complete?: StreamToolUseComplete;
93
120
  usage?: ChatUsage;
94
121
  error?: string;
95
122
  done?: boolean;
@@ -99,6 +126,11 @@ export interface RawStreamEvent {
99
126
  type?: string;
100
127
  delta?: StreamDelta;
101
128
  tool_use?: StreamToolUse;
129
+ /** Fields shared by the triplet — flattened in the wire format. */
130
+ id?: string;
131
+ name?: string;
132
+ input?: Record<string, unknown>;
133
+ partial_json?: string;
102
134
  usage?: ChatUsage;
103
135
  message?: string;
104
136
  input_tokens?: number;
@@ -0,0 +1,130 @@
1
+ import type { QuantumClient } from "./client.js";
2
+ /** Domain context for relevance analysis. */
3
+ export interface VisionContext {
4
+ /** Installation type (e.g. "solar", "heat_pump", "ev_charger"). */
5
+ installationType?: string;
6
+ /** Phase (e.g. "pre_install", "installation", "post_install"). */
7
+ phase?: string;
8
+ /** Expected items for relevance checking. */
9
+ expectedItems?: string[];
10
+ }
11
+ /** Request body for vision analysis endpoints. */
12
+ export interface VisionRequest {
13
+ /** Base64-encoded image (with or without data: prefix). */
14
+ imageBase64?: string;
15
+ /** Image URL (fetched by the model provider). */
16
+ imageUrl?: string;
17
+ /** Model to use. Default: gemini-2.5-flash. */
18
+ model?: string;
19
+ /** Analysis profile: "combined" (default), "scene", "objects", "ocr", "quality". */
20
+ profile?: string;
21
+ /** Domain context for relevance checking. */
22
+ context?: VisionContext;
23
+ }
24
+ /** A detected object with bounding box. */
25
+ export interface DetectedObject {
26
+ /** Object label. */
27
+ label: string;
28
+ /** Detection confidence (0.0 - 1.0). */
29
+ confidence: number;
30
+ /** Bounding box: [y_min, x_min, y_max, x_max] normalised to 0-1000. */
31
+ boundingBox: [number, number, number, number];
32
+ }
33
+ /** Image quality assessment. */
34
+ export interface QualityAssessment {
35
+ /** Overall rating: "good", "acceptable", "poor". */
36
+ overall: string;
37
+ /** Quality score (0.0 - 1.0). */
38
+ score: number;
39
+ /** Blur level: "none", "slight", "significant". */
40
+ blur: string;
41
+ /** Lighting: "well_lit", "dim", "dark". */
42
+ darkness: string;
43
+ /** Resolution: "high", "adequate", "low". */
44
+ resolution: string;
45
+ /** Exposure: "correct", "over", "under". */
46
+ exposure: string;
47
+ /** Specific issues found. */
48
+ issues: string[];
49
+ }
50
+ /** Relevance check against expected content. */
51
+ export interface RelevanceCheck {
52
+ /** Whether the image is relevant to the context. */
53
+ relevant: boolean;
54
+ /** Relevance score (0.0 - 1.0). */
55
+ score: number;
56
+ /** Items expected based on context. */
57
+ expectedItems: string[];
58
+ /** Items actually found in the image. */
59
+ foundItems: string[];
60
+ /** Expected but not found. */
61
+ missingItems: string[];
62
+ /** Found but not expected. */
63
+ unexpectedItems: string[];
64
+ /** Additional notes. */
65
+ notes?: string;
66
+ }
67
+ /** A detected text region in the image. */
68
+ export interface TextOverlay {
69
+ /** Extracted text content. */
70
+ text: string;
71
+ /** Bounding box: [y_min, x_min, y_max, x_max] normalised to 0-1000. */
72
+ boundingBox?: [number, number, number, number];
73
+ /** Overlay type: "gps", "timestamp", "address", "label", "other". */
74
+ type?: string;
75
+ }
76
+ /** OCR / text extraction result. */
77
+ export interface OcrResult {
78
+ /** All extracted text concatenated. */
79
+ text?: string;
80
+ /** Extracted metadata (GPS, timestamp, address, etc.). */
81
+ metadata: Record<string, string>;
82
+ /** Individual text overlays with positions. */
83
+ overlays: TextOverlay[];
84
+ }
85
+ /** Full vision analysis response. */
86
+ export interface VisionResponse {
87
+ /** Scene description. */
88
+ caption?: string;
89
+ /** Suggested tags (lowercase_snake_case). */
90
+ tags: string[];
91
+ /** Detected objects with bounding boxes. */
92
+ objects: DetectedObject[];
93
+ /** Image quality assessment. */
94
+ quality?: QualityAssessment;
95
+ /** Relevance check against context. */
96
+ relevance?: RelevanceCheck;
97
+ /** Extracted text and overlay metadata. */
98
+ ocr?: OcrResult;
99
+ /** Model used. */
100
+ model: string;
101
+ /** Cost in ticks. */
102
+ costTicks: number;
103
+ /** Request identifier. */
104
+ requestId: string;
105
+ }
106
+ /**
107
+ * Full combined vision analysis (scene + objects + quality + OCR + relevance).
108
+ * @internal
109
+ */
110
+ export declare function visionAnalyze(client: QuantumClient, req: VisionRequest): Promise<VisionResponse>;
111
+ /**
112
+ * Object detection with bounding boxes.
113
+ * @internal
114
+ */
115
+ export declare function visionDetect(client: QuantumClient, req: VisionRequest): Promise<VisionResponse>;
116
+ /**
117
+ * Scene description and tags.
118
+ * @internal
119
+ */
120
+ export declare function visionDescribe(client: QuantumClient, req: VisionRequest): Promise<VisionResponse>;
121
+ /**
122
+ * Text extraction and overlay metadata (OCR).
123
+ * @internal
124
+ */
125
+ export declare function visionOcr(client: QuantumClient, req: VisionRequest): Promise<VisionResponse>;
126
+ /**
127
+ * Image quality assessment.
128
+ * @internal
129
+ */
130
+ export declare function visionQuality(client: QuantumClient, req: VisionRequest): Promise<VisionResponse>;
package/dist/vision.js ADDED
@@ -0,0 +1,124 @@
1
+ // ── Wire format (snake_case JSON) ────────────────────────────────
2
+ /** @internal Convert camelCase request to snake_case wire format. */
3
+ function toWire(req) {
4
+ const out = {};
5
+ if (req.imageBase64 !== undefined)
6
+ out.image_base64 = req.imageBase64;
7
+ if (req.imageUrl !== undefined)
8
+ out.image_url = req.imageUrl;
9
+ if (req.model !== undefined)
10
+ out.model = req.model;
11
+ if (req.profile !== undefined)
12
+ out.profile = req.profile;
13
+ if (req.context) {
14
+ const ctx = {};
15
+ if (req.context.installationType !== undefined)
16
+ ctx.installation_type = req.context.installationType;
17
+ if (req.context.phase !== undefined)
18
+ ctx.phase = req.context.phase;
19
+ if (req.context.expectedItems !== undefined)
20
+ ctx.expected_items = req.context.expectedItems;
21
+ out.context = ctx;
22
+ }
23
+ return out;
24
+ }
25
+ /** @internal Convert snake_case wire response to camelCase. */
26
+ function fromWire(raw) {
27
+ const objects = (raw.objects ?? []).map((o) => ({
28
+ label: o.label ?? "",
29
+ confidence: o.confidence ?? 0,
30
+ boundingBox: o.bounding_box ?? [0, 0, 0, 0],
31
+ }));
32
+ let quality;
33
+ if (raw.quality) {
34
+ const q = raw.quality;
35
+ quality = {
36
+ overall: q.overall ?? "",
37
+ score: q.score ?? 0,
38
+ blur: q.blur ?? "",
39
+ darkness: q.darkness ?? "",
40
+ resolution: q.resolution ?? "",
41
+ exposure: q.exposure ?? "",
42
+ issues: q.issues ?? [],
43
+ };
44
+ }
45
+ let relevance;
46
+ if (raw.relevance) {
47
+ const r = raw.relevance;
48
+ relevance = {
49
+ relevant: r.relevant ?? false,
50
+ score: r.score ?? 0,
51
+ expectedItems: r.expected_items ?? [],
52
+ foundItems: r.found_items ?? [],
53
+ missingItems: r.missing_items ?? [],
54
+ unexpectedItems: r.unexpected_items ?? [],
55
+ notes: r.notes,
56
+ };
57
+ }
58
+ let ocr;
59
+ if (raw.ocr) {
60
+ const o = raw.ocr;
61
+ const overlays = (o.overlays ?? []).map((ov) => ({
62
+ text: ov.text ?? "",
63
+ boundingBox: ov.bounding_box,
64
+ type: ov.type,
65
+ }));
66
+ ocr = {
67
+ text: o.text,
68
+ metadata: o.metadata ?? {},
69
+ overlays,
70
+ };
71
+ }
72
+ return {
73
+ caption: raw.caption,
74
+ tags: raw.tags ?? [],
75
+ objects,
76
+ quality,
77
+ relevance,
78
+ ocr,
79
+ model: raw.model ?? "",
80
+ costTicks: raw.cost_ticks ?? 0,
81
+ requestId: raw.request_id ?? "",
82
+ };
83
+ }
84
+ // ── Client methods ───────────────────────────────────────────────
85
+ /**
86
+ * Full combined vision analysis (scene + objects + quality + OCR + relevance).
87
+ * @internal
88
+ */
89
+ export async function visionAnalyze(client, req) {
90
+ const { data } = await client._doJSON("POST", "/qai/v1/vision/analyze", toWire(req));
91
+ return fromWire(data);
92
+ }
93
+ /**
94
+ * Object detection with bounding boxes.
95
+ * @internal
96
+ */
97
+ export async function visionDetect(client, req) {
98
+ const { data } = await client._doJSON("POST", "/qai/v1/vision/detect", toWire(req));
99
+ return fromWire(data);
100
+ }
101
+ /**
102
+ * Scene description and tags.
103
+ * @internal
104
+ */
105
+ export async function visionDescribe(client, req) {
106
+ const { data } = await client._doJSON("POST", "/qai/v1/vision/describe", toWire(req));
107
+ return fromWire(data);
108
+ }
109
+ /**
110
+ * Text extraction and overlay metadata (OCR).
111
+ * @internal
112
+ */
113
+ export async function visionOcr(client, req) {
114
+ const { data } = await client._doJSON("POST", "/qai/v1/vision/ocr", toWire(req));
115
+ return fromWire(data);
116
+ }
117
+ /**
118
+ * Image quality assessment.
119
+ * @internal
120
+ */
121
+ export async function visionQuality(client, req) {
122
+ const { data } = await client._doJSON("POST", "/qai/v1/vision/quality", toWire(req));
123
+ return fromWire(data);
124
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quantum-ai-sdk",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Cosmic Duck SDK — 100+ AI endpoints across 10 providers",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",