dsh-codearts 1.1.3 → 1.1.4

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 CHANGED
@@ -3,6 +3,20 @@
3
3
  本文件记录本插件的重要改动。格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
4
4
  版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
5
5
 
6
+ ## [1.1.4] - 2026-10-26
7
+
8
+ ### 修复
9
+
10
+ - **升级到 1.1.3 报「更新失败:`ERR_PNPM_IGNORED_BUILDS`」**:1.1.3 为修 issue #2 把
11
+ `@earendil-works/pi-ai` 移进 `dependencies`,连带拉入 `@google/genai` / `protobufjs`
12
+ (都带安装期脚本);pnpm 11 默认拦截未批准的依赖脚本并以非零码退出,DSH 更新器据此
13
+ 判失败(包其实已装上)。现在 pi-ai 改为**构建期打包进 `lib/`**:它的厂商 SDK 全是
14
+ 懒加载 lane,插件只用 OpenAI 一路,tree-shaking 后 `@google/genai` / `protobufjs`
15
+ 不进产物也不进依赖树 —— 安装时零新增 npm 包,脚本拦截绝根;pi-ai 版本漂移(issue #2
16
+ 的根因)在结构上一并不可能了。1.1.3 用户侧的临时处理见 INSTALL「八」。
17
+ - 产物体积随之涨到约 1.1 MB(含 pi-ai 核心 + openai SDK 的 openai-completions 懒加载
18
+ chunk),功能与接口不变。
19
+
6
20
  ## [1.1.3] - 2026-10-26
7
21
 
8
22
  ### 修复
package/INSTALL.en.md CHANGED
@@ -133,3 +133,27 @@ console.log(b[0]===0xEF&&b[1]===0xBB&&b[2]===0xBF?'BOM!':'no-BOM');
133
133
  > PS 5.1, which crashed startup repeatedly. It was fixed by rewriting the file with Node
134
134
  > (backup `package.json.bak-bomfix-*`). A scan of the whole `~/.dsh` tree found that one
135
135
  > file only.
136
+
137
+ ## 8. Update to 1.1.3+ fails with `ERR_PNPM_IGNORED_BUILDS`
138
+
139
+ It is not actually a failed install — the `+ dsh-codearts 1.1.3` line means the package
140
+ already landed. What fails is pnpm 11's post-install check: since 1.1.3 the plugin bundles
141
+ its own copy of `@earendil-works/pi-ai`, which transitively pulls `@google/genai` and
142
+ `protobufjs`; both carry install-time scripts, pnpm 11 blocks unapproved dependency scripts
143
+ by default (`strictDepBuilds`) and exits non-zero, which the DSH updater reports as failure.
144
+ Neither script does anything needed at runtime (one is a no-op echo, the other a package
145
+ integrity self-check), so skipping them is safe.
146
+
147
+ One-time fix: append to the profile's `pnpm-workspace.yaml`
148
+ (e.g. `~/.dsh/profiles/desktop/pnpm-workspace.yaml`):
149
+
150
+ ```yaml
151
+ allowBuilds:
152
+ '@google/genai': false
153
+ protobufjs: false
154
+ ```
155
+
156
+ `false` means "deliberately never run their install scripts". Then retry the update. If the
157
+ file already contains placeholder lines like `'@google/genai': set this to true or false`
158
+ (auto-added by pnpm), replace the value with `false` — placeholders count as undecided and
159
+ keep failing. `pnpm approve-builds` in the profile directory works too.
package/INSTALL.md CHANGED
@@ -104,6 +104,28 @@ node scripts/deploy.mjs [profileDir] # profileDir 默认 <用户目录>/.dsh
104
104
  2. **用 Node `fs.writeFileSync`**(默认无 BOM)。
105
105
  3. **用 PowerShell 7 的 `-Encoding utf8NoBOM`**(PS5.1 没有该选项)。
106
106
 
