@arnilo/prism 0.3.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -1
- package/README.md +42 -62
- package/dist/agent-run-lifecycle.js +4 -0
- package/dist/agent-run-state.d.ts +5 -2
- package/dist/agent-run-state.js +18 -8
- package/dist/agent-session/session/assemble.d.ts +6 -0
- package/dist/agent-session/session/assemble.js +391 -0
- package/dist/agent-session/session/persist.d.ts +28 -0
- package/dist/agent-session/session/persist.js +166 -0
- package/dist/agent-session/session/provider-round.d.ts +6 -0
- package/dist/agent-session/session/provider-round.js +231 -0
- package/dist/agent-session/session/tool-round.d.ts +31 -0
- package/dist/agent-session/session/tool-round.js +473 -0
- package/dist/agent-session/session/types.d.ts +115 -0
- package/dist/agent-session/session/types.js +5 -0
- package/dist/agent-session/session.d.ts +54 -41
- package/dist/agent-session/session.js +23 -1132
- package/dist/capture.d.ts +63 -0
- package/dist/capture.js +67 -0
- package/dist/cli-dev.d.ts +29 -0
- package/dist/cli-dev.js +52 -0
- package/dist/cli-init.d.ts +34 -3
- package/dist/cli-init.js +192 -24
- package/dist/cli-runner.d.ts +6 -2
- package/dist/cli-runner.js +57 -10
- package/dist/content.d.ts +3 -3
- package/dist/content.js +3 -1
- package/dist/contracts-core/agent.d.ts +8 -0
- package/dist/contracts-core/batch.d.ts +97 -0
- package/dist/contracts-core/batch.js +65 -0
- package/dist/contracts-core/content.d.ts +72 -1
- package/dist/contracts-core/embeddings.d.ts +30 -0
- package/dist/contracts-core/embeddings.js +17 -0
- package/dist/contracts-core/images.d.ts +60 -0
- package/dist/contracts-core/images.js +17 -0
- package/dist/contracts-core/moderation.d.ts +46 -0
- package/dist/contracts-core/moderation.js +34 -0
- package/dist/contracts-core/speech.d.ts +39 -0
- package/dist/contracts-core/speech.js +17 -0
- package/dist/contracts-core/transcription.d.ts +48 -0
- package/dist/contracts-core/transcription.js +17 -0
- package/dist/contracts-core/video.d.ts +61 -0
- package/dist/contracts-core/video.js +17 -0
- package/dist/contracts-core.d.ts +7 -0
- package/dist/contracts-core.js +7 -0
- package/dist/contracts-protocol.d.ts +18 -0
- package/dist/contracts-run-state.d.ts +1 -2
- package/dist/index.d.ts +7 -3
- package/dist/index.js +5 -3
- package/dist/input.d.ts +8 -0
- package/dist/input.js +4 -0
- package/dist/node/agent-definitions.d.ts +1 -8
- package/dist/node/agent-definitions.js +0 -34
- package/dist/node/settings.d.ts +0 -1
- package/dist/node/settings.js +0 -5
- package/dist/pinned-fetch.js +29 -3
- package/dist/provider-events.js +3 -4
- package/dist/providers/media.d.ts +1 -2
- package/dist/providers/media.js +1 -4
- package/dist/rpc.d.ts +1 -1
- package/dist/rpc.js +4 -4
- package/dist/testing/persistence-schema.d.ts +1 -1
- package/dist/testing/persistence-schema.js +32 -28
- package/dist/testing/provider-conformance.d.ts +114 -5
- package/dist/testing/provider-conformance.js +342 -0
- package/dist/testing/tool-conformance.d.ts +25 -0
- package/dist/testing/tool-conformance.js +128 -1
- package/dist/testing/tool-effect-store-conformance.d.ts +0 -1
- package/dist/testing/tool-effect-store-conformance.js +0 -3
- package/dist/thinking.d.ts +48 -9
- package/dist/thinking.js +134 -8
- package/dist/tool-search.d.ts +76 -0
- package/dist/tool-search.js +199 -0
- package/docs/0.1.0-readiness.md +3 -3
- package/docs/a2a.md +2 -2
- package/docs/acp-agent.md +1 -1
- package/docs/acp.md +3 -3
- package/docs/ag-ui-adoption.md +1 -1
- package/docs/ag-ui.md +1 -2
- package/docs/agent-definitions.md +1 -1
- package/docs/agent-events.md +5 -5
- package/docs/agent-identity.md +13 -2
- package/docs/audit-export.md +3 -3
- package/docs/batch-jobs.md +120 -0
- package/docs/browser-automation.md +5 -5
- package/docs/caveman.md +2 -2
- package/docs/cli-rpc.md +43 -9
- package/docs/coding-agent-tools.md +19 -19
- package/docs/coding-review-and-diagnostics.md +2 -2
- package/docs/coding-security.md +5 -5
- package/docs/coding-tools.md +82 -0
- package/docs/coding-workspaces.md +2 -2
- package/docs/compaction-and-retry.md +2 -2
- package/docs/compaction-llm.md +4 -4
- package/docs/compaction-observational-memory.md +3 -3
- package/docs/computer-use-linux.md +13 -2
- package/docs/context-and-skills.md +3 -1
- package/docs/conversations.md +4 -4
- package/docs/core.md +85 -0
- package/docs/credential-storage.md +12 -8
- package/docs/credentials-and-redaction.md +1 -1
- package/docs/data-classification.md +1 -1
- package/docs/database-persistence.md +7 -3
- package/docs/dev-inspector.md +103 -0
- package/docs/device-adapters.md +2 -2
- package/docs/diagrams.md +247 -0
- package/docs/document-reader.md +6 -6
- package/docs/documents.md +214 -0
- package/docs/embeddings.md +112 -0
- package/docs/enterprise-postgres-state.md +7 -7
- package/docs/evaluations.md +41 -7
- package/docs/extensions.md +3 -3
- package/docs/forge-integration.md +3 -3
- package/docs/graft.md +5 -5
- package/docs/guardrails.md +2 -2
- package/docs/host-security.md +16 -15
- package/docs/image-generation.md +129 -0
- package/docs/impeccable.md +7 -5
- package/docs/index.md +84 -46
- package/docs/indexed-code-search.md +2 -2
- package/docs/language-intelligence.md +4 -4
- package/docs/live-testing.md +126 -0
- package/docs/mcp-tools.md +44 -13
- package/docs/middleware-hooks.md +1 -1
- package/docs/migrate-to-0.4.md +312 -0
- package/docs/migrate-to-0.5.md +122 -0
- package/docs/migration.md +51 -1
- package/docs/model-registry.md +38 -0
- package/docs/model-routing.md +6 -6
- package/docs/moderation.md +117 -0
- package/docs/multi-agent-patterns.md +177 -0
- package/docs/multimodal-content.md +27 -3
- package/docs/obscura.md +12 -12
- package/docs/observability.md +32 -7
- package/docs/openapi-tools.md +14 -4
- package/docs/operations.md +11 -0
- package/docs/performance.md +30 -10
- package/docs/persistence-credentials-multimodality-primitives.md +7 -7
- package/docs/policy-and-audit.md +18 -8
- package/docs/ponytail.md +3 -3
- package/docs/postgres-persistence.md +5 -5
- package/docs/process-sessions.md +2 -2
- package/docs/prompt-registry.md +106 -0
- package/docs/provider-caching.md +36 -32
- package/docs/provider-conformance.md +24 -2
- package/docs/provider-packages.md +58 -22
- package/docs/provider-primitives.md +5 -5
- package/docs/provider-request-policies.md +1 -1
- package/docs/providers/ai-sdk.md +18 -6
- package/docs/providers/alibaba.md +10 -6
- package/docs/providers/anthropic.md +10 -6
- package/docs/providers/azure.md +20 -4
- package/docs/providers/bedrock.md +18 -3
- package/docs/providers/clinepass.md +7 -3
- package/docs/providers/commandcode.md +253 -0
- package/docs/providers/deepseek.md +7 -3
- package/docs/providers/google.md +8 -4
- package/docs/providers/hyper.md +284 -0
- package/docs/providers/kimi.md +7 -3
- package/docs/providers/neuralwatt.md +12 -8
- package/docs/providers/ollama.md +18 -3
- package/docs/providers/openai-compatible.md +5 -1
- package/docs/providers/openai.md +9 -5
- package/docs/providers/opencode-go.md +8 -4
- package/docs/providers/openrouter.md +8 -4
- package/docs/providers/vertex.md +21 -5
- package/docs/providers/xai.md +7 -3
- package/docs/providers/zai.md +7 -3
- package/docs/rag.md +31 -9
- package/docs/release-and-install.md +181 -76
- package/docs/resource-loading.md +1 -1
- package/docs/runs-and-usage.md +28 -3
- package/docs/server.md +94 -5
- package/docs/settings-auth-trust-security.md +7 -5
- package/docs/sheets.md +229 -0
- package/docs/speech.md +126 -0
- package/docs/sqlite-persistence.md +4 -4
- package/docs/supervisors.md +4 -3
- package/docs/thinking-and-reasoning.md +93 -60
- package/docs/tool-conformance.md +28 -3
- package/docs/tool-execution-primitives.md +8 -8
- package/docs/tools.md +32 -5
- package/docs/web-tools.md +3 -3
- package/docs/wiki.md +7 -7
- package/docs/work-artifacts-and-review.md +17 -6
- package/docs/work-connectors.md +4 -4
- package/docs/work-tools.md +5 -5
- package/docs/workflow-orchestration-primitives.md +35 -11
- package/docs/workflows.md +74 -13
- package/docs/working-and-semantic-memory.md +53 -5
- package/package.json +14 -31
- package/templates/README.md +23 -0
- package/templates/deep-research/README.md.tmpl +47 -0
- package/templates/deep-research/env.example.tmpl +12 -0
- package/templates/deep-research/gitignore.tmpl +7 -0
- package/templates/deep-research/manifest.json +12 -0
- package/templates/deep-research/package.json.tmpl +23 -0
- package/templates/deep-research/src/agent.ts.tmpl +81 -0
- package/templates/deep-research/src/index.ts.tmpl +53 -0
- package/templates/deep-research/src/tests/research.test.ts.tmpl +114 -0
- package/templates/deep-research/src/tools.ts.tmpl +86 -0
- package/templates/deep-research/src/types.ts.tmpl +45 -0
- package/templates/deep-research/src/workflow.ts.tmpl +156 -0
- package/templates/deep-research/tsconfig.json.tmpl +15 -0
- package/templates/init/manifest.json +5 -0
- package/templates/init/package.json.tmpl +2 -1
- package/templates/init/providers.json +40 -24
- package/docs/antigravity-agent.md +0 -207
package/dist/cli-runner.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { basename, dirname } from "node:path";
|
|
3
3
|
import process from "node:process";
|
|
4
|
-
import {
|
|
4
|
+
import { runPrismDevSubcommand } from "./cli-dev.js";
|
|
5
|
+
import { initUsage, loadProvidersCatalog, runInitCommand } from "./cli-init.js";
|
|
5
6
|
import { providerAddUsage, runProviderAddCommand } from "./cli-provider-add.js";
|
|
6
7
|
import { createContributionRegistries, registerDiscoveredContributions } from "./contributions.js";
|
|
7
8
|
import { createAgent, createContributionRegistry, createMockProvider, providerDone, providerTextDelta, resolveInstructionInjectors, } from "./index.js";
|
|
@@ -13,12 +14,16 @@ import { createPathTrustPolicy } from "./node/trust.js";
|
|
|
13
14
|
import { runRpcServer } from "./rpc.js";
|
|
14
15
|
import { createSkillRegistry } from "./skills.js";
|
|
15
16
|
export const usage = `Usage: prism [--mode print|json|rpc] [-p prompt] [options]
|
|
16
|
-
prism init <dir> [--provider <name>] [--with-workflows] [--with-evals] [--force]
|
|
17
|
+
prism init <dir> [--template <name>] [--list-templates] [--provider <name>] [--with-workflows] [--with-evals] [--force]
|
|
17
18
|
prism providers add <name> [--base-url <url>] [--env-key <name>] [--model <id>] [--force]
|
|
19
|
+
prism dev [--port <n>] [--host <addr>] (loopback inspector; delegates into @arnilo/prism-dev)
|
|
20
|
+
|
|
18
21
|
|
|
19
22
|
Options:
|
|
20
23
|
-p, --prompt <text> Prompt to run in print/json mode
|
|
21
|
-
--provider <name>
|
|
24
|
+
--provider <name> Provider id from the init provider catalog ('mock' is built in;
|
|
25
|
+
real providers need their @arnilo/prism-providers package +
|
|
26
|
+
credential env var)
|
|
22
27
|
--model <name> Explicit model name
|
|
23
28
|
--session <id> Session id
|
|
24
29
|
--system <text> System instructions
|
|
@@ -201,11 +206,19 @@ function parseKinds(csv, flag) {
|
|
|
201
206
|
return kinds;
|
|
202
207
|
}
|
|
203
208
|
export async function runCli(argv, runtime) {
|
|
209
|
+
if (argv[0] === "dev") {
|
|
210
|
+
return runPrismDevSubcommand(argv.slice(1), {
|
|
211
|
+
stdout: runtime.stdout,
|
|
212
|
+
stderr: runtime.stderr,
|
|
213
|
+
...(runtime.loadDevCli ? { loadDevCli: runtime.loadDevCli } : {}),
|
|
214
|
+
});
|
|
215
|
+
}
|
|
204
216
|
if (argv[0] === "init") {
|
|
205
217
|
const initRuntime = {
|
|
206
218
|
stdout: runtime.stdout,
|
|
207
219
|
stderr: runtime.stderr,
|
|
208
220
|
...(runtime.initTemplatesRoot !== undefined ? { templatesRoot: runtime.initTemplatesRoot } : {}),
|
|
221
|
+
...(runtime.initGalleryRoot !== undefined ? { galleryRoot: runtime.initGalleryRoot } : {}),
|
|
209
222
|
...(runtime.initPackageVersion !== undefined ? { packageVersion: runtime.initPackageVersion } : {}),
|
|
210
223
|
...(runtime.cwd !== undefined ? { cwd: runtime.cwd } : {}),
|
|
211
224
|
};
|
|
@@ -304,7 +317,7 @@ export async function runCli(argv, runtime) {
|
|
|
304
317
|
});
|
|
305
318
|
options = { ...options, systemPromptLayers: layers };
|
|
306
319
|
}
|
|
307
|
-
const session = (runtime.createSession ?? defaultCreateSession)(options);
|
|
320
|
+
const session = await (runtime.createSession ?? defaultCreateSession)(options);
|
|
308
321
|
await runPromptMode(session, options, runtime.stdout, mode);
|
|
309
322
|
return 0;
|
|
310
323
|
}
|
|
@@ -335,13 +348,47 @@ export async function runPromptMode(session, options, stdout, mode) {
|
|
|
335
348
|
}
|
|
336
349
|
export class CliUsageError extends Error {
|
|
337
350
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
351
|
+
/** Build the agent session for the CLI. Real providers resolve through the init
|
|
352
|
+
* provider catalog (`templates/init/providers.json`): the catalog names the
|
|
353
|
+
* factory module/export and credential env var, the CLI imports it from the
|
|
354
|
+
* consumer's node_modules — same catalog `prism init` scaffolds from, so the
|
|
355
|
+
* CLI and the scaffold never disagree about how a provider is built. */
|
|
356
|
+
async function defaultCreateSession(options) {
|
|
357
|
+
const providerId = options.provider;
|
|
358
|
+
if (!providerId) {
|
|
359
|
+
throw new CliUsageError("No provider configured. Pass --provider <id> (see the init provider catalog, or 'mock') or embed Prism with an explicit provider.");
|
|
360
|
+
}
|
|
361
|
+
if (providerId === "mock")
|
|
362
|
+
return mockSession(options);
|
|
363
|
+
const spec = loadProvidersCatalog().get(providerId);
|
|
364
|
+
if (!spec?.factoryModule || !spec.factoryExport) {
|
|
365
|
+
throw new CliUsageError(`Unknown provider "${providerId}". Supported: ${["mock", ...loadProvidersCatalog().keys()].join(", ")} — or embed Prism with an explicit provider.`);
|
|
366
|
+
}
|
|
367
|
+
const envKey = spec.envKey ?? "";
|
|
368
|
+
if (!process.env[envKey])
|
|
369
|
+
throw new CliUsageError(`Provider "${providerId}" requires ${envKey} in the environment.`);
|
|
370
|
+
let factory;
|
|
371
|
+
try {
|
|
372
|
+
factory = (await import(spec.factoryModule))[spec.factoryExport];
|
|
373
|
+
}
|
|
374
|
+
catch {
|
|
375
|
+
throw new CliUsageError(`Provider "${providerId}" needs the ${spec.packageName} package installed (import ${spec.factoryModule} failed).`);
|
|
376
|
+
}
|
|
377
|
+
if (typeof factory !== "function") {
|
|
378
|
+
throw new CliUsageError(`Provider "${providerId}": ${spec.factoryModule} does not export ${spec.factoryExport}.`);
|
|
379
|
+
}
|
|
380
|
+
const providerInstance = factory({ apiKey: () => process.env[envKey] });
|
|
381
|
+
const modelConfig = { provider: spec.modelProvider, model: options.model ?? spec.modelName };
|
|
382
|
+
return agentSession({ ...options, providerInstance, modelConfig });
|
|
383
|
+
}
|
|
384
|
+
function mockSession(options) {
|
|
385
|
+
const modelConfig = { provider: "mock", model: options.model ?? "mock" };
|
|
386
|
+
return agentSession({ ...options, providerInstance: createMockProvider([providerTextDelta("Hello"), providerDone()]), modelConfig });
|
|
387
|
+
}
|
|
388
|
+
function agentSession(options) {
|
|
342
389
|
return createAgent({
|
|
343
|
-
model,
|
|
344
|
-
provider:
|
|
390
|
+
model: options.modelConfig,
|
|
391
|
+
provider: options.providerInstance,
|
|
345
392
|
instructions: options.system,
|
|
346
393
|
// ponytail: Phase 31 — file layers compose with `instructions` (base) via the existing
|
|
347
394
|
// composeSystemPrompt pipeline; rank order (user<package<app<run) is enforced inside.
|
package/dist/content.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { ContentBlock, ImageContent, Message, ModelConfig, ResourceLoadContext, ResourceLoader } from "./contracts.js";
|
|
1
|
+
import type { ContentBlock, ImageContent, Message, ModelConfig, ResourceLoadContext, ResourceLoader, VideoContent } from "./contracts.js";
|
|
2
2
|
/** Known model input capability tags for `ModelCapabilities.input`. */
|
|
3
|
-
export declare const MODEL_INPUT_CAPABILITIES: readonly ["text", "image", "audio", "file", "document"];
|
|
3
|
+
export declare const MODEL_INPUT_CAPABILITIES: readonly ["text", "image", "audio", "file", "document", "video"];
|
|
4
4
|
export type ModelInputCapability = (typeof MODEL_INPUT_CAPABILITIES)[number];
|
|
5
5
|
/** Default per-item media byte ceiling (10 MB; aligns with coding-agent image bounds). */
|
|
6
6
|
export declare const DEFAULT_MAX_MEDIA_ITEM_BYTES = 10000000;
|
|
@@ -45,7 +45,7 @@ export interface DocumentContent {
|
|
|
45
45
|
readonly transcript?: string;
|
|
46
46
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
47
47
|
}
|
|
48
|
-
export type MediaContentBlock = AudioContent | FileContent | DocumentContent | ImageContent;
|
|
48
|
+
export type MediaContentBlock = AudioContent | FileContent | DocumentContent | ImageContent | VideoContent;
|
|
49
49
|
export interface MediaContentBounds {
|
|
50
50
|
readonly maxItemBytes?: number;
|
|
51
51
|
readonly maxRequestBytes?: number;
|
package/dist/content.js
CHANGED
|
@@ -3,7 +3,7 @@ import { isIP } from "node:net";
|
|
|
3
3
|
import { pinnedFetch } from "./pinned-fetch.js";
|
|
4
4
|
import { assertPermission } from "./security.js";
|
|
5
5
|
/** Known model input capability tags for `ModelCapabilities.input`. */
|
|
6
|
-
export const MODEL_INPUT_CAPABILITIES = ["text", "image", "audio", "file", "document"];
|
|
6
|
+
export const MODEL_INPUT_CAPABILITIES = ["text", "image", "audio", "file", "document", "video"];
|
|
7
7
|
/** Default per-item media byte ceiling (10 MB; aligns with coding-agent image bounds). */
|
|
8
8
|
export const DEFAULT_MAX_MEDIA_ITEM_BYTES = 10_000_000;
|
|
9
9
|
/** Default total media byte budget per request assembly. */
|
|
@@ -44,6 +44,8 @@ export function contentBlockInputModality(block) {
|
|
|
44
44
|
return "file";
|
|
45
45
|
case "document":
|
|
46
46
|
return "document";
|
|
47
|
+
case "video":
|
|
48
|
+
return "video";
|
|
47
49
|
default:
|
|
48
50
|
return undefined;
|
|
49
51
|
}
|
|
@@ -59,6 +59,9 @@ export interface AgentConfig {
|
|
|
59
59
|
readonly activateAllSkills?: true;
|
|
60
60
|
/** Progressive: catalog (name+description) unless loaded; eager: full instructions every turn. Default progressive. */
|
|
61
61
|
readonly skillsDisclosure?: import("../skill-disclosure.js").SkillsDisclosure;
|
|
62
|
+
/** Tools disclosure: "all" (default) sends every active tool schema; "search" sends top-k + the generated `search_tools` tool. */
|
|
63
|
+
readonly toolsDisclosure?: import("../tool-search.js").ToolsDisclosure;
|
|
64
|
+
readonly toolsSearch?: import("../tool-search.js").ToolsSearchOptions;
|
|
62
65
|
/** Opt-in projection-only fold for aged large tool results in provider view; store untouched. */
|
|
63
66
|
readonly toolResultFold?: import("../tool-result-fold.js").ToolResultFoldOptions;
|
|
64
67
|
readonly inputBuilder?: InputBuilder;
|
|
@@ -74,6 +77,8 @@ export interface AgentConfig {
|
|
|
74
77
|
readonly systemPrompt?: SystemPromptConfig;
|
|
75
78
|
readonly redactor?: SecretRedactor;
|
|
76
79
|
readonly runLedger?: RunLedger;
|
|
80
|
+
/** Optional host-supplied pricing adapter: turn usage without a provider-reported cost is priced through it; absent or stale quotes degrade to usage-only. */
|
|
81
|
+
readonly costCatalog?: import("./content.js").CostCatalog;
|
|
77
82
|
/** Optional durable recovery store. */
|
|
78
83
|
readonly effectStore?: ToolEffectStore;
|
|
79
84
|
readonly ownership?: OwnershipScope;
|
|
@@ -252,6 +257,9 @@ export interface PromptBuildRequest {
|
|
|
252
257
|
readonly skills?: readonly Skill[];
|
|
253
258
|
readonly skillsDisclosure?: import("../skill-disclosure.js").SkillsDisclosure;
|
|
254
259
|
readonly loadedSkills?: import("../skill-disclosure.js").LoadedSkillSet;
|
|
260
|
+
/** Tools disclosure: "all" (default) sends every active tool schema; "search" sends top-k + the generated `search_tools` tool. */
|
|
261
|
+
readonly toolsDisclosure?: import("../tool-search.js").ToolsDisclosure;
|
|
262
|
+
readonly toolsSearch?: import("../tool-search.js").ToolsSearchOptions;
|
|
255
263
|
/** Skills demoted to catalog-only by context budget this turn. */
|
|
256
264
|
readonly demotedSkillBodies?: readonly string[];
|
|
257
265
|
readonly tools?: readonly ToolDefinition[];
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/** Provider-neutral async batch-jobs contract (plan 061 Task 7).
|
|
2
|
+
*
|
|
3
|
+
* Standalone contract — deliberately not coupled to the orchestration saga seam
|
|
4
|
+
* in v1 (plan decision). Job ids are opaque strings; request payloads are
|
|
5
|
+
* provider-native `JsonObject` bodies and inherit the provider's request caps;
|
|
6
|
+
* polling is a plain exported utility (`pollBatch`), never loop-integrated into
|
|
7
|
+
* core.
|
|
8
|
+
*/
|
|
9
|
+
import type { JsonObject, ModelCapabilities, ModelConfig } from "./content.js";
|
|
10
|
+
/** Neutral job state union. Adapters map provider states onto these:
|
|
11
|
+
* `queued` (submitted, not yet running), `cancelling`, and the three terminal
|
|
12
|
+
* states `completed` / `failed` / `cancelled` / `expired`. */
|
|
13
|
+
export type BatchJobState = "queued" | "running" | "cancelling" | "completed" | "failed" | "cancelled" | "expired";
|
|
14
|
+
export declare const BATCH_TERMINAL_STATES: readonly BatchJobState[];
|
|
15
|
+
export declare function isBatchJobTerminal(job: Pick<BatchJob, "state">): boolean;
|
|
16
|
+
export type BatchJobsErrorCode = "empty_requests" | "too_many_requests" | "unsupported_model" | "job_not_found" | "invalid_cursor" | "request_failed" | "response_malformed" | "unsupported_operation" | "job_failed" | "job_cancelled" | "job_expired";
|
|
17
|
+
export declare class BatchJobsError extends Error {
|
|
18
|
+
readonly code: BatchJobsErrorCode;
|
|
19
|
+
constructor(code: BatchJobsErrorCode, message: string);
|
|
20
|
+
}
|
|
21
|
+
export declare function modelSupportsBatchJobs(capabilities?: ModelCapabilities): boolean;
|
|
22
|
+
export declare function assertBatchJobsSupported(model: ModelConfig): void;
|
|
23
|
+
/** One batched request: provider-native body plus an optional caller-assigned
|
|
24
|
+
* correlation id echoed on results. Bodies are opaque to the contract. */
|
|
25
|
+
export interface BatchRequestItem {
|
|
26
|
+
readonly customId?: string;
|
|
27
|
+
readonly body: JsonObject;
|
|
28
|
+
}
|
|
29
|
+
export interface BatchSubmitRequest {
|
|
30
|
+
readonly model: string;
|
|
31
|
+
readonly requests: readonly BatchRequestItem[];
|
|
32
|
+
/** Provider-native routing metadata (weights, priorities) — opaque passthrough. */
|
|
33
|
+
readonly metadata?: JsonObject;
|
|
34
|
+
readonly signal?: AbortSignal;
|
|
35
|
+
}
|
|
36
|
+
export interface BatchJob {
|
|
37
|
+
/** Opaque provider job id — contract never parses or scopes it. */
|
|
38
|
+
readonly id: string;
|
|
39
|
+
readonly state: BatchJobState;
|
|
40
|
+
readonly requestCounts?: {
|
|
41
|
+
readonly total: number;
|
|
42
|
+
readonly completed: number;
|
|
43
|
+
readonly failed: number;
|
|
44
|
+
};
|
|
45
|
+
readonly createdAt?: string;
|
|
46
|
+
readonly completedAt?: string;
|
|
47
|
+
readonly expiresAt?: string;
|
|
48
|
+
/** Provider-native job fields, unmodified, for host-side audits. */
|
|
49
|
+
readonly raw?: JsonObject;
|
|
50
|
+
/** Terminal failure detail when `state` is `failed`. */
|
|
51
|
+
readonly error?: {
|
|
52
|
+
readonly code?: string;
|
|
53
|
+
readonly message?: string;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export interface BatchResultItem {
|
|
57
|
+
readonly customId: string;
|
|
58
|
+
/** Provider-native per-request response (status + payload), when it succeeded. */
|
|
59
|
+
readonly response?: JsonObject;
|
|
60
|
+
/** Per-request failure detail (the job itself may still be `completed`). */
|
|
61
|
+
readonly error?: {
|
|
62
|
+
readonly code?: string;
|
|
63
|
+
readonly message?: string;
|
|
64
|
+
};
|
|
65
|
+
/** Provider-native raw line for audits. */
|
|
66
|
+
readonly raw?: JsonObject;
|
|
67
|
+
}
|
|
68
|
+
export interface BatchResultsPage {
|
|
69
|
+
readonly job?: BatchJob;
|
|
70
|
+
readonly items: readonly BatchResultItem[];
|
|
71
|
+
/** Opaque continuation token; `null`/`undefined` when the page is last. */
|
|
72
|
+
readonly nextCursor?: string | null;
|
|
73
|
+
}
|
|
74
|
+
export interface BatchResultsOptions {
|
|
75
|
+
readonly cursor?: string | null;
|
|
76
|
+
readonly pageSize?: number;
|
|
77
|
+
readonly signal?: AbortSignal;
|
|
78
|
+
}
|
|
79
|
+
export interface BatchJobsProvider {
|
|
80
|
+
readonly id: string;
|
|
81
|
+
submit(request: BatchSubmitRequest): Promise<BatchJob>;
|
|
82
|
+
status(jobId: string): Promise<BatchJob>;
|
|
83
|
+
cancel(jobId: string): Promise<BatchJob>;
|
|
84
|
+
results(jobId: string, options?: BatchResultsOptions): Promise<BatchResultsPage>;
|
|
85
|
+
}
|
|
86
|
+
export interface PollBatchOptions {
|
|
87
|
+
readonly intervalMs?: number;
|
|
88
|
+
/** Backoff multiplier applied per poll; caps at `maxIntervalMs`. */
|
|
89
|
+
readonly backoffMultiplier?: number;
|
|
90
|
+
readonly maxIntervalMs?: number;
|
|
91
|
+
readonly maxAttempts?: number;
|
|
92
|
+
readonly signal?: AbortSignal;
|
|
93
|
+
}
|
|
94
|
+
/** Poll a job until it reaches a terminal state. Plain utility — core never
|
|
95
|
+
* calls it. Terminal failure states surface typed `BatchJobsError`s
|
|
96
|
+
* (`job_failed` / `job_cancelled` / `job_expired`); only `completed` resolves. */
|
|
97
|
+
export declare function pollBatch(provider: BatchJobsProvider, jobId: string, options?: PollBatchOptions): Promise<BatchJob>;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export const BATCH_TERMINAL_STATES = ["completed", "failed", "cancelled", "expired"];
|
|
2
|
+
export function isBatchJobTerminal(job) {
|
|
3
|
+
return BATCH_TERMINAL_STATES.includes(job.state);
|
|
4
|
+
}
|
|
5
|
+
export class BatchJobsError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
constructor(code, message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "BatchJobsError";
|
|
10
|
+
this.code = code;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function modelSupportsBatchJobs(capabilities) {
|
|
14
|
+
return capabilities?.batchJobs === true;
|
|
15
|
+
}
|
|
16
|
+
export function assertBatchJobsSupported(model) {
|
|
17
|
+
if (!modelSupportsBatchJobs(model.capabilities)) {
|
|
18
|
+
throw new BatchJobsError("unsupported_model", `Model ${model.provider}/${model.model} does not declare the batchJobs capability`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/** Poll a job until it reaches a terminal state. Plain utility — core never
|
|
22
|
+
* calls it. Terminal failure states surface typed `BatchJobsError`s
|
|
23
|
+
* (`job_failed` / `job_cancelled` / `job_expired`); only `completed` resolves. */
|
|
24
|
+
export async function pollBatch(provider, jobId, options = {}) {
|
|
25
|
+
const intervalMs = options.intervalMs ?? 30_000;
|
|
26
|
+
const multiplier = options.backoffMultiplier ?? 1;
|
|
27
|
+
const maxIntervalMs = options.maxIntervalMs ?? intervalMs * 16;
|
|
28
|
+
const maxAttempts = options.maxAttempts ?? Number.POSITIVE_INFINITY;
|
|
29
|
+
let delay = intervalMs;
|
|
30
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
31
|
+
if (options.signal?.aborted)
|
|
32
|
+
throw options.signal.reason ?? new Error("pollBatch aborted");
|
|
33
|
+
let job;
|
|
34
|
+
try {
|
|
35
|
+
job = await provider.status(jobId);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (error instanceof BatchJobsError && error.code === "job_not_found") {
|
|
39
|
+
throw new BatchJobsError("job_not_found", `pollBatch: job ${jobId} not found`);
|
|
40
|
+
}
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
if (isBatchJobTerminal(job)) {
|
|
44
|
+
if (job.state === "completed")
|
|
45
|
+
return job;
|
|
46
|
+
if (job.state === "cancelled")
|
|
47
|
+
throw new BatchJobsError("job_cancelled", `Batch job ${jobId} was cancelled`);
|
|
48
|
+
if (job.state === "expired")
|
|
49
|
+
throw new BatchJobsError("job_expired", `Batch job ${jobId} expired before completion`);
|
|
50
|
+
throw new BatchJobsError("job_failed", `Batch job ${jobId} failed: ${job.error?.message ?? "provider reported failure"}`);
|
|
51
|
+
}
|
|
52
|
+
if (attempt === maxAttempts)
|
|
53
|
+
break;
|
|
54
|
+
await new Promise((resolve) => {
|
|
55
|
+
const timer = setTimeout(resolve, delay);
|
|
56
|
+
options.signal?.addEventListener("abort", () => {
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
resolve();
|
|
59
|
+
}, { once: true });
|
|
60
|
+
});
|
|
61
|
+
delay = Math.min(delay * multiplier, maxIntervalMs);
|
|
62
|
+
}
|
|
63
|
+
throw new BatchJobsError("request_failed", `Batch job ${jobId} did not reach a terminal state within ${maxAttempts} polls`);
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=batch.js.map
|
|
@@ -16,7 +16,7 @@ export interface ErrorInfo {
|
|
|
16
16
|
readonly retryAfterMs?: number;
|
|
17
17
|
readonly cause?: unknown;
|
|
18
18
|
}
|
|
19
|
-
export type ContentBlock = TextContent | ImageContent | AudioContent | FileContent | DocumentContent | ThinkingContent | ToolCallDeltaContent | ToolCallContent | ToolResultContent;
|
|
19
|
+
export type ContentBlock = TextContent | ImageContent | AudioContent | FileContent | DocumentContent | VideoContent | ThinkingContent | ToolCallDeltaContent | ToolCallContent | ToolResultContent;
|
|
20
20
|
export interface TextContent {
|
|
21
21
|
readonly type: "text";
|
|
22
22
|
readonly text: string;
|
|
@@ -30,6 +30,19 @@ export interface ImageContent {
|
|
|
30
30
|
readonly name?: string;
|
|
31
31
|
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
32
32
|
}
|
|
33
|
+
export interface VideoContent {
|
|
34
|
+
readonly type: "video";
|
|
35
|
+
readonly mediaType?: string;
|
|
36
|
+
readonly name?: string;
|
|
37
|
+
/** Base64-encoded video bytes. */
|
|
38
|
+
readonly data?: string;
|
|
39
|
+
readonly url?: string;
|
|
40
|
+
readonly resourceUri?: string;
|
|
41
|
+
readonly durationMs?: number;
|
|
42
|
+
/** Frame-sampling hint for providers that downsample (e.g. Qwen-VL defaults to 2.0). */
|
|
43
|
+
readonly fps?: number;
|
|
44
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
45
|
+
}
|
|
33
46
|
export interface ThinkingContent {
|
|
34
47
|
readonly type: "thinking";
|
|
35
48
|
readonly text: string;
|
|
@@ -92,6 +105,22 @@ export interface ModelCapabilities {
|
|
|
92
105
|
readonly streaming?: boolean;
|
|
93
106
|
/** Native JSON-schema structured output support for this model. */
|
|
94
107
|
readonly structuredOutput?: boolean | "json_schema";
|
|
108
|
+
/** Provider-neutral embeddings generation support (plan 061). */
|
|
109
|
+
readonly embeddings?: boolean;
|
|
110
|
+
/** Portable thinking/reasoning effort levels this model declares, ascending ladder order (`none` < `minimal` < `low` < `medium` < `high` < `xhigh` < `max`). Advisory legality metadata for hosts; absent means forward-compat passthrough (phase 65). */
|
|
111
|
+
readonly thinkingLevels?: readonly string[];
|
|
112
|
+
/** Provider-neutral speech synthesis support (plan 061). */
|
|
113
|
+
readonly speech?: boolean;
|
|
114
|
+
/** Provider-neutral speech transcription support (plan 061). */
|
|
115
|
+
readonly transcription?: boolean;
|
|
116
|
+
/** Provider-neutral image generation/editing support (plan 061). */
|
|
117
|
+
readonly imageGeneration?: boolean;
|
|
118
|
+
/** Provider-neutral video generation support (plan 061). */
|
|
119
|
+
readonly videoGeneration?: boolean;
|
|
120
|
+
/** Provider-neutral moderation classification support (plan 061). */
|
|
121
|
+
readonly moderation?: boolean;
|
|
122
|
+
/** Provider-neutral async batch-jobs support (plan 061). */
|
|
123
|
+
readonly batchJobs?: boolean;
|
|
95
124
|
}
|
|
96
125
|
export interface ModelLimits {
|
|
97
126
|
readonly contextWindow?: number;
|
|
@@ -105,6 +134,36 @@ export interface ModelCost {
|
|
|
105
134
|
readonly currency?: string;
|
|
106
135
|
readonly unit?: string;
|
|
107
136
|
}
|
|
137
|
+
/** Normalized model-list/capability discovery provenance (plan 062): where a
|
|
138
|
+
* listing came from, when, and how long hosts may cache it. */
|
|
139
|
+
export interface ModelDiscoveryProvenance {
|
|
140
|
+
readonly provider: string;
|
|
141
|
+
/** ISO-8601 timestamp of the fetch (or catalog snapshot) moment. */
|
|
142
|
+
readonly fetchedAt: string;
|
|
143
|
+
/** `"api"` = live provider listing; `"catalog"` = host/registry snapshot, no network. */
|
|
144
|
+
readonly source: "api" | "catalog";
|
|
145
|
+
/** Cache-TTL guidance in milliseconds; hosts may serve the result from cache this long. */
|
|
146
|
+
readonly ttlMs?: number;
|
|
147
|
+
}
|
|
148
|
+
export interface ModelDiscoveryOptions {
|
|
149
|
+
/** Cache window in ms; within TTL a cached result is returned without network.
|
|
150
|
+
* `0` forces a refresh. Defaults to the adapter's configured TTL. */
|
|
151
|
+
readonly ttlMs?: number;
|
|
152
|
+
readonly signal?: AbortSignal;
|
|
153
|
+
}
|
|
154
|
+
/** Normalized `listModels()` result: the existing `ModelConfig` contract verbatim
|
|
155
|
+
* (id = `model`, context window = `limits`, capabilities = `capabilities`, pricing
|
|
156
|
+
* hint = `cost`) plus provenance. No new model shape ships. */
|
|
157
|
+
export interface ModelDiscoveryResult {
|
|
158
|
+
readonly models: readonly ModelConfig[];
|
|
159
|
+
readonly provenance: ModelDiscoveryProvenance;
|
|
160
|
+
}
|
|
161
|
+
/** Model-list/capability discovery seam (plan 062). Adapter implementations
|
|
162
|
+
* normalize provider listings to `ModelConfig` and cache per provider within
|
|
163
|
+
* the configured TTL; hosts merge their own catalog overrides on top. */
|
|
164
|
+
export interface ModelDiscovery {
|
|
165
|
+
listModels(options?: ModelDiscoveryOptions): Promise<ModelDiscoveryResult>;
|
|
166
|
+
}
|
|
108
167
|
export interface Usage {
|
|
109
168
|
readonly inputTokens?: number;
|
|
110
169
|
readonly outputTokens?: number;
|
|
@@ -114,3 +173,15 @@ export interface Usage {
|
|
|
114
173
|
readonly cost?: number;
|
|
115
174
|
readonly currency?: string;
|
|
116
175
|
}
|
|
176
|
+
/**
|
|
177
|
+
* Host-supplied pricing adapter (plan 062): quotes cost rates per model id. Core
|
|
178
|
+
* ships no pricing tables — when no catalog is configured, usage is reported
|
|
179
|
+
* without cost fields. Quotes follow the repo-wide `per_million_tokens` unit
|
|
180
|
+
* convention (see {@link ModelCost}); a stale or unknown model must resolve to
|
|
181
|
+
* `undefined` (degrades to usage-only), never throw.
|
|
182
|
+
*/
|
|
183
|
+
export interface CostCatalog {
|
|
184
|
+
get(modelId: string, options?: {
|
|
185
|
+
readonly signal?: AbortSignal;
|
|
186
|
+
}): Promise<ModelCost | undefined>;
|
|
187
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** Provider-neutral embeddings contract (plan 061 Task 2).
|
|
2
|
+
* One-shot batch shape: the request carries the abort signal, results report the
|
|
3
|
+
* shared `Usage`. Adapters enforce provider batch caps with typed errors — they
|
|
4
|
+
* never silently auto-chunk; callers chunk (e.g. memory's `embedBatched`).
|
|
5
|
+
* ponytail: per-item token caps are server-enforced; the local cap is batch count. */
|
|
6
|
+
import type { ModelCapabilities, ModelConfig, Usage } from "./content.js";
|
|
7
|
+
export interface EmbeddingsRequest {
|
|
8
|
+
readonly model: string;
|
|
9
|
+
readonly inputs: readonly string[];
|
|
10
|
+
/** Output dimensions override; only for models that support reduced dimensions. */
|
|
11
|
+
readonly dimensions?: number;
|
|
12
|
+
readonly signal?: AbortSignal;
|
|
13
|
+
}
|
|
14
|
+
export interface EmbeddingsResult {
|
|
15
|
+
/** Vectors in input order; `vectors[i]` corresponds to `inputs[i]`. */
|
|
16
|
+
readonly vectors: readonly (readonly number[])[];
|
|
17
|
+
readonly usage: Usage;
|
|
18
|
+
readonly dimensions: number;
|
|
19
|
+
}
|
|
20
|
+
export interface EmbeddingsProvider {
|
|
21
|
+
readonly id: string;
|
|
22
|
+
embedMany(request: EmbeddingsRequest): Promise<EmbeddingsResult>;
|
|
23
|
+
}
|
|
24
|
+
export type EmbeddingsErrorCode = "empty_input" | "batch_too_large" | "request_failed" | "response_malformed" | "unsupported_model";
|
|
25
|
+
export declare class EmbeddingsError extends Error {
|
|
26
|
+
readonly code: EmbeddingsErrorCode;
|
|
27
|
+
constructor(code: EmbeddingsErrorCode, message: string);
|
|
28
|
+
}
|
|
29
|
+
export declare function modelSupportsEmbeddings(capabilities?: ModelCapabilities): boolean;
|
|
30
|
+
export declare function assertEmbeddingsSupported(model: ModelConfig): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class EmbeddingsError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
constructor(code, message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "EmbeddingsError";
|
|
6
|
+
this.code = code;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function modelSupportsEmbeddings(capabilities) {
|
|
10
|
+
return capabilities?.embeddings === true;
|
|
11
|
+
}
|
|
12
|
+
export function assertEmbeddingsSupported(model) {
|
|
13
|
+
if (!modelSupportsEmbeddings(model.capabilities)) {
|
|
14
|
+
throw new EmbeddingsError("unsupported_model", `Model ${model.provider}/${model.model} does not declare the embeddings capability`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=embeddings.js.map
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Provider-neutral image generation/editing contract (plan 061 Task 4).
|
|
2
|
+
* Generate (prompt→image[s]) and edit (image+mask+prompt) returning `Uint8Array`
|
|
3
|
+
* bytes plus provenance — hosts own persistence (no disk writes, no URL-only
|
|
4
|
+
* contract). Edit inputs reuse the existing `ImageContent` binary content parts.
|
|
5
|
+
* Adapters enforce prompt/content caps with typed errors — they never truncate. */
|
|
6
|
+
import type { ImageContent, ModelCapabilities, ModelConfig, Usage } from "./content.js";
|
|
7
|
+
export interface ImageGenerationRequest {
|
|
8
|
+
readonly model: string;
|
|
9
|
+
readonly prompt: string;
|
|
10
|
+
/** Pixel dimensions, e.g. `1024x1024` (provider-defined vocabulary). */
|
|
11
|
+
readonly size?: string;
|
|
12
|
+
/** Output container, e.g. `png`, `jpeg`, `webp`. */
|
|
13
|
+
readonly format?: string;
|
|
14
|
+
/** Provider-defined quality tier, e.g. `standard` | `hd`. */
|
|
15
|
+
readonly quality?: string;
|
|
16
|
+
/** Number of images to generate (within the provider cap). */
|
|
17
|
+
readonly count?: number;
|
|
18
|
+
readonly signal?: AbortSignal;
|
|
19
|
+
}
|
|
20
|
+
export interface ImageEditRequest {
|
|
21
|
+
readonly model: string;
|
|
22
|
+
readonly prompt: string;
|
|
23
|
+
/** Base image(s) as existing binary content parts (base64 `data` or `url`). */
|
|
24
|
+
readonly images: readonly ImageContent[];
|
|
25
|
+
/** Optional mask as an image content part (transparent areas mark edits). */
|
|
26
|
+
readonly mask?: ImageContent;
|
|
27
|
+
readonly size?: string;
|
|
28
|
+
readonly format?: string;
|
|
29
|
+
readonly count?: number;
|
|
30
|
+
readonly signal?: AbortSignal;
|
|
31
|
+
}
|
|
32
|
+
/** One generated image: bytes plus provenance. `provider`/`model` are preserved
|
|
33
|
+
* end-to-end so hosts can attribute stored output. */
|
|
34
|
+
export interface GeneratedImage {
|
|
35
|
+
readonly bytes: Uint8Array;
|
|
36
|
+
/** e.g. `image/png`. */
|
|
37
|
+
readonly mimeType: string;
|
|
38
|
+
readonly provider: string;
|
|
39
|
+
readonly model: string;
|
|
40
|
+
/** Provider-native URL passthrough, when the provider returns one. */
|
|
41
|
+
readonly url?: string;
|
|
42
|
+
/** Provider-revised prompt, when the provider returns one. */
|
|
43
|
+
readonly revisedPrompt?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface ImageGenerationResult {
|
|
46
|
+
readonly images: readonly GeneratedImage[];
|
|
47
|
+
readonly usage?: Usage;
|
|
48
|
+
}
|
|
49
|
+
export interface ImageGenerationProvider {
|
|
50
|
+
readonly id: string;
|
|
51
|
+
generate(request: ImageGenerationRequest): Promise<ImageGenerationResult>;
|
|
52
|
+
edit(request: ImageEditRequest): Promise<ImageGenerationResult>;
|
|
53
|
+
}
|
|
54
|
+
export type ImageGenerationErrorCode = "empty_input" | "input_too_large" | "unsupported_operation" | "request_failed" | "response_malformed" | "unsupported_model";
|
|
55
|
+
export declare class ImageGenerationError extends Error {
|
|
56
|
+
readonly code: ImageGenerationErrorCode;
|
|
57
|
+
constructor(code: ImageGenerationErrorCode, message: string);
|
|
58
|
+
}
|
|
59
|
+
export declare function modelSupportsImageGeneration(capabilities?: ModelCapabilities): boolean;
|
|
60
|
+
export declare function assertImageGenerationSupported(model: ModelConfig): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export class ImageGenerationError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
constructor(code, message) {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "ImageGenerationError";
|
|
6
|
+
this.code = code;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
export function modelSupportsImageGeneration(capabilities) {
|
|
10
|
+
return capabilities?.imageGeneration === true;
|
|
11
|
+
}
|
|
12
|
+
export function assertImageGenerationSupported(model) {
|
|
13
|
+
if (!modelSupportsImageGeneration(model.capabilities)) {
|
|
14
|
+
throw new ImageGenerationError("unsupported_model", `Model ${model.provider}/${model.model} does not declare the imageGeneration capability`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=images.js.map
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/** Provider-neutral moderation classification contract (plan 061 Task 6).
|
|
2
|
+
*
|
|
3
|
+
* Scores and flagged booleans are provider output — core bakes in no policy:
|
|
4
|
+
* thresholds, blocking, and routing stay host-owned (see docs/host-security.md).
|
|
5
|
+
* Category keys use the provider-neutral vocabulary below; raw provider
|
|
6
|
+
* categories that have no neutral mapping pass through untouched.
|
|
7
|
+
*/
|
|
8
|
+
import type { JsonObject, ModelCapabilities, ModelConfig } from "./content.js";
|
|
9
|
+
/** Provider-neutral category vocabulary (canonical names; adapters map their raw
|
|
10
|
+
* categories onto these — unknown raw categories pass through as-is). */
|
|
11
|
+
export declare const MODERATION_CATEGORIES: readonly ["harassment", "harassment/threatening", "hate", "hate/threatening", "illicit", "illicit/violent", "self-harm", "self-harm/instructions", "self-harm/intent", "sexual", "sexual/minors", "violence", "violence/graphic"];
|
|
12
|
+
export type ModerationCategory = (typeof MODERATION_CATEGORIES)[number];
|
|
13
|
+
export type ModerationErrorCode = "empty_input" | "input_too_large" | "unsupported_model" | "request_failed" | "response_malformed" | "unsupported_operation";
|
|
14
|
+
export declare class ModerationError extends Error {
|
|
15
|
+
readonly code: ModerationErrorCode;
|
|
16
|
+
constructor(code: ModerationErrorCode, message: string);
|
|
17
|
+
}
|
|
18
|
+
export declare function modelSupportsModeration(capabilities?: ModelCapabilities): boolean;
|
|
19
|
+
export declare function assertModerationSupported(model: ModelConfig): void;
|
|
20
|
+
export interface ModerationRequest {
|
|
21
|
+
/** One input per call, or a batch where the provider allows it (results match
|
|
22
|
+
* input arity and order). */
|
|
23
|
+
readonly input: string | readonly string[];
|
|
24
|
+
readonly model?: string;
|
|
25
|
+
readonly signal?: AbortSignal;
|
|
26
|
+
}
|
|
27
|
+
/** Per-category verdict: provider-reported score in [0,1] plus the provider's own
|
|
28
|
+
* flagged decision — never a locally recomputed threshold. */
|
|
29
|
+
export interface ModerationCategoryResult {
|
|
30
|
+
readonly score: number;
|
|
31
|
+
readonly flagged: boolean;
|
|
32
|
+
}
|
|
33
|
+
export interface ModerationResult {
|
|
34
|
+
/** True when the provider flagged any category for this input. */
|
|
35
|
+
readonly flagged: boolean;
|
|
36
|
+
/** Category verdicts keyed by provider-neutral name (unknown raw categories pass through). */
|
|
37
|
+
readonly categories: Readonly<Record<string, ModerationCategoryResult>>;
|
|
38
|
+
/** Provider-native category/score fields, unmodified, for host-side audits. */
|
|
39
|
+
readonly raw?: JsonObject;
|
|
40
|
+
readonly model?: string;
|
|
41
|
+
readonly id?: string;
|
|
42
|
+
}
|
|
43
|
+
export interface ModerationProvider {
|
|
44
|
+
readonly id: string;
|
|
45
|
+
moderate(request: ModerationRequest): Promise<ModerationResult | readonly ModerationResult[]>;
|
|
46
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Provider-neutral category vocabulary (canonical names; adapters map their raw
|
|
2
|
+
* categories onto these — unknown raw categories pass through as-is). */
|
|
3
|
+
export const MODERATION_CATEGORIES = [
|
|
4
|
+
"harassment",
|
|
5
|
+
"harassment/threatening",
|
|
6
|
+
"hate",
|
|
7
|
+
"hate/threatening",
|
|
8
|
+
"illicit",
|
|
9
|
+
"illicit/violent",
|
|
10
|
+
"self-harm",
|
|
11
|
+
"self-harm/instructions",
|
|
12
|
+
"self-harm/intent",
|
|
13
|
+
"sexual",
|
|
14
|
+
"sexual/minors",
|
|
15
|
+
"violence",
|
|
16
|
+
"violence/graphic",
|
|
17
|
+
];
|
|
18
|
+
export class ModerationError extends Error {
|
|
19
|
+
code;
|
|
20
|
+
constructor(code, message) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.name = "ModerationError";
|
|
23
|
+
this.code = code;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function modelSupportsModeration(capabilities) {
|
|
27
|
+
return capabilities?.moderation === true;
|
|
28
|
+
}
|
|
29
|
+
export function assertModerationSupported(model) {
|
|
30
|
+
if (!modelSupportsModeration(model.capabilities)) {
|
|
31
|
+
throw new ModerationError("unsupported_model", `Model ${model.provider}/${model.model} does not declare the moderation capability`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=moderation.js.map
|