@nylorun/runtime 0.25.0-beta → 0.27.0-beta
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 +169 -0
- package/README.md +26 -16
- package/dist/adapters/execution/restate.d.ts +15 -18
- package/dist/adapters/execution/restate.js +31 -27
- package/dist/adapters/replication/pgoutput.d.ts +1 -1
- package/dist/adapters/replication/pgoutput.js +3 -2
- package/dist/adapters/sandbox/local.js +8 -5
- package/dist/adapters/sandbox/virtual.js +2 -2
- package/dist/adapters/streams/s2.d.ts +1 -1
- package/dist/adapters/streams/s2.js +18 -14
- package/dist/api/a2a/card.js +1 -1
- package/dist/api/a2a/endpoint.js +3 -4
- package/dist/api/a2a/protocol.js +4 -0
- package/dist/api/a2a/routes.d.ts +2 -6
- package/dist/api/a2a/routes.js +12 -18
- package/dist/api/ag-ui/endpoint.js +2 -3
- package/dist/api/ag-ui/routes.js +4 -4
- package/dist/api/components.d.ts +326 -45
- package/dist/api/components.js +5 -1
- package/dist/api/gate/keys.js +7 -4
- package/dist/api/gate/routes.d.ts +6 -2
- package/dist/api/gate/routes.js +15 -11
- package/dist/api/http/app.d.ts +2 -2
- package/dist/api/http/app.js +2 -2
- package/dist/api/http/body.d.ts +15 -3
- package/dist/api/http/body.js +15 -7
- package/dist/api/http/define.d.ts +1 -1
- package/dist/api/http/respond.js +7 -3
- package/dist/api/http/routes/access.js +5 -4
- package/dist/api/http/routes/artifacts.js +19 -7
- package/dist/api/http/routes/coverage.js +1 -1
- package/dist/api/http/routes/environment-manifests.js +1 -1
- package/dist/api/http/routes/environments.js +6 -6
- package/dist/api/http/routes/files.d.ts +2 -1
- package/dist/api/http/routes/files.js +31 -5
- package/dist/api/http/routes/mcp.js +1 -1
- package/dist/api/http/routes/reads.d.ts +35 -0
- package/dist/api/http/routes/reads.js +50 -22
- package/dist/api/http/routes/sessions.js +12 -11
- package/dist/api/http/routes/tenant.d.ts +2 -2
- package/dist/api/http/routes/tenant.js +69 -16
- package/dist/api/inbound-files.d.ts +3 -9
- package/dist/api/inbound-files.js +18 -24
- package/dist/api/openapi.js +6 -2
- package/dist/artifacts/disk.d.ts +0 -4
- package/dist/artifacts/disk.js +77 -73
- package/dist/artifacts/files.d.ts +13 -4
- package/dist/artifacts/files.js +27 -9
- package/dist/artifacts/folder-upload.d.ts +75 -0
- package/dist/artifacts/folder-upload.js +263 -0
- package/dist/artifacts/folders.d.ts +14 -8
- package/dist/artifacts/folders.js +19 -11
- package/dist/artifacts/links.js +7 -6
- package/dist/artifacts/parts.d.ts +9 -14
- package/dist/artifacts/parts.js +11 -9
- package/dist/artifacts/pipe.d.ts +15 -0
- package/dist/artifacts/pipe.js +71 -0
- package/dist/artifacts/quota.d.ts +36 -0
- package/dist/artifacts/quota.js +44 -0
- package/dist/artifacts/service.d.ts +25 -1
- package/dist/artifacts/service.js +70 -25
- package/dist/blob/fs.js +2 -1
- package/dist/blob/s3.d.ts +6 -2
- package/dist/blob/s3.js +9 -7
- package/dist/blob/types.d.ts +1 -1
- package/dist/blob/types.js +1 -1
- package/dist/core/limits.d.ts +11 -35
- package/dist/core/limits.js +5 -73
- package/dist/core/sandbox-routes.js +0 -1
- package/dist/core/turn-manifest.d.ts +1 -2
- package/dist/core/turn-manifest.js +4 -28
- package/dist/execution/memory.d.ts +8 -5
- package/dist/execution/memory.js +8 -6
- package/dist/execution/types.d.ts +1 -6
- package/dist/execution/types.js +0 -5
- package/dist/gates/contract.d.ts +3 -2
- package/dist/gates/contract.js +1 -1
- package/dist/gates/egress-credentials.js +4 -3
- package/dist/gates/egress.d.ts +9 -9
- package/dist/gates/egress.js +19 -19
- package/dist/gates/fixture-model.js +13 -2
- package/dist/gates/handler.d.ts +1 -3
- package/dist/gates/handler.js +4 -3
- package/dist/gates/http-client.d.ts +4 -3
- package/dist/gates/http-client.js +5 -7
- package/dist/gates/http-tool.d.ts +24 -4
- package/dist/gates/http-tool.js +53 -17
- package/dist/gates/in-process.d.ts +2 -1
- package/dist/gates/in-process.js +17 -9
- package/dist/gates/inflight.d.ts +2 -2
- package/dist/gates/inflight.js +3 -2
- package/dist/gates/journal.js +5 -7
- package/dist/gates/mcp-handler.d.ts +4 -3
- package/dist/gates/mcp-handler.js +15 -5
- package/dist/gates/model-gate.d.ts +11 -2
- package/dist/gates/policy.d.ts +28 -5
- package/dist/gates/policy.js +60 -17
- package/dist/gates/provider-gate.d.ts +22 -0
- package/dist/gates/provider-gate.js +30 -0
- package/dist/gates/tool-calls.d.ts +1 -3
- package/dist/gates/tool-calls.js +2 -3
- package/dist/gates/tool-client.d.ts +1 -1
- package/dist/gates/tool-client.js +5 -6
- package/dist/gates/tool-contract.d.ts +8 -5
- package/dist/gates/tool-contract.js +1 -1
- package/dist/gates/tool-gate.d.ts +18 -7
- package/dist/gates/tool-gate.js +49 -7
- package/dist/harness/calls.d.ts +27 -25
- package/dist/harness/calls.js +40 -46
- package/dist/harness/executors.d.ts +10 -3
- package/dist/harness/executors.js +53 -23
- package/dist/harness/main.js +2 -2
- package/dist/harness/pod.d.ts +0 -2
- package/dist/harness/pod.js +7 -6
- package/dist/harness/run-tokens.d.ts +4 -1
- package/dist/harness/run-tokens.js +6 -2
- package/dist/harness/service.d.ts +17 -14
- package/dist/harness/service.js +21 -35
- package/dist/harness/setup.d.ts +0 -2
- package/dist/harness/setup.js +4 -9
- package/dist/harness/ws-client.d.ts +2 -2
- package/dist/harness/ws-client.js +7 -5
- package/dist/harness/ws-port.d.ts +3 -4
- package/dist/harness/ws-port.js +3 -4
- package/dist/harness-api/artifacts.d.ts +20 -0
- package/dist/harness-api/artifacts.js +478 -0
- package/dist/harness-api/in-process.d.ts +2 -2
- package/dist/harness-api/in-process.js +18 -16
- package/dist/harness-api/record.d.ts +10 -9
- package/dist/harness-api/record.js +102 -157
- package/dist/harness-api/renew.d.ts +1 -1
- package/dist/harness-api/renew.js +2 -2
- package/dist/harness-api/server.d.ts +1 -16
- package/dist/harness-api/server.js +82 -73
- package/dist/harness-api/start.d.ts +20 -2
- package/dist/harness-api/start.js +57 -18
- package/dist/harness-api/tool-journal.d.ts +15 -10
- package/dist/harness-api/tool-journal.js +26 -24
- package/dist/harness-api/workspace.d.ts +0 -4
- package/dist/harness-api/workspace.js +2 -45
- package/dist/harness-api/ws-server.js +10 -10
- package/dist/host/create-host.js +2 -3
- package/dist/host/execution.js +2 -3
- package/dist/host/gates.d.ts +2 -9
- package/dist/host/gates.js +15 -12
- package/dist/host/http.d.ts +0 -2
- package/dist/host/http.js +0 -27
- package/dist/host/main.js +10 -3
- package/dist/host/operate.js +12 -3
- package/dist/host/stack-config.d.ts +11 -0
- package/dist/host/stack-config.js +21 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/infra/index.js +2 -1
- package/dist/infra/readiness.d.ts +0 -2
- package/dist/infra/readiness.js +4 -3
- package/dist/keys/client.d.ts +1 -0
- package/dist/keys/client.js +2 -3
- package/dist/keys/contract.d.ts +1 -3
- package/dist/keys/contract.js +1 -3
- package/dist/keys/egress-ca.d.ts +0 -2
- package/dist/keys/egress-ca.js +2 -3
- package/dist/keys/keys.js +6 -1
- package/dist/keys/x509.d.ts +8 -4
- package/dist/keys/x509.js +14 -5
- package/dist/management-openapi.json +1961 -994
- package/dist/mcp/connect.d.ts +35 -26
- package/dist/mcp/connect.js +112 -141
- package/dist/mcp/pool.d.ts +27 -22
- package/dist/mcp/pool.js +34 -48
- package/dist/mcp/preview.d.ts +13 -6
- package/dist/mcp/preview.js +37 -20
- package/dist/mcp/snapshot.d.ts +35 -86
- package/dist/mcp/snapshot.js +93 -135
- package/dist/model/auth-store.js +5 -3
- package/dist/model/capabilities.d.ts +1 -1
- package/dist/model/catalog.d.ts +9 -36
- package/dist/model/catalog.js +6 -33
- package/dist/model/descriptor.d.ts +51 -0
- package/dist/model/descriptor.js +83 -0
- package/dist/model/models.d.ts +0 -3
- package/dist/model/models.js +3 -5
- package/dist/model/native-blocks.js +1 -1
- package/dist/model/pi-model.d.ts +16 -5
- package/dist/model/pi-model.js +86 -105
- package/dist/openapi.json +866 -1218
- package/dist/reads/cursor.js +3 -1
- package/dist/record/append.d.ts +34 -2
- package/dist/record/append.js +50 -1
- package/dist/record/environment.d.ts +2 -0
- package/dist/record/environment.js +2 -0
- package/dist/record/index.d.ts +1 -1
- package/dist/record/index.js +1 -1
- package/dist/redact.d.ts +1 -1
- package/dist/redact.js +3 -2
- package/dist/sandbox/egress-token.d.ts +3 -3
- package/dist/sandbox/egress-token.js +3 -3
- package/dist/sandbox/join.js +3 -2
- package/dist/sandbox/manager.d.ts +41 -41
- package/dist/sandbox/manager.js +112 -44
- package/dist/sandbox/placement.d.ts +1 -1
- package/dist/sandbox/placement.js +5 -8
- package/dist/sandbox/pods/client.d.ts +1 -10
- package/dist/sandbox/pods/client.js +8 -4
- package/dist/sandbox/pods/lifecycle.d.ts +19 -11
- package/dist/sandbox/pods/lifecycle.js +45 -23
- package/dist/sandbox/pods/network-gate.d.ts +4 -5
- package/dist/sandbox/pods/network-gate.js +7 -7
- package/dist/sandbox/pods/reconcile.js +4 -1
- package/dist/sandbox/pods/spec.js +8 -5
- package/dist/sandbox/policy.d.ts +7 -1
- package/dist/sandbox/policy.js +10 -3
- package/dist/sandbox/resolve.d.ts +8 -3
- package/dist/sandbox/resolve.js +12 -2
- package/dist/sandbox/setup.d.ts +3 -1
- package/dist/sandbox/setup.js +34 -11
- package/dist/sandbox/share.d.ts +5 -14
- package/dist/sandbox/share.js +5 -34
- package/dist/sandbox/skills.d.ts +7 -13
- package/dist/sandbox/skills.js +16 -31
- package/dist/sandbox/tenant-config.d.ts +2 -2
- package/dist/sandbox/tenant-config.js +4 -3
- package/dist/sandbox/tools.d.ts +7 -1
- package/dist/sandbox/tools.js +26 -26
- package/dist/sandbox/types.d.ts +10 -3
- package/dist/sandbox/types.js +9 -0
- package/dist/store/postgres/connect.d.ts +6 -5
- package/dist/store/postgres/connect.js +14 -11
- package/dist/store/postgres/control.js +13 -13
- package/dist/store/postgres/drizzle/0028_artifact_write_keys.sql +2 -0
- package/dist/store/postgres/drizzle/0029_protocol_15.sql +11 -0
- package/dist/store/postgres/drizzle/0030_protocol_15_runtime_block.sql +11 -0
- package/dist/store/postgres/drizzle/0031_protocol_15_mcp_snapshot.sql +8 -0
- package/dist/store/postgres/drizzle/meta/_journal.json +28 -0
- package/dist/store/postgres/migrate.js +1 -1
- package/dist/store/postgres/reads.js +10 -2
- package/dist/store/postgres/schema.d.ts +19 -0
- package/dist/store/postgres/schema.js +7 -0
- package/dist/store/postgres/store.js +55 -26
- package/dist/store/types.d.ts +17 -7
- package/dist/streams/relay/core.d.ts +3 -3
- package/dist/streams/relay/core.js +9 -10
- package/dist/tenant/advance.js +21 -31
- package/dist/tenant/commands.js +9 -16
- package/dist/tenant/context.d.ts +14 -17
- package/dist/tenant/definition-files.d.ts +25 -4
- package/dist/tenant/definition-files.js +85 -47
- package/dist/tenant/effects.js +9 -36
- package/dist/tenant/environment-manifests.js +9 -1
- package/dist/tenant/environments.d.ts +0 -2
- package/dist/tenant/environments.js +54 -30
- package/dist/tenant/ephemeral.d.ts +1 -1
- package/dist/tenant/ephemeral.js +2 -1
- package/dist/tenant/history.d.ts +1 -1
- package/dist/tenant/history.js +1 -1
- package/dist/tenant/host-token.d.ts +3 -3
- package/dist/tenant/host-token.js +12 -11
- package/dist/tenant/http.d.ts +5 -8
- package/dist/tenant/http.js +9 -0
- package/dist/tenant/identity-file.d.ts +24 -1
- package/dist/tenant/identity-file.js +35 -7
- package/dist/tenant/issuers.d.ts +5 -5
- package/dist/tenant/issuers.js +31 -23
- package/dist/tenant/jwt.d.ts +8 -2
- package/dist/tenant/jwt.js +10 -2
- package/dist/tenant/limits.d.ts +90 -0
- package/dist/tenant/limits.js +175 -0
- package/dist/tenant/module.d.ts +4 -1
- package/dist/tenant/module.js +9 -8
- package/dist/tenant/outbound.d.ts +17 -19
- package/dist/tenant/outbound.js +18 -21
- package/dist/tenant/run-grants.js +3 -2
- package/dist/tenant/run-token.d.ts +0 -4
- package/dist/tenant/run-token.js +6 -11
- package/dist/tenant/runtime-limits.d.ts +24 -0
- package/dist/tenant/runtime-limits.js +27 -0
- package/dist/tenant/runtime.js +30 -43
- package/dist/tenant/session-streams.js +7 -6
- package/dist/tenant/session.d.ts +1 -1
- package/dist/tenant/session.js +1 -1
- package/dist/tenant/sessions.js +32 -29
- package/dist/tenant/signing-keys.d.ts +1 -1
- package/dist/tenant/signing-keys.js +5 -6
- package/dist/tenant/status.js +4 -3
- package/dist/tenant/streams.js +18 -20
- package/dist/tenant/sweep.d.ts +1 -21
- package/dist/tenant/sweep.js +39 -48
- package/dist/tenant/transcript.d.ts +70 -23
- package/dist/tenant/transcript.js +28 -22
- package/dist/tenant/types.d.ts +11 -16
- package/dist/tenant/worker.d.ts +2 -10
- package/dist/tenant/worker.js +5 -14
- package/dist/traces/ids.js +5 -1
- package/dist/traces/map.d.ts +9 -6
- package/dist/traces/map.js +9 -11
- package/dist/traces/otlp.d.ts +3 -3
- package/dist/traces/otlp.js +5 -3
- package/dist/traces/projector.d.ts +9 -4
- package/dist/traces/projector.js +13 -7
- package/dist/traces/read.js +6 -1
- package/dist/tuning.d.ts +383 -0
- package/dist/tuning.js +658 -0
- package/dist/vault/headers.js +4 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/artifacts/export.d.ts +0 -8
- package/dist/artifacts/export.js +0 -204
- package/dist/artifacts/media-types.d.ts +0 -30
- package/dist/artifacts/media-types.js +0 -137
- package/dist/artifacts/workspace.d.ts +0 -60
- package/dist/artifacts/workspace.js +0 -45
- package/dist/media.d.ts +0 -10
- package/dist/media.js +0 -58
- package/dist/sandbox/runtime-tools.d.ts +0 -9
- package/dist/sandbox/runtime-tools.js +0 -16
- package/dist/sandbox/session-sandbox.d.ts +0 -16
- package/dist/sandbox/session-sandbox.js +0 -77
- package/dist/tenant/artifact-tool.d.ts +0 -13
- package/dist/tenant/artifact-tool.js +0 -243
- package/dist/tenant/skill-tool.d.ts +0 -20
- package/dist/tenant/skill-tool.js +0 -67
- package/dist/tenant/tool-results.d.ts +0 -57
- package/dist/tenant/tool-results.js +0 -298
- package/dist/tenant/tool-search.d.ts +0 -39
- package/dist/tenant/tool-search.js +0 -103
package/dist/model/pi-model.d.ts
CHANGED
|
@@ -1,22 +1,33 @@
|
|
|
1
1
|
import { type Credential } from "@earendil-works/pi-ai";
|
|
2
2
|
import type { RuntimeModelAdapter } from "../contracts.js";
|
|
3
|
+
import { type RuntimeLimits } from "@nylorun/core/contracts";
|
|
3
4
|
import { type FileResolver } from "../artifacts/files.js";
|
|
4
5
|
import type { HostModelSecret } from "../vault/service.js";
|
|
5
6
|
export interface ModelPreview {
|
|
6
7
|
readonly invocationId: string;
|
|
7
8
|
readonly text: string;
|
|
8
9
|
}
|
|
9
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Retry and timeout settings for one model call (Model Calls §5, §6): the Tenant's Runtime limits
|
|
12
|
+
* `model*` (`modelCallSettingsOf`), which the gates read for each call. Each left out is that
|
|
13
|
+
* limit's default.
|
|
14
|
+
*/
|
|
10
15
|
export interface ModelCallSettings {
|
|
11
|
-
/** Attempts per call, including the first
|
|
16
|
+
/** Attempts per call, including the first (`modelAttempts`). */
|
|
12
17
|
readonly attempts?: number;
|
|
13
|
-
/** Base delay between attempts; doubles each time, with jitter
|
|
18
|
+
/** Base delay between attempts; doubles each time, with jitter (`modelRetryDelayMs`). */
|
|
14
19
|
readonly retryBaseDelayMs?: number;
|
|
15
|
-
/** A stream with no event for this long is aborted and retried
|
|
20
|
+
/** A stream with no event for this long is aborted and retried (`modelIdleMs`). */
|
|
16
21
|
readonly idleTimeoutMs?: number;
|
|
17
|
-
/** Whole-request timeout passed to the provider SDK
|
|
22
|
+
/** Whole-request timeout passed to the provider SDK (`modelRequestMs`). */
|
|
18
23
|
readonly requestTimeoutMs?: number;
|
|
24
|
+
/** Retries the provider SDK makes within one attempt (`modelProviderRetries`). */
|
|
25
|
+
readonly providerRetries?: number;
|
|
26
|
+
/** The longest delay the provider SDK waits before one of them (`modelRetryDelayMaxMs`). */
|
|
27
|
+
readonly maxRetryDelayMs?: number;
|
|
19
28
|
}
|
|
29
|
+
/** The model call settings the Runtime limits `limits` set. */
|
|
30
|
+
export declare function modelCallSettingsOf(limits: RuntimeLimits): Required<ModelCallSettings>;
|
|
20
31
|
export interface PiModelOptions {
|
|
21
32
|
readonly root?: string;
|
|
22
33
|
readonly onPreview?: (preview: ModelPreview) => void;
|
package/dist/model/pi-model.js
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { retryAssistantCall, } from "@earendil-works/pi-ai";
|
|
2
|
+
import { RUNTIME_LIMIT_DEFAULTS } from "@nylorun/core/contracts";
|
|
2
3
|
import { mediaReferenceOf } from "@nylorun/core/define";
|
|
3
4
|
import { FileUnavailableError, } from "../artifacts/files.js";
|
|
4
|
-
import { essence, inputLabel, isModelImage,
|
|
5
|
+
import { essence, inputLabel, isModelImage, modelInputOf } from "@nylorun/core/contracts";
|
|
5
6
|
import { scrub } from "../redact.js";
|
|
6
|
-
import { capabilitiesOf } from "./capabilities.js";
|
|
7
7
|
import { classifyAssistantError, failure } from "./classify.js";
|
|
8
|
+
import { addedInputsOf, describeModel, selectionOf } from "./descriptor.js";
|
|
8
9
|
import { modelsFor } from "./models.js";
|
|
9
10
|
import { NativeBlocks, nativeKindsOf } from "./native-blocks.js";
|
|
10
11
|
import { projectSecrets } from "./settings.js";
|
|
12
|
+
/** The model call settings the Runtime limits `limits` set. */
|
|
13
|
+
export function modelCallSettingsOf(limits) {
|
|
14
|
+
return {
|
|
15
|
+
attempts: limits.modelAttempts,
|
|
16
|
+
retryBaseDelayMs: limits.modelRetryDelayMs,
|
|
17
|
+
idleTimeoutMs: limits.modelIdleMs,
|
|
18
|
+
requestTimeoutMs: limits.modelRequestMs,
|
|
19
|
+
providerRetries: limits.modelProviderRetries,
|
|
20
|
+
maxRetryDelayMs: limits.modelRetryDelayMaxMs,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
11
23
|
const OPENAI_COMPATIBLE_REASONING = /^reasoning(_content|_text)?$/;
|
|
12
24
|
const emptyUsage = () => ({
|
|
13
25
|
input: 0,
|
|
@@ -31,12 +43,7 @@ const noAmbientAuth = {
|
|
|
31
43
|
* A provider failure is returned as a failure outcome; only an abort is thrown.
|
|
32
44
|
*/
|
|
33
45
|
export function piModel(options = {}) {
|
|
34
|
-
const settings = {
|
|
35
|
-
attempts: Math.max(1, options.settings?.attempts ?? 3),
|
|
36
|
-
retryBaseDelayMs: options.settings?.retryBaseDelayMs ?? 2_000,
|
|
37
|
-
idleTimeoutMs: options.settings?.idleTimeoutMs ?? 300_000,
|
|
38
|
-
requestTimeoutMs: options.settings?.requestTimeoutMs ?? 600_000,
|
|
39
|
-
};
|
|
46
|
+
const settings = { ...modelCallSettingsOf(RUNTIME_LIMIT_DEFAULTS), ...options.settings };
|
|
40
47
|
return async (call, context) => {
|
|
41
48
|
context.signal.throwIfAborted();
|
|
42
49
|
// The first stream event's time, from here (R7.1): the meter keeps it on the usage row.
|
|
@@ -54,25 +61,15 @@ export function piModel(options = {}) {
|
|
|
54
61
|
...outcome,
|
|
55
62
|
message: String(scrub(outcome.message, secrets)),
|
|
56
63
|
});
|
|
57
|
-
const
|
|
58
|
-
const selection = {
|
|
59
|
-
provider: stored.provider,
|
|
60
|
-
model: requested?.startsWith(`${stored.provider}/`)
|
|
61
|
-
? requested.slice(stored.provider.length + 1)
|
|
62
|
-
: (requested ?? stored.model),
|
|
63
|
-
...(stored.baseUrl
|
|
64
|
-
? { custom: { baseUrl: stored.baseUrl, ...(stored.settings ?? {}) } }
|
|
65
|
-
: {}),
|
|
66
|
-
};
|
|
64
|
+
const selection = selectionOf(stored, call.model?.id);
|
|
67
65
|
const registry = modelsFor(selection, hostCredentialStore(stored, options.writeHostCredential), { environment: false, authContext: noAmbientAuth });
|
|
68
66
|
const found = registry.getModel(selection.provider, selection.model);
|
|
69
67
|
if (!found)
|
|
70
68
|
return failure("invalid_request", "Unknown model. Run nylorun tenant models set.", false);
|
|
71
|
-
// What the model reads (protocol 12): its catalog's inputs and
|
|
72
|
-
// pi-ai drops an image the model's `input` lacks, so the call's
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
: stored.addedInputs?.[`${selection.provider}/${selection.model}`]);
|
|
69
|
+
// What the model reads (protocol 12), as `turn.start.model` says: its catalog's inputs and
|
|
70
|
+
// the operator's additions. pi-ai drops an image the model's `input` lacks, so the call's
|
|
71
|
+
// model carries an added one.
|
|
72
|
+
const { inputs } = describeModel(found, addedInputsOf(selection, stored, stored.addedInputs ?? {}));
|
|
76
73
|
const selected = {
|
|
77
74
|
...found,
|
|
78
75
|
input: inputs.includes("image") ? ["text", "image"] : ["text"],
|
|
@@ -80,7 +77,10 @@ export function piModel(options = {}) {
|
|
|
80
77
|
// PDFs, Office documents, audio and video go in the API's own blocks: pi-ai builds the
|
|
81
78
|
// request with a marker in each one's place and `onPayload` swaps it for the bytes.
|
|
82
79
|
const natives = new NativeBlocks();
|
|
80
|
+
// A part the provider cannot take fails the call before anything is sent: never retried.
|
|
83
81
|
const request = await buildContext(call, selected, inputs, options, natives);
|
|
82
|
+
if ("failed" in request)
|
|
83
|
+
return redacted(request.failed);
|
|
84
84
|
// Publish only portable references, never the materialized provider image bytes.
|
|
85
85
|
context.reportPreparedCall?.({
|
|
86
86
|
adapter: "runtime.pi-ai",
|
|
@@ -96,8 +96,8 @@ export function piModel(options = {}) {
|
|
|
96
96
|
sessionId: call.executionId,
|
|
97
97
|
cacheRetention: "short",
|
|
98
98
|
timeoutMs: settings.requestTimeoutMs,
|
|
99
|
-
maxRetries:
|
|
100
|
-
maxRetryDelayMs:
|
|
99
|
+
maxRetries: settings.providerRetries,
|
|
100
|
+
maxRetryDelayMs: settings.maxRetryDelayMs,
|
|
101
101
|
...(natives.size > 0
|
|
102
102
|
? {
|
|
103
103
|
// A file that cannot be carried stops the request before it is sent.
|
|
@@ -211,21 +211,6 @@ export function piModel(options = {}) {
|
|
|
211
211
|
...metadataFor(selected, part.thoughtSignature),
|
|
212
212
|
});
|
|
213
213
|
}
|
|
214
|
-
if (call.outputSchema &&
|
|
215
|
-
!output.some((part) => part.type === "tool-call")) {
|
|
216
|
-
const text = output
|
|
217
|
-
.filter((part) => part.type === "text")
|
|
218
|
-
.map((part) => part.text)
|
|
219
|
-
.join("");
|
|
220
|
-
let value;
|
|
221
|
-
try {
|
|
222
|
-
value = parseJsonWithRepair(withoutCodeFence(text));
|
|
223
|
-
}
|
|
224
|
-
catch (error) {
|
|
225
|
-
return failure("invalid_output", `The model's final answer is not valid JSON: ${error instanceof Error ? error.message : String(error)}`, false);
|
|
226
|
-
}
|
|
227
|
-
output.splice(0, output.length, { type: "json", value });
|
|
228
|
-
}
|
|
229
214
|
return {
|
|
230
215
|
output,
|
|
231
216
|
finishReason: response.stopReason === "toolUse"
|
|
@@ -255,28 +240,56 @@ export function piModel(options = {}) {
|
|
|
255
240
|
};
|
|
256
241
|
};
|
|
257
242
|
}
|
|
243
|
+
/** A part the call cannot carry: the call fails with it, before anything is sent. */
|
|
244
|
+
class Unsendable extends Error {
|
|
245
|
+
outcome;
|
|
246
|
+
constructor(outcome) {
|
|
247
|
+
super(outcome.message);
|
|
248
|
+
this.outcome = outcome;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* The provider context for `call`. The gate decides nothing about files (protocol 15): a media
|
|
253
|
+
* part names an artifact version the session may read, which it fetches (`options.files`) and
|
|
254
|
+
* translates, an image to an image block and a PDF, Office document, audio or video to a marker
|
|
255
|
+
* for its native block (`natives`). A part the model or its API cannot take is refused
|
|
256
|
+
* (`unsupported_input`): a text file (the harness inlines text), a kind the model does not read.
|
|
257
|
+
* A file it cannot fetch is `invalid_request`. Bytes go only into the provider request built
|
|
258
|
+
* here, never into the transcript or the journal.
|
|
259
|
+
*/
|
|
258
260
|
async function buildContext(call, selected, inputs, options, natives) {
|
|
261
|
+
try {
|
|
262
|
+
return await translate(call, selected, inputs, options, natives);
|
|
263
|
+
}
|
|
264
|
+
catch (error) {
|
|
265
|
+
if (error instanceof Unsendable)
|
|
266
|
+
return { failed: error.outcome };
|
|
267
|
+
throw error;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
async function translate(call, selected, inputs, options, natives) {
|
|
259
271
|
const messages = [];
|
|
260
272
|
const instructions = [];
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
273
|
+
const unsupported = (message) => new Unsendable(failure("unsupported_input", message, false));
|
|
274
|
+
/** Why the model cannot take a file of `type`, or undefined when it can. */
|
|
275
|
+
const refusal = (name, type) => {
|
|
276
|
+
const kind = modelInputOf(type);
|
|
277
|
+
const file = `File ${JSON.stringify(name)} (${essence(type)})`;
|
|
278
|
+
if (kind === "text")
|
|
279
|
+
return unsupported(`${file} is text: send its contents as a text part.`);
|
|
280
|
+
if (kind === undefined ||
|
|
281
|
+
!inputs.includes(kind) ||
|
|
282
|
+
(kind === "image" && !isModelImage(type)) ||
|
|
283
|
+
(kind !== "image" && !(isNativeKind(kind) && nativeKindsOf(selected.api).includes(kind))))
|
|
284
|
+
return unsupported(`This model (${selected.provider}/${selected.id}) does not read ${kind === "image" && inputs.includes("image") ? "this image format" : inputLabel(kind)}: ${file}.`);
|
|
285
|
+
return undefined;
|
|
286
|
+
};
|
|
287
|
+
const toProvider = async (part) => {
|
|
288
|
+
const declared = refusal(mediaReferenceOf(part.reference)?.name ?? "file", part.mediaType);
|
|
289
|
+
if (declared)
|
|
290
|
+
throw declared;
|
|
278
291
|
if (!options.files)
|
|
279
|
-
|
|
292
|
+
throw new Unsendable(failure("invalid_request", "This gate cannot fetch files: no artifact store.", false));
|
|
280
293
|
let file;
|
|
281
294
|
try {
|
|
282
295
|
file = await options.files(part.reference);
|
|
@@ -284,37 +297,21 @@ async function buildContext(call, selected, inputs, options, natives) {
|
|
|
284
297
|
catch (error) {
|
|
285
298
|
if (!(error instanceof FileUnavailableError))
|
|
286
299
|
throw error;
|
|
287
|
-
|
|
300
|
+
throw new Unsendable(failure("invalid_request", error.message, false));
|
|
288
301
|
}
|
|
289
|
-
|
|
290
|
-
type = essence(file.mediaType);
|
|
291
|
-
const stored = unreadableReason(file.mediaType, inputs);
|
|
302
|
+
const stored = refusal(file.name, file.mediaType);
|
|
292
303
|
if (stored)
|
|
293
|
-
|
|
304
|
+
throw stored;
|
|
305
|
+
const type = essence(file.mediaType);
|
|
306
|
+
const data = Buffer.from(file.bytes).toString("base64");
|
|
294
307
|
if (isModelImage(file.mediaType))
|
|
295
|
-
return { type: "image", data
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
return note("it is not UTF-8 text");
|
|
303
|
-
}
|
|
304
|
-
return {
|
|
305
|
-
type: "text",
|
|
306
|
-
text: `<file name=${JSON.stringify(file.name)} type=${JSON.stringify(type)}>\n${text}\n</file>`,
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
const kind = modelInputOf(file.mediaType);
|
|
310
|
-
if (isNativeKind(kind) && nativeKindsOf(selected.api).includes(kind))
|
|
311
|
-
return natives.add({
|
|
312
|
-
kind,
|
|
313
|
-
mediaType: type,
|
|
314
|
-
name: file.name,
|
|
315
|
-
data: Buffer.from(file.bytes).toString("base64"),
|
|
316
|
-
});
|
|
317
|
-
return note(`the Runtime does not send ${inputLabel(kind)} to this model's API (${selected.api})`);
|
|
308
|
+
return { type: "image", data, mimeType: type };
|
|
309
|
+
return natives.add({
|
|
310
|
+
kind: modelInputOf(file.mediaType),
|
|
311
|
+
mediaType: type,
|
|
312
|
+
name: file.name,
|
|
313
|
+
data,
|
|
314
|
+
});
|
|
318
315
|
};
|
|
319
316
|
const content = async (parts) => {
|
|
320
317
|
const result = [];
|
|
@@ -322,7 +319,7 @@ async function buildContext(call, selected, inputs, options, natives) {
|
|
|
322
319
|
if (part.type === "text")
|
|
323
320
|
result.push({ type: "text", text: part.text });
|
|
324
321
|
else if (part.type === "media")
|
|
325
|
-
result.push(await
|
|
322
|
+
result.push(await toProvider(part));
|
|
326
323
|
}
|
|
327
324
|
return result;
|
|
328
325
|
};
|
|
@@ -355,18 +352,7 @@ async function buildContext(call, selected, inputs, options, natives) {
|
|
|
355
352
|
description: tool.description ?? "",
|
|
356
353
|
parameters: { ...tool.inputSchema },
|
|
357
354
|
}));
|
|
358
|
-
return {
|
|
359
|
-
systemPrompt: [
|
|
360
|
-
...instructions,
|
|
361
|
-
...(call.outputSchema
|
|
362
|
-
? [
|
|
363
|
-
`Return the final answer as JSON matching this schema: ${JSON.stringify(call.outputSchema)}. Use tools when needed before returning the final JSON.`,
|
|
364
|
-
]
|
|
365
|
-
: []),
|
|
366
|
-
].join("\n"),
|
|
367
|
-
messages,
|
|
368
|
-
tools,
|
|
369
|
-
};
|
|
355
|
+
return { systemPrompt: instructions.join("\n"), messages, tools };
|
|
370
356
|
}
|
|
371
357
|
const isNativeKind = (input) => input === "pdf" || input === "office" || input === "audio" || input === "video";
|
|
372
358
|
/**
|
|
@@ -456,11 +442,6 @@ function metadataFor(selected, signature, redacted) {
|
|
|
456
442
|
},
|
|
457
443
|
};
|
|
458
444
|
}
|
|
459
|
-
/** Open-weight models often wrap a JSON answer in a Markdown code fence. */
|
|
460
|
-
function withoutCodeFence(text) {
|
|
461
|
-
const fenced = /^\s*```[a-zA-Z]*\s*\n([\s\S]*?)\n?```\s*$/.exec(text);
|
|
462
|
-
return fenced ? fenced[1] : text;
|
|
463
|
-
}
|
|
464
445
|
function usageOf(usage) {
|
|
465
446
|
return {
|
|
466
447
|
inputTokens: usage.input,
|