dsh-codex-subscription 2.1.3-beta.1 → 2.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/lib/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { createRequire } from "node:module";
1
2
  import { createHash, randomBytes, randomUUID } from "node:crypto";
2
3
  import { closeOpenAICodexWebSocketSessions, resetOpenAICodexWebSocketDebugStats } from "@earendil-works/pi-ai/api/openai-codex-responses";
3
4
  import { execFile, spawn } from "node:child_process";
@@ -9,6 +10,9 @@ import { HttpsProxyAgent } from "https-proxy-agent";
9
10
  import WebSocket from "ws";
10
11
  import { clientRequestSchema } from "@deepseek-ai/dsh-client-connection";
11
12
  import { lstat, mkdir, open, readFile, rename, rm, stat } from "node:fs/promises";
13
+ import { constants, readFileSync } from "node:fs";
14
+ import { dirname, join, resolve } from "node:path";
15
+ import { pathToFileURL } from "node:url";
12
16
  import { defineTool } from "@deepseek-ai/dsh-tools";
13
17
  import * as dshCredentials from "@deepseek-ai/dsh-credentials";
14
18
  import { dshHomePath, resolveDshHome } from "@deepseek-ai/dsh-home-paths";
@@ -18,8 +22,24 @@ import z from "@deepseek-ai/schemastery";
18
22
  import { openaiCodexProvider as createOpenAICodexProvider } from "@earendil-works/pi-ai/providers/openai-codex";
19
23
  import { createModels } from "@earendil-works/pi-ai";
20
24
  import { WebError } from "@deepseek-ai/dsh-web";
21
- import { constants } from "node:fs";
22
- import { dirname, join, resolve } from "node:path";
25
+ //#region src/settings-adapter.js
26
+ function createSettingsAdapter(ctx, schema, config, namespace) {
27
+ if (typeof ctx.settings.register === "function") return ctx.settings.register(namespace, schema);
28
+ if (typeof ctx.settings.configure !== "function" || typeof ctx.settings.update !== "function") throw new Error("DSH settings API is unavailable");
29
+ ctx.effect(() => ctx.settings.configure({ auto: false }));
30
+ const entry = ctx.fiber.entry;
31
+ const id = entry?.options?.id ?? entry?.id;
32
+ if (!id) throw new Error("DSH settings entry is unavailable");
33
+ const get = () => Object.fromEntries(Object.entries(config).map(([key, value]) => [key, typeof value?.get === "function" ? value.get() : value]));
34
+ return {
35
+ get,
36
+ update: (patch) => ctx.settings.update(id, patch),
37
+ watch(listener) {
38
+ return ctx.on("loader/volatile-update", () => listener(get()));
39
+ }
40
+ };
41
+ }
42
+ //#endregion
23
43
  //#region src/image-models.js
24
44
  const DEFAULT_IMAGE_MODEL = "gpt-image-2";
