@mcoda/codali 0.1.134 → 0.1.135-codali.4
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 +42 -0
- package/ORCHESTRATION.md +387 -0
- package/README.md +103 -1
- package/config/alternate-local.example.json +49 -0
- package/config/docdex-runtime.json +21 -0
- package/config/orchestration.schema.json +548 -0
- package/config/raijin-suku.example.json +172 -0
- package/config/terminal-long-scenarios.v1.json +70 -0
- package/dist/agents/RoleResolution.d.ts.map +1 -1
- package/dist/agents/RoleResolution.js +4 -4
- package/dist/api/CodaliApi.d.ts +16 -0
- package/dist/api/CodaliApi.d.ts.map +1 -1
- package/dist/api/CodaliApi.js +39 -10
- package/dist/cli/AskCommand.d.ts +3 -0
- package/dist/cli/AskCommand.d.ts.map +1 -1
- package/dist/cli/AskCommand.js +76 -13
- package/dist/cli/RunCommand.d.ts +4 -0
- package/dist/cli/RunCommand.d.ts.map +1 -1
- package/dist/cli/RunCommand.js +110 -24
- package/dist/cli/TerminalCommand.d.ts +35 -0
- package/dist/cli/TerminalCommand.d.ts.map +1 -0
- package/dist/cli/TerminalCommand.js +616 -0
- package/dist/cli/TerminalCredentials.d.ts +3 -0
- package/dist/cli/TerminalCredentials.d.ts.map +1 -0
- package/dist/cli/TerminalCredentials.js +89 -0
- package/dist/cli/TerminalInput.d.ts +24 -0
- package/dist/cli/TerminalInput.d.ts.map +1 -0
- package/dist/cli/TerminalInput.js +98 -0
- package/dist/cli/TerminalText.d.ts +10 -0
- package/dist/cli/TerminalText.d.ts.map +1 -0
- package/dist/cli/TerminalText.js +53 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +33 -4
- package/dist/cognitive/ConfiguredPipeline.d.ts +34 -0
- package/dist/cognitive/ConfiguredPipeline.d.ts.map +1 -0
- package/dist/cognitive/ConfiguredPipeline.js +50 -0
- package/dist/cognitive/ValidationRunner.d.ts +4 -0
- package/dist/cognitive/ValidationRunner.d.ts.map +1 -1
- package/dist/cognitive/ValidationRunner.js +18 -41
- package/dist/config/NodeOrchestration.d.ts +21 -0
- package/dist/config/NodeOrchestration.d.ts.map +1 -0
- package/dist/config/NodeOrchestration.js +54 -0
- package/dist/config/OrchestrationConfig.d.ts +100 -0
- package/dist/config/OrchestrationConfig.d.ts.map +1 -0
- package/dist/config/OrchestrationConfig.js +245 -0
- package/dist/connectors/mcp/McpClient.d.ts +3 -1
- package/dist/connectors/mcp/McpClient.d.ts.map +1 -1
- package/dist/connectors/mcp/McpClient.js +3 -2
- package/dist/connectors/mcp/McpServerRegistry.d.ts +2 -2
- package/dist/connectors/mcp/McpServerRegistry.d.ts.map +1 -1
- package/dist/connectors/mcp/McpServerRegistry.js +39 -16
- package/dist/connectors/mcp/McpToolAdapter.js +2 -2
- package/dist/connectors/media/ConfiguredMediaTools.d.ts +6 -0
- package/dist/connectors/media/ConfiguredMediaTools.d.ts.map +1 -0
- package/dist/connectors/media/ConfiguredMediaTools.js +41 -0
- package/dist/connectors/media/ImageGenerationTool.js +3 -3
- package/dist/connectors/media/MediaArtifactReceipt.d.ts +5 -0
- package/dist/connectors/media/MediaArtifactReceipt.d.ts.map +1 -0
- package/dist/connectors/media/MediaArtifactReceipt.js +65 -0
- package/dist/connectors/media/MediaJobStore.d.ts +68 -0
- package/dist/connectors/media/MediaJobStore.d.ts.map +1 -0
- package/dist/connectors/media/MediaJobStore.js +199 -0
- package/dist/connectors/media/MediaJobWorker.d.ts +2 -0
- package/dist/connectors/media/MediaJobWorker.d.ts.map +1 -0
- package/dist/connectors/media/MediaJobWorker.js +65 -0
- package/dist/connectors/media/RemoteMediaJob.d.ts +6 -0
- package/dist/connectors/media/RemoteMediaJob.d.ts.map +1 -0
- package/dist/connectors/media/RemoteMediaJob.js +80 -0
- package/dist/docdex/DocdexClient.d.ts +18 -1
- package/dist/docdex/DocdexClient.d.ts.map +1 -1
- package/dist/docdex/DocdexClient.js +135 -19
- package/dist/docdex/ManagedDocdex.d.ts +29 -0
- package/dist/docdex/ManagedDocdex.d.ts.map +1 -0
- package/dist/docdex/ManagedDocdex.js +215 -0
- package/dist/docdex/ManagedRuntime.d.ts +28 -0
- package/dist/docdex/ManagedRuntime.d.ts.map +1 -0
- package/dist/docdex/ManagedRuntime.js +212 -0
- package/dist/eval/EvaluationProcess.d.ts +13 -0
- package/dist/eval/EvaluationProcess.d.ts.map +1 -0
- package/dist/eval/EvaluationProcess.js +76 -0
- package/dist/eval/LongWorkflowJourney.d.ts +34 -0
- package/dist/eval/LongWorkflowJourney.d.ts.map +1 -0
- package/dist/eval/LongWorkflowJourney.js +243 -0
- package/dist/eval/PlanningCorpus.d.ts +45 -0
- package/dist/eval/PlanningCorpus.d.ts.map +1 -0
- package/dist/eval/PlanningCorpus.js +189 -0
- package/dist/eval/PlanningCorpusRunner.d.ts +13 -0
- package/dist/eval/PlanningCorpusRunner.d.ts.map +1 -0
- package/dist/eval/PlanningCorpusRunner.js +89 -0
- package/dist/eval/TerminalCorpusRunner.d.ts +36 -0
- package/dist/eval/TerminalCorpusRunner.d.ts.map +1 -0
- package/dist/eval/TerminalCorpusRunner.js +222 -0
- package/dist/eval/TerminalTaskCorpus.d.ts +26 -0
- package/dist/eval/TerminalTaskCorpus.d.ts.map +1 -0
- package/dist/eval/TerminalTaskCorpus.js +105 -0
- package/dist/eval/TerminalWorkflowCorpus.d.ts +11 -0
- package/dist/eval/TerminalWorkflowCorpus.d.ts.map +1 -0
- package/dist/eval/TerminalWorkflowCorpus.js +116 -0
- package/dist/eval/fixtures/TerminalRecoveryJourney.d.ts +4 -0
- package/dist/eval/fixtures/TerminalRecoveryJourney.d.ts.map +1 -0
- package/dist/eval/fixtures/TerminalRecoveryJourney.js +132 -0
- package/dist/gateway/CodaliGateway.d.ts +2 -0
- package/dist/gateway/CodaliGateway.d.ts.map +1 -1
- package/dist/gateway/CodaliGateway.js +11 -1
- package/dist/gateway/ConfiguredGateway.d.ts +23 -0
- package/dist/gateway/ConfiguredGateway.d.ts.map +1 -0
- package/dist/gateway/ConfiguredGateway.js +44 -0
- package/dist/gateway/GatewayTracer.d.ts +1 -1
- package/dist/gateway/GatewayTracer.d.ts.map +1 -1
- package/dist/gateway/GatewayTracer.js +2 -27
- package/dist/index.d.ts +23 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/permissions/PermissionGate.d.ts +44 -0
- package/dist/permissions/PermissionGate.d.ts.map +1 -0
- package/dist/permissions/PermissionGate.js +97 -0
- package/dist/providers/ConfiguredEmbeddings.d.ts +43 -0
- package/dist/providers/ConfiguredEmbeddings.d.ts.map +1 -0
- package/dist/providers/ConfiguredEmbeddings.js +87 -0
- package/dist/providers/ConfiguredModelScope.d.ts +69 -0
- package/dist/providers/ConfiguredModelScope.d.ts.map +1 -0
- package/dist/providers/ConfiguredModelScope.js +113 -0
- package/dist/providers/ConfiguredProvider.d.ts +79 -0
- package/dist/providers/ConfiguredProvider.d.ts.map +1 -0
- package/dist/providers/ConfiguredProvider.js +238 -0
- package/dist/providers/ModelServiceError.d.ts +10 -0
- package/dist/providers/ModelServiceError.d.ts.map +1 -0
- package/dist/providers/ModelServiceError.js +45 -0
- package/dist/providers/MswarmWorkerProvider.d.ts.map +1 -1
- package/dist/providers/MswarmWorkerProvider.js +4 -0
- package/dist/providers/OpenAiCompatibleProvider.d.ts.map +1 -1
- package/dist/providers/OpenAiCompatibleProvider.js +91 -50
- package/dist/providers/ProviderTypes.d.ts +12 -0
- package/dist/providers/ProviderTypes.d.ts.map +1 -1
- package/dist/runtime/CodaliJobRuntime.d.ts +6 -0
- package/dist/runtime/CodaliJobRuntime.d.ts.map +1 -1
- package/dist/runtime/CodaliJobRuntime.js +36 -1
- package/dist/runtime/CodaliRuntime.d.ts +28 -0
- package/dist/runtime/CodaliRuntime.d.ts.map +1 -1
- package/dist/runtime/CodaliRuntime.js +69 -1
- package/dist/runtime/CompletionReport.d.ts +5 -0
- package/dist/runtime/CompletionReport.d.ts.map +1 -0
- package/dist/runtime/CompletionReport.js +12 -0
- package/dist/runtime/ProgressTracker.d.ts +17 -0
- package/dist/runtime/ProgressTracker.d.ts.map +1 -0
- package/dist/runtime/ProgressTracker.js +27 -0
- package/dist/runtime/RequestedTestEvidence.d.ts +12 -0
- package/dist/runtime/RequestedTestEvidence.d.ts.map +1 -0
- package/dist/runtime/RequestedTestEvidence.js +16 -0
- package/dist/runtime/RequiredRetrieval.d.ts +13 -0
- package/dist/runtime/RequiredRetrieval.d.ts.map +1 -0
- package/dist/runtime/RequiredRetrieval.js +25 -0
- package/dist/runtime/ReviewSource.d.ts +6 -0
- package/dist/runtime/ReviewSource.d.ts.map +1 -0
- package/dist/runtime/ReviewSource.js +38 -0
- package/dist/runtime/Runner.d.ts +7 -0
- package/dist/runtime/Runner.d.ts.map +1 -1
- package/dist/runtime/Runner.js +215 -171
- package/dist/runtime/SecretRedaction.d.ts +11 -0
- package/dist/runtime/SecretRedaction.d.ts.map +1 -0
- package/dist/runtime/SecretRedaction.js +85 -0
- package/dist/runtime/SessionController.d.ts +148 -0
- package/dist/runtime/SessionController.d.ts.map +1 -0
- package/dist/runtime/SessionController.js +1357 -0
- package/dist/runtime/StructuralEvidence.d.ts +22 -0
- package/dist/runtime/StructuralEvidence.d.ts.map +1 -0
- package/dist/runtime/StructuralEvidence.js +87 -0
- package/dist/runtime/TaskReviewContext.d.ts +34 -0
- package/dist/runtime/TaskReviewContext.d.ts.map +1 -0
- package/dist/runtime/TaskReviewContext.js +34 -0
- package/dist/runtime/ValidationOutput.d.ts +5 -0
- package/dist/runtime/ValidationOutput.d.ts.map +1 -0
- package/dist/runtime/ValidationOutput.js +32 -0
- package/dist/runtime/VerificationCommand.d.ts +5 -0
- package/dist/runtime/VerificationCommand.d.ts.map +1 -0
- package/dist/runtime/VerificationCommand.js +76 -0
- package/dist/runtime/WorkStatusPage.d.ts +15 -0
- package/dist/runtime/WorkStatusPage.d.ts.map +1 -0
- package/dist/runtime/WorkStatusPage.js +58 -0
- package/dist/runtime/WorkspaceLedger.d.ts +13 -0
- package/dist/runtime/WorkspaceLedger.d.ts.map +1 -0
- package/dist/runtime/WorkspaceLedger.js +145 -0
- package/dist/runtime/WorkspaceLock.d.ts.map +1 -1
- package/dist/runtime/WorkspaceLock.js +20 -17
- package/dist/runtime/WorkspaceSnapshot.d.ts +13 -0
- package/dist/runtime/WorkspaceSnapshot.d.ts.map +1 -0
- package/dist/runtime/WorkspaceSnapshot.js +88 -0
- package/dist/session/AtomicState.d.ts +13 -0
- package/dist/session/AtomicState.d.ts.map +1 -0
- package/dist/session/AtomicState.js +123 -0
- package/dist/session/SessionStoragePath.d.ts +15 -0
- package/dist/session/SessionStoragePath.d.ts.map +1 -0
- package/dist/session/SessionStoragePath.js +89 -0
- package/dist/session/SessionStore.d.ts +9 -0
- package/dist/session/SessionStore.d.ts.map +1 -1
- package/dist/session/SessionStore.js +181 -47
- package/dist/session/WorkState.d.ts +23 -0
- package/dist/session/WorkState.d.ts.map +1 -0
- package/dist/session/WorkState.js +367 -0
- package/dist/session/WorkTypes.d.ts +94 -0
- package/dist/session/WorkTypes.d.ts.map +1 -0
- package/dist/session/WorkTypes.js +1 -0
- package/dist/tools/ToolRegistry.d.ts +2 -0
- package/dist/tools/ToolRegistry.d.ts.map +1 -1
- package/dist/tools/ToolRegistry.js +12 -2
- package/dist/tools/ToolTypes.d.ts +16 -0
- package/dist/tools/ToolTypes.d.ts.map +1 -1
- package/dist/tools/docdex/DocdexTools.d.ts +2 -0
- package/dist/tools/docdex/DocdexTools.d.ts.map +1 -1
- package/dist/tools/docdex/DocdexTools.js +17 -2
- package/dist/tools/filesystem/FileTools.d.ts.map +1 -1
- package/dist/tools/filesystem/FileTools.js +30 -10
- package/dist/tools/shell/AsyncProcess.d.ts +19 -0
- package/dist/tools/shell/AsyncProcess.d.ts.map +1 -0
- package/dist/tools/shell/AsyncProcess.js +94 -0
- package/dist/tools/shell/DarwinRuntimeLibraries.d.ts +13 -0
- package/dist/tools/shell/DarwinRuntimeLibraries.d.ts.map +1 -0
- package/dist/tools/shell/DarwinRuntimeLibraries.js +130 -0
- package/dist/tools/shell/HostToolchain.d.ts +19 -0
- package/dist/tools/shell/HostToolchain.d.ts.map +1 -0
- package/dist/tools/shell/HostToolchain.js +266 -0
- package/dist/tools/shell/IsolatedExecutor.d.ts +15 -0
- package/dist/tools/shell/IsolatedExecutor.d.ts.map +1 -0
- package/dist/tools/shell/IsolatedExecutor.js +138 -0
- package/dist/tools/shell/ShellTool.d.ts.map +1 -1
- package/dist/tools/shell/ShellTool.js +9 -29
- package/dist/tools/shell/ShellWorkingDirectory.d.ts +3 -0
- package/dist/tools/shell/ShellWorkingDirectory.d.ts.map +1 -0
- package/dist/tools/shell/ShellWorkingDirectory.js +30 -0
- package/package.json +27 -24
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { ToolExecutionError } from "../tools/ToolTypes.js";
|
|
3
|
+
const fileRead = new Set(["prepare_edit", "read_file", "list_directory", "list_files", "stat_path", "diff_summary", "search", "search_files", "search_text", "glob", "file_search"]);
|
|
4
|
+
const fileWrite = new Set(["write_file", "apply_patch", "apply_diff", "media_export_artifact"]);
|
|
5
|
+
const controlRead = new Set(["work_status", "work_refine", "work_plan", "work_claim", "work_release", "work_reopen", "work_checkpoint", "work_decision", "work_verify", "work_complete", "work_block"]);
|
|
6
|
+
const executionWork = new Set(["work_claim", "work_verify", "work_complete"]);
|
|
7
|
+
export const isExecutionWorkTool = (name) => executionWork.has(name);
|
|
8
|
+
const docdexReads = /^(docdex_(search|batch_search|rerank|open|files|tree|stats|symbols|ast|repo_inspect|impact_graph|impact_diagnostics|dag_export|memory_recall|get_profile|wakeup|diary_read|capabilities|conversation_search|conversation_read|conversation_list|kg_query))$/;
|
|
9
|
+
export const permissionKind = (tool) => {
|
|
10
|
+
if (tool.name === "run_shell")
|
|
11
|
+
return "shell";
|
|
12
|
+
if (fileWrite.has(tool.name))
|
|
13
|
+
return "write";
|
|
14
|
+
if (["tools_discover", "tools_enable"].includes(tool.name))
|
|
15
|
+
return "read";
|
|
16
|
+
if (["media_job_status", "media_job_wait", "delegate_helper"].includes(tool.name))
|
|
17
|
+
return "read";
|
|
18
|
+
if (tool.name === "media_job_cancel")
|
|
19
|
+
return "media";
|
|
20
|
+
if (/image.*generat|audio.*generat|video.*generat|media.*generat/.test(tool.name) || /^(image|audio|video|media)_generation$/.test(tool.capability))
|
|
21
|
+
return "media";
|
|
22
|
+
if (tool.name === "docdex_web_research")
|
|
23
|
+
return "web";
|
|
24
|
+
if (/^docdex_(memory_save|save_preference|index|diary_write|conversation_import|delegate)/.test(tool.name))
|
|
25
|
+
return "memory";
|
|
26
|
+
if ((fileRead.has(tool.name) || docdexReads.test(tool.name)) && tool.readOnly || controlRead.has(tool.name))
|
|
27
|
+
return "read";
|
|
28
|
+
return "external";
|
|
29
|
+
};
|
|
30
|
+
export class PermissionGate {
|
|
31
|
+
constructor(profile = "ask", prompt, options = {}) {
|
|
32
|
+
this.profile = profile;
|
|
33
|
+
this.prompt = prompt;
|
|
34
|
+
this.options = options;
|
|
35
|
+
this.grants = new Set();
|
|
36
|
+
this.denials = new Set();
|
|
37
|
+
this.revision = 1;
|
|
38
|
+
}
|
|
39
|
+
inspect() {
|
|
40
|
+
return { profile: this.profile, revision: this.revision, sessionGrants: this.grants.size, sessionDenials: this.denials.size, shellIsolated: this.options.shellIsolated === true, allowWeb: this.options.allowWeb === true, allowMemory: this.options.allowMemory === true, allowMedia: this.options.allowMedia === true, deniedTools: this.options.deniedTools ?? [] };
|
|
41
|
+
}
|
|
42
|
+
setProfile(profile) {
|
|
43
|
+
if (!["plan", "ask", "workspace"].includes(profile))
|
|
44
|
+
throw new Error("Unknown permission profile");
|
|
45
|
+
this.profile = profile;
|
|
46
|
+
this.revision += 1;
|
|
47
|
+
}
|
|
48
|
+
clearGrants() { this.grants.clear(); this.denials.clear(); this.revision += 1; }
|
|
49
|
+
exportGrants() { return { schemaVersion: 1, grants: [...this.grants], denials: [...this.denials] }; }
|
|
50
|
+
restoreGrants(value) {
|
|
51
|
+
if (value.schemaVersion !== 1 || !Array.isArray(value.grants) || !Array.isArray(value.denials) || [...value.grants, ...value.denials].some(key => typeof key !== "string" || !/^[a-f0-9]{64}$/.test(key)))
|
|
52
|
+
throw new Error("Invalid permission grant record");
|
|
53
|
+
this.grants = new Set(value.grants);
|
|
54
|
+
this.denials = new Set(value.denials);
|
|
55
|
+
this.revision += 1;
|
|
56
|
+
}
|
|
57
|
+
async authorize(tool, args, signal) {
|
|
58
|
+
signal?.throwIfAborted();
|
|
59
|
+
const kind = permissionKind(tool);
|
|
60
|
+
const key = createHash("sha256").update(JSON.stringify([tool.name, kind, args])).digest("hex");
|
|
61
|
+
const deny = (reason) => { throw new ToolExecutionError("tool_permission_denied", reason, { retryable: false, details: { tool: tool.name, kind } }); };
|
|
62
|
+
if (this.options.deniedTools?.includes(tool.name) || this.denials.has(key))
|
|
63
|
+
deny("Operation explicitly denied");
|
|
64
|
+
if (this.profile === "plan" && isExecutionWorkTool(tool.name))
|
|
65
|
+
deny("Planning mode cannot claim, verify or complete execution tasks; record the plan and leave the goal open");
|
|
66
|
+
if (kind === "read")
|
|
67
|
+
return;
|
|
68
|
+
if (this.profile === "plan")
|
|
69
|
+
deny("Planning mode permits read operations only");
|
|
70
|
+
if (kind === "web" && this.options.allowWeb)
|
|
71
|
+
return;
|
|
72
|
+
if (kind === "memory" && this.options.allowMemory)
|
|
73
|
+
return;
|
|
74
|
+
if (kind === "media" && this.options.allowMedia)
|
|
75
|
+
return;
|
|
76
|
+
if (kind === "shell" && !this.options.shellIsolated)
|
|
77
|
+
deny("An isolated shell executor is required; run codali doctor");
|
|
78
|
+
if (this.profile === "workspace" && (kind === "write" || kind === "shell"))
|
|
79
|
+
return;
|
|
80
|
+
if (this.grants.has(key))
|
|
81
|
+
return;
|
|
82
|
+
if (!this.prompt)
|
|
83
|
+
deny("Permission is required; interactive approval or an applicable grant is unavailable");
|
|
84
|
+
const revision = this.revision;
|
|
85
|
+
const answer = await this.prompt({ id: randomUUID(), tool: tool.name, kind, args, reason: `Allow ${kind} operation ${tool.name}?` }, signal);
|
|
86
|
+
signal?.throwIfAborted();
|
|
87
|
+
if (revision !== this.revision)
|
|
88
|
+
return this.authorize(tool, args, signal);
|
|
89
|
+
if (!answer.allow) {
|
|
90
|
+
if (answer.scope === "session")
|
|
91
|
+
this.denials.add(key);
|
|
92
|
+
deny("Operation denied by user");
|
|
93
|
+
}
|
|
94
|
+
if (answer.scope === "session")
|
|
95
|
+
this.grants.add(key);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ResolvedOrchestrationConfig } from "../config/OrchestrationConfig.js";
|
|
2
|
+
export interface EmbeddingReceipt {
|
|
3
|
+
id: string;
|
|
4
|
+
modelId: string;
|
|
5
|
+
catalogId: string;
|
|
6
|
+
spaceId: string;
|
|
7
|
+
configHash: string;
|
|
8
|
+
purpose: "query" | "document";
|
|
9
|
+
inputs: number;
|
|
10
|
+
reportedTokens?: number;
|
|
11
|
+
elapsedMs: number;
|
|
12
|
+
status: "succeeded" | "failed";
|
|
13
|
+
failureCode?: "aborted" | "request_failed" | "upstream_error" | "invalid_response";
|
|
14
|
+
}
|
|
15
|
+
export interface EmbeddingIntent {
|
|
16
|
+
id: string;
|
|
17
|
+
modelId: string;
|
|
18
|
+
catalogId: string;
|
|
19
|
+
spaceId: string;
|
|
20
|
+
inputs: number;
|
|
21
|
+
estimatedTokens: number;
|
|
22
|
+
}
|
|
23
|
+
/** Owns embedding identity; network retries after dispatch are deliberately left to the caller. */
|
|
24
|
+
export declare class ConfiguredEmbeddings {
|
|
25
|
+
readonly resolved: ResolvedOrchestrationConfig;
|
|
26
|
+
private readonly onReceipt?;
|
|
27
|
+
private readonly beforeRequest?;
|
|
28
|
+
readonly space: {
|
|
29
|
+
id: string;
|
|
30
|
+
queryPrefix: string;
|
|
31
|
+
documentPrefix: string;
|
|
32
|
+
normalization: "none" | "l2";
|
|
33
|
+
pooling: string;
|
|
34
|
+
revision: string;
|
|
35
|
+
dimensions: number;
|
|
36
|
+
label: string;
|
|
37
|
+
};
|
|
38
|
+
private readonly router;
|
|
39
|
+
constructor(resolved: ResolvedOrchestrationConfig, onReceipt?: ((receipt: EmbeddingReceipt) => Promise<void>) | undefined, beforeRequest?: ((intent: EmbeddingIntent) => Promise<void>) | undefined);
|
|
40
|
+
pin(directory: string): Promise<void>;
|
|
41
|
+
embed(input: string[], purpose: "query" | "document", signal?: AbortSignal): Promise<number[][]>;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=ConfiguredEmbeddings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfiguredEmbeddings.d.ts","sourceRoot":"","sources":["../../src/providers/ConfiguredEmbeddings.ts"],"names":[],"mappings":"AAIA,OAAO,EAA4B,KAAK,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAI9G,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IACpF,OAAO,EAAE,OAAO,GAAG,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAC1F,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC/B,WAAW,CAAC,EAAE,SAAS,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,kBAAkB,CAAC;CACpF;AACD,MAAM,WAAW,eAAe;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,eAAe,EAAE,MAAM,CAAC;CAAE;AAE9I,mGAAmG;AACnG,qBAAa,oBAAoB;IAGnB,QAAQ,CAAC,QAAQ,EAAE,2BAA2B;IAAE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC;IACrF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC;IAHjC,QAAQ,CAAC,KAAK;;;;;;;;;MAAC;IACf,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;gBACvB,QAAQ,EAAE,2BAA2B,EAAmB,SAAS,CAAC,GAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,aAAA,EAClH,aAAa,CAAC,GAAE,CAAC,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,aAAA;IAKvE,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYrC,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,GAAG,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;CAiDvG"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { validateEmbeddingRequest, validateEmbeddingResponse } from "@mcoda/shared";
|
|
5
|
+
import { configuredEmbeddingSpace } from "../config/OrchestrationConfig.js";
|
|
6
|
+
import { atomicWriteJson, withStateLock } from "../session/AtomicState.js";
|
|
7
|
+
import { ConfiguredProvider } from "./ConfiguredProvider.js";
|
|
8
|
+
/** Owns embedding identity; network retries after dispatch are deliberately left to the caller. */
|
|
9
|
+
export class ConfiguredEmbeddings {
|
|
10
|
+
constructor(resolved, onReceipt, beforeRequest) {
|
|
11
|
+
this.resolved = resolved;
|
|
12
|
+
this.onReceipt = onReceipt;
|
|
13
|
+
this.beforeRequest = beforeRequest;
|
|
14
|
+
this.space = configuredEmbeddingSpace(resolved.config);
|
|
15
|
+
this.router = new ConfiguredProvider(resolved, "embedding");
|
|
16
|
+
}
|
|
17
|
+
async pin(directory) {
|
|
18
|
+
const file = path.join(directory, "embedding-space.json");
|
|
19
|
+
await withStateLock(file, async () => {
|
|
20
|
+
try {
|
|
21
|
+
const previous = JSON.parse(await fs.readFile(file, "utf8"));
|
|
22
|
+
if (previous.schemaVersion !== 1 || previous.space?.id !== this.space.id)
|
|
23
|
+
throw new Error("Embedding space changed; rebuild into a separate index before using this configuration");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (error.code !== "ENOENT")
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
await atomicWriteJson(file, { schemaVersion: 1, space: this.space, createdAt: new Date().toISOString() });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
async embed(input, purpose, signal) {
|
|
34
|
+
const prefix = purpose === "query" ? this.space.queryPrefix : this.space.documentPrefix;
|
|
35
|
+
const prepared = validateEmbeddingRequest({ input: input.map(text => prefix + text) }, "pending");
|
|
36
|
+
const selected = await this.router.select("embeddings", signal);
|
|
37
|
+
const descriptor = Array.isArray(selected.actual.raw.operations)
|
|
38
|
+
? selected.actual.raw.operations.find(value => value && typeof value === "object" && value.type === "embeddings") : undefined;
|
|
39
|
+
if (selected.provider.adapter === "mswarm" && (!descriptor || descriptor.limits?.embedding_dimensions !== this.space.dimensions)) {
|
|
40
|
+
throw new Error("Embedding catalog does not attest the configured dimensions");
|
|
41
|
+
}
|
|
42
|
+
if (selected.provider.adapter === "mswarm" && selected.actual.raw.digest !== this.space.revision)
|
|
43
|
+
throw new Error("Embedding catalog revision does not match the pinned artifact");
|
|
44
|
+
const started = Date.now();
|
|
45
|
+
const id = randomUUID();
|
|
46
|
+
await this.beforeRequest?.({ id, modelId: selected.id, catalogId: selected.model.catalogId, spaceId: this.space.id,
|
|
47
|
+
inputs: input.length, estimatedTokens: Math.ceil(JSON.stringify(prepared.input).length / 3) });
|
|
48
|
+
const receipt = { id, modelId: selected.id, catalogId: selected.model.catalogId,
|
|
49
|
+
spaceId: this.space.id, configHash: this.resolved.hash, purpose, inputs: input.length };
|
|
50
|
+
let failureCode = "request_failed";
|
|
51
|
+
let vectors;
|
|
52
|
+
let reportedTokens;
|
|
53
|
+
try {
|
|
54
|
+
const payload = await this.router.client(selected.model.provider).json(`${selected.provider.baseUrl.replace(/\/$/, "")}/embeddings`, {
|
|
55
|
+
method: "POST", body: { ...prepared, model: selected.model.catalogId }, signal, timeoutMs: 120000,
|
|
56
|
+
});
|
|
57
|
+
// A relay may start a 200 keepalive before native execution fails.
|
|
58
|
+
// Do not expose upstream messages, which can contain private input.
|
|
59
|
+
if (payload && typeof payload === "object" && "error" in payload) {
|
|
60
|
+
failureCode = "upstream_error";
|
|
61
|
+
throw new Error("Embedding upstream execution failed");
|
|
62
|
+
}
|
|
63
|
+
failureCode = "invalid_response";
|
|
64
|
+
const result = validateEmbeddingResponse(payload, input.length, this.space.dimensions, selected.model.catalogId);
|
|
65
|
+
if (selected.provider.adapter === "mswarm" && payload.embedding_revision !== this.space.revision)
|
|
66
|
+
throw new Error("Embedding response revision changed after selection");
|
|
67
|
+
vectors = result.data.map(item => {
|
|
68
|
+
if (this.space.normalization === "none")
|
|
69
|
+
return item.embedding;
|
|
70
|
+
const scale = Math.max(...item.embedding.map(Math.abs));
|
|
71
|
+
if (!scale)
|
|
72
|
+
throw new Error("Embedding model returned a zero vector");
|
|
73
|
+
const norm = Math.sqrt(item.embedding.reduce((sum, value) => sum + (value / scale) ** 2, 0));
|
|
74
|
+
return item.embedding.map(value => value / scale / norm);
|
|
75
|
+
});
|
|
76
|
+
reportedTokens = result.usage?.total_tokens;
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
await this.onReceipt?.({ ...receipt, status: "failed", failureCode: signal?.aborted ? "aborted" : failureCode,
|
|
80
|
+
elapsedMs: Date.now() - started });
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
await this.onReceipt?.({ ...receipt, status: "succeeded",
|
|
84
|
+
...(reportedTokens !== undefined ? { reportedTokens } : {}), elapsedMs: Date.now() - started });
|
|
85
|
+
return vectors;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type EffortLevel, type ResolvedOrchestrationConfig } from "../config/OrchestrationConfig.js";
|
|
2
|
+
import { type ModelCallerContext, type ModelInvocation } from "./ConfiguredProvider.js";
|
|
3
|
+
import type { Provider, ProviderUsage } from "./ProviderTypes.js";
|
|
4
|
+
export interface ScopedModelUsage {
|
|
5
|
+
modelCalls: number;
|
|
6
|
+
inputTokens: number;
|
|
7
|
+
outputTokens: number;
|
|
8
|
+
totalTokens: number;
|
|
9
|
+
estimated: boolean;
|
|
10
|
+
pendingCalls: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ScopedModelEvent {
|
|
13
|
+
type: "intent" | "receipt";
|
|
14
|
+
id: string;
|
|
15
|
+
binding: string;
|
|
16
|
+
configHash: string;
|
|
17
|
+
route?: ModelInvocation;
|
|
18
|
+
status: "pending" | "success" | "failed";
|
|
19
|
+
usage: ScopedModelUsage;
|
|
20
|
+
}
|
|
21
|
+
/** Invalid upstream accounting cannot lower a shared budget or turn it into NaN. */
|
|
22
|
+
export declare const verifiedTokenUsage: (usage?: ProviderUsage) => {
|
|
23
|
+
input?: number;
|
|
24
|
+
output?: number;
|
|
25
|
+
total: number;
|
|
26
|
+
} | undefined;
|
|
27
|
+
/** One model budget/deadline for one embedded gateway or pipeline invocation. */
|
|
28
|
+
export declare class ConfiguredModelScope {
|
|
29
|
+
private readonly options;
|
|
30
|
+
private readonly resolved;
|
|
31
|
+
private readonly controller;
|
|
32
|
+
private readonly timer;
|
|
33
|
+
private readonly limits;
|
|
34
|
+
private readonly stop;
|
|
35
|
+
private readonly pending;
|
|
36
|
+
private toolCalls;
|
|
37
|
+
private readonly usage;
|
|
38
|
+
readonly id: `${string}-${string}-${string}-${string}-${string}`;
|
|
39
|
+
constructor(resolved: ResolvedOrchestrationConfig, options?: {
|
|
40
|
+
effort?: EffortLevel;
|
|
41
|
+
signal?: AbortSignal;
|
|
42
|
+
caller?: ModelCallerContext;
|
|
43
|
+
onEvent?: (event: ScopedModelEvent) => Promise<void> | void;
|
|
44
|
+
credentials?: Readonly<Record<string, string>>;
|
|
45
|
+
});
|
|
46
|
+
get signal(): AbortSignal;
|
|
47
|
+
get configHash(): string;
|
|
48
|
+
get effort(): EffortLevel;
|
|
49
|
+
matchesCaller(caller: ModelCallerContext): boolean;
|
|
50
|
+
budget(): {
|
|
51
|
+
maxSteps: number;
|
|
52
|
+
maxToolCalls: number;
|
|
53
|
+
maxModelCalls: number;
|
|
54
|
+
maxTotalTokens: number;
|
|
55
|
+
maxOutputTokens: number;
|
|
56
|
+
timeoutMs: number;
|
|
57
|
+
};
|
|
58
|
+
get toolsUsed(): number;
|
|
59
|
+
reserveTool(): void;
|
|
60
|
+
models(binding: string): {
|
|
61
|
+
id: string;
|
|
62
|
+
model: import("../config/OrchestrationConfig.js").OrchestrationModel;
|
|
63
|
+
}[];
|
|
64
|
+
snapshot(): ScopedModelUsage;
|
|
65
|
+
close(): void;
|
|
66
|
+
provider(binding: string): Provider;
|
|
67
|
+
private generate;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=ConfiguredModelScope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfiguredModelScope.d.ts","sourceRoot":"","sources":["../../src/providers/ConfiguredModelScope.ts"],"names":[],"mappings":"AACA,OAAO,EAAwD,KAAK,WAAW,EAAE,KAAK,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAC5J,OAAO,EAA4C,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAClI,OAAO,KAAK,EAAE,QAAQ,EAAqC,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAErG,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IACnF,SAAS,EAAE,OAAO,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;CAC1C;AACD,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;IACzC,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,GAAI,QAAQ,aAAa,KAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAQ/G,CAAC;AAEF,iFAAiF;AACjF,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2L;IACnN,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA8B;IACvD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyB;IACpD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;IACxB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAa;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,SAAS,CAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA2H;IACjJ,QAAQ,CAAC,EAAE,sDAAgB;gBAEf,QAAQ,EAAE,2BAA2B,EAAE,OAAO,GAAE;QAC1D,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,MAAM,CAAC,EAAE,kBAAkB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACrI,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;KAC3C;IAWN,IAAI,MAAM,IAAI,WAAW,CAAmC;IAC5D,IAAI,UAAU,IAAI,MAAM,CAA+B;IACvD,IAAI,MAAM,IAAI,WAAW,CAA4C;IACrE,aAAa,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO;IAClD,MAAM;;;;;;;;IACN,IAAI,SAAS,IAAI,MAAM,CAA2B;IAClD,WAAW,IAAI,IAAI;IASnB,MAAM,CAAC,OAAO,EAAE,MAAM;;;;IACtB,QAAQ,IAAI,gBAAgB;IAC5B,KAAK,IAAI,IAAI;IAEb,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ;YAKrB,QAAQ;CA2CvB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { effortBudget, pinOrchestrationConfig, resolveBinding } from "../config/OrchestrationConfig.js";
|
|
3
|
+
import { ConfiguredProvider, normalizeModelCaller } from "./ConfiguredProvider.js";
|
|
4
|
+
/** Invalid upstream accounting cannot lower a shared budget or turn it into NaN. */
|
|
5
|
+
export const verifiedTokenUsage = (usage) => {
|
|
6
|
+
const valid = (value) => Number.isSafeInteger(value) && value >= 0;
|
|
7
|
+
if (!usage)
|
|
8
|
+
return undefined;
|
|
9
|
+
for (const value of [usage.inputTokens, usage.outputTokens, usage.totalTokens])
|
|
10
|
+
if (value !== undefined && !valid(value))
|
|
11
|
+
return undefined;
|
|
12
|
+
const sum = usage.inputTokens !== undefined && usage.outputTokens !== undefined ? usage.inputTokens + usage.outputTokens : undefined;
|
|
13
|
+
const total = usage.totalTokens ?? sum;
|
|
14
|
+
if (!valid(total) || total < (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0))
|
|
15
|
+
return undefined;
|
|
16
|
+
return { input: usage.inputTokens, output: usage.outputTokens, total };
|
|
17
|
+
};
|
|
18
|
+
/** One model budget/deadline for one embedded gateway or pipeline invocation. */
|
|
19
|
+
export class ConfiguredModelScope {
|
|
20
|
+
constructor(resolved, options = {}) {
|
|
21
|
+
this.controller = new AbortController();
|
|
22
|
+
this.pending = new Map();
|
|
23
|
+
this.toolCalls = 0;
|
|
24
|
+
this.usage = { modelCalls: 0, inputTokens: 0, outputTokens: 0, totalTokens: 0, estimated: false, pendingCalls: 0 };
|
|
25
|
+
this.id = randomUUID();
|
|
26
|
+
this.options = { ...options, caller: normalizeModelCaller(options.caller), credentials: Object.freeze(Object.assign(Object.create(null), options.credentials)) };
|
|
27
|
+
this.resolved = pinOrchestrationConfig(resolved);
|
|
28
|
+
this.limits = effortBudget(this.resolved.config, options.effort ?? "medium");
|
|
29
|
+
this.stop = () => this.controller.abort(this.options.signal?.reason ?? new Error("Model scope cancelled"));
|
|
30
|
+
options.signal?.addEventListener("abort", this.stop, { once: true });
|
|
31
|
+
if (options.signal?.aborted)
|
|
32
|
+
this.stop();
|
|
33
|
+
this.timer = setTimeout(() => this.controller.abort(new Error("Shared model deadline exceeded")), this.limits.timeoutMs);
|
|
34
|
+
this.timer.unref();
|
|
35
|
+
}
|
|
36
|
+
get signal() { return this.controller.signal; }
|
|
37
|
+
get configHash() { return this.resolved.hash; }
|
|
38
|
+
get effort() { return this.options.effort ?? "medium"; }
|
|
39
|
+
matchesCaller(caller) { return JSON.stringify(normalizeModelCaller(caller)) === JSON.stringify(this.options.caller); }
|
|
40
|
+
budget() { return { ...this.limits }; }
|
|
41
|
+
get toolsUsed() { return this.toolCalls; }
|
|
42
|
+
reserveTool() {
|
|
43
|
+
this.signal.throwIfAborted();
|
|
44
|
+
if (this.toolCalls >= this.limits.maxToolCalls) {
|
|
45
|
+
const error = new Error("Shared orchestration tool budget exhausted");
|
|
46
|
+
this.controller.abort(error);
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
this.toolCalls++;
|
|
50
|
+
}
|
|
51
|
+
models(binding) { return structuredClone(resolveBinding(this.resolved.config, binding, "chat.completions")); }
|
|
52
|
+
snapshot() { return { ...this.usage, pendingCalls: this.pending.size, estimated: this.usage.estimated || this.pending.size > 0 }; }
|
|
53
|
+
close() { clearTimeout(this.timer); this.options.signal?.removeEventListener("abort", this.stop); this.controller.abort(new Error("Model scope closed")); }
|
|
54
|
+
provider(binding) {
|
|
55
|
+
resolveBinding(this.resolved.config, binding, "chat.completions");
|
|
56
|
+
return { name: `configured:${binding}`, supportsToolCalls: true, generate: request => this.generate(binding, request) };
|
|
57
|
+
}
|
|
58
|
+
async generate(binding, request) {
|
|
59
|
+
this.signal.throwIfAborted();
|
|
60
|
+
request.signal?.throwIfAborted();
|
|
61
|
+
const linked = new AbortController();
|
|
62
|
+
const stopScope = () => linked.abort(this.signal.reason);
|
|
63
|
+
const stopRequest = () => linked.abort(request.signal?.reason);
|
|
64
|
+
this.signal.addEventListener("abort", stopScope, { once: true });
|
|
65
|
+
request.signal?.addEventListener("abort", stopRequest, { once: true });
|
|
66
|
+
let invocation;
|
|
67
|
+
const provider = new ConfiguredProvider(this.resolved, binding, {
|
|
68
|
+
caller: this.options.caller,
|
|
69
|
+
credentials: this.options.credentials,
|
|
70
|
+
effort: this.options.effort,
|
|
71
|
+
beforeRequest: async (route, bounded) => {
|
|
72
|
+
linked.signal.throwIfAborted();
|
|
73
|
+
const reservation = Math.ceil(JSON.stringify([bounded.messages, bounded.tools]).length / 3) + (bounded.maxTokens ?? this.limits.maxOutputTokens);
|
|
74
|
+
if (this.usage.modelCalls >= this.limits.maxModelCalls || this.usage.totalTokens + reservation > this.limits.maxTotalTokens)
|
|
75
|
+
throw new Error("Shared model budget exhausted");
|
|
76
|
+
invocation = route;
|
|
77
|
+
this.usage.modelCalls++;
|
|
78
|
+
this.usage.totalTokens += reservation;
|
|
79
|
+
this.pending.set(route.id, reservation);
|
|
80
|
+
await this.options.onEvent?.({ type: "intent", id: route.id, binding, configHash: this.resolved.hash, route, status: "pending", usage: this.snapshot() });
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
try {
|
|
84
|
+
const response = await provider.generate({ ...request, signal: linked.signal, maxTokens: Math.min(request.maxTokens ?? this.limits.maxOutputTokens, this.limits.maxOutputTokens) });
|
|
85
|
+
linked.signal.throwIfAborted();
|
|
86
|
+
if (!invocation)
|
|
87
|
+
throw new Error("Configured provider did not reserve its invocation");
|
|
88
|
+
const reported = verifiedTokenUsage(response.usage);
|
|
89
|
+
if (reported) {
|
|
90
|
+
this.usage.totalTokens += reported.total - this.pending.get(invocation.id);
|
|
91
|
+
this.usage.inputTokens += reported.input ?? 0;
|
|
92
|
+
this.usage.outputTokens += reported.output ?? 0;
|
|
93
|
+
}
|
|
94
|
+
else
|
|
95
|
+
this.usage.estimated = true;
|
|
96
|
+
this.pending.delete(invocation.id);
|
|
97
|
+
await this.options.onEvent?.({ type: "receipt", id: invocation.id, binding, configHash: this.resolved.hash, route: invocation, status: "success", usage: this.snapshot() });
|
|
98
|
+
return response;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
// A submitted request is never replayed; an unknown bill keeps its reservation.
|
|
102
|
+
if (invocation && this.pending.has(invocation.id)) {
|
|
103
|
+
this.usage.estimated = true;
|
|
104
|
+
await this.options.onEvent?.({ type: "receipt", id: invocation.id, binding, configHash: this.resolved.hash, route: invocation, status: "failed", usage: this.snapshot() });
|
|
105
|
+
}
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
finally {
|
|
109
|
+
this.signal.removeEventListener("abort", stopScope);
|
|
110
|
+
request.signal?.removeEventListener("abort", stopRequest);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type OrchestrationProvider, type ResolvedOrchestrationConfig, type ModelOperation, type EffortLevel } from "../config/OrchestrationConfig.js";
|
|
2
|
+
import type { Provider, ProviderRequest, ProviderResponse } from "./ProviderTypes.js";
|
|
3
|
+
export interface CatalogEntry {
|
|
4
|
+
id: string;
|
|
5
|
+
aliases: string[];
|
|
6
|
+
backend?: string;
|
|
7
|
+
health: string;
|
|
8
|
+
supportsTools: boolean;
|
|
9
|
+
contextWindow?: number;
|
|
10
|
+
operations: string[];
|
|
11
|
+
raw: Record<string, unknown>;
|
|
12
|
+
}
|
|
13
|
+
/** Authenticated host context, separate from user/model supplied request bodies. */
|
|
14
|
+
export interface ModelCallerContext {
|
|
15
|
+
clientIdentity?: string;
|
|
16
|
+
clientProduct?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const normalizeModelCaller: (caller?: ModelCallerContext) => ModelCallerContext;
|
|
19
|
+
/** Discovery failed before inference; a caller may release its local token reservation. */
|
|
20
|
+
export declare class NativeReasoningTransportError extends Error {
|
|
21
|
+
constructor(message: string);
|
|
22
|
+
}
|
|
23
|
+
export declare const providerCredential: (provider: OrchestrationProvider) => Promise<string | undefined>;
|
|
24
|
+
export declare class ModelServiceClient {
|
|
25
|
+
readonly provider: OrchestrationProvider;
|
|
26
|
+
private readonly credentialOverride?;
|
|
27
|
+
private cache?;
|
|
28
|
+
private readonly caller;
|
|
29
|
+
constructor(provider: OrchestrationProvider, credentialOverride?: string | undefined, caller?: ModelCallerContext);
|
|
30
|
+
private credential;
|
|
31
|
+
json(url: string, options?: {
|
|
32
|
+
signal?: AbortSignal;
|
|
33
|
+
method?: string;
|
|
34
|
+
body?: unknown;
|
|
35
|
+
timeoutMs?: number;
|
|
36
|
+
}): Promise<unknown>;
|
|
37
|
+
catalog(signal?: AbortSignal, refresh?: boolean): Promise<CatalogEntry[]>;
|
|
38
|
+
usage(signal?: AbortSignal): Promise<unknown>;
|
|
39
|
+
/** The proxy and selected node must both advertise this transport contract.
|
|
40
|
+
* A model's supports_reasoning flag alone says nothing about request forwarding. */
|
|
41
|
+
requireNativeReasoning(modelId: string, parameters: string[], signal?: AbortSignal): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
export interface ModelInvocation {
|
|
44
|
+
id: string;
|
|
45
|
+
binding: string;
|
|
46
|
+
configHash: string;
|
|
47
|
+
modelId: string;
|
|
48
|
+
catalogId: string;
|
|
49
|
+
backend?: string;
|
|
50
|
+
host?: string;
|
|
51
|
+
nativeReasoningRequest?: Record<string, unknown>;
|
|
52
|
+
}
|
|
53
|
+
export declare class ConfiguredProvider implements Provider {
|
|
54
|
+
readonly resolved: ResolvedOrchestrationConfig;
|
|
55
|
+
readonly binding: string;
|
|
56
|
+
private readonly options;
|
|
57
|
+
readonly name = "configured";
|
|
58
|
+
readonly supportsToolCalls = true;
|
|
59
|
+
private clients;
|
|
60
|
+
private readonly caller;
|
|
61
|
+
private readonly credentials;
|
|
62
|
+
constructor(resolved: ResolvedOrchestrationConfig, binding?: string, options?: {
|
|
63
|
+
caller?: ModelCallerContext;
|
|
64
|
+
/** Trusted host credential resolution; never accepted from a request/config document. */
|
|
65
|
+
credentials?: Readonly<Record<string, string>>;
|
|
66
|
+
effort?: EffortLevel;
|
|
67
|
+
beforeRequest?: (invocation: ModelInvocation, request: ProviderRequest) => Promise<void>;
|
|
68
|
+
afterRequest?: (invocation: ModelInvocation, response: ProviderResponse) => Promise<void>;
|
|
69
|
+
});
|
|
70
|
+
client(providerId: string): ModelServiceClient;
|
|
71
|
+
select(operation: ModelOperation, signal?: AbortSignal, requireTools?: boolean): Promise<{
|
|
72
|
+
id: string;
|
|
73
|
+
model: import("../config/OrchestrationConfig.js").OrchestrationModel;
|
|
74
|
+
actual: CatalogEntry;
|
|
75
|
+
provider: OrchestrationProvider;
|
|
76
|
+
}>;
|
|
77
|
+
generate(request: ProviderRequest): Promise<ProviderResponse>;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=ConfiguredProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfiguredProvider.d.ts","sourceRoot":"","sources":["../../src/providers/ConfiguredProvider.ts"],"names":[],"mappings":"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"}
|