107
+ ## 八、更新到 1.1.3+ 报「更新失败:`ERR_PNPM_IGNORED_BUILDS`」
108
+
109
+ 不是安装失败 —— 看输出里的 `+ dsh-codearts 1.1.3`,包其实已经装好了。报错的是
110
+ pnpm 11 的收尾检查:1.1.3 起插件自带一份 `@earendil-works/pi-ai`,它间接依赖
111
+ `@google/genai` 和 `protobufjs`,这两个包带安装期脚本;pnpm 11 默认拦截未批准的依赖
112
+ 脚本(`strictDepBuilds`)并以**非零码退出**,DSH 更新器据此判为失败。这两个脚本一个
113
+ 是 no-op echo、一个是包完整性自检,**不跑没有任何功能影响**。
114
+
115
+ 修法(一次性):在 profile 的 `pnpm-workspace.yaml`(如
116
+ `~/.dsh/profiles/desktop/pnpm-workspace.yaml`)里追加:
117
+
118
+ ```yaml
119
+ allowBuilds:
120
+ '@google/genai': false
121
+ protobufjs: false
122
+ ```
123
+
124
+ `false` 表示「明确不跑它们的安装脚本」。然后重新更新即可。注意:如果该文件里已有
125
+ `'@google/genai': set this to true or false` 这样的占位行(pnpm 自动加的),必须把值
126
+ 改成 `false` —— 占位符不算决定,会一直报错。也可以在 profile 目录跑
127
+ `pnpm approve-builds` 交互式处理。
128
+
107
129
  写入后务必用 Node 校验前 3 字节是否为 BOM:
