@volter/twin-togetherai 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +147 -0
  3. package/dist/src/cli.d.ts +2 -0
  4. package/dist/src/cli.js +28 -0
  5. package/dist/src/index.d.ts +14 -0
  6. package/dist/src/index.js +79 -0
  7. package/dist/src/togetherai-budget.d.ts +52 -0
  8. package/dist/src/togetherai-budget.js +130 -0
  9. package/dist/src/togetherai-capabilities.d.ts +4 -0
  10. package/dist/src/togetherai-capabilities.js +1428 -0
  11. package/dist/src/togetherai-conformance.d.ts +14 -0
  12. package/dist/src/togetherai-conformance.js +452 -0
  13. package/dist/src/togetherai-connector.d.ts +164 -0
  14. package/dist/src/togetherai-connector.js +457 -0
  15. package/dist/src/togetherai-models.d.ts +19 -0
  16. package/dist/src/togetherai-models.js +49 -0
  17. package/dist/src/togetherai-scenario.d.ts +52 -0
  18. package/dist/src/togetherai-scenario.js +168 -0
  19. package/dist/src/togetherai-server.d.ts +16 -0
  20. package/dist/src/togetherai-server.js +187 -0
  21. package/dist/src/togetherai-stub.d.ts +59 -0
  22. package/dist/src/togetherai-stub.js +195 -0
  23. package/dist/src/togetherai-twin.d.ts +83 -0
  24. package/dist/src/togetherai-twin.js +1419 -0
  25. package/dist/src/togetherai-types.d.ts +207 -0
  26. package/dist/src/togetherai-types.js +26 -0
  27. package/package.json +52 -0
  28. package/src/cli.ts +27 -0
  29. package/src/index.ts +118 -0
  30. package/src/togetherai-budget.ts +156 -0
  31. package/src/togetherai-capabilities.ts +1315 -0
  32. package/src/togetherai-conformance.ts +459 -0
  33. package/src/togetherai-connector.ts +496 -0
  34. package/src/togetherai-models.ts +74 -0
  35. package/src/togetherai-scenario.ts +185 -0
  36. package/src/togetherai-server.ts +199 -0
  37. package/src/togetherai-stub.ts +197 -0
  38. package/src/togetherai-twin.ts +1448 -0
  39. package/src/togetherai-types.ts +222 -0
