@linxin666/dsh-client-ui-task-board 0.3.23 → 0.4.0

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 (37) hide show
  1. package/icon.svg +3 -0
  2. package/lib/client.js +351 -85
  3. package/lib/client.js.map +1 -1
  4. package/lib/index.js +174 -916
  5. package/lib/types/client/PluginSettingsCard.d.ts +4 -0
  6. package/lib/types/client/TaskBoardSettingsCard.d.ts +5 -5
  7. package/lib/types/client/board/TaskForm.d.ts +6 -1
  8. package/lib/types/client/board/parse-model-pref.d.ts +4 -0
  9. package/lib/types/client/index.d.ts +43 -10
  10. package/lib/types/client/locales.d.ts +1 -0
  11. package/lib/types/client/main-session.d.ts +32 -0
  12. package/lib/types/client/plugin-card-seat.d.ts +103 -0
  13. package/lib/types/client/settings-form.d.ts +17 -17
  14. package/lib/types/core/controller.d.ts +10 -8
  15. package/lib/types/core/session-reuse.d.ts +4 -2
  16. package/lib/types/host-ledger.d.ts +15 -0
  17. package/lib/types/http.d.ts +18 -1
  18. package/lib/types/index.d.ts +72 -17
  19. package/package.json +30 -24
  20. package/src/client/PluginSettingsCard.tsx +7 -2
  21. package/src/client/TaskBoardSettingsCard.tsx +7 -5
  22. package/src/client/board/NewTaskModal.tsx +33 -7
  23. package/src/client/board/TaskForm.tsx +13 -0
  24. package/src/client/board/parse-model-pref.ts +35 -0
  25. package/src/client/board.module.css +31 -12
  26. package/src/client/index.ts +121 -38
  27. package/src/client/locales.ts +2 -0
  28. package/src/client/main-session.ts +43 -0
  29. package/src/client/plugin-card-seat.ts +192 -0
  30. package/src/client/settings-form.ts +34 -31
  31. package/src/client/sidebar-entry-core.ts +3 -3
  32. package/src/client/sidebar-entry.ts +2 -2
  33. package/src/core/controller.ts +12 -8
  34. package/src/core/session-reuse.ts +14 -5
  35. package/src/host-ledger.ts +59 -11
  36. package/src/http.ts +23 -1
  37. package/src/index.ts +97 -52
package/lib/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { createRequire } from "node:module";
2
- import z from "schemastery";
2
+ import z from "@deepseek-ai/schemastery";
3
3
  import { spawn, spawnSync } from "node:child_process";
4
4
  import { createHash, timingSafeEqual } from "node:crypto";
