@pure01fx/dsh-openai-codex-auth 0.10.0 → 0.10.1

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
@@ -2,6 +2,13 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.10.1
6
+
7
+ - Targets DSH 0.1.5-rc.1 with exact SDK peers and runtime helpers; migrates Responses tool calls to ToolCallId.
8
+ - Keeps browser-local model hiding active during catalog, selection projection, and reconnection updates, filtering before subscribers receive snapshots.
9
+ - Accepts the real Node/ws successful send callback (`null`), avoiding false WebSocket send failures and unintended HTTP fallback; replaces the local ws declaration with official types and handles bounded RawData variants.
10
+ - Adds actual target directory and LLM/tools service protocol regression coverage. Older DSH releases are not claimed by this candidate.
11
+
5
12
  ## 0.10.0
6
13
 
7
14
  ### Codex cloud tools
@@ -1,6 +1,12 @@
1
1
  # Codex 云端能力兼容性跟踪
2
2
 
3
- ## 当前实现与验证边界
3
+ ## DSH 0.1.5-rc.1 版本适配
4
+
5
+ `0.10.1` 迁移 ToolCallId、精确 SDK 依赖和客户端服务提供包,隐藏策略在目录发布投影之前执行。`tests/target-directory.spec.ts` 执行官方 shell 的真实 store/Zustand/Immer 与目标目录/catalog 类,使用合成 Remote 响应和投影输入;这不是浏览器联合验收。`tests/target-services.spec.ts` 使用真实 Cordis/LlmRuntime/ToolRuntime、真实 loopback HTTP/SSE/WebSocket,验证工具 ID、工具执行、含加密 reasoning 的历史回放、永久错误和取消,并确认 WS 没有偷偷回退 HTTP。实际 socket 测试也修复了 ws 成功回调为 null 时的误判。
6
+
7
+ 该版本不运行真实 OAuth、账号刷新或付费请求,不改写既有用户数据;旧版兼容性不在声明范围。下面的线上账号结果来自原 0.10.0 验证,不能视作本版本的新验证。升级/回滚建议见 README。
8
+
9
+ ## 原 0.10.0 实现与验证边界
4
10
 
5
11
  本次范围为已确认的非语音 Codex 云端服务。参考上游 b348fc26674189f758d5941cdab3f78f258b2aa7(cloud 专用跟踪常量在 src/upstream.ts);原 Provider 协议基线仍单独保留。四个工具是普通 DSH function 工具,不依赖专用模式,不覆盖现有工具。
6
12
 
package/README.md CHANGED
@@ -17,7 +17,9 @@
17
17
 
18
18
  ## 快速开始
19
19
 
20
- 当前 `0.10.0` 版本要求 DeepSeek Harness `0.1.1-rc.2`;仍运行 DSH `0.1.0-rc.6` profile 应继续使用插件 `0.6.1`。
20
+ 版本 `0.10.1` 明确适配 DeepSeek Harness `0.1.5-rc.1`,SDK peers/runtime helpers 精确锁定该版本;不声明兼容旧 SDK。旧 DSH `0.1.1-rc.2` profile 应保留原插件 `0.10.0`,升级时在独立 profile 安装新版插件并保留原 profile/锁文件以便回滚。无需迁移账号文件或浏览器隐藏列表;`dsh.engines` 仅作兼容性说明,不当作宿主硬门禁。
21
+
22
+ 本版本通过真实目标 LLM/tools 服务与本地 HTTP/SSE/WebSocket 回放、错误/取消回归;模型隐藏覆盖真实目录/catalog/store 的投影更新、重连和重新加载。验证命令为 `pnpm typecheck && pnpm build && pnpm test`;当前版本未执行线上 OAuth/付费模型验收。
21
23
 
22
24
  将插件安装到 DSH 的 `web` profile:
23
25
 