108
130
  ```js
109
131
  const fs=require('fs');const b=fs.readFileSync(p);
package/lib/bin.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { I as codeartsAccountsPath, M as isBenefitModel, N as CodeArtsAccountStore, d as fetchCallerIdentity, n as codeartsUsagePath, r as discoverModels, t as CodeArtsUsageTracker } from "./usage-5YK7bW-e.mjs";
2
+ import { I as codeartsAccountsPath, M as isBenefitModel, N as CodeArtsAccountStore, d as fetchCallerIdentity, n as codeartsUsagePath, r as discoverModels, t as CodeArtsUsageTracker } from "./usage-B0NfG8vZ.mjs";
3
3
  import { existsSync, statSync } from "node:fs";
4
4
  //#region src/version.ts
5
- const CODEARTS_VERSION = "1.1.3";
5
+ const CODEARTS_VERSION = "1.1.4";
6
6
  //#endregion
7
7
  //#region src/bin.ts
8
8
  /**
@@ -33,70 +33,70 @@ if (typeof document !== "undefined" && document.querySelector("style[data-plugin
33
33
  document.head.appendChild(tag);
34
34
  }
35
35
  var CodeArtsPluginCard_module_css_default = {
36
- "choices": "xoziZG_choices",
37
- "claimAllRow": "xoziZG_claimAllRow",
38
- "fieldLabel": "xoziZG_fieldLabel",
39
- "balanceUnit": "xoziZG_balanceUnit",
40
- "check": "xoziZG_check",
41
- "usageFill": "xoziZG_usageFill",
42
- "modelShare": "xoziZG_modelShare",
43
- "bar": "xoziZG_bar",
44
- "balance": "xoziZG_balance",
45
- "link": "xoziZG_link",
46
- "tabPanel": "xoziZG_tabPanel",
47
- "headText": "xoziZG_headText",
48
- "balanceRow": "xoziZG_balanceRow",
49
36
  "card": "xoziZG_card",
50
- "manualForm": "xoziZG_manualForm",
51
- "name": "xoziZG_name",
52
- "creditRow": "xoziZG_creditRow",
53
- "creditLink": "xoziZG_creditLink",
37
+ "statusLine": "xoziZG_statusLine",
54
38
  "tabs": "xoziZG_tabs",
55
- "body": "xoziZG_body",
56
- "count": "xoziZG_count",
57
- "accountHint": "xoziZG_accountHint",
58
- "meta": "xoziZG_meta",
59
- "sectionLabel": "xoziZG_sectionLabel",
60
- "manual": "xoziZG_manual",
39
+ "actions": "xoziZG_actions",
40
+ "choiceRow": "xoziZG_choiceRow",
41
+ "modelShare": "xoziZG_modelShare",
42
+ "accountRowActions": "xoziZG_accountRowActions",
43
+ "sectionHead": "xoziZG_sectionHead",
61
44
  "creditFooter": "xoziZG_creditFooter",
62
- "creditHint": "xoziZG_creditHint",
63
- "modelChart": "xoziZG_modelChart",
64
- "accountCard": "xoziZG_accountCard",
65
45
  "danger": "xoziZG_danger",
66
- "accountToolbar": "xoziZG_accountToolbar",
46
+ "modelRequests": "xoziZG_modelRequests",
47
+ "manual": "xoziZG_manual",
48
+ "fieldLabel": "xoziZG_fieldLabel",
49
+ "count": "xoziZG_count",
50
+ "modelName": "xoziZG_modelName",
51
+ "expiryLabel": "xoziZG_expiryLabel",
52
+ "name": "xoziZG_name",
53
+ "barFill": "xoziZG_barFill",
54
+ "balanceUnit": "xoziZG_balanceUnit",
55
+ "section": "xoziZG_section",
56
+ "usageBar": "xoziZG_usageBar",
57
+ "accountHint": "xoziZG_accountHint",
58
+ "modelTrack": "xoziZG_modelTrack",
59
+ "accountInfo": "xoziZG_accountInfo",
60
+ "balanceRow": "xoziZG_balanceRow",
67
61
  "modelTokens": "xoziZG_modelTokens",
62
+ "accountNameRow": "xoziZG_accountNameRow",
63
+ "claimAllRow": "xoziZG_claimAllRow",
64
+ "modelRow": "xoziZG_modelRow",
68
65
  "manualSummary": "xoziZG_manualSummary",
69
- "balanceMeta": "xoziZG_balanceMeta",
70
- "header": "xoziZG_header",
71
- "sectionHead": "xoziZG_sectionHead",
72
- "accountEntry": "xoziZG_accountEntry",
73
- "hint": "xoziZG_hint",
74
- "error": "xoziZG_error",
75
- "modelName": "xoziZG_modelName",
76
- "field": "xoziZG_field",
66
+ "accountName": "xoziZG_accountName",
77
67
  "avatar": "xoziZG_avatar",
78
- "modelTrack": "xoziZG_modelTrack",
79
- "usageBar": "xoziZG_usageBar",
68
+ "choices": "xoziZG_choices",
69
+ "creditHint": "xoziZG_creditHint",
70
+ "creditRow": "xoziZG_creditRow",
71
+ "field": "xoziZG_field",
72
+ "usageFill": "xoziZG_usageFill",
80
73
  "updated": "xoziZG_updated",
81
- "modelRow": "xoziZG_modelRow",
82
74
  "expiryRow": "xoziZG_expiryRow",
83
- "actions": "xoziZG_actions",
84
- "accountRowActions": "xoziZG_accountRowActions",
85
75
  "accountRow": "xoziZG_accountRow",
86
- "accountInfo": "xoziZG_accountInfo",
87
- "modelRequests": "xoziZG_modelRequests",
88
- "modelFill": "xoziZG_modelFill",
76
+ "error": "xoziZG_error",
77
+ "bar": "xoziZG_bar",
78
+ "header": "xoziZG_header",
79
+ "tabPanel": "xoziZG_tabPanel",
80
+ "meta": "xoziZG_meta",
89
81
  "desc": "xoziZG_desc",
90
- "accountNameRow": "xoziZG_accountNameRow",
91
- "area": "xoziZG_area",
82
+ "balance": "xoziZG_balance",
83
+ "modelFill": "xoziZG_modelFill",
84
+ "creditRows": "xoziZG_creditRows",
85
+ "modelChart": "xoziZG_modelChart",
86
+ "headText": "xoziZG_headText",
87
+ "accountToolbar": "xoziZG_accountToolbar",
92
88
  "creditBlock": "xoziZG_creditBlock",
93
- "expiryLabel": "xoziZG_expiryLabel",
94
- "accountName": "xoziZG_accountName",
95
- "section": "xoziZG_section",
96
- "choiceRow": "xoziZG_choiceRow",
97
- "barFill": "xoziZG_barFill",
98
- "statusLine": "xoziZG_statusLine",
99
- "creditRows": "xoziZG_creditRows"
89
+ "sectionLabel": "xoziZG_sectionLabel",
90
+ "manualForm": "xoziZG_manualForm",
91
+ "area": "xoziZG_area",
92
+ "balanceMeta": "xoziZG_balanceMeta",
93
+ "accountCard": "xoziZG_accountCard",
94
+ "check": "xoziZG_check",
95
+ "creditLink": "xoziZG_creditLink",
96
+ "link": "xoziZG_link",
97
+ "accountEntry": "xoziZG_accountEntry",
98
+ "body": "xoziZG_body",
99
+ "hint": "xoziZG_hint"
100
100
  };
101
101
  //#endregion
102
102
  //#region src/client/CodeArtsPluginCard.tsx
@@ -0,0 +1,113 @@
1
+ import { n as __exportAll } from "./rolldown-runtime-B4iAMlE-.mjs";
2
+ //#region node_modules/.pnpm/@earendil-works+pi-ai@1.3.0_@aws-sdk+credential-provider-node@3.972.84_@smithy+signature-v4@5.7.4_ws@8.22.0_zod@4.6.5/node_modules/@earendil-works/pi-ai/dist/utils/text.js
3
+ /** Extract and join text from message content. */
4
+ function contentText(content, separator = "\n") {
5
+ if (typeof content === "string") return content;
6
+ return content.filter((block) => block.type === "text").map((block) => block.text).join(separator);
7
+ }
8
+ /** Render a system message as a complete prompt: its content followed by its sections. */
9
+ function getSystemMessageText(message) {
10
+ const parts = [contentText(message.content)];
11
+ for (const text of Object.values(message.sections ?? {})) if (text !== null) parts.push(text);
12
+ return parts.filter((part) => part.length > 0).join("\n\n");
13
+ }
14
+ /**
15
+ * Render a later system message for APIs that accept system messages mid-conversation.
16
+ * Section changes are framed by name so the model can relate them to the leading prompt.
17
+ * This framing is request-time only and may change between versions.
18
+ */
19
+ function renderSystemMessageUpdate(message) {
20
+ const parts = [];
21
+ const text = contentText(message.content);
22
+ if (text.length > 0) parts.push(text);
23
+ for (const [name, value] of Object.entries(message.sections ?? {})) parts.push(value === null ? `Removed system prompt section "${name}".` : `Updated system prompt section "${name}":\n\n${value}`);
24
+ return parts.join("\n\n");
25
+ }
26
+ //#endregion
27
+ //#region node_modules/.pnpm/@earendil-works+pi-ai@1.3.0_@aws-sdk+credential-provider-node@3.972.84_@smithy+signature-v4@5.7.4_ws@8.22.0_zod@4.6.5/node_modules/@earendil-works/pi-ai/dist/utils/estimate.js
28
+ var estimate_exports = /* @__PURE__ */ __exportAll({
29
+ calculateContextTokens: () => calculateContextTokens,
30
+ estimateContextTokens: () => estimateContextTokens,
31
+ estimateMessageTokens: () => estimateMessageTokens,
32
+ estimateTextAndImageContentTokens: () => estimateTextAndImageContentTokens,
33
+ estimateTextTokens: () => estimateTextTokens
34
+ });
35
+ const CHARS_PER_TOKEN = 3.5;
36
+ const ESTIMATED_IMAGE_CHARS = 4800;
37
+ function calculateContextTokens(usage) {
38
+ return usage.totalTokens || usage.input + usage.output + usage.cacheRead + usage.cacheWrite;
39
+ }
40
+ function safeJsonStringify(value) {
41
+ try {
42
+ return JSON.stringify(value) ?? "undefined";
43
+ } catch {
44
+ return "[unserializable]";
45
+ }
46
+ }
47
+ function estimateTextAndImageContentChars(content) {
48
+ if (typeof content === "string") return content.length;
49
+ let chars = 0;
50
+ for (const block of content) chars += block.type === "text" ? block.text.length : ESTIMATED_IMAGE_CHARS;
51
+ return chars;
52
+ }
53
+ function estimateTextTokens(text) {
54
+ return Math.ceil(text.length / CHARS_PER_TOKEN);
55
+ }
56
+ function estimateTextAndImageContentTokens(content) {
57
+ return Math.ceil(estimateTextAndImageContentChars(content) / CHARS_PER_TOKEN);
58
+ }
59
+ function estimateMessageTokens(message) {
60
+ let chars = 0;
61
+ if (message.role === "system") return estimateTextTokens(getSystemMessageText(message)) + estimateToolsTokens(message.toolsAdded) + estimateToolsTokens(message.toolsRemoved);
62
+ if (message.role === "user") return estimateTextAndImageContentTokens(message.content);
63
+ if (message.role === "toolResult") return estimateTextAndImageContentTokens(message.content);
64
+ for (const block of message.content) if (block.type === "text") chars += block.text.length;
65
+ else if (block.type === "thinking") chars += block.thinking.length;
66
+ else chars += block.name.length + safeJsonStringify(block.arguments).length;
67
+ return Math.ceil(chars / CHARS_PER_TOKEN);
68
+ }
69
+ function getLastAssistantUsageInfo(messages) {
70
+ let latestPrefixTimestamp = Number.NEGATIVE_INFINITY;
71
+ let usageInfo;
72
+ for (let i = 0; i < messages.length; i++) {
73
+ const message = messages[i];
74
+ if (message.role === "assistant") {
75
+ const assistant = message;
76
+ if (assistant.timestamp >= latestPrefixTimestamp && assistant.stopReason !== "aborted" && assistant.stopReason !== "error" && calculateContextTokens(assistant.usage) > 0) usageInfo = {
77
+ usage: assistant.usage,
78
+ index: i
79
+ };
80
+ }
81
+ latestPrefixTimestamp = Math.max(latestPrefixTimestamp, message.timestamp);
82
+ }
83
+ return usageInfo;
84
+ }
85
+ function estimateContextTokens(context) {
86
+ const messages = "messages" in context ? context.messages : context;
87
+ const usageInfo = getLastAssistantUsageInfo(messages);
88
+ if (usageInfo) {
89
+ const usageTokens = calculateContextTokens(usageInfo.usage);
90
+ let trailingTokens = 0;
91
+ for (let i = usageInfo.index + 1; i < messages.length; i++) trailingTokens += estimateMessageTokens(messages[i]);
92
+ return {
93
+ tokens: usageTokens + trailingTokens,
94
+ usageTokens,
95
+ trailingTokens,
96
+ lastUsageIndex: usageInfo.index
97
+ };
98
+ }
99
+ let tokens = 0;
100
+ for (const message of messages) tokens += estimateMessageTokens(message);
101
+ return {
102
+ tokens,
103
+ usageTokens: 0,
104
+ trailingTokens: tokens,
105
+ lastUsageIndex: null
106
+ };
107
+ }
108
+ function estimateToolsTokens(tools) {
109
+ if (!tools || tools.length === 0) return 0;
110
+ return estimateTextTokens(safeJsonStringify(tools));
111
+ }
112
+ //#endregion
113
+ export { renderSystemMessageUpdate as a, getSystemMessageText as i, estimate_exports as n, contentText as r, estimateContextTokens as t };