5
5
  import { chmodSync, closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, readdirSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
6
6
  import { dirname, isAbsolute, join, win32 } from "node:path";
7
7
  import { homedir } from "node:os";
8
8
  import { isAbsolute as isAbsolute$1, join as join$1 } from "node:path/posix";
9
- import { Service } from "@deepseek-ai/cordis";
9
+ import { Context, Service } from "@deepseek-ai/cordis";
10
10
  //#region src/core/schedule.ts
11
11
  /** Inclusive ranges per field, in cron order. */
12
12
  const FIELD_RANGES = [
@@ -181,8 +181,10 @@ function isDigits(value) {
181
181
  * Pick the session a new execution of this task may continue in, or undefined
182
182
  * to mint a fresh conversation. Reuse requires ALL of:
183
183
  * - the task opted in (`reuseSession === true`);
184
- * - the task's newest execution carries a session id and has settled (an open
185
- * execution would have made the ledger refuse the run in the first place);
184
+ * - the task's newest SETTLED execution carries a session id (issue #1587: the
185
+ * launch path calls this after `startExecution` appended this run's own open
186
+ * record, so reading the array tail always found an unsettled row and reuse
187
+ * never happened);
186
188
  * - the roster is known and that session is present and idle.
187
189
  *
188
190
  * An unknown roster (session/list unavailable) never reuses: minting a fresh
@@ -194,8 +196,15 @@ function isDigits(value) {
194
196
  */
195
197
  function reusableSessionId(task, idleSessionIds) {
196
198
  if (task.reuseSession !== true || idleSessionIds === void 0) return void 0;
197
- const last = task.executions[task.executions.length - 1];
198
- if (last === void 0 || last.sessionId === void 0 || last.endedAt === void 0) return void 0;
199
+ let last;
200
+ for (let index = task.executions.length - 1; index >= 0; index -= 1) {
201
+ const candidate = task.executions[index];
202
+ if (candidate.sessionId !== void 0 && candidate.endedAt !== void 0) {
203
+ last = candidate;
204
+ break;
205
+ }
206
+ }
207
+ if (last === void 0 || last.sessionId === void 0) return void 0;
199
208
  return idleSessionIds.has(last.sessionId) ? last.sessionId : void 0;
200
209
  }
201
210
  //#endregion
@@ -1406,6 +1415,11 @@ function processIsAlive(pid) {
1406
1415
  }
1407
1416
  }
1408
1417
  const PROCESS_PROBE_TIMEOUT_MS = 3e3;
1418
+ /**
1419
+ * The CIM fallback pays a WMI cold start, so it gets a wider budget than the
1420
+ * direct `Get-Process` read it backs up.
1421
+ */
1422
+ const CIM_PROBE_TIMEOUT_MS = 8e3;
1409
1423
  let ownStartTime;
1410
1424
  let ownStartTimeResolved = false;
1411
1425
  /**
@@ -1430,6 +1444,52 @@ function linuxStartTimeMs(pid) {
1430
1444
  return;
1431
1445
  }
1432
1446
  }
1447
+ /** Default probe: one hidden, profile-free PowerShell process per script. */
1448
+ const runPowerShellProbe = (script, timeoutMs) => {
1449
+ const probe = spawnSync("powershell", [
1450
+ "-NoProfile",
1451
+ "-NonInteractive",
1452
+ "-Command",
1453
+ script
1454
+ ], {
1455
+ timeout: timeoutMs,
1456
+ windowsHide: true
1457
+ });
1458
+ if (probe.status !== 0 || probe.stdout.length === 0) return void 0;
1459
+ return probe.stdout.toString("utf8").trim();
1460
+ };
1461
+ /** The epoch-millisecond reading a probe printed, or undefined when unusable. */
1462
+ function parseProbeEpochMs(raw) {
1463
+ if (raw === void 0 || raw.trim() === "") return void 0;
1464
+ const started = Number(raw.trim());
1465
+ return Number.isFinite(started) ? started : void 0;
1466
+ }
1467
+ /** Start time through Get-Process: precise, but empty for protected processes. */
1468
+ function getProcessStartScript(pid) {
1469
+ return "[DateTimeOffset]::FromFileTime((Get-Process -Id " + String(pid) + " -ErrorAction SilentlyContinue).StartTime.ToUniversalTime().ToFileTime()).ToUnixTimeMilliseconds()";
1470
+ }
1471
+ /** Start time through Win32_Process: readable for System/svchost too. */
1472
+ function cimStartScript(pid) {
1473
+ return "$p=Get-CimInstance Win32_Process -Filter \"ProcessId=" + String(pid) + "\" -ErrorAction SilentlyContinue;if($p -ne $null){[DateTimeOffset]::FromFileTime($p.CreationDate.ToUniversalTime().ToFileTime()).ToUnixTimeMilliseconds()}";
1474
+ }
1475
+ /**
1476
+ * Windows start time (Unix epoch ms) of a live process.
1477
+ *
1478
+ * `Get-Process` is the precise first choice, but an unprivileged caller cannot
1479
+ * read `.StartTime` for a protected process (System, svchost): the property is
1480
+ * empty, so the probe returns nothing. Without a fallback, a crash leftover
1481
+ * lock whose PID was reused by such a process could never be proven stale and
1482
+ * blocked every startup until the lock was deleted by hand (issue #1629).
1483
+ * Win32_Process through CIM reports the same CreationDate for those processes
1484
+ * at the same millisecond precision, so it is the second identity source. The
1485
+ * probe is injectable so the fallback chain is testable off Windows.
1486
+ */
1487
+ function win32StartTimeMs(pid, probe = runPowerShellProbe) {
1488
+ if (!Number.isSafeInteger(pid) || pid <= 0) return void 0;
1489
+ const direct = parseProbeEpochMs(probe(getProcessStartScript(pid), PROCESS_PROBE_TIMEOUT_MS));
1490
+ if (direct !== void 0) return direct;
1491
+ return parseProbeEpochMs(probe(cimStartScript(pid), CIM_PROBE_TIMEOUT_MS));
1492
+ }
1433
1493
  /**
1434
1494
  * Best-effort start time (Unix epoch ms) of a live process. Used to prove
1435
1495
  * whether the ledger lock really belongs to the PID recorded in it, so a
@@ -1439,20 +1499,7 @@ function linuxStartTimeMs(pid) {
1439
1499
  */
1440
1500
  function processStartTimeMs(pid) {
1441
1501
  if (process.platform === "linux") return linuxStartTimeMs(pid);
1442
- if (process.platform === "win32") {
1443
- const probe = spawnSync("powershell", [
1444
- "-NoProfile",
1445
- "-NonInteractive",
1446
- "-Command",
1447
- "[DateTimeOffset]::FromFileTime((Get-Process -Id " + String(pid) + " -ErrorAction SilentlyContinue).StartTime.ToUniversalTime().ToFileTime()).ToUnixTimeMilliseconds()"
1448
- ], {
1449
- timeout: PROCESS_PROBE_TIMEOUT_MS,
1450
- windowsHide: true
1451
- });
1452
- if (probe.status !== 0 || probe.stdout.length === 0) return void 0;
1453
- const started = Number(probe.stdout.toString("utf8").trim());
1454
- return Number.isFinite(started) ? started : void 0;
1455
- }
1502
+ if (process.platform === "win32") return win32StartTimeMs(pid);
1456
1503
  const env = {
1457
1504
  ...process.env,
1458
1505
  LC_ALL: "C"
@@ -3032,7 +3079,7 @@ function safeConsoleError(message, ...args) {
3032
3079
  } catch {}
3033
3080
  }
3034
3081
  //#endregion
3035
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-typert-protocol@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-typert-protocol/lib/index.js
3082
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-typert-protocol@0.1.7-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-typert-protocol/lib/index.js
3036
3083
  /** The one Remote failure class shared by owners, the Gateway, and consumers. */
3037
3084
  /**
3038
3085
  * One Remote call failure: a real Error carrying its stable code and typed
@@ -3076,7 +3123,10 @@ function isTypertRemoteSegment(value) {
3076
3123
  }
3077
3124
  const REMOTE_METHOD_DESCRIPTOR = "@deepseek-ai/dsh-typert-protocol/remote-methods";
3078
3125
  /**
3079
- * Bind one visible Service field to a Cordis key and Remote namespace.
3126
+ * Bind one visible Service field to a Cordis key and Remote namespace. A
3127
+ * service that owns a Cordis Context also gives its tree `ctx.invocation`,
3128
+ * `undefined` outside a Remote call, so no `TypertRemoteService` is needed for
3129
+ * a Host composition to read it.
3080
3130
  * @param service - owning Service instance, normally `this`.
3081
3131
  * @param serviceKey - exact Cordis service key.
3082
3132
  * @param options - optional distinct wire namespace.
@@ -3086,6 +3136,8 @@ function bindTypertRemote(service, serviceKey, options = {}) {
3086
3136
  validateName("service key", serviceKey);
3087
3137
  const namespace = options.namespace ?? serviceKey;
3088
3138
  validateName("namespace", namespace);
3139
+ const ctx = Reflect.get(service, "ctx");
3140
+ if (ctx instanceof Context) provideInvocationAccessor(ctx);
3089
3141
  return Object.freeze({
3090
3142
  service,
3091
3143
  serviceKey,
@@ -3107,6 +3159,16 @@ var TypertRemoteService = class extends Service {
3107
3159
  this.typertRemote = bindTypertRemote(this, this.name, options);
3108
3160
  }
3109
3161
  };
3162
+ /**
3163
+ * Make `ctx.invocation` read as `undefined` outside a Remote call instead of the
3164
+ * reflect service's "cannot get property" error; a call-derived Context shadows
3165
+ * the accessor with its own property. The first Remote Service constructed in a
3166
+ * tree registers it on the root, where it outlives any one Service.
3167
+ */
3168
+ function provideInvocationAccessor(ctx) {
3169
+ if (Object.hasOwn(ctx.root.reflect.props, "invocation")) return;
3170
+ ctx.root.accessor("invocation", { get: () => void 0 });
3171
+ }
3110
3172
  function Remote(methodExportOrOptions, context) {
3111
3173
  if (typeof methodExportOrOptions === "string") {
3112
3174
  validateName("Remote export name", methodExportOrOptions);
@@ -3177,7 +3239,7 @@ function validateName(subject, value) {
3177
3239
  if (!isTypertRemoteSegment(value)) throw new TypeError(`typert-protocol: ${subject} must contain only RPC endpoint segment characters`);
3178
3240
  }
3179
3241
  //#endregion
3180
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-util-values@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-util-values/lib/index.js
3242
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-util-values@0.1.7-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-util-values/lib/index.js
3181
3243
  /**
3182
3244
  * Deep-freeze an object graph in place while leaving live AbortSignal objects mutable.
3183
3245
  * @param value - value to freeze.
@@ -3221,7 +3283,7 @@ function deepFreeze(value) {
3221
3283
  return value;
3222
3284
  }
3223
3285
  //#endregion
3224
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-util-crypto@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-util-crypto/lib/index.js
3286
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-util-crypto@0.1.7-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-util-crypto/lib/index.js
3225
3287
  /**
3226
3288
  * Random v4 UUID, minted from `crypto.getRandomValues`.
3227
3289
  * @returns the UUID string.
@@ -3234,7 +3296,7 @@ function randomUUID() {
3234
3296
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
3235
3297
  }
3236
3298
  //#endregion
3237
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-brand@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-brand/lib/index.js
3299
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-brand@0.1.7-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-brand/lib/index.js
3238
3300
  /**
3239
3301
  * Duplicate-install-safe nominal primitive helpers.
3240
3302
  *
@@ -3257,801 +3319,11 @@ function brandString(value) {
3257
3319
  return value;
3258
3320
  }
3259
3321
  //#endregion
3260
- //#region ../../node_modules/.pnpm/@deepseek-ai+cosmokit@1.8.3/node_modules/@deepseek-ai/cosmokit/lib/index.js
3261
- /** Return true when a value is `null` or `undefined`. */
3262
- function isNullable(value) {
3263
- return value === null || value === void 0;
3264
- }
3265
- /** Return true for non-array object values. */
3266
- function isPlainObject(data) {
3267
- return data && typeof data === "object" && !Array.isArray(data);
3268
- }
3269
- /** Filter object entries and return a new object. */
3270
- function filterKeys(object, filter) {
3271
- return Object.fromEntries(Object.entries(object).filter(([key, value]) => filter(key, value)));
3272
- }
3273
- /** Map object values while preserving the original key set. */
3274
- function mapValues(object, transform) {
3275
- return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, transform(value, key)]));
3276
- }
3277
- /** Pick selected keys from an object, optionally including `undefined` values. */
3278
- function pick(source, keys, forced) {
3279
- if (!keys) return { ...source };
3280
- const result = {};
3281
- for (const key of keys) if (forced || source[key] !== void 0) result[key] = source[key];
3282
- return result;
3283
- }
3284
- /** Test values using `instanceof` with a `toStringTag` fallback. */
3285
- function is(type, value) {
3286
- if (arguments.length === 1) return (value) => is(type, value);
3287
- return type in globalThis && value instanceof globalThis[type] || Object.prototype.toString.call(value).slice(8, -1) === type;
3288
- }
3289
- function isArrayBufferLike(value) {
3290
- return is("ArrayBuffer", value) || is("SharedArrayBuffer", value);
3291
- }
3292
- function isArrayBufferSource(value) {
3293
- return isArrayBufferLike(value) || ArrayBuffer.isView(value);
3294
- }
3295
- /** Binary source detection and base64/hex conversion helpers. */
3296
- var Binary;
3297
- (function(Binary) {
3298
- Binary.is = isArrayBufferLike;
3299
- Binary.isSource = isArrayBufferSource;
3300
- function fromSource(source) {
3301
- if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
3302
- else return source;
3303
- }
3304
- Binary.fromSource = fromSource;
3305
- function toBase64(source) {
3306
- source = fromSource(source);
3307
- if (typeof Buffer !== "undefined") return Buffer.from(source).toString("base64");
3308
- let binary = "";
3309
- const bytes = new Uint8Array(source);
3310
- for (let i = 0; i < bytes.byteLength; i++) binary += String.fromCharCode(bytes[i]);
3311
- return btoa(binary);
3312
- }
3313
- Binary.toBase64 = toBase64;
3314
- function fromBase64(source) {
3315
- if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "base64"));
3316
- return Uint8Array.from(atob(source), (c) => c.charCodeAt(0));
3317
- }
3318
- Binary.fromBase64 = fromBase64;
3319
- function toHex(source) {
3320
- source = fromSource(source);
3321
- if (typeof Buffer !== "undefined") return Buffer.from(source).toString("hex");
3322
- return Array.from(new Uint8Array(source), (byte) => byte.toString(16).padStart(2, "0")).join("");
3323
- }
3324
- Binary.toHex = toHex;
3325
- function fromHex(source) {
3326
- if (typeof Buffer !== "undefined") return fromSource(Buffer.from(source, "hex"));
3327
- const hex = source.length % 2 === 0 ? source : source.slice(0, source.length - 1);
3328
- const buffer = [];
3329
- for (let i = 0; i < hex.length; i += 2) buffer.push(parseInt(`${hex[i]}${hex[i + 1]}`, 16));
3330
- return Uint8Array.from(buffer).buffer;
3331
- }
3332
- Binary.fromHex = fromHex;
3333
- })(Binary || (Binary = {}));
3334
- Binary.fromBase64;
3335
- Binary.toBase64;
3336
- Binary.fromHex;
3337
- Binary.toHex;
3338
- /** Deep-clone common JavaScript values while preserving prototypes and cycles. */
3339
- function clone(source, refs = /* @__PURE__ */ new Map()) {
3340
- if (!source || typeof source !== "object") return source;
3341
- if (is("Date", source)) return new Date(source.valueOf());
3342
- if (is("RegExp", source)) return new RegExp(source.source, source.flags);
3343
- if (isArrayBufferLike(source)) return source.slice(0);
3344
- if (ArrayBuffer.isView(source)) return source.buffer.slice(source.byteOffset, source.byteOffset + source.byteLength);
3345
- const cached = refs.get(source);
3346
- if (cached) return cached;
3347
- if (Array.isArray(source)) {
3348
- const result = [];
3349
- refs.set(source, result);
3350
- source.forEach((value, index) => {
3351
- result[index] = Reflect.apply(clone, null, [value, refs]);
3352
- });
3353
- return result;
3354
- }
3355
- const result = Object.create(Object.getPrototypeOf(source));
3356
- refs.set(source, result);
3357
- for (const key of Reflect.ownKeys(source)) {
3358
- const descriptor = { ...Reflect.getOwnPropertyDescriptor(source, key) };
3359
- if ("value" in descriptor) descriptor.value = Reflect.apply(clone, null, [descriptor.value, refs]);
3360
- Reflect.defineProperty(result, key, descriptor);
3361
- }
3362
- return result;
3363
- }
3364
- /** Deeply compare arrays, dates, regexps, buffers, and plain object fields. */
3365
- function deepEqual(a, b, strict) {
3366
- if (a === b) return true;
3367
- if (!strict && isNullable(a) && isNullable(b)) return true;
3368
- if (typeof a !== typeof b) return false;
3369
- if (typeof a !== "object") return false;
3370
- if (!a || !b) return false;
3371
- function check(test, then) {
3372
- return test(a) ? test(b) ? then(a, b) : false : test(b) ? false : void 0;
3373
- }
3374
- return check(Array.isArray, (a, b) => a.length === b.length && a.every((item, index) => deepEqual(item, b[index]))) ?? check(is("Date"), (a, b) => a.valueOf() === b.valueOf()) ?? check(is("RegExp"), (a, b) => a.source === b.source && a.flags === b.flags) ?? check(isArrayBufferLike, (a, b) => {
3375
- if (a.byteLength !== b.byteLength) return false;
3376
- const viewA = new Uint8Array(a);
3377
- const viewB = new Uint8Array(b);
3378
- for (let i = 0; i < viewA.length; i++) if (viewA[i] !== viewB[i]) return false;
3379
- return true;
3380
- }) ?? Object.keys({
3381
- ...a,
3382
- ...b
3383
- }).every((key) => deepEqual(a[key], b[key], strict));
3384
- }
3385
- /** Time constants plus parsing and formatting helpers. */
3386
- var Time;
3387
- (function(Time) {
3388
- Time.millisecond = 1;
3389
- Time.second = 1e3;
3390
- Time.minute = Time.second * 60;
3391
- Time.hour = Time.minute * 60;
3392
- Time.day = Time.hour * 24;
3393
- Time.week = Time.day * 7;
3394
- let timezoneOffset = (/* @__PURE__ */ new Date()).getTimezoneOffset();
3395
- function setTimezoneOffset(offset) {
3396
- timezoneOffset = offset;
3397
- }
3398
- Time.setTimezoneOffset = setTimezoneOffset;
3399
- function getTimezoneOffset() {
3400
- return timezoneOffset;
3401
- }
3402
- Time.getTimezoneOffset = getTimezoneOffset;
3403
- function getDateNumber(date = /* @__PURE__ */ new Date(), offset) {
3404
- if (typeof date === "number") date = new Date(date);
3405
- if (offset === void 0) offset = timezoneOffset;
3406
- return Math.floor((date.valueOf() / Time.minute - offset) / 1440);
3407
- }
3408
- Time.getDateNumber = getDateNumber;
3409
- function fromDateNumber(value, offset) {
3410
- const date = new Date(value * Time.day);
3411
- if (offset === void 0) offset = timezoneOffset;
3412
- return new Date(+date + offset * Time.minute);
3413
- }
3414
- Time.fromDateNumber = fromDateNumber;
3415
- const numeric = /\d+(?:\.\d+)?/.source;
3416
- const timeRegExp = new RegExp(`^${[
3417
- "w(?:eek(?:s)?)?",
3418
- "d(?:ay(?:s)?)?",
3419
- "h(?:our(?:s)?)?",
3420
- "m(?:in(?:ute)?(?:s)?)?",
3421
- "s(?:ec(?:ond)?(?:s)?)?"
3422
- ].map((unit) => `(${numeric}${unit})?`).join("")}$`);
3423
- function parseTime(source) {
3424
- const capture = timeRegExp.exec(source);
3425
- if (!capture) return 0;
3426
- return (parseFloat(capture[1]) * Time.week || 0) + (parseFloat(capture[2]) * Time.day || 0) + (parseFloat(capture[3]) * Time.hour || 0) + (parseFloat(capture[4]) * Time.minute || 0) + (parseFloat(capture[5]) * Time.second || 0);
3427
- }
3428
- Time.parseTime = parseTime;
3429
- function parseDate(date) {
3430
- const parsed = parseTime(date);
3431
- if (parsed) date = Date.now() + parsed;
3432
- else if (/^\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).toLocaleDateString()}-${date}`;
3433
- else if (/^\d{1,2}-\d{1,2}-\d{1,2}(:\d{1,2}){1,2}$/.test(date)) date = `${(/* @__PURE__ */ new Date()).getFullYear()}-${date}`;
3434
- return date ? new Date(date) : /* @__PURE__ */ new Date();
3435
- }
3436
- Time.parseDate = parseDate;
3437
- function format(ms) {
3438
- const abs = Math.abs(ms);
3439
- if (abs >= Time.day - Time.hour / 2) return Math.round(ms / Time.day) + "d";
3440
- else if (abs >= Time.hour - Time.minute / 2) return Math.round(ms / Time.hour) + "h";
3441
- else if (abs >= Time.minute - Time.second / 2) return Math.round(ms / Time.minute) + "m";
3442
- else if (abs >= Time.second) return Math.round(ms / Time.second) + "s";
3443
- return ms + "ms";
3444
- }
3445
- Time.format = format;
3446
- function toDigits(source, length = 2) {
3447
- return source.toString().padStart(length, "0");
3448
- }
3449
- Time.toDigits = toDigits;
3450
- function template(template, time = /* @__PURE__ */ new Date()) {
3451
- return template.replace("yyyy", time.getFullYear().toString()).replace("yy", time.getFullYear().toString().slice(2)).replace("MM", toDigits(time.getMonth() + 1)).replace("dd", toDigits(time.getDate())).replace("hh", toDigits(time.getHours())).replace("mm", toDigits(time.getMinutes())).replace("ss", toDigits(time.getSeconds())).replace("SSS", toDigits(time.getMilliseconds(), 3));
3452
- }
3453
- Time.template = template;
3454
- })(Time || (Time = {}));
3455
- //#endregion
3456
- //#region ../../node_modules/.pnpm/@deepseek-ai+schemastery@3.18.2/node_modules/@deepseek-ai/schemastery/lib/index.mjs
3457
- const kSchema = Symbol.for("schemastery");
3458
- const kValidationError = Symbol.for("ValidationError");
3459
- globalThis.__schemastery_index__ ??= 0;
3460
- globalThis.__schemastery_refs__ = void 0;
3461
- var ValidationError = class extends TypeError {
3462
- options;
3463
- name = "ValidationError";
3464
- constructor(message, options) {
3465
- let prefix = "$";
3466
- for (const segment of options.path || []) if (typeof segment === "string") prefix += "." + segment;
3467
- else if (typeof segment === "number") prefix += "[" + segment + "]";
3468
- else if (typeof segment === "symbol") prefix += `[Symbol(${segment.toString()})]`;
3469
- if (prefix.startsWith(".")) prefix = prefix.slice(1);
3470
- super((prefix === "$" ? "" : `${prefix} `) + message);
3471
- this.options = options;
3472
- }
3473
- static is(error) {
3474
- return !!error?.[kValidationError];
3475
- }
3476
- };
3477
- Object.defineProperty(ValidationError.prototype, kValidationError, { value: true });
3478
- const Schema = function(options) {
3479
- const schema = function(data, options = {}) {
3480
- return Schema.resolve(data, schema, options)[0];
3481
- };
3482
- if (options.refs) {
3483
- const refs = mapValues(options.refs, (options) => new Schema(options));
3484
- const getRef = (uid) => refs[uid];
3485
- for (const key in refs) {
3486
- const options = refs[key];
3487
- options.sKey = getRef(options.sKey);
3488
- options.inner = getRef(options.inner);
3489
- options.list = options.list && options.list.map(getRef);
3490
- options.dict = options.dict && mapValues(options.dict, getRef);
3491
- }
3492
- return refs[options.uid];
3493
- }
3494
- Object.assign(schema, options);
3495
- if (typeof schema.callback === "string") try {
3496
- schema.callback = new Function("return " + schema.callback)();
3497
- } catch {}
3498
- Object.defineProperty(schema, "uid", { value: globalThis.__schemastery_index__++ });
3499
- Object.setPrototypeOf(schema, Schema.prototype);
3500
- schema.meta ||= {};
3501
- schema.toString = schema.toString.bind(schema);
3502
- return schema;
3503
- };
3504
- Schema.prototype = Object.create(Function.prototype);
3505
- Schema.prototype[kSchema] = true;
3506
- Object.defineProperty(Schema.prototype, "~standard", { get() {
3507
- return {
3508
- version: 1,
3509
- vendor: "schemastery",
3510
- validate: (value) => {
3511
- try {
3512
- return { value: Schema.resolve(value, this, {})[0] };
3513
- } catch (error) {
3514
- if (ValidationError.is(error)) return { issues: [{
3515
- message: error.message,
3516
- path: error.options.path
3517
- }] };
3518
- throw error;
3519
- }
3520
- }
3521
- };
3522
- } });
3523
- Schema.ValidationError = ValidationError;
3524
- Schema.prototype.toJSON = function toJSON() {
3525
- if (globalThis.__schemastery_refs__) {
3526
- globalThis.__schemastery_refs__[this.uid] ??= JSON.parse(JSON.stringify({ ...this }));
3527
- return this.uid;
3528
- }
3529
- globalThis.__schemastery_refs__ = { [this.uid]: { ...this } };
3530
- globalThis.__schemastery_refs__[this.uid] = JSON.parse(JSON.stringify({ ...this }));
3531
- const result = {
3532
- uid: this.uid,
3533
- refs: globalThis.__schemastery_refs__
3534
- };
3535
- globalThis.__schemastery_refs__ = void 0;
3536
- return result;
3537
- };
3538
- Schema.prototype.set = function set(key, value) {
3539
- this.dict[key] = value;
3540
- return this;
3541
- };
3542
- Schema.prototype.push = function push(value) {
3543
- this.list.push(value);
3544
- return this;
3545
- };
3546
- function mergeDesc(original, messages) {
3547
- const result = typeof original === "string" ? { "": original } : { ...original };
3548
- for (const locale in messages) {
3549
- const value = messages[locale];
3550
- if (value?.$description || value?.$desc) result[locale] = value.$description || value.$desc;
3551
- else if (typeof value === "string") result[locale] = value;
3552
- }
3553
- return result;
3554
- }
3555
- function getInner(value) {
3556
- return value?.$value ?? value?.$inner;
3557
- }
3558
- function extractKeys(data) {
3559
- return filterKeys(data ?? {}, (key) => !key.startsWith("$"));
3560
- }
3561
- Schema.prototype.i18n = function i18n(messages) {
3562
- const schema = Schema(this);
3563
- const desc = mergeDesc(schema.meta.description, messages);
3564
- if (Object.keys(desc).length) schema.meta.description = desc;
3565
- if (schema.dict) schema.dict = mapValues(schema.dict, (inner, key) => {
3566
- return inner.i18n(mapValues(messages, (data) => getInner(data)?.[key] ?? data?.[key]));
3567
- });
3568
- if (schema.list) schema.list = schema.list.map((inner, index) => {
3569
- return inner.i18n(mapValues(messages, (data = {}) => {
3570
- if (Array.isArray(getInner(data))) return getInner(data)[index];
3571
- if (Array.isArray(data)) return data[index];
3572
- return extractKeys(data);
3573
- }));
3574
- });
3575
- if (schema.inner) schema.inner = schema.inner.i18n(mapValues(messages, (data) => {
3576
- if (getInner(data)) return getInner(data);
3577
- return extractKeys(data);
3578
- }));
3579
- if (schema.sKey) schema.sKey = schema.sKey.i18n(mapValues(messages, (data) => data?.$key));
3580
- return schema;
3581
- };
3582
- Schema.prototype.extra = function extra(key, value) {
3583
- const schema = Schema(this);
3584
- schema.meta = {
3585
- ...schema.meta,
3586
- [key]: value
3587
- };
3588
- return schema;
3589
- };
3590
- for (const key of [
3591
- "required",
3592
- "disabled",
3593
- "collapse",
3594
- "hidden",
3595
- "loose"
3596
- ]) Object.assign(Schema.prototype, { [key](value = true) {
3597
- const schema = Schema(this);
3598
- schema.meta = {
3599
- ...schema.meta,
3600
- [key]: value
3601
- };
3602
- return schema;
3603
- } });
3604
- Schema.prototype.deprecated = function deprecated() {
3605
- const schema = Schema(this);
3606
- schema.meta.badges ||= [];
3607
- schema.meta.badges.push({
3608
- text: "deprecated",
3609
- type: "danger"
3610
- });
3611
- return schema;
3612
- };
3613
- Schema.prototype.experimental = function experimental() {
3614
- const schema = Schema(this);
3615
- schema.meta.badges ||= [];
3616
- schema.meta.badges.push({
3617
- text: "experimental",
3618
- type: "warning"
3619
- });
3620
- return schema;
3621
- };
3622
- Schema.prototype.pattern = function pattern(regexp) {
3623
- const schema = Schema(this);
3624
- const pattern = pick(regexp, ["source", "flags"]);
3625
- schema.meta = {
3626
- ...schema.meta,
3627
- pattern
3628
- };
3629
- return schema;
3630
- };
3631
- Schema.prototype.simplify = function simplify(value) {
3632
- if (deepEqual(value, this.meta.default, this.type === "dict")) return null;
3633
- if (isNullable(value)) return value;
3634
- if (this.type === "object" || this.type === "dict") {
3635
- const result = {};
3636
- for (const key in value) {
3637
- const item = (this.type === "object" ? this.dict[key] : this.inner)?.simplify(value[key]);
3638
- if (this.type === "dict" || !isNullable(item)) result[key] = item;
3639
- }
3640
- if (deepEqual(result, this.meta.default, this.type === "dict")) return null;
3641
- return result;
3642
- } else if (this.type === "array" || this.type === "tuple") {
3643
- const result = [];
3644
- value.forEach((value, index) => {
3645
- const schema = this.type === "array" ? this.inner : this.list[index];
3646
- const item = schema ? schema.simplify(value) : value;
3647
- result.push(item);
3648
- });
3649
- return result;
3650
- } else if (this.type === "intersect") {
3651
- const result = {};
3652
- for (const item of this.list) Object.assign(result, item.simplify(value));
3653
- return result;
3654
- } else if (this.type === "union") for (const schema of this.list) try {
3655
- Schema.resolve(value, schema, {});
3656
- return schema.simplify(value);
3657
- } catch {}
3658
- return value;
3659
- };
3660
- Schema.prototype.toString = function toString(inline) {
3661
- return formatters[this.type]?.(this, inline) ?? `Schema<${this.type}>`;
3662
- };
3663
- Schema.prototype.role = function role(role, extra) {
3664
- const schema = Schema(this);
3665
- schema.meta = {
3666
- ...schema.meta,
3667
- role,
3668
- extra
3669
- };
3670
- return schema;
3671
- };
3672
- for (const key of [
3673
- "default",
3674
- "link",
3675
- "comment",
3676
- "description",
3677
- "max",
3678
- "min",
3679
- "step"
3680
- ]) Object.assign(Schema.prototype, { [key](value) {
3681
- const schema = Schema(this);
3682
- schema.meta = {
3683
- ...schema.meta,
3684
- [key]: value
3685
- };
3686
- return schema;
3687
- } });
3688
- const resolvers = {};
3689
- Schema.extend = function extend(type, resolve) {
3690
- resolvers[type] = resolve;
3691
- };
3692
- Schema.resolve = function resolve(data, schema, options = {}, strict = false) {
3693
- if (!schema) return [data];
3694
- if (options.ignore?.(data, schema)) return [data];
3695
- if (isNullable(data) && schema.type !== "lazy") {
3696
- if (schema.meta.required) throw new ValidationError(`missing required value`, options);
3697
- let current = schema;
3698
- let fallback = schema.meta.default;
3699
- while (current?.type === "intersect" && isNullable(fallback)) {
3700
- current = current.list[0];
3701
- fallback = current?.meta.default;
3702
- }
3703
- if (isNullable(fallback)) return [data];
3704
- data = clone(fallback);
3705
- }
3706
- const callback = resolvers[schema.type];
3707
- if (!callback) throw new ValidationError(`unsupported type "${schema.type}"`, options);
3708
- try {
3709
- return callback(data, schema, options, strict);
3710
- } catch (error) {
3711
- if (!schema.meta.loose) throw error;
3712
- return [schema.meta.default];
3713
- }
3714
- };
3715
- Schema.from = function from(source) {
3716
- if (isNullable(source)) return Schema.any();
3717
- else if ([
3718
- "string",
3719
- "number",
3720
- "boolean"
3721
- ].includes(typeof source)) return Schema.const(source).required();
3722
- else if (source[kSchema]) return source;
3723
- else if (typeof source === "function") switch (source) {
3724
- case String: return Schema.string().required();
3725
- case Number: return Schema.number().required();
3726
- case Boolean: return Schema.boolean().required();
3727
- case Function: return Schema.function().required();
3728
- default: return Schema.is(source).required();
3729
- }
3730
- else throw new TypeError(`cannot infer schema from ${source}`);
3731
- };
3732
- Schema.lazy = function lazy(builder) {
3733
- const toJSON = () => {
3734
- if (!schema.inner[kSchema]) {
3735
- schema.inner = schema.builder();
3736
- schema.inner.meta = {
3737
- ...schema.meta,
3738
- ...schema.inner.meta
3739
- };
3740
- }
3741
- return schema.inner.toJSON();
3742
- };
3743
- const schema = new Schema({
3744
- type: "lazy",
3745
- builder,
3746
- inner: { toJSON }
3747
- });
3748
- return schema;
3749
- };
3750
- Schema.natural = function natural() {
3751
- return Schema.number().step(1).min(0);
3752
- };
3753
- Schema.percent = function percent() {
3754
- return Schema.number().step(.01).min(0).max(1).role("slider");
3755
- };
3756
- Schema.date = function date() {
3757
- return Schema.union([Schema.is(Date), Schema.transform(Schema.string().role("datetime"), (value, options) => {
3758
- const date = new Date(value);
3759
- if (isNaN(+date)) throw new ValidationError(`invalid date "${value}"`, options);
3760
- return date;
3761
- }, true)]);
3762
- };
3763
- Schema.regExp = function regExp(flag = "") {
3764
- return Schema.union([Schema.is(RegExp), Schema.transform(Schema.string().role("regexp", { flag }), (value, options) => {
3765
- try {
3766
- return new RegExp(value, flag);
3767
- } catch (e) {
3768
- throw new ValidationError(e.message, options);
3769
- }
3770
- }, true)]);
3771
- };
3772
- Schema.arrayBuffer = function arrayBuffer(encoding) {
3773
- return Schema.union([
3774
- Schema.is(ArrayBuffer),
3775
- Schema.is(SharedArrayBuffer),
3776
- Schema.transform(Schema.any(), (value, options) => {
3777
- if (Binary.isSource(value)) return Binary.fromSource(value);
3778
- throw new ValidationError(`expected ArrayBufferSource but got ${value}`, options);
3779
- }, true),
3780
- ...encoding ? [Schema.transform(Schema.string(), (value, options) => {
3781
- try {
3782
- return encoding === "base64" ? Binary.fromBase64(value) : Binary.fromHex(value);
3783
- } catch (e) {
3784
- throw new ValidationError(e.message, options);
3785
- }
3786
- }, true)] : []
3787
- ]);
3788
- };
3789
- Schema.extend("lazy", (data, schema, options, strict) => {
3790
- if (!schema.inner[kSchema]) {
3791
- schema.inner = schema.builder();
3792
- schema.inner.meta = {
3793
- ...schema.meta,
3794
- ...schema.inner.meta
3795
- };
3796
- }
3797
- return Schema.resolve(data, schema.inner, options, strict);
3798
- });
3799
- Schema.extend("any", (data) => {
3800
- return [data];
3801
- });
3802
- Schema.extend("never", (data, _, options) => {
3803
- throw new ValidationError(`expected nullable but got ${data}`, options);
3804
- });
3805
- Schema.extend("const", (data, { value }, options) => {
3806
- if (deepEqual(data, value)) return [value];
3807
- throw new ValidationError(`expected ${value} but got ${data}`, options);
3808
- });
3809
- function checkWithinRange(data, meta, description, options, skipMin = false) {
3810
- const { max = Infinity, min = -Infinity } = meta;
3811
- if (data > max) throw new ValidationError(`expected ${description} <= ${max} but got ${data}`, options);
3812
- if (data < min && !skipMin) throw new ValidationError(`expected ${description} >= ${min} but got ${data}`, options);
3813
- }
3814
- Schema.extend("string", (data, { meta }, options) => {
3815
- if (typeof data !== "string") throw new ValidationError(`expected string but got ${data}`, options);
3816
- if (meta.pattern) {
3817
- const regexp = new RegExp(meta.pattern.source, meta.pattern.flags);
3818
- if (!regexp.test(data)) throw new ValidationError(`expect string to match regexp ${regexp}`, options);
3819
- }
3820
- checkWithinRange(data.length, meta, "string length", options);
3821
- return [data];
3822
- });
3823
- function decimalShift(data, digits) {
3824
- const str = data.toString();
3825
- if (str.includes("e")) return data * Math.pow(10, digits);
3826
- const index = str.indexOf(".");
3827
- if (index === -1) return data * Math.pow(10, digits);
3828
- const frac = str.slice(index + 1);
3829
- const integer = str.slice(0, index);
3830
- if (frac.length <= digits) return +(integer + frac.padEnd(digits, "0"));
3831
- return +(integer + frac.slice(0, digits) + "." + frac.slice(digits));
3832
- }
3833
- function isMultipleOf(data, min, step) {
3834
- step = Math.abs(step);
3835
- if (!/^\d+\.\d+$/.test(step.toString())) return (data - min) % step === 0;
3836
- const index = step.toString().indexOf(".");
3837
- const digits = step.toString().slice(index + 1).length;
3838
- return Math.abs(decimalShift(data, digits) - decimalShift(min, digits)) % decimalShift(step, digits) === 0;
3839
- }
3840
- Schema.extend("number", (data, { meta }, options) => {
3841
- if (typeof data !== "number") throw new ValidationError(`expected number but got ${data}`, options);
3842
- checkWithinRange(data, meta, "number", options);
3843
- const { step } = meta;
3844
- if (step && !isMultipleOf(data, meta.min ?? 0, step)) throw new ValidationError(`expected number multiple of ${step} but got ${data}`, options);
3845
- return [data];
3846
- });
3847
- Schema.extend("boolean", (data, _, options) => {
3848
- if (typeof data === "boolean") return [data];
3849
- throw new ValidationError(`expected boolean but got ${data}`, options);
3850
- });
3851
- Schema.extend("bitset", (data, { bits, meta }, options) => {
3852
- let value = 0, keys = [];
3853
- if (typeof data === "number") {
3854
- value = data;
3855
- for (const key in bits) if (data & bits[key]) keys.push(key);
3856
- } else if (Array.isArray(data)) {
3857
- keys = data;
3858
- for (const key of keys) {
3859
- if (typeof key !== "string") throw new ValidationError(`expected string but got ${key}`, options);
3860
- if (key in bits) value |= bits[key];
3861
- }
3862
- } else throw new ValidationError(`expected number or array but got ${data}`, options);
3863
- if (value === meta.default) return [value];
3864
- return [value, keys];
3865
- });
3866
- Schema.extend("function", (data, _, options) => {
3867
- if (typeof data === "function") return [data];
3868
- throw new ValidationError(`expected function but got ${data}`, options);
3869
- });
3870
- Schema.extend("is", (data, { constructor }, options) => {
3871
- if (typeof constructor === "function") {
3872
- if (data instanceof constructor) return [data];
3873
- throw new ValidationError(`expected ${constructor.name} but got ${data}`, options);
3874
- } else {
3875
- if (isNullable(data)) throw new ValidationError(`expected ${constructor} but got ${data}`, options);
3876
- let prototype = Object.getPrototypeOf(data);
3877
- while (prototype) {
3878
- if (prototype.constructor?.name === constructor) return [data];
3879
- prototype = Object.getPrototypeOf(prototype);
3880
- }
3881
- throw new ValidationError(`expected ${constructor} but got ${data}`, options);
3882
- }
3883
- });
3884
- function property(data, key, schema, options) {
3885
- try {
3886
- const [value, adapted] = Schema.resolve(data[key], schema, {
3887
- ...options,
3888
- path: [...options.path || [], key]
3889
- });
3890
- if (adapted !== void 0) data[key] = adapted;
3891
- return value;
3892
- } catch (e) {
3893
- if (!options?.autofix) throw e;
3894
- delete data[key];
3895
- return schema.meta.default;
3896
- }
3897
- }
3898
- Schema.extend("array", (data, { inner, meta }, options) => {
3899
- if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
3900
- checkWithinRange(data.length, meta, "array length", options, !isNullable(inner.meta.default));
3901
- return [data.map((_, index) => property(data, index, inner, options))];
3902
- });
3903
- Schema.extend("dict", (data, { inner, sKey }, options, strict) => {
3904
- if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
3905
- const result = {};
3906
- for (const key in data) {
3907
- let rKey;
3908
- try {
3909
- rKey = Schema.resolve(key, sKey, options)[0];
3910
- } catch (error) {
3911
- if (strict) continue;
3912
- throw error;
3913
- }
3914
- result[rKey] = property(data, key, inner, options);
3915
- data[rKey] = data[key];
3916
- if (key !== rKey) delete data[key];
3917
- }
3918
- return [result];
3919
- });
3920
- Schema.extend("tuple", (data, { list }, options, strict) => {
3921
- if (!Array.isArray(data)) throw new ValidationError(`expected array but got ${data}`, options);
3922
- const result = list.map((inner, index) => property(data, index, inner, options));
3923
- if (strict) return [result];
3924
- result.push(...data.slice(list.length));
3925
- return [result];
3926
- });
3927
- function merge(result, data) {
3928
- for (const key in data) {
3929
- if (key in result) continue;
3930
- result[key] = data[key];
3931
- }
3932
- }
3933
- Schema.extend("object", (data, { dict }, options, strict) => {
3934
- if (!isPlainObject(data)) throw new ValidationError(`expected object but got ${data}`, options);
3935
- const result = {};
3936
- for (const key in dict) {
3937
- const value = property(data, key, dict[key], options);
3938
- if (!isNullable(value) || key in data) result[key] = value;
3939
- }
3940
- if (!strict) merge(result, data);
3941
- return [result];
3942
- });
3943
- Schema.extend("union", (data, { list, toString }, options, strict) => {
3944
- const messages = [];
3945
- for (const inner of list) try {
3946
- return Schema.resolve(data, inner, options, strict);
3947
- } catch (error) {
3948
- messages.push(error);
3949
- }
3950
- throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
3951
- });
3952
- Schema.extend("intersect", (data, { list, toString }, options, strict) => {
3953
- if (!list.length) return [data];
3954
- let result;
3955
- for (const inner of list) {
3956
- const value = Schema.resolve(data, inner, options, true)[0];
3957
- if (isNullable(value)) continue;
3958
- if (isNullable(result)) result = value;
3959
- else if (typeof result !== typeof value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
3960
- else if (typeof value === "object") merge(result ??= {}, value);
3961
- else if (result !== value) throw new ValidationError(`expected ${toString()} but got ${JSON.stringify(data)}`, options);
3962
- }
3963
- if (!strict && isPlainObject(data)) merge(result, data);
3964
- return [result];
3965
- });
3966
- Schema.extend("transform", (data, { inner, callback, preserve }, options) => {
3967
- const [result, adapted = data] = Schema.resolve(data, inner, options, true);
3968
- if (preserve) return [callback(result)];
3969
- else return [callback(result), callback(adapted)];
3970
- });
3971
- const formatters = {};
3972
- function defineMethod(name, keys, format) {
3973
- formatters[name] = format;
3974
- Object.assign(Schema, { [name](...args) {
3975
- const schema = new Schema({ type: name });
3976
- keys.forEach((key, index) => {
3977
- switch (key) {
3978
- case "sKey":
3979
- schema.sKey = args[index] ?? Schema.string();
3980
- break;
3981
- case "inner":
3982
- schema.inner = Schema.from(args[index]);
3983
- break;
3984
- case "list":
3985
- schema.list = args[index].map(Schema.from);
3986
- break;
3987
- case "dict":
3988
- schema.dict = mapValues(args[index], Schema.from);
3989
- break;
3990
- case "bits":
3991
- schema.bits = {};
3992
- for (const key in args[index]) {
3993
- if (typeof args[index][key] !== "number") continue;
3994
- schema.bits[key] = args[index][key];
3995
- }
3996
- break;
3997
- case "callback": {
3998
- const callback = schema.callback = args[index];
3999
- callback["toJSON"] ||= () => callback.toString();
4000
- break;
4001
- }
4002
- case "constructor": {
4003
- const constructor = schema.constructor = args[index];
4004
- if (typeof constructor === "function") constructor["toJSON"] ||= () => constructor["name"];
4005
- break;
4006
- }
4007
- default: schema[key] = args[index];
4008
- }
4009
- });
4010
- if (name === "object" || name === "dict") schema.meta.default = {};
4011
- else if (name === "array" || name === "tuple") schema.meta.default = [];
4012
- else if (name === "bitset") schema.meta.default = 0;
4013
- return schema;
4014
- } });
4015
- }
4016
- defineMethod("is", ["constructor"], ({ constructor }) => {
4017
- if (typeof constructor === "function") return constructor.name;
4018
- else return constructor;
4019
- });
4020
- defineMethod("any", [], () => "any");
4021
- defineMethod("never", [], () => "never");
4022
- defineMethod("const", ["value"], ({ value }) => typeof value === "string" ? JSON.stringify(value) : value);
4023
- defineMethod("string", [], () => "string");
4024
- defineMethod("number", [], () => "number");
4025
- defineMethod("boolean", [], () => "boolean");
4026
- defineMethod("bitset", ["bits"], () => "bitset");
4027
- defineMethod("function", [], () => "function");
4028
- defineMethod("array", ["inner"], ({ inner }) => `${inner.toString(true)}[]`);
4029
- defineMethod("dict", ["inner", "sKey"], ({ inner, sKey }) => `{ [key: ${sKey.toString()}]: ${inner.toString()} }`);
4030
- defineMethod("tuple", ["list"], ({ list }) => `[${list.map((inner) => inner.toString()).join(", ")}]`);
4031
- defineMethod("object", ["dict"], ({ dict }) => {
4032
- if (Object.keys(dict).length === 0) return "{}";
4033
- return `{ ${Object.entries(dict).map(([key, inner]) => {
4034
- return `${key}${inner.meta.required ? "" : "?"}: ${inner.toString()}`;
4035
- }).join(", ")} }`;
4036
- });
4037
- defineMethod("union", ["list"], ({ list }, inline) => {
4038
- const result = list.map(({ toString: format }) => format()).join(" | ");
4039
- return inline ? `(${result})` : result;
4040
- });
4041
- defineMethod("intersect", ["list"], ({ list }) => {
4042
- return `${list.map((inner) => inner.toString(true)).join(" & ")}`;
4043
- });
4044
- defineMethod("transform", [
4045
- "inner",
4046
- "callback",
4047
- "preserve"
4048
- ], ({ inner }, isInner) => inner.toString(isInner));
4049
- //#endregion
4050
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-timeout@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-timeout/lib/index.js
3322
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-timeout@0.1.7-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-timeout/lib/index.js
4051
3323
  /** Largest delay Node schedules without clamping it to one millisecond. */
4052
3324
  const MAX_TIMER_DELAY_MS = 2147483647;
4053
3325
  //#endregion
4054
- //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-llm@0.1.5-rc.1_@deepseek-ai+cordis@4.0.2/node_modules/@deepseek-ai/dsh-llm/lib/index.js
3326
+ //#region ../../node_modules/.pnpm/@deepseek-ai+dsh-llm@0.1.7-rc.1_@deepseek-ai+cordis@4.0.4/node_modules/@deepseek-ai/dsh-llm/lib/index.js
4055
3327
  /**
4056
3328
  * Detach and deep-freeze a message whose identity already exists.
4057
3329
  * @param message - complete message, including its stable identity.
@@ -4066,10 +3338,10 @@ function freezeMessage(message) {
4066
3338
  * @returns an immutable message with a fresh stable identity.
4067
3339
  */
4068
3340
  function createMessage(input) {
4069
- return freezeMessage({
3341
+ return deepFreeze(structuredClone({
4070
3342
  ...input,
4071
3343
  id: brandString(randomUUID())
4072
- });
3344
+ }));
4073
3345
  }
4074
3346
  /**
4075
3347
  * Create one identified user-role message and freeze it before publication.
@@ -4134,22 +3406,22 @@ const DEFAULT_RETRYABLE_CODES = Object.freeze([
4134
3406
  "TIMEOUT",
4135
3407
  "TRANSPORT"
4136
3408
  ]);
4137
- const backoffSchema = Schema.object({
4138
- initialDelayMs: Schema.number().max(MAX_TIMER_DELAY_MS).default(DEFAULT_INITIAL_DELAY_MS),
4139
- maxDelayMs: Schema.number().max(MAX_TIMER_DELAY_MS).default(DEFAULT_MAX_DELAY_MS),
4140
- jitterRatio: Schema.number().min(0).max(1).default(DEFAULT_JITTER_RATIO)
3409
+ const backoffSchema = z.object({
3410
+ initialDelayMs: z.number().max(MAX_TIMER_DELAY_MS).default(DEFAULT_INITIAL_DELAY_MS),
3411
+ maxDelayMs: z.number().max(MAX_TIMER_DELAY_MS).default(DEFAULT_MAX_DELAY_MS),
3412
+ jitterRatio: z.number().min(0).max(1).default(DEFAULT_JITTER_RATIO)
4141
3413
  });
4142
- const normalPolicySchema = Schema.object({
4143
- mode: Schema.const("normal").required(),
4144
- maxRetries: Schema.number().step(1).min(0).max(Number.MAX_SAFE_INTEGER).default(DEFAULT_MAX_RETRIES),
4145
- retryableCodes: Schema.array(Schema.string()).default([...DEFAULT_RETRYABLE_CODES]),
3414
+ const normalPolicySchema = z.object({
3415
+ mode: z.const("normal").required(),
3416
+ maxRetries: z.number().step(1).min(0).max(Number.MAX_SAFE_INTEGER).default(DEFAULT_MAX_RETRIES),
3417
+ retryableCodes: z.array(z.string()).default([...DEFAULT_RETRYABLE_CODES]),
4146
3418
  backoff: backoffSchema
4147
3419
  });
4148
- const alwaysPolicySchema = Schema.object({
4149
- mode: Schema.const("always").required(),
3420
+ const alwaysPolicySchema = z.object({
3421
+ mode: z.const("always").required(),
4150
3422
  backoff: backoffSchema
4151
3423
  });
4152
- Schema.union([normalPolicySchema, alwaysPolicySchema]);
3424
+ z.union([normalPolicySchema, alwaysPolicySchema]);
4153
3425
  const NORMAL_POLICY_KEYS = /* @__PURE__ */ new Set([
4154
3426
  "mode",
4155
3427
  "maxRetries",
@@ -4293,13 +3565,15 @@ function failureSnapshot(value) {
4293
3565
  const status = candidate.status;
4294
3566
  const providerRetryAfterMs = candidate.providerRetryAfterMs;
4295
3567
  const requestId = candidate.requestId;
4296
- if (typeof message !== "string" || message.length === 0 || typeof code !== "string" || code.length === 0 || status !== void 0 && (!Number.isInteger(status) || status < 100 || status > 599) || providerRetryAfterMs !== void 0 && (!Number.isFinite(providerRetryAfterMs) || providerRetryAfterMs <= 0) || requestId !== void 0 && (typeof requestId !== "string" || requestId.length === 0)) return void 0;
3568
+ const offloadImages = candidate.offloadImages;
3569
+ if (typeof message !== "string" || message.length === 0 || typeof code !== "string" || code.length === 0 || status !== void 0 && (!Number.isInteger(status) || status < 100 || status > 599) || providerRetryAfterMs !== void 0 && (!Number.isFinite(providerRetryAfterMs) || providerRetryAfterMs <= 0) || requestId !== void 0 && (typeof requestId !== "string" || requestId.length === 0) || offloadImages !== void 0 && (!Number.isSafeInteger(offloadImages) || offloadImages <= 0)) return void 0;
4297
3570
  return Object.freeze({
4298
3571
  message,
4299
3572
  code,
4300
3573
  ...status === void 0 ? {} : { status },
4301
3574
  ...providerRetryAfterMs === void 0 ? {} : { providerRetryAfterMs },
4302
- ...requestId === void 0 ? {} : { requestId }
3575
+ ...requestId === void 0 ? {} : { requestId },
3576
+ ...offloadImages === void 0 ? {} : { offloadImages }
4303
3577
  });
4304
3578
  } catch (_sdkFailureGetter) {
4305
3579
  return;
@@ -4329,25 +3603,23 @@ function textOnlyImageText(ref) {
4329
3603
  return `[image omitted because this model accepts text only; attachment sha256:${String(ref.attachmentId).slice(7, 15)}]`;
4330
3604
  }
4331
3605
  /**
4332
- * True when typed model content contains an image block, walking nested
4333
- * tool-result content. This is the one recursive image walk shared by every
4334
- * image policy (capability gating, text-only serialization, compaction
4335
- * survey), so a consumer cannot silently diverge on nesting depth.
3606
+ * True when typed model content contains an image block. This is the one image
3607
+ * walk shared by every image policy (capability gating, text-only
3608
+ * serialization, compaction survey), so a consumer cannot silently diverge.
4336
3609
  * @param content - typed model content blocks.
4337
- * @returns whether any nested block is an image.
3610
+ * @returns whether any block is an image.
4338
3611
  */
4339
3612
  function contentHasImage(content) {
4340
- return content.some((block) => block.type === "image" || block.type === "tool-result" && contentHasImage(block.content));
3613
+ return content.some((block) => block.type === "image");
4341
3614
  }
4342
3615
  /**
4343
- * True when typed model content contains a file block, walking nested
4344
- * tool-result content on the same recursion every file policy shares.
3616
+ * True when typed model content contains a file block.
4345
3617
  * Reads current content on every call without retaining scan results.
4346
3618
  * @param content - typed model content blocks.
4347
- * @returns whether any nested block is a file.
3619
+ * @returns whether any block is a file.
4348
3620
  */
4349
3621
  function contentHasFile(content) {
4350
- for (const block of content) if (block.type === "file" || block.type === "tool-result" && contentHasFile(block.content)) return true;
3622
+ for (const block of content) if (block.type === "file") return true;
4351
3623
  return false;
4352
3624
  }
4353
3625
  /**
@@ -4364,7 +3636,7 @@ function fileHandleText(ref, readonlyPath) {
4364
3636
  if (readonlyPath === void 0) return `[${identity} was uploaded, but the current execution environment cannot access a readable path. Report that limitation if its contents are needed; do not claim to have read it.]`;
4365
3637
  return `[${identity}: verbatim read-only copy saved at ${quoted(readonlyPath)}. Read that path with your file tools when its contents are needed; copy it to a writable location before modifying it. When delegating file work, include this saved path in the delegation prompt; only subagents sharing this execution environment can read it.]`;
4366
3638
  }
4367
- /** Replace every file occurrence, including nested tool results, with handle text. */
3639
+ /** Replace every file occurrence with handle text. */
4368
3640
  function replaceFilesWithHandles(blocks, resolvePath) {
4369
3641
  let next;
4370
3642
  for (const [index, block] of blocks.entries()) {
@@ -4376,29 +3648,10 @@ function replaceFilesWithHandles(blocks, resolvePath) {
4376
3648
  });
4377
3649
  continue;
4378
3650
  }
4379
- if (block.type === "tool-result") {
4380
- const content = replaceFilesWithHandles(block.content, resolvePath);
4381
- if (content !== block.content) {
4382
- next ??= blocks.slice(0, index);
4383
- next.push({
4384
- ...block,
4385
- content
4386
- });
4387
- continue;
4388
- }
4389
- }
4390
3651
  next?.push(block);
4391
3652
  }
4392
3653
  return next ?? blocks;
4393
3654
  }
4394
- /**
4395
- * Project durable file history into deterministic handle text for every model
4396
- * route. Unlike images, no provider receives file blocks natively, so this
4397
- * projection is unconditional in request assembly.
4398
- * @param messages - complete request history.
4399
- * @param resolvePath - resolve one reference's current execution-world read path.
4400
- * @returns the original list without files, otherwise shallow message copies with handle text.
4401
- */
4402
3655
  function projectFilesToText(messages, resolvePath) {
4403
3656
  if (!messages.some((message) => contentHasFile(message.content))) return messages;
4404
3657
  return messages.map((message) => {
@@ -4409,7 +3662,7 @@ function projectFilesToText(messages, resolvePath) {
4409
3662
  };
4410
3663
  });
4411
3664
  }
4412
- /** Replace every image occurrence, including nested tool results, for a text-only model. */
3665
+ /** Replace every image occurrence for a text-only model. */
4413
3666
  function replaceImagesForTextModel(blocks) {
4414
3667
  let next;
4415
3668
  for (const [index, block] of blocks.entries()) {
@@ -4421,26 +3674,10 @@ function replaceImagesForTextModel(blocks) {
4421
3674
  });
4422
3675
  continue;
4423
3676
  }
4424
- if (block.type === "tool-result") {
4425
- const content = replaceImagesForTextModel(block.content);
4426
- if (content !== block.content) {
4427
- next ??= blocks.slice(0, index);
4428
- next.push({
4429
- ...block,
4430
- content
4431
- });
4432
- continue;
4433
- }
4434
- }
4435
3677
  next?.push(block);
4436
3678
  }
4437
3679
  return next ?? blocks;
4438
3680
  }
4439
- /**
4440
- * Project durable image history into deterministic text for an exact text-only model.
4441
- * @param messages - complete request history.
4442
- * @returns the original list without images, otherwise shallow message copies with stable placeholders.
4443
- */
4444
3681
  function projectImagesForTextModel(messages) {
4445
3682
  if (!messages.some((message) => contentHasImage(message.content))) return messages;
4446
3683
  return messages.map((message) => {
@@ -4530,7 +3767,8 @@ var LlmError = class extends HarnessError {
4530
3767
  code,
4531
3768
  ...options?.status === void 0 ? {} : { status: options.status },
4532
3769
  ...options?.providerRetryAfterMs === void 0 ? {} : { providerRetryAfterMs: options.providerRetryAfterMs },
4533
- ...options?.requestId === void 0 ? {} : { requestId: options.requestId }
3770
+ ...options?.requestId === void 0 ? {} : { requestId: options.requestId },
3771
+ ...options?.offloadImages === void 0 ? {} : { offloadImages: options.offloadImages }
4534
3772
  });
4535
3773
  }
4536
3774
  };
@@ -4798,7 +4036,8 @@ var LlmError = class extends HarnessError {
4798
4036
  id: model.id,
4799
4037
  ...model.name === void 0 ? {} : { name: model.name },
4800
4038
  ...model.contextWindow === void 0 ? {} : { contextWindow: model.contextWindow },
4801
- ...model.maxTokens === void 0 ? {} : { maxTokens: model.maxTokens }
4039
+ ...model.maxTokens === void 0 ? {} : { maxTokens: model.maxTokens },
4040
+ ...model.inputModalities === void 0 ? {} : { inputModalities: [...model.inputModalities] }
4802
4041
  });
4803
4042
  }
4804
4043
  return models;
@@ -5027,8 +4266,9 @@ var LlmError = class extends HarnessError {
5027
4266
  /** Remove replay state whose historical route is owned by another adapter. */
5028
4267
  forAdapter(options, adapter) {
5029
4268
  const messages = options.messages.map((message) => {
4269
+ if (message.role !== "assistant") return message;
5030
4270
  const source = message.source;
5031
- if (message.role !== "assistant" || source.kind !== "model" || source.replayState === void 0) return message;
4271
+ if (source.replayState === void 0) return message;
5032
4272
  if (this.adapters.get(source.provider)?.adapter === adapter) return message;
5033
4273
  return freezeMessage({
5034
4274
  ...message,
@@ -5684,19 +4924,35 @@ const inject = [
5684
4924
  /** Model-facing announcement: plugin presence, capabilities, and limits. */
5685
4925
  const TASK_BOARD_GUIDANCE = "本机已安装 dsh-task-board 插件(DSH Web GUI 的任务看板):侧边栏「任务看板」入口;在 dsh-web 插件全家桶仓库(packages/dsh-task-board)统一维护,经聚合包 web-ui-all 一键安装。能力:多列看板管理任务;Host 权威账本;关闭浏览器后仍由 Host 执行和结算;任务可钉住工作区、agent 预设和权限;支持 Host 本地时区的 5 段 cron,错过的触发点不补跑;可选且默认关闭的空闲系统睡眠保护允许屏幕熄灭,但不承诺拦截合盖、手动睡眠、休眠、关机或唤醒已睡眠机器。执行消耗 API 额度。用户提到「任务看板 / 看板 / 定时任务」时即指本插件,请据此协作。若你同时用 todo_write 维护会话顶部的可见计划列表,最终回复前必须再次调用 todo_write 收尾:没有剩余工作时不要保留 in_progress,已完成的最后一步要标为 completed。";
5686
4926
  /**
5687
- * Settings namespace of the board's announcement capability — the section the
5688
- * web settings surface edits. Spelled here rather than imported: the browser
5689
- * half spells the same value and must not depend on a Host package.
4927
+ * The schema is left to inference rather than annotated with `z<Config>`: a
4928
+ * volatile field's parsed output is a `Volatile` reference while its accepted
4929
+ * input stays the plain value, so the two sides no longer share one shape and
4930
+ * the annotation would reject the schema the Host must be given.
5690
4931
  */
5691
- const TASK_BOARD_SETTINGS_NAMESPACE = "task-board";
5692
4932
  const Config = z.object({
5693
- announceToAgent: z.boolean().default(false),
5694
- enabled: z.boolean().default(true),
5695
- preventIdleSleep: z.boolean().default(false),
4933
+ announceToAgent: z.boolean().default(false).volatile(),
4934
+ enabled: z.boolean().default(true).volatile(),
4935
+ preventIdleSleep: z.boolean().default(false).volatile(),
5696
4936
  trustedProxyHosts: z.array(z.string()).default([]),
5697
4937
  proxyTokenEnv: z.string().min(1).default(DEFAULT_PROXY_TOKEN_ENV),
5698
4938
  sessionDefaultPermission: z.union(TASK_PERMISSIONS).default(DEFAULT_SESSION_PERMISSION)
5699
4939
  });
4940
+ /**
4941
+ * Read one config field's current value.
4942
+ *
4943
+ * The Loader hands schema-volatile fields as stable references it commits in
4944
+ * place, so a live value must be read at use time rather than captured when
4945
+ * the plugin activates; a plain value (a programmatic mount, or a field the
4946
+ * schema does not mark volatile) is returned as it stands.
4947
+ * @param field - the config field as the Loader handed it.
4948
+ * @param fallback - value to use when the field is absent.
4949
+ * @returns the effective field value.
4950
+ */
4951
+ function readConfigField(field, fallback) {
4952
+ if (field === void 0) return fallback;
4953
+ if (typeof field === "object" && field !== null && typeof field.get === "function") return field.get();
4954
+ return field;
4955
+ }
5700
4956
  /** Resolve proxy access without ever placing the token value in plugin config. */
5701
4957
  function resolveProxyAccess(config, env = process.env) {
5702
4958
  const trustedProxyHosts = config?.trustedProxyHosts ?? [];
@@ -5728,15 +4984,26 @@ function resolveLlmRuntime(ctx) {
5728
4984
  }
5729
4985
  }
5730
4986
  /**
5731
- * Register the board's announcement section, gated on the composition entry's
5732
- * `announceToAgent` (and the live settings value once the web settings
5733
- * surface is served). The section is re-registered whenever the source
5734
- * changes, so a settings edit takes effect without a restart.
4987
+ * Activate the board's host half: ledger, routes, cron scheduler, power
4988
+ * inhibitor, and the model-facing announcement.
4989
+ *
4990
+ * The effective settings are the config the Host hands this row. The three
4991
+ * fields the browser card edits are schema-volatile, so the Loader commits an
4992
+ * edit into the running fiber's references instead of remounting the row —
4993
+ * `sync` therefore reads them at use time and follows
4994
+ * `loader/volatile-update`, the event the Loader emits once it has committed
4995
+ * them. Every other field reloads the row, which re-runs this activation.
5735
4996
  * @param ctx - the plugin context (systemPrompt injected).
5736
4997
  * @param config - resolved plugin config (schema defaults applied by the loader).
5737
4998
  */
5738
4999
  const apply = mountOnce("@linxin666/dsh-client-ui-task-board", applyImpl);
5739
5000
  function applyImpl(ctx, config) {
5001
+ /** Current master switch (the browser half reads the same field from its own form). */
5002
+ const enabled = () => readConfigField(config?.enabled, true);
5003
+ /** Current announcement flag. */
5004
+ const announceToAgent = () => readConfigField(config?.announceToAgent, DEFAULT_ANNOUNCE);
5005
+ /** Current idle-sleep protection flag. */
5006
+ const preventIdleSleep = () => readConfigField(config?.preventIdleSleep, false);
5740
5007
  const host = new TaskBoardHostService(ctx.typertGateway, {
5741
5008
  workspaceRegistry: ctx.workspaceRegistry,
5742
5009
  sessionDefaultPermission: config?.sessionDefaultPermission ?? "read-only",
@@ -5746,7 +5013,7 @@ function applyImpl(ctx, config) {
5746
5013
  return (await ctx.commands.execute(agent, line, [], signal))?.result;
5747
5014
  } }
5748
5015
  });
5749
- host.setConfiguration(config?.enabled ?? true, config?.preventIdleSleep ?? false);
5016
+ host.setConfiguration(enabled(), preventIdleSleep());
5750
5017
  host.start();
5751
5018
  ctx.effect(() => {
5752
5019
  const disposers = [];
@@ -5767,41 +5034,32 @@ function applyImpl(ctx, config) {
5767
5034
  host.dispose();
5768
5035
  };
5769
5036
  }, "task-board: host ledger, scheduler, and routes");
5770
- let current = () => config ?? {};
5771
5037
  let disposeSection;
5038
+ let applied;
5772
5039
  const sync = () => {
5040
+ const next = {
5041
+ enabled: enabled(),
5042
+ announceToAgent: announceToAgent(),
5043
+ preventIdleSleep: preventIdleSleep()
5044
+ };
5045
+ if (applied !== void 0 && applied.enabled === next.enabled && applied.announceToAgent === next.announceToAgent && applied.preventIdleSleep === next.preventIdleSleep) return;
5046
+ applied = next;
5047
+ host.setConfiguration(next.enabled, next.preventIdleSleep);
5773
5048
  if (disposeSection !== void 0) {
5774
5049
  disposeSection();
5775
5050
  disposeSection = void 0;
5776
5051
  }
5777
- const active = current().enabled ?? true;
5778
- host.setConfiguration(active, current().preventIdleSleep ?? false);
5779
- if (!active) return;
5780
- if ((current().announceToAgent ?? DEFAULT_ANNOUNCE) === false) return;
5052
+ if (!next.enabled || !next.announceToAgent) return;
5781
5053
  disposeSection = ctx.systemPrompt.section({
5782
5054
  name: "plugin:task-board",
5783
5055
  order: SECTION_ORDER,
5784
5056
  text: TASK_BOARD_GUIDANCE
5785
5057
  });
5786
5058
  };
5787
- ctx.inject(["settings"], (settingsCtx) => {
5788
- try {
5789
- if (typeof settingsCtx.settings?.installSection === "function") settingsCtx.settings.installSection(ctx, TASK_BOARD_SETTINGS_NAMESPACE, Config, config ?? {}, {
5790
- setSource: (source) => {
5791
- current = source;
5792
- },
5793
- onChange: sync
5794
- });
5795
- else if (typeof settingsCtx.settings?.register === "function") {
5796
- const scope = settingsCtx.settings.register(TASK_BOARD_SETTINGS_NAMESPACE, Config, { base: config ?? {} });
5797
- current = () => scope?.get?.() ?? config ?? {};
5798
- scope?.watch?.(() => {
5799
- sync();
5800
- });
5801
- }
5802
- } catch {}
5059
+ ctx.on("loader/volatile-update", () => {
5060
+ sync();
5803
5061
  });
5804
5062
  sync();
5805
5063
  }
5806
5064
  //#endregion
5807
- export { Config, DEFAULT_PROXY_TOKEN_ENV, TASK_BOARD_GUIDANCE, TASK_BOARD_SETTINGS_NAMESPACE, apply, inject, resolveLlmRuntime, resolveProxyAccess };
5065
+ export { Config, DEFAULT_PROXY_TOKEN_ENV, TASK_BOARD_GUIDANCE, apply, inject, readConfigField, resolveLlmRuntime, resolveProxyAccess };