@shuind/dsh-codex-harness 0.1.25 → 0.1.26

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/README.md CHANGED
@@ -14,12 +14,13 @@
14
14
  - **远程搜索与压缩**:OpenAI Responses 请求默认优先使用 hosted `web_search` 和 `/responses/compact`;失败时回退到 DSH 的本地实现。
15
15
  - **远程压缩用量**:`/responses/compact` 返回标准 `usage` 时,插件会把 `input_tokens`、缓存读写和 `output_tokens` 原样拆分为 DSH 的用量字段;不再把远程压缩伪造成 `0`。中转站缺失或返回不一致的 usage 时,插件不会编造数字。
16
16
  - **上下文容量**:在 Web 中设置 `1K`–`1000K` tokens,设置值作用于下一次请求。
17
+ - **自动压缩阈值**:Codex preset 的自动压缩会读取最新请求持久化的有效上下文容量;例如设置 `400K` 时,默认 `80%` pressure threshold 是 `320K`,不会错误地按适配器默认 `262,144` 在约 `210K` 提前触发。
17
18
  - **活动状态**:Codex 请求模型、接收模型回复或进行上下文压缩时,在 `Deep diving...` 右侧显示对应阶段和耗时,让长时间 Deep Diving 不再像卡住。
18
19
 
19
20
  ## 安装
20
21
 
21
22
  ```sh
22
- dsh plugin --profile web add @shuind/dsh-codex-harness@0.1.24
23
+ dsh plugin --profile web add @shuind/dsh-codex-harness@0.1.26
23
24
  ```
24
25
 
25
26
  重启 Web,创建新会话,在模式菜单中选择 **Codex 模式**。
@@ -52,7 +53,7 @@ Fast 设置保存在 `codex` 命名空间,只对 Codex preset 生效。
52
53
 
53
54
  ### 上下文容量
54
55
 
55
- 点击 Web 顶部的上下文使用量指示器,可以设置下一次请求的上下文容量。上方 meter 显示当前请求的实际容量;修改设置后,需要发送下一次请求才会更新。
56
+ 点击 Web 顶部的上下文使用量指示器,可以设置下一次请求的上下文容量。上方 meter 显示当前请求的实际容量;修改设置后,需要发送下一次请求才会更新。Codex preset 的自动压缩也使用这个已经持久化的有效容量。
56
57
 
57
58
  上下文容量使用整数 K tokens,范围为 `1K` 到 `1000K`。实际可用上限仍取决于模型和中转站支持情况。
58
59
 
@@ -106,7 +107,7 @@ description: 使用 Codex 工具并开启可选协作提示词。
106
107
  order: 10
