@trim21/personal-pi-extensions 0.1.597 → 0.1.599

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.
Files changed (2) hide show
  1. package/package.json +5 -5
  2. package/src/lib/proxy.ts +23 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trim21/personal-pi-extensions",
3
- "version": "0.1.597",
3
+ "version": "0.1.599",
4
4
  "type": "module",
5
5
  "description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
6
6
  "keywords": [
@@ -37,8 +37,8 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@earendil-works/pi-agent-core": ">=0.84.1",
40
- "@earendil-works/pi-ai": "^0.84.1",
41
- "@earendil-works/pi-coding-agent": "^0.84.1",
40
+ "@earendil-works/pi-ai": ">=0.84.1",
41
+ "@earendil-works/pi-coding-agent": ">=0.84.1",
42
42
  "@eslint/js": "10.0.1",
43
43
  "@types/lodash-es": "^4.17.12",
44
44
  "@types/node": "^24.13.3",
@@ -60,7 +60,7 @@
60
60
  "lint-staged": "^17.3.0",
61
61
  "prettier": "^3.9.6",
62
62
  "shlex": "^3.0.0",
63
- "typebox": "1.3.1",
63
+ "typebox": ">=1.3.1",
64
64
  "typescript": "npm:@typescript/typescript6@^6.0.2",
65
65
  "typescript-eslint": "^8.67.0",
66
66
  "vitest": "^5.0.0"
@@ -108,7 +108,7 @@
108
108
  "minimatch": "^10.2.6",
109
109
  "octokit": "^5.0.5",
110
110
  "turndown": "^7.2.0",
111
- "undici": "^7.29.0",
111
+ "undici": "^8.0.0",
112
112
  "vscode-jsonrpc": "^9.0.1",
113
113
  "vscode-languageserver-types": "^3.18.0",
114
114
  "web-tree-sitter": "^0.27.0"
package/src/lib/proxy.ts CHANGED
@@ -21,7 +21,7 @@ import { homedir } from "node:os";
21
21
  import { join } from "node:path";
22
22
 
23
23
  import { Type } from "typebox";
24
- import { EnvHttpProxyAgent } from "undici";
24
+ import { EnvHttpProxyAgent, fetch as undiciFetch } from "undici";
25
25
 
26
26
  import { parseWithSchema } from "./parse-with-schema.js";
27
27
 
@@ -144,17 +144,15 @@ export function proxyEnvVars(settings: HttpProxySettings): NodeJS.ProcessEnv {
144
144
  * `agent` 选项,@octokit/request 的选项里没有这个字段,也没有任何地方把它转交给
145
145
  * fetch),所以代理只能从 fetch 挂进去。
146
146
  */
147
- function createProxyDispatcher(
148
- proxy: string,
149
- noProxy: string | undefined,
150
- ): NonNullable<RequestInit["dispatcher"]> {
151
- // undici 包与 Node 全局 fetch 各带一份 Dispatcher 类型声明(@types/node 走
152
- // undici-types),结构一致但 compose 重载对不上,这里只做类型层面的转换。
147
+ function createProxyDispatcher(proxy: string, noProxy: string | undefined): EnvHttpProxyAgent {
153
148
  return new EnvHttpProxyAgent({
154
149
  httpProxy: proxy,
155
150
  httpsProxy: proxy,
151
+ // undici 8 起只有 https 目标默认走 CONNECT 隧道,http 目标改为 absolute-form
152
+ // 转发;这里保持隧道语义统一,http 与 https 一律 CONNECT。
153
+ proxyTunnel: true,
156
154
  ...(noProxy && { noProxy }),
157
- }) as unknown as NonNullable<RequestInit["dispatcher"]>;
155
+ });
158
156
  }
159
157
 
160
158
  export interface HttpProxy {
@@ -162,14 +160,15 @@ export interface HttpProxy {
162
160
  readonly settings: HttpProxySettings;
163
161
  /** 要注入 gh 子进程的代理环境变量;未配置代理时为空对象。 */
164
162
  readonly env: NodeJS.ProcessEnv;
165
- /** 走代理的 fetch;未配置代理时就是全局 fetch。 */
163
+ /** 请求用的 fetch:undici 的 fetch,配置了代理时挂上 dispatcher。 */
166
164
  readonly fetch: typeof globalThis.fetch;
167
165
  }
168
166
 
169
167
  /**
170
- * 读一次配置并组装代理层。缓存的是 dispatcher(连接池复用),**不是**
171
- * `globalThis.fetch` 本身:每次调用都取当前的全局 fetch,否则首个请求之后替换
172
- * `globalThis.fetch`(插桩、测试替身)就不再生效。
168
+ * 读一次配置并组装代理层。请求一律走 undici 自己的 fetch——undici 8 的 dispatcher
169
+ * 换了 handler 协议,Node 全局 fetch 挂不上它(抛 `invalid onRequestStart method`),
170
+ * 所以测试替身 mock undici 的 fetch 即可覆盖全部请求。缓存的是 dispatcher(连接池
171
+ * 复用),不是 fetch 本身。
173
172
  */
174
173
  export function createHttpProxy(
175
174
  configPath: string = proxyConfigPath(),
@@ -177,13 +176,20 @@ export function createHttpProxy(
177
176
  ): HttpProxy {
178
177
  const settings = readProxySettings(configPath, env);
179
178
  const { proxy, noProxy } = settings;
180
- let dispatcher: NonNullable<RequestInit["dispatcher"]> | undefined;
179
+ let dispatcher: EnvHttpProxyAgent | undefined;
181
180
 
182
- const fetch: typeof globalThis.fetch = (input, init) => {
183
- if (!proxy) return globalThis.fetch(input, init);
181
+ const fetch: typeof undiciFetch = (input, init) => {
182
+ if (!proxy) return undiciFetch(input, init);
184
183
  dispatcher ??= createProxyDispatcher(proxy, noProxy);
185
- return globalThis.fetch(input, { ...init, dispatcher });
184
+ return undiciFetch(input, { ...init, dispatcher });
186
185
  };
187
186
 
188
- return { settings, env: proxyEnvVars(settings), fetch };
187
+ return {
188
+ settings,
189
+ env: proxyEnvVars(settings),
190
+ // undici 的 fetch 与 Node 全局 fetch(@types/node 走 undici-types)各带一份
191
+ // Request/Response 类型声明,结构一致但对不上;调用方只传 string | URL,
192
+ // 这里只做类型层面的转换。
193
+ fetch: fetch as typeof globalThis.fetch,
194
+ };
189
195
  }