@trim21/personal-pi-extensions 0.1.550 → 0.1.551

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 +1 -1
  2. package/src/lib/gh-proxy.ts +18 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trim21/personal-pi-extensions",
3
- "version": "0.1.550",
3
+ "version": "0.1.551",
4
4
  "type": "module",
5
5
  "description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
6
6
  "keywords": [
@@ -132,24 +132,22 @@ export function proxyEnvVars(settings: GhProxySettings): NodeJS.ProcessEnv {
132
132
  }
133
133
 
134
134
  /**
135
- * 挂着代理 dispatcher 的 fetch,供 octokit 的 `request.fetch` 使用。
136
- *
137
- * octokit v5 丢弃了 node-fetch 时代的 `agent` 选项(@octokit/request 的选项里没有
138
- * 这个字段,也没有任何地方把它转交给 fetch),只接受自定义 fetch —— octokit
139
- * README 的 Proxy Servers 一节就是挂 undici 的代理 dispatcher。NO_PROXY 匹配由
140
- * EnvHttpProxyAgent 负责;未配置代理时原样返回全局 fetch,默认路径行为不变。
135
+ * 代理 dispatcher:NO_PROXY 匹配、CONNECT 隧道都交给 undici 的
136
+ * EnvHttpProxyAgent,octokit 侧只认自定义 fetch(v5 丢掉了 node-fetch 时代的
137
+ * `agent` 选项,@octokit/request 的选项里没有这个字段,也没有任何地方把它转交给
138
+ * fetch),所以代理只能从 fetch 挂进去。
141
139
  */
142
- function createFetch(settings: GhProxySettings): typeof globalThis.fetch {
143
- const { proxy, noProxy } = settings;
144
- if (!proxy) return globalThis.fetch;
140
+ function createProxyDispatcher(
141
+ proxy: string,
142
+ noProxy: string | undefined,
143
+ ): NonNullable<RequestInit["dispatcher"]> {
145
144
  // undici 包与 Node 全局 fetch 各带一份 Dispatcher 类型声明(@types/node 走
146
145
  // undici-types),结构一致但 compose 重载对不上,这里只做类型层面的转换。
147
- const dispatcher = new EnvHttpProxyAgent({
146
+ return new EnvHttpProxyAgent({
148
147
  httpProxy: proxy,
149
148
  httpsProxy: proxy,
150
149
  ...(noProxy && { noProxy }),
151
150
  }) as unknown as NonNullable<RequestInit["dispatcher"]>;
152
- return (input, init) => globalThis.fetch(input, { ...init, dispatcher });
153
151
  }
154
152
 
155
153
  export interface GhProxy {
@@ -164,13 +162,17 @@ export interface GhProxy {
164
162
  /**
165
163
  * 创建代理配置读取器。配置只在首次使用时读一次并缓存;`load` 与 `fetch` 共用这次
166
164
  * 读取,因此运行期不会出现两者看到不同配置的情况。
165
+ *
166
+ * 缓存的是 dispatcher(连接池复用),**不是** `globalThis.fetch` 本身:每次调用都
167
+ * 取当前的全局 fetch,否则首个请求之后替换 `globalThis.fetch`(插桩、测试替身)
168
+ * 就不再生效。
167
169
  */
168
170
  export function createGhProxy(
169
171
  configPath: string = ghProxyConfigPath(),
170
172
  env: NodeJS.ProcessEnv = process.env,
171
173
  ): GhProxy {
172
174
  let loading: Promise<GhProxyLoad> | undefined;
173
- let proxied: typeof globalThis.fetch | undefined;
175
+ let dispatcher: NonNullable<RequestInit["dispatcher"]> | undefined;
174
176
 
175
177
  function load(): Promise<GhProxyLoad> {
176
178
  loading ??= resolveSettings(configPath, env);
@@ -185,8 +187,10 @@ export function createGhProxy(
185
187
  },
186
188
  fetch: async (input, init) => {
187
189
  const { settings } = await load();
188
- proxied ??= createFetch(settings);
189
- return proxied(input, init);
190
+ const { proxy, noProxy } = settings;
191
+ if (!proxy) return globalThis.fetch(input, init);
192
+ dispatcher ??= createProxyDispatcher(proxy, noProxy);
193
+ return globalThis.fetch(input, { ...init, dispatcher });
190
194
  },
191
195
  };
192
196
  }