@@ -0,0 +1,1315 @@
1
+ // Together AI capability manifest — the EXPECTED REAL-PRODUCT SURFACE (the target), authored
2
+ // top-down from what the Together API actually does — NOT from what this twin has built. The
3
+ // denominator was enumerated from TWO first-party sources, both read on 2026-09-16:
4
+ // • Together's own published OpenAPI spec (api.together.xyz/openapi.json, captured to
5
+ // test-fixtures/togetherai-openapi.yaml): 141 paths / 156 operations — the /v1 inference
6
+ // half (chat/completions, completions, embeddings, models, files, fine-tunes, rerank,
7
+ // images, audio, batches, whoami) AND the v2 management half (endpoints, deployments,
8
+ // compute, rl, videos, evaluation, queue, tci) this pack models the INFERENCE half of;
9
+ // • `together-ai@0.53.0` (Stainless-generated from Together's own spec): the model unions,
10
+ // the SDK-only upload flow (302 redirect + x-together-file-id), whoami, and the
11
+ // TOGETHER_BASE_URL/TOGETHER_API_KEY/TOGETHER_PROJECT_ID env contract.
12
+ // Most entries start as `todo` and coverage reads LOW until the twin truly reaches 100% of the
13
+ // API. `verify()` (required to count as done) is ground truth; `expected:'done'` only on
14
+ // capabilities we genuinely claim, so a broken one shows as a regression.
15
+ //
16
+ // There are NO carve-outs. A twin is a deterministic, offline model of the vendor's API contract:
17
+ // where the vendor runs a model, the twin returns a DETERMINISTIC labeled stub, and that stub IS
18
+ // the twin's answer, not a shortfall from a "real" one. The protocol envelope (shape/streaming/
19
+ // tool_calls/usage/prompt array) is faithful. Every entry here is either done or todo.
20
+ //
21
+ // TIERING (§6 rule 3, per the groq pack's corrected reading): `core` = "first-week-of-every-
22
+ // integration". Week-one Together integrations are chat completions (+ the OpenAI-compatible
23
+ // spine) and nothing else, so `core` is reserved for the chat/streaming/tools/errors/auth spine
24
+ // plus the conformance and connector-pull backbone. Embeddings/rerank/images/audio, the Batch
25
+ // API (files + batches), fine-tunes and whoami are specialist surfaces tiered `common`. The v2
26
+ // management half (endpoints/deployments/compute/rl/videos/evaluation/queue/tci) is `edge` —
27
+ // real Together surface, out of this pack's served scope, filed honestly as todo.
28
+ //
29
+ // (Together is an API-first vendor — app.together.ai is a console, not where the work happens —
30
+ // so this pack ships NO mirror and has NO UI capabilities.)
31
+ import { mkdtempSync, rmSync } from 'node:fs';
32
+ import { tmpdir } from 'node:os';
33
+ import { join } from 'node:path';
34
+ import { checkCapabilities, type CapabilityReport, type CapabilitySpec, verifyBoundary, isInfrastructureError, harnessError } from '@volter/world-tooling';
35
+ import { pendingActions, projectResources } from '@volter/world-core';
36
+ import { handleTogetheraiTwinRequest, handleTogetheraiUploadDoor, type TogetheraiResponseEnvelope } from './togetherai-twin.ts';
37
+ import {
38
+ externalIdFor,
39
+ fullSyncTogetherai,
40
+ liveTogetheraiExecute,
41
+ pullTogetheraiState,
42
+ pushTogetheraiAction,
43
+ pushPendingTogetheraiActions,
44
+ syncTogetheraiFromReal,
45
+ togetheraiRequestForAction,
46
+ unpushableReason,
47
+ type TogetheraiExecute,
48
+ } from './togetherai-connector.ts';
49
+ import type { SseEvent } from './togetherai-types.ts';
50
+
51
+ // ── API verify: drive REAL requests against a fresh temp root, then assert status/shape ──
52
+ type Step = { m: string; p: string; b?: unknown };
53
+ type Body = Record<string, any>;
54
+
55
+ /** Run a sequence of real Together requests against an isolated root; return all responses. */
56
+ async function withRoot(steps: (h: (s: Step) => Promise<TogetheraiResponseEnvelope>, root: string) => Promise<boolean>): Promise<boolean> {
57
+ const root = mkdtempSync(join(tmpdir(), 'togetherai-cap-'));
58
+ const h = (s: Step) => handleTogetheraiTwinRequest({ method: s.m, path: s.p, body: s.b === undefined ? undefined : JSON.stringify(s.b), root });
59
+ try {
60
+ // `root` is handed to the steps too, so a verify can inspect the LOG (projectResources /
61
+ // pendingActions) and not merely the responses — the difference between proving "the reply
62
+ // did not change" and proving "nothing was written" (§9 round two).
63
+ return await verifyBoundary('togetherai.withRoot', () => steps(h, root));
64
+ } finally {
65
+ rmSync(root, { recursive: true, force: true });
66
+ }
67
+ }
68
+
69
+ /** Like withRoot, but the request helper passes request HEADERS through (for auth / the
70
+ * deterministic 429 / 402 / 503 triggers, which the trusted no-headers helper never fires). */
71
+ type StepH = Step & { headers?: Record<string, string> };
72
+ async function withRootH(steps: (h: (s: StepH) => Promise<TogetheraiResponseEnvelope>) => Promise<boolean>): Promise<boolean> {
73
+ const root = mkdtempSync(join(tmpdir(), 'togetherai-cap-'));
74
+ const h = (s: StepH) => handleTogetheraiTwinRequest({ method: s.m, path: s.p, body: s.b === undefined ? undefined : JSON.stringify(s.b), root, ...(s.headers ? { headers: s.headers } : {}) });
75
+ try {
76
+ return await verifyBoundary('togetherai.withRootH', () => steps(h));
77
+ } finally {
78
+ rmSync(root, { recursive: true, force: true });
79
+ }
80
+ }
81
+
82
+ /** Collect the streaming SSE events for a chat request against an isolated root. */
83
+ function withStream(body: unknown, fn: (events: SseEvent[], final: TogetheraiResponseEnvelope) => boolean): Promise<boolean> {
84
+ return new Promise<boolean>((resolve, reject) => {
85
+ const root = mkdtempSync(join(tmpdir(), 'togetherai-cap-'));
86
+ const events: SseEvent[] = [];
87
+ handleTogetheraiTwinRequest({ method: 'POST', path: '/v1/chat/completions', body: JSON.stringify(body), root, sseSink: (e) => events.push(e) })
88
+ .then((final) => resolve(fn(events, final)))
89
+ .catch((err) => { if (isInfrastructureError(err)) reject(harnessError('togetherai.withStream', err)); else resolve(false); })
90
+ .finally(() => rmSync(root, { recursive: true, force: true }));
91
+ });
92
+ }
93
+
94
+ /** A connector verify against an isolated root, with the injected fake executor the test builds. */
95
+ async function withConnectorRoot(id: string, fn: (root: string) => Promise<boolean>): Promise<boolean> {
96
+ const root = mkdtempSync(join(tmpdir(), 'togetherai-cap-'));
97
+ try {
98
+ return await fn(root);
99
+ } catch (err) {
100
+ if (isInfrastructureError(err)) throw harnessError(id, err);
101
+ return false;
102
+ } finally {
103
+ rmSync(root, { recursive: true, force: true });
104
+ }
105
+ }
106
+
107
+ const ok = (r: TogetheraiResponseEnvelope) => r.status >= 200 && r.status < 300;
108
+ const rid = (r: TogetheraiResponseEnvelope) => (r.body as Body)?.id as string;
109
+ const errType = (r: TogetheraiResponseEnvelope) => (r.body as Body)?.error?.type as string;
110
+ const status = (r: TogetheraiResponseEnvelope) => r.status;
111
+
112
+ // ── shorthands (mirror the groq/openai manifests) ──
113
+ const done = (id: string, area: string, title: string, dimension: CapabilitySpec['dimension'], tier: CapabilitySpec['tier'], verify: CapabilitySpec['verify']): CapabilitySpec => ({ id, area, title, dimension, tier, expected: 'done', verify });
114
+ const todo = (id: string, area: string, title: string, dimension: CapabilitySpec['dimension'], tier: CapabilitySpec['tier']): CapabilitySpec => ({ id, area, title, dimension, tier, expected: 'todo' });
115
+
116
+ const CHAT_PATH = '/v1/chat/completions';
117
+ const CHAT = (extra: Record<string, unknown> = {}) => ({ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', messages: [{ role: 'user', content: 'hello twin' }], ...extra });
118
+ const WEATHER_TOOL = { type: 'function', function: { name: 'get_weather', parameters: { type: 'object', properties: { city: { type: 'string' }, days: { type: 'integer' } } } } };
119
+ const TIME_TOOL = { type: 'function', function: { name: 'get_time', parameters: { type: 'object', properties: { tz: { type: 'string' } } } } };
120
+
121
+ /** Seed a batch-api file and a batch over it. Returns the batch id. */
122
+ async function seedBatch(h: (s: Step) => Promise<TogetheraiResponseEnvelope>): Promise<string | null> {
123
+ const f = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'batch-api', filename: 'in.jsonl', content: '{"custom_id":"a"}' } });
124
+ if (!ok(f)) return null;
125
+ const b = await h({ m: 'POST', p: '/v1/batches', b: { input_file_id: rid(f), endpoint: '/v1/chat/completions' } });
126
+ return ok(b) ? ((b.body as Body).job?.id as string) ?? null : null;
127
+ }
128
+
129
+ export const TOGETHERAI_CAPABILITIES: CapabilitySpec[] = [
130
+ // ── chat ────────────────────────────────────────────────────────────────────
131
+ done('togetherai.chat.basic', 'chat', 'POST /v1/chat/completions answers a labeled stub completion with Together envelope (choices, prompt array, usage)', 'api', 'core', () =>
132
+ withRoot(async (h) => {
133
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT() });
134
+ if (!ok(r)) return false;
135
+ const b = r.body as Body;
136
+ return b.object === 'chat.completion' && Array.isArray(b.choices) && b.choices.length === 1
137
+ && b.choices[0].message.role === 'assistant'
138
+ && typeof b.choices[0].message.content === 'string'
139
+ && String(b.choices[0].message.content).includes('[twin-stub:')
140
+ && Array.isArray(b.prompt) && b.prompt.length === 0
141
+ && typeof b.usage?.prompt_tokens === 'number' && typeof b.usage?.completion_tokens === 'number'
142
+ && typeof b.created === 'number' && typeof b.model === 'string';
143
+ })),
144
+ done('togetherai.chat.echo_prompt', 'chat', "echo:true returns Together's REQUIRED prompt array with the echoed prompt", 'api', 'core', () =>
145
+ withRoot(async (h) => {
146
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ echo: true }) });
147
+ if (!ok(r)) return false;
148
+ const prompt = (r.body as Body).prompt;
149
+ return Array.isArray(prompt) && prompt.length === 1 && typeof prompt[0].text === 'string'
150
+ && String(prompt[0].text).includes('hello twin');
151
+ })),
152
+ done('togetherai.chat.missing_model', 'chat', 'a chat request without model is a 400 invalid_request_error', 'api', 'core', () =>
153
+ withRoot(async (h) => {
154
+ const { model: _m, ...noModel } = CHAT();
155
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: noModel });
156
+ return status(r) === 400 && errType(r) === 'invalid_request_error';
157
+ })),
158
+ done('togetherai.chat.missing_messages', 'chat', 'a chat request without messages is a 400', 'api', 'core', () =>
159
+ withRoot(async (h) => {
160
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo' } });
161
+ return status(r) === 400 && errType(r) === 'invalid_request_error';
162
+ })),
163
+ done('togetherai.chat.n_range', 'chat', "Together's n is 1..128 (OpenAI-compatible freedom Groq lacks): 129 is a 400, n:3 answers 3 choices", 'api', 'core', () =>
164
+ withRoot(async (h) => {
165
+ const over = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ n: 129 }) });
166
+ if (status(over) !== 400 || errType(over) !== 'invalid_request_error') return false;
167
+ const three = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ n: 3 }) });
168
+ if (!ok(three)) return false;
169
+ const choices = (three.body as Body).choices;
170
+ return Array.isArray(choices) && choices.length === 3 && choices[0].index === 0 && choices[2].index === 2;
171
+ })),
172
+ done('togetherai.chat.logprobs_range', 'chat', "Together's logprobs is an INTEGER 0..20 (not OpenAI's boolean): 21 is a 400", 'api', 'core', () =>
173
+ withRoot(async (h) => {
174
+ const over = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ logprobs: 21 }) });
175
+ if (status(over) !== 400) return false;
176
+ const okReq = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ logprobs: 5 }) });
177
+ return ok(okReq);
178
+ })),
179
+ done('togetherai.chat.context_behavior_enum', 'chat', "context_length_exceeded_behavior is a closed enum {truncate,error}; anything else is a 400", 'api', 'core', () =>
180
+ withRoot(async (h) => {
181
+ const bad = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ context_length_exceeded_behavior: 'shrink' }) });
182
+ if (status(bad) !== 400) return false;
183
+ const good = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ context_length_exceeded_behavior: 'truncate' }) });
184
+ return ok(good);
185
+ })),
186
+ done('togetherai.chat.reasoning_effort', 'chat', "reasoning_effort {low,medium,high} surfaces a reasoning field on the assistant message; an off-enum value 400s", 'api', 'core', () =>
187
+ withRoot(async (h) => {
188
+ const bad = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ reasoning_effort: 'maximum' }) });
189
+ if (status(bad) !== 400) return false;
190
+ const good = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ reasoning_effort: 'high' }) });
191
+ if (!ok(good)) return false;
192
+ const msg = (good.body as Body).choices[0].message;
193
+ return typeof msg.reasoning === 'string' && msg.reasoning.includes('[twin-stub:');
194
+ })),
195
+ done('togetherai.chat.compliance_const', 'chat', "compliance is a const 'hipaa' on Together's schema — another value is a 400", 'api', 'core', () =>
196
+ withRoot(async (h) => {
197
+ const bad = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ compliance: 'gdpr' }) });
198
+ if (status(bad) !== 400) return false;
199
+ const good = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ compliance: 'hipaa' }) });
200
+ return ok(good);
201
+ })),
202
+ done('togetherai.chat.accepted_ignored', 'chat', "OpenAI fields Together ACCEPTS BUT IGNORES (service_tier, store, metadata, prediction) do not change the answer", 'api', 'core', () =>
203
+ withRoot(async (h) => {
204
+ const plain = await h({ m: 'POST', p: CHAT_PATH, b: CHAT() });
205
+ const decorated = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ service_tier: 'flex', store: true, metadata: { k: 'v' }, prediction: { content: 'x' } }) });
206
+ return ok(plain) && ok(decorated)
207
+ && (plain.body as Body).choices[0].message.content === (decorated.body as Body).choices[0].message.content;
208
+ })),
209
+ done('togetherai.chat.flat_model_404', 'chat', "a flat OpenAI-style model id Together does not serve (gpt-4o) is a 404, not a stub", 'api', 'core', () =>
210
+ withRoot(async (h) => {
211
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ model: 'gpt-4o' }) });
212
+ return status(r) === 404 && errType(r) === 'invalid_request_error';
213
+ })),
214
+ done('togetherai.chat.non_chat_model_404', 'chat', "asking an embedding/rerank/image/speech model to chat is a 404", 'api', 'core', () =>
215
+ withRoot(async (h) => {
216
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ model: 'WhereIsAI/UAE-Large-V1' }) });
217
+ return status(r) === 404;
218
+ })),
219
+ done('togetherai.chat.stop_truncates', 'chat', "stop sequences truncate the completion at the EARLIEST occurrence across the list", 'api', 'core', () =>
220
+ withRoot(async (h) => {
221
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ stop: ['zzz', 'deterministic'] }) });
222
+ if (!ok(r)) return false;
223
+ const content = String((r.body as Body).choices[0].message.content);
224
+ return !content.includes('deterministic') && content.length > 0;
225
+ })),
226
+ done('togetherai.chat.max_tokens_length', 'chat', "a max_tokens below the stub length truncates and reports finish_reason:'length'; a NON-INTEGER max_tokens is a 400", 'api', 'core', () =>
227
+ withRoot(async (h) => {
228
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ max_tokens: 5 }) });
229
+ if (!ok(r) || (r.body as Body).choices[0].finish_reason !== 'length') return false;
230
+ const bad = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ max_tokens: 'five' }) });
231
+ return status(bad) === 400 && errType(bad) === 'invalid_request_error';
232
+ })),
233
+
234
+ // ── context length (Together's own 403) ─────────────────────────────────────
235
+ done('togetherai.chat.context_403', 'chat', "input + max_tokens beyond the model window answers Together's 403 context-length error (NOT 400/413)", 'api', 'core', () =>
236
+ withRoot(async (h) => {
237
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ max_tokens: 200_000 }) });
238
+ return status(r) === 403 && errType(r) === 'invalid_request_error'
239
+ && String((r.body as Body).error.message).includes('maximum context length');
240
+ })),
241
+ done('togetherai.chat.context_truncate', 'chat', "context_length_exceeded_behavior:'truncate' caps max_tokens to the window instead of 403", 'api', 'core', () =>
242
+ withRoot(async (h) => {
243
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ max_tokens: 200_000, context_length_exceeded_behavior: 'truncate' }) });
244
+ // The capability is the AVOIDANCE: with truncate, an over-window request answers 200 where
245
+ // the default answers 403. (The deterministic stub's completion is far shorter than the
246
+ // window even after the cap, so `finish_reason:'length'` is not part of this contract.)
247
+ return ok(r) && Array.isArray((r.body as Body).choices);
248
+ })),
249
+
250
+ // ── tools ───────────────────────────────────────────────────────────────────
251
+ done('togetherai.tools.first_tool_called', 'tools', 'with tools, the stub deterministically calls the first tool with schema-typed placeholder arguments', 'api', 'core', () =>
252
+ withRoot(async (h) => {
253
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ tools: [WEATHER_TOOL, TIME_TOOL] }) });
254
+ if (!ok(r)) return false;
255
+ const msg = (r.body as Body).choices[0].message;
256
+ return (r.body as Body).choices[0].finish_reason === 'tool_calls'
257
+ && Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0
258
+ // The FIRST call is the first tool in the list, with schema-typed placeholder arguments
259
+ // (parallel:true calls every tool; the first call is still the first-listed one).
260
+ && msg.tool_calls[0].function.name === 'get_weather'
261
+ && msg.tool_calls[0].function.arguments.includes('"city"');
262
+ })),
263
+ done('togetherai.tools.tool_choice_none', 'tools', "tool_choice:'none' forbids the tool call and answers text", 'api', 'core', () =>
264
+ withRoot(async (h) => {
265
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ tools: [WEATHER_TOOL], tool_choice: 'none' }) });
266
+ return ok(r) && (r.body as Body).choices[0].finish_reason === 'stop'
267
+ && !(r.body as Body).choices[0].message.tool_calls;
268
+ })),
269
+ done('togetherai.tools.tool_choice_named', 'tools', "a named tool_choice {function:{name}} forces THAT tool; an off-enum STRING tool_choice and a named tool_choice WITHOUT function.name are each a 400", 'api', 'core', () =>
270
+ withRoot(async (h) => {
271
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ tools: [WEATHER_TOOL, TIME_TOOL], tool_choice: { function: { name: 'get_time' } } }) });
272
+ if (!ok(r) || (r.body as Body).choices[0].message.tool_calls?.[0]?.function.name !== 'get_time') return false;
273
+ const badEnum = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ tools: [WEATHER_TOOL], tool_choice: 'sometimes' }) });
274
+ if (status(badEnum) !== 400) return false;
275
+ const noName = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ tools: [WEATHER_TOOL], tool_choice: { function: {} } }) });
276
+ return status(noName) === 400 && errType(noName) === 'invalid_request_error';
277
+ })),
278
+ done('togetherai.tools.parallel_default', 'tools', "parallel_tool_calls defaults true: every provided tool is called; false calls exactly one", 'api', 'core', () =>
279
+ withRoot(async (h) => {
280
+ const all = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ tools: [WEATHER_TOOL, TIME_TOOL] }) });
281
+ const one = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ tools: [WEATHER_TOOL, TIME_TOOL], parallel_tool_calls: false }) });
282
+ return ok(all) && ok(one)
283
+ && (all.body as Body).choices[0].message.tool_calls.length === 2
284
+ && (one.body as Body).choices[0].message.tool_calls.length === 1;
285
+ })),
286
+ done('togetherai.tools.legacy_functions', 'tools', "Together's DEPRECATED functions param answers the DEPRECATED function_call shape with finish_reason:'function_call'", 'api', 'core', () =>
287
+ withRoot(async (h) => {
288
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ functions: [{ name: 'get_weather', parameters: { type: 'object', properties: { city: { type: 'string' } } } }] }) });
289
+ if (!ok(r)) return false;
290
+ const choice = (r.body as Body).choices[0];
291
+ return choice.finish_reason === 'function_call' && choice.message.function_call?.name === 'get_weather';
292
+ })),
293
+ done('togetherai.tools.tool_result_turn', 'tools', "a tool result turn (role:'tool' with tool_call_id) is accepted and answered", 'api', 'core', () =>
294
+ withRoot(async (h) => {
295
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', messages: [
296
+ { role: 'assistant', tool_calls: [{ id: 'call_x', type: 'function', function: { name: 'get_weather', arguments: '{}' } }] },
297
+ { role: 'tool', tool_call_id: 'call_x', content: 'sunny' },
298
+ ] } });
299
+ return ok(r) && typeof (r.body as Body).choices[0].message.content === 'string';
300
+ })),
301
+
302
+ // ── structured outputs ──────────────────────────────────────────────────────
303
+ done('togetherai.structured.json_object', 'structured_outputs', "response_format json_object answers valid JSON", 'api', 'common', () =>
304
+ withRoot(async (h) => {
305
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ response_format: { type: 'json_object' } }) });
306
+ if (!ok(r)) return false;
307
+ const content = String((r.body as Body).choices[0].message.content);
308
+ try { JSON.parse(content); return true; } catch { return false; }
309
+ })),
310
+ done('togetherai.structured.json_schema_name_required', 'structured_outputs', "Together's json_schema REQUIRES json_schema.name (≤64, [a-zA-Z0-9_-]) — an omission is a 400", 'api', 'common', () =>
311
+ withRoot(async (h) => {
312
+ const noName = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ response_format: { type: 'json_schema', json_schema: { schema: { type: 'object', properties: { a: { type: 'string' } } } } } }) });
313
+ if (status(noName) !== 400) return false;
314
+ const badName = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ response_format: { type: 'json_schema', json_schema: { name: 'bad name!', schema: {} } } }) });
315
+ if (status(badName) !== 400) return false;
316
+ const good = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ response_format: { type: 'json_schema', json_schema: { name: 'my-schema_1', schema: { type: 'object', properties: { a: { type: 'string' } } } } } }) });
317
+ if (!ok(good)) return false;
318
+ try { JSON.parse(String((good.body as Body).choices[0].message.content)); return true; } catch { return false; }
319
+ })),
320
+ done('togetherai.structured.response_format_bad_type', 'structured_outputs', "an unknown response_format.type is a 400", 'api', 'common', () =>
321
+ withRoot(async (h) => {
322
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT({ response_format: { type: 'xml' } }) });
323
+ return status(r) === 400;
324
+ })),
325
+
326
+ // ── completions (legacy text) ───────────────────────────────────────────────
327
+ done('togetherai.completions.basic', 'chat', 'POST /v1/completions answers object:text.completion with the REQUIRED prompt array + usage', 'api', 'common', () =>
328
+ withRoot(async (h) => {
329
+ const r = await h({ m: 'POST', p: '/v1/completions', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', prompt: 'Once upon a time' } });
330
+ if (!ok(r)) return false;
331
+ const b = r.body as Body;
332
+ return b.object === 'text.completion' && Array.isArray(b.prompt) && b.prompt.length === 1
333
+ && typeof b.choices[0].text === 'string' && typeof b.usage.total_tokens === 'number';
334
+ })),
335
+ done('togetherai.completions.missing_prompt', 'chat', 'a completion without prompt is a 400', 'api', 'common', () =>
336
+ withRoot(async (h) => {
337
+ const r = await h({ m: 'POST', p: '/v1/completions', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo' } });
338
+ return status(r) === 400;
339
+ })),
340
+ done('togetherai.completions.non_chat_model_404', 'chat', 'asking an embedding model to complete text is a 404, never a stub', 'api', 'common', () =>
341
+ withRoot(async (h) => {
342
+ const r = await h({ m: 'POST', p: '/v1/completions', b: { model: 'BAAI/bge-large-en-v1.5', prompt: 'x' } });
343
+ return status(r) === 404 && errType(r) === 'invalid_request_error';
344
+ })),
345
+ done('togetherai.completions.max_tokens_truncates', 'chat', "a max_tokens below the stub length truncates the text and reports finish_reason:'length'; a non-integer max_tokens is a 400", 'api', 'common', () =>
346
+ withRoot(async (h) => {
347
+ const r = await h({ m: 'POST', p: '/v1/completions', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', prompt: 'x', max_tokens: 5 } });
348
+ if (!ok(r)) return false;
349
+ const b = r.body as Body;
350
+ if (b.choices[0].finish_reason !== 'length' || b.choices[0].text.length === 0) return false;
351
+ const bad = await h({ m: 'POST', p: '/v1/completions', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', prompt: 'x', max_tokens: 2.5 } });
352
+ return status(bad) === 400 && errType(bad) === 'invalid_request_error';
353
+ })),
354
+
355
+ // ── streaming ───────────────────────────────────────────────────────────────
356
+ done('togetherai.stream.chunk_sequence', 'streaming', "stream:true emits role chunk → content chunks → finish_reason chunk → usage tail → [DONE], every chunk carrying Together's nullable usage+warnings", 'api', 'core', () =>
357
+ withStream(CHAT({ stream: true }), (events, final) => {
358
+ if (!ok(final)) return false;
359
+ const data = events.filter((e) => !e.done).map((e) => e.data as Body);
360
+ if (!data.length) return false;
361
+ if (data.some((c) => c.object !== 'chat.completion.chunk')) return false;
362
+ if (!data.every((c) => 'usage' in c && 'warnings' in c)) return false;
363
+ const first = data[0];
364
+ if (first.choices?.[0]?.delta?.role !== 'assistant') return false;
365
+ const withFinish = data.filter((c) => c.choices?.[0]?.finish_reason);
366
+ if (withFinish.length !== 1 || withFinish[0].choices[0].finish_reason !== 'stop') return false;
367
+ const tail = data[data.length - 1];
368
+ if (!Array.isArray(tail.choices) || tail.choices.length !== 0) return false;
369
+ if (typeof tail.usage?.total_tokens !== 'number') return false;
370
+ return events[events.length - 1].done === true;
371
+ })),
372
+ done('togetherai.stream.tools_stream', 'streaming', 'a tool-call completion streams tool_calls deltas then the finish_reason chunk', 'api', 'core', () =>
373
+ withStream(CHAT({ stream: true, tools: [WEATHER_TOOL] }), (events) => {
374
+ const data = events.filter((e) => !e.done).map((e) => e.data as Body);
375
+ const toolChunks = data.filter((c) => c.choices?.[0]?.delta?.tool_calls);
376
+ const finish = data.find((c) => c.choices?.[0]?.finish_reason);
377
+ return toolChunks.length >= 2 && finish?.choices[0].finish_reason === 'tool_calls';
378
+ })),
379
+ done('togetherai.stream.pre_stream_refusal', 'streaming', 'a pre-stream failure (missing messages) answers its REAL 400 on the stream request — never a 200 event-stream refusal', 'api', 'core', () =>
380
+ withStream({ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', stream: true }, (_events, final) => status(final) === 400 && errType(final) === 'invalid_request_error')),
381
+ done('togetherai.stream.reasoning_chunk', 'streaming', 'a reasoning_effort request streams the reasoning delta before content', 'api', 'core', () =>
382
+ withStream(CHAT({ stream: true, reasoning_effort: 'high' }), (events) => {
383
+ const data = events.filter((e) => !e.done).map((e) => e.data as Body);
384
+ const reasoningIdx = data.findIndex((c) => c.choices?.[0]?.delta?.reasoning);
385
+ const contentIdx = data.findIndex((c) => c.choices?.[0]?.delta?.content);
386
+ return reasoningIdx >= 0 && contentIdx > reasoningIdx;
387
+ })),
388
+ done('togetherai.stream.completions_stream', 'streaming', 'the LEGACY /v1/completions streams too: per-piece token chunks then the finish chunk carrying the usage (finish_reason at the chunk TOP level, per the SDK CompletionChunk)', 'api', 'common', () =>
389
+ new Promise<boolean>((resolve, reject) => {
390
+ const root = mkdtempSync(join(tmpdir(), 'togetherai-cap-'));
391
+ const events: SseEvent[] = [];
392
+ handleTogetheraiTwinRequest({ method: 'POST', path: '/v1/completions', body: JSON.stringify({ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', prompt: 'x', stream: true }), root, sseSink: (e) => events.push(e) })
393
+ .then((final) => {
394
+ const data = events.filter((e) => !e.done).map((e) => e.data as Body);
395
+ const finish = data.find((c) => c.finish_reason);
396
+ resolve(ok(final) && data.length >= 2 && data.every((c) => c.object === 'completion.chunk')
397
+ && finish?.finish_reason === 'stop' && typeof finish.usage?.total_tokens === 'number'
398
+ && events[events.length - 1].done === true);
399
+ })
400
+ .catch((err) => { if (isInfrastructureError(err)) reject(harnessError('togetherai.stream.completions_stream', err)); else resolve(false); })
401
+ .finally(() => rmSync(root, { recursive: true, force: true }));
402
+ })),
403
+
404
+ // ── embeddings ──────────────────────────────────────────────────────────────
405
+ done('togetherai.embeddings.basic', 'embeddings', 'POST /v1/embeddings answers deterministic L2-normalized vectors with the documented dimensionality and NO usage key', 'api', 'common', () =>
406
+ withRoot(async (h) => {
407
+ const r = await h({ m: 'POST', p: '/v1/embeddings', b: { model: 'WhereIsAI/UAE-Large-V1', input: 'hello twin' } });
408
+ if (!ok(r)) return false;
409
+ const b = r.body as Body;
410
+ if (b.object !== 'list' || b.model !== 'WhereIsAI/UAE-Large-V1') return false;
411
+ if ('usage' in b) return false; // Together's EmbeddingsResponse has no usage key
412
+ const vec = b.data[0].embedding as number[];
413
+ if (b.data[0].object !== 'embedding' || vec.length !== 1024) return false;
414
+ const norm = Math.sqrt(vec.reduce((s: number, v: number) => s + v * v, 0));
415
+ return Math.abs(norm - 1) < 1e-6;
416
+ })),
417
+ done('togetherai.embeddings.batch_deterministic', 'embeddings', 'an array input answers one embedding per element, index-aligned and deterministic across calls', 'api', 'common', () =>
418
+ withRoot(async (h) => {
419
+ const b1 = await h({ m: 'POST', p: '/v1/embeddings', b: { model: 'BAAI/bge-base-en-v1.5', input: ['a', 'b'] } });
420
+ const b2 = await h({ m: 'POST', p: '/v1/embeddings', b: { model: 'BAAI/bge-base-en-v1.5', input: ['a', 'b'] } });
421
+ if (!ok(b1) || !ok(b2)) return false;
422
+ const d1 = (b1.body as Body).data;
423
+ const d2 = (b2.body as Body).data;
424
+ return d1.length === 2 && d1[0].index === 0 && d1[1].index === 1
425
+ && d1[0].embedding.length === 768 && JSON.stringify(d1) === JSON.stringify(d2);
426
+ })),
427
+ done('togetherai.embeddings.wrong_model', 'embeddings', 'a chat model on /v1/embeddings is a 404', 'api', 'common', () =>
428
+ withRoot(async (h) => {
429
+ const r = await h({ m: 'POST', p: '/v1/embeddings', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', input: 'x' } });
430
+ return status(r) === 404;
431
+ })),
432
+
433
+ // ── rerank (Together-native) ────────────────────────────────────────────────
434
+ done('togetherai.rerank.basic', 'rerank', 'POST /v1/rerank answers Together-native {object:rerank, results:[{index,relevance_score,document}]} with a deterministic order', 'api', 'common', () =>
435
+ withRoot(async (h) => {
436
+ const r = await h({ m: 'POST', p: '/v1/rerank', b: { model: 'Salesforce/Llama-Rank-v1', query: 'q', documents: ['alpha', 'beta', 'gamma'] } });
437
+ if (!ok(r)) return false;
438
+ const b = r.body as Body;
439
+ if (b.object !== 'rerank' || !Array.isArray(b.results) || b.results.length !== 3) return false;
440
+ const idxs = b.results.map((x: Body) => x.index).sort((a: number, c: number) => a - c);
441
+ if (JSON.stringify(idxs) !== '[0,1,2]') return false;
442
+ return b.results.every((x: Body) => typeof x.relevance_score === 'number');
443
+ })),
444
+ done('togetherai.rerank.top_n', 'rerank', 'top_n truncates the results; return_documents:false omits the document text', 'api', 'common', () =>
445
+ withRoot(async (h) => {
446
+ const top = await h({ m: 'POST', p: '/v1/rerank', b: { model: 'Salesforce/Llama-Rank-v1', query: 'q', documents: ['a', 'b', 'c'], top_n: 2 } });
447
+ if (!ok(top) || (top.body as Body).results.length !== 2) return false;
448
+ const bare = await h({ m: 'POST', p: '/v1/rerank', b: { model: 'Salesforce/Llama-Rank-v1', query: 'q', documents: ['a', 'b'], return_documents: false } });
449
+ return ok(bare) && (bare.body as Body).results.every((x: Body) => !('document' in x));
450
+ })),
451
+ done('togetherai.rerank.missing_documents', 'rerank', 'a rerank without documents is a 400', 'api', 'common', () =>
452
+ withRoot(async (h) => {
453
+ const r = await h({ m: 'POST', p: '/v1/rerank', b: { model: 'Salesforce/Llama-Rank-v1', query: 'q' } });
454
+ return status(r) === 400;
455
+ })),
456
+
457
+ // ── images ──────────────────────────────────────────────────────────────────
458
+ done('togetherai.images.basic', 'images', 'POST /v1/images/generations answers a labeled stub image (url or b64_json discriminated); output_format defaults to jpeg (the SDK documents "Defaults to `jpeg`") and an off-enum value is a 400', 'api', 'common', () =>
459
+ withRoot(async (h) => {
460
+ // The stub label carries the format, base64-encoded inside the data: URL — decode to read it.
461
+ const labelOf = (u: unknown) => Buffer.from(String(u).replace(/^data:[^,]*,/, ''), 'base64').toString('utf8');
462
+ const r = await h({ m: 'POST', p: '/v1/images/generations', b: { model: 'black-forest-labs/FLUX.1-schnell', prompt: 'a cat' } });
463
+ if (!ok(r)) return false;
464
+ const d = (r.body as Body).data;
465
+ if (!(Array.isArray(d) && d.length === 1 && d[0].type === 'url' && typeof d[0].url === 'string'
466
+ && d[0].url.startsWith('data:') && labelOf(d[0].url).includes('jpeg image stub'))) return false;
467
+ // The default is jpeg, NOT png: the label names it, and an off-enum output_format is a 400.
468
+ const png = await h({ m: 'POST', p: '/v1/images/generations', b: { model: 'black-forest-labs/FLUX.1-schnell', prompt: 'a cat', output_format: 'png' } });
469
+ if (!ok(png) || !labelOf((png.body as Body).data[0].url).includes('png image stub')) return false;
470
+ const bad = await h({ m: 'POST', p: '/v1/images/generations', b: { model: 'black-forest-labs/FLUX.1-schnell', prompt: 'a cat', output_format: 'webp' } });
471
+ return status(bad) === 400 && errType(bad) === 'invalid_request_error';
472
+ })),
473
+ done('togetherai.images.b64_and_count', 'images', "response_format 'base64' (Together's enum, not OpenAI's b64_json) returns base64 bodies; n answers n images", 'api', 'common', () =>
474
+ withRoot(async (h) => {
475
+ const r = await h({ m: 'POST', p: '/v1/images/generations', b: { model: 'black-forest-labs/FLUX.1-schnell', prompt: 'a cat', response_format: 'base64', n: 2 } });
476
+ if (!ok(r)) return false;
477
+ const d = (r.body as Body).data;
478
+ if (d.length !== 2 || !d.every((x: Body) => x.type === 'b64_json' && typeof x.b64_json === 'string')) return false;
479
+ // OpenAI's value is refused, not accepted (the OpenAI-compatibility line: Together's image
480
+ // API is its own).
481
+ const openaiValue = await h({ m: 'POST', p: '/v1/images/generations', b: { model: 'black-forest-labs/FLUX.1-schnell', prompt: 'a cat', response_format: 'b64_json' } });
482
+ return openaiValue.status === 400;
483
+ })),
484
+ done('togetherai.images.wrong_model', 'images', 'a chat model on /v1/images/generations is a 404', 'api', 'common', () =>
485
+ withRoot(async (h) => {
486
+ const r = await h({ m: 'POST', p: '/v1/images/generations', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', prompt: 'x' } });
487
+ return status(r) === 404;
488
+ })),
489
+
490
+ // ── audio ───────────────────────────────────────────────────────────────────
491
+ done('togetherai.audio.speech', 'audio', 'POST /v1/audio/speech answers a labeled stub body for a closed 3-model speech union; a chat model 404s', 'api', 'common', () =>
492
+ withRoot(async (h) => {
493
+ const r = await h({ m: 'POST', p: '/v1/audio/speech', b: { model: 'cartesia/sonic', input: 'hello', voice: 'female' } });
494
+ if (!ok(r) || typeof r.body !== 'string' || !String(r.body).includes('[twin-stub:')) return false;
495
+ const bad = await h({ m: 'POST', p: '/v1/audio/speech', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', input: 'hello', voice: 'female' } });
496
+ return status(bad) === 404;
497
+ })),
498
+ done('togetherai.audio.speech_validations', 'audio', 'speech without input or voice is a 400; an off-union response_format is a 400', 'api', 'common', () =>
499
+ withRoot(async (h) => {
500
+ const noVoice = await h({ m: 'POST', p: '/v1/audio/speech', b: { model: 'cartesia/sonic', input: 'hello' } });
501
+ if (status(noVoice) !== 400) return false;
502
+ const badFormat = await h({ m: 'POST', p: '/v1/audio/speech', b: { model: 'cartesia/sonic', input: 'hello', voice: 'female', response_format: 'aac' } });
503
+ return status(badFormat) === 400;
504
+ })),
505
+ done('togetherai.audio.transcriptions', 'audio', 'POST /v1/audio/transcriptions answers json/text/verbose_json stub transcripts seeded from the audio reference', 'api', 'common', () =>
506
+ withRoot(async (h) => {
507
+ const j = await h({ m: 'POST', p: '/v1/audio/transcriptions', b: { model: 'cartesia/sonic', file: 'clip.wav' } });
508
+ if (!ok(j) || String((j.body as Body).text).includes('clip.wav') === false) return false;
509
+ const t = await h({ m: 'POST', p: '/v1/audio/transcriptions', b: { model: 'cartesia/sonic', file: 'clip.wav', response_format: 'text' } });
510
+ if (!ok(t) || typeof t.body !== 'string') return false;
511
+ const v = await h({ m: 'POST', p: '/v1/audio/transcriptions', b: { model: 'cartesia/sonic', file: 'clip.wav', response_format: 'verbose_json' } });
512
+ const vb = v.body as Body;
513
+ return ok(v) && vb.task === 'transcribe' && typeof vb.duration === 'number' && Array.isArray(vb.segments);
514
+ })),
515
+ done('togetherai.audio.translations', 'audio', 'POST /v1/audio/translations mirrors transcriptions with task:translate', 'api', 'common', () =>
516
+ withRoot(async (h) => {
517
+ const r = await h({ m: 'POST', p: '/v1/audio/translations', b: { model: 'cartesia/sonic', url: 'https://example.com/a.wav', response_format: 'verbose_json' } });
518
+ return ok(r) && (r.body as Body).task === 'translate';
519
+ })),
520
+ done('togetherai.audio.requires_source', 'audio', 'a transcription with neither file nor url is a 400', 'api', 'common', () =>
521
+ withRoot(async (h) => {
522
+ const r = await h({ m: 'POST', p: '/v1/audio/transcriptions', b: { model: 'cartesia/sonic' } });
523
+ return status(r) === 400;
524
+ })),
525
+
526
+ // ── models (static catalog) ─────────────────────────────────────────────────
527
+ done('togetherai.models.list_bare_array', 'models', 'GET /v1/models answers a BARE ARRAY of ModelInfo (id/object/created/type REQUIRED), not an OpenAI list envelope', 'api', 'core', () =>
528
+ withRoot(async (h) => {
529
+ const r = await h({ m: 'GET', p: '/v1/models' });
530
+ if (!ok(r) || !Array.isArray(r.body)) return false;
531
+ const list = r.body as Body[];
532
+ return list.length > 0 && list.every((m) => typeof m.id === 'string' && m.object === 'model' && typeof m.created === 'number' && typeof m.type === 'string');
533
+ })),
534
+ done('togetherai.models.retrieve_slashed_id', 'models', 'GET /v1/models/:id resolves ids containing slashes (Together model ids are org/model)', 'api', 'core', () =>
535
+ withRoot(async (h) => {
536
+ const r = await h({ m: 'GET', p: '/v1/models/meta-llama/Llama-3.3-70B-Instruct-Turbo' });
537
+ if (!ok(r) || (r.body as Body).id !== 'meta-llama/Llama-3.3-70B-Instruct-Turbo') return false;
538
+ const missing = await h({ m: 'GET', p: '/v1/models/nope/none' });
539
+ return status(missing) === 404;
540
+ })),
541
+
542
+ // ── whoami ──────────────────────────────────────────────────────────────────
543
+ done('togetherai.whoami', 'whoami', 'GET /v1/whoami answers the WhoamiResponse identity (api_key_id/project/organization ids)', 'api', 'common', () =>
544
+ withRoot(async (h) => {
545
+ const r = await h({ m: 'GET', p: '/v1/whoami' });
546
+ if (!ok(r)) return false;
547
+ const b = r.body as Body;
548
+ return typeof b.api_key_id === 'string' && typeof b.project_id === 'string' && typeof b.organization_id === 'string';
549
+ })),
550
+ done('togetherai.protocol.non_v1_404', 'protocol', "everything Together's inference API serves hangs off /v1 — a path outside it (and any unknown /v1 route) is a 404 naming the prefix, never a stub", 'api', 'core', () =>
551
+ withRoot(async (h) => {
552
+ const outside = await h({ m: 'GET', p: '/v2/models' });
553
+ if (status(outside) !== 404 || !String((outside.body as Body).error.message).includes('/v1')) return false;
554
+ const root_ = await h({ m: 'GET', p: '/' });
555
+ if (status(root_) !== 404) return false;
556
+ const unknownV1 = await h({ m: 'GET', p: '/v1/zzz_nope' });
557
+ return status(unknownV1) === 404 && errType(unknownV1) === 'invalid_request_error';
558
+ })),
559
+
560
+ // ── files (stateful; Together-native shape) ─────────────────────────────────
561
+ done('togetherai.files.create_list_get', 'files', "POST /v1/files/upload (the spec's create) makes a file with Together purposes, GET lists {data:[...]}, GET :id retrieves the FileResponse with Processed/FileType; an explicit file_type is honored and an off-set one is a 400", 'api', 'common', () =>
562
+ withRoot(async (h) => {
563
+ const c = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', filename: 'train.jsonl', content: '{"x":1}' } });
564
+ if (!ok(c)) return false;
565
+ const fb = c.body as Body;
566
+ if (fb.object !== 'file' || fb.Processed !== true || fb.FileType !== 'jsonl') return false;
567
+ // An explicit file_type overrides the filename's extension (§9 round two, R2-D3: the old
568
+ // OR-condition silently discarded it).
569
+ const explicit = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'batch-api', filename: 'mislabeled.jsonl', file_type: 'csv', content: 'a,b' } });
570
+ if (!ok(explicit) || (explicit.body as Body).FileType !== 'csv') return false;
571
+ // An off-set file_type is a 400 (Together's FileType is the closed {csv,jsonl,parquet}).
572
+ const invalid = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'batch-api', filename: 'doc.docx', file_type: 'docx', content: 'x' } });
573
+ if (invalid.status !== 400) return false;
574
+ const list = await h({ m: 'GET', p: '/v1/files' });
575
+ if (!ok(list) || !Array.isArray((list.body as Body).data) || (list.body as Body).data.length !== 2) return false;
576
+ const one = await h({ m: 'GET', p: `/v1/files/${fb.id}` });
577
+ return ok(one) && (one.body as Body).filename === 'train.jsonl';
578
+ })),
579
+ done('togetherai.files.purposes_closed', 'files', "Together's FilePurpose is a closed set {fine-tune,eval,batch-api} — OpenAI's 'batch' purpose is a 400", 'api', 'common', () =>
580
+ withRoot(async (h) => {
581
+ const openai = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'batch', filename: 'x.jsonl', content: '{}' } });
582
+ if (status(openai) !== 400) return false;
583
+ const evalOk = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'eval', filename: 'e.jsonl', content: '{}' } });
584
+ const batchOk = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'batch-api', filename: 'b.jsonl', content: '{}' } });
585
+ return ok(evalOk) && ok(batchOk);
586
+ })),
587
+ done('togetherai.files.delete', 'files', 'DELETE /v1/files/:id removes the file from the list, a re-GET 404s, and DELETE of an UNKNOWN id is a 404 (never a fake success)', 'api', 'common', () =>
588
+ withRoot(async (h, root) => {
589
+ const missing = await h({ m: 'DELETE', p: '/v1/files/file_nope' });
590
+ if (status(missing) !== 404) return false;
591
+ const c = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', filename: 'gone.jsonl', content: 'x' } });
592
+ if (!ok(c)) return false;
593
+ const fid = rid(c);
594
+ const del = await h({ m: 'DELETE', p: `/v1/files/${fid}` });
595
+ if (!ok(del) || (del.body as Body).deleted !== true) return false;
596
+ const list = await h({ m: 'GET', p: '/v1/files' });
597
+ if ((list.body as Body).data.length !== 0) return false;
598
+ const gone = await h({ m: 'GET', p: `/v1/files/${fid}` });
599
+ if (status(gone) !== 404) return false;
600
+ // Nothing was written beyond the delete itself: the create + delete pair, the delete last.
601
+ const actions = pendingActions('togetherai', root);
602
+ return actions.length === 2 && actions[1].operation === 'file.delete';
603
+ })),
604
+ done('togetherai.files.upload_multipart', 'files', "the spec's POST /v1/files/upload (multipart) creates the file", 'api', 'common', () =>
605
+ withRoot(async (h) => {
606
+ const r = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', filename: 'up.jsonl', content: '{"a":1}' } });
607
+ return ok(r) && (r.body as Body).filename === 'up.jsonl';
608
+ })),
609
+ done('togetherai.files.malformed_escape_404', 'files', 'GET /v1/files/%zz — a malformed percent-escape — answers the vendor 404, not an internal error', 'api', 'common', () =>
610
+ // HOLLOW BY METHOD (2026-09-16 sweep): the behavior is a try/catch, and the sweep's two
611
+ // families (GUARD `if (…)`→false, PROPERTY `key: v,`→undefined) cannot reach a try/catch —
612
+ // no mechanical mutation lands. Hand-walked instead: deleting the try/catch (decSafe becomes
613
+ // a bare decodeURIComponent) reddens THIS cell — the pin is live, just outside the sweep's
614
+ // grammar.
615
+ withRoot(async (h) => {
616
+ const r = await h({ m: 'GET', p: '/v1/files/%zz' });
617
+ return status(r) === 404 && errType(r) === 'invalid_request_error';
618
+ })),
619
+ done('togetherai.files.no_json_create', 'files', "the spec has NO JSON create at POST /v1/files (GET only there) — a JSON or EMPTY body answers the vendor's 400 naming the real doors, and mints nothing", 'api', 'common', () =>
620
+ withRoot(async (h, root) => {
621
+ const json = await h({ m: 'POST', p: '/v1/files', b: { purpose: 'batch-api', filename: 'x.jsonl', content: '{}' } });
622
+ if (status(json) !== 400 || errType(json) !== 'invalid_request_error') return false;
623
+ const empty = await h({ m: 'POST', p: '/v1/files', b: '' });
624
+ if (status(empty) !== 400) return false;
625
+ // The refusal MINTS NOTHING: no stored file, no action.
626
+ const list = await h({ m: 'GET', p: '/v1/files' });
627
+ if ((list.body as Body).data.length !== 0) return false;
628
+ return pendingActions('togetherai', root).length === 0;
629
+ })),
630
+ // ── EMPTY/PARTIAL REQUESTS ON EVERY WRITE DOOR (the §9 round-three CLASS fix) ──────────────
631
+ // One titled claim per door: a request lacking the resource's required parts answers the
632
+ // vendor's 4xx envelope and stores NOTHING (no row, no action). A required field must never be
633
+ // defaulted into existence — the round-three blocker was exactly that default (`purpose` →
634
+ // 'fine-tune', `filename` → 'upload.jsonl') minting a file from a bodyless POST. Each verify
635
+ // asserts status + envelope AND the unchanged store, so removing the guard reddens it.
636
+ done('togetherai.files.upload_empty_400', 'files', "POST /v1/files/upload with NO body answers the vendor's 400 ('purpose' is a required property) and stores nothing — the required parts are never defaulted (the round-three class fix)", 'api', 'common', () =>
637
+ withRoot(async (h, root) => {
638
+ const r = await h({ m: 'POST', p: '/v1/files/upload', b: undefined });
639
+ if (status(r) !== 400 || errType(r) !== 'invalid_request_error') return false;
640
+ if (!String((r.body as Body)?.error?.message).includes("'purpose'")) return false;
641
+ const list = await h({ m: 'GET', p: '/v1/files' });
642
+ if ((list.body as Body).data.length !== 0) return false;
643
+ return pendingActions('togetherai', root).length === 0;
644
+ })),
645
+ done('togetherai.files.upload_empty_json_400', 'files', "POST /v1/files/upload with an EMPTY JSON object answers the vendor's 400 and stores nothing", 'api', 'common', () =>
646
+ withRoot(async (h, root) => {
647
+ const r = await h({ m: 'POST', p: '/v1/files/upload', b: {} });
648
+ if (status(r) !== 400 || errType(r) !== 'invalid_request_error') return false;
649
+ const list = await h({ m: 'GET', p: '/v1/files' });
650
+ if ((list.body as Body).data.length !== 0) return false;
651
+ return pendingActions('togetherai', root).length === 0;
652
+ })),
653
+ done('togetherai.files.upload_no_filename_400', 'files', "POST /v1/files/upload with a purpose but NO file/filename part (a multipart without its file part, adapted) answers the vendor's 400 ('filename' is a required property) and stores nothing — filename is never defaulted to 'upload.jsonl'", 'api', 'common', () =>
654
+ withRoot(async (h, root) => {
655
+ const r = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', content: '{}' } });
656
+ if (status(r) !== 400 || errType(r) !== 'invalid_request_error') return false;
657
+ if (!String((r.body as Body)?.error?.message).includes("'filename'")) return false;
658
+ const list = await h({ m: 'GET', p: '/v1/files' });
659
+ if ((list.body as Body).data.length !== 0) return false;
660
+ return pendingActions('togetherai', root).length === 0;
661
+ })),
662
+ done('togetherai.files.upload_no_purpose_400', 'files', "POST /v1/files/upload with a filename but NO purpose answers the vendor's 400 and stores nothing — purpose is never defaulted to 'fine-tune'", 'api', 'common', () =>
663
+ withRoot(async (h, root) => {
664
+ const r = await h({ m: 'POST', p: '/v1/files/upload', b: { filename: 'x.jsonl', content: '{}' } });
665
+ if (status(r) !== 400 || errType(r) !== 'invalid_request_error') return false;
666
+ const list = await h({ m: 'GET', p: '/v1/files' });
667
+ if ((list.body as Body).data.length !== 0) return false;
668
+ return pendingActions('togetherai', root).length === 0;
669
+ })),
670
+ done('togetherai.files.sdk_flow_missing_name_400', 'files', "the SDK redirect flow with purpose in the query but NO file_name answers the vendor's 400 and stores nothing — the 302 is never minted for a half-specified flow", 'api', 'common', () =>
671
+ withRoot(async (h, root) => {
672
+ const r = await h({ m: 'POST', p: '/v1/files?purpose=fine-tune&file_type=jsonl', b: '' });
673
+ if (status(r) !== 400 || errType(r) !== 'invalid_request_error') return false;
674
+ if (!String((r.body as Body)?.error?.message).includes("'filename'")) return false;
675
+ const list = await h({ m: 'GET', p: '/v1/files' });
676
+ if ((list.body as Body).data.length !== 0) return false;
677
+ return pendingActions('togetherai', root).length === 0;
678
+ })),
679
+ done('togetherai.files.sdk_flow_missing_purpose_400', 'files', "the SDK redirect flow with file_name in the query but NO purpose answers the vendor's 400 and stores nothing", 'api', 'common', () =>
680
+ withRoot(async (h, root) => {
681
+ const r = await h({ m: 'POST', p: '/v1/files?file_name=rows.jsonl&file_type=jsonl', b: '' });
682
+ if (status(r) !== 400 || errType(r) !== 'invalid_request_error') return false;
683
+ if (!String((r.body as Body)?.error?.message).includes("'purpose'")) return false;
684
+ const list = await h({ m: 'GET', p: '/v1/files' });
685
+ if ((list.body as Body).data.length !== 0) return false;
686
+ return pendingActions('togetherai', root).length === 0;
687
+ })),
688
+ done('togetherai.files.sdk_flow_empty_query_400', 'files', "POST /v1/files with an EMPTY query and empty body answers the vendor's 400 naming the real doors and stores nothing", 'api', 'common', () =>
689
+ withRoot(async (h, root) => {
690
+ const r = await h({ m: 'POST', p: '/v1/files', b: '' });
691
+ if (status(r) !== 400 || errType(r) !== 'invalid_request_error') return false;
692
+ const list = await h({ m: 'GET', p: '/v1/files' });
693
+ if ((list.body as Body).data.length !== 0) return false;
694
+ return pendingActions('togetherai', root).length === 0;
695
+ })),
696
+ done('togetherai.files.upload_door_unknown_id_404', 'files', "PUT /twin/upload/<id> for an UNKNOWN file id answers 404 and stores nothing — the bytes door refuses an object that does not exist", 'api', 'common', () =>
697
+ withRoot(async (h, root) => {
698
+ const put = await handleTogetheraiUploadDoor({ method: 'PUT', path: '/twin/upload/file_nope', body: 'bytes', root });
699
+ if (status(put) !== 404) return false;
700
+ const list = await h({ m: 'GET', p: '/v1/files' });
701
+ if ((list.body as Body).data.length !== 0) return false;
702
+ return pendingActions('togetherai', root).length === 0;
703
+ })),
704
+ done('togetherai.files.sdk_redirect_flow', 'files', "the together-ai SDK's own upload flow: POST /v1/files?<params> answers 302 + Location + x-together-file-id, and the PUT fills the bytes", 'api', 'common', () =>
705
+ withRoot(async (h, root) => {
706
+ const r = await h({ m: 'POST', p: '/v1/files?file_name= sdk.jsonl&file_type=jsonl&purpose=fine-tune', b: '' });
707
+ if (status(r) !== 302) return false;
708
+ const loc = r.headers?.location;
709
+ const fid = r.headers?.['x-together-file-id'];
710
+ if (typeof loc !== 'string' || typeof fid !== 'string' || !fid) return false;
711
+ // The PUT lands on the twin-only /twin/upload door (kept out of the /v1 manifest on
712
+ // purpose); drive THAT handler directly — the /v1 router 404s the door by design, and the
713
+ // door itself answers a non-PUT with the same 404.
714
+ const wrongMethod = await handleTogetheraiUploadDoor({ method: 'GET', path: loc, root });
715
+ if (status(wrongMethod) !== 404) return false;
716
+ const put = await handleTogetheraiUploadDoor({ method: 'PUT', path: loc, body: 'the actual bytes', root });
717
+ if (!ok(put)) return false;
718
+ const one = await h({ m: 'GET', p: `/v1/files/${fid}` });
719
+ const b = one.body as Body;
720
+ return ok(one) && b.bytes === 'the actual bytes'.length;
721
+ })),
722
+ done('togetherai.files.content_download', 'files', 'GET /v1/files/:id/content returns the stored bytes', 'api', 'common', () =>
723
+ withRoot(async (h) => {
724
+ const c = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'eval', filename: 'e.jsonl', content: 'BODY123' } });
725
+ if (!ok(c)) return false;
726
+ const r = await h({ m: 'GET', p: `/v1/files/${rid(c)}/content` });
727
+ return ok(r) && r.body === 'BODY123';
728
+ })),
729
+
730
+ // ── batches (stateful, Together-native shapes) ──────────────────────────────
731
+ done('togetherai.batches.create_201_wrapped', 'batches', 'POST /v1/batches answers 201 with BatchJobWithWarning {job} — NOT an OpenAI 200 batch object', 'api', 'common', () =>
732
+ withRoot(async (h) => {
733
+ const bid = await seedBatch(h);
734
+ if (!bid) return false;
735
+ return bid.startsWith('batch_twin_');
736
+ })),
737
+ done('togetherai.batches.list_bare_array', 'batches', 'GET /v1/batches answers a BARE ARRAY of BatchJob (Together schema), not {object:list,data}', 'api', 'common', () =>
738
+ withRoot(async (h) => {
739
+ if (!(await seedBatch(h))) return false;
740
+ const r = await h({ m: 'GET', p: '/v1/batches' });
741
+ if (!ok(r) || !Array.isArray(r.body)) return false;
742
+ const b = (r.body as Body[])[0];
743
+ return b.status === 'VALIDATING' && b.endpoint === '/v1/chat/completions' && typeof b.input_file_id === 'string';
744
+ })),
745
+ done('togetherai.batches.endpoints_closed', 'batches', "Together's batch endpoint is a closed 3-set {chat/completions, audio/transcriptions, audio/translations} — OpenAI's /v1/embeddings endpoint is a 400", 'api', 'common', () =>
746
+ withRoot(async (h) => {
747
+ const f = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'batch-api', filename: 'in.jsonl', content: '{}' } });
748
+ if (!ok(f)) return false;
749
+ const openai = await h({ m: 'POST', p: '/v1/batches', b: { input_file_id: rid(f), endpoint: '/v1/embeddings' } });
750
+ if (status(openai) !== 400) return false;
751
+ const audio = await h({ m: 'POST', p: '/v1/batches', b: { input_file_id: rid(f), endpoint: '/v1/audio/transcriptions' } });
752
+ return ok(audio);
753
+ })),
754
+ done('togetherai.batches.missing_file_404', 'batches', 'a batch over an unknown input_file_id is a 404 (never a fake success)', 'api', 'common', () =>
755
+ withRoot(async (h) => {
756
+ const r = await h({ m: 'POST', p: '/v1/batches', b: { input_file_id: 'file_nope', endpoint: '/v1/chat/completions' } });
757
+ return status(r) === 404;
758
+ })),
759
+ done('togetherai.batches.empty_request_400', 'batches', "POST /v1/batches with NO body (and with an empty JSON object) answers the vendor's 400 ('input_file_id' is a required property) and stores nothing", 'api', 'common', () =>
760
+ withRoot(async (h, root) => {
761
+ const empty = await h({ m: 'POST', p: '/v1/batches', b: undefined });
762
+ if (status(empty) !== 400 || errType(empty) !== 'invalid_request_error') return false;
763
+ if (!String((empty.body as Body)?.error?.message).includes("'input_file_id'")) return false;
764
+ const obj = await h({ m: 'POST', p: '/v1/batches', b: {} });
765
+ if (status(obj) !== 400) return false;
766
+ const half = await h({ m: 'POST', p: '/v1/batches', b: { endpoint: '/v1/chat/completions' } });
767
+ if (status(half) !== 400) return false;
768
+ const list = (await h({ m: 'GET', p: '/v1/batches' })).body as Body[];
769
+ if (!Array.isArray(list) || list.length !== 0) return false;
770
+ return pendingActions('togetherai', root).length === 0;
771
+ })),
772
+ done('togetherai.batches.cancel', 'batches', 'POST /v1/batches/:id/cancel moves the job to CANCELLED; cancelling again is a 400', 'api', 'common', () =>
773
+ withRoot(async (h) => {
774
+ const bid = await seedBatch(h);
775
+ if (!bid) return false;
776
+ const c = await h({ m: 'POST', p: `/v1/batches/${bid}/cancel` });
777
+ if (!ok(c) || (c.body as Body).status !== 'CANCELLED') return false;
778
+ const again = await h({ m: 'POST', p: `/v1/batches/${bid}/cancel` });
779
+ return status(again) === 400;
780
+ })),
781
+ done('togetherai.batches.cancel_unknown_404', 'batches', 'POST /v1/batches/:id/cancel for an UNKNOWN batch answers 404 and stores nothing', 'api', 'common', () =>
782
+ withRoot(async (h, root) => {
783
+ const r = await h({ m: 'POST', p: '/v1/batches/batch_nope/cancel' });
784
+ if (status(r) !== 404) return false;
785
+ return pendingActions('togetherai', root).length === 0;
786
+ })),
787
+ done('togetherai.batches.progression_todo', 'batches', 'the asynchronous VALIDATING→IN_PROGRESS→COMPLETED progression is NOT simulated (a GET that writes would break the read contract) — filed as todo', 'api', 'common', () =>
788
+ withRoot(async (h, root) => {
789
+ const bid = await seedBatch(h);
790
+ if (!bid) return false;
791
+ // Seeding itself writes (batch.create); the read contract is about the GET.
792
+ const seeded = pendingActions('togetherai', root).length;
793
+ const before = await h({ m: 'GET', p: `/v1/batches/${bid}` });
794
+ if (!ok(before) || (before.body as Body).status !== 'VALIDATING') return false;
795
+ // A read must not write: no NEW pending actions after the GET.
796
+ return pendingActions('togetherai', root).length === seeded;
797
+ })),
798
+
799
+ // ── fine-tunes (stateful, Together-native) ──────────────────────────────────
800
+ done('togetherai.finetunes.create', 'fine_tuning', 'POST /v1/fine-tunes creates a job over a fine-tune-purpose file; a wrong-purpose file is a 400 and an unknown file a 404', 'api', 'common', () =>
801
+ withRoot(async (h) => {
802
+ const good = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', filename: 't.jsonl', content: '{}' } });
803
+ if (!ok(good)) return false;
804
+ const ft = await h({ m: 'POST', p: '/v1/fine-tunes', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: rid(good) } });
805
+ if (!ok(ft) || (ft.body as Body).status !== 'pending') return false;
806
+ const evalFile = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'eval', filename: 'e.jsonl', content: '{}' } });
807
+ const wrong = await h({ m: 'POST', p: '/v1/fine-tunes', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: rid(evalFile) } });
808
+ if (status(wrong) !== 400) return false;
809
+ const missing = await h({ m: 'POST', p: '/v1/fine-tunes', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: 'file_nope' } });
810
+ return status(missing) === 404;
811
+ })),
812
+ done('togetherai.finetunes.empty_request_400', 'fine_tuning', "POST /v1/fine-tunes with NO body (and with an empty JSON object) answers the vendor's 400 ('model' is a required property) and stores nothing", 'api', 'common', () =>
813
+ withRoot(async (h, root) => {
814
+ const empty = await h({ m: 'POST', p: '/v1/fine-tunes', b: undefined });
815
+ if (status(empty) !== 400 || errType(empty) !== 'invalid_request_error') return false;
816
+ if (!String((empty.body as Body)?.error?.message).includes("'model'")) return false;
817
+ const obj = await h({ m: 'POST', p: '/v1/fine-tunes', b: {} });
818
+ if (status(obj) !== 400) return false;
819
+ const half = await h({ m: 'POST', p: '/v1/fine-tunes', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo' } });
820
+ if (status(half) !== 400) return false;
821
+ const list = (await h({ m: 'GET', p: '/v1/fine-tunes' })).body as Body[];
822
+ if (!Array.isArray(list) || list.length !== 0) return false;
823
+ return pendingActions('togetherai', root).length === 0;
824
+ })),
825
+ done('togetherai.finetunes.cancel_unknown_404', 'fine_tuning', 'POST /v1/fine-tunes/:id/cancel for an UNKNOWN job answers 404 and stores nothing', 'api', 'common', () =>
826
+ withRoot(async (h, root) => {
827
+ const r = await h({ m: 'POST', p: '/v1/fine-tunes/ft_nope/cancel' });
828
+ if (status(r) !== 404) return false;
829
+ return pendingActions('togetherai', root).length === 0;
830
+ })),
831
+ done('togetherai.finetunes.delete_unknown_404', 'fine_tuning', 'DELETE /v1/fine-tunes/:id for an UNKNOWN job answers 404 and stores nothing', 'api', 'common', () =>
832
+ withRoot(async (h, root) => {
833
+ const r = await h({ m: 'DELETE', p: '/v1/fine-tunes/ft_nope' });
834
+ if (status(r) !== 404) return false;
835
+ return pendingActions('togetherai', root).length === 0;
836
+ })),
837
+ done('togetherai.files.delete_unknown_404_noop', 'files', 'DELETE /v1/files/:id for an UNKNOWN file answers 404 and stores nothing (already asserted positively in togetherai.files.delete; this is the unchanged-store half of the door contract)', 'api', 'common', () =>
838
+ withRoot(async (h, root) => {
839
+ const r = await h({ m: 'DELETE', p: '/v1/files/file_nope' });
840
+ if (status(r) !== 404) return false;
841
+ return pendingActions('togetherai', root).length === 0;
842
+ })),
843
+ done('togetherai.finetunes.list_get_cancel_delete', 'fine_tuning', 'list / GET :id retrieves the stored job / cancel (status→cancel_requested, terminal states refused) / delete', 'api', 'common', () =>
844
+ withRoot(async (h) => {
845
+ const f = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', filename: 't.jsonl', content: '{}' } });
846
+ if (!ok(f)) return false;
847
+ const ft = await h({ m: 'POST', p: '/v1/fine-tunes', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: rid(f) } });
848
+ if (!ok(ft)) return false;
849
+ const ftid = rid(ft);
850
+ const list = await h({ m: 'GET', p: '/v1/fine-tunes' });
851
+ if (!ok(list) || !(list.body as Body[]).some((x) => x.id === ftid)) return false;
852
+ // GET /v1/fine-tunes/{id} reads the STORED job back (read-back, not just a 200): a handler
853
+ // that lost the route answers the router's not-found and this fails.
854
+ const one = await h({ m: 'GET', p: `/v1/fine-tunes/${ftid}` });
855
+ if (!ok(one) || (one.body as Body).id !== ftid || (one.body as Body).status !== 'pending') return false;
856
+ const missing = await h({ m: 'GET', p: '/v1/fine-tunes/ft_nope' });
857
+ if (status(missing) !== 404) return false;
858
+ const cancel = await h({ m: 'POST', p: `/v1/fine-tunes/${ftid}/cancel` });
859
+ if (!ok(cancel) || (cancel.body as Body).status !== 'cancel_requested') return false;
860
+ const again = await h({ m: 'POST', p: `/v1/fine-tunes/${ftid}/cancel` });
861
+ if (status(again) !== 400) return false;
862
+ const del = await h({ m: 'DELETE', p: `/v1/fine-tunes/${ftid}` });
863
+ // Together's fine-tune delete answers {message} (fine-tuning.d.ts:1073), not {id, deleted}.
864
+ if (!ok(del) || typeof (del.body as Body).message !== 'string') return false;
865
+ // A DELETE of an UNKNOWN fine-tune is a 404, never a fake success.
866
+ const delMissing = await h({ m: 'DELETE', p: '/v1/fine-tunes/ft_nope' });
867
+ return status(delMissing) === 404 && errType(delMissing) === 'invalid_request_error';
868
+ })),
869
+ done('togetherai.finetunes.aux_endpoints', 'fine_tuning', 'estimate-price (the SDK\'s discriminated union: an AvailableEstimate whose token counts derive from the stored file\'s content, train_file_invalid over an unknown one) / preview (tokenized rows over the sampled file, 404 over an unknown one) / events + checkpoints (derived from the stored job\'s status; an unknown job 404s) / models/limits (the FinetuneModelLimits shape for a known chat model, 404 otherwise)', 'api', 'common', () =>
870
+ withRoot(async (h) => {
871
+ // An unknown training_file → UnavailableEstimate with the vendor's train_file_invalid reason.
872
+ const unknown = await h({ m: 'POST', p: '/v1/fine-tunes/estimate-price', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: 'file_nope' } });
873
+ if (!ok(unknown)) return false;
874
+ const u = unknown.body as Body;
875
+ if (u.estimation_available !== false || u.unavailable_reason !== 'train_file_invalid') return false;
876
+ // A real file → AvailableEstimate whose token counts DERIVE from the stored content:
877
+ // two JSONL rows of 3 tokens each estimate 6 train tokens (n_epochs omitted → 1), so a
878
+ // handler that answers zeros or ignores the file loses the read-back.
879
+ const made = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', filename: 'est.jsonl', content: '{"text":"r"}\n{"text":"s"}\n' } });
880
+ if (!ok(made)) return false;
881
+ const fid = (made.body as Body).id as string;
882
+ const price = await h({ m: 'POST', p: '/v1/fine-tunes/estimate-price', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: fid } });
883
+ if (!ok(price)) return false;
884
+ const p = price.body as Body;
885
+ if (p.estimation_available !== true || typeof p.estimated_total_price !== 'number' || p.estimated_total_price <= 0) return false;
886
+ if (p.estimated_train_token_count !== 6) return false;
887
+ // More epochs scale the estimate — the same read-back, a second way.
888
+ const price3 = await h({ m: 'POST', p: '/v1/fine-tunes/estimate-price', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: fid, n_epochs: 3 } });
889
+ if (!ok(price3) || (price3.body as Body).estimated_train_token_count !== 18) return false;
890
+ // Preview over the SAME file: vendor's FineTunePreviewResponse — rows carrying
891
+ // input_ids/labels/num_tokens, max_seq_length from the model's context length.
892
+ const prev = await h({ m: 'POST', p: '/v1/fine-tunes/preview', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: fid } });
893
+ if (!ok(prev)) return false;
894
+ const pv = prev.body as Body;
895
+ if (pv.max_seq_length !== 131_072 || pv.model !== 'meta-llama/Llama-3.3-70B-Instruct-Turbo' || !Array.isArray(pv.rows) || pv.rows.length !== 2) return false;
896
+ const row = pv.rows[0] as Body;
897
+ if (!Array.isArray(row.input_ids) || row.input_ids.length === 0 || !Array.isArray(row.labels) || typeof row.num_tokens !== 'number') return false;
898
+ const prevUnknown = await h({ m: 'POST', p: '/v1/fine-tunes/preview', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: 'file_nope' } });
899
+ if (status(prevUnknown) !== 404) return false;
900
+ // events + checkpoints over a REAL job: a pending job has no events (the vendor's job has
901
+ // not started) and no checkpoints (none produced); cancelling files the lifecycle events
902
+ // the stored status grounds; a still-running job yields NO fabricated checkpoint.
903
+ const ft = await h({ m: 'POST', p: '/v1/fine-tunes', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: fid } });
904
+ if (!ok(ft)) return false;
905
+ const ftid = (ft.body as Body).id as string;
906
+ const ev0 = await h({ m: 'GET', p: `/v1/fine-tunes/${ftid}/events` });
907
+ if (!ok(ev0) || (ev0.body as Body).data.length !== 0) return false;
908
+ const cp0 = await h({ m: 'GET', p: `/v1/fine-tunes/${ftid}/checkpoints` });
909
+ if (!ok(cp0) || (cp0.body as Body).data.length !== 0) return false;
910
+ const cancel = await h({ m: 'POST', p: `/v1/fine-tunes/${ftid}/cancel` });
911
+ if (!ok(cancel)) return false;
912
+ const ev1 = await h({ m: 'GET', p: `/v1/fine-tunes/${ftid}/events` });
913
+ if (!ok(ev1)) return false;
914
+ const data = (ev1.body as Body).data as Body[];
915
+ if (!(data.some((e) => e.type === 'job_start') && data.some((e) => e.type === 'cancel_requested'))) return false;
916
+ if (data.some((e) => e.object !== 'fine-tune-event')) return false;
917
+ const evUnknown = await h({ m: 'GET', p: '/v1/fine-tunes/ft_nope/events' });
918
+ if (status(evUnknown) !== 404) return false;
919
+ const cpUnknown = await h({ m: 'GET', p: '/v1/fine-tunes/ft_nope/checkpoints' });
920
+ if (status(cpUnknown) !== 404) return false;
921
+ // models/limits: the FinetuneModelLimits shape for a KNOWN chat model — the read-backs
922
+ // name the model and carry the vendor's REQUIRED keys; an unknown model is a 404 and a
923
+ // MISSING model_name is the vendor's 400 (model_name is REQUIRED, fine-tuning.d.ts:1798).
924
+ const limits = await h({ m: 'GET', p: '/v1/fine-tunes/models/limits?model_name=meta-llama/Llama-3.3-70B-Instruct-Turbo' });
925
+ if (!ok(limits)) return false;
926
+ const lm = limits.body as Body;
927
+ if (lm.model_name !== 'meta-llama/Llama-3.3-70B-Instruct-Turbo' || typeof lm.max_num_epochs !== 'number'
928
+ || typeof lm.lora_training?.max_rank !== 'number' || typeof lm.max_seq_length_sft !== 'number') return false;
929
+ const limitsUnknown = await h({ m: 'GET', p: '/v1/fine-tunes/models/limits?model_name=nope' });
930
+ if (status(limitsUnknown) !== 404) return false;
931
+ const limitsMissing = await h({ m: 'GET', p: '/v1/fine-tunes/models/limits' });
932
+ if (status(limitsMissing) !== 400 || errType(limitsMissing) !== 'invalid_request_error') return false;
933
+ // estimate-price with NEITHER required param is a 400; preview's guards: a missing model /
934
+ // training_file is a 400, an unknown one a 404, and a non-fine-tunable (image) model a 404.
935
+ const priceMissing = await h({ m: 'POST', p: '/v1/fine-tunes/estimate-price', b: {} });
936
+ if (status(priceMissing) !== 400) return false;
937
+ // fine-tuning.d.ts:1691 pins training_file as REQUIRED: a model-only request is a 400, never an estimate
938
+ const priceModelOnly = await h({ m: 'POST', p: '/v1/fine-tunes/estimate-price', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo' } });
939
+ if (status(priceModelOnly) !== 400 || errType(priceModelOnly) !== 'invalid_request_error') return false;
940
+ // create refuses an unknown base model the way preview and models/limits already do
941
+ const ftUnknownModel = await h({ m: 'POST', p: '/v1/fine-tunes', b: { model: 'not-a-real-model', training_file: fid } });
942
+ if (status(ftUnknownModel) !== 404) return false;
943
+ const prevNoModel = await h({ m: 'POST', p: '/v1/fine-tunes/preview', b: { training_file: fid } });
944
+ if (status(prevNoModel) !== 400) return false;
945
+ const prevNoFile = await h({ m: 'POST', p: '/v1/fine-tunes/preview', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo' } });
946
+ if (status(prevNoFile) !== 400) return false;
947
+ const prevImageModel = await h({ m: 'POST', p: '/v1/fine-tunes/preview', b: { model: 'black-forest-labs/FLUX.1-schnell', training_file: fid } });
948
+ if (status(prevImageModel) !== 404) return false;
949
+ // The dataset_format is DETECTED from the sampled rows (fine-tuning.d.ts:158,
950
+ // check-file.mjs column map): {text:…} rows are 'general'; {messages:…} rows are
951
+ // 'conversation'; {prompt,completion} rows are 'instruction'.
952
+ const conv = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', filename: 'conv.jsonl', content: '{"messages":[{"role":"user","content":"hi"}]}\n' } });
953
+ if (!ok(conv)) return false;
954
+ const prevConv = await h({ m: 'POST', p: '/v1/fine-tunes/preview', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: rid(conv) } });
955
+ if (!ok(prevConv) || (prevConv.body as Body).dataset_format !== 'conversation') return false;
956
+ const inst = await h({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', filename: 'inst.jsonl', content: '{"prompt":"q","completion":"a"}\n' } });
957
+ if (!ok(inst)) return false;
958
+ const prevInst = await h({ m: 'POST', p: '/v1/fine-tunes/preview', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: rid(inst) } });
959
+ if (!ok(prevInst) || (prevInst.body as Body).dataset_format !== 'instruction') return false;
960
+ return (prev.body as Body).dataset_format === 'general';
961
+ })),
962
+
963
+ // ── auth (modeled 401) ──────────────────────────────────────────────────────
964
+ done('togetherai.auth.missing_key_401', 'auth', 'a request with an auth surface but no credential is a 401 (Together: "A missing or invalid API key")', 'api', 'core', () =>
965
+ withRootH(async (h) => {
966
+ const r = await h({ m: 'GET', p: '/v1/models', headers: {} });
967
+ return status(r) === 401 && errType(r) === 'invalid_request_error';
968
+ })),
969
+ done('togetherai.auth.invalid_key_401', 'auth', "the invalid-key sentinel answers 401; any other bearer key is accepted", 'api', 'core', () =>
970
+ withRootH(async (h) => {
971
+ const bad = await h({ m: 'GET', p: '/v1/models', headers: { authorization: 'Bearer twin_invalid' } });
972
+ if (status(bad) !== 401) return false;
973
+ const good = await h({ m: 'GET', p: '/v1/models', headers: { authorization: 'Bearer any-real-shaped-key' } });
974
+ return ok(good);
975
+ })),
976
+ done('togetherai.auth.trusted_calls_ungated', 'auth', 'in-process trusted calls (no headers, no apiKey) are NOT auth-gated', 'api', 'core', () =>
977
+ withRoot(async (h) => {
978
+ // Reads a real value back: a dead handler answering 200 {} must fail this too.
979
+ const r = await h({ m: 'GET', p: '/v1/models' });
980
+ return ok(r) && Array.isArray((r.body as Body)) && (r.body as Body[]).some((m) => m.id === 'meta-llama/Llama-3.3-70B-Instruct-Turbo');
981
+ })),
982
+
983
+ // ── rate limits / faults (deterministic triggers) ───────────────────────────
984
+ done('togetherai.rate.force_429', 'rate_limits', "x-twin-force-rate-limit answers Together's 429 (dynamic_request_limited) with x-ratelimit-reset", 'api', 'core', () =>
985
+ withRootH(async (h) => {
986
+ // Headers present → the auth gate runs; the trigger must pass a credential to reach it.
987
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT(), headers: { authorization: 'Bearer key_twin', 'x-twin-force-rate-limit': '1' } });
988
+ return status(r) === 429 && errType(r) === 'dynamic_request_limited'
989
+ && r.headers?.['x-ratelimit-reset'] === '60';
990
+ })),
991
+ done('togetherai.rate.force_402', 'rate_limits', "x-twin-force-spending-limit answers Together's 402 monthly spending limit", 'api', 'common', () =>
992
+ withRootH(async (h) => {
993
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT(), headers: { authorization: 'Bearer key_twin', 'x-twin-force-spending-limit': '1' } });
994
+ return status(r) === 402;
995
+ })),
996
+ done('togetherai.rate.force_503', 'rate_limits', "x-twin-force-engine-overloaded answers Together's 503 engine_overloaded", 'api', 'common', () =>
997
+ withRootH(async (h) => {
998
+ const r = await h({ m: 'POST', p: CHAT_PATH, b: CHAT(), headers: { authorization: 'Bearer key_twin', 'x-twin-force-engine-overloaded': 'true' } });
999
+ return status(r) === 503 && errType(r) === 'engine_overloaded';
1000
+ })),
1001
+
1002
+ // ── read-only (D3) ──────────────────────────────────────────────────────────
1003
+ // EVERY write door, not only the /v1 router: the /twin/upload bytes door is driven by the
1004
+ // server OUTSIDE handleTogetheraiTwinRequest (togetherai-server.ts calls
1005
+ // handleTogetheraiUploadDoor directly), so a verify that only drove the router left that door
1006
+ // writing on a --read-only server (§9 round three, defect 2). Each door is driven against a
1007
+ // SEEDED resource so the 405 (not a 404) proves the guard — and the store count is asserted
1008
+ // unchanged after every refusal.
1009
+ done('togetherai.readonly.rejected', 'conformance', 'a readOnly twin rejects EVERY write door — both /v1 create doors, all four cancel/delete doors AND the twin-only PUT /twin/upload bytes door — with the vendor-shaped 405 while reads still answer', 'api', 'core', () =>
1010
+ withRoot(async (h, root) => {
1011
+ const ro = (s: Step) => handleTogetheraiTwinRequest({ method: s.m, path: s.p, body: s.b === undefined ? undefined : JSON.stringify(s.b), root, readOnly: true });
1012
+ // Reads still answer.
1013
+ const read = await ro({ m: 'GET', p: '/v1/models' });
1014
+ if (!ok(read)) return false;
1015
+ // The two create doors.
1016
+ const upload = await ro({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'eval', filename: 'x.jsonl', content: '{}' } });
1017
+ if (status(upload) !== 405) return false;
1018
+ const sdkFlow = await ro({ m: 'POST', p: '/v1/files?file_name=x.jsonl&purpose=eval', b: '' });
1019
+ if (status(sdkFlow) !== 405) return false;
1020
+ // Seed the stateful objects the remaining doors mutate (seeded WRITABLE, before the
1021
+ // read-only pass — the root is the same, so the seeds are real rows).
1022
+ const seed = (s: Step) => handleTogetheraiTwinRequest({ method: s.m, path: s.p, body: s.b === undefined ? undefined : JSON.stringify(s.b), root });
1023
+ const f = await seed({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'batch-api', filename: 'in.jsonl', content: '{}' } });
1024
+ if (!ok(f)) return false;
1025
+ const fid = rid(f);
1026
+ const b = await seed({ m: 'POST', p: '/v1/batches', b: { input_file_id: fid, endpoint: '/v1/chat/completions' } });
1027
+ if (!ok(b)) return false;
1028
+ const bid = (b.body as Body).job?.id as string;
1029
+ const ftSeed = await seed({ m: 'POST', p: '/v1/files/upload', b: { purpose: 'fine-tune', filename: 't.jsonl', content: '{}' } });
1030
+ if (!ok(ftSeed)) return false;
1031
+ const ft = await seed({ m: 'POST', p: '/v1/fine-tunes', b: { model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: rid(ftSeed) } });
1032
+ if (!ok(ft)) return false;
1033
+ const ftid = rid(ft);
1034
+ // The four cancel/delete doors over SEEDED objects: a 404 here would mean the seed failed,
1035
+ // not that the guard held.
1036
+ const cancels = [
1037
+ await ro({ m: 'POST', p: `/v1/batches/${bid}/cancel` }),
1038
+ await ro({ m: 'POST', p: `/v1/fine-tunes/${ftid}/cancel` }),
1039
+ await ro({ m: 'DELETE', p: `/v1/files/${fid}` }),
1040
+ await ro({ m: 'DELETE', p: `/v1/fine-tunes/${ftid}` }),
1041
+ ];
1042
+ if (!cancels.every((r) => status(r) === 405)) return false;
1043
+ // The twin-only bytes door, driven through its OWN handler (the path the server takes).
1044
+ const put = await handleTogetheraiUploadDoor({ method: 'PUT', path: `/twin/upload/${fid}`, body: 'bytes', root, readOnly: true });
1045
+ if (status(put) !== 405) return false;
1046
+ // Nothing was written by any refusal: the store holds exactly the four seeds.
1047
+ const list = await h({ m: 'GET', p: '/v1/files' });
1048
+ if ((list.body as Body).data.length !== 2) return false;
1049
+ const batches = (await h({ m: 'GET', p: '/v1/batches' })).body as Body[];
1050
+ if (batches.length !== 1 || batches[0].status !== 'VALIDATING') return false;
1051
+ const fts = (await h({ m: 'GET', p: '/v1/fine-tunes' })).body as Body[];
1052
+ if (fts.length !== 1 || fts[0].status !== 'pending') return false;
1053
+ const bytes = await h({ m: 'GET', p: `/v1/files/${fid}/content` });
1054
+ return bytes.body === '{}';
1055
+ })),
1056
+
1057
+ // ── connector ───────────────────────────────────────────────────────────────
1058
+ done('togetherai.connector.pull_maps', 'connector', 'pull maps real Models/Files/Batches to sync resources (bare-array and {data} list shapes both accepted)', 'connector', 'core', () =>
1059
+ withConnectorRoot('togetherai.connector.pull_maps', async () => {
1060
+ const calls: Array<{ method: string; path: string }> = [];
1061
+ const execute: TogetheraiExecute = async (method, path) => {
1062
+ const out: { [k: string]: unknown; data?: any } = { data: undefined };
1063
+ calls.push({ method, path });
1064
+ if (path === '/v1/models') out.data = [{ id: 'm2', object: 'model', created: 1, type: 'chat' }];
1065
+ else if (path === '/v1/files') out.data = [{ id: 'f2', object: 'file', bytes: 5, created_at: 2, filename: 'f', purpose: 'fine-tune', Processed: true, FileType: 'jsonl' }];
1066
+ else if (path === '/v1/batches') out.data = [{ id: 'b2', object: 'batch', endpoint: '/v1/chat/completions', input_file_id: 'f2', status: 'STATUS_COMPLETED', created_at: new Date(0).toISOString() }];
1067
+ else throw new Error(`unexpected ${path}`);
1068
+ return out;
1069
+ };
1070
+ const state = await pullTogetheraiState(execute);
1071
+ if (state.length !== 3) return false;
1072
+ if (calls.length !== 3 || !calls.every((c) => c.method === 'GET')) return false;
1073
+ const model = state.find((r) => r.type === 'model');
1074
+ const file = state.find((r) => r.type === 'file');
1075
+ const batch = state.find((r) => r.type === 'batch');
1076
+ return model?.id === 'm2' && file?.id === 'f2' && (file.fields as Body).Processed === true && batch?.id === 'b2';
1077
+ })),
1078
+ done('togetherai.connector.pull_error_throws', 'connector', 'a refused pull throws (an error envelope is NOT an empty account)', 'connector', 'core', () =>
1079
+ withConnectorRoot('togetherai.connector.pull_error_throws', async () => {
1080
+ const execute: TogetheraiExecute = async () => ({ error: { message: 'dynamic_request_limited', type: 'dynamic_request_limited' } });
1081
+ try {
1082
+ await pullTogetheraiState(execute);
1083
+ return false;
1084
+ } catch (e) {
1085
+ return e instanceof Error && e.message.includes('dynamic_request_limited');
1086
+ }
1087
+ })),
1088
+ done('togetherai.connector.sync_noop_on_repeat', 'connector', 'syncing identical real state twice appends deltas once and nothing the second time', 'connector', 'core', () =>
1089
+ // HOLLOW BY METHOD (2026-09-16 sweep): the "second identical sync appends 0" half is owned by
1090
+ // the KERNEL's shadow-diff (world-core observe.ts foldResources — unchanged fields append
1091
+ // nothing), not by a pack line; the sweep only mutates <pack>-twin/-connector/-stub. Hand-walked:
1092
+ // every neuterable pack-side line (the fold call's `at`/`batch` keys, the resource map) either
1093
+ // breaks the FIRST-sync half too or leaves the cell green — no pack line owns the repeat-noop
1094
+ // alone. The pin still fails when sync stops working at all (the first-sync assertions).
1095
+ withConnectorRoot('togetherai.connector.sync_noop_on_repeat', async (root) => {
1096
+ // One row per collection (the fold observes models+files+batches — three collections, three
1097
+ // observed rows), identical across the two syncs.
1098
+ const execute: TogetheraiExecute = async (_method, path) => {
1099
+ if (path === '/v1/models') return { data: [{ id: 'm2', object: 'model', created: 1, type: 'chat' }] };
1100
+ if (path === '/v1/files') return { data: [] };
1101
+ if (path === '/v1/batches') return { data: [] };
1102
+ throw new Error(`unexpected ${path}`);
1103
+ };
1104
+ const first = await syncTogetheraiFromReal(execute, { root, occurredAt: '2026-09-16T00:00:01Z' });
1105
+ const second = await syncTogetheraiFromReal(execute, { root, occurredAt: '2026-09-16T00:00:02Z' });
1106
+ return first.observed === 1 && first.deltasAppended === 1 && second.observed === 1 && second.deltasAppended === 0;
1107
+ })),
1108
+ done('togetherai.connector.push_batch_create', 'connector', 'a local batch create pushes POST /v1/batches with a VENDOR-RESOLVED input_file_id and records the vendor id (nested job.id accepted)', 'connector', 'core', () =>
1109
+ withConnectorRoot('togetherai.connector.push_batch_create', async (root) => {
1110
+ // A batch create references a file; file.create is UNPUSHABLE, so a file's vendor id exists
1111
+ // at the twin only through a PULL (the fold observes the vendor's row under the vendor's own
1112
+ // id — it does not alias a locally-minted row). Pull a vendor file first, then create the
1113
+ // batch through the handler against it.
1114
+ const pulled = await syncTogetheraiFromReal(async (_m, path) => {
1115
+ if (path === '/v1/models') return { data: [] };
1116
+ if (path === '/v1/files') return { data: [{ id: 'file-real-1', object: 'file', bytes: 14, created_at: 2, filename: 'in.jsonl', purpose: 'batch-api', Processed: true, FileType: 'jsonl' }] };
1117
+ if (path === '/v1/batches') return { data: [] };
1118
+ throw new Error(`unexpected ${path}`);
1119
+ }, { root, occurredAt: '2026-09-16T00:00:00Z' });
1120
+ if (pulled.observed !== 1) return false;
1121
+ const created = await handleTogetheraiTwinRequest({ method: 'POST', path: '/v1/batches', body: JSON.stringify({ input_file_id: 'file-real-1', endpoint: '/v1/chat/completions' }), root, occurredAt: '2026-09-16T00:00:01Z' });
1122
+ if (!ok(created)) return false;
1123
+ const pending = pendingActions('togetherai', root).filter((a) => a.subject.type === 'batch');
1124
+ if (pending.length !== 1) return false;
1125
+ const calls: Array<{ method: string; path: string; body?: unknown }> = [];
1126
+ const execute: TogetheraiExecute = async (method, path, body) => {
1127
+ calls.push({ method, path, body });
1128
+ return { job: { id: 'b-real-1' } };
1129
+ };
1130
+ // The push sends the file's VENDOR id (the pulled row's own id) — never a twin mint.
1131
+ const pushed = await pushPendingTogetheraiActions(execute, { root, occurredAt: '2026-09-16T00:00:02Z' });
1132
+ if (pushed.pushed !== 1 || calls.length !== 1) return false;
1133
+ if (calls[0].method !== 'POST' || calls[0].path !== '/v1/batches') return false;
1134
+ const sent = (calls[0].body ?? {}) as Body;
1135
+ if (sent.input_file_id !== 'file-real-1' || sent.endpoint !== '/v1/chat/completions') return false;
1136
+ // …and the vendor's answer is recorded as the batch's external id, so a later cancel
1137
+ // addresses b-real-1, never the twin's mint.
1138
+ const batch = projectResources('togetherai', root).find((r) => r.type === 'batch');
1139
+ return batch?._external_id === 'b-real-1';
1140
+ })),
1141
+ done('togetherai.connector.push_batch_local_file_refused', 'connector', 'a batch create over a locally-minted file (no pull, no vendor id) is REFUSED, never sent with the twin\'s own id', 'connector', 'core', () =>
1142
+ withConnectorRoot('togetherai.connector.push_batch_local_file_refused', async (root) => {
1143
+ // Seed a LOCAL file create (unpushable — no vendor id can ever be recorded for it) and a
1144
+ // batch over it. The push must refuse the batch rather than send `file_twin_1` at the vendor.
1145
+ const seeded = await handleTogetheraiTwinRequest({ method: 'POST', path: '/v1/files/upload', body: JSON.stringify({ purpose: 'batch-api', filename: 'in.jsonl', content: '{"text":"row"}' }), root, occurredAt: '2026-09-16T00:00:00Z' });
1146
+ if (!ok(seeded)) return false;
1147
+ const created = await handleTogetheraiTwinRequest({ method: 'POST', path: '/v1/batches', body: JSON.stringify({ input_file_id: rid(seeded), endpoint: '/v1/chat/completions' }), root, occurredAt: '2026-09-16T00:00:01Z' });
1148
+ if (!ok(created)) return false;
1149
+ if (pendingActions('togetherai', root).filter((a) => a.subject.type === 'batch').length !== 1) return false;
1150
+ const calls: Array<{ method: string; path: string; body?: unknown }> = [];
1151
+ const execute: TogetheraiExecute = async (method, path, body) => {
1152
+ calls.push({ method, path, body });
1153
+ return { job: { id: 'b-real-1' } };
1154
+ };
1155
+ const refused = await pushPendingTogetheraiActions(execute, { root, occurredAt: '2026-09-16T00:00:02Z' });
1156
+ if (refused.pushed !== 0 || calls.length !== 0) return false;
1157
+ if (!refused.refused.some((r) => r.operation === 'batch.create' && r.reason.includes('input_file_id'))) return false;
1158
+ // Skip-and-report: the batch stays pending, so a later pull CAN still resolve it.
1159
+ return pendingActions('togetherai', root).some((a) => a.subject.type === 'batch');
1160
+ })),
1161
+ done('togetherai.connector.push_addresses_vendor_id', 'connector', "a cancel of a PUSHED resource addresses the vendor by the recorded external id — never the twin's own mint", 'connector', 'core', () =>
1162
+ withConnectorRoot('togetherai.connector.push_addresses_vendor_id', async (root) => {
1163
+ // Pull a vendor file (the only way a file gets a vendor id), create a batch over it through
1164
+ // the handler, push: the create confirms and records `b-real-9` as the batch's external id.
1165
+ const pulled = await syncTogetheraiFromReal(async (_m, path) => {
1166
+ if (path === '/v1/models') return { data: [] };
1167
+ if (path === '/v1/files') return { data: [{ id: 'file-real-9', object: 'file', bytes: 14, created_at: 2, filename: 'in.jsonl', purpose: 'batch-api', Processed: true, FileType: 'jsonl' }] };
1168
+ if (path === '/v1/batches') return { data: [] };
1169
+ throw new Error(`unexpected ${path}`);
1170
+ }, { root, occurredAt: '2026-09-16T00:00:00Z' });
1171
+ if (pulled.observed !== 1) return false;
1172
+ const created = await handleTogetheraiTwinRequest({ method: 'POST', path: '/v1/batches', body: JSON.stringify({ input_file_id: 'file-real-9', endpoint: '/v1/chat/completions' }), root, occurredAt: '2026-09-16T00:00:01Z' });
1173
+ if (!ok(created)) return false;
1174
+ const calls: Array<{ method: string; path: string }> = [];
1175
+ const execute: TogetheraiExecute = async (method, path) => {
1176
+ calls.push({ method, path });
1177
+ return method === 'POST' ? { job: { id: 'b-real-9' } } : {};
1178
+ };
1179
+ const first = await pushPendingTogetheraiActions(execute, { root, occurredAt: '2026-09-16T00:00:02Z' });
1180
+ if (first.pushed !== 1) return false;
1181
+ const batch = projectResources('togetherai', root).find((r) => r.type === 'batch');
1182
+ if (!batch || batch._external_id !== 'b-real-9') return false;
1183
+ // Cancel the pushed batch: the wire must address b-real-9, never the twin's mint.
1184
+ const cancelled = await handleTogetheraiTwinRequest({ method: 'POST', path: `/v1/batches/${String(batch.id)}/cancel`, root, occurredAt: '2026-09-16T00:00:03Z' });
1185
+ if (!ok(cancelled)) return false;
1186
+ const before = calls.length;
1187
+ const second = await pushPendingTogetheraiActions(execute, { root, occurredAt: '2026-09-16T00:00:04Z' });
1188
+ if (second.pushed !== 1) return false;
1189
+ const cancelCall = calls.slice(before).find((c) => c.path.includes('/cancel'));
1190
+ return cancelCall !== undefined && cancelCall.path === '/v1/batches/b-real-9/cancel';
1191
+ })),
1192
+ done('togetherai.connector.unpushable_file_create', 'connector', "file.create is REFUSED with a reason (the 302-redirect upload is not expressible in JSON) — skip-and-report, never confirmed", 'connector', 'core', () =>
1193
+ withConnectorRoot('togetherai.connector.unpushable_file_create', async (root) => {
1194
+ const reason = unpushableReason('file.create');
1195
+ if (reason === null) return false;
1196
+ // Seed a REAL local file create through the handler so there is a pending action to refuse.
1197
+ const seeded = await handleTogetheraiTwinRequest({ method: 'POST', path: '/v1/files/upload', body: JSON.stringify({ purpose: 'batch-api', filename: 'up.jsonl', content: '{"text":"row"}' }), root, occurredAt: '2026-09-16T00:00:00Z' });
1198
+ if (!ok(seeded)) return false;
1199
+ const pending = pendingActions('togetherai', root).filter((a) => a.subject.type === 'file');
1200
+ if (pending.length !== 1) return false;
1201
+ const execute: TogetheraiExecute = async () => { throw new Error('must not be called'); };
1202
+ const pushed = await pushPendingTogetheraiActions(execute, { root, occurredAt: '2026-09-16T00:00:01Z' });
1203
+ // Skipped-and-reported: not confirmed, stays pending, named in `refused`.
1204
+ return pushed.pushed === 0 && pushed.refused.length === 1 && pushed.refused[0].reason.length > 0
1205
+ && pendingActions('togetherai', root).some((a) => a.subject.type === 'file');
1206
+ })),
1207
+ done('togetherai.connector.local_id_never_addressed', 'connector', 'a locally-minted subject with no recorded external id is refused, never guessed at', 'connector', 'core', () =>
1208
+ withConnectorRoot('togetherai.connector.local_id_never_addressed', async () => {
1209
+ try {
1210
+ togetheraiRequestForAction({ operation: 'file.delete', subject: { type: 'file', id: 'file_twin_1' } });
1211
+ return false;
1212
+ } catch (e) {
1213
+ return e instanceof Error && e.message.includes('refusing to address');
1214
+ }
1215
+ })),
1216
+ done('togetherai.connector.full_sync', 'connector', 'fullSync pushes then pulls; re-running with nothing pending and identical state is a no-op', 'connector', 'core', () =>
1217
+ withConnectorRoot('togetherai.connector.full_sync', async (root) => {
1218
+ // The fixture CARRIES a pending pushable action (§9 round two, R2-D1: a push half over an
1219
+ // empty pending queue is vacuous — it proves nothing about the push). A finetune over the
1220
+ // pulled file pushes POST /v1/fine-tunes inside the first sync's push half.
1221
+ let files = [{ id: 'f-real', object: 'file', bytes: 3, created_at: 1, filename: 'f', purpose: 'fine-tune', Processed: true, FileType: 'jsonl' }];
1222
+ const pushedCreates: Array<{ method: string; path: string }> = [];
1223
+ const execute: TogetheraiExecute = async (method, path, body) => {
1224
+ const out: { [k: string]: unknown; data?: any } = { data: undefined };
1225
+ if (path === '/v1/files') { out.data = files; if (method !== 'GET') out.id = 'f-real-2'; }
1226
+ else if (path === '/v1/fine-tunes') { pushedCreates.push({ method, path }); return { id: 'ft-real-1' }; }
1227
+ else if (path === '/v1/batches' || path === '/v1/models') out.data = [];
1228
+ else throw new Error(`unexpected ${method} ${path}`);
1229
+ return out;
1230
+ };
1231
+ // Pull first so the file exists with its vendor id, then create the finetune locally.
1232
+ const seed = await syncTogetheraiFromReal(execute, { root, occurredAt: '2026-09-16T00:00:00Z' });
1233
+ if (seed.observed < 1) return false;
1234
+ const created = await handleTogetheraiTwinRequest({ method: 'POST', path: '/v1/fine-tunes', body: JSON.stringify({ model: 'meta-llama/Llama-3.3-70B-Instruct-Turbo', training_file: 'f-real' }), root, occurredAt: '2026-09-16T00:00:01Z' });
1235
+ if (!ok(created)) return false;
1236
+ const first = await fullSyncTogetherai(execute, { root, occurredAt: '2026-09-16T00:00:02Z' });
1237
+ if (first.pushed !== 1 || pushedCreates.length !== 1 || pushedCreates[0].path !== '/v1/fine-tunes') return false;
1238
+ const ftRow = projectResources('togetherai', root).find((r) => r.type === 'finetune');
1239
+ if (!ftRow || ftRow._external_id !== 'ft-real-1') return false;
1240
+ const second = await fullSyncTogetherai(execute, { root, occurredAt: '2026-09-16T00:00:03Z' });
1241
+ return second.deltasAppended === 0 && second.pushed === 0;
1242
+ })),
1243
+ done('togetherai.connector.live_guard_path', 'connector', 'liveTogetheraiExecute refuses an unmodeled path BEFORE charging the budget', 'connector', 'core', () =>
1244
+ withConnectorRoot('togetherai.connector.live_guard_path', async () => {
1245
+ let fetched = 0;
1246
+ const exec = liveTogetheraiExecute('sk_twin_test', 'https://api.together.xyz', { fetchImpl: (async () => { fetched += 1; throw new Error('should not fetch'); }) as unknown as typeof fetch });
1247
+ try {
1248
+ await exec('GET', '/v2/endpoints');
1249
+ return false;
1250
+ } catch (e) {
1251
+ return fetched === 0 && e instanceof Error && e.message.includes('unmodeled path');
1252
+ }
1253
+ })),
1254
+ done('togetherai.connector.live_guard_budget', 'connector', 'liveTogetheraiExecute charges the budget before the fetch and refuses when the ceiling says stop', 'connector', 'core', () =>
1255
+ // HOLLOW BY METHOD (2026-09-16 sweep): the owning line — `const reservation =
1256
+ // budget.checkBudget(weight);` — is a const declaration, unreachable by the sweep's GUARD and
1257
+ // PROPERTY families. Hand-walked: replacing the call with a constant reservation (charging
1258
+ // nothing) reddens THIS cell — the 11th call succeeds when the ceiling check is skipped, so
1259
+ // `count() === 10` fails. The pin is live, just outside the sweep's grammar.
1260
+ withConnectorRoot('togetherai.connector.live_guard_budget', async (root) => {
1261
+ let fetched = 0;
1262
+ const count = () => fetched;
1263
+ // An ISOLATED ledger under this verify's own root: the default ledger path is shared across
1264
+ // the process, so another test's charges would make this verify order-dependent (§9 round
1265
+ // one, S1).
1266
+ const exec = liveTogetheraiExecute('sk_twin_test', 'https://api.together.xyz', {
1267
+ fetchImpl: (async () => { fetched += 1; return new Response(JSON.stringify({ id: 'm' }), { status: 200 }); }) as unknown as typeof fetch,
1268
+ budgetOptions: { path: join(root, 'budget-ledger.json') },
1269
+ });
1270
+ try { await exec('POST', '/v1/chat/completions', { model: 'm' }); } catch { return false; }
1271
+ if (count() !== 1) return false;
1272
+ // inference weight 6: after 10 calls the 60-unit window is exhausted → the 11th refuses.
1273
+ for (let i = 0; i < 9; i++) {
1274
+ try { await exec('POST', '/v1/chat/completions', { model: 'm' }); } catch { return false; }
1275
+ }
1276
+ try {
1277
+ await exec('POST', '/v1/chat/completions', { model: 'm' });
1278
+ return false; // the 11th must have been refused
1279
+ } catch {
1280
+ return count() === 10;
1281
+ }
1282
+ })),
1283
+
1284
+ // ── v2 management half — real Together surface, out of the served scope ─────
1285
+ todo('togetherai.endpoints.crud', 'endpoints', 'v2 endpoints (create/list/get/update/delete + hardware + clusters/availability-zones)', 'api', 'niche'),
1286
+ todo('togetherai.endpoints.deployments', 'endpoints', 'deployments + rollouts + ab/shadow experiments + adapters', 'api', 'niche'),
1287
+ todo('togetherai.compute.clusters', 'compute', 'compute clusters/regions/storage + remediations', 'api', 'niche'),
1288
+ todo('togetherai.videos', 'videos', 'video generation (v2 base URL)', 'api', 'niche'),
1289
+ todo('togetherai.evaluation', 'evaluation', 'evaluation runs + model-list', 'api', 'niche'),
1290
+ todo('togetherai.queue', 'queue', 'queue submit/status/cancel/clear/metrics', 'api', 'niche'),
1291
+ todo('togetherai.tci', 'tci', 'tci execute + sessions', 'api', 'niche'),
1292
+ todo('togetherai.rl', 'models', 'rl model-resources + training-sessions + operations (v2 management half)', 'api', 'niche'),
1293
+ todo('togetherai.audio.websocket', 'audio', '/v1/audio/speech/websocket (realtime speech)', 'api', 'niche'),
1294
+ todo('togetherai.finetunes.metrics', 'fine_tuning', '/v1/fine-tunes/{id}/metrics + download-tokenized-dataset + /finetune/download', 'api', 'niche'),
1295
+ todo('togetherai.models.upload', 'models', 'POST /v1/models (upload a custom model) + /v1/models/{id}/events', 'api', 'niche'),
1296
+ todo('togetherai.billing', 'usage', '/v1/billing/usage', 'api', 'niche'),
1297
+ // Together's error ENVELOPE behavior as a first-class area (the {message,type} two-key body
1298
+ // every 4xx/5xx carries, and its status table) — the per-status cases live in their areas.
1299
+ todo('togetherai.errors.envelope', 'errors', 'the vendor error envelope {message,type[,param,code]} across every 4xx/5xx (consistency sweep)', 'api', 'core'),
1300
+ todo('togetherai.usage.endpoints', 'usage', 'the v2 usage/reporting endpoints (model usage, balances)', 'api', 'niche'),
1301
+ todo('togetherai.batches.progression', 'batches', 'the asynchronous batch status progression (VALIDATING→IN_PROGRESS→COMPLETED) — needs a write-on-tick design that keeps GETs read-only', 'api', 'common'),
1302
+ todo('togetherai.connector.pull_finetunes', 'connector', 'the connector pulls no finetune collection (COLLECTIONS covers model/file/batch) — a finetune created at the vendor never mirrors in', 'connector', 'common'),
1303
+ todo('togetherai.finetunes.progression', 'fine_tuning', 'the asynchronous fine-tune status progression (pending→running→completed) — same constraint as batches', 'api', 'common'),
1304
+ todo('togetherai.files.finetune_validation', 'files', 'fine-tune file VALIDATION (format checks + validation_report on the FileResponse)', 'api', 'common'),
1305
+ ];
1306
+
1307
+ export const TOGETHERAI_AREAS = [
1308
+ 'audio', 'auth', 'batches', 'chat', 'compute', 'conformance', 'connector', 'embeddings',
1309
+ 'endpoints', 'errors', 'evaluation', 'files', 'fine_tuning', 'images', 'models', 'protocol', 'queue',
1310
+ 'rate_limits', 'rerank', 'streaming', 'structured_outputs', 'tools', 'tci', 'usage', 'videos', 'whoami',
1311
+ ] as const;
1312
+
1313
+ export function togetheraiCapabilities(): Promise<CapabilityReport> {
1314
+ return checkCapabilities('togetherai', TOGETHERAI_CAPABILITIES);
1315
+ }