pi2dsh 0.3.4 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{all-Rt4K68QA.mjs → all-DSpxKvHa.mjs} +10 -10
- package/dist/{all-Rt4K68QA.mjs.map → all-DSpxKvHa.mjs.map} +1 -1
- package/dist/{anthropic-messages-Beym0_aC.mjs → anthropic-messages-BL9N1Idv.mjs} +3 -3
- package/dist/{anthropic-messages-Beym0_aC.mjs.map → anthropic-messages-BL9N1Idv.mjs.map} +1 -1
- package/dist/{azure-openai-responses-cHqZTgLD.mjs → azure-openai-responses-A67VbaZ1.mjs} +3 -3
- package/dist/{azure-openai-responses-cHqZTgLD.mjs.map → azure-openai-responses-A67VbaZ1.mjs.map} +1 -1
- package/dist/cli.mjs +1 -1
- package/dist/compat/pi-ai.d.mts +3 -38
- package/dist/compat/pi-ai.d.mts.map +1 -1
- package/dist/compat/pi-ai.mjs +3 -3
- package/dist/compat/pi-coding-agent.d.mts +71 -32
- package/dist/compat/pi-coding-agent.d.mts.map +1 -1
- package/dist/compat/pi-coding-agent.mjs +2 -2
- package/dist/credentials-oauth.mjs +2 -2
- package/dist/{dist-QBBA-dL_.mjs → dist-BYA74yh_.mjs} +2 -2
- package/dist/{dist-QBBA-dL_.mjs.map → dist-BYA74yh_.mjs.map} +1 -1
- package/dist/dist-DeonWo7m.mjs +1089 -0
- package/dist/dist-DeonWo7m.mjs.map +1 -0
- package/dist/{google-generative-ai-B7OZs5lu.mjs → google-generative-ai-DT5S8D8y.mjs} +2 -2
- package/dist/{google-generative-ai-B7OZs5lu.mjs.map → google-generative-ai-DT5S8D8y.mjs.map} +1 -1
- package/dist/{google-shared-CRsAUItF.mjs → google-shared-DYP_9cnK.mjs} +4 -4
- package/dist/{google-shared-CRsAUItF.mjs.map → google-shared-DYP_9cnK.mjs.map} +1 -1
- package/dist/{google-vertex-DmdaHQtB.mjs → google-vertex-Dpq7O7Be.mjs} +3 -3
- package/dist/{google-vertex-DmdaHQtB.mjs.map → google-vertex-Dpq7O7Be.mjs.map} +1 -1
- package/dist/host.mjs +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{json-parse-CFyFZSLJ.mjs → json-parse-Dz5sKMTv.mjs} +2 -2
- package/dist/{json-parse-CFyFZSLJ.mjs.map → json-parse-Dz5sKMTv.mjs.map} +1 -1
- package/dist/{mcp-config-D2B3kv-Z.mjs → mcp-config-B3h5jTBb.mjs} +9 -8
- package/dist/mcp-config-B3h5jTBb.mjs.map +1 -0
- package/dist/{mistral-conversations-HHZCcFv_.mjs → mistral-conversations-BsxbCCWx.mjs} +4 -4
- package/dist/{mistral-conversations-HHZCcFv_.mjs.map → mistral-conversations-BsxbCCWx.mjs.map} +1 -1
- package/dist/{multipart-parser-CIa5BbwO.mjs → multipart-parser-woKCuALW.mjs} +3 -3
- package/dist/{multipart-parser-CIa5BbwO.mjs.map → multipart-parser-woKCuALW.mjs.map} +1 -1
- package/dist/{openai-codex-responses-vmovNu-q.mjs → openai-codex-responses-C7vviVT2.mjs} +3 -3
- package/dist/{openai-codex-responses-vmovNu-q.mjs.map → openai-codex-responses-C7vviVT2.mjs.map} +1 -1
- package/dist/{openai-completions-fXHhRolF.mjs → openai-completions-By8QNX1P.mjs} +3 -3
- package/dist/{openai-completions-fXHhRolF.mjs.map → openai-completions-By8QNX1P.mjs.map} +1 -1
- package/dist/{openai-responses-DKdCYf3h.mjs → openai-responses-DboJUcFN.mjs} +3 -3
- package/dist/{openai-responses-DKdCYf3h.mjs.map → openai-responses-DboJUcFN.mjs.map} +1 -1
- package/dist/{openai-responses-shared-D0Jq7yVP.mjs → openai-responses-shared-BDzn7nJY.mjs} +2 -2
- package/dist/{openai-responses-shared-D0Jq7yVP.mjs.map → openai-responses-shared-BDzn7nJY.mjs.map} +1 -1
- package/dist/{otel-BQSQRBLF.mjs → otel-PimLMoiV.mjs} +3 -3
- package/dist/{otel-BQSQRBLF.mjs.map → otel-PimLMoiV.mjs.map} +1 -1
- package/dist/{pi-ai-DhYGgq4Y.mjs → pi-ai-B_88Wb0r.mjs} +49 -6
- package/dist/{pi-ai-DhYGgq4Y.mjs.map → pi-ai-B_88Wb0r.mjs.map} +1 -1
- package/dist/{pi-coding-agent-fPHwKP4d.mjs → pi-coding-agent-COMX0KHL.mjs} +109 -34
- package/dist/pi-coding-agent-COMX0KHL.mjs.map +1 -0
- package/dist/{pi-messages-CV-Ts8An.mjs → pi-messages-B-7Xo_I0.mjs} +3 -3
- package/dist/{pi-messages-CV-Ts8An.mjs.map → pi-messages-B-7Xo_I0.mjs.map} +1 -1
- package/dist/pi-types-KazmR2O5.d.mts +62 -0
- package/dist/pi-types-KazmR2O5.d.mts.map +1 -0
- package/dist/pi-uuid-Db8ShZsK.mjs +47 -0
- package/dist/pi-uuid-Db8ShZsK.mjs.map +1 -0
- package/dist/{provider-env-C72pF4vP.mjs → provider-env-D-cCRWzv.mjs} +2 -2
- package/dist/{provider-env-C72pF4vP.mjs.map → provider-env-D-cCRWzv.mjs.map} +1 -1
- package/dist/{runtime-B9R7bDWT.mjs → runtime-B7mEIRf-.mjs} +1183 -52
- package/dist/runtime-B7mEIRf-.mjs.map +1 -0
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/{src-C3WBfOks.mjs → src-BEl3QrGL.mjs} +3 -3
- package/dist/{src-C3WBfOks.mjs.map → src-BEl3QrGL.mjs.map} +1 -1
- package/package.json +2 -2
- package/dist/build-BG7p2Lbr.mjs +0 -4416
- package/dist/build-BG7p2Lbr.mjs.map +0 -1
- package/dist/dist-IQKOgQyt.mjs +0 -10035
- package/dist/dist-IQKOgQyt.mjs.map +0 -1
- package/dist/mcp-config-D2B3kv-Z.mjs.map +0 -1
- package/dist/pi-coding-agent-fPHwKP4d.mjs.map +0 -1
- package/dist/pi-types-BLt46jaf.d.mts +0 -2494
- package/dist/pi-types-BLt46jaf.d.mts.map +0 -1
- package/dist/rolldown-runtime-CTfmNlz1.mjs +0 -44
- package/dist/runtime-B9R7bDWT.mjs.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { C as realBuiltinProvider, R as AssistantMessageEventStream, S as openAIResponsesApi, a as builtinProviders, i as anthropicMessagesApi, r as __setPiAiLlmBridge, x as openAICompletionsApi } from "./pi-ai-B_88Wb0r.mjs";
|
|
3
|
+
import { r as normalizePath, t as getAgentDir } from "./pi-config-shim-CZ1wFzqM.mjs";
|
|
4
|
+
import { E as __setSubagentSessionFactory, S as Theme, f as ExtensionRunner } from "./pi-coding-agent-COMX0KHL.mjs";
|
|
4
5
|
import { a as resolvePiProviderAuth, n as loginPiProvider, r as providerSupportsOAuth, t as FileCredentialStore } from "./oauth-bridge-C6fL1qSv.mjs";
|
|
5
|
-
import { L as AssistantMessageEventStream, S as realBuiltinProvider, i as builtinProviders, n as __setPiAiLlmBridge } from "./pi-ai-DhYGgq4Y.mjs";
|
|
6
6
|
import { createRequire } from "node:module";
|
|
7
7
|
import { access, readFile } from "node:fs/promises";
|
|
8
8
|
import { join } from "node:path";
|
|
@@ -14,6 +14,9 @@ import { createJiti } from "jiti";
|
|
|
14
14
|
import { createUserMessage } from "@deepseek-ai/dsh-llm";
|
|
15
15
|
import { renderPrompt } from "@deepseek-ai/dsh-system-prompt";
|
|
16
16
|
import { randomUUID } from "node:crypto";
|
|
17
|
+
import { execSync, spawnSync } from "child_process";
|
|
18
|
+
import { Type } from "typebox";
|
|
19
|
+
import { Compile } from "typebox/compile";
|
|
17
20
|
//#region src/session-bridge.ts
|
|
18
21
|
function sidecarDir() {
|
|
19
22
|
return join(getAgentDir(), "session-entries");
|
|
@@ -526,15 +529,28 @@ function llmOf(ctx) {
|
|
|
526
529
|
return;
|
|
527
530
|
}
|
|
528
531
|
}
|
|
532
|
+
const PI_MODEL_PASSTHROUGH_FIELDS = [
|
|
533
|
+
"baseUrl",
|
|
534
|
+
"cost",
|
|
535
|
+
"contextWindow",
|
|
536
|
+
"maxTokens",
|
|
537
|
+
"samplingParams",
|
|
538
|
+
"thinkingLevelMap",
|
|
539
|
+
"compat",
|
|
540
|
+
"headers"
|
|
541
|
+
];
|
|
529
542
|
function piModelFromInfo(info) {
|
|
530
543
|
const modalities = Array.isArray(info.inputModalities) ? info.inputModalities : void 0;
|
|
544
|
+
const carried = {};
|
|
545
|
+
for (const field of PI_MODEL_PASSTHROUGH_FIELDS) if (info[field] !== void 0) carried[field] = info[field];
|
|
531
546
|
return {
|
|
547
|
+
...carried,
|
|
532
548
|
id: String(info.id ?? ""),
|
|
533
549
|
name: String(info.name ?? info.id ?? ""),
|
|
534
550
|
provider: String(info.provider ?? ""),
|
|
535
|
-
api: "
|
|
551
|
+
api: typeof info.api === "string" ? info.api : "faux",
|
|
536
552
|
input: modalities === void 0 ? ["text"] : modalities.filter((m) => m === "text" || m === "image"),
|
|
537
|
-
reasoning: info.reasoning !== void 0
|
|
553
|
+
reasoning: typeof info.reasoning === "boolean" ? info.reasoning : info.reasoning !== void 0
|
|
538
554
|
};
|
|
539
555
|
}
|
|
540
556
|
/**
|
|
@@ -726,7 +742,7 @@ function streamViaDshLlm(llm, request) {
|
|
|
726
742
|
content: [],
|
|
727
743
|
provider,
|
|
728
744
|
model: modelId,
|
|
729
|
-
api: "
|
|
745
|
+
api: "faux"
|
|
730
746
|
};
|
|
731
747
|
const content = partial.content;
|
|
732
748
|
let usage;
|
|
@@ -882,7 +898,7 @@ function streamViaDshLlm(llm, request) {
|
|
|
882
898
|
content: content.filter((block) => block !== void 0),
|
|
883
899
|
provider,
|
|
884
900
|
model: modelId,
|
|
885
|
-
api: "
|
|
901
|
+
api: "faux",
|
|
886
902
|
...usage === void 0 ? {} : { usage },
|
|
887
903
|
stopReason,
|
|
888
904
|
timestamp: Date.now()
|
|
@@ -1096,7 +1112,820 @@ async function* piEventsToDshChunks(events) {
|
|
|
1096
1112
|
};
|
|
1097
1113
|
}
|
|
1098
1114
|
//#endregion
|
|
1115
|
+
//#region src/compat/vendor/pi-json.ts
|
|
1116
|
+
/** Strip `//` line comments and trailing commas from JSON, leaving string literals untouched. */
|
|
1117
|
+
function stripJsonComments(input) {
|
|
1118
|
+
return input.replace(/"(?:\\.|[^"\\])*"|\/\/[^\n]*/g, (m) => m[0] === "\"" ? m : "").replace(/"(?:\\.|[^"\\])*"|,(\s*[}\]])/g, (m, tail) => tail ?? (m[0] === "\"" ? m : ""));
|
|
1119
|
+
}
|
|
1120
|
+
//#endregion
|
|
1121
|
+
//#region src/compat/vendor/pi-model-config.ts
|
|
1122
|
+
/** Immutable, credential-blind models.json snapshot. */
|
|
1123
|
+
const PercentileCutoffsSchema = Type.Object({
|
|
1124
|
+
p50: Type.Optional(Type.Number()),
|
|
1125
|
+
p75: Type.Optional(Type.Number()),
|
|
1126
|
+
p90: Type.Optional(Type.Number()),
|
|
1127
|
+
p99: Type.Optional(Type.Number())
|
|
1128
|
+
});
|
|
1129
|
+
const OpenRouterRoutingSchema = Type.Object({
|
|
1130
|
+
allow_fallbacks: Type.Optional(Type.Boolean()),
|
|
1131
|
+
require_parameters: Type.Optional(Type.Boolean()),
|
|
1132
|
+
data_collection: Type.Optional(Type.Union([Type.Literal("deny"), Type.Literal("allow")])),
|
|
1133
|
+
zdr: Type.Optional(Type.Boolean()),
|
|
1134
|
+
enforce_distillable_text: Type.Optional(Type.Boolean()),
|
|
1135
|
+
order: Type.Optional(Type.Array(Type.String())),
|
|
1136
|
+
only: Type.Optional(Type.Array(Type.String())),
|
|
1137
|
+
ignore: Type.Optional(Type.Array(Type.String())),
|
|
1138
|
+
quantizations: Type.Optional(Type.Array(Type.String())),
|
|
1139
|
+
sort: Type.Optional(Type.Union([Type.String(), Type.Object({
|
|
1140
|
+
by: Type.Optional(Type.String()),
|
|
1141
|
+
partition: Type.Optional(Type.Union([Type.String(), Type.Null()]))
|
|
1142
|
+
})])),
|
|
1143
|
+
max_price: Type.Optional(Type.Object({
|
|
1144
|
+
prompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
1145
|
+
completion: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
1146
|
+
image: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
1147
|
+
audio: Type.Optional(Type.Union([Type.Number(), Type.String()])),
|
|
1148
|
+
request: Type.Optional(Type.Union([Type.Number(), Type.String()]))
|
|
1149
|
+
})),
|
|
1150
|
+
preferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),
|
|
1151
|
+
preferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema]))
|
|
1152
|
+
});
|
|
1153
|
+
const VercelGatewayRoutingSchema = Type.Object({
|
|
1154
|
+
only: Type.Optional(Type.Array(Type.String())),
|
|
1155
|
+
order: Type.Optional(Type.Array(Type.String()))
|
|
1156
|
+
});
|
|
1157
|
+
const ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);
|
|
1158
|
+
const ThinkingLevelMapSchema = Type.Object({
|
|
1159
|
+
off: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1160
|
+
minimal: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1161
|
+
low: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1162
|
+
medium: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1163
|
+
high: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1164
|
+
xhigh: Type.Optional(ThinkingLevelMapValueSchema),
|
|
1165
|
+
max: Type.Optional(ThinkingLevelMapValueSchema)
|
|
1166
|
+
});
|
|
1167
|
+
const ChatTemplateKwargScalarSchema = Type.Union([
|
|
1168
|
+
Type.String(),
|
|
1169
|
+
Type.Number(),
|
|
1170
|
+
Type.Boolean(),
|
|
1171
|
+
Type.Null()
|
|
1172
|
+
]);
|
|
1173
|
+
const ChatTemplateKwargVariableSchema = Type.Object({
|
|
1174
|
+
$var: Type.Union([Type.Literal("thinking.enabled"), Type.Literal("thinking.effort")]),
|
|
1175
|
+
omitWhenOff: Type.Optional(Type.Boolean())
|
|
1176
|
+
});
|
|
1177
|
+
const ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);
|
|
1178
|
+
const OpenAICompletionsCompatSchema = Type.Object({
|
|
1179
|
+
supportsStore: Type.Optional(Type.Boolean()),
|
|
1180
|
+
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
1181
|
+
supportsReasoningEffort: Type.Optional(Type.Boolean()),
|
|
1182
|
+
supportsUsageInStreaming: Type.Optional(Type.Boolean()),
|
|
1183
|
+
maxTokensField: Type.Optional(Type.Union([Type.Literal("max_completion_tokens"), Type.Literal("max_tokens")])),
|
|
1184
|
+
requiresToolResultName: Type.Optional(Type.Boolean()),
|
|
1185
|
+
requiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),
|
|
1186
|
+
requiresThinkingAsText: Type.Optional(Type.Boolean()),
|
|
1187
|
+
requiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),
|
|
1188
|
+
thinkingFormat: Type.Optional(Type.Union([
|
|
1189
|
+
Type.Literal("openai"),
|
|
1190
|
+
Type.Literal("openrouter"),
|
|
1191
|
+
Type.Literal("together"),
|
|
1192
|
+
Type.Literal("baseten"),
|
|
1193
|
+
Type.Literal("deepseek"),
|
|
1194
|
+
Type.Literal("zai"),
|
|
1195
|
+
Type.Literal("qwen"),
|
|
1196
|
+
Type.Literal("chat-template"),
|
|
1197
|
+
Type.Literal("qwen-chat-template"),
|
|
1198
|
+
Type.Literal("string-thinking"),
|
|
1199
|
+
Type.Literal("ant-ling")
|
|
1200
|
+
])),
|
|
1201
|
+
chatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),
|
|
1202
|
+
chatTemplateArgs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),
|
|
1203
|
+
cacheControlFormat: Type.Optional(Type.Literal("anthropic")),
|
|
1204
|
+
openRouterRouting: Type.Optional(OpenRouterRoutingSchema),
|
|
1205
|
+
vercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),
|
|
1206
|
+
supportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),
|
|
1207
|
+
supportsStrictMode: Type.Optional(Type.Boolean()),
|
|
1208
|
+
sendSessionAffinityHeaders: Type.Optional(Type.Boolean()),
|
|
1209
|
+
deferredToolsMode: Type.Optional(Type.Literal("kimi")),
|
|
1210
|
+
sessionAffinityFormat: Type.Optional(Type.Union([
|
|
1211
|
+
Type.Literal("openai"),
|
|
1212
|
+
Type.Literal("openai-nosession"),
|
|
1213
|
+
Type.Literal("openrouter")
|
|
1214
|
+
])),
|
|
1215
|
+
supportsLongCacheRetention: Type.Optional(Type.Boolean())
|
|
1216
|
+
});
|
|
1217
|
+
const OpenAIResponsesCompatSchema = Type.Object({
|
|
1218
|
+
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
1219
|
+
sessionAffinityFormat: Type.Optional(Type.Union([
|
|
1220
|
+
Type.Literal("openai"),
|
|
1221
|
+
Type.Literal("openai-nosession"),
|
|
1222
|
+
Type.Literal("openrouter")
|
|
1223
|
+
])),
|
|
1224
|
+
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
1225
|
+
supportsStrictMode: Type.Optional(Type.Boolean()),
|
|
1226
|
+
supportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),
|
|
1227
|
+
supportsAdditionalTools: Type.Optional(Type.Boolean()),
|
|
1228
|
+
supportsToolSearch: Type.Optional(Type.Boolean())
|
|
1229
|
+
});
|
|
1230
|
+
const AnthropicMessagesCompatSchema = Type.Object({
|
|
1231
|
+
supportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),
|
|
1232
|
+
supportsLongCacheRetention: Type.Optional(Type.Boolean()),
|
|
1233
|
+
sendSessionAffinityHeaders: Type.Optional(Type.Boolean()),
|
|
1234
|
+
supportsCacheControlOnTools: Type.Optional(Type.Boolean()),
|
|
1235
|
+
supportsTemperature: Type.Optional(Type.Boolean()),
|
|
1236
|
+
forceAdaptiveThinking: Type.Optional(Type.Boolean()),
|
|
1237
|
+
allowEmptySignature: Type.Optional(Type.Boolean()),
|
|
1238
|
+
supportsStrictTools: Type.Optional(Type.Boolean()),
|
|
1239
|
+
supportsToolReferences: Type.Optional(Type.Boolean())
|
|
1240
|
+
});
|
|
1241
|
+
const ProviderCompatSchema = Type.Union([
|
|
1242
|
+
OpenAICompletionsCompatSchema,
|
|
1243
|
+
OpenAIResponsesCompatSchema,
|
|
1244
|
+
AnthropicMessagesCompatSchema
|
|
1245
|
+
]);
|
|
1246
|
+
const ModelCostRatesSchema = {
|
|
1247
|
+
input: Type.Number(),
|
|
1248
|
+
output: Type.Number(),
|
|
1249
|
+
cacheRead: Type.Number(),
|
|
1250
|
+
cacheWrite: Type.Number()
|
|
1251
|
+
};
|
|
1252
|
+
const ModelCostTierSchema = Type.Object({
|
|
1253
|
+
inputTokensAbove: Type.Number(),
|
|
1254
|
+
...ModelCostRatesSchema
|
|
1255
|
+
});
|
|
1256
|
+
const ModelCostSchema = Type.Object({
|
|
1257
|
+
...ModelCostRatesSchema,
|
|
1258
|
+
tiers: Type.Optional(Type.Array(ModelCostTierSchema))
|
|
1259
|
+
});
|
|
1260
|
+
const ModelDefinitionSchema = Type.Object({
|
|
1261
|
+
id: Type.String({ minLength: 1 }),
|
|
1262
|
+
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
1263
|
+
api: Type.Optional(Type.String({ minLength: 1 })),
|
|
1264
|
+
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
1265
|
+
reasoning: Type.Optional(Type.Boolean()),
|
|
1266
|
+
thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
|
|
1267
|
+
input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
|
|
1268
|
+
cost: Type.Optional(ModelCostSchema),
|
|
1269
|
+
contextWindow: Type.Optional(Type.Number()),
|
|
1270
|
+
maxTokens: Type.Optional(Type.Number()),
|
|
1271
|
+
samplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
1272
|
+
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
1273
|
+
compat: Type.Optional(ProviderCompatSchema)
|
|
1274
|
+
});
|
|
1275
|
+
const ModelOverrideSchema = Type.Object({
|
|
1276
|
+
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
1277
|
+
reasoning: Type.Optional(Type.Boolean()),
|
|
1278
|
+
thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
|
|
1279
|
+
input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
|
|
1280
|
+
cost: Type.Optional(Type.Object({
|
|
1281
|
+
input: Type.Optional(Type.Number()),
|
|
1282
|
+
output: Type.Optional(Type.Number()),
|
|
1283
|
+
cacheRead: Type.Optional(Type.Number()),
|
|
1284
|
+
cacheWrite: Type.Optional(Type.Number()),
|
|
1285
|
+
tiers: Type.Optional(Type.Array(ModelCostTierSchema))
|
|
1286
|
+
})),
|
|
1287
|
+
contextWindow: Type.Optional(Type.Number()),
|
|
1288
|
+
maxTokens: Type.Optional(Type.Number()),
|
|
1289
|
+
samplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
1290
|
+
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
1291
|
+
compat: Type.Optional(ProviderCompatSchema)
|
|
1292
|
+
});
|
|
1293
|
+
const ProviderConfigSchema = Type.Object({
|
|
1294
|
+
name: Type.Optional(Type.String({ minLength: 1 })),
|
|
1295
|
+
baseUrl: Type.Optional(Type.String({ minLength: 1 })),
|
|
1296
|
+
apiKey: Type.Optional(Type.String({ minLength: 1 })),
|
|
1297
|
+
api: Type.Optional(Type.String({ minLength: 1 })),
|
|
1298
|
+
oauth: Type.Optional(Type.Literal("radius")),
|
|
1299
|
+
headers: Type.Optional(Type.Record(Type.String(), Type.String())),
|
|
1300
|
+
compat: Type.Optional(ProviderCompatSchema),
|
|
1301
|
+
authHeader: Type.Optional(Type.Boolean()),
|
|
1302
|
+
models: Type.Optional(Type.Array(ModelDefinitionSchema)),
|
|
1303
|
+
modelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema))
|
|
1304
|
+
});
|
|
1305
|
+
const ModelsConfigSchema = Type.Object({ providers: Type.Record(Type.String(), ProviderConfigSchema) });
|
|
1306
|
+
const validateModelsConfig = Compile(ModelsConfigSchema);
|
|
1307
|
+
function formatValidationPath(error) {
|
|
1308
|
+
if (error.keyword === "required") {
|
|
1309
|
+
const requiredProperty = error.params.requiredProperties?.[0];
|
|
1310
|
+
if (requiredProperty) {
|
|
1311
|
+
const basePath = error.instancePath.replace(/^\//, "").replace(/\//g, ".");
|
|
1312
|
+
return basePath ? `${basePath}.${requiredProperty}` : requiredProperty;
|
|
1313
|
+
}
|
|
1314
|
+
}
|
|
1315
|
+
return error.instancePath.replace(/^\//, "").replace(/\//g, ".") || "root";
|
|
1316
|
+
}
|
|
1317
|
+
function deepFreeze(value) {
|
|
1318
|
+
if (typeof value !== "object" || value === null || Object.isFrozen(value)) return value;
|
|
1319
|
+
for (const child of Object.values(value)) deepFreeze(child);
|
|
1320
|
+
return Object.freeze(value);
|
|
1321
|
+
}
|
|
1322
|
+
/** One immutable load of models.json. */
|
|
1323
|
+
var ModelConfig = class ModelConfig {
|
|
1324
|
+
providers;
|
|
1325
|
+
error;
|
|
1326
|
+
constructor(providers, error) {
|
|
1327
|
+
this.providers = providers;
|
|
1328
|
+
this.error = error;
|
|
1329
|
+
}
|
|
1330
|
+
static async load(modelsJsonPath) {
|
|
1331
|
+
if (!modelsJsonPath) return new ModelConfig(/* @__PURE__ */ new Map());
|
|
1332
|
+
const path = normalizePath(modelsJsonPath);
|
|
1333
|
+
let content;
|
|
1334
|
+
try {
|
|
1335
|
+
content = await readFile(path, "utf-8");
|
|
1336
|
+
} catch (error) {
|
|
1337
|
+
if (error.code === "ENOENT") return new ModelConfig(/* @__PURE__ */ new Map());
|
|
1338
|
+
return new ModelConfig(/* @__PURE__ */ new Map(), `Failed to load models.json: ${error instanceof Error ? error.message : error}\n\nFile: ${path}`);
|
|
1339
|
+
}
|
|
1340
|
+
let parsed;
|
|
1341
|
+
try {
|
|
1342
|
+
parsed = JSON.parse(stripJsonComments(content));
|
|
1343
|
+
} catch (error) {
|
|
1344
|
+
return new ModelConfig(/* @__PURE__ */ new Map(), `Failed to parse models.json: ${error instanceof Error ? error.message : error}\n\nFile: ${path}`);
|
|
1345
|
+
}
|
|
1346
|
+
if (!validateModelsConfig.Check(parsed)) {
|
|
1347
|
+
const errors = validateModelsConfig.Errors(parsed).map((error) => ` - ${formatValidationPath(error)}: ${error.message}`).join("\n") || "Unknown schema error";
|
|
1348
|
+
return new ModelConfig(/* @__PURE__ */ new Map(), `Invalid models.json schema:\n${errors}\n\nFile: ${path}`);
|
|
1349
|
+
}
|
|
1350
|
+
const config = parsed;
|
|
1351
|
+
const providers = /* @__PURE__ */ new Map();
|
|
1352
|
+
for (const [providerId, provider] of Object.entries(config.providers)) providers.set(providerId, deepFreeze(structuredClone(provider)));
|
|
1353
|
+
return new ModelConfig(providers);
|
|
1354
|
+
}
|
|
1355
|
+
getProvider(providerId) {
|
|
1356
|
+
return this.providers.get(providerId);
|
|
1357
|
+
}
|
|
1358
|
+
getProviderIds() {
|
|
1359
|
+
return [...this.providers.keys()];
|
|
1360
|
+
}
|
|
1361
|
+
getError() {
|
|
1362
|
+
return this.error;
|
|
1363
|
+
}
|
|
1364
|
+
};
|
|
1365
|
+
//#endregion
|
|
1366
|
+
//#region src/compat/vendor/pi-models-compose.ts
|
|
1367
|
+
function mergeCompat(base, override) {
|
|
1368
|
+
if (!override) return base;
|
|
1369
|
+
const merged = {
|
|
1370
|
+
...base,
|
|
1371
|
+
...override
|
|
1372
|
+
};
|
|
1373
|
+
const baseNested = base;
|
|
1374
|
+
const overrideNested = override;
|
|
1375
|
+
const mergedNested = merged;
|
|
1376
|
+
for (const key of [
|
|
1377
|
+
"openRouterRouting",
|
|
1378
|
+
"vercelGatewayRouting",
|
|
1379
|
+
"chatTemplateKwargs",
|
|
1380
|
+
"chatTemplateArgs"
|
|
1381
|
+
]) {
|
|
1382
|
+
const baseValue = baseNested?.[key];
|
|
1383
|
+
const overrideValue = overrideNested[key];
|
|
1384
|
+
if (typeof baseValue === "object" && baseValue !== null || typeof overrideValue === "object" && overrideValue !== null) mergedNested[key] = {
|
|
1385
|
+
...baseValue,
|
|
1386
|
+
...overrideValue
|
|
1387
|
+
};
|
|
1388
|
+
}
|
|
1389
|
+
return merged;
|
|
1390
|
+
}
|
|
1391
|
+
function applyModelOverride(model, override) {
|
|
1392
|
+
return {
|
|
1393
|
+
...model,
|
|
1394
|
+
name: override.name ?? model.name,
|
|
1395
|
+
reasoning: override.reasoning ?? model.reasoning,
|
|
1396
|
+
thinkingLevelMap: override.thinkingLevelMap ? {
|
|
1397
|
+
...model.thinkingLevelMap,
|
|
1398
|
+
...override.thinkingLevelMap
|
|
1399
|
+
} : model.thinkingLevelMap,
|
|
1400
|
+
input: override.input ?? model.input,
|
|
1401
|
+
cost: override.cost ? {
|
|
1402
|
+
input: override.cost.input ?? model.cost.input,
|
|
1403
|
+
output: override.cost.output ?? model.cost.output,
|
|
1404
|
+
cacheRead: override.cost.cacheRead ?? model.cost.cacheRead,
|
|
1405
|
+
cacheWrite: override.cost.cacheWrite ?? model.cost.cacheWrite,
|
|
1406
|
+
tiers: override.cost.tiers ?? model.cost.tiers
|
|
1407
|
+
} : model.cost,
|
|
1408
|
+
contextWindow: override.contextWindow ?? model.contextWindow,
|
|
1409
|
+
maxTokens: override.maxTokens ?? model.maxTokens,
|
|
1410
|
+
samplingParams: override.samplingParams ? {
|
|
1411
|
+
...model.samplingParams,
|
|
1412
|
+
...override.samplingParams
|
|
1413
|
+
} : model.samplingParams,
|
|
1414
|
+
compat: mergeCompat(model.compat, override.compat)
|
|
1415
|
+
};
|
|
1416
|
+
}
|
|
1417
|
+
function modelFromJson(providerId, definition, providerConfig, defaults) {
|
|
1418
|
+
const api = definition.api ?? providerConfig.api ?? defaults?.api;
|
|
1419
|
+
if (!api) throw new Error(`Provider ${providerId}, model ${definition.id}: no "api" specified. Set at provider or model level.`);
|
|
1420
|
+
const baseUrl = definition.baseUrl ?? providerConfig.baseUrl ?? defaults?.baseUrl;
|
|
1421
|
+
if (!baseUrl) throw new Error(`Provider ${providerId}: "baseUrl" is required when defining custom models.`);
|
|
1422
|
+
if (definition.contextWindow !== void 0 && definition.contextWindow <= 0) throw new Error(`Provider ${providerId}, model ${definition.id}: invalid contextWindow`);
|
|
1423
|
+
if (definition.maxTokens !== void 0 && definition.maxTokens <= 0) throw new Error(`Provider ${providerId}, model ${definition.id}: invalid maxTokens`);
|
|
1424
|
+
return {
|
|
1425
|
+
id: definition.id,
|
|
1426
|
+
name: definition.name ?? definition.id,
|
|
1427
|
+
api,
|
|
1428
|
+
provider: providerId,
|
|
1429
|
+
baseUrl,
|
|
1430
|
+
reasoning: definition.reasoning ?? false,
|
|
1431
|
+
thinkingLevelMap: definition.thinkingLevelMap,
|
|
1432
|
+
input: definition.input ?? ["text"],
|
|
1433
|
+
cost: definition.cost ?? {
|
|
1434
|
+
input: 0,
|
|
1435
|
+
output: 0,
|
|
1436
|
+
cacheRead: 0,
|
|
1437
|
+
cacheWrite: 0
|
|
1438
|
+
},
|
|
1439
|
+
contextWindow: definition.contextWindow ?? 128e3,
|
|
1440
|
+
maxTokens: definition.maxTokens ?? 16384,
|
|
1441
|
+
samplingParams: definition.samplingParams,
|
|
1442
|
+
headers: void 0,
|
|
1443
|
+
compat: mergeCompat(providerConfig.compat, definition.compat)
|
|
1444
|
+
};
|
|
1445
|
+
}
|
|
1446
|
+
function applyModelsJson(providerId, baseModels, config) {
|
|
1447
|
+
if (!config) return [...baseModels];
|
|
1448
|
+
if (config.oauth && !config.baseUrl) throw new Error(`Provider ${providerId}: "baseUrl" is required when "oauth" is set.`);
|
|
1449
|
+
const hasOverrides = config.modelOverrides && Object.keys(config.modelOverrides).length > 0;
|
|
1450
|
+
if (!config.models?.length && !config.baseUrl && !config.headers && !config.compat && !hasOverrides && !config.apiKey && !config.oauth && config.authHeader === void 0) throw new Error(`Provider ${providerId}: must specify "baseUrl", "headers", "compat", "modelOverrides", or "models".`);
|
|
1451
|
+
const models = baseModels.map((model) => ({
|
|
1452
|
+
...model,
|
|
1453
|
+
baseUrl: config.oauth === "radius" ? model.baseUrl : config.baseUrl ?? model.baseUrl,
|
|
1454
|
+
compat: mergeCompat(model.compat, config.compat)
|
|
1455
|
+
}));
|
|
1456
|
+
for (const definition of config.models ?? []) {
|
|
1457
|
+
const existingIndex = models.findIndex((model) => model.id === definition.id);
|
|
1458
|
+
const model = modelFromJson(providerId, definition, config, existingIndex >= 0 ? models[existingIndex] : models[0]);
|
|
1459
|
+
if (existingIndex >= 0) models[existingIndex] = model;
|
|
1460
|
+
else models.push(model);
|
|
1461
|
+
}
|
|
1462
|
+
return models;
|
|
1463
|
+
}
|
|
1464
|
+
//#endregion
|
|
1465
|
+
//#region src/compat/vendor/pi-shell-config.ts
|
|
1466
|
+
function isLegacyWslBashPath(path) {
|
|
1467
|
+
const normalized = path.replace(/\//g, "\\").toLowerCase();
|
|
1468
|
+
return /^[a-z]:\\windows\\(?:system32|sysnative)\\bash\.exe$/.test(normalized);
|
|
1469
|
+
}
|
|
1470
|
+
function getBashShellConfig(shell) {
|
|
1471
|
+
return isLegacyWslBashPath(shell) ? {
|
|
1472
|
+
shell,
|
|
1473
|
+
args: ["-s"],
|
|
1474
|
+
commandTransport: "stdin"
|
|
1475
|
+
} : {
|
|
1476
|
+
shell,
|
|
1477
|
+
args: ["-c"]
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1480
|
+
function findBashOnPath() {
|
|
1481
|
+
if (process.platform === "win32") {
|
|
1482
|
+
try {
|
|
1483
|
+
const result = spawnSync("where", ["bash.exe"], {
|
|
1484
|
+
encoding: "utf-8",
|
|
1485
|
+
timeout: 5e3,
|
|
1486
|
+
windowsHide: true
|
|
1487
|
+
});
|
|
1488
|
+
if (result.status === 0 && result.stdout) {
|
|
1489
|
+
const firstMatch = result.stdout.trim().split(/\r?\n/)[0];
|
|
1490
|
+
if (firstMatch && existsSync(firstMatch)) return firstMatch;
|
|
1491
|
+
}
|
|
1492
|
+
} catch {}
|
|
1493
|
+
return null;
|
|
1494
|
+
}
|
|
1495
|
+
try {
|
|
1496
|
+
const result = spawnSync("which", ["bash"], {
|
|
1497
|
+
encoding: "utf-8",
|
|
1498
|
+
timeout: 5e3
|
|
1499
|
+
});
|
|
1500
|
+
if (result.status === 0 && result.stdout) {
|
|
1501
|
+
const firstMatch = result.stdout.trim().split(/\r?\n/)[0];
|
|
1502
|
+
if (firstMatch) return firstMatch;
|
|
1503
|
+
}
|
|
1504
|
+
} catch {}
|
|
1505
|
+
return null;
|
|
1506
|
+
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Resolve shell configuration based on platform and an optional explicit shell path.
|
|
1509
|
+
* Resolution order:
|
|
1510
|
+
* 1. User-specified shellPath
|
|
1511
|
+
* 2. On Windows: Git Bash in known locations, then bash on PATH
|
|
1512
|
+
* 3. On Unix: /bin/bash, then bash on PATH, then fallback to sh
|
|
1513
|
+
*/
|
|
1514
|
+
function getShellConfig(customShellPath) {
|
|
1515
|
+
if (customShellPath) {
|
|
1516
|
+
if (existsSync(customShellPath)) return getBashShellConfig(customShellPath);
|
|
1517
|
+
throw new Error(`Custom shell path not found: ${customShellPath}`);
|
|
1518
|
+
}
|
|
1519
|
+
if (process.platform === "win32") {
|
|
1520
|
+
const paths = [];
|
|
1521
|
+
const programFiles = process.env.ProgramFiles;
|
|
1522
|
+
if (programFiles) paths.push(`${programFiles}\\Git\\bin\\bash.exe`);
|
|
1523
|
+
const programFilesX86 = process.env["ProgramFiles(x86)"];
|
|
1524
|
+
if (programFilesX86) paths.push(`${programFilesX86}\\Git\\bin\\bash.exe`);
|
|
1525
|
+
for (const path of paths) if (existsSync(path)) return getBashShellConfig(path);
|
|
1526
|
+
const bashOnPath = findBashOnPath();
|
|
1527
|
+
if (bashOnPath) return getBashShellConfig(bashOnPath);
|
|
1528
|
+
throw new Error(`No bash shell found. Options:
|
|
1529
|
+
1. Install Git for Windows: https://git-scm.com/download/win
|
|
1530
|
+
2. Add your bash to PATH (Cygwin, MSYS2, etc.)
|
|
1531
|
+
3. Set shellPath in settings.json
|
|
1532
|
+
|
|
1533
|
+
Searched Git Bash in:\n${paths.map((p) => ` ${p}`).join("\n")}`);
|
|
1534
|
+
}
|
|
1535
|
+
if (existsSync("/bin/bash")) return getBashShellConfig("/bin/bash");
|
|
1536
|
+
const bashOnPath = findBashOnPath();
|
|
1537
|
+
if (bashOnPath) return getBashShellConfig(bashOnPath);
|
|
1538
|
+
return {
|
|
1539
|
+
shell: "sh",
|
|
1540
|
+
args: ["-c"]
|
|
1541
|
+
};
|
|
1542
|
+
}
|
|
1543
|
+
//#endregion
|
|
1544
|
+
//#region src/compat/vendor/pi-resolve-config-value.ts
|
|
1545
|
+
/**
|
|
1546
|
+
* Resolve configuration values that may be shell commands, environment variables, or literals.
|
|
1547
|
+
* Used by auth-storage.ts and model-registry.ts.
|
|
1548
|
+
*/
|
|
1549
|
+
const ENV_VAR_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
1550
|
+
const ENV_VAR_NAME_PREFIX_RE = /^[A-Za-z_][A-Za-z0-9_]*/;
|
|
1551
|
+
function appendLiteral(parts, value) {
|
|
1552
|
+
if (!value) return;
|
|
1553
|
+
const previousPart = parts[parts.length - 1];
|
|
1554
|
+
if (previousPart?.type === "literal") {
|
|
1555
|
+
previousPart.value += value;
|
|
1556
|
+
return;
|
|
1557
|
+
}
|
|
1558
|
+
parts.push({
|
|
1559
|
+
type: "literal",
|
|
1560
|
+
value
|
|
1561
|
+
});
|
|
1562
|
+
}
|
|
1563
|
+
function parseConfigValueTemplate(config) {
|
|
1564
|
+
const parts = [];
|
|
1565
|
+
let index = 0;
|
|
1566
|
+
while (index < config.length) {
|
|
1567
|
+
const dollarIndex = config.indexOf("$", index);
|
|
1568
|
+
if (dollarIndex < 0) {
|
|
1569
|
+
appendLiteral(parts, config.slice(index));
|
|
1570
|
+
break;
|
|
1571
|
+
}
|
|
1572
|
+
appendLiteral(parts, config.slice(index, dollarIndex));
|
|
1573
|
+
const nextChar = config[dollarIndex + 1];
|
|
1574
|
+
if (nextChar === "$" || nextChar === "!") {
|
|
1575
|
+
appendLiteral(parts, nextChar);
|
|
1576
|
+
index = dollarIndex + 2;
|
|
1577
|
+
continue;
|
|
1578
|
+
}
|
|
1579
|
+
if (nextChar === "{") {
|
|
1580
|
+
const endIndex = config.indexOf("}", dollarIndex + 2);
|
|
1581
|
+
if (endIndex < 0) {
|
|
1582
|
+
appendLiteral(parts, "$");
|
|
1583
|
+
index = dollarIndex + 1;
|
|
1584
|
+
continue;
|
|
1585
|
+
}
|
|
1586
|
+
const name = config.slice(dollarIndex + 2, endIndex);
|
|
1587
|
+
if (ENV_VAR_NAME_RE.test(name)) parts.push({
|
|
1588
|
+
type: "env",
|
|
1589
|
+
name
|
|
1590
|
+
});
|
|
1591
|
+
else appendLiteral(parts, config.slice(dollarIndex, endIndex + 1));
|
|
1592
|
+
index = endIndex + 1;
|
|
1593
|
+
continue;
|
|
1594
|
+
}
|
|
1595
|
+
const match = config.slice(dollarIndex + 1).match(ENV_VAR_NAME_PREFIX_RE);
|
|
1596
|
+
if (match) {
|
|
1597
|
+
parts.push({
|
|
1598
|
+
type: "env",
|
|
1599
|
+
name: match[0]
|
|
1600
|
+
});
|
|
1601
|
+
index = dollarIndex + 1 + match[0].length;
|
|
1602
|
+
continue;
|
|
1603
|
+
}
|
|
1604
|
+
appendLiteral(parts, "$");
|
|
1605
|
+
index = dollarIndex + 1;
|
|
1606
|
+
}
|
|
1607
|
+
return parts;
|
|
1608
|
+
}
|
|
1609
|
+
function parseConfigValueReference(config) {
|
|
1610
|
+
if (config.startsWith("!")) return {
|
|
1611
|
+
type: "command",
|
|
1612
|
+
config
|
|
1613
|
+
};
|
|
1614
|
+
return {
|
|
1615
|
+
type: "template",
|
|
1616
|
+
parts: parseConfigValueTemplate(config)
|
|
1617
|
+
};
|
|
1618
|
+
}
|
|
1619
|
+
function resolveEnvConfigValue(name, env) {
|
|
1620
|
+
return env?.[name] || process.env[name] || void 0;
|
|
1621
|
+
}
|
|
1622
|
+
function getTemplateEnvVarNames(parts) {
|
|
1623
|
+
const names = [];
|
|
1624
|
+
for (const part of parts) {
|
|
1625
|
+
if (part.type !== "env" || names.includes(part.name)) continue;
|
|
1626
|
+
names.push(part.name);
|
|
1627
|
+
}
|
|
1628
|
+
return names;
|
|
1629
|
+
}
|
|
1630
|
+
function resolveTemplate(parts, env) {
|
|
1631
|
+
let resolved = "";
|
|
1632
|
+
for (const part of parts) {
|
|
1633
|
+
if (part.type === "literal") {
|
|
1634
|
+
resolved += part.value;
|
|
1635
|
+
continue;
|
|
1636
|
+
}
|
|
1637
|
+
const envValue = resolveEnvConfigValue(part.name, env);
|
|
1638
|
+
if (envValue === void 0) return void 0;
|
|
1639
|
+
resolved += envValue;
|
|
1640
|
+
}
|
|
1641
|
+
return resolved;
|
|
1642
|
+
}
|
|
1643
|
+
function getConfigValueEnvVarNames(config) {
|
|
1644
|
+
const reference = parseConfigValueReference(config);
|
|
1645
|
+
return reference.type === "template" ? getTemplateEnvVarNames(reference.parts) : [];
|
|
1646
|
+
}
|
|
1647
|
+
function getMissingConfigValueEnvVarNames(config, env) {
|
|
1648
|
+
return getConfigValueEnvVarNames(config).filter((name) => resolveEnvConfigValue(name, env) === void 0);
|
|
1649
|
+
}
|
|
1650
|
+
function isCommandConfigValue(config) {
|
|
1651
|
+
return parseConfigValueReference(config).type === "command";
|
|
1652
|
+
}
|
|
1653
|
+
function isConfigValueConfigured(config, env) {
|
|
1654
|
+
return getMissingConfigValueEnvVarNames(config, env).length === 0;
|
|
1655
|
+
}
|
|
1656
|
+
function executeWithConfiguredShell(command) {
|
|
1657
|
+
try {
|
|
1658
|
+
const { shell, args, commandTransport } = getShellConfig();
|
|
1659
|
+
const commandFromStdin = commandTransport === "stdin";
|
|
1660
|
+
const result = spawnSync(shell, commandFromStdin ? args : [...args, command], {
|
|
1661
|
+
encoding: "utf-8",
|
|
1662
|
+
input: commandFromStdin ? command : void 0,
|
|
1663
|
+
timeout: 1e4,
|
|
1664
|
+
stdio: [
|
|
1665
|
+
commandFromStdin ? "pipe" : "ignore",
|
|
1666
|
+
"pipe",
|
|
1667
|
+
"ignore"
|
|
1668
|
+
],
|
|
1669
|
+
shell: false,
|
|
1670
|
+
windowsHide: true
|
|
1671
|
+
});
|
|
1672
|
+
if (result.error) {
|
|
1673
|
+
if (result.error.code === "ENOENT") return {
|
|
1674
|
+
executed: false,
|
|
1675
|
+
value: void 0
|
|
1676
|
+
};
|
|
1677
|
+
return {
|
|
1678
|
+
executed: true,
|
|
1679
|
+
value: void 0
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1682
|
+
if (result.status !== 0) return {
|
|
1683
|
+
executed: true,
|
|
1684
|
+
value: void 0
|
|
1685
|
+
};
|
|
1686
|
+
return {
|
|
1687
|
+
executed: true,
|
|
1688
|
+
value: (result.stdout ?? "").trim() || void 0
|
|
1689
|
+
};
|
|
1690
|
+
} catch {
|
|
1691
|
+
return {
|
|
1692
|
+
executed: false,
|
|
1693
|
+
value: void 0
|
|
1694
|
+
};
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
function executeWithDefaultShell(command) {
|
|
1698
|
+
try {
|
|
1699
|
+
return execSync(command, {
|
|
1700
|
+
encoding: "utf-8",
|
|
1701
|
+
timeout: 1e4,
|
|
1702
|
+
stdio: [
|
|
1703
|
+
"ignore",
|
|
1704
|
+
"pipe",
|
|
1705
|
+
"ignore"
|
|
1706
|
+
]
|
|
1707
|
+
}).trim() || void 0;
|
|
1708
|
+
} catch {
|
|
1709
|
+
return;
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
function executeCommandUncached(commandConfig) {
|
|
1713
|
+
const command = commandConfig.slice(1);
|
|
1714
|
+
return process.platform === "win32" ? (() => {
|
|
1715
|
+
const configuredResult = executeWithConfiguredShell(command);
|
|
1716
|
+
return configuredResult.executed ? configuredResult.value : executeWithDefaultShell(command);
|
|
1717
|
+
})() : executeWithDefaultShell(command);
|
|
1718
|
+
}
|
|
1719
|
+
/**
|
|
1720
|
+
* Resolve all header values using the same resolution logic as API keys.
|
|
1721
|
+
*/
|
|
1722
|
+
function resolveConfigValueUncached(config, env) {
|
|
1723
|
+
const reference = parseConfigValueReference(config);
|
|
1724
|
+
if (reference.type === "command") return executeCommandUncached(reference.config);
|
|
1725
|
+
return resolveTemplate(reference.parts, env);
|
|
1726
|
+
}
|
|
1727
|
+
function resolveConfigValueOrThrow(config, description, env) {
|
|
1728
|
+
const resolvedValue = resolveConfigValueUncached(config, env);
|
|
1729
|
+
if (resolvedValue !== void 0) return resolvedValue;
|
|
1730
|
+
const reference = parseConfigValueReference(config);
|
|
1731
|
+
if (reference.type === "command") throw new Error(`Failed to resolve ${description} from shell command: ${reference.config.slice(1)}`);
|
|
1732
|
+
if (reference.type === "template") {
|
|
1733
|
+
const missingEnvVars = getMissingConfigValueEnvVarNames(config, env);
|
|
1734
|
+
if (missingEnvVars.length === 1) throw new Error(`Failed to resolve ${description} from environment variable: ${missingEnvVars[0]}`);
|
|
1735
|
+
if (missingEnvVars.length > 1) throw new Error(`Failed to resolve ${description} from environment variables: ${missingEnvVars.join(", ")}`);
|
|
1736
|
+
}
|
|
1737
|
+
throw new Error(`Failed to resolve ${description}`);
|
|
1738
|
+
}
|
|
1739
|
+
function resolveHeadersOrThrow(headers, description, env) {
|
|
1740
|
+
if (!headers) return void 0;
|
|
1741
|
+
const resolved = {};
|
|
1742
|
+
for (const [key, value] of Object.entries(headers)) resolved[key] = resolveConfigValueOrThrow(value, `${description} header "${key}"`, env);
|
|
1743
|
+
return Object.keys(resolved).length > 0 ? resolved : void 0;
|
|
1744
|
+
}
|
|
1745
|
+
//#endregion
|
|
1746
|
+
//#region src/models-json.ts
|
|
1747
|
+
function modelsJsonPath() {
|
|
1748
|
+
return join(getAgentDir(), "models.json");
|
|
1749
|
+
}
|
|
1750
|
+
const emptySnapshot = () => ({
|
|
1751
|
+
models: [],
|
|
1752
|
+
providers: /* @__PURE__ */ new Map(),
|
|
1753
|
+
errors: []
|
|
1754
|
+
});
|
|
1755
|
+
/**
|
|
1756
|
+
* One load of models.json projected to Pi Model objects. Mirrors Pi's
|
|
1757
|
+
* composeModelProvider composition order: base (builtin) models →
|
|
1758
|
+
* applyModelsJson upserts → modelOverrides as the topmost user-config layer.
|
|
1759
|
+
* A provider that fails composition contributes an error and is skipped —
|
|
1760
|
+
* the same per-entry isolation the rest of the bridge applies to extensions.
|
|
1761
|
+
*/
|
|
1762
|
+
async function loadModelsJsonSnapshot(baseProviderOf) {
|
|
1763
|
+
const snapshot = emptySnapshot();
|
|
1764
|
+
const config = await ModelConfig.load(modelsJsonPath());
|
|
1765
|
+
const loadError = config.getError();
|
|
1766
|
+
if (loadError !== void 0) {
|
|
1767
|
+
snapshot.errors.push(loadError);
|
|
1768
|
+
return snapshot;
|
|
1769
|
+
}
|
|
1770
|
+
for (const providerId of config.getProviderIds()) {
|
|
1771
|
+
const providerConfig = config.getProvider(providerId);
|
|
1772
|
+
if (providerConfig === void 0) continue;
|
|
1773
|
+
try {
|
|
1774
|
+
const base = await baseProviderOf?.(providerId);
|
|
1775
|
+
const composed = applyModelsJson(providerId, typeof base?.getModels === "function" ? base.getModels() : [], providerConfig).map((model) => {
|
|
1776
|
+
const override = providerConfig.modelOverrides?.[String(model.id)];
|
|
1777
|
+
return override ? applyModelOverride(model, override) : model;
|
|
1778
|
+
});
|
|
1779
|
+
snapshot.models.push(...composed);
|
|
1780
|
+
snapshot.providers.set(providerId, providerConfig);
|
|
1781
|
+
} catch (error) {
|
|
1782
|
+
snapshot.errors.push(error instanceof Error ? error.message : String(error));
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
return snapshot;
|
|
1786
|
+
}
|
|
1787
|
+
/**
|
|
1788
|
+
* Pi's configured-auth answer for a models.json provider, following
|
|
1789
|
+
* composeApiKeyAuth.resolve + withConfiguredAuth and the registry's
|
|
1790
|
+
* translation of their failures:
|
|
1791
|
+
* - a configured apiKey resolves through $ENV/!command or fails loudly with
|
|
1792
|
+
* the resolver's message;
|
|
1793
|
+
* - authHeader folds the resolved key into an Authorization header and,
|
|
1794
|
+
* without a key, becomes Pi's "No API key found" answer;
|
|
1795
|
+
* - a provider with neither key nor authHeader answers with its resolved
|
|
1796
|
+
* headers only (the registry's compatibility path).
|
|
1797
|
+
*/
|
|
1798
|
+
function resolveModelsJsonAuth(providerId, provider) {
|
|
1799
|
+
try {
|
|
1800
|
+
const headers = resolveHeadersOrThrow(provider.headers, `provider "${providerId}"`);
|
|
1801
|
+
const rawKey = provider.apiKey;
|
|
1802
|
+
if (rawKey === void 0) {
|
|
1803
|
+
if (provider.authHeader ?? false) return {
|
|
1804
|
+
ok: false,
|
|
1805
|
+
error: `No API key found for "${providerId}"`
|
|
1806
|
+
};
|
|
1807
|
+
return {
|
|
1808
|
+
ok: true,
|
|
1809
|
+
...headers === void 0 ? {} : { headers }
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
const apiKey = resolveConfigValueOrThrow(rawKey, `API key for provider "${providerId}"`);
|
|
1813
|
+
const merged = provider.authHeader ?? false ? {
|
|
1814
|
+
...headers,
|
|
1815
|
+
Authorization: `Bearer ${apiKey}`
|
|
1816
|
+
} : headers;
|
|
1817
|
+
return {
|
|
1818
|
+
ok: true,
|
|
1819
|
+
apiKey,
|
|
1820
|
+
...merged === void 0 ? {} : { headers: merged }
|
|
1821
|
+
};
|
|
1822
|
+
} catch (error) {
|
|
1823
|
+
return {
|
|
1824
|
+
ok: false,
|
|
1825
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1826
|
+
};
|
|
1827
|
+
}
|
|
1828
|
+
}
|
|
1829
|
+
/**
|
|
1830
|
+
* Pi's withConfiguredAuth layered over an auth resolved by another family
|
|
1831
|
+
* (an extension-registered provider or a builtin): models.json headers
|
|
1832
|
+
* override the resolved ones, and authHeader folds the resolved key into
|
|
1833
|
+
* an Authorization header — failing loudly without one, as Pi does.
|
|
1834
|
+
*/
|
|
1835
|
+
function applyModelsJsonConfiguredAuth(providerId, provider, auth) {
|
|
1836
|
+
try {
|
|
1837
|
+
const configured = resolveHeadersOrThrow(provider.headers, `provider "${providerId}"`);
|
|
1838
|
+
let headers = auth.headers || configured ? {
|
|
1839
|
+
...auth.headers,
|
|
1840
|
+
...configured
|
|
1841
|
+
} : void 0;
|
|
1842
|
+
if (provider.authHeader ?? false) {
|
|
1843
|
+
if (auth.apiKey === void 0) return {
|
|
1844
|
+
ok: false,
|
|
1845
|
+
error: `No API key found for "${providerId}"`
|
|
1846
|
+
};
|
|
1847
|
+
headers = {
|
|
1848
|
+
...headers,
|
|
1849
|
+
Authorization: `Bearer ${auth.apiKey}`
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1852
|
+
return {
|
|
1853
|
+
ok: true,
|
|
1854
|
+
...auth.apiKey === void 0 ? {} : { apiKey: auth.apiKey },
|
|
1855
|
+
...headers === void 0 ? {} : { headers }
|
|
1856
|
+
};
|
|
1857
|
+
} catch (error) {
|
|
1858
|
+
return {
|
|
1859
|
+
ok: false,
|
|
1860
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1861
|
+
};
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
/**
|
|
1865
|
+
* One models.json provider as a Pi Provider object: the composed Pi Models
|
|
1866
|
+
* as its catalog and Pi's per-api wire clients as its transport (attached by
|
|
1867
|
+
* the provider adapter's synthesis). Registered as a DSH llm route, this
|
|
1868
|
+
* makes the DSH directory the single model directory — the Pi registry
|
|
1869
|
+
* projects it back, and registry.getProvider() answers a genuine Pi
|
|
1870
|
+
* Provider, so packages that stream through the provider surface work
|
|
1871
|
+
* unchanged.
|
|
1872
|
+
*/
|
|
1873
|
+
function modelsJsonPiProvider(providerId, provider, models) {
|
|
1874
|
+
return {
|
|
1875
|
+
id: providerId,
|
|
1876
|
+
name: provider.name ?? providerId,
|
|
1877
|
+
...provider.baseUrl === void 0 ? {} : { baseUrl: provider.baseUrl },
|
|
1878
|
+
...provider.api === void 0 ? {} : { api: provider.api },
|
|
1879
|
+
getModels: () => models
|
|
1880
|
+
};
|
|
1881
|
+
}
|
|
1882
|
+
/**
|
|
1883
|
+
* Pi's configured-check (not liveness) for a models.json provider — the
|
|
1884
|
+
* configuredRequestAuthStatus semantics: a literal or !command key counts as
|
|
1885
|
+
* configured, a templated key counts only when its env vars are present, and
|
|
1886
|
+
* a provider without an apiKey defers to the other credential families.
|
|
1887
|
+
*/
|
|
1888
|
+
function modelsJsonAuthConfigured(provider) {
|
|
1889
|
+
const value = provider.apiKey;
|
|
1890
|
+
if (value === void 0) return void 0;
|
|
1891
|
+
if (isCommandConfigValue(value)) return true;
|
|
1892
|
+
if (getConfigValueEnvVarNames(value).length > 0) return isConfigValueConfigured(value);
|
|
1893
|
+
return true;
|
|
1894
|
+
}
|
|
1895
|
+
//#endregion
|
|
1099
1896
|
//#region src/provider-adapter.ts
|
|
1897
|
+
const PI_API_FACTORIES = {
|
|
1898
|
+
"openai-completions": openAICompletionsApi,
|
|
1899
|
+
"openai-responses": openAIResponsesApi,
|
|
1900
|
+
"anthropic-messages": anthropicMessagesApi
|
|
1901
|
+
};
|
|
1902
|
+
function piApiClientFor(api) {
|
|
1903
|
+
const factory = typeof api === "string" ? PI_API_FACTORIES[api] : void 0;
|
|
1904
|
+
return factory === void 0 ? void 0 : factory();
|
|
1905
|
+
}
|
|
1906
|
+
/**
|
|
1907
|
+
* Give a config-only Pi provider (models.json entries, packages that declare
|
|
1908
|
+
* models without a stream) Pi's own transport: each call dispatches on the
|
|
1909
|
+
* model's declared `api` to the real pi-ai client, exactly as Pi's
|
|
1910
|
+
* provider composer does. Undispatchable providers (no models, or an api
|
|
1911
|
+
* with no client) answer undefined and stay off the directory.
|
|
1912
|
+
*/
|
|
1913
|
+
function withSynthesizedTransport(provider) {
|
|
1914
|
+
const models = typeof provider.getModels === "function" ? provider.getModels() : Array.isArray(provider.models) ? provider.models : [];
|
|
1915
|
+
if (models.length === 0) return void 0;
|
|
1916
|
+
if (!models.some((model) => piApiClientFor(model.api) !== void 0)) return void 0;
|
|
1917
|
+
const dispatch = (simple) => (model, context, options) => {
|
|
1918
|
+
const client = piApiClientFor(model.api);
|
|
1919
|
+
if (client === void 0) throw new Error(`pi2dsh: no wire-protocol client for api ${JSON.stringify(String(model.api))} (model ${String(model.provider)}/${String(model.id)})`);
|
|
1920
|
+
return (simple ? client.streamSimple ?? client.stream : client.stream).call(client, model, context, options);
|
|
1921
|
+
};
|
|
1922
|
+
return {
|
|
1923
|
+
...provider,
|
|
1924
|
+
getModels: () => models,
|
|
1925
|
+
stream: dispatch(false),
|
|
1926
|
+
streamSimple: dispatch(true)
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1100
1929
|
function providerCarriesTransport(value) {
|
|
1101
1930
|
return typeof value?.stream === "function";
|
|
1102
1931
|
}
|
|
@@ -1108,6 +1937,22 @@ function providerModels(provider) {
|
|
|
1108
1937
|
return [];
|
|
1109
1938
|
}
|
|
1110
1939
|
}
|
|
1940
|
+
const PI_CARRIED_FIELDS = [
|
|
1941
|
+
"api",
|
|
1942
|
+
"baseUrl",
|
|
1943
|
+
"cost",
|
|
1944
|
+
"contextWindow",
|
|
1945
|
+
"maxTokens",
|
|
1946
|
+
"samplingParams",
|
|
1947
|
+
"thinkingLevelMap",
|
|
1948
|
+
"compat",
|
|
1949
|
+
"headers"
|
|
1950
|
+
];
|
|
1951
|
+
function piCarriedFields(model) {
|
|
1952
|
+
const carried = {};
|
|
1953
|
+
for (const field of PI_CARRIED_FIELDS) if (model[field] !== void 0) carried[field] = model[field];
|
|
1954
|
+
return carried;
|
|
1955
|
+
}
|
|
1111
1956
|
/**
|
|
1112
1957
|
* Wrap one Pi provider object as a DSH LlmAdapter-shaped route handler.
|
|
1113
1958
|
* Structural typing carries it through `llm.registerAdapter`.
|
|
@@ -1120,6 +1965,7 @@ function piProviderDshAdapter(providerId, provider, host) {
|
|
|
1120
1965
|
}),
|
|
1121
1966
|
providerRetryPolicy: () => void 0,
|
|
1122
1967
|
listModels: async (id) => providerModels(provider).map((model) => ({
|
|
1968
|
+
...piCarriedFields(model),
|
|
1123
1969
|
provider: id,
|
|
1124
1970
|
id: String(model.id ?? ""),
|
|
1125
1971
|
name: String(model.name ?? model.id ?? ""),
|
|
@@ -1128,6 +1974,7 @@ function piProviderDshAdapter(providerId, provider, host) {
|
|
|
1128
1974
|
resolveModel: async (id, modelId) => {
|
|
1129
1975
|
const known = providerModels(provider).find((model) => model.id === modelId);
|
|
1130
1976
|
return {
|
|
1977
|
+
...known === void 0 ? {} : piCarriedFields(known),
|
|
1131
1978
|
provider: id,
|
|
1132
1979
|
id: modelId,
|
|
1133
1980
|
name: String(known?.name ?? modelId),
|
|
@@ -1156,17 +2003,20 @@ function piProviderDshAdapter(providerId, provider, host) {
|
|
|
1156
2003
|
};
|
|
1157
2004
|
}
|
|
1158
2005
|
/**
|
|
1159
|
-
* Register the provider as a live DSH route when
|
|
1160
|
-
*
|
|
1161
|
-
*
|
|
1162
|
-
*
|
|
2006
|
+
* Register the provider as a live DSH route when an llm service is mounted.
|
|
2007
|
+
* A provider carrying its own transport streams through it; a config-only
|
|
2008
|
+
* provider gets Pi's synthesized per-api transport. A route conflict (an
|
|
2009
|
+
* adapter already owns the name — e.g. a deployment-configured `deepseek`)
|
|
2010
|
+
* keeps the existing route and reports the skip.
|
|
1163
2011
|
* @returns the route disposer, or undefined when nothing was registered.
|
|
1164
2012
|
*/
|
|
1165
2013
|
function registerPiProviderRoute(options) {
|
|
1166
2014
|
const { llm, providerId, provider, host } = options;
|
|
1167
|
-
if (llm === void 0
|
|
2015
|
+
if (llm === void 0) return void 0;
|
|
2016
|
+
const transport = providerCarriesTransport(provider) ? provider : withSynthesizedTransport(provider);
|
|
2017
|
+
if (transport === void 0) return void 0;
|
|
1168
2018
|
try {
|
|
1169
|
-
return llm.registerAdapter([providerId], piProviderDshAdapter(providerId,
|
|
2019
|
+
return llm.registerAdapter([providerId], piProviderDshAdapter(providerId, transport, host));
|
|
1170
2020
|
} catch (error) {
|
|
1171
2021
|
host.warn(`[pi2dsh] Pi provider ${JSON.stringify(providerId)} was not added as a DSH llm route (${error instanceof Error ? error.message : String(error)}); the existing route keeps the name`);
|
|
1172
2022
|
return;
|
|
@@ -1428,7 +2278,7 @@ function currentPiModel(state, agent) {
|
|
|
1428
2278
|
id,
|
|
1429
2279
|
name: id,
|
|
1430
2280
|
provider,
|
|
1431
|
-
api: "
|
|
2281
|
+
api: "faux",
|
|
1432
2282
|
input: ["text"],
|
|
1433
2283
|
reasoning: false
|
|
1434
2284
|
};
|
|
@@ -1518,28 +2368,43 @@ function contextFor(ctx, state, agent, signal, command = false) {
|
|
|
1518
2368
|
const session = agentSession(agent);
|
|
1519
2369
|
const providerConfig = (name) => state.providers.get(name);
|
|
1520
2370
|
const catalog = state.modelCatalog;
|
|
1521
|
-
const
|
|
1522
|
-
const
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
}
|
|
1530
|
-
if (!Array.isArray(models)) continue;
|
|
1531
|
-
for (const model of models) out.push({
|
|
1532
|
-
...model,
|
|
1533
|
-
provider: String(model.provider ?? key)
|
|
1534
|
-
});
|
|
2371
|
+
const piNativeEntry = (provider, id) => {
|
|
2372
|
+
const source = state.modelsJsonProviders.get(provider) ?? (state.providerRouteDisposers.has(provider) ? state.providers.get(provider) : void 0);
|
|
2373
|
+
if (source === void 0) return void 0;
|
|
2374
|
+
let models;
|
|
2375
|
+
try {
|
|
2376
|
+
models = typeof source.getModels === "function" ? source.getModels() : source.models;
|
|
2377
|
+
} catch {
|
|
2378
|
+
return;
|
|
1535
2379
|
}
|
|
1536
|
-
return
|
|
2380
|
+
if (!Array.isArray(models)) return void 0;
|
|
2381
|
+
return models.find((model) => model.id === id);
|
|
1537
2382
|
};
|
|
1538
|
-
const
|
|
1539
|
-
const
|
|
1540
|
-
|
|
1541
|
-
|
|
2383
|
+
const restorePiShape = (entry) => {
|
|
2384
|
+
const native = piNativeEntry(String(entry.provider ?? ""), String(entry.id ?? ""));
|
|
2385
|
+
return native === void 0 ? entry : {
|
|
2386
|
+
...entry,
|
|
2387
|
+
...native,
|
|
2388
|
+
provider: entry.provider
|
|
2389
|
+
};
|
|
1542
2390
|
};
|
|
2391
|
+
const allModels = () => (catalog?.all() ?? []).map(restorePiShape);
|
|
2392
|
+
const dshRoutedStream = (model, context, options) => {
|
|
2393
|
+
const llm = llmOf(ctx);
|
|
2394
|
+
if (llm === void 0) throw new Error("pi2dsh: model calls need a DSH llm service; this composition mounts none");
|
|
2395
|
+
return streamViaDshLlm(llm, {
|
|
2396
|
+
model,
|
|
2397
|
+
context,
|
|
2398
|
+
options
|
|
2399
|
+
});
|
|
2400
|
+
};
|
|
2401
|
+
const dshRoutedPiProvider = (base, providerId) => ({
|
|
2402
|
+
...base,
|
|
2403
|
+
id: providerId,
|
|
2404
|
+
getModels: () => allModels().filter((model) => model.provider === providerId),
|
|
2405
|
+
stream: dshRoutedStream,
|
|
2406
|
+
streamSimple: dshRoutedStream
|
|
2407
|
+
});
|
|
1543
2408
|
const base = {
|
|
1544
2409
|
ui,
|
|
1545
2410
|
mode: "rpc",
|
|
@@ -1552,15 +2417,28 @@ function contextFor(ctx, state, agent, signal, command = false) {
|
|
|
1552
2417
|
modelRegistry: {
|
|
1553
2418
|
getAll: () => allModels(),
|
|
1554
2419
|
getAvailable: () => allModels(),
|
|
1555
|
-
find: (provider, modelId) =>
|
|
1556
|
-
|
|
2420
|
+
find: (provider, modelId) => {
|
|
2421
|
+
const entry = catalog?.find(provider, modelId);
|
|
2422
|
+
return entry === void 0 ? void 0 : restorePiShape(entry);
|
|
2423
|
+
},
|
|
2424
|
+
getError: () => {
|
|
2425
|
+
const problems = state.modelsJson?.errors ?? [];
|
|
2426
|
+
return problems.length > 0 ? problems.join("\n") : void 0;
|
|
2427
|
+
},
|
|
1557
2428
|
hasConfiguredAuth: (model) => {
|
|
1558
2429
|
const provider = String(model?.provider ?? "");
|
|
1559
|
-
|
|
2430
|
+
if (provider.length === 0) return false;
|
|
2431
|
+
const jsonProvider = state.modelsJson?.providers.get(provider);
|
|
2432
|
+
if (jsonProvider !== void 0) {
|
|
2433
|
+
const configured = modelsJsonAuthConfigured(jsonProvider);
|
|
2434
|
+
if (configured !== void 0) return configured;
|
|
2435
|
+
}
|
|
2436
|
+
return state.providers.has(provider) || (catalog?.all() ?? []).some((entry) => entry.provider === provider) || jsonProvider !== void 0;
|
|
1560
2437
|
},
|
|
1561
2438
|
getApiKeyAndHeaders: async (model) => {
|
|
1562
2439
|
const provider = String(model?.provider ?? "");
|
|
1563
|
-
const
|
|
2440
|
+
const jsonProvider = state.modelsJson?.providers.get(provider);
|
|
2441
|
+
const config = providerConfig(provider) ?? (jsonProvider?.apiKey !== void 0 ? void 0 : await realBuiltinProvider(provider));
|
|
1564
2442
|
if (config !== void 0) {
|
|
1565
2443
|
const auth = (await resolvePiProviderAuth({
|
|
1566
2444
|
providerId: provider,
|
|
@@ -1568,13 +2446,34 @@ function contextFor(ctx, state, agent, signal, command = false) {
|
|
|
1568
2446
|
store: oauthStoreOf(state)
|
|
1569
2447
|
}))?.auth;
|
|
1570
2448
|
if (auth?.apiKey === void 0) return { ok: false };
|
|
2449
|
+
const configured = jsonProvider === void 0 ? void 0 : applyModelsJsonConfiguredAuth(provider, jsonProvider, {
|
|
2450
|
+
apiKey: auth.apiKey,
|
|
2451
|
+
...auth.headers === void 0 ? {} : { headers: auth.headers }
|
|
2452
|
+
});
|
|
2453
|
+
if (configured !== void 0 && !configured.ok) return {
|
|
2454
|
+
ok: false,
|
|
2455
|
+
error: configured.error
|
|
2456
|
+
};
|
|
2457
|
+
const headers = configured?.ok ? configured.headers : auth.headers;
|
|
1571
2458
|
return {
|
|
1572
2459
|
ok: true,
|
|
1573
2460
|
apiKey: auth.apiKey,
|
|
1574
|
-
...
|
|
2461
|
+
...headers === void 0 ? {} : { headers },
|
|
1575
2462
|
...auth.baseUrl === void 0 && config.baseUrl === void 0 ? {} : { baseUrl: auth.baseUrl ?? config.baseUrl }
|
|
1576
2463
|
};
|
|
1577
2464
|
}
|
|
2465
|
+
if (jsonProvider !== void 0) {
|
|
2466
|
+
const resolved = resolveModelsJsonAuth(provider, jsonProvider);
|
|
2467
|
+
if (!resolved.ok) return {
|
|
2468
|
+
ok: false,
|
|
2469
|
+
error: resolved.error
|
|
2470
|
+
};
|
|
2471
|
+
return {
|
|
2472
|
+
ok: true,
|
|
2473
|
+
...resolved.apiKey === void 0 ? {} : { apiKey: resolved.apiKey },
|
|
2474
|
+
...resolved.headers === void 0 ? {} : { headers: resolved.headers }
|
|
2475
|
+
};
|
|
2476
|
+
}
|
|
1578
2477
|
try {
|
|
1579
2478
|
const entry = llmOf(ctx)?.listConfigurableProviders?.()?.find((candidate) => candidate.provider === provider);
|
|
1580
2479
|
if (entry === void 0) return { ok: false };
|
|
@@ -1592,11 +2491,23 @@ function contextFor(ctx, state, agent, signal, command = false) {
|
|
|
1592
2491
|
}
|
|
1593
2492
|
},
|
|
1594
2493
|
getProviderAuthStatus: (provider) => providerSupportsOAuth(providerConfig(provider)) ? "oauth" : "none",
|
|
1595
|
-
getProvider: (provider) =>
|
|
2494
|
+
getProvider: (provider) => {
|
|
2495
|
+
const base = providerConfig(provider) ?? state.modelsJsonProviders.get(provider);
|
|
2496
|
+
if (base !== void 0) return state.providerRouteDisposers.has(provider) || state.providerRouteDisposers.has(`${MODELS_JSON_ROUTE_PREFIX}${provider}`) ? dshRoutedPiProvider(base, provider) : base;
|
|
2497
|
+
if ((catalog?.all() ?? []).some((entry) => entry.provider === provider)) return dshRoutedPiProvider({
|
|
2498
|
+
id: provider,
|
|
2499
|
+
name: provider
|
|
2500
|
+
}, provider);
|
|
2501
|
+
},
|
|
2502
|
+
complete: async (model, context, options) => {
|
|
2503
|
+
const result = await dshRoutedStream(model, context ?? {}, options).result();
|
|
2504
|
+
if (result instanceof Error) throw result;
|
|
2505
|
+
return result;
|
|
2506
|
+
},
|
|
1596
2507
|
getRegisteredProviderConfig: (provider) => providerConfig(provider),
|
|
1597
2508
|
getRegisteredProviderIds: () => [...state.providers.keys()],
|
|
1598
2509
|
getProviderDisplayName: (provider) => {
|
|
1599
|
-
const config = providerConfig(provider);
|
|
2510
|
+
const config = providerConfig(provider) ?? state.modelsJsonProviders.get(provider);
|
|
1600
2511
|
return typeof config?.name === "string" ? config.name : provider;
|
|
1601
2512
|
},
|
|
1602
2513
|
getProviderAuth: async (provider) => {
|
|
@@ -1630,10 +2541,11 @@ function contextFor(ctx, state, agent, signal, command = false) {
|
|
|
1630
2541
|
return provider.length > 0 && providerSupportsOAuth(providerConfig(provider));
|
|
1631
2542
|
},
|
|
1632
2543
|
refresh: async () => {
|
|
2544
|
+
await reloadModelsJson(ctx, state);
|
|
1633
2545
|
await catalog?.refresh();
|
|
1634
2546
|
return {
|
|
1635
|
-
models:
|
|
1636
|
-
errors: []
|
|
2547
|
+
models: allModels(),
|
|
2548
|
+
errors: [...state.modelsJson?.errors ?? []]
|
|
1637
2549
|
};
|
|
1638
2550
|
}
|
|
1639
2551
|
},
|
|
@@ -1974,11 +2886,77 @@ function subscribeInterceptors(ctx, state) {
|
|
|
1974
2886
|
};
|
|
1975
2887
|
return downstream;
|
|
1976
2888
|
});
|
|
2889
|
+
cordis.on("agent/pre-step", async (payload, next) => {
|
|
2890
|
+
const decision = await next();
|
|
2891
|
+
if (decision.kind !== "enter" || payload.step !== 1) return decision;
|
|
2892
|
+
if ((state.handlers.get("before_agent_start")?.length ?? 0) === 0) return decision;
|
|
2893
|
+
const agent = payload.agent;
|
|
2894
|
+
if (isSubagentOrigin(agent)) return decision;
|
|
2895
|
+
const signal = payload.signal;
|
|
2896
|
+
const messages = decision.messages ?? [];
|
|
2897
|
+
const userMessages = messages.filter((message) => (message.source?.kind ?? "user") === "user");
|
|
2898
|
+
const prompt = userMessages.flatMap((message) => textBlocks(message.content)).map((block) => block.text).join("\n");
|
|
2899
|
+
const images = await collectPiImages(ctx, userMessages);
|
|
2900
|
+
state.turnSystemPromptOverrides.delete(agent);
|
|
2901
|
+
const event = {
|
|
2902
|
+
type: "before_agent_start",
|
|
2903
|
+
prompt,
|
|
2904
|
+
...images.length > 0 ? { images } : {},
|
|
2905
|
+
systemPrompt: state.currentSystemPrompt,
|
|
2906
|
+
systemPromptOptions: {}
|
|
2907
|
+
};
|
|
2908
|
+
const results = await dispatch(state, "before_agent_start", event, contextFor(ctx, state, agent, signal));
|
|
2909
|
+
const injected = [];
|
|
2910
|
+
for (const result of results) {
|
|
2911
|
+
if (typeof result !== "object" || result === null) continue;
|
|
2912
|
+
const record = result;
|
|
2913
|
+
if (typeof record.systemPrompt === "string") {
|
|
2914
|
+
state.turnSystemPromptOverrides.set(agent, record.systemPrompt);
|
|
2915
|
+
event.systemPrompt = record.systemPrompt;
|
|
2916
|
+
}
|
|
2917
|
+
const message = record.message;
|
|
2918
|
+
if (message !== void 0) {
|
|
2919
|
+
const content = message.content;
|
|
2920
|
+
const blocks = await piToDshContent(ctx, typeof content === "string" ? [{
|
|
2921
|
+
type: "text",
|
|
2922
|
+
text: content
|
|
2923
|
+
}] : content ?? []);
|
|
2924
|
+
injected.push(createUserMessage({
|
|
2925
|
+
content: blocks,
|
|
2926
|
+
source: {
|
|
2927
|
+
kind: "plugin",
|
|
2928
|
+
plugin: state.messageSource,
|
|
2929
|
+
...typeof message.customType === "string" ? { piCustomType: message.customType } : {}
|
|
2930
|
+
}
|
|
2931
|
+
}));
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
const stepMessages = injected.length === 0 ? messages : [...messages, ...injected];
|
|
2935
|
+
const transformed = await applyPiContextTransform(ctx, state, agent, signal, stepMessages);
|
|
2936
|
+
if (transformed === stepMessages && injected.length === 0) return decision;
|
|
2937
|
+
return {
|
|
2938
|
+
...decision,
|
|
2939
|
+
messages: transformed
|
|
2940
|
+
};
|
|
2941
|
+
});
|
|
1977
2942
|
cordis.on("system-prompt/assemble", async (assembly, assembleContext, next) => {
|
|
1978
2943
|
const downstream = await next();
|
|
1979
2944
|
if ((state.handlers.get("before_agent_start")?.length ?? 0) === 0) return downstream;
|
|
1980
2945
|
const original = renderPrompt(downstream);
|
|
1981
2946
|
state.currentSystemPrompt = original;
|
|
2947
|
+
const agent = assembleContext.agent ?? assembleContext.scope;
|
|
2948
|
+
if (agent !== void 0 && !isSubagentOrigin(agent)) {
|
|
2949
|
+
const override = state.turnSystemPromptOverrides.get(agent);
|
|
2950
|
+
if (override === void 0) return downstream;
|
|
2951
|
+
state.currentSystemPrompt = override;
|
|
2952
|
+
return {
|
|
2953
|
+
...downstream,
|
|
2954
|
+
sections: [{
|
|
2955
|
+
name: "pi2dsh:system-prompt",
|
|
2956
|
+
text: override
|
|
2957
|
+
}]
|
|
2958
|
+
};
|
|
2959
|
+
}
|
|
1982
2960
|
const event = {
|
|
1983
2961
|
type: "before_agent_start",
|
|
1984
2962
|
prompt: "",
|
|
@@ -1987,12 +2965,9 @@ function subscribeInterceptors(ctx, state) {
|
|
|
1987
2965
|
};
|
|
1988
2966
|
const results = await dispatch(state, "before_agent_start", event, contextFor(ctx, state, assembleContext.scope, assembleContext.signal));
|
|
1989
2967
|
let replacement = original;
|
|
1990
|
-
for (const result of results) {
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
event.systemPrompt = replacement;
|
|
1994
|
-
}
|
|
1995
|
-
if (typeof result === "object" && result !== null && result.message !== void 0) logger(ctx).warn("[pi2dsh] before_agent_start custom-message injection is unsupported and was ignored");
|
|
2968
|
+
for (const result of results) if (typeof result === "object" && result !== null && typeof result.systemPrompt === "string") {
|
|
2969
|
+
replacement = result.systemPrompt;
|
|
2970
|
+
event.systemPrompt = replacement;
|
|
1996
2971
|
}
|
|
1997
2972
|
state.currentSystemPrompt = replacement;
|
|
1998
2973
|
return {
|
|
@@ -2004,10 +2979,146 @@ function subscribeInterceptors(ctx, state) {
|
|
|
2004
2979
|
};
|
|
2005
2980
|
});
|
|
2006
2981
|
}
|
|
2982
|
+
function piShapeOfPending(message) {
|
|
2983
|
+
const source = message.source;
|
|
2984
|
+
const content = dshToPiContent(message.content ?? []);
|
|
2985
|
+
return typeof source?.piCustomType === "string" ? {
|
|
2986
|
+
role: "custom",
|
|
2987
|
+
customType: source.piCustomType,
|
|
2988
|
+
content
|
|
2989
|
+
} : {
|
|
2990
|
+
role: "user",
|
|
2991
|
+
content
|
|
2992
|
+
};
|
|
2993
|
+
}
|
|
2994
|
+
async function applyPiContextTransform(ctx, state, agent, signal, pending) {
|
|
2995
|
+
if ((state.handlers.get("context")?.length ?? 0) === 0) return pending;
|
|
2996
|
+
const session = agentSession(agent);
|
|
2997
|
+
const history = [];
|
|
2998
|
+
for (const event of session?.events ?? []) {
|
|
2999
|
+
const projected = messageFromSessionEvent(event);
|
|
3000
|
+
if (projected === void 0) continue;
|
|
3001
|
+
if (event.type === "user/message") {
|
|
3002
|
+
const customType = (event.data?.source)?.piCustomType;
|
|
3003
|
+
if (typeof customType === "string") {
|
|
3004
|
+
history.push({
|
|
3005
|
+
...projected,
|
|
3006
|
+
role: "custom",
|
|
3007
|
+
customType
|
|
3008
|
+
});
|
|
3009
|
+
continue;
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
history.push(projected);
|
|
3013
|
+
}
|
|
3014
|
+
const projectedPending = pending.map(piShapeOfPending);
|
|
3015
|
+
const event = {
|
|
3016
|
+
type: "context",
|
|
3017
|
+
messages: [...history, ...projectedPending]
|
|
3018
|
+
};
|
|
3019
|
+
const results = await dispatch(state, "context", event, contextFor(ctx, state, agent, signal));
|
|
3020
|
+
let current = event.messages;
|
|
3021
|
+
for (const result of results) {
|
|
3022
|
+
if (typeof result !== "object" || result === null) continue;
|
|
3023
|
+
const returned = result.messages;
|
|
3024
|
+
if (!Array.isArray(returned)) continue;
|
|
3025
|
+
if (returned.length !== current.length) {
|
|
3026
|
+
logger(ctx).warn("[pi2dsh] a Pi context handler changed the message count; DSH durable history is append-only, so the transform was ignored");
|
|
3027
|
+
continue;
|
|
3028
|
+
}
|
|
3029
|
+
current = returned;
|
|
3030
|
+
}
|
|
3031
|
+
if (current === event.messages) return pending;
|
|
3032
|
+
for (let index = 0; index < history.length; index++) {
|
|
3033
|
+
if (current[index] === history[index]) continue;
|
|
3034
|
+
if (JSON.stringify(current[index]) === JSON.stringify(history[index])) continue;
|
|
3035
|
+
logger(ctx).warn("[pi2dsh] a Pi context handler edited already-entered history; DSH durable history is append-only, so those edits were ignored (only this step's not-yet-entered messages accept the transform)");
|
|
3036
|
+
break;
|
|
3037
|
+
}
|
|
3038
|
+
const tail = current.slice(history.length);
|
|
3039
|
+
const rebuilt = [];
|
|
3040
|
+
for (const [index, original] of pending.entries()) {
|
|
3041
|
+
const shape = tail[index];
|
|
3042
|
+
if (shape === void 0) {
|
|
3043
|
+
rebuilt.push(original);
|
|
3044
|
+
continue;
|
|
3045
|
+
}
|
|
3046
|
+
const blocks = await piToDshContent(ctx, typeof shape.content === "string" ? [{
|
|
3047
|
+
type: "text",
|
|
3048
|
+
text: shape.content
|
|
3049
|
+
}] : shape.content ?? []);
|
|
3050
|
+
rebuilt.push(createUserMessage({
|
|
3051
|
+
content: blocks,
|
|
3052
|
+
source: original.source ?? {
|
|
3053
|
+
kind: "plugin",
|
|
3054
|
+
plugin: state.messageSource
|
|
3055
|
+
}
|
|
3056
|
+
}));
|
|
3057
|
+
}
|
|
3058
|
+
return rebuilt;
|
|
3059
|
+
}
|
|
3060
|
+
async function collectPiImages(ctx, messages) {
|
|
3061
|
+
const attachments = ctx.get("attachments");
|
|
3062
|
+
if (attachments === void 0) return [];
|
|
3063
|
+
const images = [];
|
|
3064
|
+
for (const message of messages) {
|
|
3065
|
+
const content = message.content;
|
|
3066
|
+
if (!Array.isArray(content)) continue;
|
|
3067
|
+
for (const block of content) {
|
|
3068
|
+
if (block?.type !== "image" || block.attachment === void 0) continue;
|
|
3069
|
+
try {
|
|
3070
|
+
const stored = await attachments.readImage(block.attachment);
|
|
3071
|
+
images.push({
|
|
3072
|
+
type: "image",
|
|
3073
|
+
data: Buffer.from(stored.data).toString("base64"),
|
|
3074
|
+
mimeType: String(block.attachment.mediaType ?? "image/png")
|
|
3075
|
+
});
|
|
3076
|
+
} catch {}
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
return images;
|
|
3080
|
+
}
|
|
2007
3081
|
function oauthStoreOf(state) {
|
|
2008
3082
|
state.oauthStore ??= new FileCredentialStore(join(getAgentDir(), "auth.json"));
|
|
2009
3083
|
return state.oauthStore;
|
|
2010
3084
|
}
|
|
3085
|
+
const MODELS_JSON_ROUTE_PREFIX = "models.json/";
|
|
3086
|
+
async function reloadModelsJson(ctx, state) {
|
|
3087
|
+
for (const [key, dispose] of state.providerRouteDisposers) {
|
|
3088
|
+
if (!key.startsWith(MODELS_JSON_ROUTE_PREFIX)) continue;
|
|
3089
|
+
state.providerRouteDisposers.delete(key);
|
|
3090
|
+
dispose();
|
|
3091
|
+
}
|
|
3092
|
+
state.modelsJsonProviders.clear();
|
|
3093
|
+
state.modelsJson = await loadModelsJsonSnapshot(realBuiltinProvider);
|
|
3094
|
+
for (const problem of state.modelsJson.errors) logger(ctx).warn(`[pi2dsh] models.json: ${problem}`);
|
|
3095
|
+
for (const [providerId, providerConfig] of state.modelsJson.providers) {
|
|
3096
|
+
const models = state.modelsJson.models.filter((model) => model.provider === providerId);
|
|
3097
|
+
const provider = modelsJsonPiProvider(providerId, providerConfig, models);
|
|
3098
|
+
const routeDisposer = registerPiProviderRoute({
|
|
3099
|
+
llm: llmOf(ctx),
|
|
3100
|
+
providerId,
|
|
3101
|
+
provider,
|
|
3102
|
+
host: {
|
|
3103
|
+
resolveAuth: async () => {
|
|
3104
|
+
const resolved = resolveModelsJsonAuth(providerId, providerConfig);
|
|
3105
|
+
if (!resolved.ok) return void 0;
|
|
3106
|
+
return { auth: {
|
|
3107
|
+
...resolved.apiKey === void 0 ? {} : { apiKey: resolved.apiKey },
|
|
3108
|
+
...resolved.headers === void 0 ? {} : { headers: resolved.headers },
|
|
3109
|
+
...providerConfig.baseUrl === void 0 ? {} : { baseUrl: providerConfig.baseUrl }
|
|
3110
|
+
} };
|
|
3111
|
+
},
|
|
3112
|
+
warn: (message) => logger(ctx).warn(message)
|
|
3113
|
+
}
|
|
3114
|
+
});
|
|
3115
|
+
if (routeDisposer !== void 0) {
|
|
3116
|
+
state.modelsJsonProviders.set(providerId, provider);
|
|
3117
|
+
state.providerRouteDisposers.set(`${MODELS_JSON_ROUTE_PREFIX}${providerId}`, routeDisposer);
|
|
3118
|
+
logger(ctx).info(`[pi2dsh] models.json provider ${JSON.stringify(providerId)} registered as a native DSH llm route (${models.length} models)`);
|
|
3119
|
+
}
|
|
3120
|
+
}
|
|
3121
|
+
}
|
|
2011
3122
|
function ensureLoginCommand(ctx, state) {
|
|
2012
3123
|
if (state.loginCommandRegistered === true) return;
|
|
2013
3124
|
state.loginCommandRegistered = true;
|
|
@@ -2206,15 +3317,19 @@ function dshCommandName(ctx, piName) {
|
|
|
2206
3317
|
return name;
|
|
2207
3318
|
}
|
|
2208
3319
|
function registerCommand(ctx, state, command) {
|
|
2209
|
-
if (state.commands.has(command.name))
|
|
3320
|
+
if (state.commands.has(command.name)) {
|
|
3321
|
+
state.commandDisposers.get(command.name)?.();
|
|
3322
|
+
state.commandDisposers.delete(command.name);
|
|
3323
|
+
}
|
|
2210
3324
|
state.commands.set(command.name, command);
|
|
2211
3325
|
const commands = ctx.get("commands");
|
|
2212
3326
|
if (commands === void 0) {
|
|
2213
3327
|
logger(ctx).warn(`[pi2dsh] command /${command.name} was not registered because this DSH composition has no ctx.commands`);
|
|
2214
3328
|
return;
|
|
2215
3329
|
}
|
|
2216
|
-
|
|
2217
|
-
|
|
3330
|
+
const baseName = dshCommandName(ctx, command.name);
|
|
3331
|
+
const definitionFor = (dshName) => ({
|
|
3332
|
+
name: dshName,
|
|
2218
3333
|
description: command.description || `Migrated Pi command /${command.name}`,
|
|
2219
3334
|
...command.argumentHint !== void 0 ? { input: { hint: command.argumentHint } } : {},
|
|
2220
3335
|
async handler(invocation) {
|
|
@@ -2228,6 +3343,18 @@ function registerCommand(ctx, state, command) {
|
|
|
2228
3343
|
};
|
|
2229
3344
|
}
|
|
2230
3345
|
});
|
|
3346
|
+
let lastError;
|
|
3347
|
+
for (let ordinal = 1; ordinal <= 9; ordinal++) {
|
|
3348
|
+
const dshName = ordinal === 1 ? baseName : `${baseName}-${ordinal}`;
|
|
3349
|
+
try {
|
|
3350
|
+
state.commandDisposers.set(command.name, commands.register(definitionFor(dshName)));
|
|
3351
|
+
if (ordinal > 1) logger(ctx).warn(`[pi2dsh] command /${command.name} collides with an earlier registration in this host; mounted as /${dshName} (Pi numbers colliding commands the same way)`);
|
|
3352
|
+
return;
|
|
3353
|
+
} catch (error) {
|
|
3354
|
+
lastError = error;
|
|
3355
|
+
}
|
|
3356
|
+
}
|
|
3357
|
+
logger(ctx).warn(`[pi2dsh] command /${command.name} was not registered: ${lastError instanceof Error ? lastError.message : String(lastError)}`);
|
|
2231
3358
|
}
|
|
2232
3359
|
function requireSession(state, operation) {
|
|
2233
3360
|
const session = agentSession(currentAgent(state));
|
|
@@ -2569,6 +3696,8 @@ async function applyPiPackage(ctx, options) {
|
|
|
2569
3696
|
toolDisposers: /* @__PURE__ */ new Map(),
|
|
2570
3697
|
toolRestrictions: /* @__PURE__ */ new WeakMap(),
|
|
2571
3698
|
commands: /* @__PURE__ */ new Map(),
|
|
3699
|
+
commandDisposers: /* @__PURE__ */ new Map(),
|
|
3700
|
+
modelsJsonProviders: /* @__PURE__ */ new Map(),
|
|
2572
3701
|
flags: /* @__PURE__ */ new Map(),
|
|
2573
3702
|
notifications: [],
|
|
2574
3703
|
activeAgents: /* @__PURE__ */ new Set(),
|
|
@@ -2588,6 +3717,7 @@ async function applyPiPackage(ctx, options) {
|
|
|
2588
3717
|
toolsExpanded: false,
|
|
2589
3718
|
modelOverrides: /* @__PURE__ */ new WeakMap(),
|
|
2590
3719
|
thinkingLevels: /* @__PURE__ */ new WeakMap(),
|
|
3720
|
+
turnSystemPromptOverrides: /* @__PURE__ */ new WeakMap(),
|
|
2591
3721
|
globalThinkingLevel: "off",
|
|
2592
3722
|
argMutations: /* @__PURE__ */ new WeakMap(),
|
|
2593
3723
|
streamingTexts: /* @__PURE__ */ new Map(),
|
|
@@ -2616,6 +3746,7 @@ async function applyPiPackage(ctx, options) {
|
|
|
2616
3746
|
}
|
|
2617
3747
|
const llm = llmOf(ctx);
|
|
2618
3748
|
state.modelCatalog = new ModelCatalog(llm);
|
|
3749
|
+
await reloadModelsJson(ctx, state);
|
|
2619
3750
|
if (llm !== void 0) {
|
|
2620
3751
|
ctx.on("llm/adapters-updated", () => {
|
|
2621
3752
|
state.modelCatalog?.refresh();
|
|
@@ -2654,4 +3785,4 @@ const runtimeInternals = {
|
|
|
2654
3785
|
//#endregion
|
|
2655
3786
|
export { normalizeToolSchema as n, runtimeInternals as r, applyPiPackage as t };
|
|
2656
3787
|
|
|
2657
|
-
//# sourceMappingURL=runtime-
|
|
3788
|
+
//# sourceMappingURL=runtime-B7mEIRf-.mjs.map
|