@eddyskywalker/dsh-chatgpt-subscription 0.59.0 → 0.60.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +1 -1
- package/lib/client.js +1578 -232
- package/lib/client.js.map +1 -1
- package/lib/codemode.js +537 -150
- package/lib/index.js +177 -183
- package/lib/llm-compat-u9mor0uu.js +110 -0
- package/lib/types/client/codemode/CodeRunToolView.d.ts +68 -0
- package/lib/types/client/codemode/CodeRunToolView.d.ts.map +1 -0
- package/lib/types/client/codemode/highlight.d.ts +25 -0
- package/lib/types/client/codemode/highlight.d.ts.map +1 -0
- package/lib/types/client/codemode/styles.d.ts +11 -0
- package/lib/types/client/codemode/styles.d.ts.map +1 -0
- package/lib/types/client/codemode/tool-name.d.ts +10 -0
- package/lib/types/client/codemode/tool-name.d.ts.map +1 -0
- package/lib/types/client/index.d.ts.map +1 -1
- package/lib/types/client/locales-ru/hub.d.ts.map +1 -1
- package/lib/types/client/locales.d.ts +23 -1
- package/lib/types/client/locales.d.ts.map +1 -1
- package/lib/types/compat.d.ts +1 -1
- package/lib/types/entry-codemode.d.ts.map +1 -1
- package/lib/types/host/codemode/executor.d.ts.map +1 -1
- package/lib/types/host/codemode/rules.d.ts +16 -6
- package/lib/types/host/codemode/rules.d.ts.map +1 -1
- package/lib/types/host/codemode/transport.d.ts +82 -41
- package/lib/types/host/codemode/transport.d.ts.map +1 -1
- package/lib/types/host/command-code/model-catalog.d.ts +14 -14
- package/lib/types/host/command-code/model-catalog.d.ts.map +1 -1
- package/lib/types/host/command-code/routes.d.ts.map +1 -1
- package/lib/types/host/preset-sync.d.ts +19 -4
- package/lib/types/host/preset-sync.d.ts.map +1 -1
- package/package.json +1 -1
- package/presets/dispatch/README.md +1 -3
- package/presets/dispatch/agent.cordis.yml +9 -7
package/lib/index.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { a as resolveProgressUpdatesSettings, n as attachProgressSettings } from "./entry-progress-updates-CxQewio9.js";
|
|
2
2
|
import { attachPlanModePipelineSettings, resolvePlanModePipelineEnabled } from "./plan-mode-pipeline.js";
|
|
3
|
+
import { n as PLUGIN_MESSAGE_SOURCE_KIND, r as normalizeGenerateOptions, t as LlmError$1 } from "./llm-compat-u9mor0uu.js";
|
|
3
4
|
import { DEFAULT_SKIP_PROVIDERS, PRUNER_SERVICE_NAME, resolveSkipProviders, shouldSkipPruningForSession } from "./tool-result-pruner.js";
|
|
4
5
|
import { PLAN_PROJECTION_KEY, createPlanNotice } from "./plan-mode.js";
|
|
5
6
|
import { createRequire } from "node:module";
|
|
6
7
|
import * as LlmModule from "@deepseek-ai/dsh-llm";
|
|
7
|
-
import { EMPTY_RESPONSE_CODE, HarnessError, LlmAdapter, LlmError,
|
|
8
|
+
import { EMPTY_RESPONSE_CODE, HarnessError, LlmAdapter, LlmError, ProviderRequestId, ReasoningEffortId, ToolCallId, attributionHeaders, createUserMessage, errorChain, resolveRetryPolicy } from "@deepseek-ai/dsh-llm";
|
|
8
9
|
import { defineTool } from "@deepseek-ai/dsh-tools";
|
|
9
10
|
import { z } from "zod";
|
|
10
11
|
import z$1 from "@deepseek-ai/schemastery";
|
|
11
12
|
import fs, { chmod, lstat, mkdir, open, readFile, realpath, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
12
|
-
import path, { basename, dirname, extname, join, relative, resolve } from "node:path";
|
|
13
|
+
import path, { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
13
14
|
import os, { homedir, platform, userInfo } from "node:os";
|
|
14
15
|
import { constants, createCipheriv, createDecipheriv, createHash, createHmac, publicEncrypt, randomBytes, randomUUID } from "node:crypto";
|
|
15
16
|
import { isDeepStrictEqual } from "node:util";
|
|
@@ -807,7 +808,7 @@ const ROUTE_PREFIX$5 = "/api/dsh-chatgpt-subscription";
|
|
|
807
808
|
* `test/responses-client.test.ts` asserts the two agree, so a release that
|
|
808
809
|
* forgets this constant fails the suite instead of shipping quietly.
|
|
809
810
|
*/
|
|
810
|
-
const PLUGIN_VERSION = "0.
|
|
811
|
+
const PLUGIN_VERSION = "0.60.0";
|
|
811
812
|
const CODEX_CHATGPT_PROVIDER_ID = "codex-chatgpt";
|
|
812
813
|
const CODEX_API_BASE = "https://chatgpt.com/backend-api/codex";
|
|
813
814
|
const CODEX_RESPONSES_URL = `${CODEX_API_BASE}/responses`;
|
|
@@ -4434,7 +4435,7 @@ var OAuthService = class {
|
|
|
4434
4435
|
throw new OAuthServiceError("oauth-token-exchange-failed", `The ChatGPT device code could not be issued (${response.status}${detail === null ? "" : `, ${detail}`}).`, response.status);
|
|
4435
4436
|
}
|
|
4436
4437
|
const payload = await response.json().catch(() => null);
|
|
4437
|
-
const record = isRecord$
|
|
4438
|
+
const record = isRecord$67(payload) ? payload : {};
|
|
4438
4439
|
const authId = nonEmptyString$11(record.device_auth_id);
|
|
4439
4440
|
const userCode = nonEmptyString$11(record.user_code) ?? nonEmptyString$11(record.usercode);
|
|
4440
4441
|
if (authId === void 0 || userCode === void 0) throw new OAuthServiceError("oauth-token-exchange-failed", "ChatGPT returned no device code.");
|
|
@@ -4501,7 +4502,7 @@ var OAuthService = class {
|
|
|
4501
4502
|
const detail = deviceErrorIdentifier(payload);
|
|
4502
4503
|
throw new OAuthServiceError("oauth-token-exchange-failed", `The ChatGPT device confirmation was refused (${response.status}${detail === void 0 ? "" : `, ${detail}`}).`, response.status);
|
|
4503
4504
|
}
|
|
4504
|
-
const record = isRecord$
|
|
4505
|
+
const record = isRecord$67(payload) ? payload : {};
|
|
4505
4506
|
const authorizationCode = nonEmptyString$11(record.authorization_code);
|
|
4506
4507
|
const codeVerifier = nonEmptyString$11(record.code_verifier);
|
|
4507
4508
|
if (authorizationCode === void 0 || codeVerifier === void 0) throw new OAuthServiceError("oauth-token-exchange-failed", "ChatGPT confirmed the device code but returned no authorization code.");
|
|
@@ -4834,11 +4835,11 @@ const DEVICE_PENDING_STATUSES = /* @__PURE__ */ new Set([
|
|
|
4834
4835
|
function isPendingDeviceAnswer(response, payload) {
|
|
4835
4836
|
if (response.status === 403 || response.status === 404) return true;
|
|
4836
4837
|
if (!response.ok && response.status !== 400) return false;
|
|
4837
|
-
if (!isRecord$
|
|
4838
|
+
if (!isRecord$67(payload)) return false;
|
|
4838
4839
|
const status = payload.status;
|
|
4839
4840
|
if (typeof status === "string" && DEVICE_PENDING_STATUSES.has(status.toLowerCase())) return true;
|
|
4840
4841
|
const error = payload.error;
|
|
4841
|
-
if (isRecord$
|
|
4842
|
+
if (isRecord$67(error)) {
|
|
4842
4843
|
const code = error.code;
|
|
4843
4844
|
if (typeof code === "string" && DEVICE_PENDING_STATUSES.has(code.toLowerCase())) return true;
|
|
4844
4845
|
}
|
|
@@ -4852,18 +4853,18 @@ function isPendingDeviceAnswer(response, payload) {
|
|
|
4852
4853
|
* wrong.
|
|
4853
4854
|
*/
|
|
4854
4855
|
function deviceErrorIdentifier(payload) {
|
|
4855
|
-
if (!isRecord$
|
|
4856
|
+
if (!isRecord$67(payload)) return void 0;
|
|
4856
4857
|
const candidates = [payload.code];
|
|
4857
4858
|
const error = payload.error;
|
|
4858
4859
|
if (typeof error === "string") candidates.push(error);
|
|
4859
|
-
else if (isRecord$
|
|
4860
|
+
else if (isRecord$67(error)) candidates.push(error.code, error.type);
|
|
4860
4861
|
candidates.push(payload.status);
|
|
4861
4862
|
for (const candidate of candidates) if (typeof candidate === "string" && /^[a-z0-9_.-]{1,64}$/i.test(candidate)) return candidate;
|
|
4862
4863
|
}
|
|
4863
4864
|
function nonEmptyString$11(value) {
|
|
4864
4865
|
return typeof value === "string" && value !== "" ? value : void 0;
|
|
4865
4866
|
}
|
|
4866
|
-
function isRecord$
|
|
4867
|
+
function isRecord$67(value) {
|
|
4867
4868
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4868
4869
|
}
|
|
4869
4870
|
async function oauthErrorIdentifier(response) {
|
|
@@ -5044,7 +5045,7 @@ const CODEX_CLI_CREDENTIAL_SOURCE = "codex";
|
|
|
5044
5045
|
* here, and the import has to be repeated afterwards.
|
|
5045
5046
|
*/
|
|
5046
5047
|
const ADOPTED_CODEX_CREDENTIAL_EXPIRED_HINT = "The sign-in imported from the Codex CLI has expired. Sign in again in the Codex CLI, then import it again from this settings card.";
|
|
5047
|
-
function isRecord$
|
|
5048
|
+
function isRecord$66(value) {
|
|
5048
5049
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5049
5050
|
}
|
|
5050
5051
|
/** A trimmed, non-empty string, or nothing. */
|
|
@@ -5146,7 +5147,7 @@ function decodeJwtClaims$1(token) {
|
|
|
5146
5147
|
if (parts.length !== 3) return void 0;
|
|
5147
5148
|
try {
|
|
5148
5149
|
const value = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf8"));
|
|
5149
|
-
return isRecord$
|
|
5150
|
+
return isRecord$66(value) ? value : void 0;
|
|
5150
5151
|
} catch {
|
|
5151
5152
|
return;
|
|
5152
5153
|
}
|
|
@@ -5191,10 +5192,10 @@ function expiryFromAccessToken(accessToken) {
|
|
|
5191
5192
|
* the file carries cannot reach the result.
|
|
5192
5193
|
*/
|
|
5193
5194
|
function parseAdoptedCodexCredential(value, sourcePath) {
|
|
5194
|
-
if (!isRecord$
|
|
5195
|
+
if (!isRecord$66(value)) return void 0;
|
|
5195
5196
|
if (value.auth_mode !== "chatgpt") return void 0;
|
|
5196
5197
|
const tokens = value[CODEX_CLI_TOKENS_KEY];
|
|
5197
|
-
if (!isRecord$
|
|
5198
|
+
if (!isRecord$66(tokens)) return void 0;
|
|
5198
5199
|
const accessToken = nonEmptyString$10(tokens.access_token);
|
|
5199
5200
|
if (accessToken === void 0) return void 0;
|
|
5200
5201
|
const refreshToken = nonEmptyString$10(tokens.refresh_token);
|
|
@@ -5213,7 +5214,7 @@ function parseAdoptedCodexCredential(value, sourcePath) {
|
|
|
5213
5214
|
const email = claims === void 0 ? void 0 : nonEmptyString$10(claims.email);
|
|
5214
5215
|
if (email !== void 0) credentials.email = email;
|
|
5215
5216
|
const authClaims = claims === void 0 ? void 0 : claims[CODEX_AUTH_CLAIMS_KEY];
|
|
5216
|
-
const planType = isRecord$
|
|
5217
|
+
const planType = isRecord$66(authClaims) ? nonEmptyString$10(authClaims.chatgpt_plan_type) : void 0;
|
|
5217
5218
|
if (planType !== void 0) credentials.planType = planType;
|
|
5218
5219
|
}
|
|
5219
5220
|
const accountId = nonEmptyString$10(tokens.account_id);
|
|
@@ -5999,114 +6000,6 @@ function webServerOrigin(server) {
|
|
|
5999
6000
|
return `http://${server.host === "0.0.0.0" ? "127.0.0.1" : server.host}:${server.port}`;
|
|
6000
6001
|
}
|
|
6001
6002
|
//#endregion
|
|
6002
|
-
//#region src/host/common/llm-compat.ts
|
|
6003
|
-
/** This package's kind in the harness message-source map. */
|
|
6004
|
-
const PLUGIN_MESSAGE_SOURCE_KIND = "dsh-chatgpt-subscription";
|
|
6005
|
-
function isRecord$66(value) {
|
|
6006
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6007
|
-
}
|
|
6008
|
-
/** Read a message body's blocks, keeping every entry that carries a block tag. */
|
|
6009
|
-
function readBlocks(raw) {
|
|
6010
|
-
if (!Array.isArray(raw)) return [];
|
|
6011
|
-
return raw.filter((block) => isRecord$66(block) && typeof block.type === "string");
|
|
6012
|
-
}
|
|
6013
|
-
/**
|
|
6014
|
-
* The first value that is a non-empty string.
|
|
6015
|
-
*
|
|
6016
|
-
* Used for fields the two generations spell in different places: a value that
|
|
6017
|
-
* is present but empty must not shadow a real one further down the chain, which
|
|
6018
|
-
* is what `??` alone does.
|
|
6019
|
-
*/
|
|
6020
|
-
function firstNonEmptyString(...values) {
|
|
6021
|
-
for (const value of values) if (typeof value === "string" && value !== "") return value;
|
|
6022
|
-
return "";
|
|
6023
|
-
}
|
|
6024
|
-
/**
|
|
6025
|
-
* The result block a `role: 'tool'` message already carries inside its body.
|
|
6026
|
-
*
|
|
6027
|
-
* Some harness generations deliver the call id inside the result block rather
|
|
6028
|
-
* than on the message, and one shape carries both: `role: 'tool'` with a
|
|
6029
|
-
* `tool-result` block holding the id. Reading only the message-level fields
|
|
6030
|
-
* leaves {@link toolCallIdOf} nothing to find.
|
|
6031
|
-
*/
|
|
6032
|
-
function embeddedToolResult(content) {
|
|
6033
|
-
if (content.length !== 1) return void 0;
|
|
6034
|
-
const [block] = content;
|
|
6035
|
-
return block?.type === "tool-result" ? block : void 0;
|
|
6036
|
-
}
|
|
6037
|
-
/**
|
|
6038
|
-
* The call id one `role: 'tool'` message associates with its `tool-call`.
|
|
6039
|
-
*
|
|
6040
|
-
* The id is the only thing tying a result to the call it answers: a mapper that
|
|
6041
|
-
* sends it empty makes every result an orphan and tells the repair pass that no
|
|
6042
|
-
* call was answered, which some gateways reject outright (WorkBuddy answers
|
|
6043
|
-
* `11148`, "tool calls and tool results do not match"). It therefore has to be
|
|
6044
|
-
* read from every place the harness generations put it — the message, the
|
|
6045
|
-
* message's source, and the result block inside the body — and an empty string
|
|
6046
|
-
* must not shadow a later, real one.
|
|
6047
|
-
*/
|
|
6048
|
-
function toolCallIdOf(raw, source, embedded) {
|
|
6049
|
-
return firstNonEmptyString(raw.toolCallId, raw.callId, source?.callId, embedded?.toolCallId);
|
|
6050
|
-
}
|
|
6051
|
-
/**
|
|
6052
|
-
* Normalize one harness message list into {@link Message}.
|
|
6053
|
-
*
|
|
6054
|
-
* A 0.1.7 `role: 'tool'` message is re-wrapped as the user-role message holding
|
|
6055
|
-
* one {@link ToolResultBlock} that the mappers expect, keeping the tool
|
|
6056
|
-
* provenance (`kind: 'tool'`) they use to tell a real tool result from a user
|
|
6057
|
-
* turn. A message that already carries that block keeps its own body instead of
|
|
6058
|
-
* nesting a second `tool-result` around it. Everything a newer harness adds
|
|
6059
|
-
* beside that keeps its own shape.
|
|
6060
|
-
* @param messages - Messages straight off the request options, in either generation's shape.
|
|
6061
|
-
* @returns The same conversation in the pre-0.1.7 vocabulary.
|
|
6062
|
-
*/
|
|
6063
|
-
function normalizeMessages(messages) {
|
|
6064
|
-
const normalized = [];
|
|
6065
|
-
for (const raw of messages ?? []) {
|
|
6066
|
-
if (!isRecord$66(raw)) continue;
|
|
6067
|
-
const content = readBlocks(raw.content);
|
|
6068
|
-
if (raw.role === "tool") {
|
|
6069
|
-
const source = isRecord$66(raw.source) ? raw.source : void 0;
|
|
6070
|
-
const embedded = embeddedToolResult(content);
|
|
6071
|
-
const callId = toolCallIdOf(raw, source, embedded);
|
|
6072
|
-
const isError = raw.isError === true || embedded?.isError === true;
|
|
6073
|
-
normalized.push({
|
|
6074
|
-
id: raw.id,
|
|
6075
|
-
role: "user",
|
|
6076
|
-
content: [{
|
|
6077
|
-
type: "tool-result",
|
|
6078
|
-
toolCallId: callId,
|
|
6079
|
-
content: embedded === void 0 ? content : embedded.content,
|
|
6080
|
-
...isError ? { isError: true } : {}
|
|
6081
|
-
}],
|
|
6082
|
-
source: {
|
|
6083
|
-
kind: "tool",
|
|
6084
|
-
callId
|
|
6085
|
-
}
|
|
6086
|
-
});
|
|
6087
|
-
continue;
|
|
6088
|
-
}
|
|
6089
|
-
normalized.push({
|
|
6090
|
-
id: raw.id,
|
|
6091
|
-
role: typeof raw.role === "string" ? raw.role : "user",
|
|
6092
|
-
content,
|
|
6093
|
-
...isRecord$66(raw.source) ? { source: raw.source } : {}
|
|
6094
|
-
});
|
|
6095
|
-
}
|
|
6096
|
-
return normalized;
|
|
6097
|
-
}
|
|
6098
|
-
/**
|
|
6099
|
-
* Normalize request options for the mappers.
|
|
6100
|
-
* @param options - Request options the harness handed the adapter.
|
|
6101
|
-
* @returns The same options with {@link Message} history.
|
|
6102
|
-
*/
|
|
6103
|
-
function normalizeGenerateOptions(options) {
|
|
6104
|
-
return {
|
|
6105
|
-
...options,
|
|
6106
|
-
messages: normalizeMessages(options.messages)
|
|
6107
|
-
};
|
|
6108
|
-
}
|
|
6109
|
-
//#endregion
|
|
6110
6003
|
//#region src/host/codex-images.ts
|
|
6111
6004
|
/**
|
|
6112
6005
|
* Output canvases the Codex image endpoint accepts in `size`.
|
|
@@ -20079,6 +19972,21 @@ const COMMAND_CODE_MODELS = [
|
|
|
20079
19972
|
maxTokens: 256e3,
|
|
20080
19973
|
hidden: false
|
|
20081
19974
|
},
|
|
19975
|
+
{
|
|
19976
|
+
id: "stealth/crouton-alpha",
|
|
19977
|
+
name: "Crouton Alpha",
|
|
19978
|
+
inputModalities: ["text", "image"],
|
|
19979
|
+
reasoningEfforts: [
|
|
19980
|
+
"low",
|
|
19981
|
+
"medium",
|
|
19982
|
+
"high",
|
|
19983
|
+
"xhigh",
|
|
19984
|
+
"max"
|
|
19985
|
+
],
|
|
19986
|
+
contextWindow: 1048576,
|
|
19987
|
+
maxTokens: 943718,
|
|
19988
|
+
hidden: false
|
|
19989
|
+
},
|
|
20082
19990
|
{
|
|
20083
19991
|
id: "reflection/beam:free",
|
|
20084
19992
|
name: "Beam 1.0",
|
|
@@ -20096,7 +20004,7 @@ const COMMAND_CODE_MODELS = [
|
|
|
20096
20004
|
},
|
|
20097
20005
|
{
|
|
20098
20006
|
id: "poolside/laguna-s-2.1-free",
|
|
20099
|
-
name: "Laguna S 2.1",
|
|
20007
|
+
name: "Laguna S 2.1 (Free)",
|
|
20100
20008
|
inputModalities: ["text"],
|
|
20101
20009
|
reasoningEfforts: [],
|
|
20102
20010
|
contextWindow: 256e3,
|
|
@@ -20125,6 +20033,32 @@ const COMMAND_CODE_MODELS = [
|
|
|
20125
20033
|
maxTokens: 32768,
|
|
20126
20034
|
hidden: false
|
|
20127
20035
|
},
|
|
20036
|
+
{
|
|
20037
|
+
id: "inclusionai/ling-3.1-flash-1019",
|
|
20038
|
+
name: "Ling 3.1 Flash 1019",
|
|
20039
|
+
inputModalities: ["text"],
|
|
20040
|
+
reasoningEfforts: [
|
|
20041
|
+
"low",
|
|
20042
|
+
"medium",
|
|
20043
|
+
"high"
|
|
20044
|
+
],
|
|
20045
|
+
contextWindow: 1e6,
|
|
20046
|
+
maxTokens: 262144,
|
|
20047
|
+
hidden: false
|
|
20048
|
+
},
|
|
20049
|
+
{
|
|
20050
|
+
id: "inclusionai/ling-3.1-flash-1019:free",
|
|
20051
|
+
name: "Ling 3.1 Flash 1019",
|
|
20052
|
+
inputModalities: ["text"],
|
|
20053
|
+
reasoningEfforts: [
|
|
20054
|
+
"low",
|
|
20055
|
+
"medium",
|
|
20056
|
+
"high"
|
|
20057
|
+
],
|
|
20058
|
+
contextWindow: 1e6,
|
|
20059
|
+
maxTokens: 262144,
|
|
20060
|
+
hidden: true
|
|
20061
|
+
},
|
|
20128
20062
|
{
|
|
20129
20063
|
id: "meta/muse-spark-1.1",
|
|
20130
20064
|
name: "Muse Spark 1.1",
|
|
@@ -20286,42 +20220,37 @@ const COMMAND_CODE_MODELS = [
|
|
|
20286
20220
|
function commandCodeModelDef(modelId) {
|
|
20287
20221
|
return COMMAND_CODE_MODELS.find((model) => model.id === modelId);
|
|
20288
20222
|
}
|
|
20289
|
-
/**
|
|
20290
|
-
|
|
20291
|
-
|
|
20292
|
-
|
|
20293
|
-
|
|
20294
|
-
|
|
20295
|
-
|
|
20296
|
-
|
|
20297
|
-
|
|
20298
|
-
|
|
20299
|
-
|
|
20300
|
-
|
|
20301
|
-
|
|
20302
|
-
|
|
20303
|
-
|
|
20304
|
-
|
|
20305
|
-
|
|
20306
|
-
|
|
20307
|
-
|
|
20308
|
-
|
|
20309
|
-
|
|
20310
|
-
|
|
20311
|
-
|
|
20312
|
-
|
|
20313
|
-
|
|
20314
|
-
|
|
20315
|
-
|
|
20316
|
-
|
|
20317
|
-
|
|
20318
|
-
|
|
20319
|
-
|
|
20320
|
-
"xiaomi/mimo-v2.5",
|
|
20321
|
-
"stealth/space-bunny-alpha",
|
|
20322
|
-
"inclusionai/ling-3.0-flash-sante:free",
|
|
20323
|
-
"inclusionai/ling-3.1-flash:free"
|
|
20324
|
-
];
|
|
20223
|
+
/** Default-selection deltas recognized by `resolveEnabledModelIds` in `./routes.ts`. */
|
|
20224
|
+
const SHIPPED_DEFAULT_MIGRATIONS = [{
|
|
20225
|
+
version: "1.88.4",
|
|
20226
|
+
added: ["stealth/crouton-alpha", "inclusionai/ling-3.1-flash-1019"],
|
|
20227
|
+
retired: []
|
|
20228
|
+
}, {
|
|
20229
|
+
version: "1.88.2",
|
|
20230
|
+
added: [
|
|
20231
|
+
"claude-haiku-5-5",
|
|
20232
|
+
"gpt-6.1-terra",
|
|
20233
|
+
"moonshotai/Kimi-K3.1-Pro",
|
|
20234
|
+
"minimax/minimax-m3.1-flash",
|
|
20235
|
+
"ornith/ornith-1.5-122b",
|
|
20236
|
+
"Qwen/Qwen3.8-Max-Prime",
|
|
20237
|
+
"google/gemini-4-argon",
|
|
20238
|
+
"nvidia/nemotron-3.5-super-vl",
|
|
20239
|
+
"stealth/glyph-cluster:free",
|
|
20240
|
+
"reflection/beam:free",
|
|
20241
|
+
"inclusionai/ling-3.1-flash",
|
|
20242
|
+
"meta/muse-spark-open",
|
|
20243
|
+
"meta/muse-wonder-1.0",
|
|
20244
|
+
"mistral/mistral-large-4"
|
|
20245
|
+
],
|
|
20246
|
+
retired: [
|
|
20247
|
+
"xiaomi/mimo-v2.5-pro",
|
|
20248
|
+
"xiaomi/mimo-v2.5",
|
|
20249
|
+
"stealth/space-bunny-alpha",
|
|
20250
|
+
"inclusionai/ling-3.0-flash-sante:free",
|
|
20251
|
+
"inclusionai/ling-3.1-flash:free"
|
|
20252
|
+
]
|
|
20253
|
+
}];
|
|
20325
20254
|
//#endregion
|
|
20326
20255
|
//#region src/host/command-code/types.ts
|
|
20327
20256
|
const PROVIDER_ID$11 = "command-code";
|
|
@@ -24692,16 +24621,20 @@ function resolveEnabledModelIds$5(stored, catalog, enabled = true) {
|
|
|
24692
24621
|
/**
|
|
24693
24622
|
* Whether a stored selection still is a shipped default.
|
|
24694
24623
|
*
|
|
24695
|
-
*
|
|
24696
|
-
*
|
|
24697
|
-
*
|
|
24624
|
+
* Walk the recorded catalog refreshes newest-first. Each step reconstructs one
|
|
24625
|
+
* earlier default, so users who never edited either the immediate previous
|
|
24626
|
+
* release or an older recorded release still receive the current catalog.
|
|
24698
24627
|
*/
|
|
24699
24628
|
function isUneditedSelection(stored, shipped) {
|
|
24700
24629
|
if (stored.length === 0) return false;
|
|
24701
24630
|
if (sameSelection(stored, shipped)) return true;
|
|
24702
|
-
|
|
24703
|
-
for (const
|
|
24704
|
-
|
|
24631
|
+
let previous = new Set(shipped);
|
|
24632
|
+
for (const migration of SHIPPED_DEFAULT_MIGRATIONS) {
|
|
24633
|
+
previous = new Set([...previous].filter((id) => !migration.added.includes(id)));
|
|
24634
|
+
for (const id of migration.retired) previous.add(id);
|
|
24635
|
+
if (sameSelection(stored, previous)) return true;
|
|
24636
|
+
}
|
|
24637
|
+
return false;
|
|
24705
24638
|
}
|
|
24706
24639
|
/** Whether two id lists name exactly the same models, in any order. */
|
|
24707
24640
|
function sameSelection(stored, other) {
|
|
@@ -92408,6 +92341,7 @@ const RENAMED_PACKAGES = /* @__PURE__ */ new Map([["@deepseek-ai/dsh-workflow-wo
|
|
|
92408
92341
|
*/
|
|
92409
92342
|
const OPTIONALLY_ABSENT_PACKAGES = [
|
|
92410
92343
|
"@deepseek-ai/dsh-tool-present",
|
|
92344
|
+
"@deepseek-ai/dsh-tool-subagent-control/list-agents",
|
|
92411
92345
|
"@eddyskywalker/dsh-chatgpt-subscription/plan-mode-pipeline",
|
|
92412
92346
|
"@eddyskywalker/dsh-chatgpt-subscription/plan-mode",
|
|
92413
92347
|
"@eddyskywalker/dsh-chatgpt-subscription/tool-result-pruner"
|
|
@@ -92470,12 +92404,20 @@ function candidatePackageRoots(entryScript = process.argv[1]) {
|
|
|
92470
92404
|
} catch {}
|
|
92471
92405
|
return [...roots];
|
|
92472
92406
|
}
|
|
92407
|
+
/** The package-name portion of a bare package or package-subpath specifier. */
|
|
92408
|
+
function packageNameOf(specifier) {
|
|
92409
|
+
return specifier.split("/").slice(0, specifier.startsWith("@") ? 2 : 1).join("/");
|
|
92410
|
+
}
|
|
92473
92411
|
/**
|
|
92474
92412
|
* Whether a package or exported subpath is installed in any candidate node_modules tree.
|
|
92475
92413
|
* A subpath needs its own exact `exports` key; the package root alone is not enough.
|
|
92414
|
+
*
|
|
92415
|
+
* The nearest manifest on each Node resolution chain is authoritative. Looking
|
|
92416
|
+
* farther out after that manifest rejects a subpath would let an unrelated old
|
|
92417
|
+
* installation resurrect an export the running package deliberately removed.
|
|
92476
92418
|
*/
|
|
92477
92419
|
function packageInstalled(specifier, roots = candidatePackageRoots()) {
|
|
92478
|
-
const pkg =
|
|
92420
|
+
const pkg = packageNameOf(specifier);
|
|
92479
92421
|
const subpath = specifier.slice(pkg.length);
|
|
92480
92422
|
for (const root of roots) {
|
|
92481
92423
|
let dir = root;
|
|
@@ -92485,9 +92427,9 @@ function packageInstalled(specifier, roots = candidatePackageRoots()) {
|
|
|
92485
92427
|
if (subpath === "") return true;
|
|
92486
92428
|
try {
|
|
92487
92429
|
const manifest = JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
92488
|
-
|
|
92430
|
+
return manifest.exports !== void 0 && Object.prototype.hasOwnProperty.call(manifest.exports, `.${subpath}`);
|
|
92489
92431
|
} catch {
|
|
92490
|
-
|
|
92432
|
+
return false;
|
|
92491
92433
|
}
|
|
92492
92434
|
}
|
|
92493
92435
|
const parent = dirname(dir);
|
|
@@ -92498,20 +92440,72 @@ function packageInstalled(specifier, roots = candidatePackageRoots()) {
|
|
|
92498
92440
|
return false;
|
|
92499
92441
|
}
|
|
92500
92442
|
/**
|
|
92501
|
-
*
|
|
92502
|
-
*
|
|
92503
|
-
*
|
|
92504
|
-
|
|
92443
|
+
* Packages the preset intentionally loads from the plugin's own dependency
|
|
92444
|
+
* closure rather than the harness installation. Every other harness row must
|
|
92445
|
+
* resolve where the registry mounts it, not merely beside this plugin.
|
|
92446
|
+
*/
|
|
92447
|
+
const PLUGIN_RESOLVED_PACKAGES = ["@eddyskywalker/dsh-chatgpt-subscription", "@deepseek-ai/dsh-tool-executor-native"];
|
|
92448
|
+
/** Whether `candidate` is `root` itself or one of its descendants. */
|
|
92449
|
+
function pathInside(root, candidate) {
|
|
92450
|
+
const rel = relative(root, candidate);
|
|
92451
|
+
return rel === "" || rel !== ".." && !rel.startsWith(`..${sep}`) && !isAbsolute(rel);
|
|
92452
|
+
}
|
|
92453
|
+
/**
|
|
92454
|
+
* Whether a plugin-side resolution points into the package the harness's own
|
|
92455
|
+
* entry script reaches. Walking ancestors mirrors Node's node_modules lookup;
|
|
92456
|
+
* the CLI commonly sits in `bin/`, beside rather than inside node_modules.
|
|
92457
|
+
*/
|
|
92458
|
+
function resolvedFromHarness(resolved, entryDir, specifier) {
|
|
92459
|
+
if (typeof resolved !== "string") return false;
|
|
92460
|
+
let path;
|
|
92461
|
+
try {
|
|
92462
|
+
path = fileURLToPath(resolved);
|
|
92463
|
+
} catch {
|
|
92464
|
+
return false;
|
|
92465
|
+
}
|
|
92466
|
+
const pkg = packageNameOf(specifier);
|
|
92467
|
+
let dir = entryDir;
|
|
92468
|
+
for (;;) {
|
|
92469
|
+
if (pathInside(join(dir, "node_modules", pkg), path)) return true;
|
|
92470
|
+
const parent = dirname(dir);
|
|
92471
|
+
if (parent === dir) return false;
|
|
92472
|
+
dir = parent;
|
|
92473
|
+
}
|
|
92474
|
+
}
|
|
92475
|
+
/**
|
|
92476
|
+
* Resolve against the installation that will actually mount the preset.
|
|
92477
|
+
*
|
|
92478
|
+
* `import.meta.resolve` is based at this plugin, while the harness mounts
|
|
92479
|
+
* runtime-declared preset rows from its own context. A successful plugin-side
|
|
92480
|
+
* resolution is therefore not sufficient for a harness package: an old copy in
|
|
92481
|
+
* the profile tree must not override the running harness's missing export.
|
|
92482
|
+
* Plugin-owned rows and the plugin-borne native executor are the deliberate
|
|
92483
|
+
* exceptions. With no harness entry, retain the legacy local probe behavior.
|
|
92484
|
+
*/
|
|
92485
|
+
function resolvesFromInstallation(specifier, entryScript, resolveFromPlugin) {
|
|
92486
|
+
const entryDir = harnessEntryDir(entryScript);
|
|
92487
|
+
if (entryDir !== void 0 && packageInstalled(specifier, [entryDir])) return true;
|
|
92488
|
+
let resolved;
|
|
92489
|
+
let didResolve = false;
|
|
92490
|
+
if (resolveFromPlugin !== void 0) try {
|
|
92491
|
+
resolved = resolveFromPlugin(specifier);
|
|
92492
|
+
didResolve = true;
|
|
92493
|
+
} catch {}
|
|
92494
|
+
if (entryDir === void 0) {
|
|
92495
|
+
if (didResolve) return true;
|
|
92496
|
+
return packageInstalled(specifier, candidatePackageRoots(entryScript));
|
|
92497
|
+
}
|
|
92498
|
+
if (didResolve && PLUGIN_RESOLVED_PACKAGES.includes(packageNameOf(specifier))) return true;
|
|
92499
|
+
return didResolve && resolvedFromHarness(resolved, entryDir, specifier);
|
|
92500
|
+
}
|
|
92501
|
+
/**
|
|
92502
|
+
* Whether a bare specifier resolves in the installation that mounts presets.
|
|
92505
92503
|
* @param specifier - bare package specifier.
|
|
92506
92504
|
* @returns whether the specifier resolves.
|
|
92507
92505
|
*/
|
|
92508
92506
|
function resolvesFromHere(specifier) {
|
|
92509
|
-
const
|
|
92510
|
-
|
|
92511
|
-
resolve(specifier);
|
|
92512
|
-
return true;
|
|
92513
|
-
} catch {}
|
|
92514
|
-
return packageInstalled(specifier);
|
|
92507
|
+
const resolveFromPlugin = import.meta.resolve;
|
|
92508
|
+
return resolvesFromInstallation(specifier, process.argv[1], resolveFromPlugin);
|
|
92515
92509
|
}
|
|
92516
92510
|
/**
|
|
92517
92511
|
* Point every renamed package name at the spelling this installation ships.
|
|
@@ -92900,8 +92894,8 @@ const DISPATCH_PRESET = {
|
|
|
92900
92894
|
|
|
92901
92895
|
## R0.5 · Compatibility Gate (Once per New Session, Before R0)
|
|
92902
92896
|
A legacy Agent Teams runtime (pre-#7519) registers spawn_teammate and replaces send_message / list_agents / interrupt_agent with team-scoped variants, leaving spawned subagents unreachable. The current runtime only adds a shared task board (team_task_create and its list/get/update siblings) and reuses this mode's tools.
|
|
92903
|
-
Criterion: whether spawn_teammate exists (
|
|
92904
|
-
- Absent -> Write "Orchestration ready: subagent" and proceed to R0. The board tools stay
|
|
92897
|
+
Criterion: whether spawn_teammate exists (check via code_run). Never gate on wait_agent, send_message, list_agents, or interrupt_agent: this mode mounts those itself.
|
|
92898
|
+
- Absent -> Write "Orchestration ready: subagent" and proceed to R0. The board tools stay declared whether or not the board is on - frozen declaration, not availability - so confirm with team_task_list before relying on it. When the board is on it is bookkeeping, not a second dispatcher: the dispatch ledger stays the dispatch authority and R5 briefs stay the task contract; publish cross-agent dependencies (blocked_by) and write scopes on one team task per brief, claimed and completed by the child that owns it; never start work because a task is ready, and never reassign a task to skip R6.
|
|
92905
92899
|
- Present -> This session runs the legacy runtime and is **not orchestratable**. In order, and nothing else:
|
|
92906
92900
|
1. State in one sentence that the legacy runtime shadows the coordination tools and this mode has no degraded path.
|
|
92907
92901
|
2. Call ask_user_question once (see R-W) offering: disable the legacy runtime, restart Host, **start a new session**; switch preset; or execute this task directly.
|
|
@@ -92931,7 +92925,7 @@ L0/L1: execute directly (or 1 subagent for L1). L2: R-G, R9, and R6 are mandator
|
|
|
92931
92925
|
- [Media generation] Generate/revise/retry images directly; delegate complex creative work, never a bare call.
|
|
92932
92926
|
|
|
92933
92927
|
## R2 · Model Routing (Check Availability First, Then Decide How to Dispatch)
|
|
92934
|
-
Check whether list_subagent_models exists
|
|
92928
|
+
Check whether list_subagent_models exists. The tool row and provider/model/reasoning_effort parameters are mounted statically, so they are present even in a session that authorized no route at all. Read that fact instead of inferring it from the tool's output:
|
|
92935
92929
|
- If the output says neither—no authorized-routes block and no "No allowlist is in force" sentence—the annotation is absent and you cannot read the posture. Treat it as [State: Unlisted] for behaviour, but say "unconfirmed" rather than claiming either posture, and never report a route as authorized.
|
|
92936
92930
|
- [State: Listed] Output ends with "Authorized child routes for this Session": enforcement is active.
|
|
92937
92931
|
- The sole source of truth for the allowlist is list_subagent_models: call list_subagent_models({}) to list authorized providers, and call list_subagent_models({ provider }) to list authorized models under that provider; trust its output directly without cross-checking local config files or workspace code (even if upstream tool text says "Catalog membership is advisory", the runtime output is already filtered to this session's allowlist).
|
|
@@ -92947,7 +92941,7 @@ A subagent has full authority to plan, execute, and self-verify within its assig
|
|
|
92947
92941
|
Every task brief covers six elements: Goal / Boundary (which files or modules may be touched) / Constraints / Limits (see below) / Acceptance Criteria / Required Evidence to Report.
|
|
92948
92942
|
- [Compact Delta Brief] Standing default limits and the report schema already live in [Role Identification], so use a Compact Delta Brief by default: state Goal, original file/line Source Pointers (do not paraphrase code into long prose), Module-Interface Boundary, Constraints, Acceptance Criteria, and Required Evidence, and omit repeating standing limits unless overriding them.
|
|
92949
92943
|
- [Limits] When overriding any standing limit, write one line per limit spelling out four things: **what it bounds, in what unit, the cap, and whether it accumulates**. Write explicit caps ("at most 3 attempts", "edits at most 5 files", "test runs: unlimited"), never ranges ("2–5 files"); where an override dimension is left unstated, silence is read as a limit of zero, and a quota that resets per cycle is lost, not banked.
|
|
92950
|
-
- Do not ask the child to restate your rules back as a correctness check; if a limit is genuinely unclear, instruct the child to spend one minimal tool call to verify it. Dispatch independent tasks concurrently in one message (
|
|
92944
|
+
- Do not ask the child to restate your rules back as a correctness check; if a limit is genuinely unclear, instruct the child to spend one minimal tool call to verify it. Dispatch independent tasks concurrently in one message (native calls; use code_run Promise.all for batch filter/MCP) only after the interview has converged.
|
|
92951
92945
|
|
|
92952
92946
|
## R6 · Review & Acceptance
|
|
92953
92947
|
Two layers: subagent self-check -> your independent review (reading diffs, running tests, checking each criterion). The completion notification is a post-hoc signal: it tells you a child stopped, not that the work passed.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { LlmError as LlmError$1 } from "@deepseek-ai/dsh-llm";
|
|
2
|
+
//#region src/host/common/llm-compat.ts
|
|
3
|
+
/** This package's kind in the harness message-source map. */
|
|
4
|
+
const PLUGIN_MESSAGE_SOURCE_KIND = "dsh-chatgpt-subscription";
|
|
5
|
+
function isRecord(value) {
|
|
6
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7
|
+
}
|
|
8
|
+
/** Read a message body's blocks, keeping every entry that carries a block tag. */
|
|
9
|
+
function readBlocks(raw) {
|
|
10
|
+
if (!Array.isArray(raw)) return [];
|
|
11
|
+
return raw.filter((block) => isRecord(block) && typeof block.type === "string");
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The first value that is a non-empty string.
|
|
15
|
+
*
|
|
16
|
+
* Used for fields the two generations spell in different places: a value that
|
|
17
|
+
* is present but empty must not shadow a real one further down the chain, which
|
|
18
|
+
* is what `??` alone does.
|
|
19
|
+
*/
|
|
20
|
+
function firstNonEmptyString(...values) {
|
|
21
|
+
for (const value of values) if (typeof value === "string" && value !== "") return value;
|
|
22
|
+
return "";
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The result block a `role: 'tool'` message already carries inside its body.
|
|
26
|
+
*
|
|
27
|
+
* Some harness generations deliver the call id inside the result block rather
|
|
28
|
+
* than on the message, and one shape carries both: `role: 'tool'` with a
|
|
29
|
+
* `tool-result` block holding the id. Reading only the message-level fields
|
|
30
|
+
* leaves {@link toolCallIdOf} nothing to find.
|
|
31
|
+
*/
|
|
32
|
+
function embeddedToolResult(content) {
|
|
33
|
+
if (content.length !== 1) return void 0;
|
|
34
|
+
const [block] = content;
|
|
35
|
+
return block?.type === "tool-result" ? block : void 0;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* The call id one `role: 'tool'` message associates with its `tool-call`.
|
|
39
|
+
*
|
|
40
|
+
* The id is the only thing tying a result to the call it answers: a mapper that
|
|
41
|
+
* sends it empty makes every result an orphan and tells the repair pass that no
|
|
42
|
+
* call was answered, which some gateways reject outright (WorkBuddy answers
|
|
43
|
+
* `11148`, "tool calls and tool results do not match"). It therefore has to be
|
|
44
|
+
* read from every place the harness generations put it — the message, the
|
|
45
|
+
* message's source, and the result block inside the body — and an empty string
|
|
46
|
+
* must not shadow a later, real one.
|
|
47
|
+
*/
|
|
48
|
+
function toolCallIdOf(raw, source, embedded) {
|
|
49
|
+
return firstNonEmptyString(raw.toolCallId, raw.callId, source?.callId, embedded?.toolCallId);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Normalize one harness message list into {@link Message}.
|
|
53
|
+
*
|
|
54
|
+
* A 0.1.7 `role: 'tool'` message is re-wrapped as the user-role message holding
|
|
55
|
+
* one {@link ToolResultBlock} that the mappers expect, keeping the tool
|
|
56
|
+
* provenance (`kind: 'tool'`) they use to tell a real tool result from a user
|
|
57
|
+
* turn. A message that already carries that block keeps its own body instead of
|
|
58
|
+
* nesting a second `tool-result` around it. Everything a newer harness adds
|
|
59
|
+
* beside that keeps its own shape.
|
|
60
|
+
* @param messages - Messages straight off the request options, in either generation's shape.
|
|
61
|
+
* @returns The same conversation in the pre-0.1.7 vocabulary.
|
|
62
|
+
*/
|
|
63
|
+
function normalizeMessages(messages) {
|
|
64
|
+
const normalized = [];
|
|
65
|
+
for (const raw of messages ?? []) {
|
|
66
|
+
if (!isRecord(raw)) continue;
|
|
67
|
+
const content = readBlocks(raw.content);
|
|
68
|
+
if (raw.role === "tool") {
|
|
69
|
+
const source = isRecord(raw.source) ? raw.source : void 0;
|
|
70
|
+
const embedded = embeddedToolResult(content);
|
|
71
|
+
const callId = toolCallIdOf(raw, source, embedded);
|
|
72
|
+
const isError = raw.isError === true || embedded?.isError === true;
|
|
73
|
+
normalized.push({
|
|
74
|
+
id: raw.id,
|
|
75
|
+
role: "user",
|
|
76
|
+
content: [{
|
|
77
|
+
type: "tool-result",
|
|
78
|
+
toolCallId: callId,
|
|
79
|
+
content: embedded === void 0 ? content : embedded.content,
|
|
80
|
+
...isError ? { isError: true } : {}
|
|
81
|
+
}],
|
|
82
|
+
source: {
|
|
83
|
+
kind: "tool",
|
|
84
|
+
callId
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
normalized.push({
|
|
90
|
+
id: raw.id,
|
|
91
|
+
role: typeof raw.role === "string" ? raw.role : "user",
|
|
92
|
+
content,
|
|
93
|
+
...isRecord(raw.source) ? { source: raw.source } : {}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return normalized;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Normalize request options for the mappers.
|
|
100
|
+
* @param options - Request options the harness handed the adapter.
|
|
101
|
+
* @returns The same options with {@link Message} history.
|
|
102
|
+
*/
|
|
103
|
+
function normalizeGenerateOptions(options) {
|
|
104
|
+
return {
|
|
105
|
+
...options,
|
|
106
|
+
messages: normalizeMessages(options.messages)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
//#endregion
|
|
110
|
+
export { PLUGIN_MESSAGE_SOURCE_KIND as n, normalizeGenerateOptions as r, LlmError$1 as t };
|