@xiaoso/dsh-tool-plus 0.1.6 → 0.1.7-beta.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/THIRD_PARTY_NOTICES.md +9 -3
- package/lib/{abort-Cwwm4Err.mjs → abort-Caqff3M6.mjs} +2 -2
- package/lib/alibaba-coding-plan-DTupMiAi.mjs +73 -0
- package/lib/alibaba-token-plan-CHGyWOfX.mjs +46 -0
- package/lib/alibaba-token-plan-Dj3OZhEE.mjs +82 -0
- package/lib/{amazon-bedrock-TVMpUTRG.mjs → amazon-bedrock-DbFSYXfJ.mjs} +117 -38
- package/lib/{anthropic-BL6LFDQS.mjs → anthropic-CTJ3IQVa.mjs} +675 -166
- package/lib/anthropic-CXfWlp-x.mjs +105 -0
- package/lib/{aws-credentials-B20dliS7.mjs → anthropic-wire-CKuhDwZ1.mjs} +74 -14
- package/lib/{api-key-login-CIDnXeYd.mjs → api-key-validation-CGCJFbFr.mjs} +27 -68
- package/lib/{azure-openai-responses-BkhsLmN3.mjs → azure-openai-responses-ChFbWaGj.mjs} +27 -16
- package/lib/{browser-render-CmgvSNte.mjs → browser-render-9o0Rknop.mjs} +4 -4
- package/lib/bun-shim.mjs +71 -2
- package/lib/{bundled-references-ChZSPDFw.mjs → bundled-references-DY3EJxZV.mjs} +6 -5
- package/lib/cline-pass-Bwg3esu9.mjs +44 -0
- package/lib/cloudflare-ai-gateway-BupNXyKK.mjs +35 -0
- package/lib/cloudflare-ai-gateway-EWo0VkP5.mjs +44 -0
- package/lib/collapse-DOR8sOGf.mjs +2304 -0
- package/lib/coreweave-C82HrLpb.mjs +31 -0
- package/lib/coreweave-Ct8cF-da.mjs +14 -0
- package/lib/{cursor-B6HcmplF.mjs → cursor-B95LzVWV.mjs} +11 -3
- package/lib/{cursor-CRpLpaZ3.mjs → cursor-DJV_dcgB.mjs} +887 -1784
- package/lib/{cursor-B8m6SqAH.mjs → cursor-LKGjucn2.mjs} +48 -38
- package/lib/cursor-proto-B8Wj8bv9.mjs +10513 -0
- package/lib/{deterministic-id-D-yIV_eI.mjs → deterministic-id-CUEIMSqR.mjs} +1 -1
- package/lib/devin-BMTdx_hx.mjs +316 -0
- package/lib/{devin-DUAfvBsW.mjs → devin-DSp0Rw_E.mjs} +172 -86
- package/lib/devin-ExGIghmx.mjs +69 -0
- package/lib/devin-proto-Br8fdyNl.mjs +2888 -0
- package/lib/{dom-CawWi8fa.mjs → dom-DG3sPESc.mjs} +8 -8
- package/lib/effort-BdtQMN-_.mjs +23 -0
- package/lib/{error-C-f_Wnw4.mjs → error-CORgGg5a.mjs} +275 -154
- package/lib/{event-stream-Dh2guZxS.mjs → event-stream-ulcDenZD.mjs} +20 -4
- package/lib/{gemini-headers-DKUShltF.mjs → gemini-headers-Co9cVvex.mjs} +2 -2
- package/lib/{github-copilot-suDymKrx.mjs → github-copilot-Dstq1D3s.mjs} +69 -29
- package/lib/github-copilot-headers-DOh1gt_w.mjs +312 -0
- package/lib/gitlab-duo-DSCMrU0m.mjs +11 -0
- package/lib/google-CtsKkOQK.mjs +38 -0
- package/lib/google-antigravity-z-5KsEci.mjs +252 -0
- package/lib/{google-auth-DYJLM792.mjs → google-auth-ieLBaneO.mjs} +4 -4
- package/lib/{google-gemini-cli-8BT513Ul.mjs → google-gemini-cli-C6NE5mWz.mjs} +28 -54
- package/lib/{google-gemini-cli-D6cSmfvB.mjs → google-gemini-cli-CAIPSl7e.mjs} +23 -29
- package/lib/google-oauth-shared-DhMllAkt.mjs +53 -0
- package/lib/{google-shared-CVbHK5vZ.mjs → google-shared-B0aNCYEH.mjs} +140 -44
- package/lib/{google-validation-Cgbn3tWJ.mjs → google-validation-BEkNs-Bx.mjs} +1 -1
- package/lib/{google-vertex-Bui-ypAe.mjs → google-vertex-Bbd1tYNc.mjs} +8 -8
- package/lib/hosts-00rjRzUD.mjs +203 -0
- package/lib/id-AL5obQzR.mjs +71 -0
- package/lib/{idle-iterator-CYAxUkSD.mjs → idle-iterator-DlUkEfzW.mjs} +3 -3
- package/lib/index.mjs +587 -5266
- package/lib/kilo-ChJL54wq.mjs +81 -0
- package/lib/kimi-C2c_Zq8A.mjs +67 -0
- package/lib/{launch-BmgEUycu.mjs → launch-DKDH71En.mjs} +1 -1
- package/lib/markit-CmRfm4E2.mjs +9885 -0
- package/lib/models-DnXMYGcJ.mjs +381604 -0
- package/lib/muse-code-Di1VZmB1.mjs +143 -0
- package/lib/{ollama-Df9ce-Cp.mjs → ollama-B8ic3sEp.mjs} +15 -30
- package/lib/{openai-codex-CAVI3Me-.mjs → openai-codex-DuJNC99x.mjs} +29 -99
- package/lib/{openai-codex-responses-BcnOotRB.mjs → openai-codex-responses-BL29nh9K.mjs} +204 -116
- package/lib/{openai-completions-Bq4WT47M.mjs → openai-completions-BK2f2dBv.mjs} +152 -82
- package/lib/openai-configuration-update-xMYUjaK_.mjs +150 -0
- package/lib/{openai-reasoning-fallback-DXsfiSXO.mjs → openai-reasoning-fallback-BdB3RCbj.mjs} +106 -12
- package/lib/{openai-responses-Mq_-PjvE.mjs → openai-responses-CGQPlIIy.mjs} +76 -82
- package/lib/{perplexity-XgLF73E7.mjs → perplexity-TBjz3VMB.mjs} +52 -9
- package/lib/{pkce-BlQikGPu.mjs → pkce-BYjmugmw.mjs} +1 -1
- package/lib/protobuf-aab1UGVn.mjs +717 -0
- package/lib/{provider-response-C6vcbQyO.mjs → provider-response-SqKSkkUc.mjs} +1 -1
- package/lib/{proxy-D9lm7ONA.mjs → proxy-5nWqRL1f.mjs} +45 -5
- package/lib/{readability-Cpm-ocau.mjs → readability-uGhqb4GC.mjs} +2 -2
- package/lib/reference-CtvM4zLU.mjs +114 -0
- package/lib/{request-debug-HJMoJncL.mjs → request-debug-NQN0BjHH.mjs} +1 -1
- package/lib/{sanitize-text-CfcXzw5X.mjs → sanitize-text-BCf5KmCf.mjs} +1 -1
- package/lib/{scrapers-Cg5w77td.mjs → scrapers-D8oWspgW.mjs} +12 -12
- package/lib/{src-BcD0_rQR.mjs → src-BwW51vA5.mjs} +979 -388
- package/lib/{sse-debug-CYdjOC96.mjs → sse-debug-B-tkLCPW.mjs} +1 -1
- package/lib/{stream-Bjq8wjfr.mjs → stream-B_7qN-bA.mjs} +3802 -2623
- package/lib/stream-markup-healing-DKT1lnkW.mjs +267 -0
- package/lib/{strict-tool-validation-imVLUcbI.mjs → strict-tool-validation-CBTz1dAA.mjs} +2 -2
- package/lib/taxonomy-DSIM99rS.mjs +15392 -0
- package/lib/{stream-markup-healing-DZ6bVDxH.mjs → thinking-CiLa2LFB.mjs} +31 -186
- package/lib/{turndown-DN7ByzEI.mjs → turndown-DrX1M4WG.mjs} +4 -4
- package/lib/{type-guards-B9VVjRDK.mjs → type-guards-CttAANEx.mjs} +1 -1
- package/lib/{types-DX_bvuus.mjs → types-PVueGi9S.mjs} +2 -2
- package/lib/{utils-C-dSORPa.mjs → utils-CCfhUQen.mjs} +2364 -2676
- package/lib/{utils-Cp2Mxf_U.mjs → utils-CUPhpw9A.mjs} +413 -134
- package/lib/{utils-CQHPEQ3W.mjs → utils-DeWqNWV8.mjs} +2 -2
- package/lib/{vision-guard-mBmtAHx0.mjs → vision-guard-_XwsL1DF.mjs} +14 -29
- package/lib/xai-oauth-CXhnz0gO.mjs +210 -0
- package/lib/{xiaomi-7mE345KX.mjs → xiaomi-psoUItal.mjs} +8 -37
- package/lib/{zai-CeNpMV3W.mjs → zai-ApJ8HBgT.mjs} +8 -71
- package/lib/{zip-BK7UHCwX.mjs → zip-Kd602XNe.mjs} +1 -1
- package/package.json +11 -11
- package/presets/package.json +1 -1
- package/presets/tool-plus-ptc/agent.cordis.yml +1 -1
- package/presets/tool-plus-standard/agent.cordis.yml +1 -1
- package/lib/agent_pb-Rizyt9Zg.mjs +0 -805
- package/lib/anthropic-CDmj476p.mjs +0 -262
- package/lib/api_server_pb-CDZgLMta.mjs +0 -252
- package/lib/callback-server-CFJK-jvK.mjs +0 -398
- package/lib/codex-P1dGpX7G.mjs +0 -54
- package/lib/device-code-CuXTWYwY.mjs +0 -51
- package/lib/devin-BcQwht1W.mjs +0 -114
- package/lib/devin-BvMfGevz.mjs +0 -95
- package/lib/github-copilot-B3kQl0g0.mjs +0 -104
- package/lib/gitlab-duo-BriUTP8k.mjs +0 -155
- package/lib/gitlab-duo-workflow-wK5Ljzmc.mjs +0 -91
- package/lib/google-CE5tFDod.mjs +0 -30
- package/lib/google-antigravity-C1jgNljz.mjs +0 -198
- package/lib/google-oauth-shared-BLVTvokk.mjs +0 -147
- package/lib/grammar-D-NqNUxQ.mjs +0 -49
- package/lib/identity-HNO1Oe9B.mjs +0 -219
- package/lib/kimi-DgcUpPtK.mjs +0 -236
- package/lib/markit-DtGoRE6M.mjs +0 -1417
- package/lib/minimax-code-Y3h5li9N.mjs +0 -53
- package/lib/models-DRA2c_8U.mjs +0 -104660
- package/lib/opencode-BsVw9rCD.mjs +0 -38
- package/lib/to-binary-B1BEBIPC.mjs +0 -6002
- package/lib/wafer-BlhWLweO.mjs +0 -17
- package/lib/xai-oauth-5pORHUrg.mjs +0 -446
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
2
|
__installBunShim();
|
|
3
|
-
import { n as wrapFetchForExtraCa } from "./src-
|
|
4
|
-
//#region node_modules/.pnpm/@oh-my-pi+pi-catalog@
|
|
3
|
+
import { n as wrapFetchForExtraCa } from "./src-BwW51vA5.mjs";
|
|
4
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-catalog@18.1.17/node_modules/@oh-my-pi/pi-catalog/src/utils.ts
|
|
5
5
|
/**
|
|
6
6
|
* Fetch implementation for catalog discovery probes: the caller's override
|
|
7
7
|
* when given, otherwise global fetch wrapped for `NODE_EXTRA_CA_CERTS`.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
2
|
__installBunShim();
|
|
3
|
-
import
|
|
4
|
-
import "./
|
|
5
|
-
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@
|
|
3
|
+
import "./src-BwW51vA5.mjs";
|
|
4
|
+
import "./effort-BdtQMN-_.mjs";
|
|
5
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/types.ts
|
|
6
6
|
/**
|
|
7
7
|
* Ceiling on the output-token count omp requests from any OpenAI-family endpoint
|
|
8
8
|
* (openai-responses, azure/xai responses, and openai-completions). Mirrors
|
|
@@ -22,7 +22,7 @@ function excludesInferredOpenAIServiceTier(provider) {
|
|
|
22
22
|
return provider === "fireworks" || provider === "github-copilot";
|
|
23
23
|
}
|
|
24
24
|
function isOpenAIServiceTierModel(model) {
|
|
25
|
-
return !excludesInferredOpenAIServiceTier(model.provider) && isOpenAIServiceTierApi(model.api) &&
|
|
25
|
+
return !excludesInferredOpenAIServiceTier(model.provider) && isOpenAIServiceTierApi(model.api) && model.identity.class === "openai";
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* True when the tier should be sent on the wire as the provider's service-tier
|
|
@@ -45,7 +45,7 @@ function shouldSendServiceTier(serviceTier, target) {
|
|
|
45
45
|
return false;
|
|
46
46
|
}
|
|
47
47
|
//#endregion
|
|
48
|
-
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@
|
|
48
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/providers/vision-guard.ts
|
|
49
49
|
const NON_VISION_IMAGE_PLACEHOLDER = "[image omitted: model does not support vision]";
|
|
50
50
|
function partitionVisionContent(content, supportsImages) {
|
|
51
51
|
const textBlocks = content.filter((block) => block.type === "text");
|
|
@@ -63,30 +63,15 @@ function joinTextWithImagePlaceholder(text, omittedImages) {
|
|
|
63
63
|
return parts.join("\n");
|
|
64
64
|
}
|
|
65
65
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* guard only covers families verified to be text-only for issue #1859:
|
|
71
|
-
* `qwen*-coder*` and `qwen*-max` up to and including `qwen3.7-max`.
|
|
72
|
-
*
|
|
73
|
-
* Qwen-Max became multimodal at `qwen3.8-max` (image input, issue #8019), so
|
|
74
|
-
* `-max` SKUs at version 3.8 or newer are excluded — otherwise the override
|
|
75
|
-
* would strip images from a genuinely vision-capable flagship (issue #8305).
|
|
76
|
-
*
|
|
77
|
-
* Used as a defensive override in `convertMessages` so a misconfigured custom
|
|
78
|
-
* provider (issue #1859) can't drive the request into an unrecoverable 400.
|
|
66
|
+
* Evaluates whether an OpenAI-compatible Chat Completions model genuinely
|
|
67
|
+
* supports multimodal image inputs on the wire. Defensive guards override
|
|
68
|
+
* misconfigured provider descriptors or user model entries (e.g. text-only
|
|
69
|
+
* DashScope Qwen SKUs, DeepSeek models) whose endpoints reject `image_url`.
|
|
79
70
|
*/
|
|
80
|
-
function
|
|
81
|
-
if (!
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
if (/\bqwen(?:[\d.]+)?-coder\b/.test(id)) return true;
|
|
85
|
-
const maxMatch = id.match(/\bqwen(?:(\d+)(?:\.(\d+))?)?-max\b/);
|
|
86
|
-
if (!maxMatch) return false;
|
|
87
|
-
const major = maxMatch[1] ? Number.parseInt(maxMatch[1], 10) : 0;
|
|
88
|
-
const minor = maxMatch[2] ? Number.parseInt(maxMatch[2], 10) : 0;
|
|
89
|
-
return major < 3 || major === 3 && minor < 8;
|
|
71
|
+
function isOpenAICompletionsVisionSupported(model) {
|
|
72
|
+
if (!model.input.includes("image")) return false;
|
|
73
|
+
if (model.compat.stripImageInput) return false;
|
|
74
|
+
return true;
|
|
90
75
|
}
|
|
91
76
|
//#endregion
|
|
92
|
-
export { OPENAI_MAX_OUTPUT_TOKENS as a, partitionVisionContent as i,
|
|
77
|
+
export { OPENAI_MAX_OUTPUT_TOKENS as a, partitionVisionContent as i, isOpenAICompletionsVisionSupported as n, shouldSendServiceTier as o, joinTextWithImagePlaceholder as r, NON_VISION_IMAGE_PLACEHOLDER as t };
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
|
+
__installBunShim();
|
|
3
|
+
import { r as __exportAll } from "./fs-promises-shim-Bx0fpxuk.mjs";
|
|
4
|
+
import { f as OAuthError } from "./error-CORgGg5a.mjs";
|
|
5
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/xai-oauth.ts
|
|
6
|
+
/**
|
|
7
|
+
* xAI OAuth endpoint discovery, identity, and billing helpers.
|
|
8
|
+
*/
|
|
9
|
+
var xai_oauth_exports = /* @__PURE__ */ __exportAll({
|
|
10
|
+
buildXAICliBillingUrl: () => buildXAICliBillingUrl,
|
|
11
|
+
extractXAIAccessTokenSubject: () => extractXAIAccessTokenSubject,
|
|
12
|
+
fetchXAIOAuthIdentity: () => fetchXAIOAuthIdentity,
|
|
13
|
+
getXAICliBillingHeaders: () => getXAICliBillingHeaders,
|
|
14
|
+
getXAITokenEndpoint: () => getXAITokenEndpoint,
|
|
15
|
+
parseXAIAccessTokenPayload: () => parseXAIAccessTokenPayload,
|
|
16
|
+
validateXAIBillingEndpoint: () => validateXAIBillingEndpoint,
|
|
17
|
+
validateXAIEndpoint: () => validateXAIEndpoint
|
|
18
|
+
});
|
|
19
|
+
const XAI_OAUTH_ISSUER = "https://auth.x.ai";
|
|
20
|
+
const XAI_OAUTH_DISCOVERY_URL = `${XAI_OAUTH_ISSUER}/.well-known/openid-configuration`;
|
|
21
|
+
const XAI_OAUTH_USERINFO_URL = `${XAI_OAUTH_ISSUER}/oauth2/userinfo`;
|
|
22
|
+
const XAI_CLI_BILLING_BASE_URL = "https://cli-chat-proxy.grok.com";
|
|
23
|
+
const XAI_CLI_BILLING_PATH = "/v1/billing";
|
|
24
|
+
const XAI_CLI_BILLING_FORMAT = "credits";
|
|
25
|
+
const DISCOVERY_TIMEOUT_MS = 15e3;
|
|
26
|
+
function isRecord(value) {
|
|
27
|
+
return typeof value === "object" && value !== null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate an xAI OIDC endpoint against its scheme and host.
|
|
31
|
+
*
|
|
32
|
+
* The discovery response is long-lived and its token endpoint receives every
|
|
33
|
+
* future refresh token. Rejecting non-HTTPS or non-`x.ai` / `*.x.ai` hosts
|
|
34
|
+
* pins that endpoint to the xAI auth origin.
|
|
35
|
+
*
|
|
36
|
+
* @throws Error with message `Invalid xAI <field>: <url>` when the URL fails
|
|
37
|
+
* either scheme or host validation.
|
|
38
|
+
*/
|
|
39
|
+
function isXaiAuthHostname(host) {
|
|
40
|
+
return host === "x.ai" || host.endsWith(".x.ai");
|
|
41
|
+
}
|
|
42
|
+
/** SuperGrok CLI billing proxy host (`cli-chat-proxy.grok.com`), not the OIDC issuer. */
|
|
43
|
+
function isXaiBillingHostname(host) {
|
|
44
|
+
return host === "grok.com" || host.endsWith(".grok.com");
|
|
45
|
+
}
|
|
46
|
+
function validateXAIEndpoint(url, field) {
|
|
47
|
+
let parsed;
|
|
48
|
+
try {
|
|
49
|
+
parsed = new URL(url);
|
|
50
|
+
} catch {
|
|
51
|
+
throw new OAuthError(`Invalid xAI ${field}: ${url}`, {
|
|
52
|
+
kind: "validation",
|
|
53
|
+
provider: "xai"
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
if (parsed.protocol !== "https:") throw new OAuthError(`Invalid xAI ${field}: ${url}`, {
|
|
57
|
+
kind: "validation",
|
|
58
|
+
provider: "xai"
|
|
59
|
+
});
|
|
60
|
+
const host = parsed.hostname.toLowerCase();
|
|
61
|
+
if (!host || !isXaiAuthHostname(host)) throw new OAuthError(`Invalid xAI ${field}: ${url}`, {
|
|
62
|
+
kind: "validation",
|
|
63
|
+
provider: "xai"
|
|
64
|
+
});
|
|
65
|
+
return url;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Pin SuperGrok billing URLs to HTTPS `grok.com` / `*.grok.com`.
|
|
69
|
+
* The CLI billing proxy is intentionally not on `*.x.ai`.
|
|
70
|
+
*/
|
|
71
|
+
function validateXAIBillingEndpoint(url, field = "billing_url") {
|
|
72
|
+
let parsed;
|
|
73
|
+
try {
|
|
74
|
+
parsed = new URL(url);
|
|
75
|
+
} catch {
|
|
76
|
+
throw new OAuthError(`Invalid xAI ${field}: ${url}`, {
|
|
77
|
+
kind: "validation",
|
|
78
|
+
provider: "xai"
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
if (parsed.protocol !== "https:") throw new OAuthError(`Invalid xAI ${field}: ${url}`, {
|
|
82
|
+
kind: "validation",
|
|
83
|
+
provider: "xai"
|
|
84
|
+
});
|
|
85
|
+
const host = parsed.hostname.toLowerCase();
|
|
86
|
+
if (!host || !isXaiBillingHostname(host)) throw new OAuthError(`Invalid xAI ${field}: ${url}`, {
|
|
87
|
+
kind: "validation",
|
|
88
|
+
provider: "xai"
|
|
89
|
+
});
|
|
90
|
+
return url;
|
|
91
|
+
}
|
|
92
|
+
/** Fetch xAI's OIDC discovery document and validate the token endpoint. */
|
|
93
|
+
async function xaiOAuthDiscovery(timeoutMs = DISCOVERY_TIMEOUT_MS, fetchOverride, signal) {
|
|
94
|
+
const fetchImpl = fetchOverride ?? fetch;
|
|
95
|
+
let response;
|
|
96
|
+
try {
|
|
97
|
+
response = await fetchImpl(XAI_OAUTH_DISCOVERY_URL, {
|
|
98
|
+
method: "GET",
|
|
99
|
+
headers: { Accept: "application/json" },
|
|
100
|
+
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(timeoutMs)]) : AbortSignal.timeout(timeoutMs)
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
throw new OAuthError(`xAI OIDC discovery failed: ${error instanceof Error ? error.message : String(error)}`, {
|
|
104
|
+
kind: "discovery",
|
|
105
|
+
provider: "xai",
|
|
106
|
+
cause: error
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
if (response.status !== 200) throw new OAuthError(`xAI OIDC discovery returned status ${response.status}.`, {
|
|
110
|
+
kind: "discovery",
|
|
111
|
+
provider: "xai",
|
|
112
|
+
status: response.status
|
|
113
|
+
});
|
|
114
|
+
let payload;
|
|
115
|
+
try {
|
|
116
|
+
payload = await response.json();
|
|
117
|
+
} catch (error) {
|
|
118
|
+
throw new OAuthError(`xAI OIDC discovery returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`, {
|
|
119
|
+
kind: "validation",
|
|
120
|
+
provider: "xai",
|
|
121
|
+
cause: error
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (!isRecord(payload)) throw new OAuthError("xAI OIDC discovery response was not a JSON object.", {
|
|
125
|
+
kind: "validation",
|
|
126
|
+
provider: "xai"
|
|
127
|
+
});
|
|
128
|
+
const tokenEndpoint = typeof payload.token_endpoint === "string" ? payload.token_endpoint.trim() : "";
|
|
129
|
+
if (!tokenEndpoint) throw new OAuthError("xAI OIDC discovery response was missing token_endpoint.", {
|
|
130
|
+
kind: "validation",
|
|
131
|
+
provider: "xai"
|
|
132
|
+
});
|
|
133
|
+
validateXAIEndpoint(tokenEndpoint, "token_endpoint");
|
|
134
|
+
return { token_endpoint: tokenEndpoint };
|
|
135
|
+
}
|
|
136
|
+
/** Discover and pin the xAI token endpoint used by login and refresh. */
|
|
137
|
+
async function getXAITokenEndpoint(signal) {
|
|
138
|
+
return validateXAIEndpoint((await xaiOAuthDiscovery(DISCOVERY_TIMEOUT_MS, void 0, signal)).token_endpoint, "token_endpoint");
|
|
139
|
+
}
|
|
140
|
+
/** Decode an xAI access-token JWT payload without verifying its signature. */
|
|
141
|
+
function parseXAIAccessTokenPayload(jwt) {
|
|
142
|
+
try {
|
|
143
|
+
if (typeof jwt !== "string" || !jwt.includes(".")) return null;
|
|
144
|
+
const parts = jwt.split(".");
|
|
145
|
+
if (parts.length < 2) return null;
|
|
146
|
+
const payloadPart = parts[1];
|
|
147
|
+
if (!payloadPart) return null;
|
|
148
|
+
const decoded = Buffer.from(payloadPart, "base64url").toString("utf8");
|
|
149
|
+
const payload = JSON.parse(decoded);
|
|
150
|
+
return isRecord(payload) && !Array.isArray(payload) ? payload : null;
|
|
151
|
+
} catch {
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** Extract the stable xAI subject UUID from an access token. */
|
|
156
|
+
function extractXAIAccessTokenSubject(jwt) {
|
|
157
|
+
const sub = parseXAIAccessTokenPayload(jwt)?.sub;
|
|
158
|
+
return typeof sub === "string" && sub.trim() ? sub.trim() : void 0;
|
|
159
|
+
}
|
|
160
|
+
/** Fetch optional OIDC userinfo for a valid xAI access token. */
|
|
161
|
+
async function fetchXAIOAuthIdentity(accessToken, fetchOverride, signal) {
|
|
162
|
+
const token = accessToken.trim();
|
|
163
|
+
if (!token) return null;
|
|
164
|
+
const fetchImpl = fetchOverride ?? fetch;
|
|
165
|
+
try {
|
|
166
|
+
const response = await fetchImpl(XAI_OAUTH_USERINFO_URL, {
|
|
167
|
+
method: "GET",
|
|
168
|
+
headers: {
|
|
169
|
+
Authorization: `Bearer ${token}`,
|
|
170
|
+
Accept: "application/json"
|
|
171
|
+
},
|
|
172
|
+
redirect: "error",
|
|
173
|
+
signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(DISCOVERY_TIMEOUT_MS)]) : AbortSignal.timeout(DISCOVERY_TIMEOUT_MS)
|
|
174
|
+
});
|
|
175
|
+
if (!response.ok) return null;
|
|
176
|
+
const payload = await response.json();
|
|
177
|
+
if (!isRecord(payload) || Array.isArray(payload)) return null;
|
|
178
|
+
const sub = typeof payload.sub === "string" && payload.sub.trim() ? payload.sub.trim() : void 0;
|
|
179
|
+
const email = typeof payload.email === "string" && payload.email.trim() ? payload.email.trim() : void 0;
|
|
180
|
+
const name = typeof payload.name === "string" && payload.name.trim() ? payload.name.trim() : void 0;
|
|
181
|
+
if (!sub && !email && !name) return null;
|
|
182
|
+
return {
|
|
183
|
+
...sub ? { accountId: sub } : {},
|
|
184
|
+
...email ? { email: email.toLowerCase() } : {},
|
|
185
|
+
...name ? { name } : {}
|
|
186
|
+
};
|
|
187
|
+
} catch {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/** Build the SuperGrok CLI billing URL. Pass `""` to omit `format` (unified monthly payload). */
|
|
192
|
+
function buildXAICliBillingUrl(format = XAI_CLI_BILLING_FORMAT) {
|
|
193
|
+
const url = new URL(XAI_CLI_BILLING_PATH, XAI_CLI_BILLING_BASE_URL);
|
|
194
|
+
if (format) url.searchParams.set("format", format);
|
|
195
|
+
return validateXAIBillingEndpoint(url.toString());
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Headers for SuperGrok CLI billing (`cli-chat-proxy.grok.com`).
|
|
199
|
+
* Official Grok CLI also sends `X-XAI-Token-Auth: xai-grok-cli` on this host;
|
|
200
|
+
* include it so billing stays on the same product gate as chat inference.
|
|
201
|
+
*/
|
|
202
|
+
function getXAICliBillingHeaders(options) {
|
|
203
|
+
return {
|
|
204
|
+
Authorization: `Bearer ${options.accessToken}`,
|
|
205
|
+
Accept: "application/json",
|
|
206
|
+
"X-XAI-Token-Auth": "xai-grok-cli"
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
//#endregion
|
|
210
|
+
export { xai_oauth_exports as a, getXAICliBillingHeaders as i, extractXAIAccessTokenSubject as n, fetchXAIOAuthIdentity as r, buildXAICliBillingUrl as t };
|
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
2
|
__installBunShim();
|
|
3
|
-
import {
|
|
4
|
-
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@
|
|
3
|
+
import { f as OAuthError, g as OnPromptRequiredError, m as LoginCancelledError, p as ApiKeyRequiredError } from "./error-CORgGg5a.mjs";
|
|
4
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/xiaomi.ts
|
|
5
5
|
/**
|
|
6
6
|
* Xiaomi MiMo login flow.
|
|
7
7
|
*
|
|
8
8
|
* Xiaomi MiMo provides OpenAI-compatible models via
|
|
9
9
|
* https://api.xiaomimimo.com/v1.
|
|
10
10
|
*
|
|
11
|
-
* Standard Xiaomi login
|
|
12
|
-
*
|
|
11
|
+
* Standard Xiaomi login accepts both pay-as-you-go keys and regional `tp-...`
|
|
12
|
+
* keys, probing the regional Token Plan clusters in fallback order.
|
|
13
13
|
*/
|
|
14
14
|
const PROVIDER_ID = "xiaomi";
|
|
15
15
|
const PROVIDER_NAME = "Xiaomi MiMo";
|
|
16
16
|
const STANDARD_AUTH_URL = "https://platform.xiaomimimo.com/#/console/api-keys";
|
|
17
|
-
const TOKEN_PLAN_AUTH_URL = "https://platform.xiaomimimo.com/console/plan-manage";
|
|
18
17
|
const STANDARD_API_BASE_URL = "https://api.xiaomimimo.com/v1";
|
|
19
18
|
const TOKEN_PLAN_KEY_PREFIX = "tp-";
|
|
20
19
|
const STANDARD_VALIDATION_MODEL = "mimo-v2.5";
|
|
@@ -33,18 +32,13 @@ const TOKEN_PLAN_VALIDATION_ENDPOINTS = {
|
|
|
33
32
|
model: TOKEN_PLAN_VALIDATION_MODEL
|
|
34
33
|
}
|
|
35
34
|
};
|
|
36
|
-
const TOKEN_PLAN_REGION_NAMES = {
|
|
37
|
-
sgp: "Singapore",
|
|
38
|
-
ams: "Europe",
|
|
39
|
-
cn: "China"
|
|
40
|
-
};
|
|
41
35
|
function isTokenPlanKey(apiKey) {
|
|
42
36
|
return apiKey.startsWith(TOKEN_PLAN_KEY_PREFIX);
|
|
43
37
|
}
|
|
44
38
|
const VALIDATION_TIMEOUT_MS = 15e3;
|
|
45
|
-
async function validateXiaomiApiKey(apiKey,
|
|
39
|
+
async function validateXiaomiApiKey(apiKey, signal, fetchOverride) {
|
|
46
40
|
const fetchImpl = fetchOverride ?? fetch;
|
|
47
|
-
const endpoints =
|
|
41
|
+
const endpoints = isTokenPlanKey(apiKey) ? [
|
|
48
42
|
TOKEN_PLAN_VALIDATION_ENDPOINTS.sgp,
|
|
49
43
|
TOKEN_PLAN_VALIDATION_ENDPOINTS.ams,
|
|
50
44
|
TOKEN_PLAN_VALIDATION_ENDPOINTS.cn
|
|
@@ -127,31 +121,8 @@ async function loginXiaomi(options) {
|
|
|
127
121
|
const trimmed = apiKey.trim();
|
|
128
122
|
if (!trimmed) throw new ApiKeyRequiredError();
|
|
129
123
|
options.onProgress?.(`Validating ${PROVIDER_ID} API key...`);
|
|
130
|
-
await validateXiaomiApiKey(trimmed,
|
|
131
|
-
return trimmed;
|
|
132
|
-
}
|
|
133
|
-
/**
|
|
134
|
-
* Login to a regional Xiaomi Token Plan endpoint.
|
|
135
|
-
*
|
|
136
|
-
* Prompts for a token-plan API key and validates it against the selected region.
|
|
137
|
-
*/
|
|
138
|
-
async function loginXiaomiTokenPlan(options, region) {
|
|
139
|
-
const fetchImpl = options.fetch ?? fetch;
|
|
140
|
-
if (!options.onPrompt) throw new OnPromptRequiredError(`Xiaomi Token Plan (${TOKEN_PLAN_REGION_NAMES[region]})`);
|
|
141
|
-
options.onAuth?.({
|
|
142
|
-
url: TOKEN_PLAN_AUTH_URL,
|
|
143
|
-
instructions: `Copy your token-plan API key for the ${TOKEN_PLAN_REGION_NAMES[region]} region`
|
|
144
|
-
});
|
|
145
|
-
const apiKey = await options.onPrompt({
|
|
146
|
-
message: `Paste your Xiaomi Token Plan ${TOKEN_PLAN_REGION_NAMES[region]} API key (tp-...)`,
|
|
147
|
-
placeholder: "tp-..."
|
|
148
|
-
});
|
|
149
|
-
if (options.signal?.aborted) throw new LoginCancelledError();
|
|
150
|
-
const trimmed = apiKey.trim();
|
|
151
|
-
if (!trimmed) throw new ApiKeyRequiredError();
|
|
152
|
-
options.onProgress?.(`Validating Xiaomi Token Plan (${TOKEN_PLAN_REGION_NAMES[region]}) API key...`);
|
|
153
|
-
await validateXiaomiApiKey(trimmed, region, options.signal, fetchImpl);
|
|
124
|
+
await validateXiaomiApiKey(trimmed, options.signal, fetchImpl);
|
|
154
125
|
return trimmed;
|
|
155
126
|
}
|
|
156
127
|
//#endregion
|
|
157
|
-
export { loginXiaomi
|
|
128
|
+
export { loginXiaomi };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
2
|
__installBunShim();
|
|
3
|
-
import { V as ProviderHttpError,
|
|
4
|
-
|
|
5
|
-
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@17.3.5/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/zai.ts
|
|
3
|
+
import { V as ProviderHttpError, f as OAuthError } from "./error-CORgGg5a.mjs";
|
|
4
|
+
//#region node_modules/.pnpm/@oh-my-pi+pi-ai@18.1.17/node_modules/@oh-my-pi/pi-ai/src/registry/oauth/zai.ts
|
|
6
5
|
/**
|
|
7
6
|
* Z.ai / GLM OAuth flow (GLM Coding Plan · Sign in)
|
|
8
7
|
*
|
|
@@ -17,22 +16,11 @@ const env = (key) => {
|
|
|
17
16
|
const value = process.env[key];
|
|
18
17
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
19
18
|
};
|
|
20
|
-
const CLIENT_ID = env("ZAI_OAUTH_CLIENT_ID") ?? "client_P8X5CMWmlaRO9gyO-KSqtg";
|
|
21
|
-
const AUTHORIZE_URL = env("ZAI_OAUTH_AUTHORIZE_URL") ?? "https://chat.z.ai/api/oauth/authorize";
|
|
22
|
-
const TOKEN_URL = env("ZAI_OAUTH_TOKEN_URL") ?? "https://zcode.z.ai/api/v1/oauth/token";
|
|
23
19
|
const BIZ_BASE = env("ZAI_BIZ_BASE") ?? "https://api.z.ai";
|
|
24
20
|
/** Business-login endpoint: exchanges the OAuth access token for a biz token. */
|
|
25
21
|
const BUSINESS_LOGIN_URL = env("ZAI_BUSINESS_LOGIN_URL") ?? "https://api.z.ai/api/auth/z/login";
|
|
26
22
|
/** OMP's own key name so sign-in never mutates ZCode's `zcode-api-key`. */
|
|
27
23
|
const KEY_NAME = "oh-my-pi";
|
|
28
|
-
const CALLBACK_PORT = 54548;
|
|
29
|
-
const CALLBACK_PATH = "/callback";
|
|
30
|
-
/** Durable minted key never expires; matches the perplexity NEVER_EXPIRES sentinel. */
|
|
31
|
-
const NEVER_EXPIRES = 864e13;
|
|
32
|
-
function formatErrorDetails(error) {
|
|
33
|
-
if (error instanceof Error) return error.message;
|
|
34
|
-
return String(error);
|
|
35
|
-
}
|
|
36
24
|
/**
|
|
37
25
|
* Z.ai's `{ code, msg, data, success }` envelope. The OAuth token endpoint
|
|
38
26
|
* signals success with `code: 0`; the biz endpoints (`api.z.ai`) use
|
|
@@ -143,61 +131,10 @@ async function mintZaiApiKey(oauthAccessToken, fetchImpl) {
|
|
|
143
131
|
});
|
|
144
132
|
return `${apiKey}.${secretKey}`;
|
|
145
133
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
async generateAuthUrl(state, redirectUri) {
|
|
153
|
-
const authParams = new URLSearchParams({
|
|
154
|
-
redirect_uri: redirectUri,
|
|
155
|
-
response_type: "code",
|
|
156
|
-
client_id: CLIENT_ID,
|
|
157
|
-
state
|
|
158
|
-
});
|
|
159
|
-
return {
|
|
160
|
-
url: `${AUTHORIZE_URL}?${authParams.toString()}`,
|
|
161
|
-
instructions: "Complete Z.ai login in your browser. If the browser cannot reach this machine, paste the final redirect URL or authorization code when prompted."
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
async exchangeToken(code, state, redirectUri) {
|
|
165
|
-
if (this.ctrl.signal?.aborted) throw new LoginCancelledError(`OAuth callback cancelled: ${this.ctrl.signal.reason}`);
|
|
166
|
-
let body;
|
|
167
|
-
try {
|
|
168
|
-
body = await postJson(TOKEN_URL, {
|
|
169
|
-
provider: "zai",
|
|
170
|
-
code,
|
|
171
|
-
redirect_uri: redirectUri,
|
|
172
|
-
state
|
|
173
|
-
}, {}, this.#fetch);
|
|
174
|
-
} catch (error) {
|
|
175
|
-
throw new OAuthError(`Token exchange request failed. url=${TOKEN_URL}; redirect_uri=${redirectUri}; details=${formatErrorDetails(error)}`, {
|
|
176
|
-
kind: "token-exchange",
|
|
177
|
-
provider: "zai",
|
|
178
|
-
cause: error
|
|
179
|
-
});
|
|
180
|
-
}
|
|
181
|
-
const data = unwrapEnvelope(body, "token exchange");
|
|
182
|
-
const oauthAccessToken = trimmedString(data?.zai?.access_token);
|
|
183
|
-
if (!oauthAccessToken) throw new OAuthError("Z.ai token response missing access token", {
|
|
184
|
-
kind: "validation",
|
|
185
|
-
provider: "zai"
|
|
186
|
-
});
|
|
187
|
-
return {
|
|
188
|
-
access: await mintZaiApiKey(oauthAccessToken, this.#fetch),
|
|
189
|
-
refresh: "",
|
|
190
|
-
expires: NEVER_EXPIRES,
|
|
191
|
-
email: typeof data?.user?.email === "string" ? data.user.email : void 0,
|
|
192
|
-
accountId: typeof data?.user?.id === "string" || typeof data?.user?.id === "number" ? String(data.user.id) : void 0
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
};
|
|
196
|
-
/**
|
|
197
|
-
* Login with Z.ai OAuth (GLM Coding Plan).
|
|
198
|
-
*/
|
|
199
|
-
async function loginZaiOAuth(ctrl) {
|
|
200
|
-
return new ZaiOAuthFlow(ctrl).login();
|
|
201
|
-
}
|
|
134
|
+
/** Replaces the short-lived OAuth token with the durable key minted by the Z.ai business APIs. */
|
|
135
|
+
const zaiMintKeyHook = async (credentials, context) => ({
|
|
136
|
+
...credentials,
|
|
137
|
+
access: await mintZaiApiKey(credentials.access, context.fetch)
|
|
138
|
+
});
|
|
202
139
|
//#endregion
|
|
203
|
-
export {
|
|
140
|
+
export { zaiMintKeyHook };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { installBunShim as __installBunShim } from "./bun-shim.mjs";
|
|
2
2
|
__installBunShim();
|
|
3
|
-
import {
|
|
3
|
+
import { k as formatBytes } from "./src-BwW51vA5.mjs";
|
|
4
4
|
import { n as ToolError } from "./tool-errors-DoyxivAR.mjs";
|
|
5
5
|
import * as path from "node:path";
|
|
6
6
|
import * as zlib from "node:zlib";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xiaoso/dsh-tool-plus",
|
|
3
3
|
"description": "Oh My Pi bash runtime ported as a deepseek-harness tool plugin: persistent shell session, output minimizer, managed background jobs, command interception",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.7-beta.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"deepseek-harness",
|
|
@@ -98,20 +98,20 @@
|
|
|
98
98
|
"sharp": ">=0.33"
|
|
99
99
|
},
|
|
100
100
|
"dependencies": {
|
|
101
|
+
"@deepseek-ai/dsh-brand": "0.1.5-rc.1",
|
|
102
|
+
"@deepseek-ai/dsh-invariants": "0.1.5-rc.1",
|
|
101
103
|
"@deepseek-ai/schemastery": "3.18.2",
|
|
102
|
-
"@oh-my-pi/omptype": "
|
|
103
|
-
"@oh-my-pi/pi-agent-core": "
|
|
104
|
-
"@oh-my-pi/pi-ai": "
|
|
105
|
-
"@oh-my-pi/pi-catalog": "
|
|
106
|
-
"@oh-my-pi/pi-natives": "
|
|
107
|
-
"@oh-my-pi/pi-tui": "
|
|
108
|
-
"@oh-my-pi/pi-utils": "
|
|
104
|
+
"@oh-my-pi/omptype": "18.1.17",
|
|
105
|
+
"@oh-my-pi/pi-agent-core": "18.1.17",
|
|
106
|
+
"@oh-my-pi/pi-ai": "18.1.17",
|
|
107
|
+
"@oh-my-pi/pi-catalog": "18.1.17",
|
|
108
|
+
"@oh-my-pi/pi-natives": "18.1.17",
|
|
109
|
+
"@oh-my-pi/pi-tui": "18.1.17",
|
|
110
|
+
"@oh-my-pi/pi-utils": "18.1.17",
|
|
109
111
|
"json5": "^2.2.3",
|
|
110
112
|
"puppeteer-core": "^25.3.0",
|
|
111
113
|
"trash": "^10.1.1",
|
|
112
|
-
"yaml": "^2.9.0"
|
|
113
|
-
"@deepseek-ai/dsh-brand": "0.1.5-rc.1",
|
|
114
|
-
"@deepseek-ai/dsh-invariants": "0.1.5-rc.1"
|
|
114
|
+
"yaml": "^2.9.0"
|
|
115
115
|
},
|
|
116
116
|
"devDependencies": {
|
|
117
117
|
"@deepseek-ai/cordis": "4.0.2",
|
package/presets/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xiaoso/dsh-tool-plus-presets",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7-beta.0",
|
|
4
4
|
"description": "Agent-preset installer for dsh-tool-plus: installs the standard / PTC enhanced preset templates into a DeepSeek Harness home.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
|
|
140
140
|
Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.
|
|
141
141
|
|
|
142
|
-
When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
|
|
142
|
+
When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
|
|
143
143
|
|
|
144
144
|
# ── compaction ──────────────────────────────────────────────────────────────
|
|
145
145
|
|
|
@@ -135,7 +135,7 @@
|
|
|
135
135
|
|
|
136
136
|
Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.
|
|
137
137
|
|
|
138
|
-
When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
|
|
138
|
+
When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
|
|
139
139
|
|
|
140
140
|
# ── compaction ──────────────────────────────────────────────────────────────
|
|
141
141
|
|