pi2dsh 0.15.2 → 0.16.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/README.md +41 -60
- package/README.zh.md +34 -54
- package/dist/{analyzer-C5FQXB7R.mjs → analyzer-dRAMYI3l.mjs} +2 -2
- package/dist/{analyzer-C5FQXB7R.mjs.map → analyzer-dRAMYI3l.mjs.map} +1 -1
- package/dist/cli.mjs +2 -3
- package/dist/cli.mjs.map +1 -1
- package/dist/compat/pi-ai.d.mts +1 -1
- package/dist/compat/pi-ai.mjs +1 -2
- package/dist/compat/pi-coding-agent.mjs +1 -1
- package/dist/credentials-oauth.d.mts +8 -2
- package/dist/credentials-oauth.d.mts.map +1 -1
- package/dist/credentials-oauth.mjs +134 -1
- package/dist/credentials-oauth.mjs.map +1 -0
- package/dist/{google-generative-ai-2gCFYp-t.mjs → google-generative-ai-Dpb_X-Kt.mjs} +2 -2
- package/dist/{google-generative-ai-2gCFYp-t.mjs.map → google-generative-ai-Dpb_X-Kt.mjs.map} +1 -1
- package/dist/{google-shared-75IdVyrx.mjs → google-shared-CL1Za-ev.mjs} +12 -12
- package/dist/{google-shared-75IdVyrx.mjs.map → google-shared-CL1Za-ev.mjs.map} +1 -1
- package/dist/{google-vertex-Bhyo4z2i.mjs → google-vertex-BXRKa49Y.mjs} +2 -2
- package/dist/{google-vertex-Bhyo4z2i.mjs.map → google-vertex-BXRKa49Y.mjs.map} +1 -1
- package/dist/host.mjs +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3 -4
- package/dist/index.mjs.map +1 -1
- package/dist/{compatibility-DVMqXJux.mjs → mcp-config-2s_i_H3R.mjs} +180 -3
- package/dist/mcp-config-2s_i_H3R.mjs.map +1 -0
- package/dist/{mistral-conversations-DJyeTo8C.mjs → mistral-conversations-D-Kf38nj.mjs} +5491 -407
- package/dist/mistral-conversations-D-Kf38nj.mjs.map +1 -0
- package/dist/{multipart-parser-SRcGkVuX.mjs → multipart-parser-CBAi6PxA.mjs} +2 -2
- package/dist/{multipart-parser-SRcGkVuX.mjs.map → multipart-parser-CBAi6PxA.mjs.map} +1 -1
- package/dist/{credentials-oauth-Didpkkjx.mjs → oauth-bridge-C_MAPMGA.mjs} +11 -88
- package/dist/oauth-bridge-C_MAPMGA.mjs.map +1 -0
- package/dist/oauth-bridge-hOnT3acY.d.mts +34 -0
- package/dist/oauth-bridge-hOnT3acY.d.mts.map +1 -0
- package/dist/{otel-CBhmS-NR.mjs → otel-EL651-JR.mjs} +2 -2
- package/dist/{otel-CBhmS-NR.mjs.map → otel-EL651-JR.mjs.map} +1 -1
- package/dist/{pi-ai-DpqiLdPA.mjs → pi-ai-DQPHUR9S.mjs} +252 -7
- package/dist/pi-ai-DQPHUR9S.mjs.map +1 -0
- package/dist/{pi-ai-ZU5MelXy.d.mts → pi-ai-hGbYES_v.d.mts} +2 -2
- package/dist/{pi-ai-ZU5MelXy.d.mts.map → pi-ai-hGbYES_v.d.mts.map} +1 -1
- package/dist/{pi-coding-agent-DK8hbJP5.mjs → pi-coding-agent-f3_hNCpd.mjs} +0 -0
- package/dist/{pi-coding-agent-DK8hbJP5.mjs.map → pi-coding-agent-f3_hNCpd.mjs.map} +1 -1
- package/dist/{runtime-BlbKWw7W.mjs → runtime-C6_pOPmL.mjs} +198 -47
- package/dist/runtime-C6_pOPmL.mjs.map +1 -0
- package/dist/runtime.d.mts +29 -47
- package/dist/runtime.d.mts.map +1 -1
- package/dist/runtime.mjs +1 -1
- package/dist/{from-BCscBQ9P.mjs → src-85HOaW5W.mjs} +1185 -10
- package/dist/src-85HOaW5W.mjs.map +1 -0
- package/package.json +28 -21
- package/dist/compatibility-DVMqXJux.mjs.map +0 -1
- package/dist/completionchunk-Dhk56lZl.mjs +0 -5212
- package/dist/completionchunk-Dhk56lZl.mjs.map +0 -1
- package/dist/credentials-oauth-Didpkkjx.mjs.map +0 -1
- package/dist/from-BCscBQ9P.mjs.map +0 -1
- package/dist/mcp-config-jmzbgdHa.mjs +0 -181
- package/dist/mcp-config-jmzbgdHa.mjs.map +0 -1
- package/dist/mistral-conversations-DJyeTo8C.mjs.map +0 -1
- package/dist/openai-responses-BRdGpBX6.mjs +0 -251
- package/dist/openai-responses-BRdGpBX6.mjs.map +0 -1
- package/dist/pi-ai-DpqiLdPA.mjs.map +0 -1
- package/dist/runtime-BlbKWw7W.mjs.map +0 -1
- package/dist/src-DlTagfW5.mjs +0 -1186
- package/dist/src-DlTagfW5.mjs.map +0 -1
|
@@ -4,7 +4,7 @@ import { m as clampThinkingLevel, p as calculateCost, r as buildBaseOptions, s a
|
|
|
4
4
|
import { n as normalizeProviderError, t as formatProviderError } from "./error-body-DKA3lknR.mjs";
|
|
5
5
|
import { n as providerHeadersToRecord } from "./headers-CPzZhJQn.mjs";
|
|
6
6
|
import { t as getProviderEnvValue } from "./provider-env-C72pF4vP.mjs";
|
|
7
|
-
import { a as resolveGoogleFunctionCallingMode, c as supportsGoogleStrictToolSampling, d as ThinkingLevel, i as mapStopReason, l as GoogleGenAI, n as convertTools, o as retainThoughtSignature, r as isThinkingPart, s as retryGoogleRequest, t as convertMessages, u as ResourceScope } from "./google-shared-
|
|
7
|
+
import { a as resolveGoogleFunctionCallingMode, c as supportsGoogleStrictToolSampling, d as ThinkingLevel, i as mapStopReason, l as GoogleGenAI, n as convertTools, o as retainThoughtSignature, r as isThinkingPart, s as retryGoogleRequest, t as convertMessages, u as ResourceScope } from "./google-shared-CL1Za-ev.mjs";
|
|
8
8
|
//#region node_modules/.pnpm/@earendil-works+pi-ai@0.84.1_ws@8.21.3_zod@4.4.3/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js
|
|
9
9
|
const API_VERSION = "v1";
|
|
10
10
|
const GCP_VERTEX_CREDENTIALS_MARKER = "gcp-vertex-credentials";
|
|
@@ -397,4 +397,4 @@ function getGoogleBudget(model, effort, customBudgets) {
|
|
|
397
397
|
//#endregion
|
|
398
398
|
export { stream, streamSimple };
|
|
399
399
|
|
|
400
|
-
//# sourceMappingURL=google-vertex-
|
|
400
|
+
//# sourceMappingURL=google-vertex-BXRKa49Y.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-vertex-Bhyo4z2i.mjs","names":[],"sources":["../node_modules/.pnpm/@earendil-works+pi-ai@0.84.1_ws@8.21.3_zod@4.4.3/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js"],"sourcesContent":["import { GoogleGenAI, ResourceScope, ThinkingLevel, } from \"@google/genai\";\nimport { calculateCost, clampThinkingLevel } from \"../models.js\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { providerHeadersToRecord } from \"../utils/headers.js\";\nimport { getProviderEnvValue } from \"../utils/provider-env.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport { convertMessages, convertTools, isThinkingPart, mapStopReason, resolveGoogleFunctionCallingMode, retainThoughtSignature, retryGoogleRequest, supportsGoogleStrictToolSampling, } from \"./google-shared.js\";\nimport { buildBaseOptions } from \"./simple-options.js\";\nconst API_VERSION = \"v1\";\nconst GCP_VERTEX_CREDENTIALS_MARKER = \"gcp-vertex-credentials\";\nconst THINKING_LEVEL_MAP = {\n THINKING_LEVEL_UNSPECIFIED: ThinkingLevel.THINKING_LEVEL_UNSPECIFIED,\n MINIMAL: ThinkingLevel.MINIMAL,\n LOW: ThinkingLevel.LOW,\n MEDIUM: ThinkingLevel.MEDIUM,\n HIGH: ThinkingLevel.HIGH,\n};\n// Counter for generating unique tool call IDs\nlet toolCallCounter = 0;\nexport const stream = (model, context, options) => {\n const stream = new AssistantMessageEventStream();\n (async () => {\n const output = {\n role: \"assistant\",\n content: [],\n api: \"google-vertex\",\n provider: model.provider,\n model: model.id,\n usage: {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n },\n stopReason: \"pending\",\n timestamp: Date.now(),\n };\n try {\n if (options?.fetch && options.fetch !== globalThis.fetch) {\n throw new Error(\"Custom fetch is not supported by the Google Vertex adapter\");\n }\n const apiKey = resolveApiKey(options);\n // Create the client using either a Vertex API key, if provided, or ADC with project and location\n const client = apiKey\n ? createClientWithApiKey(model, apiKey, options?.headers)\n : createClient(model, resolveProject(options), resolveLocation(options), options?.headers, options?.env);\n let params = buildParams(model, context, options);\n const nextParams = await options?.onPayload?.(params, model);\n if (nextParams !== undefined) {\n params = nextParams;\n }\n const googleStream = await retryGoogleRequest(() => client.models.generateContentStream(params), options);\n stream.push({ type: \"start\", partial: output });\n let currentBlock = null;\n const blocks = output.content;\n const blockIndex = () => blocks.length - 1;\n for await (const chunk of googleStream) {\n // Vertex uses the same @google/genai GenerateContentResponse type as Gemini.\n // responseId is documented there as an output-only identifier for each response.\n output.responseId ||= chunk.responseId;\n const candidate = chunk.candidates?.[0];\n if (candidate?.content?.parts) {\n for (const part of candidate.content.parts) {\n if (part.text !== undefined) {\n const isThinking = isThinkingPart(part);\n if (!currentBlock ||\n (isThinking && currentBlock.type !== \"thinking\") ||\n (!isThinking && currentBlock.type !== \"text\")) {\n if (currentBlock) {\n if (currentBlock.type === \"text\") {\n stream.push({\n type: \"text_end\",\n contentIndex: blocks.length - 1,\n content: currentBlock.text,\n partial: output,\n });\n }\n else {\n stream.push({\n type: \"thinking_end\",\n contentIndex: blockIndex(),\n content: currentBlock.thinking,\n partial: output,\n });\n }\n }\n if (isThinking) {\n currentBlock = { type: \"thinking\", thinking: \"\", thinkingSignature: undefined };\n output.content.push(currentBlock);\n stream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n }\n else {\n currentBlock = { type: \"text\", text: \"\" };\n output.content.push(currentBlock);\n stream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n }\n }\n if (currentBlock.type === \"thinking\") {\n currentBlock.thinking += part.text;\n currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);\n stream.push({\n type: \"thinking_delta\",\n contentIndex: blockIndex(),\n delta: part.text,\n partial: output,\n });\n }\n else {\n currentBlock.text += part.text;\n currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);\n stream.push({\n type: \"text_delta\",\n contentIndex: blockIndex(),\n delta: part.text,\n partial: output,\n });\n }\n }\n if (part.functionCall) {\n if (currentBlock) {\n if (currentBlock.type === \"text\") {\n stream.push({\n type: \"text_end\",\n contentIndex: blockIndex(),\n content: currentBlock.text,\n partial: output,\n });\n }\n else {\n stream.push({\n type: \"thinking_end\",\n contentIndex: blockIndex(),\n content: currentBlock.thinking,\n partial: output,\n });\n }\n currentBlock = null;\n }\n const providedId = part.functionCall.id;\n const needsNewId = !providedId || output.content.some((b) => b.type === \"toolCall\" && b.id === providedId);\n const toolCallId = needsNewId\n ? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}`\n : providedId;\n const toolCall = {\n type: \"toolCall\",\n id: toolCallId,\n name: part.functionCall.name || \"\",\n arguments: part.functionCall.args ?? {},\n ...(part.thoughtSignature && { thoughtSignature: part.thoughtSignature }),\n };\n output.content.push(toolCall);\n stream.push({ type: \"toolcall_start\", contentIndex: blockIndex(), partial: output });\n stream.push({\n type: \"toolcall_delta\",\n contentIndex: blockIndex(),\n delta: JSON.stringify(toolCall.arguments),\n partial: output,\n });\n stream.push({ type: \"toolcall_end\", contentIndex: blockIndex(), toolCall, partial: output });\n }\n }\n }\n if (candidate?.finishReason) {\n output.rawStopReason = candidate.finishReason;\n output.stopReason = mapStopReason(candidate.finishReason);\n if (output.content.some((b) => b.type === \"toolCall\")) {\n output.stopReason = \"toolUse\";\n }\n }\n if (chunk.usageMetadata) {\n output.usage = {\n input: (chunk.usageMetadata.promptTokenCount || 0) - (chunk.usageMetadata.cachedContentTokenCount || 0),\n output: (chunk.usageMetadata.candidatesTokenCount || 0) + (chunk.usageMetadata.thoughtsTokenCount || 0),\n cacheRead: chunk.usageMetadata.cachedContentTokenCount || 0,\n cacheWrite: 0,\n reasoning: chunk.usageMetadata.thoughtsTokenCount || 0,\n totalTokens: chunk.usageMetadata.totalTokenCount || 0,\n cost: {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n total: 0,\n },\n };\n calculateCost(model, output.usage);\n }\n }\n if (currentBlock) {\n if (currentBlock.type === \"text\") {\n stream.push({\n type: \"text_end\",\n contentIndex: blockIndex(),\n content: currentBlock.text,\n partial: output,\n });\n }\n else {\n stream.push({\n type: \"thinking_end\",\n contentIndex: blockIndex(),\n content: currentBlock.thinking,\n partial: output,\n });\n }\n }\n if (options?.signal?.aborted) {\n throw new Error(\"Request was aborted\");\n }\n if (output.stopReason === \"pending\") {\n throw new Error(\"Google Vertex stream ended without a finish reason\");\n }\n if (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n const errorMessage = output.rawStopReason\n ? `Provider stopped with: ${output.rawStopReason}`\n : \"An unknown error occurred\";\n throw new Error(errorMessage);\n }\n stream.push({ type: \"done\", reason: output.stopReason, message: output });\n stream.end();\n }\n catch (error) {\n // Remove internal index property used during streaming\n for (const block of output.content) {\n if (\"index\" in block) {\n delete block.index;\n }\n }\n output.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n output.errorMessage = formatProviderError(normalizeProviderError(error));\n stream.push({ type: \"error\", reason: output.stopReason, error: output });\n stream.end();\n }\n })();\n return stream;\n};\nexport const streamSimple = (model, context, options) => {\n const base = buildBaseOptions(model, context, options, undefined);\n if (!options?.reasoning) {\n return stream(model, context, {\n ...base,\n thinking: { enabled: false },\n });\n }\n const clampedReasoning = clampThinkingLevel(model, options.reasoning);\n const effort = (clampedReasoning === \"off\" ? \"high\" : clampedReasoning);\n const geminiModel = model;\n if (isGemini3ProModel(geminiModel) || isGemini3FlashModel(geminiModel)) {\n return stream(model, context, {\n ...base,\n thinking: {\n enabled: true,\n level: getGemini3ThinkingLevel(effort, geminiModel),\n },\n });\n }\n return stream(model, context, {\n ...base,\n thinking: {\n enabled: true,\n budgetTokens: getGoogleBudget(geminiModel, effort, options.thinkingBudgets),\n },\n });\n};\nfunction createClient(model, project, location, optionsHeaders, env) {\n const googleAuthOptions = buildGoogleAuthOptions(env);\n return new GoogleGenAI({\n vertexai: true,\n project,\n location,\n apiVersion: API_VERSION,\n ...(googleAuthOptions ? { googleAuthOptions } : {}),\n httpOptions: buildHttpOptions(model, optionsHeaders),\n });\n}\nfunction createClientWithApiKey(model, apiKey, optionsHeaders) {\n return new GoogleGenAI({\n vertexai: true,\n apiKey,\n apiVersion: API_VERSION,\n httpOptions: buildHttpOptions(model, optionsHeaders),\n });\n}\nfunction buildHttpOptions(model, optionsHeaders) {\n const httpOptions = {};\n const baseUrl = resolveCustomBaseUrl(model.baseUrl);\n if (baseUrl) {\n httpOptions.baseUrl = baseUrl;\n httpOptions.baseUrlResourceScope = ResourceScope.COLLECTION;\n if (baseUrlIncludesApiVersion(baseUrl)) {\n httpOptions.apiVersion = \"\";\n }\n }\n const headers = providerHeadersToRecord({ ...model.headers, ...optionsHeaders });\n if (headers) {\n httpOptions.headers = headers;\n }\n return Object.keys(httpOptions).length > 0 ? httpOptions : undefined;\n}\nfunction resolveCustomBaseUrl(baseUrl) {\n const trimmed = baseUrl.trim();\n if (!trimmed || trimmed.includes(\"{location}\")) {\n return undefined;\n }\n return trimmed;\n}\nfunction baseUrlIncludesApiVersion(baseUrl) {\n try {\n const url = new URL(baseUrl);\n return url.pathname.split(\"/\").some((part) => /^v\\d+(?:beta\\d*)?$/.test(part));\n }\n catch {\n return /(?:^|\\/)v\\d+(?:beta\\d*)?(?:\\/|$)/.test(baseUrl);\n }\n}\nfunction buildGoogleAuthOptions(env) {\n const keyFilename = getProviderEnvValue(\"GOOGLE_APPLICATION_CREDENTIALS\", env);\n return keyFilename ? { keyFilename } : undefined;\n}\nfunction resolveApiKey(options) {\n const apiKey = options?.apiKey?.trim();\n if (!apiKey || apiKey === GCP_VERTEX_CREDENTIALS_MARKER || isPlaceholderApiKey(apiKey)) {\n return undefined;\n }\n return apiKey;\n}\nfunction isPlaceholderApiKey(apiKey) {\n return /^<[^>]+>$/.test(apiKey);\n}\nfunction resolveProject(options) {\n const project = options?.project ||\n getProviderEnvValue(\"GOOGLE_CLOUD_PROJECT\", options?.env) ||\n getProviderEnvValue(\"GCLOUD_PROJECT\", options?.env);\n if (!project) {\n throw new Error(\"Vertex AI requires a project ID. Set GOOGLE_CLOUD_PROJECT/GCLOUD_PROJECT or pass project in options.\");\n }\n return project;\n}\nfunction resolveLocation(options) {\n const location = options?.location || getProviderEnvValue(\"GOOGLE_CLOUD_LOCATION\", options?.env);\n if (!location) {\n throw new Error(\"Vertex AI requires a location. Set GOOGLE_CLOUD_LOCATION or pass location in options.\");\n }\n return location;\n}\nfunction buildParams(model, context, options = {}) {\n const contents = convertMessages(model, context);\n const generationConfig = {};\n if (options.temperature !== undefined) {\n generationConfig.temperature = options.temperature;\n }\n if (options.maxTokens !== undefined) {\n generationConfig.maxOutputTokens = options.maxTokens;\n }\n const functionCallingMode = context.tools?.length\n ? resolveGoogleFunctionCallingMode(context.tools, options.toolChoice, supportsGoogleStrictToolSampling(model.id))\n : undefined;\n const config = {\n ...(Object.keys(generationConfig).length > 0 && generationConfig),\n ...(context.systemPrompt && { systemInstruction: sanitizeSurrogates(context.systemPrompt) }),\n ...(context.tools && context.tools.length > 0 && { tools: convertTools(context.tools) }),\n ...(functionCallingMode !== undefined && {\n toolConfig: { functionCallingConfig: { mode: functionCallingMode } },\n }),\n };\n if (options.thinking?.enabled && model.reasoning) {\n const thinkingConfig = { includeThoughts: true };\n if (options.thinking.level !== undefined) {\n thinkingConfig.thinkingLevel = THINKING_LEVEL_MAP[options.thinking.level];\n }\n else if (options.thinking.budgetTokens !== undefined) {\n thinkingConfig.thinkingBudget = options.thinking.budgetTokens;\n }\n config.thinkingConfig = thinkingConfig;\n }\n else if (model.reasoning && options.thinking && !options.thinking.enabled) {\n config.thinkingConfig = getDisabledThinkingConfig(model);\n }\n if (options.signal) {\n if (options.signal.aborted) {\n throw new Error(\"Request aborted\");\n }\n config.abortSignal = options.signal;\n }\n const params = {\n model: model.id,\n contents,\n config,\n };\n return params;\n}\nfunction isGemini3ProModel(model) {\n return /gemini-3(?:\\.\\d+)?-pro/.test(model.id.toLowerCase());\n}\nfunction isGemini3FlashModel(model) {\n const id = model.id.toLowerCase();\n return /gemini-3(?:\\.\\d+)?-flash/.test(id) || id === \"gemini-flash-latest\" || id === \"gemini-flash-lite-latest\";\n}\nfunction getDisabledThinkingConfig(model) {\n // Google docs: Gemini 3.1 Pro cannot disable thinking, and Gemini 3 Flash / Flash-Lite\n // do not support full thinking-off either. For Gemini 3 models, use the lowest supported\n // thinkingLevel without includeThoughts so hidden thinking remains invisible to pi.\n const geminiModel = model;\n if (isGemini3ProModel(geminiModel)) {\n return { thinkingLevel: ThinkingLevel.LOW };\n }\n if (isGemini3FlashModel(geminiModel)) {\n return { thinkingLevel: ThinkingLevel.MINIMAL };\n }\n // Gemini 2.x supports disabling via thinkingBudget = 0.\n return { thinkingBudget: 0 };\n}\nfunction getGemini3ThinkingLevel(effort, model) {\n if (isGemini3ProModel(model)) {\n switch (effort) {\n case \"minimal\":\n case \"low\":\n return \"LOW\";\n case \"medium\":\n case \"high\":\n return \"HIGH\";\n }\n }\n switch (effort) {\n case \"minimal\":\n return \"MINIMAL\";\n case \"low\":\n return \"LOW\";\n case \"medium\":\n return \"MEDIUM\";\n case \"high\":\n return \"HIGH\";\n }\n}\nfunction getGoogleBudget(model, effort, customBudgets) {\n if (customBudgets?.[effort] !== undefined) {\n return customBudgets[effort];\n }\n if (model.id.includes(\"2.5-pro\")) {\n const budgets = {\n minimal: 128,\n low: 2048,\n medium: 8192,\n high: 32768,\n };\n return budgets[effort];\n }\n if (model.id.includes(\"2.5-flash\")) {\n const budgets = {\n minimal: 128,\n low: 2048,\n medium: 8192,\n high: 24576,\n };\n return budgets[effort];\n }\n return -1;\n}\n//# sourceMappingURL=google-vertex.js.map"],"x_google_ignoreList":[0],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"google-vertex-BXRKa49Y.mjs","names":[],"sources":["../node_modules/.pnpm/@earendil-works+pi-ai@0.84.1_ws@8.21.3_zod@4.4.3/node_modules/@earendil-works/pi-ai/dist/api/google-vertex.js"],"sourcesContent":["import { GoogleGenAI, ResourceScope, ThinkingLevel, } from \"@google/genai\";\nimport { calculateCost, clampThinkingLevel } from \"../models.js\";\nimport { formatProviderError, normalizeProviderError } from \"../utils/error-body.js\";\nimport { AssistantMessageEventStream } from \"../utils/event-stream.js\";\nimport { providerHeadersToRecord } from \"../utils/headers.js\";\nimport { getProviderEnvValue } from \"../utils/provider-env.js\";\nimport { sanitizeSurrogates } from \"../utils/sanitize-unicode.js\";\nimport { convertMessages, convertTools, isThinkingPart, mapStopReason, resolveGoogleFunctionCallingMode, retainThoughtSignature, retryGoogleRequest, supportsGoogleStrictToolSampling, } from \"./google-shared.js\";\nimport { buildBaseOptions } from \"./simple-options.js\";\nconst API_VERSION = \"v1\";\nconst GCP_VERTEX_CREDENTIALS_MARKER = \"gcp-vertex-credentials\";\nconst THINKING_LEVEL_MAP = {\n THINKING_LEVEL_UNSPECIFIED: ThinkingLevel.THINKING_LEVEL_UNSPECIFIED,\n MINIMAL: ThinkingLevel.MINIMAL,\n LOW: ThinkingLevel.LOW,\n MEDIUM: ThinkingLevel.MEDIUM,\n HIGH: ThinkingLevel.HIGH,\n};\n// Counter for generating unique tool call IDs\nlet toolCallCounter = 0;\nexport const stream = (model, context, options) => {\n const stream = new AssistantMessageEventStream();\n (async () => {\n const output = {\n role: \"assistant\",\n content: [],\n api: \"google-vertex\",\n provider: model.provider,\n model: model.id,\n usage: {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n totalTokens: 0,\n cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n },\n stopReason: \"pending\",\n timestamp: Date.now(),\n };\n try {\n if (options?.fetch && options.fetch !== globalThis.fetch) {\n throw new Error(\"Custom fetch is not supported by the Google Vertex adapter\");\n }\n const apiKey = resolveApiKey(options);\n // Create the client using either a Vertex API key, if provided, or ADC with project and location\n const client = apiKey\n ? createClientWithApiKey(model, apiKey, options?.headers)\n : createClient(model, resolveProject(options), resolveLocation(options), options?.headers, options?.env);\n let params = buildParams(model, context, options);\n const nextParams = await options?.onPayload?.(params, model);\n if (nextParams !== undefined) {\n params = nextParams;\n }\n const googleStream = await retryGoogleRequest(() => client.models.generateContentStream(params), options);\n stream.push({ type: \"start\", partial: output });\n let currentBlock = null;\n const blocks = output.content;\n const blockIndex = () => blocks.length - 1;\n for await (const chunk of googleStream) {\n // Vertex uses the same @google/genai GenerateContentResponse type as Gemini.\n // responseId is documented there as an output-only identifier for each response.\n output.responseId ||= chunk.responseId;\n const candidate = chunk.candidates?.[0];\n if (candidate?.content?.parts) {\n for (const part of candidate.content.parts) {\n if (part.text !== undefined) {\n const isThinking = isThinkingPart(part);\n if (!currentBlock ||\n (isThinking && currentBlock.type !== \"thinking\") ||\n (!isThinking && currentBlock.type !== \"text\")) {\n if (currentBlock) {\n if (currentBlock.type === \"text\") {\n stream.push({\n type: \"text_end\",\n contentIndex: blocks.length - 1,\n content: currentBlock.text,\n partial: output,\n });\n }\n else {\n stream.push({\n type: \"thinking_end\",\n contentIndex: blockIndex(),\n content: currentBlock.thinking,\n partial: output,\n });\n }\n }\n if (isThinking) {\n currentBlock = { type: \"thinking\", thinking: \"\", thinkingSignature: undefined };\n output.content.push(currentBlock);\n stream.push({ type: \"thinking_start\", contentIndex: blockIndex(), partial: output });\n }\n else {\n currentBlock = { type: \"text\", text: \"\" };\n output.content.push(currentBlock);\n stream.push({ type: \"text_start\", contentIndex: blockIndex(), partial: output });\n }\n }\n if (currentBlock.type === \"thinking\") {\n currentBlock.thinking += part.text;\n currentBlock.thinkingSignature = retainThoughtSignature(currentBlock.thinkingSignature, part.thoughtSignature);\n stream.push({\n type: \"thinking_delta\",\n contentIndex: blockIndex(),\n delta: part.text,\n partial: output,\n });\n }\n else {\n currentBlock.text += part.text;\n currentBlock.textSignature = retainThoughtSignature(currentBlock.textSignature, part.thoughtSignature);\n stream.push({\n type: \"text_delta\",\n contentIndex: blockIndex(),\n delta: part.text,\n partial: output,\n });\n }\n }\n if (part.functionCall) {\n if (currentBlock) {\n if (currentBlock.type === \"text\") {\n stream.push({\n type: \"text_end\",\n contentIndex: blockIndex(),\n content: currentBlock.text,\n partial: output,\n });\n }\n else {\n stream.push({\n type: \"thinking_end\",\n contentIndex: blockIndex(),\n content: currentBlock.thinking,\n partial: output,\n });\n }\n currentBlock = null;\n }\n const providedId = part.functionCall.id;\n const needsNewId = !providedId || output.content.some((b) => b.type === \"toolCall\" && b.id === providedId);\n const toolCallId = needsNewId\n ? `${part.functionCall.name}_${Date.now()}_${++toolCallCounter}`\n : providedId;\n const toolCall = {\n type: \"toolCall\",\n id: toolCallId,\n name: part.functionCall.name || \"\",\n arguments: part.functionCall.args ?? {},\n ...(part.thoughtSignature && { thoughtSignature: part.thoughtSignature }),\n };\n output.content.push(toolCall);\n stream.push({ type: \"toolcall_start\", contentIndex: blockIndex(), partial: output });\n stream.push({\n type: \"toolcall_delta\",\n contentIndex: blockIndex(),\n delta: JSON.stringify(toolCall.arguments),\n partial: output,\n });\n stream.push({ type: \"toolcall_end\", contentIndex: blockIndex(), toolCall, partial: output });\n }\n }\n }\n if (candidate?.finishReason) {\n output.rawStopReason = candidate.finishReason;\n output.stopReason = mapStopReason(candidate.finishReason);\n if (output.content.some((b) => b.type === \"toolCall\")) {\n output.stopReason = \"toolUse\";\n }\n }\n if (chunk.usageMetadata) {\n output.usage = {\n input: (chunk.usageMetadata.promptTokenCount || 0) - (chunk.usageMetadata.cachedContentTokenCount || 0),\n output: (chunk.usageMetadata.candidatesTokenCount || 0) + (chunk.usageMetadata.thoughtsTokenCount || 0),\n cacheRead: chunk.usageMetadata.cachedContentTokenCount || 0,\n cacheWrite: 0,\n reasoning: chunk.usageMetadata.thoughtsTokenCount || 0,\n totalTokens: chunk.usageMetadata.totalTokenCount || 0,\n cost: {\n input: 0,\n output: 0,\n cacheRead: 0,\n cacheWrite: 0,\n total: 0,\n },\n };\n calculateCost(model, output.usage);\n }\n }\n if (currentBlock) {\n if (currentBlock.type === \"text\") {\n stream.push({\n type: \"text_end\",\n contentIndex: blockIndex(),\n content: currentBlock.text,\n partial: output,\n });\n }\n else {\n stream.push({\n type: \"thinking_end\",\n contentIndex: blockIndex(),\n content: currentBlock.thinking,\n partial: output,\n });\n }\n }\n if (options?.signal?.aborted) {\n throw new Error(\"Request was aborted\");\n }\n if (output.stopReason === \"pending\") {\n throw new Error(\"Google Vertex stream ended without a finish reason\");\n }\n if (output.stopReason === \"aborted\" || output.stopReason === \"error\") {\n const errorMessage = output.rawStopReason\n ? `Provider stopped with: ${output.rawStopReason}`\n : \"An unknown error occurred\";\n throw new Error(errorMessage);\n }\n stream.push({ type: \"done\", reason: output.stopReason, message: output });\n stream.end();\n }\n catch (error) {\n // Remove internal index property used during streaming\n for (const block of output.content) {\n if (\"index\" in block) {\n delete block.index;\n }\n }\n output.stopReason = options?.signal?.aborted ? \"aborted\" : \"error\";\n output.errorMessage = formatProviderError(normalizeProviderError(error));\n stream.push({ type: \"error\", reason: output.stopReason, error: output });\n stream.end();\n }\n })();\n return stream;\n};\nexport const streamSimple = (model, context, options) => {\n const base = buildBaseOptions(model, context, options, undefined);\n if (!options?.reasoning) {\n return stream(model, context, {\n ...base,\n thinking: { enabled: false },\n });\n }\n const clampedReasoning = clampThinkingLevel(model, options.reasoning);\n const effort = (clampedReasoning === \"off\" ? \"high\" : clampedReasoning);\n const geminiModel = model;\n if (isGemini3ProModel(geminiModel) || isGemini3FlashModel(geminiModel)) {\n return stream(model, context, {\n ...base,\n thinking: {\n enabled: true,\n level: getGemini3ThinkingLevel(effort, geminiModel),\n },\n });\n }\n return stream(model, context, {\n ...base,\n thinking: {\n enabled: true,\n budgetTokens: getGoogleBudget(geminiModel, effort, options.thinkingBudgets),\n },\n });\n};\nfunction createClient(model, project, location, optionsHeaders, env) {\n const googleAuthOptions = buildGoogleAuthOptions(env);\n return new GoogleGenAI({\n vertexai: true,\n project,\n location,\n apiVersion: API_VERSION,\n ...(googleAuthOptions ? { googleAuthOptions } : {}),\n httpOptions: buildHttpOptions(model, optionsHeaders),\n });\n}\nfunction createClientWithApiKey(model, apiKey, optionsHeaders) {\n return new GoogleGenAI({\n vertexai: true,\n apiKey,\n apiVersion: API_VERSION,\n httpOptions: buildHttpOptions(model, optionsHeaders),\n });\n}\nfunction buildHttpOptions(model, optionsHeaders) {\n const httpOptions = {};\n const baseUrl = resolveCustomBaseUrl(model.baseUrl);\n if (baseUrl) {\n httpOptions.baseUrl = baseUrl;\n httpOptions.baseUrlResourceScope = ResourceScope.COLLECTION;\n if (baseUrlIncludesApiVersion(baseUrl)) {\n httpOptions.apiVersion = \"\";\n }\n }\n const headers = providerHeadersToRecord({ ...model.headers, ...optionsHeaders });\n if (headers) {\n httpOptions.headers = headers;\n }\n return Object.keys(httpOptions).length > 0 ? httpOptions : undefined;\n}\nfunction resolveCustomBaseUrl(baseUrl) {\n const trimmed = baseUrl.trim();\n if (!trimmed || trimmed.includes(\"{location}\")) {\n return undefined;\n }\n return trimmed;\n}\nfunction baseUrlIncludesApiVersion(baseUrl) {\n try {\n const url = new URL(baseUrl);\n return url.pathname.split(\"/\").some((part) => /^v\\d+(?:beta\\d*)?$/.test(part));\n }\n catch {\n return /(?:^|\\/)v\\d+(?:beta\\d*)?(?:\\/|$)/.test(baseUrl);\n }\n}\nfunction buildGoogleAuthOptions(env) {\n const keyFilename = getProviderEnvValue(\"GOOGLE_APPLICATION_CREDENTIALS\", env);\n return keyFilename ? { keyFilename } : undefined;\n}\nfunction resolveApiKey(options) {\n const apiKey = options?.apiKey?.trim();\n if (!apiKey || apiKey === GCP_VERTEX_CREDENTIALS_MARKER || isPlaceholderApiKey(apiKey)) {\n return undefined;\n }\n return apiKey;\n}\nfunction isPlaceholderApiKey(apiKey) {\n return /^<[^>]+>$/.test(apiKey);\n}\nfunction resolveProject(options) {\n const project = options?.project ||\n getProviderEnvValue(\"GOOGLE_CLOUD_PROJECT\", options?.env) ||\n getProviderEnvValue(\"GCLOUD_PROJECT\", options?.env);\n if (!project) {\n throw new Error(\"Vertex AI requires a project ID. Set GOOGLE_CLOUD_PROJECT/GCLOUD_PROJECT or pass project in options.\");\n }\n return project;\n}\nfunction resolveLocation(options) {\n const location = options?.location || getProviderEnvValue(\"GOOGLE_CLOUD_LOCATION\", options?.env);\n if (!location) {\n throw new Error(\"Vertex AI requires a location. Set GOOGLE_CLOUD_LOCATION or pass location in options.\");\n }\n return location;\n}\nfunction buildParams(model, context, options = {}) {\n const contents = convertMessages(model, context);\n const generationConfig = {};\n if (options.temperature !== undefined) {\n generationConfig.temperature = options.temperature;\n }\n if (options.maxTokens !== undefined) {\n generationConfig.maxOutputTokens = options.maxTokens;\n }\n const functionCallingMode = context.tools?.length\n ? resolveGoogleFunctionCallingMode(context.tools, options.toolChoice, supportsGoogleStrictToolSampling(model.id))\n : undefined;\n const config = {\n ...(Object.keys(generationConfig).length > 0 && generationConfig),\n ...(context.systemPrompt && { systemInstruction: sanitizeSurrogates(context.systemPrompt) }),\n ...(context.tools && context.tools.length > 0 && { tools: convertTools(context.tools) }),\n ...(functionCallingMode !== undefined && {\n toolConfig: { functionCallingConfig: { mode: functionCallingMode } },\n }),\n };\n if (options.thinking?.enabled && model.reasoning) {\n const thinkingConfig = { includeThoughts: true };\n if (options.thinking.level !== undefined) {\n thinkingConfig.thinkingLevel = THINKING_LEVEL_MAP[options.thinking.level];\n }\n else if (options.thinking.budgetTokens !== undefined) {\n thinkingConfig.thinkingBudget = options.thinking.budgetTokens;\n }\n config.thinkingConfig = thinkingConfig;\n }\n else if (model.reasoning && options.thinking && !options.thinking.enabled) {\n config.thinkingConfig = getDisabledThinkingConfig(model);\n }\n if (options.signal) {\n if (options.signal.aborted) {\n throw new Error(\"Request aborted\");\n }\n config.abortSignal = options.signal;\n }\n const params = {\n model: model.id,\n contents,\n config,\n };\n return params;\n}\nfunction isGemini3ProModel(model) {\n return /gemini-3(?:\\.\\d+)?-pro/.test(model.id.toLowerCase());\n}\nfunction isGemini3FlashModel(model) {\n const id = model.id.toLowerCase();\n return /gemini-3(?:\\.\\d+)?-flash/.test(id) || id === \"gemini-flash-latest\" || id === \"gemini-flash-lite-latest\";\n}\nfunction getDisabledThinkingConfig(model) {\n // Google docs: Gemini 3.1 Pro cannot disable thinking, and Gemini 3 Flash / Flash-Lite\n // do not support full thinking-off either. For Gemini 3 models, use the lowest supported\n // thinkingLevel without includeThoughts so hidden thinking remains invisible to pi.\n const geminiModel = model;\n if (isGemini3ProModel(geminiModel)) {\n return { thinkingLevel: ThinkingLevel.LOW };\n }\n if (isGemini3FlashModel(geminiModel)) {\n return { thinkingLevel: ThinkingLevel.MINIMAL };\n }\n // Gemini 2.x supports disabling via thinkingBudget = 0.\n return { thinkingBudget: 0 };\n}\nfunction getGemini3ThinkingLevel(effort, model) {\n if (isGemini3ProModel(model)) {\n switch (effort) {\n case \"minimal\":\n case \"low\":\n return \"LOW\";\n case \"medium\":\n case \"high\":\n return \"HIGH\";\n }\n }\n switch (effort) {\n case \"minimal\":\n return \"MINIMAL\";\n case \"low\":\n return \"LOW\";\n case \"medium\":\n return \"MEDIUM\";\n case \"high\":\n return \"HIGH\";\n }\n}\nfunction getGoogleBudget(model, effort, customBudgets) {\n if (customBudgets?.[effort] !== undefined) {\n return customBudgets[effort];\n }\n if (model.id.includes(\"2.5-pro\")) {\n const budgets = {\n minimal: 128,\n low: 2048,\n medium: 8192,\n high: 32768,\n };\n return budgets[effort];\n }\n if (model.id.includes(\"2.5-flash\")) {\n const budgets = {\n minimal: 128,\n low: 2048,\n medium: 8192,\n high: 24576,\n };\n return budgets[effort];\n }\n return -1;\n}\n//# sourceMappingURL=google-vertex.js.map"],"x_google_ignoreList":[0],"mappings":"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"}
|
package/dist/host.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { a as registerVisionCompanions, t as applyPiPackage } from "./runtime-
|
|
2
|
+
import { a as registerVisionCompanions, t as applyPiPackage } from "./runtime-C6_pOPmL.mjs";
|
|
3
3
|
import { t as resolvePiPackage } from "./source-0sA5z08z.mjs";
|
|
4
4
|
import { createRequire } from "node:module";
|
|
5
5
|
import { readFile } from "node:fs/promises";
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/engine.ts","../src/compatibility.ts","../src/mcp-config.ts","../src/source.ts","../src/index.ts"],"mappings":";;;;;UA6BiB;;EAEf;;EAEA;;;;;;;;EAQA,2BAA2B;;;iBAIb,gBAAgB;UAUtB;EACR;EACA;;;;;;;;iBAyBoB,0BACpB,qBACA;EAAW;EAAoB,QAAQ;IACtC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6FK,yBACd,KAAK,SACL,kBAAkB,iBAAiB,0BACnC;EAAU,KAAK;;;cAmGJ;cACA;iBAES,MAAM,KAAK,SAAS,SAAQ,eAAoB;;;UCzR5D;EACR,OAAO;EACP;;EAEA;;;;;;;;;UAUQ,oBAAoB;EAC5B;;cAQW;cAKA;cAKA;cAYA,mBAAmB,SAAS,eAAe,SAAS,eAAe;cA+NnE,eAAe,SAAS,eAAe;cA4BvC,kBAAkB,SAAS,eAAe;cA+B1C,WAAW,SAAS,eAAe;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/engine.ts","../src/compatibility.ts","../src/mcp-config.ts","../src/source.ts","../src/index.ts"],"mappings":";;;;;UA6BiB;;EAEf;;EAEA;;;;;;;;EAQA,2BAA2B;;;iBAIb,gBAAgB;UAUtB;EACR;EACA;;;;;;;;iBAyBoB,0BACpB,qBACA;EAAW;EAAoB,QAAQ;IACtC,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA6FK,yBACd,KAAK,SACL,kBAAkB,iBAAiB,0BACnC;EAAU,KAAK;;;cAmGJ;cACA;iBAES,MAAM,KAAK,SAAS,SAAQ,eAAoB;;;UCzR5D;EACR,OAAO;EACP;;EAEA;;;;;;;;;UAUQ,oBAAoB;EAC5B;;cAQW;cAKA;cAKA;cAYA,mBAAmB,SAAS,eAAe,SAAS,eAAe;cA+NnE,eAAe,SAAS,eAAe;cA4BvC,kBAAkB,SAAS,eAAe;cA+B1C,WAAW,SAAS,eAAe;cA8InC,aAAa,SAAS,eAAe;iBAgHlC,WAAW,iBAAiB;iBAI5B,aAAa,gBAAgB;iBAO7B,kBAAkB,qBAAqB,uBAAuB;iBAS9D,uBAAuB,mBAAmB;iBAI1C,yBAAyB,mBAAmB;;;KCllBvD,gBAAgB;UAEJ;EACf;EACA;EACA;EACA;EACA;EACA,MAAM;EACN;EACA;EACA,UAAU;EACV;;UAGe;EACf;EACA;;UAGe;EACf,SAAS;EACT,SAAS;EACT,UAAU;EACV;;iBA6Cc,oBAAoB,aAAa;EAA8B,SAAS,YAAY;EAAc;;iBAoElG,mBAAmB,aAAa,wBAA4B;;iBAsD5D,eAAe,QAAQ;;;iBC5EjB,iBAAiB,gBAAgB,eAAsB,QAAQ;;;;;;;;iBChH/D,eAAe,KAAK,oBAAoB,QAAQ"}
|
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
import { a as registerVisionCompanions } from "./runtime-
|
|
2
|
+
import { a as registerVisionCompanions } from "./runtime-C6_pOPmL.mjs";
|
|
3
3
|
import { t as resolvePiPackage } from "./source-0sA5z08z.mjs";
|
|
4
4
|
import { applyPiHost, applyPreparedPiHost, manifestForInstalled, preparePiHost } from "./host.mjs";
|
|
5
|
-
import { a as
|
|
6
|
-
import { n as convertPiMcpConfig, r as renderMcpPatch, t as collectPiMcpServers } from "./mcp-config-jmzbgdHa.mjs";
|
|
5
|
+
import { a as CONTEXT_RULES, c as PI_AI_PACKAGES, d as UI_CONTEXT_RULES, f as ruleForApi, g as ruleForUiContextProperty, h as ruleForHostImport, i as API_RULES, l as PI_CODING_AGENT_PACKAGES, m as ruleForEvent, n as convertPiMcpConfig, o as EVENT_RULES, p as ruleForContextProperty, r as renderMcpPatch, s as HOST_IMPORT_RULES, t as collectPiMcpServers, u as PI_TUI_PACKAGES } from "./mcp-config-2s_i_H3R.mjs";
|
|
7
6
|
import { readFile } from "node:fs/promises";
|
|
8
7
|
import { existsSync } from "node:fs";
|
|
9
8
|
import { dirname, join } from "node:path";
|
|
@@ -234,7 +233,7 @@ async function apply(ctx, config = {}) {
|
|
|
234
233
|
* @returns the compatibility report.
|
|
235
234
|
*/
|
|
236
235
|
async function analyzePackage(pkg) {
|
|
237
|
-
const { analyzePackage: run } = await import("./analyzer-
|
|
236
|
+
const { analyzePackage: run } = await import("./analyzer-dRAMYI3l.mjs");
|
|
238
237
|
return run(pkg);
|
|
239
238
|
}
|
|
240
239
|
//#endregion
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/engine.ts","../src/index.ts"],"sourcesContent":["// The pi2dsh engine: ONE installed copy of the bridge that mounts every Pi\n// package the user has added to their DSH profile.\n//\n// dsh plugin --profile p add pi2dsh ← the engine (this plugin)\n// dsh plugin --profile p add @kassing/pi-vision ← plain npm dependency\n// dsh plugin --profile p add pi-vision-tool ← plain npm dependency\n//\n// DSH's plugin manager records only packages that declare `dsh.bundle` as\n// profile layers; everything else stays an ordinary dependency (\"a plain\n// library is fine\"). The engine reads the profile manifest's DIRECT\n// dependencies — every entry there was an explicit `dsh plugin add` — and\n// mounts each package that identifies as a Pi package, all through one\n// bridge instance: one model ledger, one command space, one upgrade unit.\n//\n// Discovery is manifest-driven, never a node_modules scan (the lesson from\n// Prettier 3 dropping directory-based plugin discovery): the dependency list\n// is the user's explicit intent, and package identification uses the same\n// Pi markers `resolvePiPackage` has always used (the `pi` manifest field,\n// with Pi's directory conventions as fallback).\n\nimport { readFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { applyPreparedPiHost, preparePiHost, type PreparedPiHostPackage } from './host.js'\nimport { registerVisionCompanions } from './runtime.js'\nimport { resolvePiPackage } from './source.js'\n\nexport interface EngineConfig {\n /** Mount exactly these packages (skips discovery). */\n packages?: string[]\n /** Never mount these packages even when discovered. */\n exclude?: string[]\n /**\n * Image-admission companion routes. Default: AUTOMATIC — every text-only\n * llm route gets a \\`<route>-vision\\` companion that admits pasted images\n * (a mounted vision extension analyzes them; without one the image is\n * materialized to a file any image-capable tool can read). \\`false\\`\n * turns companions off; an explicit \\`{ <route>: [modelIds] }\\` narrows.\n */\n visionCompanions?: false | Record<string, readonly string[]>\n}\n\n/** Locate the DSH profile root: the nearest ancestor holding cordis.yml. */\nexport function findProfileRoot(start: string): string | undefined {\n let dir = start\n for (;;) {\n if (existsSync(join(dir, 'cordis.yml')) && existsSync(join(dir, 'package.json'))) return dir\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\ninterface DiscoveredPackage {\n name: string\n dir: string\n}\n\ninterface ProfileManifest {\n dependencies?: Record<string, string>\n dsh?: { profile?: { bundles?: string[] } }\n}\n\nasync function readProfileManifest(profileRoot: string): Promise<ProfileManifest> {\n return JSON.parse(await readFile(join(profileRoot, 'package.json'), 'utf8')) as ProfileManifest\n}\n\nfunction resolveDependencyDir(profileRoot: string, name: string): string | undefined {\n // Direct dependencies of the profile live under its node_modules by name\n // (pnpm links them there); resolving by path needs no exports gymnastics.\n const dir = join(profileRoot, 'node_modules', name)\n return existsSync(join(dir, 'package.json')) ? dir : undefined\n}\n\n/**\n * The profile's direct dependencies that identify as Pi packages: not the\n * engine itself, not a `dsh.bundle` (those are DSH plugins, not Pi\n * packages), carrying either Pi's `pi` manifest field or extension sources\n * under Pi's directory conventions.\n */\nexport async function discoverProfilePiPackages(\n profileRoot: string,\n options: { exclude?: string[], warn?: (message: string) => void } = {},\n): Promise<DiscoveredPackage[]> {\n const warn = options.warn ?? (() => {})\n const excluded = new Set(options.exclude ?? [])\n const manifest = await readProfileManifest(profileRoot)\n const discovered: DiscoveredPackage[] = []\n for (const name of Object.keys(manifest.dependencies ?? {})) {\n if (name === 'pi2dsh' || excluded.has(name)) continue\n const dir = resolveDependencyDir(profileRoot, name)\n if (dir === undefined) {\n warn(`[pi2dsh engine] dependency ${JSON.stringify(name)} is not installed under the profile; skipping`)\n continue\n }\n let packageJson: Record<string, unknown>\n try {\n packageJson = JSON.parse(await readFile(join(dir, 'package.json'), 'utf8')) as Record<string, unknown>\n } catch (error) {\n warn(`[pi2dsh engine] cannot read ${name}/package.json (${error instanceof Error ? error.message : String(error)}); skipping`)\n continue\n }\n // A dsh.bundle-declaring package is a DSH plugin layer, never a Pi package.\n if ((packageJson.dsh as { bundle?: unknown } | undefined)?.bundle !== undefined) continue\n if (packageJson.pi !== undefined && typeof packageJson.pi === 'object') {\n discovered.push({ name, dir })\n continue\n }\n // No `pi` field: fall back to Pi's directory conventions via the same\n // resolver every other mount path uses (a package with zero extension\n // sources is a plain library and stays unmounted).\n try {\n const pkg = await resolvePiPackage(dir)\n try {\n if (pkg.resources.extensions.length > 0) discovered.push({ name, dir })\n } finally {\n await pkg.dispose()\n }\n } catch {\n // Not resolvable as a Pi package — a plain library.\n }\n }\n return discovered\n}\n\ninterface AgentScopedMount {\n ready: Promise<void>\n /** Set when the mount failed; the agent then runs as a plain DSH agent. */\n failure?: string\n}\n\n/** The loose shapes of the official DSH seams this file consumes. */\ninterface AgentLike {\n ctx: Context\n}\ninterface EngineHostContext {\n /** Un-injected reflection access (the ctx.get('loader') idiom): the engine\n * must not hard-depend on the agent registry — compositions without one\n * (bare test hosts) simply have no agents to mount for. */\n get?(name: string): unknown\n tools?: { schemas?(scope: unknown): Array<{ name: string }> }\n on(name: string, listener: (...args: never[]) => unknown): () => void\n}\ninterface AgentRegistryLike {\n roots?(): AgentLike[]\n}\n\n/**\n * The single mount path on every DSH surface: one Pi runtime per root Agent.\n *\n * Pi instantiates its extensions once per session; DSH's twin of that scope is\n * the Agent with its public `agent.ctx` (\"contributions are agent-local,\n * unwind on disposal\"). Mounting is driven purely by official core seams, so\n * the same semantics hold on the TUI, web, headless, ACP and config-declared\n * agents alike:\n *\n * - `agent/created` fires on every publication path before the loop can run\n * a first turn; it eagerly starts that agent's mount.\n * - `system-prompt/assemble` (awaited waterfall, runs in every step's\n * preStep) gates the assembly on the mount and patches the pre-waterfall\n * tools snapshot from the official scoped projection `tools.schemas()` —\n * stock DSH collects `assembly.tools` before dispatching the waterfall,\n * so a mount that lands during the wait would otherwise miss turn one.\n * - `tools/pre-execute` (awaited waterfall) closes the same window for\n * direct executions that bypass assembly.\n *\n * `agent/session-start` deliberately is NOT the trigger: DSH documents it as a\n * veto-less notification that cannot gate startup. The waterfalls above are\n * the officially awaited seams, and the exact pattern of registering onto a\n * foreign agent's ctx from a lifecycle event is what DSH's own schedule\n * plugin ships.\n *\n * A mount failure never takes the Agent down: the agent keeps running as a\n * plain DSH agent, the failure is reported loudly once, and only the Pi\n * packages are missing — the capability-gap discipline, not a rollback.\n */\nexport function installAgentScopedMounts(\n ctx: Context,\n preparedPackages: Promise<readonly PreparedPiHostPackage[]>,\n report: { warn(message: string): void },\n): void {\n const host = ctx as unknown as EngineHostContext\n const mounts = new WeakMap<object, AgentScopedMount>()\n\n const registry = (): AgentRegistryLike | undefined => {\n try {\n return host.get?.('agents') as AgentRegistryLike | undefined\n } catch {\n return undefined\n }\n }\n\n const isRootAgent = (agent: object): boolean => {\n // Subagents keep Pi's own sub-session semantics through the session\n // bridge; only runtime roots receive a Pi runtime (the same distinction\n // DSH's schedule plugin draws via agents.roots()).\n const agents = registry()\n const roots = agents?.roots\n if (typeof roots !== 'function') return true\n try {\n return (roots.call(agents) as unknown[]).includes(agent)\n } catch {\n return true\n }\n }\n\n const ensureMount = (agent: AgentLike): AgentScopedMount => {\n let mount = mounts.get(agent)\n if (mount === undefined) {\n const started: AgentScopedMount = { ready: Promise.resolve() }\n started.ready = preparedPackages.then(async prepared => {\n if (prepared.length === 0) return\n try {\n await applyPreparedPiHost(agent.ctx, prepared, agent as unknown as Record<string, unknown>)\n } catch (error) {\n // Loud, once per agent; the gates resolve so the plain DSH agent\n // keeps working. Faking success is forbidden — the message names\n // what is missing.\n started.failure = error instanceof Error ? error.message : String(error)\n report.warn(`[pi2dsh engine] Pi packages failed to mount for this agent; it continues without them: ${started.failure}`)\n }\n })\n mounts.set(agent, started)\n mount = started\n }\n return mount\n }\n\n // Eager start on publication. `agent/created` reaches host-level listeners\n // on every create/resume/config path, before the loop can open a turn.\n host.on('agent/created', ((payload: { agent: AgentLike }) => {\n if (isRootAgent(payload.agent)) ensureMount(payload.agent)\n }) as never)\n\n // Correctness boundary #1: no prompt assembly for a root agent proceeds\n // before its Pi runtime is mounted, and the tools snapshot taken before\n // this waterfall is reconciled against the official scoped projection.\n host.on('system-prompt/assemble', (async (\n assembly: { tools: Array<{ name: string }> },\n context: { agent?: AgentLike },\n next: () => Promise<unknown>,\n ) => {\n const agent = context.agent\n if (agent !== undefined && isRootAgent(agent)) {\n await ensureMount(agent).ready\n const schemas = host.tools?.schemas\n if (typeof schemas === 'function') {\n const present = new Set(assembly.tools.map(tool => tool.name))\n for (const schema of schemas.call(host.tools, agent)) {\n if (!present.has(schema.name)) assembly.tools.push(schema)\n }\n }\n }\n return next()\n }) as never)\n\n // Correctness boundary #2: tool execution for a root agent waits for the\n // same mount (serially awaited by the tool runtime before dispatch).\n host.on('tools/pre-execute', (async (\n exec: { agent?: AgentLike },\n next: () => Promise<unknown>,\n ) => {\n if (exec.agent !== undefined && isRootAgent(exec.agent)) await ensureMount(exec.agent).ready\n return next()\n }) as never)\n\n // Backfill: agents published before this plugin finished loading (a surface\n // that skips the official await-the-loader pattern DSH's headless runner\n // uses). Their next assembly still passes the gates above.\n void preparedPackages.then(() => {\n const agents = registry()\n const roots = agents?.roots\n if (typeof roots !== 'function') return\n for (const agent of roots.call(agents)) ensureMount(agent)\n })\n}\n\n/** Cordis plugin surface: `dsh plugin add pi2dsh` mounts this. */\nexport const name = 'pi2dsh'\nexport const inject = ['tools', 'systemPrompt', 'commands', 'skills']\n\nexport async function apply(ctx: Context, config: EngineConfig = {}): Promise<void> {\n // Same emission as the runtime's logger helper: the cordis logger AND the\n // console — profile logger levels must never hide what the engine mounted.\n const log = (ctx as unknown as { logger?: { info?(m: string): void, warn?(m: string): void } }).logger\n const warn = (message: string): void => { log?.warn?.(message); console.warn(message) }\n const info = (message: string): void => { log?.info?.(message); console.log(message) }\n\n // The loader resolves plugins against the profile's baseUrl; that IS the\n // profile root. The ancestor walk from the installed engine is the\n // fallback for compositions without a loader (tests, hand-built hosts).\n const baseUrl = (ctx as unknown as { baseUrl?: string }).baseUrl\n const profileRoot = (baseUrl !== undefined ? findProfileRoot(fileURLToPath(new URL('.', baseUrl))) : undefined)\n ?? findProfileRoot(dirname(fileURLToPath(import.meta.url)))\n if (profileRoot === undefined) {\n throw new Error('pi2dsh engine: no DSH profile root (cordis.yml + package.json) above the installed engine — is pi2dsh installed via `dsh plugin add pi2dsh`?')\n }\n\n // The single mount path, before any await: gates and lifecycle listeners\n // must exist the moment a surface can publish its first Agent. Package\n // preparation resolves behind this promise; the gates hold each agent's\n // first assembly until its own mount lands.\n let resolvePrepared!: (prepared: readonly PreparedPiHostPackage[]) => void\n const preparedPackages = new Promise<readonly PreparedPiHostPackage[]>(resolve => {\n resolvePrepared = resolve\n })\n installAgentScopedMounts(ctx, preparedPackages, { warn })\n\n registerVisionCompanions(ctx, config.visionCompanions)\n\n try {\n // The host half, mounted exactly once regardless of packages or agents:\n // Pi's built-in provider directory, `/login`, and credential recovery.\n // Without it a fresh engine cannot run `/login openai-codex`: DSH treats\n // the unknown slash line as a model prompt and fails on the unrelated\n // default provider credential. Community packages join the same\n // SharedHostState (keyed on ctx.root), so host-level resources stay\n // single-instance no matter which agent scope mounts them.\n await applyPreparedPiHost(ctx, [{\n name: 'pi2dsh-builtins',\n rootUrl: new URL('.', import.meta.url),\n manifest: {\n schemaVersion: 1,\n package: { name: 'pi2dsh-builtins', version: '0.0.0', source: 'engine' },\n extensions: [],\n skillDirs: [],\n prompts: [],\n },\n }])\n\n const packages = Array.isArray(config.packages) && config.packages.length > 0\n ? config.packages.map(name => ({ name }))\n : await discoverProfilePiPackages(profileRoot, {\n ...(Array.isArray(config.exclude) ? { exclude: config.exclude } : {}),\n warn,\n })\n if (packages.length === 0) {\n info('[pi2dsh engine] no Pi packages installed in this profile yet — add one with: dsh plugin --profile <p> add <pi-package>')\n resolvePrepared([])\n return\n }\n info(`[pi2dsh engine] preparing ${packages.length} Pi package(s): ${packages.map(pkg => pkg.name).join(', ')}`)\n const prepared = await preparePiHost(\n { packages: packages.map(pkg => ({ name: pkg.name })) },\n join(profileRoot, 'package.json'),\n )\n // Host anchors, before the per-Agent gates open: every package's\n // HOST-level contributions (provider routes, OAuth accounts, /login,\n // credential recovery, companions, skills) exist from engine apply — a\n // surface with zero live Agents (web at boot) still advertises them, the\n // first Agent's model resolution finds its routes, and routes survive\n // Agent churn. Anchors serve no Agent; sessions belong to the per-Agent\n // instances the gates mount.\n await applyPreparedPiHost(ctx, prepared, undefined, { hostAnchor: true })\n resolvePrepared(prepared)\n } catch (error) {\n // The gates must never hang on a failed preparation; agents keep running\n // as plain DSH agents while the engine failure propagates loudly.\n resolvePrepared([])\n throw error\n }\n}\n","// Engine surface: `dsh plugin add pi2dsh` resolves this entry as a cordis\n// plugin (named exports, no default — a default export would make the\n// loader discard the function-plugin namespace).\nexport { apply, inject, name, discoverProfilePiPackages, findProfileRoot, installAgentScopedMounts, type EngineConfig } from './engine.js'\n\n// The CLI-only analysis surface loads lazily: its static-analysis dependency\n// (the 23 MB typescript compiler, an optional peer) must never be pulled\n// into a profile that installs the ENGINE. The dynamic import below keeps\n// the analyzer in its own chunk, off the engine's load path.\nimport type { CompatibilityReport, ResolvedPiPackage } from './types.js'\n\n/**\n * Static compatibility analysis of one resolved Pi package (CLI `inspect`).\n * @param pkg - the resolved package.\n * @returns the compatibility report.\n */\nexport async function analyzePackage(pkg: ResolvedPiPackage): Promise<CompatibilityReport> {\n const { analyzePackage: run } = await import('./analyzer.js')\n return run(pkg)\n}\n\nexport {\n API_RULES,\n CONTEXT_RULES,\n EVENT_RULES,\n HOST_IMPORT_RULES,\n PI_AI_PACKAGES,\n PI_CODING_AGENT_PACKAGES,\n PI_TUI_PACKAGES,\n UI_CONTEXT_RULES,\n ruleForApi,\n ruleForContextProperty,\n ruleForEvent,\n ruleForHostImport,\n ruleForUiContextProperty,\n} from './compatibility.js'\nexport { applyPiHost, applyPreparedPiHost, manifestForInstalled, preparePiHost } from './host.js'\nexport { collectPiMcpServers, convertPiMcpConfig, renderMcpPatch } from './mcp-config.js'\nexport { resolvePiPackage } from './source.js'\nexport type * from './types.js'\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/engine.ts","../src/index.ts"],"sourcesContent":["// The pi2dsh engine: ONE installed copy of the bridge that mounts every Pi\n// package the user has added to their DSH profile.\n//\n// dsh plugin --profile p add pi2dsh ← the engine (this plugin)\n// dsh plugin --profile p add @kassing/pi-vision ← plain npm dependency\n// dsh plugin --profile p add pi-vision-tool ← plain npm dependency\n//\n// DSH's plugin manager records only packages that declare `dsh.bundle` as\n// profile layers; everything else stays an ordinary dependency (\"a plain\n// library is fine\"). The engine reads the profile manifest's DIRECT\n// dependencies — every entry there was an explicit `dsh plugin add` — and\n// mounts each package that identifies as a Pi package, all through one\n// bridge instance: one model ledger, one command space, one upgrade unit.\n//\n// Discovery is manifest-driven, never a node_modules scan (the lesson from\n// Prettier 3 dropping directory-based plugin discovery): the dependency list\n// is the user's explicit intent, and package identification uses the same\n// Pi markers `resolvePiPackage` has always used (the `pi` manifest field,\n// with Pi's directory conventions as fallback).\n\nimport { readFile } from 'node:fs/promises'\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport type { Context } from '@deepseek-ai/cordis'\nimport { applyPreparedPiHost, preparePiHost, type PreparedPiHostPackage } from './host.js'\nimport { registerVisionCompanions } from './runtime.js'\nimport { resolvePiPackage } from './source.js'\n\nexport interface EngineConfig {\n /** Mount exactly these packages (skips discovery). */\n packages?: string[]\n /** Never mount these packages even when discovered. */\n exclude?: string[]\n /**\n * Image-admission companion routes. Default: AUTOMATIC — every text-only\n * llm route gets a \\`<route>-vision\\` companion that admits pasted images\n * (a mounted vision extension analyzes them; without one the image is\n * materialized to a file any image-capable tool can read). \\`false\\`\n * turns companions off; an explicit \\`{ <route>: [modelIds] }\\` narrows.\n */\n visionCompanions?: false | Record<string, readonly string[]>\n}\n\n/** Locate the DSH profile root: the nearest ancestor holding cordis.yml. */\nexport function findProfileRoot(start: string): string | undefined {\n let dir = start\n for (;;) {\n if (existsSync(join(dir, 'cordis.yml')) && existsSync(join(dir, 'package.json'))) return dir\n const parent = dirname(dir)\n if (parent === dir) return undefined\n dir = parent\n }\n}\n\ninterface DiscoveredPackage {\n name: string\n dir: string\n}\n\ninterface ProfileManifest {\n dependencies?: Record<string, string>\n dsh?: { profile?: { bundles?: string[] } }\n}\n\nasync function readProfileManifest(profileRoot: string): Promise<ProfileManifest> {\n return JSON.parse(await readFile(join(profileRoot, 'package.json'), 'utf8')) as ProfileManifest\n}\n\nfunction resolveDependencyDir(profileRoot: string, name: string): string | undefined {\n // Direct dependencies of the profile live under its node_modules by name\n // (pnpm links them there); resolving by path needs no exports gymnastics.\n const dir = join(profileRoot, 'node_modules', name)\n return existsSync(join(dir, 'package.json')) ? dir : undefined\n}\n\n/**\n * The profile's direct dependencies that identify as Pi packages: not the\n * engine itself, not a `dsh.bundle` (those are DSH plugins, not Pi\n * packages), carrying either Pi's `pi` manifest field or extension sources\n * under Pi's directory conventions.\n */\nexport async function discoverProfilePiPackages(\n profileRoot: string,\n options: { exclude?: string[], warn?: (message: string) => void } = {},\n): Promise<DiscoveredPackage[]> {\n const warn = options.warn ?? (() => {})\n const excluded = new Set(options.exclude ?? [])\n const manifest = await readProfileManifest(profileRoot)\n const discovered: DiscoveredPackage[] = []\n for (const name of Object.keys(manifest.dependencies ?? {})) {\n if (name === 'pi2dsh' || excluded.has(name)) continue\n const dir = resolveDependencyDir(profileRoot, name)\n if (dir === undefined) {\n warn(`[pi2dsh engine] dependency ${JSON.stringify(name)} is not installed under the profile; skipping`)\n continue\n }\n let packageJson: Record<string, unknown>\n try {\n packageJson = JSON.parse(await readFile(join(dir, 'package.json'), 'utf8')) as Record<string, unknown>\n } catch (error) {\n warn(`[pi2dsh engine] cannot read ${name}/package.json (${error instanceof Error ? error.message : String(error)}); skipping`)\n continue\n }\n // A dsh.bundle-declaring package is a DSH plugin layer, never a Pi package.\n if ((packageJson.dsh as { bundle?: unknown } | undefined)?.bundle !== undefined) continue\n if (packageJson.pi !== undefined && typeof packageJson.pi === 'object') {\n discovered.push({ name, dir })\n continue\n }\n // No `pi` field: fall back to Pi's directory conventions via the same\n // resolver every other mount path uses (a package with zero extension\n // sources is a plain library and stays unmounted).\n try {\n const pkg = await resolvePiPackage(dir)\n try {\n if (pkg.resources.extensions.length > 0) discovered.push({ name, dir })\n } finally {\n await pkg.dispose()\n }\n } catch {\n // Not resolvable as a Pi package — a plain library.\n }\n }\n return discovered\n}\n\ninterface AgentScopedMount {\n ready: Promise<void>\n /** Set when the mount failed; the agent then runs as a plain DSH agent. */\n failure?: string\n}\n\n/** The loose shapes of the official DSH seams this file consumes. */\ninterface AgentLike {\n ctx: Context\n}\ninterface EngineHostContext {\n /** Un-injected reflection access (the ctx.get('loader') idiom): the engine\n * must not hard-depend on the agent registry — compositions without one\n * (bare test hosts) simply have no agents to mount for. */\n get?(name: string): unknown\n tools?: { schemas?(scope: unknown): Array<{ name: string }> }\n on(name: string, listener: (...args: never[]) => unknown): () => void\n}\ninterface AgentRegistryLike {\n roots?(): AgentLike[]\n}\n\n/**\n * The single mount path on every DSH surface: one Pi runtime per root Agent.\n *\n * Pi instantiates its extensions once per session; DSH's twin of that scope is\n * the Agent with its public `agent.ctx` (\"contributions are agent-local,\n * unwind on disposal\"). Mounting is driven purely by official core seams, so\n * the same semantics hold on the TUI, web, headless, ACP and config-declared\n * agents alike:\n *\n * - `agent/created` fires on every publication path before the loop can run\n * a first turn; it eagerly starts that agent's mount.\n * - `system-prompt/assemble` (awaited waterfall, runs in every step's\n * preStep) gates the assembly on the mount and patches the pre-waterfall\n * tools snapshot from the official scoped projection `tools.schemas()` —\n * stock DSH collects `assembly.tools` before dispatching the waterfall,\n * so a mount that lands during the wait would otherwise miss turn one.\n * - `tools/pre-execute` (awaited waterfall) closes the same window for\n * direct executions that bypass assembly.\n *\n * `agent/session-start` deliberately is NOT the trigger: DSH documents it as a\n * veto-less notification that cannot gate startup. The waterfalls above are\n * the officially awaited seams, and the exact pattern of registering onto a\n * foreign agent's ctx from a lifecycle event is what DSH's own schedule\n * plugin ships.\n *\n * A mount failure never takes the Agent down: the agent keeps running as a\n * plain DSH agent, the failure is reported loudly once, and only the Pi\n * packages are missing — the capability-gap discipline, not a rollback.\n */\nexport function installAgentScopedMounts(\n ctx: Context,\n preparedPackages: Promise<readonly PreparedPiHostPackage[]>,\n report: { warn(message: string): void },\n): void {\n const host = ctx as unknown as EngineHostContext\n const mounts = new WeakMap<object, AgentScopedMount>()\n\n const registry = (): AgentRegistryLike | undefined => {\n try {\n return host.get?.('agents') as AgentRegistryLike | undefined\n } catch {\n return undefined\n }\n }\n\n const isRootAgent = (agent: object): boolean => {\n // Subagents keep Pi's own sub-session semantics through the session\n // bridge; only runtime roots receive a Pi runtime (the same distinction\n // DSH's schedule plugin draws via agents.roots()).\n const agents = registry()\n const roots = agents?.roots\n if (typeof roots !== 'function') return true\n try {\n return (roots.call(agents) as unknown[]).includes(agent)\n } catch {\n return true\n }\n }\n\n const ensureMount = (agent: AgentLike): AgentScopedMount => {\n let mount = mounts.get(agent)\n if (mount === undefined) {\n const started: AgentScopedMount = { ready: Promise.resolve() }\n started.ready = preparedPackages.then(async prepared => {\n if (prepared.length === 0) return\n try {\n await applyPreparedPiHost(agent.ctx, prepared, agent as unknown as Record<string, unknown>)\n } catch (error) {\n // Loud, once per agent; the gates resolve so the plain DSH agent\n // keeps working. Faking success is forbidden — the message names\n // what is missing.\n started.failure = error instanceof Error ? error.message : String(error)\n report.warn(`[pi2dsh engine] Pi packages failed to mount for this agent; it continues without them: ${started.failure}`)\n }\n })\n mounts.set(agent, started)\n mount = started\n }\n return mount\n }\n\n // Eager start on publication. `agent/created` reaches host-level listeners\n // on every create/resume/config path, before the loop can open a turn.\n host.on('agent/created', ((payload: { agent: AgentLike }) => {\n if (isRootAgent(payload.agent)) ensureMount(payload.agent)\n }) as never)\n\n // Correctness boundary #1: no prompt assembly for a root agent proceeds\n // before its Pi runtime is mounted, and the tools snapshot taken before\n // this waterfall is reconciled against the official scoped projection.\n host.on('system-prompt/assemble', (async (\n assembly: { tools: Array<{ name: string }> },\n context: { agent?: AgentLike },\n next: () => Promise<unknown>,\n ) => {\n const agent = context.agent\n if (agent !== undefined && isRootAgent(agent)) {\n await ensureMount(agent).ready\n const schemas = host.tools?.schemas\n if (typeof schemas === 'function') {\n const present = new Set(assembly.tools.map(tool => tool.name))\n for (const schema of schemas.call(host.tools, agent)) {\n if (!present.has(schema.name)) assembly.tools.push(schema)\n }\n }\n }\n return next()\n }) as never)\n\n // Correctness boundary #2: tool execution for a root agent waits for the\n // same mount (serially awaited by the tool runtime before dispatch).\n host.on('tools/pre-execute', (async (\n exec: { agent?: AgentLike },\n next: () => Promise<unknown>,\n ) => {\n if (exec.agent !== undefined && isRootAgent(exec.agent)) await ensureMount(exec.agent).ready\n return next()\n }) as never)\n\n // Backfill: agents published before this plugin finished loading (a surface\n // that skips the official await-the-loader pattern DSH's headless runner\n // uses). Their next assembly still passes the gates above.\n void preparedPackages.then(() => {\n const agents = registry()\n const roots = agents?.roots\n if (typeof roots !== 'function') return\n for (const agent of roots.call(agents)) ensureMount(agent)\n })\n}\n\n/** Cordis plugin surface: `dsh plugin add pi2dsh` mounts this. */\nexport const name = 'pi2dsh'\nexport const inject = ['tools', 'systemPrompt', 'commands', 'skills']\n\nexport async function apply(ctx: Context, config: EngineConfig = {}): Promise<void> {\n // Same emission as the runtime's logger helper: the cordis logger AND the\n // console — profile logger levels must never hide what the engine mounted.\n const log = (ctx as unknown as { logger?: { info?(m: string): void, warn?(m: string): void } }).logger\n const warn = (message: string): void => { log?.warn?.(message); console.warn(message) }\n const info = (message: string): void => { log?.info?.(message); console.log(message) }\n\n // The loader resolves plugins against the profile's baseUrl; that IS the\n // profile root. The ancestor walk from the installed engine is the\n // fallback for compositions without a loader (tests, hand-built hosts).\n const baseUrl = (ctx as unknown as { baseUrl?: string }).baseUrl\n const profileRoot = (baseUrl !== undefined ? findProfileRoot(fileURLToPath(new URL('.', baseUrl))) : undefined)\n ?? findProfileRoot(dirname(fileURLToPath(import.meta.url)))\n if (profileRoot === undefined) {\n throw new Error('pi2dsh engine: no DSH profile root (cordis.yml + package.json) above the installed engine — is pi2dsh installed via `dsh plugin add pi2dsh`?')\n }\n\n // The single mount path, before any await: gates and lifecycle listeners\n // must exist the moment a surface can publish its first Agent. Package\n // preparation resolves behind this promise; the gates hold each agent's\n // first assembly until its own mount lands.\n let resolvePrepared!: (prepared: readonly PreparedPiHostPackage[]) => void\n const preparedPackages = new Promise<readonly PreparedPiHostPackage[]>(resolve => {\n resolvePrepared = resolve\n })\n installAgentScopedMounts(ctx, preparedPackages, { warn })\n\n registerVisionCompanions(ctx, config.visionCompanions)\n\n try {\n // The host half, mounted exactly once regardless of packages or agents:\n // Pi's built-in provider directory, `/login`, and credential recovery.\n // Without it a fresh engine cannot run `/login openai-codex`: DSH treats\n // the unknown slash line as a model prompt and fails on the unrelated\n // default provider credential. Community packages join the same\n // SharedHostState (keyed on ctx.root), so host-level resources stay\n // single-instance no matter which agent scope mounts them.\n await applyPreparedPiHost(ctx, [{\n name: 'pi2dsh-builtins',\n rootUrl: new URL('.', import.meta.url),\n manifest: {\n schemaVersion: 1,\n package: { name: 'pi2dsh-builtins', version: '0.0.0', source: 'engine' },\n extensions: [],\n skillDirs: [],\n prompts: [],\n },\n }])\n\n const packages = Array.isArray(config.packages) && config.packages.length > 0\n ? config.packages.map(name => ({ name }))\n : await discoverProfilePiPackages(profileRoot, {\n ...(Array.isArray(config.exclude) ? { exclude: config.exclude } : {}),\n warn,\n })\n if (packages.length === 0) {\n info('[pi2dsh engine] no Pi packages installed in this profile yet — add one with: dsh plugin --profile <p> add <pi-package>')\n resolvePrepared([])\n return\n }\n info(`[pi2dsh engine] preparing ${packages.length} Pi package(s): ${packages.map(pkg => pkg.name).join(', ')}`)\n const prepared = await preparePiHost(\n { packages: packages.map(pkg => ({ name: pkg.name })) },\n join(profileRoot, 'package.json'),\n )\n // Host anchors, before the per-Agent gates open: every package's\n // HOST-level contributions (provider routes, OAuth accounts, /login,\n // credential recovery, companions, skills) exist from engine apply — a\n // surface with zero live Agents (web at boot) still advertises them, the\n // first Agent's model resolution finds its routes, and routes survive\n // Agent churn. Anchors serve no Agent; sessions belong to the per-Agent\n // instances the gates mount.\n await applyPreparedPiHost(ctx, prepared, undefined, { hostAnchor: true })\n resolvePrepared(prepared)\n } catch (error) {\n // The gates must never hang on a failed preparation; agents keep running\n // as plain DSH agents while the engine failure propagates loudly.\n resolvePrepared([])\n throw error\n }\n}\n","// Engine surface: `dsh plugin add pi2dsh` resolves this entry as a cordis\n// plugin (named exports, no default — a default export would make the\n// loader discard the function-plugin namespace).\nexport { apply, inject, name, discoverProfilePiPackages, findProfileRoot, installAgentScopedMounts, type EngineConfig } from './engine.js'\n\n// The CLI-only analysis surface loads lazily: its static-analysis dependency\n// (the 23 MB typescript compiler, an optional peer) must never be pulled\n// into a profile that installs the ENGINE. The dynamic import below keeps\n// the analyzer in its own chunk, off the engine's load path.\nimport type { CompatibilityReport, ResolvedPiPackage } from './types.js'\n\n/**\n * Static compatibility analysis of one resolved Pi package (CLI `inspect`).\n * @param pkg - the resolved package.\n * @returns the compatibility report.\n */\nexport async function analyzePackage(pkg: ResolvedPiPackage): Promise<CompatibilityReport> {\n const { analyzePackage: run } = await import('./analyzer.js')\n return run(pkg)\n}\n\nexport {\n API_RULES,\n CONTEXT_RULES,\n EVENT_RULES,\n HOST_IMPORT_RULES,\n PI_AI_PACKAGES,\n PI_CODING_AGENT_PACKAGES,\n PI_TUI_PACKAGES,\n UI_CONTEXT_RULES,\n ruleForApi,\n ruleForContextProperty,\n ruleForEvent,\n ruleForHostImport,\n ruleForUiContextProperty,\n} from './compatibility.js'\nexport { applyPiHost, applyPreparedPiHost, manifestForInstalled, preparePiHost } from './host.js'\nexport { collectPiMcpServers, convertPiMcpConfig, renderMcpPatch } from './mcp-config.js'\nexport { resolvePiPackage } from './source.js'\nexport type * from './types.js'\n"],"mappings":";;;;;;;;;;;AA6CA,SAAgB,gBAAgB,OAAmC;CACjE,IAAI,MAAM;CACV,SAAS;EACP,IAAI,WAAW,KAAK,KAAK,YAAY,CAAC,KAAK,WAAW,KAAK,KAAK,cAAc,CAAC,GAAG,OAAO;EACzF,MAAM,SAAS,QAAQ,GAAG;EAC1B,IAAI,WAAW,KAAK,OAAO,KAAA;EAC3B,MAAM;CACR;AACF;AAYA,eAAe,oBAAoB,aAA+C;CAChF,OAAO,KAAK,MAAM,MAAM,SAAS,KAAK,aAAa,cAAc,GAAG,MAAM,CAAC;AAC7E;AAEA,SAAS,qBAAqB,aAAqB,MAAkC;CAGnF,MAAM,MAAM,KAAK,aAAa,gBAAgB,IAAI;CAClD,OAAO,WAAW,KAAK,KAAK,cAAc,CAAC,IAAI,MAAM,KAAA;AACvD;;;;;;;AAQA,eAAsB,0BACpB,aACA,UAAoE,CAAC,GACvC;CAC9B,MAAM,OAAO,QAAQ,eAAe,CAAC;CACrC,MAAM,WAAW,IAAI,IAAI,QAAQ,WAAW,CAAC,CAAC;CAC9C,MAAM,WAAW,MAAM,oBAAoB,WAAW;CACtD,MAAM,aAAkC,CAAC;CACzC,KAAK,MAAM,QAAQ,OAAO,KAAK,SAAS,gBAAgB,CAAC,CAAC,GAAG;EAC3D,IAAI,SAAS,YAAY,SAAS,IAAI,IAAI,GAAG;EAC7C,MAAM,MAAM,qBAAqB,aAAa,IAAI;EAClD,IAAI,QAAQ,KAAA,GAAW;GACrB,KAAK,8BAA8B,KAAK,UAAU,IAAI,EAAE,8CAA8C;GACtG;EACF;EACA,IAAI;EACJ,IAAI;GACF,cAAc,KAAK,MAAM,MAAM,SAAS,KAAK,KAAK,cAAc,GAAG,MAAM,CAAC;EAC5E,SAAS,OAAO;GACd,KAAK,+BAA+B,KAAK,iBAAiB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,YAAY;GAC7H;EACF;EAEA,IAAK,YAAY,KAA0C,WAAW,KAAA,GAAW;EACjF,IAAI,YAAY,OAAO,KAAA,KAAa,OAAO,YAAY,OAAO,UAAU;GACtE,WAAW,KAAK;IAAE;IAAM;GAAI,CAAC;GAC7B;EACF;EAIA,IAAI;GACF,MAAM,MAAM,MAAM,iBAAiB,GAAG;GACtC,IAAI;IACF,IAAI,IAAI,UAAU,WAAW,SAAS,GAAG,WAAW,KAAK;KAAE;KAAM;IAAI,CAAC;GACxE,UAAU;IACR,MAAM,IAAI,QAAQ;GACpB;EACF,QAAQ,CAER;CACF;CACA,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,SAAgB,yBACd,KACA,kBACA,QACM;CACN,MAAM,OAAO;CACb,MAAM,yBAAS,IAAI,QAAkC;CAErD,MAAM,iBAAgD;EACpD,IAAI;GACF,OAAO,KAAK,MAAM,QAAQ;EAC5B,QAAQ;GACN;EACF;CACF;CAEA,MAAM,eAAe,UAA2B;EAI9C,MAAM,SAAS,SAAS;EACxB,MAAM,QAAQ,QAAQ;EACtB,IAAI,OAAO,UAAU,YAAY,OAAO;EACxC,IAAI;GACF,OAAQ,MAAM,KAAK,MAAM,CAAC,CAAe,SAAS,KAAK;EACzD,QAAQ;GACN,OAAO;EACT;CACF;CAEA,MAAM,eAAe,UAAuC;EAC1D,IAAI,QAAQ,OAAO,IAAI,KAAK;EAC5B,IAAI,UAAU,KAAA,GAAW;GACvB,MAAM,UAA4B,EAAE,OAAO,QAAQ,QAAQ,EAAE;GAC7D,QAAQ,QAAQ,iBAAiB,KAAK,OAAM,aAAY;IACtD,IAAI,SAAS,WAAW,GAAG;IAC3B,IAAI;KACF,MAAM,oBAAoB,MAAM,KAAK,UAAU,KAA2C;IAC5F,SAAS,OAAO;KAId,QAAQ,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;KACvE,OAAO,KAAK,0FAA0F,QAAQ,SAAS;IACzH;GACF,CAAC;GACD,OAAO,IAAI,OAAO,OAAO;GACzB,QAAQ;EACV;EACA,OAAO;CACT;CAIA,KAAK,GAAG,mBAAmB,YAAkC;EAC3D,IAAI,YAAY,QAAQ,KAAK,GAAG,YAAY,QAAQ,KAAK;CAC3D,EAAW;CAKX,KAAK,GAAG,2BAA2B,OACjC,UACA,SACA,SACG;EACH,MAAM,QAAQ,QAAQ;EACtB,IAAI,UAAU,KAAA,KAAa,YAAY,KAAK,GAAG;GAC7C,MAAM,YAAY,KAAK,CAAC,CAAC;GACzB,MAAM,UAAU,KAAK,OAAO;GAC5B,IAAI,OAAO,YAAY,YAAY;IACjC,MAAM,UAAU,IAAI,IAAI,SAAS,MAAM,KAAI,SAAQ,KAAK,IAAI,CAAC;IAC7D,KAAK,MAAM,UAAU,QAAQ,KAAK,KAAK,OAAO,KAAK,GACjD,IAAI,CAAC,QAAQ,IAAI,OAAO,IAAI,GAAG,SAAS,MAAM,KAAK,MAAM;GAE7D;EACF;EACA,OAAO,KAAK;CACd,EAAW;CAIX,KAAK,GAAG,sBAAsB,OAC5B,MACA,SACG;EACH,IAAI,KAAK,UAAU,KAAA,KAAa,YAAY,KAAK,KAAK,GAAG,MAAM,YAAY,KAAK,KAAK,CAAC,CAAC;EACvF,OAAO,KAAK;CACd,EAAW;CAKX,iBAAsB,WAAW;EAC/B,MAAM,SAAS,SAAS;EACxB,MAAM,QAAQ,QAAQ;EACtB,IAAI,OAAO,UAAU,YAAY;EACjC,KAAK,MAAM,SAAS,MAAM,KAAK,MAAM,GAAG,YAAY,KAAK;CAC3D,CAAC;AACH;;AAGA,MAAa,OAAO;AACpB,MAAa,SAAS;CAAC;CAAS;CAAgB;CAAY;AAAQ;AAEpE,eAAsB,MAAM,KAAc,SAAuB,CAAC,GAAkB;CAGlF,MAAM,MAAO,IAAmF;CAChG,MAAM,QAAQ,YAA0B;EAAE,KAAK,OAAO,OAAO;EAAG,QAAQ,KAAK,OAAO;CAAE;CACtF,MAAM,QAAQ,YAA0B;EAAE,KAAK,OAAO,OAAO;EAAG,QAAQ,IAAI,OAAO;CAAE;CAKrF,MAAM,UAAW,IAAwC;CACzD,MAAM,eAAe,YAAY,KAAA,IAAY,gBAAgB,cAAc,IAAI,IAAI,KAAK,OAAO,CAAC,CAAC,IAAI,KAAA,MAChG,gBAAgB,QAAQ,cAAc,YAAY,GAAG,CAAC,CAAC;CAC5D,IAAI,gBAAgB,KAAA,GAClB,MAAM,IAAI,MAAM,8IAA8I;CAOhK,IAAI;CAIJ,yBAAyB,KAAK,IAHD,SAA0C,YAAW;EAChF,kBAAkB;CACpB,CAC6C,GAAG,EAAE,KAAK,CAAC;CAExD,yBAAyB,KAAK,OAAO,gBAAgB;CAErD,IAAI;EAQF,MAAM,oBAAoB,KAAK,CAAC;GAC9B,MAAM;GACN,SAAS,IAAI,IAAI,KAAK,YAAY,GAAG;GACrC,UAAU;IACR,eAAe;IACf,SAAS;KAAE,MAAM;KAAmB,SAAS;KAAS,QAAQ;IAAS;IACvE,YAAY,CAAC;IACb,WAAW,CAAC;IACZ,SAAS,CAAC;GACZ;EACF,CAAC,CAAC;EAEF,MAAM,WAAW,MAAM,QAAQ,OAAO,QAAQ,KAAK,OAAO,SAAS,SAAS,IACxE,OAAO,SAAS,KAAI,UAAS,EAAE,KAAK,EAAE,IACtC,MAAM,0BAA0B,aAAa;GAC3C,GAAI,MAAM,QAAQ,OAAO,OAAO,IAAI,EAAE,SAAS,OAAO,QAAQ,IAAI,CAAC;GACnE;EACF,CAAC;EACL,IAAI,SAAS,WAAW,GAAG;GACzB,KAAK,wHAAwH;GAC7H,gBAAgB,CAAC,CAAC;GAClB;EACF;EACA,KAAK,6BAA6B,SAAS,OAAO,kBAAkB,SAAS,KAAI,QAAO,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,GAAG;EAC9G,MAAM,WAAW,MAAM,cACrB,EAAE,UAAU,SAAS,KAAI,SAAQ,EAAE,MAAM,IAAI,KAAK,EAAE,EAAE,GACtD,KAAK,aAAa,cAAc,CAClC;EAQA,MAAM,oBAAoB,KAAK,UAAU,KAAA,GAAW,EAAE,YAAY,KAAK,CAAC;EACxE,gBAAgB,QAAQ;CAC1B,SAAS,OAAO;EAGd,gBAAgB,CAAC,CAAC;EAClB,MAAM;CACR;AACF;;;;;;;;AC3VA,eAAsB,eAAe,KAAsD;CACzF,MAAM,EAAE,gBAAgB,QAAQ,MAAM,OAAO;CAC7C,OAAO,IAAI,GAAG;AAChB"}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
|
|
2
|
+
import { t as getAgentDir } from "./pi-config-shim-CZ1wFzqM.mjs";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { homedir } from "node:os";
|
|
2
6
|
//#region src/compatibility.ts
|
|
3
7
|
const rule = (level, detail) => ({
|
|
4
8
|
level,
|
|
@@ -330,7 +334,7 @@ const API_RULES = Object.freeze({
|
|
|
330
334
|
},
|
|
331
335
|
registerProvider: {
|
|
332
336
|
level: "partial",
|
|
333
|
-
detail: "Two outcomes, by whether the provider carries its own transport. WITH a transport (pi-ai createProvider and friends): it becomes a real DSH llm route through llm.registerAdapter, and from then on the package's own HTTP client carries the turn — its API key or OAuth token is resolved by Pi's credential chain and persisted in the bridge's auth.json, not by DSH credentials. WITHOUT one (catalog-only): protocol, endpoint, credential reference, model capabilities, reasoning levels and the compat fields offered by DSH are translated into the official llm-pi-ai profile; no bridge transport is synthesized.",
|
|
337
|
+
detail: "Two outcomes, by whether the provider carries its own transport. WITH a transport (pi-ai createProvider and friends): it becomes a real DSH llm route through llm.registerAdapter, and from then on the package's own HTTP client carries the turn — its API key or OAuth token is resolved by Pi's credential chain and persisted in the bridge's auth.json, not by DSH credentials. WITHOUT one (catalog-only): protocol, endpoint, credential reference, model capabilities, reasoning levels and the compat fields offered by DSH are translated into the official llm-pi-ai profile; no bridge transport is synthesized. An OAuth-capable provider additionally gets /login <id>, and on hosts that compose the official authorization service (0.1.1 line) it also joins DSH's native sign-in registry as a `pi2dsh/<id>` flow: the flow runs the package's own login, the official sign-out (deleteRecord) removes the bridge's stored login, and the official llm-pi-ai catalog flows coexist in the same listing under their own scope.",
|
|
334
338
|
design: "Two mechanisms behind one call. A provider carrying its own transport becomes a real DSH route through llm.registerAdapter, and the package's own HTTP client then carries the turn with its key resolved by Pi's credential chain into the bridge's auth.json. A catalog-only declaration becomes configuration for DSH's official llm-pi-ai adapter, which owns credentials and the real HTTP request. Both enter the one DSH model directory. The shared ledger follows Pi's layered composition (model-runtime registerProvider/recomposeProvider at the pinned upstream): the engine's built-in OAuth entries are the base layer, package registrations overlay it field-wise (defined fields win, undefined fields expose the base — a package overriding only the endpoint keeps the builtin OAuth flow), later packages override earlier ones in load order, re-registration merges defined fields over the package's previous registration, and a changed composition rebuilds the route. One adaptation for the long-lived host: overlays are slotted per package so another agent instance's idempotent re-registration cannot perturb cross-package order."
|
|
335
339
|
},
|
|
336
340
|
unregisterProvider: {
|
|
@@ -597,6 +601,179 @@ function ruleForUiContextProperty(property) {
|
|
|
597
601
|
return UI_CONTEXT_RULES[property];
|
|
598
602
|
}
|
|
599
603
|
//#endregion
|
|
600
|
-
|
|
604
|
+
//#region src/mcp-config.ts
|
|
605
|
+
/** Pi's documented config precedence, lowest to highest. */
|
|
606
|
+
function piMcpConfigPaths(cwd) {
|
|
607
|
+
const home = homedir();
|
|
608
|
+
return [
|
|
609
|
+
join(home, ".config", "mcp", "mcp.json"),
|
|
610
|
+
join(home, ".agents", "mcp.json"),
|
|
611
|
+
join(home, ".agents", "mcp", "mcp.json"),
|
|
612
|
+
join(getAgentDir(), "mcp.json"),
|
|
613
|
+
join(cwd, ".mcp.json"),
|
|
614
|
+
join(cwd, ".pi", "mcp.json")
|
|
615
|
+
];
|
|
616
|
+
}
|
|
617
|
+
function stringRecord(value) {
|
|
618
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
619
|
+
const entries = Object.entries(value).filter((entry) => typeof entry[1] === "string");
|
|
620
|
+
return entries.length === 0 ? void 0 : Object.fromEntries(entries);
|
|
621
|
+
}
|
|
622
|
+
function parseServer(name, raw, sourcePath) {
|
|
623
|
+
if (typeof raw !== "object" || raw === null) return void 0;
|
|
624
|
+
const record = raw;
|
|
625
|
+
const disabled = record.disabled === true;
|
|
626
|
+
if (typeof record.url === "string") return {
|
|
627
|
+
name,
|
|
628
|
+
sourcePath,
|
|
629
|
+
transport: "streamable-http",
|
|
630
|
+
url: record.url,
|
|
631
|
+
...stringRecord(record.headers) === void 0 ? {} : { headers: stringRecord(record.headers) },
|
|
632
|
+
disabled
|
|
633
|
+
};
|
|
634
|
+
if (typeof record.command === "string") return {
|
|
635
|
+
name,
|
|
636
|
+
sourcePath,
|
|
637
|
+
transport: "stdio",
|
|
638
|
+
command: record.command,
|
|
639
|
+
...Array.isArray(record.args) ? { args: record.args.map(String) } : {},
|
|
640
|
+
...stringRecord(record.env) === void 0 ? {} : { env: stringRecord(record.env) },
|
|
641
|
+
...typeof record.cwd === "string" ? { cwd: record.cwd } : {},
|
|
642
|
+
disabled
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
function collectPiMcpServers(cwd, extraPaths = []) {
|
|
646
|
+
const servers = /* @__PURE__ */ new Map();
|
|
647
|
+
const sources = [];
|
|
648
|
+
for (const path of [...piMcpConfigPaths(cwd), ...extraPaths]) {
|
|
649
|
+
if (!existsSync(path)) continue;
|
|
650
|
+
let parsed;
|
|
651
|
+
try {
|
|
652
|
+
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
653
|
+
} catch {
|
|
654
|
+
continue;
|
|
655
|
+
}
|
|
656
|
+
const mcpServers = parsed?.mcpServers;
|
|
657
|
+
if (typeof mcpServers !== "object" || mcpServers === null) continue;
|
|
658
|
+
sources.push(path);
|
|
659
|
+
for (const [name, raw] of Object.entries(mcpServers)) {
|
|
660
|
+
const record = raw;
|
|
661
|
+
const existing = servers.get(name);
|
|
662
|
+
if (existing !== void 0 && typeof record === "object" && record !== null && record.command === void 0 && record.url === void 0 && typeof record.disabled === "boolean") {
|
|
663
|
+
servers.set(name, {
|
|
664
|
+
...existing,
|
|
665
|
+
disabled: record.disabled,
|
|
666
|
+
sourcePath: path
|
|
667
|
+
});
|
|
668
|
+
continue;
|
|
669
|
+
}
|
|
670
|
+
const server = parseServer(name, raw, path);
|
|
671
|
+
if (server !== void 0) servers.set(name, server);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return {
|
|
675
|
+
servers,
|
|
676
|
+
sources
|
|
677
|
+
};
|
|
678
|
+
}
|
|
679
|
+
const SERVER_NAME_PATTERN = /^[A-Za-z0-9_-]{1,32}$/u;
|
|
680
|
+
const ENV_REFERENCE_PATTERN = /^\$\{?([A-Za-z_][A-Za-z0-9_]*)\}?$/u;
|
|
681
|
+
const SECRETISH_KEY_PATTERN = /token|secret|key|password|credential/iu;
|
|
682
|
+
function js(expression) {
|
|
683
|
+
return { __pi2dshJs: expression };
|
|
684
|
+
}
|
|
685
|
+
function convertValueMap(server, kind, values, warnings) {
|
|
686
|
+
if (values === void 0) return void 0;
|
|
687
|
+
const output = {};
|
|
688
|
+
for (const [key, value] of Object.entries(values)) {
|
|
689
|
+
const reference = ENV_REFERENCE_PATTERN.exec(value);
|
|
690
|
+
if (reference !== null) {
|
|
691
|
+
output[key] = js(`process.env.${reference[1]}`);
|
|
692
|
+
continue;
|
|
693
|
+
}
|
|
694
|
+
if (SECRETISH_KEY_PATTERN.test(key)) warnings.push({
|
|
695
|
+
server,
|
|
696
|
+
message: `${kind}.${key} carries a literal value; move the secret to an environment variable and reference it as $NAME so the patch stays credential-free`
|
|
697
|
+
});
|
|
698
|
+
output[key] = value;
|
|
699
|
+
}
|
|
700
|
+
return output;
|
|
701
|
+
}
|
|
702
|
+
function convertPiMcpConfig(cwd, extraPaths = []) {
|
|
703
|
+
const { servers, sources } = collectPiMcpServers(cwd, extraPaths);
|
|
704
|
+
const warnings = [];
|
|
705
|
+
const entries = [];
|
|
706
|
+
for (const server of servers.values()) {
|
|
707
|
+
if (server.disabled) {
|
|
708
|
+
warnings.push({
|
|
709
|
+
server: server.name,
|
|
710
|
+
message: "skipped: disabled in Pi configuration"
|
|
711
|
+
});
|
|
712
|
+
continue;
|
|
713
|
+
}
|
|
714
|
+
if (!SERVER_NAME_PATTERN.test(server.name)) {
|
|
715
|
+
warnings.push({
|
|
716
|
+
server: server.name,
|
|
717
|
+
message: "skipped: DSH serverName must match [A-Za-z0-9_-]{1,32}; rename the server in the Pi config"
|
|
718
|
+
});
|
|
719
|
+
continue;
|
|
720
|
+
}
|
|
721
|
+
const config = {
|
|
722
|
+
serverName: server.name,
|
|
723
|
+
transport: server.transport
|
|
724
|
+
};
|
|
725
|
+
if (server.transport === "stdio") {
|
|
726
|
+
config.command = server.command;
|
|
727
|
+
if (server.args !== void 0) config.args = server.args;
|
|
728
|
+
const env = convertValueMap(server.name, "env", server.env, warnings);
|
|
729
|
+
if (env !== void 0) config.env = env;
|
|
730
|
+
if (server.cwd !== void 0) config.cwd = server.cwd;
|
|
731
|
+
} else {
|
|
732
|
+
config.url = server.url;
|
|
733
|
+
const headers = convertValueMap(server.name, "headers", server.headers, warnings);
|
|
734
|
+
if (headers !== void 0) config.headers = headers;
|
|
735
|
+
}
|
|
736
|
+
entries.push({
|
|
737
|
+
id: `mcp-${server.name}`,
|
|
738
|
+
name: "@deepseek-ai/dsh-mcp-client",
|
|
739
|
+
config
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
return {
|
|
743
|
+
servers: [...servers.values()],
|
|
744
|
+
entries,
|
|
745
|
+
warnings,
|
|
746
|
+
sources
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
function yamlScalar(value, indent) {
|
|
750
|
+
if (typeof value === "object" && value !== null && "__pi2dshJs" in value) return `!!js ${value.__pi2dshJs}`;
|
|
751
|
+
if (typeof value === "string") return /^[A-Za-z0-9@._\/:-]+$/u.test(value) ? value : JSON.stringify(value);
|
|
752
|
+
if (Array.isArray(value)) {
|
|
753
|
+
if (value.length === 0) return "[]";
|
|
754
|
+
return `\n${value.map((item) => `${indent} - ${yamlScalar(item, `${indent} `)}`).join("\n")}`;
|
|
755
|
+
}
|
|
756
|
+
if (typeof value === "object" && value !== null) {
|
|
757
|
+
const record = value;
|
|
758
|
+
const keys = Object.keys(record);
|
|
759
|
+
if (keys.length === 0) return "{}";
|
|
760
|
+
return `\n${keys.map((key) => `${indent} ${key}: ${yamlScalar(record[key], `${indent} `)}`).join("\n")}`;
|
|
761
|
+
}
|
|
762
|
+
return String(value);
|
|
763
|
+
}
|
|
764
|
+
/** Render the converted entries as a cordis.patch.yml `insert` block. */
|
|
765
|
+
function renderMcpPatch(result) {
|
|
766
|
+
if (result.entries.length === 0) return "# no enabled MCP servers found in Pi configuration\n";
|
|
767
|
+
const lines = ["- insert:"];
|
|
768
|
+
for (const entry of result.entries) {
|
|
769
|
+
lines.push(` - id: ${String(entry.id)}`);
|
|
770
|
+
lines.push(` name: '@deepseek-ai/dsh-mcp-client'`);
|
|
771
|
+
lines.push(` inject: [tools]`);
|
|
772
|
+
lines.push(` config:${yamlScalar(entry.config, " ")}`);
|
|
773
|
+
}
|
|
774
|
+
return `${lines.join("\n")}\n`;
|
|
775
|
+
}
|
|
776
|
+
//#endregion
|
|
777
|
+
export { CONTEXT_RULES as a, PI_AI_PACKAGES as c, UI_CONTEXT_RULES as d, ruleForApi as f, ruleForUiContextProperty as g, ruleForHostImport as h, API_RULES as i, PI_CODING_AGENT_PACKAGES as l, ruleForEvent as m, convertPiMcpConfig as n, EVENT_RULES as o, ruleForContextProperty as p, renderMcpPatch as r, HOST_IMPORT_RULES as s, collectPiMcpServers as t, PI_TUI_PACKAGES as u };
|
|
601
778
|
|
|
602
|
-
//# sourceMappingURL=
|
|
779
|
+
//# sourceMappingURL=mcp-config-2s_i_H3R.mjs.map
|