package/client.js CHANGED
@@ -112,6 +112,9 @@ window.__ModuleLoader__.load({
112
112
  dispose: directory.dispose,
113
113
  wrappedLoad: undefined,
114
114
  wrappedDispose: undefined,
115
+ set: directory.store && directory.store.set,
116
+ wrappedSet: undefined,
117
+ visibleGroups: undefined,
115
118
  generation: 0,
116
119
  rawGroups: directory.store && typeof directory.store.getSnapshot === 'function'
117
120
  ? directory.store.getSnapshot().groups : [],
@@ -124,15 +127,30 @@ window.__ModuleLoader__.load({
124
127
  const groups = visibleModelGroups(rawGroups)
125
128
  return value && typeof value === 'object' ? { ...value, groups } : value
126
129
  }
127
- record.rawGroups = rawGroups
130
+ if (rawGroups !== record.visibleGroups) record.rawGroups = rawGroups
128
131
  const groups = render(directory, record.rawGroups)
132
+ record.visibleGroups = groups
129
133
  return value && typeof value === 'object' ? { ...value, groups } : value
130
134
  }
131
135
  record.wrappedDispose = function (...args) {
132
136
  ++record.generation
133
137
  tracked.delete(directory)
138
+ if (directory.store.set === record.wrappedSet) directory.store.set = record.set
134
139
  return record.dispose.apply(this, args)
135
140
  }
141
+ // Target ModelDirectory publishes catalog/selection/reconnect snapshots through set.
142
+ // Filter before publication so no subscriber can observe a hidden row.
143
+ if (typeof record.set === 'function') {
144
+ record.wrappedSet = function (state) {
145
+ if (state.groups !== record.visibleGroups) record.rawGroups = state.groups
146
+ const available = codexModels(record.rawGroups)
147
+ if (available.length > 0) writeAvailableModels(available)
148
+ const groups = visibleModelGroups(record.rawGroups)
149
+ record.visibleGroups = groups
150
+ return record.set.call(this, { ...state, groups })
151
+ }
152
+ directory.store.set = record.wrappedSet
153
+ }
136
154
  directory.load = record.wrappedLoad
137
155
  directory.dispose = record.wrappedDispose
138
156
  tracked.set(directory, record)
@@ -148,7 +166,9 @@ window.__ModuleLoader__.load({
148
166
  for (const directory of resolver.live.directories.values()) track(directory)
149
167
  }
150
168
  const refresh = () => {
151
- for (const [directory, record] of tracked) render(directory, record.rawGroups)
169
+ for (const [directory, record] of tracked) {
170
+ record.visibleGroups = render(directory, record.rawGroups)
171
+ }
152
172
  }
153
173
  window.addEventListener(MODEL_VISIBILITY_EVENT, refresh)
154
174
 
@@ -159,6 +179,7 @@ window.__ModuleLoader__.load({
159
179
  ++record.generation
160
180
  if (directory.load === record.wrappedLoad) directory.load = record.load
161
181
  if (directory.dispose === record.wrappedDispose) directory.dispose = record.dispose
182
+ if (directory.store.set === record.wrappedSet) directory.store.set = record.set
162
183
  }
163
184
  tracked.clear()
164
185
  }
@@ -68,11 +68,15 @@ class NodeNativeCodexWebSocket {
68
68
  this.fail(failure('native Codex WebSocket returned a binary frame', 'WS_PROTOCOL_ERROR'));
69
69
  return;
70
70
  }
71
- if (data.byteLength > maxFrameBytes) {
71
+ const bytes = Array.isArray(data)
72
+ ? data.reduce((total, chunk) => total + chunk.byteLength, 0) : data.byteLength;
73
+ if (bytes > maxFrameBytes) {
72
74
  this.fail(failure('native Codex WebSocket frame exceeded the size limit', 'WS_FRAME_TOO_LARGE'));
73
75
  return;
74
76
  }
75
- this.push({ type: 'text', text: data.toString('utf8') }, data.byteLength);
77
+ const buffer = Array.isArray(data) ? Buffer.concat(data, bytes)
78
+ : Buffer.isBuffer(data) ? data : Buffer.from(data);
79
+ this.push({ type: 'text', text: buffer.toString('utf8') }, bytes);
76
80
  });
77
81
  socket.on('close', (code, reason) => {
78
82
  this.ended = true;
@@ -124,7 +128,7 @@ class NodeNativeCodexWebSocket {
124
128
  signal?.addEventListener('abort', abort, { once: true });
125
129
  this.socket.send(text, (error) => {
126
130
  signal?.removeEventListener('abort', abort);
127
- if (error === undefined)
131
+ if (error === undefined || error === null)
128
132
  resolve();
129
133
  else
130
134
  reject(failure('native Codex WebSocket send failed', 'WS_RETRYABLE', error));
@@ -1,4 +1,4 @@
1
- import { CallId, LlmError, type ContentBlock, type GenerateOptions, type StreamChunk, type TokenUsage, type ToolSchema } from '@deepseek-ai/dsh-llm';
1
+ import { ToolCallId, LlmError, type ContentBlock, type GenerateOptions, type StreamChunk, type TokenUsage, type ToolSchema } from '@deepseek-ai/dsh-llm';
2
2
  import { type ParseSseOptions } from './sse.js';
3
3
  import { type NativeCodexReplaySource } from './replay.js';
4
4
  export declare const DEFAULT_CODEX_INSTRUCTIONS = "You are Codex, an AI coding agent. Help the user with software engineering tasks.";
@@ -11,7 +11,7 @@ export interface ResolvedImagePart {
11
11
  }
12
12
  export interface ResolvedToolResultPart {
13
13
  type: 'tool-result';
14
- toolCallId: CallId;
14
+ toolCallId: ToolCallId;
15
15
  content: readonly ResolvedContentPart[];
16
16
  isError?: boolean;
17
17
  }
package/lib/responses.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /** Pure DSH-to-Codex Responses request and stream translation. */
2
2
  import { createHash } from 'node:crypto';
3
- import { CallId, CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, isContextWindowExceededError, isQuotaExceededError, LlmError, QUOTA_EXCEEDED_CODE, } from '@deepseek-ai/dsh-llm';
3
+ import { ToolCallId, CONTEXT_WINDOW_EXCEEDED_CODE, EMPTY_RESPONSE_CODE, isContextWindowExceededError, isQuotaExceededError, LlmError, QUOTA_EXCEEDED_CODE, } from '@deepseek-ai/dsh-llm';
4
4
  import { parseSse } from './sse.js';
5
5
  import { NativeCodexReplayCapture, replayAssistantInput, replayableItemId, } from './replay.js';
6
6
  export const DEFAULT_CODEX_INSTRUCTIONS = 'You are Codex, an AI coding agent. Help the user with software engineering tasks.';
@@ -312,7 +312,7 @@ function closeBlock(block) {
312
312
  return { type: 'text', text: block.text };
313
313
  if (block.kind === 'reasoning')
314
314
  return { type: 'reasoning', text: block.text };
315
- return { type: 'tool-call', id: CallId(block.callId), name: block.name ?? '', arguments: block.text };
315
+ return { type: 'tool-call', id: ToolCallId(block.callId), name: block.name ?? '', arguments: block.text };
316
316
  }
317
317
  /** Stateful, transport-free Responses event to DSH chunk translator. */
318
318
  export class ResponsesStreamTranslator {
@@ -398,7 +398,7 @@ export class ResponsesStreamTranslator {
398
398
  this.sawToolCall = true;
399
399
  const block = this.open(`${item.id}:call`, 'tool-call', chunks, item.call_id, item.name);
400
400
  chunks.push({
401
- type: 'tool-call-delta', index: block.index, id: CallId(block.callId),
401
+ type: 'tool-call-delta', index: block.index, id: ToolCallId(block.callId),
402
402
  name: item.name, argumentsDelta: '',
403
403
  });
404
404
  return chunks;
@@ -430,7 +430,7 @@ export class ResponsesStreamTranslator {
430
430
  const delta = eventDelta(event);
431
431
  this.append(block, delta);
432
432
  chunks.push({
433
- type: 'tool-call-delta', index: block.index, id: CallId(block.callId),
433
+ type: 'tool-call-delta', index: block.index, id: ToolCallId(block.callId),
434
434
  ...block.name === undefined ? {} : { name: block.name }, argumentsDelta: delta,
435
435
  });
436
436
  return chunks;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pure01fx/dsh-openai-codex-auth",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "Native ChatGPT Codex provider, device-code-first login, and same-origin Web integration for DeepSeek Harness",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -86,16 +86,22 @@
86
86
  "LICENSE",
87
87
  "CODEX-COMPATIBILITY.md"
88
88
  ],
89
+ "scripts": {
90
+ "build": "tsc",
91
+ "typecheck": "tsc --noEmit",
92
+ "test": "vitest run",
93
+ "prepack": "pnpm build"
94
+ },
89
95
  "dsh": {
90
96
  "engines": {
91
- "dsh": "0.1.1-rc.2"
97
+ "dsh": "0.1.5-rc.1"
92
98
  },
93
99
  "bundle": {
94
100
  "patch": "./cordis.patch.yml"
95
101
  },
96
102
  "client": {
97
103
  "inject": [
98
- "@deepseek-ai/dsh-client-runtime",
104
+ "@deepseek-ai/dsh-client-ui-renderer",
99
105
  "@deepseek-ai/dsh-client-ui-model-selection",
100
106
  "@deepseek-ai/dsh-client-ui-conversation",
101
107
  "@deepseek-ai/dsh-client-ui-settings"
@@ -105,19 +111,19 @@
105
111
  },
106
112
  "peerDependencies": {
107
113
  "@deepseek-ai/cordis": "^4.0.1",
108
- "@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
109
- "@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
110
- "@deepseek-ai/dsh-fs": "0.1.1-rc.2",
111
- "@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
112
- "@deepseek-ai/dsh-llm": "0.1.1-rc.2",
113
- "@deepseek-ai/dsh-sandbox": "0.1.1-rc.2",
114
- "@deepseek-ai/dsh-sandbox-policy": "0.1.1-rc.2",
115
- "@deepseek-ai/dsh-shell": "0.1.1-rc.2",
116
- "@deepseek-ai/dsh-tools": "0.1.1-rc.2"
114
+ "@deepseek-ai/dsh-attachment": "0.1.5-rc.1",
115
+ "@deepseek-ai/dsh-credentials": "0.1.5-rc.1",
116
+ "@deepseek-ai/dsh-fs": "0.1.5-rc.1",
117
+ "@deepseek-ai/dsh-host-webserver": "0.1.5-rc.1",
118
+ "@deepseek-ai/dsh-llm": "0.1.5-rc.1",
119
+ "@deepseek-ai/dsh-sandbox": "0.1.5-rc.1",
120
+ "@deepseek-ai/dsh-sandbox-policy": "0.1.5-rc.1",
121
+ "@deepseek-ai/dsh-shell": "0.1.5-rc.1",
122
+ "@deepseek-ai/dsh-tools": "0.1.5-rc.1"
117
123
  },
118
124
  "dependencies": {
119
- "@deepseek-ai/dsh-atomic-write": "0.1.1-rc.2",
120
- "@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
125
+ "@deepseek-ai/dsh-atomic-write": "0.1.5-rc.1",
126
+ "@deepseek-ai/dsh-home-paths": "0.1.5-rc.1",
121
127
  "@deepseek-ai/schemastery": "^3.18.1",
122
128
  "https-proxy-agent": "7.0.6",
123
129
  "image-size": "^2.0.2",
@@ -125,23 +131,26 @@
125
131
  "ws": "8.21.3"
126
132
  },
127
133
  "devDependencies": {
134
+ "@deepseek-ai/dsh-client-ui-model-selection": "0.1.5-rc.1",
135
+ "@deepseek-ai/dsh-web-frontend": "0.1.5-rc.1",
128
136
  "@deepseek-ai/cordis": "^4.0.1",
129
- "@deepseek-ai/dsh-agent": "0.1.1-rc.2",
130
- "@deepseek-ai/dsh-attachment": "0.1.1-rc.2",
131
- "@deepseek-ai/dsh-attachment-local": "0.1.1-rc.2",
132
- "@deepseek-ai/dsh-credentials": "0.1.1-rc.2",
133
- "@deepseek-ai/dsh-fs": "0.1.1-rc.2",
134
- "@deepseek-ai/dsh-host-webserver": "0.1.1-rc.2",
135
- "@deepseek-ai/dsh-llm": "0.1.1-rc.2",
136
- "@deepseek-ai/dsh-sandbox": "0.1.1-rc.2",
137
- "@deepseek-ai/dsh-sandbox-policy": "0.1.1-rc.2",
138
- "@deepseek-ai/dsh-scope": "0.1.1-rc.2",
139
- "@deepseek-ai/dsh-session": "0.1.1-rc.2",
140
- "@deepseek-ai/dsh-shell": "0.1.1-rc.2",
141
- "@deepseek-ai/dsh-system-prompt": "0.1.1-rc.2",
142
- "@deepseek-ai/dsh-tools": "0.1.1-rc.2",
137
+ "@deepseek-ai/dsh-agent": "0.1.5-rc.1",
138
+ "@deepseek-ai/dsh-attachment": "0.1.5-rc.1",
139
+ "@deepseek-ai/dsh-attachment-local": "0.1.5-rc.1",
140
+ "@deepseek-ai/dsh-credentials": "0.1.5-rc.1",
141
+ "@deepseek-ai/dsh-fs": "0.1.5-rc.1",
142
+ "@deepseek-ai/dsh-host-webserver": "0.1.5-rc.1",
143
+ "@deepseek-ai/dsh-llm": "0.1.5-rc.1",
144
+ "@deepseek-ai/dsh-sandbox": "0.1.5-rc.1",
145
+ "@deepseek-ai/dsh-sandbox-policy": "0.1.5-rc.1",
146
+ "@deepseek-ai/dsh-scope": "0.1.5-rc.1",
147
+ "@deepseek-ai/dsh-session": "0.1.5-rc.1",
148
+ "@deepseek-ai/dsh-shell": "0.1.5-rc.1",
149
+ "@deepseek-ai/dsh-system-prompt": "0.1.5-rc.1",
150
+ "@deepseek-ai/dsh-tools": "0.1.5-rc.1",
143
151
  "@types/node": "^22.20.0",
144
152
  "@types/proxy-from-env": "1.0.4",
153
+ "@types/ws": "8.18.1",
145
154
  "sharp": "^0.35.4",
146
155
  "typescript": "^6.0.3",
147
156
  "vitest": "^4.1.8"
@@ -165,9 +174,5 @@
165
174
  "@deepseek-ai/dsh-sandbox-policy": {
166
175
  "optional": true
167
176
  }
168
- },
169
- "scripts": {
170
- "build": "tsc",
171
- "test": "vitest run"
172
177
  }
173
- }
178
+ }