107
108
  ```
108
109
 
109
- 然后在 Web 的 **Agent 预设** 中选择 `My Codex`,再新建会话。这个 preset 会加载 Codex 工具,并开启协作提示词;网页搜索、远程压缩、后台任务控制和 Skills 等其他功能需要在同一个 `agent.cordis.yml` 中按需添加。
110
+ 然后在 Web 的 **Agent 预设** 中选择 `My Codex`,再新建会话。这个 preset 会加载 Codex 工具,并开启协作提示词;网页搜索、远程压缩、后台任务控制和 Skills 等其他功能需要在同一个 `agent.cordis.yml` 中按需添加。若希望自定义 preset 也修正自动压缩阈值,请在 compaction 隔离组中使用 `@shuind/dsh-codex-harness/compaction` 替代 `@deepseek-ai/dsh-compaction-basic`。
110
111
 
111
112
  ### 可选协作提示词(私货)
112
113
 
package/lib/client.js CHANGED
@@ -21,6 +21,10 @@ window.__ModuleLoader__.load({
21
21
  //#endregion
22
22
  //#region lib/types/client/activity.js
23
23
  /** Client-only inference used while the host activity projection frame is in flight. */
24
+ /** Equality for selector hooks, whose default is reference identity. */
25
+ function sameModelActivity(left, right) {
26
+ return left?.activity === right?.activity && left?.startedAt === right?.startedAt;
27
+ }
24
28
  /** Infer the request-phase clock from the existing conversation snapshot. */
25
29
  function awaitingModelStartedAt(snapshot) {
26
30
  if (!snapshot.running || snapshot.runningCalls.length > 0) return void 0;
@@ -320,7 +324,7 @@ window.__ModuleLoader__.load({
320
324
  function ActivityLine({ sessionId, useSession, useSessions, useProjection, t }) {
321
325
  const agentPreset = useSessions((state) => state.byId[sessionId]?.agentPreset);
322
326
  const projectedActivity = useProjection("codexActivity");
323
- const fallbackActivity = useSession((snapshot) => modelActivity(snapshot));
327
+ const fallbackActivity = useSession(modelActivity, sameModelActivity);
324
328
  const normalizedProjectedActivity = projectedActivity?.activity === "awaiting-model" ? {
325
329
  activity: fallbackActivity?.activity ?? "requesting-model",
326
330
  startedAt: fallbackActivity?.startedAt ?? projectedActivity.startedAt
@@ -0,0 +1,45 @@
1
+ import { AsyncLocalStorage } from "node:async_hooks";
2
+ import BasicCompactionEngine from "@deepseek-ai/dsh-compaction-basic";
3
+ //#region lib/types/compaction.js
4
+ /** Codex compaction backend that honors the latest durable request capacity. */
5
+ /** Overlay only the capacity lookup used by pressure compaction. */
6
+ function withDurableContextCapacity(llm, activeSession) {
7
+ return new Proxy(llm, { get(target, property) {
8
+ if (property === "resolveModelInfo") return async (provider, model, signal) => {
9
+ const info = await target.resolveModelInfo(provider, model, signal);
10
+ const requestContext = activeSession.getStore()?.requestContext();
11
+ if (requestContext?.provider !== provider || requestContext.model !== model || requestContext.contextWindow === void 0) return info;
12
+ return {
13
+ ...info,
14
+ context: {
15
+ ...info.context,
16
+ contextWindow: requestContext.contextWindow
17
+ }
18
+ };
19
+ };
20
+ const value = Reflect.get(target, property, target);
21
+ return typeof value === "function" ? value.bind(target) : value;
22
+ } });
23
+ }
24
+ /**
25
+ * Keep the upstream compaction policy, retention, overflow recovery, and
26
+ * transaction implementation intact. The scoped LLM seam changes only the
27
+ * context metadata returned during a pressure check.
28
+ */
29
+ var CodexCompactionEngine = class extends BasicCompactionEngine {
30
+ static inject = BasicCompactionEngine.inject;
31
+ static Config = BasicCompactionEngine.Config;
32
+ activeSession;
33
+ constructor(ctx, config = {}) {
34
+ const activeSession = new AsyncLocalStorage();
35
+ const llm = ctx.get("llm");
36
+ if (llm === void 0) throw new Error("codex compaction requires ctx.llm");
37
+ super(ctx.extend({ llm: withDurableContextCapacity(llm, activeSession) }), config);
38
+ this.activeSession = activeSession;
39
+ }
40
+ compactIfNeeded(agent, trigger, signal) {
41
+ return this.activeSession.run(agent.session, () => super.compactIfNeeded(agent, trigger, signal));
42
+ }
43
+ };
44
+ //#endregion
45
+ export { CodexCompactionEngine as default };
@@ -8,6 +8,8 @@ export type CodexModelActivity = {
8
8
  activity: 'requesting-model' | 'model-reply';
9
9
  startedAt: number;
10
10
  };
11
+ /** Equality for selector hooks, whose default is reference identity. */
12
+ export declare function sameModelActivity(left: CodexModelActivity | undefined, right: CodexModelActivity | undefined): boolean;
11
13
  /** Infer the request-phase clock from the existing conversation snapshot. */
12
14
  export declare function awaitingModelStartedAt(snapshot: ActivitySessionSnapshot): number | undefined;
13
15
  /** Infer the first non-empty model token timestamp from the current snapshot. */
@@ -1,4 +1,8 @@
1
1
  /** Client-only inference used while the host activity projection frame is in flight. */
2
+ /** Equality for selector hooks, whose default is reference identity. */
3
+ export function sameModelActivity(left, right) {
4
+ return left?.activity === right?.activity && left?.startedAt === right?.startedAt;
5
+ }
2
6
  /** Infer the request-phase clock from the existing conversation snapshot. */
3
7
  export function awaitingModelStartedAt(snapshot) {
4
8
  if (!snapshot.running || snapshot.runningCalls.length > 0)
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /** Browser controls for the Codex request settings mounted by the Host plugin. */
3
3
  import { useEffect, useState } from 'react';
4
4
  import { CODEX_CONTEXT_MAX, CODEX_CONTEXT_UNIT, isCodexPresetId } from "../context.js";
5
- import { modelActivity } from "./activity.js";
5
+ import { modelActivity, sameModelActivity } from "./activity.js";
6
6
  const NS = 'codex';
7
7
  const SETTINGS_NAMESPACE = 'codex';
8
8
  const MODEL_SETTINGS_SLOT = 'conversation.input.model.settings';
@@ -148,7 +148,7 @@ export function ActivityLine({ sessionId, useSession, useSessions, useProjection
148
148
  // The projection is the authoritative phase and clock. The session snapshot
149
149
  // fallback only covers the short wire gap before the next projection frame;
150
150
  // tool calls intentionally remain silent because their cards own the status.
151
- const fallbackActivity = useSession((snapshot) => modelActivity(snapshot));
151
+ const fallbackActivity = useSession(modelActivity, sameModelActivity);
152
152
  // `undefined` means the key has not arrived yet; `null` is an authoritative
153
153
  // clear and must not be resurrected by the local snapshot fallback.
154
154
  const normalizedProjectedActivity = projectedActivity?.activity === 'awaiting-model'
@@ -0,0 +1,18 @@
1
+ /** Codex compaction backend that honors the latest durable request capacity. */
2
+ import { Context } from '@deepseek-ai/cordis';
3
+ import BasicCompactionEngine from '@deepseek-ai/dsh-compaction-basic';
4
+ import type { CompactionResult, CompactionTrigger } from '@deepseek-ai/dsh-compaction';
5
+ import type { Agent } from '@deepseek-ai/dsh-agent';
6
+ /**
7
+ * Keep the upstream compaction policy, retention, overflow recovery, and
8
+ * transaction implementation intact. The scoped LLM seam changes only the
9
+ * context metadata returned during a pressure check.
10
+ */
11
+ export default class CodexCompactionEngine extends BasicCompactionEngine {
12
+ static inject: string[];
13
+ static Config: import("@deepseek-ai/schemastery").default<import("@deepseek-ai/dsh-compaction-basic").BasicCompactionConfig>;
14
+ private readonly activeSession;
15
+ constructor(ctx: Context, config?: ConstructorParameters<typeof BasicCompactionEngine>[1]);
16
+ compactIfNeeded(agent: Agent, trigger: CompactionTrigger, signal: AbortSignal): Promise<CompactionResult | null>;
17
+ }
18
+ //# sourceMappingURL=compaction.d.ts.map
@@ -0,0 +1,48 @@
1
+ /** Codex compaction backend that honors the latest durable request capacity. */
2
+ import { AsyncLocalStorage } from 'node:async_hooks';
3
+ import BasicCompactionEngine from '@deepseek-ai/dsh-compaction-basic';
4
+ /** Overlay only the capacity lookup used by pressure compaction. */
5
+ function withDurableContextCapacity(llm, activeSession) {
6
+ return new Proxy(llm, {
7
+ get(target, property) {
8
+ if (property === 'resolveModelInfo') {
9
+ return async (provider, model, signal) => {
10
+ const info = await target.resolveModelInfo(provider, model, signal);
11
+ const requestContext = activeSession.getStore()?.requestContext();
12
+ if (requestContext?.provider !== provider
13
+ || requestContext.model !== model
14
+ || requestContext.contextWindow === undefined)
15
+ return info;
16
+ return {
17
+ ...info,
18
+ context: { ...info.context, contextWindow: requestContext.contextWindow },
19
+ };
20
+ };
21
+ }
22
+ const value = Reflect.get(target, property, target);
23
+ return typeof value === 'function' ? value.bind(target) : value;
24
+ },
25
+ });
26
+ }
27
+ /**
28
+ * Keep the upstream compaction policy, retention, overflow recovery, and
29
+ * transaction implementation intact. The scoped LLM seam changes only the
30
+ * context metadata returned during a pressure check.
31
+ */
32
+ export default class CodexCompactionEngine extends BasicCompactionEngine {
33
+ static inject = BasicCompactionEngine.inject;
34
+ static Config = BasicCompactionEngine.Config;
35
+ activeSession;
36
+ constructor(ctx, config = {}) {
37
+ const activeSession = new AsyncLocalStorage();
38
+ const llm = ctx.get('llm');
39
+ if (llm === undefined)
40
+ throw new Error('codex compaction requires ctx.llm');
41
+ super(ctx.extend({ llm: withDurableContextCapacity(llm, activeSession) }), config);
42
+ this.activeSession = activeSession;
43
+ }
44
+ compactIfNeeded(agent, trigger, signal) {
45
+ return this.activeSession.run(agent.session, () => super.compactIfNeeded(agent, trigger, signal));
46
+ }
47
+ }
48
+ //# sourceMappingURL=compaction.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shuind/dsh-codex-harness",
3
- "version": "0.1.25",
3
+ "version": "0.1.26",
4
4
  "description": "A Codex harness with a streamlined system prompt for GPT models that do not fit DSH's native interface, while remaining compatible with the DSH plugin ecosystem.",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -18,6 +18,10 @@
18
18
  "types": "./lib/types/installer.d.ts",
19
19
  "default": "./lib/installer.js"
20
20
  },
21
+ "./compaction": {
22
+ "types": "./lib/types/compaction.d.ts",
23
+ "default": "./lib/compaction.js"
24
+ },
21
25
  "./client": {
22
26
  "types": "./lib/types/client/index.d.ts",
23
27
  "default": "./lib/client.js"
@@ -30,6 +34,7 @@
30
34
  "lib/index.js",
31
35
  "lib/invariant.js",
32
36
  "lib/installer.js",
37
+ "lib/compaction.js",
33
38
  "lib/types/**/*.js",
34
39
  "lib/types/**/*.d.ts",
35
40
  "lib/client.js",
@@ -87,6 +92,9 @@
87
92
  "@deepseek-ai/dsh-client-ui-conversation": ">=0.1.0-rc.8",
88
93
  "@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.8",
89
94
  "@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.8",
95
+ "@deepseek-ai/dsh-compaction": ">=0.1.1-rc.2",
96
+ "@deepseek-ai/dsh-compaction-basic": ">=0.1.1-rc.2",
97
+ "@deepseek-ai/dsh-compaction-tool-result-pruner": ">=0.1.1-rc.2",
90
98
  "@deepseek-ai/dsh-credentials": ">=0.1.0-rc.8",
91
99
  "@deepseek-ai/dsh-fs": ">=0.0.1-rc.1",
92
100
  "@deepseek-ai/dsh-invariants": ">=0.0.1-rc.1",
@@ -95,6 +103,7 @@
95
103
  "@deepseek-ai/dsh-settings": ">=0.1.0-rc.8",
96
104
  "@deepseek-ai/dsh-sandbox": ">=0.0.1-rc.1",
97
105
  "@deepseek-ai/dsh-sandbox-policy": ">=0.0.1-rc.1",
106
+ "@deepseek-ai/dsh-session": ">=0.1.1-rc.2",
98
107
  "@deepseek-ai/dsh-shell": ">=0.0.1-rc.5",
99
108
  "@deepseek-ai/dsh-shell-env": ">=0.0.1-rc.3",
100
109
  "@deepseek-ai/dsh-system-prompt": ">=0.0.1-rc.1",
@@ -102,6 +111,7 @@
102
111
  "@deepseek-ai/dsh-tool-todo": ">=0.0.1-rc.1",
103
112
  "@deepseek-ai/dsh-terminal": ">=0.0.1-rc.3",
104
113
  "@deepseek-ai/dsh-tool-jobs": ">=0.1.0-rc.8",
114
+ "@deepseek-ai/dsh-token-meter": ">=0.1.1-rc.2",
105
115
  "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1"
106
116
  },
107
117
  "peerDependenciesMeta": {
@@ -126,6 +136,15 @@
126
136
  "@deepseek-ai/dsh-client-ui-slots": {
127
137
  "optional": true
128
138
  },
139
+ "@deepseek-ai/dsh-compaction": {
140
+ "optional": true
141
+ },
142
+ "@deepseek-ai/dsh-compaction-basic": {
143
+ "optional": true
144
+ },
145
+ "@deepseek-ai/dsh-compaction-tool-result-pruner": {
146
+ "optional": true
147
+ },
129
148
  "@deepseek-ai/dsh-credentials": {
130
149
  "optional": true
131
150
  },
@@ -150,6 +169,9 @@
150
169
  "@deepseek-ai/dsh-sandbox-policy": {
151
170
  "optional": true
152
171
  },
172
+ "@deepseek-ai/dsh-session": {
173
+ "optional": true
174
+ },
153
175
  "@deepseek-ai/dsh-shell": {
154
176
  "optional": true
155
177
  },
@@ -171,6 +193,9 @@
171
193
  "@deepseek-ai/dsh-tool-jobs": {
172
194
  "optional": true
173
195
  },
196
+ "@deepseek-ai/dsh-token-meter": {
197
+ "optional": true
198
+ },
174
199
  "@deepseek-ai/dsh-tools": {
175
200
  "optional": true
176
201
  }
@@ -183,6 +208,9 @@
183
208
  "@deepseek-ai/dsh-client-ui-conversation": "0.1.0-rc.8",
184
209
  "@deepseek-ai/dsh-client-ui-settings": "0.1.0-rc.8",
185
210
  "@deepseek-ai/dsh-client-ui-slots": "0.1.0-rc.8",
211
+ "@deepseek-ai/dsh-compaction": "0.1.1-rc.2",
212
+ "@deepseek-ai/dsh-compaction-basic": "0.1.1-rc.2",
213
+ "@deepseek-ai/dsh-compaction-tool-result-pruner": "0.1.1-rc.2",
186
214
  "@deepseek-ai/dsh-credentials": "0.1.0-rc.8",
187
215
  "@deepseek-ai/dsh-fs": "0.1.0-rc.6",
188
216
  "@deepseek-ai/dsh-invariants": "0.1.0-rc.6",
@@ -191,6 +219,7 @@
191
219
  "@deepseek-ai/dsh-settings": "0.1.0-rc.8",
192
220
  "@deepseek-ai/dsh-sandbox": "0.1.0-rc.6",
193
221
  "@deepseek-ai/dsh-sandbox-policy": "0.1.0-rc.6",
222
+ "@deepseek-ai/dsh-session": "0.1.1-rc.2",
194
223
  "@deepseek-ai/dsh-shell": "0.1.0-rc.6",
195
224
  "@deepseek-ai/dsh-shell-env": "0.1.0-rc.6",
196
225
  "@deepseek-ai/dsh-system-prompt": "0.1.0-rc.6",
@@ -198,6 +227,7 @@
198
227
  "@deepseek-ai/dsh-tool-todo": "0.1.0-rc.6",
199
228
  "@deepseek-ai/dsh-terminal": "0.1.0-rc.6",
200
229
  "@deepseek-ai/dsh-tool-jobs": "0.1.0-rc.8",
230
+ "@deepseek-ai/dsh-token-meter": "0.1.1-rc.2",
201
231
  "@deepseek-ai/dsh-tools": "0.1.0-rc.6",
202
232
  "@types/node": "^22.20.0",
203
233
  "@types/react": "~18.3.1",
@@ -70,7 +70,7 @@
70
70
  toolResultPruner: true
71
71
  config:
72
72
  - id: compaction-basic
73
- name: '@deepseek-ai/dsh-compaction-basic'
73
+ name: '@shuind/dsh-codex-harness/compaction'
74
74
 
75
75
  - id: command-compact
76
76
  name: '@deepseek-ai/dsh-command-compact'
@@ -70,7 +70,7 @@
70
70
  toolResultPruner: true
71
71
  config:
72
72
  - id: compaction-basic
73
- name: '@deepseek-ai/dsh-compaction-basic'
73
+ name: '@shuind/dsh-codex-harness/compaction'
74
74
 
75
75
  - id: command-compact
76
76
  name: '@deepseek-ai/dsh-command-compact'