25
45
  const IMAGE_MODELS = Object.freeze({
@@ -875,6 +895,10 @@ const RPC_ENDPOINTS = Object.freeze([
875
895
  "preferences/status",
876
896
  "preferences/models",
877
897
  "preferences/update",
898
+ "runtime/status",
899
+ "runtime/install",
900
+ "runtime/remove",
901
+ "runtime/cancel",
878
902
  "reset-credit/inspect",
879
903
  "reset-credit/prepare",
880
904
  "reset-credit/consume",
@@ -1048,6 +1072,48 @@ function authenticatedSubagentChild(child, { Transport, getTokens, thread, signa
1048
1072
  } });
1049
1073
  }
1050
1074
  //#endregion
1075
+ //#region src/subagent-runtime.js
1076
+ const SUBAGENT_RUNTIME_PACKAGE = "@deepseek-ai/dsh-subagent-codex";
1077
+ const SUBAGENT_RUNTIME_VERSION = "0.1.5-rc.2";
1078
+ const require = createRequire(import.meta.url);
1079
+ const execute = promisify(execFile);
1080
+ function inspectSubagentRuntime(resolve = require.resolve) {
1081
+ try {
1082
+ const manifestPath = resolve(`${SUBAGENT_RUNTIME_PACKAGE}/package.json`);
1083
+ if (JSON.parse(readFileSync(manifestPath, "utf8")).version !== "0.1.5-rc.2") return {
1084
+ installed: false,
1085
+ present: true
1086
+ };
1087
+ return { installed: true };
1088
+ } catch {
1089
+ return { installed: false };
1090
+ }
1091
+ }
1092
+ async function loadSubagentRuntime({ resolve: resolve$1 = require.resolve, run = execute, importModule = (url) => import(url) } = {}) {
1093
+ if (!inspectSubagentRuntime(resolve$1).installed) throw new Error("Codex subtask runtime is not prepared");
1094
+ const entry = resolve$1(SUBAGENT_RUNTIME_PACKAGE);
1095
+ const providerRequire = createRequire(entry);
1096
+ const codexManifestPath = providerRequire.resolve("@openai/codex/package.json");
1097
+ const codex = JSON.parse(readFileSync(codexManifestPath, "utf8"));
1098
+ if (codex.version !== "0.153.4" || typeof codex.bin?.codex !== "string") throw new Error("Codex subtask runtime version is unsupported");
1099
+ const wrapper = resolve(dirname(codexManifestPath), codex.bin.codex);
1100
+ try {
1101
+ const { stdout } = await run(process.execPath, [wrapper, "--version"], {
1102
+ timeout: 1e4,
1103
+ maxBuffer: 4096,
1104
+ windowsHide: true
1105
+ });
1106
+ if (stdout.trim() !== "codex-cli 0.153.4") throw new Error("Unexpected CLI version");
1107
+ } catch {
1108
+ throw new Error("Codex subtask runtime is incomplete; prepare it for this platform");
1109
+ }
1110
+ const [official, { JsonRpcLineTransport: Transport }] = await Promise.all([importModule(pathToFileURL(entry).href), importModule(pathToFileURL(providerRequire.resolve("@deepseek-ai/dsh-sdk-protocol")).href)]);
1111
+ return {
1112
+ official,
1113
+ Transport
1114
+ };
1115
+ }
1116
+ //#endregion
1051
1117
  //#region src/subagent-backend.js
1052
1118
  const SUBAGENT_PROVIDER = "codex-subscription-subagent";
1053
1119
  const MODES = /* @__PURE__ */ new Set([
@@ -1086,7 +1152,7 @@ function subagentThreadPolicy(parent, policy, requested = {}) {
1086
1152
  };
1087
1153
  }
1088
1154
  /** Reuse the official DSH process/turn provider; keep only subscription auth here. */
1089
- function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refresh, loadRuntime }) {
1155
+ function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refresh, loadRuntime, maintenance = () => false }) {
1090
1156
  let runtime;
1091
1157
  const load = () => runtime ??= loadRuntime().catch((error) => {
1092
1158
  runtime = void 0;
@@ -1107,6 +1173,7 @@ function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refre
1107
1173
  inheritsParentContext: false,
1108
1174
  async start(request) {
1109
1175
  if (disposed) throw new Error("Codex subagent is unavailable");
1176
+ if (maintenance()) throw new Error("Codex subtask component is being changed; restart DSH after completion");
1110
1177
  const controller = new AbortController();
1111
1178
  active.add(controller);
1112
1179
  const signal = AbortSignal.any([request.signal, controller.signal]);
@@ -1178,7 +1245,11 @@ function createSubscriptionSubagent({ ctx, nativeHome, resolveAuth, store, refre
1178
1245
  }
1179
1246
  }
1180
1247
  },
1181
- prepare: load,
1248
+ activeCount: () => active.size,
1249
+ prepare: () => {
1250
+ if (maintenance()) return Promise.reject(/* @__PURE__ */ new Error("Restart DSH after changing the Codex subtask component"));
1251
+ return load();
1252
+ },
1182
1253
  dispose() {
1183
1254
  disposed = true;
1184
1255
  for (const controller of active) controller.abort();
@@ -1252,11 +1323,106 @@ function createSubagentBackendSwitcher({ entries, prepare, persist }) {
1252
1323
  }
1253
1324
  };
1254
1325
  }
1255
- async function loadSubagentRuntime() {
1256
- const [official, { JsonRpcLineTransport: Transport }] = await Promise.all([import("@deepseek-ai/dsh-subagent-codex"), import("@deepseek-ai/dsh-sdk-protocol")]);
1326
+ //#endregion
1327
+ //#region src/runtime-management.js
1328
+ function createRuntimeManagement({ manager, inspect, active, selectDsh }) {
1329
+ let operation;
1330
+ let state = {
1331
+ phase: "idle",
1332
+ restartRequired: false
1333
+ };
1334
+ const supported = (value) => [
1335
+ "listBundles",
1336
+ "installBundle",
1337
+ "removeBundle",
1338
+ "cancelInstall"
1339
+ ].every((key) => typeof value?.[key] === "function");
1340
+ const status = async () => {
1341
+ const host = manager();
1342
+ let bundle;
1343
+ let available = supported(host);
1344
+ try {
1345
+ if (available) bundle = (await host.listBundles()).find((value) => value.name === SUBAGENT_RUNTIME_PACKAGE);
1346
+ } catch {
1347
+ available = false;
1348
+ }
1349
+ const runtime = inspect();
1350
+ return {
1351
+ ...state,
1352
+ available,
1353
+ installed: runtime.installed,
1354
+ present: runtime.installed || runtime.present === true || bundle?.installed === true,
1355
+ removable: available && bundle?.installed === true && !bundle.readOnlyReason,
1356
+ active: active()
1357
+ };
1358
+ };
1359
+ const start = async (action) => {
1360
+ if (!["install", "remove"].includes(action)) throw Error("invalid-action");
1361
+ if (operation) throw Error("busy");
1362
+ if (state.restartRequired) throw Error("restart-required");
1363
+ if (active() > 0) throw Error("active-tasks");
1364
+ const host = manager();
1365
+ if (!supported(host)) throw Error("unavailable");
1366
+ const requestId = randomUUID();
1367
+ const current = {
1368
+ action,
1369
+ requestId,
1370
+ host
1371
+ };
1372
+ operation = current;
1373
+ state = {
1374
+ phase: action === "install" ? "installing" : "removing",
1375
+ restartRequired: false
1376
+ };
1377
+ current.done = (async () => {
1378
+ try {
1379
+ if (action === "remove") {
1380
+ const bundle = (await host.listBundles()).find((value) => value.name === SUBAGENT_RUNTIME_PACKAGE);
1381
+ if (!bundle?.installed || bundle.readOnlyReason) throw Error("not-removable");
1382
+ await selectDsh();
1383
+ }
1384
+ const result = action === "install" ? await host.installBundle(`${SUBAGENT_RUNTIME_PACKAGE}@${SUBAGENT_RUNTIME_VERSION}`, {
1385
+ enabled: false,
1386
+ requestId
1387
+ }) : await host.removeBundle(SUBAGENT_RUNTIME_PACKAGE);
1388
+ if (result.application === "cancelled") state = {
1389
+ phase: "cancelled",
1390
+ restartRequired: false
1391
+ };
1392
+ else if (["applied", "restart-required"].includes(result.application)) state = {
1393
+ phase: "done",
1394
+ restartRequired: true
1395
+ };
1396
+ else state = {
1397
+ phase: "failed",
1398
+ restartRequired: false,
1399
+ error: result.packageResult?.kind ?? result.error?.code ?? "operation-error"
1400
+ };
1401
+ } catch (error) {
1402
+ state = {
1403
+ phase: "failed",
1404
+ restartRequired: false,
1405
+ error: error.message === "not-removable" ? "not-removable" : "operation-error"
1406
+ };
1407
+ } finally {
1408
+ operation = void 0;
1409
+ }
1410
+ })();
1411
+ return status();
1412
+ };
1257
1413
  return {
1258
- official,
1259
- Transport
1414
+ status,
1415
+ start,
1416
+ blocked: () => operation !== void 0 || state.restartRequired,
1417
+ progress(value) {
1418
+ if (operation?.action === "install" && value.requestId === operation.requestId && value.phase === "applying") state.phase = "applying";
1419
+ },
1420
+ async cancel() {
1421
+ const current = operation;
1422
+ if (current?.action !== "install") return status();
1423
+ if ((await current.host.cancelInstall(current.requestId)).status === "cancelled") await current.done;
1424
+ return status();
1425
+ }
1260
1426
  };
1261
1427
  }
1262
1428
  //#endregion
@@ -2644,7 +2810,7 @@ function openaiCodexSubscriptionProvider({ resolveSpeedMode = () => void 0, reso
2644
2810
  Object.freeze(["0.82.1", "0.85.1"]);
2645
2811
  //#endregion
2646
2812
  //#region src/version.js
2647
- const PACKAGE_VERSION = "2.1.3-beta.1";
2813
+ const PACKAGE_VERSION = "2.1.4";
2648
2814
  const USER_AGENT = `dsh-codex-subscription/${PACKAGE_VERSION}`;
2649
2815
  //#endregion
2650
2816
  //#region src/model-catalog.js
@@ -2689,7 +2855,8 @@ function unsupportedCapabilities(value) {
2689
2855
  function visibleModel(value) {
2690
2856
  if (!record$4(value)) return void 0;
2691
2857
  const id = nonEmpty$2(value.slug);
2692
- if (id === void 0 || value.visibility !== "list") return void 0;
2858
+ const reserve = id === "gpt-reserve" && ["list", "hide"].includes(value.visibility);
2859
+ if (id === void 0 || value.visibility !== "list" && !reserve) return void 0;
2693
2860
  const supported = Array.isArray(value.supported_reasoning_levels) ? value.supported_reasoning_levels : [];
2694
2861
  const input = Array.isArray(value.input_modalities) ? value.input_modalities.filter((item) => ["text", "image"].includes(item)) : ["text", "image"];
2695
2862
  const unsupported = unsupportedCapabilities({
@@ -2699,7 +2866,7 @@ function visibleModel(value) {
2699
2866
  return {
2700
2867
  ...Object.keys(unsupported).length ? { unsupported } : {},
2701
2868
  id,
2702
- name: nonEmpty$2(value.display_name) ?? id,
2869
+ name: reserve ? "GPT-Reserve (Experimental)" : nonEmpty$2(value.display_name) ?? id,
2703
2870
  description: nonEmpty$2(value.description),
2704
2871
  priority: Number.isFinite(value.priority) ? value.priority : 0,
2705
2872
  input: input.length > 0 ? input : ["text"],
@@ -2719,7 +2886,7 @@ function visibleModel(value) {
2719
2886
  function parseOfficialModelCatalog(value) {
2720
2887
  if (!record$4(value) || !Array.isArray(value.models)) throw new Error("Codex returned a malformed model catalog");
2721
2888
  const seen = /* @__PURE__ */ new Set();
2722
- return value.models.map(visibleModel).filter((model) => model !== void 0 && !seen.has(model.id) && seen.add(model.id)).sort((left, right) => right.priority - left.priority);
2889
+ return value.models.map(visibleModel).filter((model) => model !== void 0 && !seen.has(model.id) && seen.add(model.id)).sort((left, right) => Number(left.id === "gpt-reserve") - Number(right.id === "gpt-reserve") || right.priority - left.priority);
2723
2890
  }
2724
2891
  function mergeModel(baseModels, remote) {
2725
2892
  const base = baseModels.find((model) => model.id === remote.id) ?? baseModels.find((model) => model.id !== "gpt-5.3-codex-spark") ?? baseModels[0];
@@ -4693,8 +4860,31 @@ const publicError = (code, message) => ({
4693
4860
  details: { issues: [] }
4694
4861
  }
4695
4862
  });
4696
- function createSubscriptionRpcHandler({ authHandler, usageReader, resetCreditService, preferences, diagnosticsReader, modelCatalog, originalImages, resolveInheritedOriginal, closeConnections }) {
4863
+ function createSubscriptionRpcHandler({ authHandler, usageReader, resetCreditService, preferences, runtimeManagement, diagnosticsReader, modelCatalog, originalImages, resolveInheritedOriginal, closeConnections }) {
4697
4864
  return async (endpoint, payload, signal) => {
4865
+ if ([
4866
+ "runtime/status",
4867
+ "runtime/install",
4868
+ "runtime/remove",
4869
+ "runtime/cancel"
4870
+ ].includes(endpoint)) try {
4871
+ signal.throwIfAborted();
4872
+ if (!runtimeManagement) return publicError("unavailable", "Runtime management is unavailable");
4873
+ const action = endpoint.split("/")[1];
4874
+ return {
4875
+ ok: true,
4876
+ value: action === "status" ? await runtimeManagement.status() : action === "cancel" ? await runtimeManagement.cancel() : await runtimeManagement.start(action)
4877
+ };
4878
+ } catch (error) {
4879
+ if (signal.aborted) throw error;
4880
+ const code = [
4881
+ "busy",
4882
+ "active-tasks",
4883
+ "restart-required",
4884
+ "unavailable"
4885
+ ].includes(error.message) ? error.message : "operation-error";
4886
+ return publicError(code, code);
4887
+ }
4698
4888
  if (endpoint === "image/original/chunk") try {
4699
4889
  signal.throwIfAborted();
4700
4890
  if (typeof payload?.sessionId !== "string" || payload.sessionId.length === 0 || payload.sessionId.length > 512 || typeof payload?.assetId !== "string" || !ORIGINAL_IMAGE_ID_PATTERN.test(payload.assetId) || !Number.isSafeInteger(payload?.offset) || payload.offset < 0 || payload.offset % 4194304 !== 0) return publicError("invalid-input", "Invalid original image request");
@@ -4878,28 +5068,30 @@ function createSearchProviderSwitcher(loader) {
4878
5068
  }
4879
5069
  });
4880
5070
  }
4881
- function apply(ctx) {
4882
- const settings = ctx.settings.register(SETTINGS_NAMESPACE, z.object({
4883
- ...Object.fromEntries(Object.entries(PREFERENCE_FIELDS).map(([field, rule]) => [field, rule.default === void 0 ? z.union(rule.choices) : z.union(rule.choices).default(rule.default)])),
4884
- imageModel: z.union(Object.keys(IMAGE_MODELS)).default(DEFAULT_IMAGE_MODEL),
4885
- imageQuality: z.union([
4886
- "auto",
4887
- "low",
4888
- "medium",
4889
- "high",
4890
- "xhigh",
4891
- "max"
4892
- ]).default("auto"),
4893
- ...Object.fromEntries(Object.entries(IMAGE_FEATURE_DEFAULTS).map(([key, value]) => [key, z.boolean().default(value)])),
4894
- [CUSTOM_CONTEXT_OVERRIDES_FIELD]: z.dict(z.number().step(1).min(1).max(MAX_CONTEXT_BUDGET)).default({}),
4895
- [SEARCH_MODE_FIELD]: z.union(SEARCH_MODES).default("live"),
4896
- [SEARCH_DOMAINS_FIELD]: z.transform(z.array(z.string()).max(20), normalizeSearchDomains).default([]),
4897
- ...Object.fromEntries(QUOTA_THRESHOLD_FIELDS.map((key) => [key, z.number().step(1).min(1).max(100).default(20)])),
4898
- [QUOTA_ALERTS_FIELD]: z.union(QUOTA_ALERT_MODES).default("important"),
4899
- [LEGACY_QUICK_QUOTA_FIELD]: z.boolean(),
4900
- [CUSTOM_CONTEXT_WINDOW_FIELD]: z.number().step(1).min(128e3).max(1e6).default(DEFAULT_CUSTOM_CONTEXT_WINDOW),
4901
- ...Object.fromEntries(Object.entries(CUSTOM_CONTEXT_MODEL_FIELDS).map(([modelKey, field]) => [field, z.number().step(1).min(128e3).max(CUSTOM_CONTEXT_MODEL_CAPS[modelKey]).default(CUSTOM_CONTEXT_MODEL_DEFAULTS[modelKey])]))
4902
- }));
5071
+ const settingsFields = {
5072
+ ...Object.fromEntries(Object.entries(PREFERENCE_FIELDS).map(([field, rule]) => [field, rule.default === void 0 ? z.union(rule.choices) : z.union(rule.choices).default(rule.default)])),
5073
+ imageModel: z.union(Object.keys(IMAGE_MODELS)).default(DEFAULT_IMAGE_MODEL),
5074
+ imageQuality: z.union([
5075
+ "auto",
5076
+ "low",
5077
+ "medium",
5078
+ "high",
5079
+ "xhigh",
5080
+ "max"
5081
+ ]).default("auto"),
5082
+ ...Object.fromEntries(Object.entries(IMAGE_FEATURE_DEFAULTS).map(([key, value]) => [key, z.boolean().default(value)])),
5083
+ [CUSTOM_CONTEXT_OVERRIDES_FIELD]: z.dict(z.number().step(1).min(1).max(MAX_CONTEXT_BUDGET)).default({}),
5084
+ [SEARCH_MODE_FIELD]: z.union(SEARCH_MODES).default("live"),
5085
+ [SEARCH_DOMAINS_FIELD]: z.transform(z.array(z.string()).max(20), normalizeSearchDomains).default([]),
5086
+ ...Object.fromEntries(QUOTA_THRESHOLD_FIELDS.map((key) => [key, z.number().step(1).min(1).max(100).default(20)])),
5087
+ [QUOTA_ALERTS_FIELD]: z.union(QUOTA_ALERT_MODES).default("important"),
5088
+ [LEGACY_QUICK_QUOTA_FIELD]: z.boolean(),
5089
+ [CUSTOM_CONTEXT_WINDOW_FIELD]: z.number().step(1).min(128e3).max(1e6).default(DEFAULT_CUSTOM_CONTEXT_WINDOW),
5090
+ ...Object.fromEntries(Object.entries(CUSTOM_CONTEXT_MODEL_FIELDS).map(([modelKey, field]) => [field, z.number().step(1).min(128e3).max(CUSTOM_CONTEXT_MODEL_CAPS[modelKey]).default(CUSTOM_CONTEXT_MODEL_DEFAULTS[modelKey])]))
5091
+ };
5092
+ const Config = z.object(Object.fromEntries(Object.entries(settingsFields).map(([key, field]) => [key, typeof field.volatile === "function" ? field.volatile() : field])));
5093
+ function apply(ctx, config = {}) {
5094
+ const settings = createSettingsAdapter(ctx, z.object(settingsFields), config, SETTINGS_NAMESPACE);
4903
5095
  const searchProvider = createSearchProviderSwitcher(ctx.loader);
4904
5096
  const network = createCodexNetworkTransport();
4905
5097
  const originalImages = new OriginalImageStore();
@@ -4915,6 +5107,16 @@ function apply(ctx) {
4915
5107
  const baseProvider = createOpenAICodexProvider();
4916
5108
  let resolveAuth = async () => void 0;
4917
5109
  let subagentBackend;
5110
+ const runtimeManagement = createRuntimeManagement({
5111
+ manager: () => ctx.get?.("pluginManager"),
5112
+ inspect: inspectSubagentRuntime,
5113
+ active: () => subagentBackend?.activeCount() ?? 0,
5114
+ selectDsh: async () => {
5115
+ if (subagentBackend) await subagentBackend.select("dsh");
5116
+ else await settings.update({ subagentBackend: "dsh" });
5117
+ }
5118
+ });
5119
+ ctx.effect(() => ctx.on?.("plugin-manager/install-state", (value) => runtimeManagement.progress(value)));
4918
5120
  const modelCatalog = createOfficialModelCatalog({
4919
5121
  getAuth: (options) => resolveAuth(options),
4920
5122
  readCredential: (options) => store.read(PROVIDER, options),
@@ -4953,6 +5155,7 @@ function apply(ctx) {
4953
5155
  connectionMode: settings.get().connectionMode ?? "sse",
4954
5156
  subagentBackend: settings.get().subagentBackend ?? "dsh",
4955
5157
  subagentBackendAvailable: subagentBackend !== void 0,
5158
+ subagentRuntimeInstalled: inspectSubagentRuntime().installed,
4956
5159
  ...readCapabilitySettings(settings.get()),
4957
5160
  [QUICK_QUOTA_MODE_FIELD]: normalizeQuickQuotaMode(settings.get()[QUICK_QUOTA_MODE_FIELD], settings.get()[LEGACY_QUICK_QUOTA_FIELD]),
4958
5161
  [SEARCH_PROVIDER_FIELD]: settings.get()[SEARCH_PROVIDER_FIELD],
@@ -5019,7 +5222,8 @@ function apply(ctx) {
5019
5222
  resolveAuth,
5020
5223
  store,
5021
5224
  refresh: (credential) => network.run("oauth", () => baseProvider.auth.oauth.refresh(credential)),
5022
- loadRuntime: loadSubagentRuntime
5225
+ loadRuntime: loadSubagentRuntime,
5226
+ maintenance: runtimeManagement.blocked
5023
5227
  });
5024
5228
  scoped.subagents.registerProvider(instance.provider);
5025
5229
  const switcher = createSubagentBackendSwitcher({
@@ -5040,7 +5244,10 @@ function apply(ctx) {
5040
5244
  throw error;
5041
5245
  }
5042
5246
  };
5043
- subagentBackend = { select };
5247
+ subagentBackend = {
5248
+ select,
5249
+ activeCount: instance.activeCount
5250
+ };
5044
5251
  const sync = (value) => {
5045
5252
  const mode = value.subagentBackend ?? "dsh";
5046
5253
  if (mode !== requested) select(mode).catch(() => scoped.logger.warn("Could not switch the subscription subagent backend"));
@@ -5185,6 +5392,7 @@ function apply(ctx) {
5185
5392
  usageReader,
5186
5393
  resetCreditService,
5187
5394
  preferences,
5395
+ runtimeManagement,
5188
5396
  diagnosticsReader: () => createSubscriptionDiagnostics({
5189
5397
  auth,
5190
5398
  preferences,
@@ -5217,4 +5425,4 @@ function apply(ctx) {
5217
5425
  }, "codex-subscription: DSH-trusted account RPC"));
5218
5426
  }
5219
5427
  //#endregion
5220
- export { CODEX_IMAGE_GENERATION_URL, CODEX_IMAGE_TOOL_NAME, CODEX_RESET_CONSUME_URL, CODEX_RESET_CREDITS_URL, CODEX_USAGE_URL, CodexLoginCoordinator, DshOAuthCredentialStore, apply, assertCodexAuthUrl, commandForCodexAuthUrl, createCodexAuthService, createCodexImageTool, createCodexResetCreditService, createCodexRpcHandler, createCodexUsageReader, createSearchProviderSwitcher, createSubscriptionDiagnostics, createSubscriptionRpcHandler, decodeCodexPng, inject, name, normalizeContextMode, normalizeCustomContextWindow, openCodexAuthUrl, parseCodexUsage };
5428
+ export { CODEX_IMAGE_GENERATION_URL, CODEX_IMAGE_TOOL_NAME, CODEX_RESET_CONSUME_URL, CODEX_RESET_CREDITS_URL, CODEX_USAGE_URL, CodexLoginCoordinator, Config, DshOAuthCredentialStore, apply, assertCodexAuthUrl, commandForCodexAuthUrl, createCodexAuthService, createCodexImageTool, createCodexResetCreditService, createCodexRpcHandler, createCodexUsageReader, createSearchProviderSwitcher, createSubscriptionDiagnostics, createSubscriptionRpcHandler, decodeCodexPng, inject, name, normalizeContextMode, normalizeCustomContextWindow, openCodexAuthUrl, parseCodexUsage };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-codex-subscription",
3
- "version": "2.1.3-beta.1",
3
+ "version": "2.1.4",
4
4
  "description": "Use ChatGPT and Codex subscriptions in DeepSeek Harness with OAuth, quota, safe resets, web search, images, and Fast mode",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -73,26 +73,27 @@
73
73
  "node": "^22.19.0 || >=24.0.0"
74
74
  },
75
75
  "peerDependencies": {
76
- "@deepseek-ai/cordis": "4.0.1 || 4.0.2",
77
- "@deepseek-ai/dsh-api-remotes": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
78
- "@deepseek-ai/dsh-client-connection": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
79
- "@deepseek-ai/dsh-client-locale": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
80
- "@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
81
- "@deepseek-ai/dsh-client-ui-model-selection": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
82
- "@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
83
- "@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
84
- "@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
85
- "@deepseek-ai/dsh-client-ui-tool": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
86
- "@deepseek-ai/dsh-credentials": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
87
- "@deepseek-ai/dsh-llm": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
88
- "@deepseek-ai/dsh-llm-pi-ai": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
89
- "@deepseek-ai/dsh-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
90
- "@deepseek-ai/dsh-tools": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
91
- "@deepseek-ai/dsh-web": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2",
76
+ "@deepseek-ai/cordis": "4.0.1 || 4.0.2 || 4.0.3",
77
+ "@deepseek-ai/dsh-api-remotes": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
78
+ "@deepseek-ai/dsh-client-connection": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
79
+ "@deepseek-ai/dsh-client-locale": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
80
+ "@deepseek-ai/dsh-client-ui-conversation": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
81
+ "@deepseek-ai/dsh-client-ui-model-selection": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
82
+ "@deepseek-ai/dsh-client-ui-primitives": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
83
+ "@deepseek-ai/dsh-client-ui-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
84
+ "@deepseek-ai/dsh-client-ui-slots": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
85
+ "@deepseek-ai/dsh-client-ui-tool": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
86
+ "@deepseek-ai/dsh-credentials": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
87
+ "@deepseek-ai/dsh-llm": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
88
+ "@deepseek-ai/dsh-llm-pi-ai": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
89
+ "@deepseek-ai/dsh-settings": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
90
+ "@deepseek-ai/dsh-tools": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
91
+ "@deepseek-ai/dsh-web": "0.1.2-rc.1 || 0.1.5-alpha.1 || 0.1.5-alpha.2 || 0.1.5-rc.1 || 0.1.5-rc.2 || 0.1.6-alpha.1 || 0.1.6-alpha.2 || 0.1.7-alpha.1",
92
92
  "@deepseek-ai/schemastery": "3.18.1 || ^3.18.2",
93
93
  "@earendil-works/pi-ai": "0.82.1 || 0.85.1",
94
94
  "react": "^18.2.0",
95
- "react-dom": "^18.2.0"
95
+ "react-dom": "^18.2.0",
96
+ "@deepseek-ai/dsh-subagent-codex": "0.1.5-rc.2"
96
97
  },
97
98
  "devDependencies": {
98
99
  "@deepseek-ai/cordis": "4.0.2",
@@ -120,16 +121,18 @@
120
121
  "fake-indexeddb": "6.2.5",
121
122
  "react": "18.3.1",
122
123
  "react-dom": "18.3.1",
123
- "tsdown": "0.22.2"
124
+ "tsdown": "0.22.2",
125
+ "@deepseek-ai/dsh-subagent-codex": "0.1.5-rc.2"
124
126
  },
125
127
  "dependencies": {
126
128
  "@deepseek-ai/dsh-home-paths": "0.1.1-rc.2",
127
129
  "https-proxy-agent": "7.0.6",
128
130
  "ws": "8.21.3"
129
131
  },
130
- "optionalDependencies": {
131
- "@deepseek-ai/dsh-sdk-protocol": "0.1.5-rc.2",
132
- "@deepseek-ai/dsh-subagent-codex": "0.1.5-rc.2"
132
+ "peerDependenciesMeta": {
133
+ "@deepseek-ai/dsh-subagent-codex": {
134
+ "optional": true
135
+ }
133
136
  },
134
137
  "scripts": {
135
138
  "build": "tsdown --config tsdown.config.mjs",