@vidge/dsh-agent-hub 0.1.0-rc1

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 (56) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +133 -0
  3. package/README.zh.md +115 -0
  4. package/cordis.patch.yml +22 -0
  5. package/lib/client.js +1494 -0
  6. package/lib/index.js +5045 -0
  7. package/lib/invariant.js +96 -0
  8. package/lib/types/client/LoopEngineComposerSelect.d.ts +73 -0
  9. package/lib/types/client/LoopEngineSection.d.ts +43 -0
  10. package/lib/types/client/engine-rpc.d.ts +74 -0
  11. package/lib/types/client/index.d.ts +28 -0
  12. package/lib/types/client/locales.d.ts +44 -0
  13. package/lib/types/client/session-location.d.ts +63 -0
  14. package/lib/types/client/store.d.ts +58 -0
  15. package/lib/types/commands.d.ts +69 -0
  16. package/lib/types/driver-core/context-files.d.ts +62 -0
  17. package/lib/types/driver-core/ownership.d.ts +40 -0
  18. package/lib/types/driver-core/permission-knobs.d.ts +26 -0
  19. package/lib/types/driver-core/prompt.d.ts +23 -0
  20. package/lib/types/driver-core/skill-inject.d.ts +59 -0
  21. package/lib/types/engine-claude/agent.d.ts +116 -0
  22. package/lib/types/engine-claude/loop.d.ts +99 -0
  23. package/lib/types/engine-claude/mapping.d.ts +84 -0
  24. package/lib/types/engine-claude/permission.d.ts +41 -0
  25. package/lib/types/engine-claude/process.d.ts +59 -0
  26. package/lib/types/engine-claude/provider-env.d.ts +50 -0
  27. package/lib/types/engine-claude/sdk.d.ts +101 -0
  28. package/lib/types/engine-claude/types.d.ts +28 -0
  29. package/lib/types/engine-codex/agent.d.ts +109 -0
  30. package/lib/types/engine-codex/appserver/client.d.ts +49 -0
  31. package/lib/types/engine-codex/appserver/mapping.d.ts +67 -0
  32. package/lib/types/engine-codex/appserver/thread.d.ts +66 -0
  33. package/lib/types/engine-codex/appserver/types.d.ts +215 -0
  34. package/lib/types/engine-codex/loop.d.ts +92 -0
  35. package/lib/types/engine-codex/permission.d.ts +32 -0
  36. package/lib/types/engine-codex/skills.d.ts +29 -0
  37. package/lib/types/engine-codex/types.d.ts +19 -0
  38. package/lib/types/engine-pi/agent.d.ts +125 -0
  39. package/lib/types/engine-pi/loop.d.ts +96 -0
  40. package/lib/types/engine-pi/permission.d.ts +43 -0
  41. package/lib/types/engine-pi/rpc/client.d.ts +105 -0
  42. package/lib/types/engine-pi/rpc/mapping.d.ts +37 -0
  43. package/lib/types/engine-pi/rpc/types.d.ts +235 -0
  44. package/lib/types/engine-pi/skills.d.ts +55 -0
  45. package/lib/types/engine-pi/types.d.ts +27 -0
  46. package/lib/types/engine-record.d.ts +124 -0
  47. package/lib/types/index.d.ts +138 -0
  48. package/lib/types/invariant.d.ts +23 -0
  49. package/lib/types/llm-compat.d.ts +32 -0
  50. package/lib/types/namespace.d.ts +19 -0
  51. package/lib/types/patch-manager.d.ts +78 -0
  52. package/lib/types/router.d.ts +189 -0
  53. package/lib/types/rpc.d.ts +113 -0
  54. package/lib/types/settings.d.ts +29 -0
  55. package/lib/types/skills.d.ts +93 -0
  56. package/package.json +107 -0
package/lib/client.js ADDED
@@ -0,0 +1,1494 @@
1
+ var module = { exports: {} }; var exports = module.exports; window.__ModuleLoader__.load({ id: "@vidge/dsh-agent-hub", factory: (require) => {
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/client/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ apply: () => apply,
24
+ inject: () => inject
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/client/LoopEngineSection.tsx
29
+ var import_react = require("react");
30
+ var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
31
+ var import_jsx_runtime = require("react/jsx-runtime");
32
+ var ENGINE_OPTIONS = [
33
+ { value: "in-process", key: "engineInProcess" },
34
+ { value: "claude-code", key: "engineClaudeCode" },
35
+ { value: "codex", key: "engineCodex" },
36
+ { value: "pi", key: "enginePi" }
37
+ ];
38
+ function engineLabelKey(engine) {
39
+ switch (engine) {
40
+ case "claude-code":
41
+ return "engineClaudeCode";
42
+ case "codex":
43
+ return "engineCodex";
44
+ case "pi":
45
+ return "enginePi";
46
+ default:
47
+ return "engineInProcess";
48
+ }
49
+ }
50
+ var shell = {
51
+ display: "flex",
52
+ flexDirection: "column",
53
+ gap: 12,
54
+ maxWidth: 720,
55
+ color: "var(--dsw-alias-label-primary)"
56
+ };
57
+ var titleStyle = {
58
+ margin: 0,
59
+ fontSize: 18,
60
+ fontWeight: 600
61
+ };
62
+ var intro = {
63
+ margin: 0,
64
+ fontSize: 13,
65
+ color: "var(--dsw-alias-label-tertiary)"
66
+ };
67
+ var trigger = {
68
+ appearance: "none",
69
+ boxSizing: "border-box",
70
+ display: "inline-flex",
71
+ alignItems: "center",
72
+ gap: 8,
73
+ width: "fit-content",
74
+ minWidth: 200,
75
+ padding: "9px 12px",
76
+ border: "1px solid var(--dsw-alias-border-l2)",
77
+ borderRadius: 10,
78
+ background: "var(--dsw-alias-bg-layer-1)",
79
+ color: "var(--dsw-alias-label-primary)",
80
+ font: "inherit",
81
+ fontSize: 13,
82
+ cursor: "pointer"
83
+ };
84
+ var triggerDisabled = { ...trigger, opacity: 0.5, cursor: "default" };
85
+ var notice = {
86
+ margin: 0,
87
+ fontSize: 12,
88
+ color: "var(--dsw-alias-label-secondary)"
89
+ };
90
+ var error = {
91
+ margin: 0,
92
+ fontSize: 13,
93
+ color: "var(--dsw-alias-state-error-primary)"
94
+ };
95
+ var toggleRow = {
96
+ display: "flex",
97
+ alignItems: "center",
98
+ gap: 8,
99
+ fontSize: 13,
100
+ color: "var(--dsw-alias-label-primary)",
101
+ cursor: "pointer"
102
+ };
103
+ var toggleCheckbox = {
104
+ width: 16,
105
+ height: 16,
106
+ accentColor: "var(--dsw-alias-brand-primary, var(--dsw-alias-label-primary))",
107
+ cursor: "pointer"
108
+ };
109
+ function LoopEngineSection(props) {
110
+ const { controller, useSnapshot, t } = props;
111
+ const { status, engine, showInComposer, writable } = useSnapshot((snapshot) => snapshot);
112
+ const [open, setOpen] = (0, import_react.useState)(false);
113
+ const navId = (0, import_react.useId)();
114
+ const triggerRef = (0, import_react.useRef)(null);
115
+ if (status === "unavailable") {
116
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { "aria-labelledby": navId, style: shell, children: [
117
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { id: navId, style: titleStyle, children: t("nav") }),
118
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: intro, children: t("description") }),
119
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { role: "alert", style: error, children: t("unavailable") })
120
+ ] });
121
+ }
122
+ const disabled = status === "saving" || !writable;
123
+ const label = t(engineLabelKey(engine));
124
+ const onSelect = (next) => {
125
+ setOpen(false);
126
+ const value = next;
127
+ if (value === engine) return;
128
+ void controller.setEngine(value);
129
+ };
130
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { "aria-labelledby": navId, style: shell, children: [
131
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { id: navId, style: titleStyle, children: t("nav") }),
132
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: intro, children: t("description") }),
133
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
134
+ import_dsh_client_ui_primitives.Menu,
135
+ {
136
+ open,
137
+ onClose: () => {
138
+ setOpen(false);
139
+ },
140
+ items: ENGINE_OPTIONS.map((option) => ({ id: option.value, label: t(option.key) })),
141
+ selectedId: engine,
142
+ onSelect,
143
+ align: "start",
144
+ portal: true,
145
+ getAnchorRect: () => triggerRef.current?.getBoundingClientRect() ?? null,
146
+ anchor: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
147
+ "button",
148
+ {
149
+ type: "button",
150
+ ref: triggerRef,
151
+ "aria-haspopup": "menu",
152
+ "aria-expanded": open,
153
+ disabled,
154
+ style: disabled ? triggerDisabled : trigger,
155
+ onClick: () => {
156
+ setOpen(!open);
157
+ },
158
+ children: [
159
+ label,
160
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
161
+ ]
162
+ }
163
+ )
164
+ }
165
+ ),
166
+ status === "saving" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: notice, children: t("saving") }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: notice, children: t("switchNotice") }),
167
+ engine === "claude-code" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: notice, children: t("claudeModelNotice") }) : null,
168
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: toggleRow, children: [
169
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
170
+ "input",
171
+ {
172
+ type: "checkbox",
173
+ checked: showInComposer,
174
+ disabled,
175
+ style: toggleCheckbox,
176
+ onChange: (event) => {
177
+ void controller.setShowInComposer(event.currentTarget.checked);
178
+ }
179
+ }
180
+ ),
181
+ t("showInComposerLabel")
182
+ ] })
183
+ ] });
184
+ }
185
+
186
+ // src/client/LoopEngineComposerSelect.tsx
187
+ var import_react2 = require("react");
188
+ var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
189
+ var import_jsx_runtime2 = require("react/jsx-runtime");
190
+ var ENGINE_OPTIONS2 = [
191
+ { value: "in-process", key: "engineInProcess" },
192
+ { value: "claude-code", key: "engineClaudeCode" },
193
+ { value: "codex", key: "engineCodex" },
194
+ { value: "pi", key: "enginePi" }
195
+ ];
196
+ function engineLabelKey2(engine) {
197
+ switch (engine) {
198
+ case "claude-code":
199
+ return "engineClaudeCode";
200
+ case "codex":
201
+ return "engineCodex";
202
+ case "pi":
203
+ return "enginePi";
204
+ default:
205
+ return "engineInProcess";
206
+ }
207
+ }
208
+ var trigger2 = {
209
+ appearance: "none",
210
+ boxSizing: "border-box",
211
+ display: "inline-flex",
212
+ alignItems: "center",
213
+ gap: 6,
214
+ padding: "4px 8px",
215
+ border: "1px solid var(--dsw-alias-border-l2)",
216
+ borderRadius: 10,
217
+ background: "var(--dsw-alias-bg-layer-1)",
218
+ color: "var(--dsw-alias-label-primary)",
219
+ font: "inherit",
220
+ fontSize: 12,
221
+ lineHeight: "20px",
222
+ whiteSpace: "nowrap",
223
+ cursor: "pointer"
224
+ };
225
+ var triggerBusy = { ...trigger2, opacity: 0.5, cursor: "default" };
226
+ var frozen = {
227
+ boxSizing: "border-box",
228
+ display: "inline-flex",
229
+ alignItems: "center",
230
+ padding: "4px 8px",
231
+ color: "var(--dsw-alias-label-secondary)",
232
+ font: "inherit",
233
+ fontSize: 12,
234
+ lineHeight: "20px",
235
+ whiteSpace: "nowrap"
236
+ };
237
+ function LoopEngineComposerSelect(props) {
238
+ const { rpc, switcher, useSnapshot, session, t } = props;
239
+ const { status, showInComposer } = useSnapshot((snapshot) => snapshot);
240
+ const [open, setOpen] = (0, import_react2.useState)(false);
241
+ const [busy, setBusy] = (0, import_react2.useState)(false);
242
+ const triggerRef = (0, import_react2.useRef)(null);
243
+ const [engine, setEngine] = (0, import_react2.useState)(void 0);
244
+ const [resolving, setResolving] = (0, import_react2.useState)(false);
245
+ const sessionId = session?.sessionId;
246
+ (0, import_react2.useEffect)(() => {
247
+ if (sessionId === void 0) {
248
+ setEngine(void 0);
249
+ setResolving(false);
250
+ return;
251
+ }
252
+ const abort = new AbortController();
253
+ setEngine(void 0);
254
+ setResolving(true);
255
+ void rpc.resolve(sessionId, abort.signal).then((resolved) => {
256
+ if (abort.signal.aborted) return;
257
+ setEngine(resolved);
258
+ setResolving(false);
259
+ });
260
+ return () => {
261
+ abort.abort();
262
+ };
263
+ }, [rpc, sessionId]);
264
+ if (status === "loading" || !showInComposer) return null;
265
+ const label = engine !== void 0 ? t(engineLabelKey2(engine)) : t(resolving ? "engineResolving" : "engineUnknown");
266
+ const notice2 = engine === "claude-code" ? t("claudeModelNotice") : engine === void 0 && !resolving ? t("engineUnknownNotice") : t("switchCreatesSession");
267
+ if (!rpc.available) {
268
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: frozen, title: t("boundNotice"), children: label });
269
+ }
270
+ const onSelect = (next) => {
271
+ setOpen(false);
272
+ const value = next;
273
+ if (value === engine || busy) return;
274
+ setBusy(true);
275
+ void switcher.startSessionOn(value).finally(() => {
276
+ setBusy(false);
277
+ });
278
+ };
279
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
280
+ import_dsh_client_ui_primitives2.Menu,
281
+ {
282
+ open,
283
+ onClose: () => {
284
+ setOpen(false);
285
+ },
286
+ items: ENGINE_OPTIONS2.map((option) => ({ id: option.value, label: t(option.key) })),
287
+ selectedId: engine,
288
+ onSelect,
289
+ align: "start",
290
+ portal: true,
291
+ getAnchorRect: () => triggerRef.current?.getBoundingClientRect() ?? null,
292
+ anchor: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
293
+ "button",
294
+ {
295
+ type: "button",
296
+ ref: triggerRef,
297
+ "aria-haspopup": "menu",
298
+ "aria-expanded": open,
299
+ disabled: busy,
300
+ style: busy ? triggerBusy : trigger2,
301
+ title: notice2,
302
+ onClick: () => {
303
+ setOpen(!open);
304
+ },
305
+ children: [
306
+ label,
307
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.IconChevronDownOutline14, { size: 14 })
308
+ ]
309
+ }
310
+ )
311
+ }
312
+ );
313
+ }
314
+
315
+ // src/namespace.ts
316
+ var LOOP_ENGINE_SETTINGS_NAMESPACE_LITERAL = "agent-loop-engine";
317
+ var LOOP_ENGINE_IDS = ["in-process", "claude-code", "codex", "pi"];
318
+
319
+ // src/client/engine-rpc.ts
320
+ var CHANNEL = "/loop-engine";
321
+ function decodeEngine(value) {
322
+ if (typeof value !== "object" || value === null) return void 0;
323
+ const { engine } = value;
324
+ return LOOP_ENGINE_IDS.find((id) => id === engine);
325
+ }
326
+ var EngineRpc = class {
327
+ /**
328
+ * @param connection - the browser connection, or undefined when the profile has none.
329
+ */
330
+ constructor(connection) {
331
+ this.connection = connection;
332
+ }
333
+ connection;
334
+ /** Whether the channel is reachable; false makes the composer read-only. */
335
+ get available() {
336
+ return this.connection !== void 0;
337
+ }
338
+ /**
339
+ * Claim an engine for a session id the caller is about to create.
340
+ *
341
+ * Must be awaited before the session is created: the host resolves the
342
+ * reservation inside `createAgent`, which the harness fires eagerly at
343
+ * session-open.
344
+ *
345
+ * @param sessionId - id the caller will pass to `sessions.create`.
346
+ * @param engine - engine that session must run on.
347
+ * @returns whether the reservation landed.
348
+ */
349
+ async bind(sessionId, engine) {
350
+ const result = await this.call("bind", { sessionId, engine });
351
+ return result !== void 0;
352
+ }
353
+ /**
354
+ * Read the engine a session is actually bound to.
355
+ * @param sessionId - the session to look up.
356
+ * @param signal - abort when the seat unmounts or the session changes.
357
+ * @returns the engine, or undefined when unknown or unreachable.
358
+ */
359
+ async resolve(sessionId, signal) {
360
+ return decodeEngine(await this.call("resolve", { sessionId }, signal));
361
+ }
362
+ /**
363
+ * Issue one call, folding transport and endpoint failures into `undefined`.
364
+ *
365
+ * A failure here is never worth breaking the composer over: the engine is a
366
+ * label and a convenience, and the session works regardless.
367
+ */
368
+ async call(endpoint, payload, signal) {
369
+ const connection = this.connection;
370
+ if (connection === void 0) return void 0;
371
+ try {
372
+ const result = await connection.rpc.call(CHANNEL, endpoint, payload, signal);
373
+ return result.ok ? result.value : void 0;
374
+ } catch {
375
+ return void 0;
376
+ }
377
+ }
378
+ };
379
+
380
+ // src/client/session-location.ts
381
+ function sessionLocation(sessions, workspaces) {
382
+ const current2 = sessions.current;
383
+ if (current2 === void 0) return {};
384
+ const workspaceId = workspaces?.find((item) => item.sessionIds.includes(current2))?.workspaceId;
385
+ if (workspaceId !== void 0) return { workspaceId };
386
+ const cwd = sessions.byId[current2]?.cwd;
387
+ return cwd === void 0 ? {} : { cwd };
388
+ }
389
+
390
+ // node_modules/.pnpm/zustand@4.4.7_@types+react@19.2.18_immer@10.2.0_react@18.3.1/node_modules/zustand/esm/vanilla.mjs
391
+ var import_meta = {};
392
+ var createStoreImpl = (createState) => {
393
+ let state;
394
+ const listeners = /* @__PURE__ */ new Set();
395
+ const setState = (partial, replace) => {
396
+ const nextState = typeof partial === "function" ? partial(state) : partial;
397
+ if (!Object.is(nextState, state)) {
398
+ const previousState = state;
399
+ state = (replace != null ? replace : typeof nextState !== "object" || nextState === null) ? nextState : Object.assign({}, state, nextState);
400
+ listeners.forEach((listener) => listener(state, previousState));
401
+ }
402
+ };
403
+ const getState = () => state;
404
+ const subscribe = (listener) => {
405
+ listeners.add(listener);
406
+ return () => listeners.delete(listener);
407
+ };
408
+ const destroy = () => {
409
+ if ((import_meta.env ? import_meta.env.MODE : void 0) !== "production") {
410
+ console.warn(
411
+ "[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."
412
+ );
413
+ }
414
+ listeners.clear();
415
+ };
416
+ const api = { setState, getState, subscribe, destroy };
417
+ state = createState(setState, getState, api);
418
+ return api;
419
+ };
420
+ var createStore = (createState) => createState ? createStoreImpl(createState) : createStoreImpl;
421
+
422
+ // node_modules/.pnpm/zustand@4.4.7_@types+react@19.2.18_immer@10.2.0_react@18.3.1/node_modules/zustand/esm/middleware.mjs
423
+ var subscribeWithSelectorImpl = (fn) => (set2, get, api) => {
424
+ const origSubscribe = api.subscribe;
425
+ api.subscribe = (selector, optListener, options) => {
426
+ let listener = selector;
427
+ if (optListener) {
428
+ const equalityFn = (options == null ? void 0 : options.equalityFn) || Object.is;
429
+ let currentSlice = selector(api.getState());
430
+ listener = (state) => {
431
+ const nextSlice = selector(state);
432
+ if (!equalityFn(currentSlice, nextSlice)) {
433
+ const previousSlice = currentSlice;
434
+ optListener(currentSlice = nextSlice, previousSlice);
435
+ }
436
+ };
437
+ if (options == null ? void 0 : options.fireImmediately) {
438
+ optListener(currentSlice, currentSlice);
439
+ }
440
+ }
441
+ return origSubscribe(listener);
442
+ };
443
+ const initialState = fn(set2, get, api);
444
+ return initialState;
445
+ };
446
+ var subscribeWithSelector = subscribeWithSelectorImpl;
447
+
448
+ // node_modules/.pnpm/immer@10.2.0/node_modules/immer/dist/immer.mjs
449
+ var NOTHING = /* @__PURE__ */ Symbol.for("immer-nothing");
450
+ var DRAFTABLE = /* @__PURE__ */ Symbol.for("immer-draftable");
451
+ var DRAFT_STATE = /* @__PURE__ */ Symbol.for("immer-state");
452
+ var errors = true ? [
453
+ // All error codes, starting by 0:
454
+ function(plugin) {
455
+ return `The plugin for '${plugin}' has not been loaded into Immer. To enable the plugin, import and call \`enable${plugin}()\` when initializing your application.`;
456
+ },
457
+ function(thing) {
458
+ return `produce can only be called on things that are draftable: plain objects, arrays, Map, Set or classes that are marked with '[immerable]: true'. Got '${thing}'`;
459
+ },
460
+ "This object has been frozen and should not be mutated",
461
+ function(data) {
462
+ return "Cannot use a proxy that has been revoked. Did you pass an object from inside an immer function to an async process? " + data;
463
+ },
464
+ "An immer producer returned a new value *and* modified its draft. Either return a new value *or* modify the draft.",
465
+ "Immer forbids circular references",
466
+ "The first or second argument to `produce` must be a function",
467
+ "The third argument to `produce` must be a function or undefined",
468
+ "First argument to `createDraft` must be a plain object, an array, or an immerable object",
469
+ "First argument to `finishDraft` must be a draft returned by `createDraft`",
470
+ function(thing) {
471
+ return `'current' expects a draft, got: ${thing}`;
472
+ },
473
+ "Object.defineProperty() cannot be used on an Immer draft",
474
+ "Object.setPrototypeOf() cannot be used on an Immer draft",
475
+ "Immer only supports deleting array indices",
476
+ "Immer only supports setting array indices and the 'length' property",
477
+ function(thing) {
478
+ return `'original' expects a draft, got: ${thing}`;
479
+ }
480
+ // Note: if more errors are added, the errorOffset in Patches.ts should be increased
481
+ // See Patches.ts for additional errors
482
+ ] : [];
483
+ function die(error2, ...args) {
484
+ if (true) {
485
+ const e = errors[error2];
486
+ const msg = typeof e === "function" ? e.apply(null, args) : e;
487
+ throw new Error(`[Immer] ${msg}`);
488
+ }
489
+ throw new Error(
490
+ `[Immer] minified error nr: ${error2}. Full error at: https://bit.ly/3cXEKWf`
491
+ );
492
+ }
493
+ var getPrototypeOf = Object.getPrototypeOf;
494
+ function isDraft(value) {
495
+ return !!value && !!value[DRAFT_STATE];
496
+ }
497
+ function isDraftable(value) {
498
+ if (!value)
499
+ return false;
500
+ return isPlainObject(value) || Array.isArray(value) || !!value[DRAFTABLE] || !!value.constructor?.[DRAFTABLE] || isMap(value) || isSet(value);
501
+ }
502
+ var objectCtorString = Object.prototype.constructor.toString();
503
+ var cachedCtorStrings = /* @__PURE__ */ new WeakMap();
504
+ function isPlainObject(value) {
505
+ if (!value || typeof value !== "object")
506
+ return false;
507
+ const proto = Object.getPrototypeOf(value);
508
+ if (proto === null || proto === Object.prototype)
509
+ return true;
510
+ const Ctor = Object.hasOwnProperty.call(proto, "constructor") && proto.constructor;
511
+ if (Ctor === Object)
512
+ return true;
513
+ if (typeof Ctor !== "function")
514
+ return false;
515
+ let ctorString = cachedCtorStrings.get(Ctor);
516
+ if (ctorString === void 0) {
517
+ ctorString = Function.toString.call(Ctor);
518
+ cachedCtorStrings.set(Ctor, ctorString);
519
+ }
520
+ return ctorString === objectCtorString;
521
+ }
522
+ function each(obj, iter, strict = true) {
523
+ if (getArchtype(obj) === 0) {
524
+ const keys = strict ? Reflect.ownKeys(obj) : Object.keys(obj);
525
+ keys.forEach((key) => {
526
+ iter(key, obj[key], obj);
527
+ });
528
+ } else {
529
+ obj.forEach((entry, index) => iter(index, entry, obj));
530
+ }
531
+ }
532
+ function getArchtype(thing) {
533
+ const state = thing[DRAFT_STATE];
534
+ return state ? state.type_ : Array.isArray(thing) ? 1 : isMap(thing) ? 2 : isSet(thing) ? 3 : 0;
535
+ }
536
+ function has(thing, prop) {
537
+ return getArchtype(thing) === 2 ? thing.has(prop) : Object.prototype.hasOwnProperty.call(thing, prop);
538
+ }
539
+ function set(thing, propOrOldValue, value) {
540
+ const t = getArchtype(thing);
541
+ if (t === 2)
542
+ thing.set(propOrOldValue, value);
543
+ else if (t === 3) {
544
+ thing.add(value);
545
+ } else
546
+ thing[propOrOldValue] = value;
547
+ }
548
+ function is(x, y) {
549
+ if (x === y) {
550
+ return x !== 0 || 1 / x === 1 / y;
551
+ } else {
552
+ return x !== x && y !== y;
553
+ }
554
+ }
555
+ function isMap(target) {
556
+ return target instanceof Map;
557
+ }
558
+ function isSet(target) {
559
+ return target instanceof Set;
560
+ }
561
+ function latest(state) {
562
+ return state.copy_ || state.base_;
563
+ }
564
+ function shallowCopy(base, strict) {
565
+ if (isMap(base)) {
566
+ return new Map(base);
567
+ }
568
+ if (isSet(base)) {
569
+ return new Set(base);
570
+ }
571
+ if (Array.isArray(base))
572
+ return Array.prototype.slice.call(base);
573
+ const isPlain = isPlainObject(base);
574
+ if (strict === true || strict === "class_only" && !isPlain) {
575
+ const descriptors = Object.getOwnPropertyDescriptors(base);
576
+ delete descriptors[DRAFT_STATE];
577
+ let keys = Reflect.ownKeys(descriptors);
578
+ for (let i = 0; i < keys.length; i++) {
579
+ const key = keys[i];
580
+ const desc = descriptors[key];
581
+ if (desc.writable === false) {
582
+ desc.writable = true;
583
+ desc.configurable = true;
584
+ }
585
+ if (desc.get || desc.set)
586
+ descriptors[key] = {
587
+ configurable: true,
588
+ writable: true,
589
+ // could live with !!desc.set as well here...
590
+ enumerable: desc.enumerable,
591
+ value: base[key]
592
+ };
593
+ }
594
+ return Object.create(getPrototypeOf(base), descriptors);
595
+ } else {
596
+ const proto = getPrototypeOf(base);
597
+ if (proto !== null && isPlain) {
598
+ return { ...base };
599
+ }
600
+ const obj = Object.create(proto);
601
+ return Object.assign(obj, base);
602
+ }
603
+ }
604
+ function freeze(obj, deep = false) {
605
+ if (isFrozen(obj) || isDraft(obj) || !isDraftable(obj))
606
+ return obj;
607
+ if (getArchtype(obj) > 1) {
608
+ Object.defineProperties(obj, {
609
+ set: dontMutateMethodOverride,
610
+ add: dontMutateMethodOverride,
611
+ clear: dontMutateMethodOverride,
612
+ delete: dontMutateMethodOverride
613
+ });
614
+ }
615
+ Object.freeze(obj);
616
+ if (deep)
617
+ Object.values(obj).forEach((value) => freeze(value, true));
618
+ return obj;
619
+ }
620
+ function dontMutateFrozenCollections() {
621
+ die(2);
622
+ }
623
+ var dontMutateMethodOverride = {
624
+ value: dontMutateFrozenCollections
625
+ };
626
+ function isFrozen(obj) {
627
+ if (obj === null || typeof obj !== "object")
628
+ return true;
629
+ return Object.isFrozen(obj);
630
+ }
631
+ var plugins = {};
632
+ function getPlugin(pluginKey) {
633
+ const plugin = plugins[pluginKey];
634
+ if (!plugin) {
635
+ die(0, pluginKey);
636
+ }
637
+ return plugin;
638
+ }
639
+ var currentScope;
640
+ function getCurrentScope() {
641
+ return currentScope;
642
+ }
643
+ function createScope(parent_, immer_) {
644
+ return {
645
+ drafts_: [],
646
+ parent_,
647
+ immer_,
648
+ // Whenever the modified draft contains a draft from another scope, we
649
+ // need to prevent auto-freezing so the unowned draft can be finalized.
650
+ canAutoFreeze_: true,
651
+ unfinalizedDrafts_: 0
652
+ };
653
+ }
654
+ function usePatchesInScope(scope, patchListener) {
655
+ if (patchListener) {
656
+ getPlugin("Patches");
657
+ scope.patches_ = [];
658
+ scope.inversePatches_ = [];
659
+ scope.patchListener_ = patchListener;
660
+ }
661
+ }
662
+ function revokeScope(scope) {
663
+ leaveScope(scope);
664
+ scope.drafts_.forEach(revokeDraft);
665
+ scope.drafts_ = null;
666
+ }
667
+ function leaveScope(scope) {
668
+ if (scope === currentScope) {
669
+ currentScope = scope.parent_;
670
+ }
671
+ }
672
+ function enterScope(immer2) {
673
+ return currentScope = createScope(currentScope, immer2);
674
+ }
675
+ function revokeDraft(draft) {
676
+ const state = draft[DRAFT_STATE];
677
+ if (state.type_ === 0 || state.type_ === 1)
678
+ state.revoke_();
679
+ else
680
+ state.revoked_ = true;
681
+ }
682
+ function processResult(result, scope) {
683
+ scope.unfinalizedDrafts_ = scope.drafts_.length;
684
+ const baseDraft = scope.drafts_[0];
685
+ const isReplaced = result !== void 0 && result !== baseDraft;
686
+ if (isReplaced) {
687
+ if (baseDraft[DRAFT_STATE].modified_) {
688
+ revokeScope(scope);
689
+ die(4);
690
+ }
691
+ if (isDraftable(result)) {
692
+ result = finalize(scope, result);
693
+ if (!scope.parent_)
694
+ maybeFreeze(scope, result);
695
+ }
696
+ if (scope.patches_) {
697
+ getPlugin("Patches").generateReplacementPatches_(
698
+ baseDraft[DRAFT_STATE].base_,
699
+ result,
700
+ scope.patches_,
701
+ scope.inversePatches_
702
+ );
703
+ }
704
+ } else {
705
+ result = finalize(scope, baseDraft, []);
706
+ }
707
+ revokeScope(scope);
708
+ if (scope.patches_) {
709
+ scope.patchListener_(scope.patches_, scope.inversePatches_);
710
+ }
711
+ return result !== NOTHING ? result : void 0;
712
+ }
713
+ function finalize(rootScope, value, path) {
714
+ if (isFrozen(value))
715
+ return value;
716
+ const useStrictIteration = rootScope.immer_.shouldUseStrictIteration();
717
+ const state = value[DRAFT_STATE];
718
+ if (!state) {
719
+ each(
720
+ value,
721
+ (key, childValue) => finalizeProperty(rootScope, state, value, key, childValue, path),
722
+ useStrictIteration
723
+ );
724
+ return value;
725
+ }
726
+ if (state.scope_ !== rootScope)
727
+ return value;
728
+ if (!state.modified_) {
729
+ maybeFreeze(rootScope, state.base_, true);
730
+ return state.base_;
731
+ }
732
+ if (!state.finalized_) {
733
+ state.finalized_ = true;
734
+ state.scope_.unfinalizedDrafts_--;
735
+ const result = state.copy_;
736
+ let resultEach = result;
737
+ let isSet2 = false;
738
+ if (state.type_ === 3) {
739
+ resultEach = new Set(result);
740
+ result.clear();
741
+ isSet2 = true;
742
+ }
743
+ each(
744
+ resultEach,
745
+ (key, childValue) => finalizeProperty(
746
+ rootScope,
747
+ state,
748
+ result,
749
+ key,
750
+ childValue,
751
+ path,
752
+ isSet2
753
+ ),
754
+ useStrictIteration
755
+ );
756
+ maybeFreeze(rootScope, result, false);
757
+ if (path && rootScope.patches_) {
758
+ getPlugin("Patches").generatePatches_(
759
+ state,
760
+ path,
761
+ rootScope.patches_,
762
+ rootScope.inversePatches_
763
+ );
764
+ }
765
+ }
766
+ return state.copy_;
767
+ }
768
+ function finalizeProperty(rootScope, parentState, targetObject, prop, childValue, rootPath, targetIsSet) {
769
+ if (childValue == null) {
770
+ return;
771
+ }
772
+ if (typeof childValue !== "object" && !targetIsSet) {
773
+ return;
774
+ }
775
+ const childIsFrozen = isFrozen(childValue);
776
+ if (childIsFrozen && !targetIsSet) {
777
+ return;
778
+ }
779
+ if (childValue === targetObject)
780
+ die(5);
781
+ if (isDraft(childValue)) {
782
+ const path = rootPath && parentState && parentState.type_ !== 3 && // Set objects are atomic since they have no keys.
783
+ !has(parentState.assigned_, prop) ? rootPath.concat(prop) : void 0;
784
+ const res = finalize(rootScope, childValue, path);
785
+ set(targetObject, prop, res);
786
+ if (isDraft(res)) {
787
+ rootScope.canAutoFreeze_ = false;
788
+ } else
789
+ return;
790
+ } else if (targetIsSet) {
791
+ targetObject.add(childValue);
792
+ }
793
+ if (isDraftable(childValue) && !childIsFrozen) {
794
+ if (!rootScope.immer_.autoFreeze_ && rootScope.unfinalizedDrafts_ < 1) {
795
+ return;
796
+ }
797
+ if (parentState && parentState.base_ && parentState.base_[prop] === childValue && childIsFrozen) {
798
+ return;
799
+ }
800
+ finalize(rootScope, childValue);
801
+ if ((!parentState || !parentState.scope_.parent_) && typeof prop !== "symbol" && (isMap(targetObject) ? targetObject.has(prop) : Object.prototype.propertyIsEnumerable.call(targetObject, prop)))
802
+ maybeFreeze(rootScope, childValue);
803
+ }
804
+ }
805
+ function maybeFreeze(scope, value, deep = false) {
806
+ if (!scope.parent_ && scope.immer_.autoFreeze_ && scope.canAutoFreeze_) {
807
+ freeze(value, deep);
808
+ }
809
+ }
810
+ function createProxyProxy(base, parent) {
811
+ const isArray = Array.isArray(base);
812
+ const state = {
813
+ type_: isArray ? 1 : 0,
814
+ // Track which produce call this is associated with.
815
+ scope_: parent ? parent.scope_ : getCurrentScope(),
816
+ // True for both shallow and deep changes.
817
+ modified_: false,
818
+ // Used during finalization.
819
+ finalized_: false,
820
+ // Track which properties have been assigned (true) or deleted (false).
821
+ assigned_: {},
822
+ // The parent draft state.
823
+ parent_: parent,
824
+ // The base state.
825
+ base_: base,
826
+ // The base proxy.
827
+ draft_: null,
828
+ // set below
829
+ // The base copy with any updated values.
830
+ copy_: null,
831
+ // Called by the `produce` function.
832
+ revoke_: null,
833
+ isManual_: false
834
+ };
835
+ let target = state;
836
+ let traps = objectTraps;
837
+ if (isArray) {
838
+ target = [state];
839
+ traps = arrayTraps;
840
+ }
841
+ const { revoke, proxy } = Proxy.revocable(target, traps);
842
+ state.draft_ = proxy;
843
+ state.revoke_ = revoke;
844
+ return proxy;
845
+ }
846
+ var objectTraps = {
847
+ get(state, prop) {
848
+ if (prop === DRAFT_STATE)
849
+ return state;
850
+ const source = latest(state);
851
+ if (!has(source, prop)) {
852
+ return readPropFromProto(state, source, prop);
853
+ }
854
+ const value = source[prop];
855
+ if (state.finalized_ || !isDraftable(value)) {
856
+ return value;
857
+ }
858
+ if (value === peek(state.base_, prop)) {
859
+ prepareCopy(state);
860
+ return state.copy_[prop] = createProxy(value, state);
861
+ }
862
+ return value;
863
+ },
864
+ has(state, prop) {
865
+ return prop in latest(state);
866
+ },
867
+ ownKeys(state) {
868
+ return Reflect.ownKeys(latest(state));
869
+ },
870
+ set(state, prop, value) {
871
+ const desc = getDescriptorFromProto(latest(state), prop);
872
+ if (desc?.set) {
873
+ desc.set.call(state.draft_, value);
874
+ return true;
875
+ }
876
+ if (!state.modified_) {
877
+ const current2 = peek(latest(state), prop);
878
+ const currentState = current2?.[DRAFT_STATE];
879
+ if (currentState && currentState.base_ === value) {
880
+ state.copy_[prop] = value;
881
+ state.assigned_[prop] = false;
882
+ return true;
883
+ }
884
+ if (is(value, current2) && (value !== void 0 || has(state.base_, prop)))
885
+ return true;
886
+ prepareCopy(state);
887
+ markChanged(state);
888
+ }
889
+ if (state.copy_[prop] === value && // special case: handle new props with value 'undefined'
890
+ (value !== void 0 || prop in state.copy_) || // special case: NaN
891
+ Number.isNaN(value) && Number.isNaN(state.copy_[prop]))
892
+ return true;
893
+ state.copy_[prop] = value;
894
+ state.assigned_[prop] = true;
895
+ return true;
896
+ },
897
+ deleteProperty(state, prop) {
898
+ if (peek(state.base_, prop) !== void 0 || prop in state.base_) {
899
+ state.assigned_[prop] = false;
900
+ prepareCopy(state);
901
+ markChanged(state);
902
+ } else {
903
+ delete state.assigned_[prop];
904
+ }
905
+ if (state.copy_) {
906
+ delete state.copy_[prop];
907
+ }
908
+ return true;
909
+ },
910
+ // Note: We never coerce `desc.value` into an Immer draft, because we can't make
911
+ // the same guarantee in ES5 mode.
912
+ getOwnPropertyDescriptor(state, prop) {
913
+ const owner = latest(state);
914
+ const desc = Reflect.getOwnPropertyDescriptor(owner, prop);
915
+ if (!desc)
916
+ return desc;
917
+ return {
918
+ writable: true,
919
+ configurable: state.type_ !== 1 || prop !== "length",
920
+ enumerable: desc.enumerable,
921
+ value: owner[prop]
922
+ };
923
+ },
924
+ defineProperty() {
925
+ die(11);
926
+ },
927
+ getPrototypeOf(state) {
928
+ return getPrototypeOf(state.base_);
929
+ },
930
+ setPrototypeOf() {
931
+ die(12);
932
+ }
933
+ };
934
+ var arrayTraps = {};
935
+ each(objectTraps, (key, fn) => {
936
+ arrayTraps[key] = function() {
937
+ arguments[0] = arguments[0][0];
938
+ return fn.apply(this, arguments);
939
+ };
940
+ });
941
+ arrayTraps.deleteProperty = function(state, prop) {
942
+ if (isNaN(parseInt(prop)))
943
+ die(13);
944
+ return arrayTraps.set.call(this, state, prop, void 0);
945
+ };
946
+ arrayTraps.set = function(state, prop, value) {
947
+ if (prop !== "length" && isNaN(parseInt(prop)))
948
+ die(14);
949
+ return objectTraps.set.call(this, state[0], prop, value, state[0]);
950
+ };
951
+ function peek(draft, prop) {
952
+ const state = draft[DRAFT_STATE];
953
+ const source = state ? latest(state) : draft;
954
+ return source[prop];
955
+ }
956
+ function readPropFromProto(state, source, prop) {
957
+ const desc = getDescriptorFromProto(source, prop);
958
+ return desc ? `value` in desc ? desc.value : (
959
+ // This is a very special case, if the prop is a getter defined by the
960
+ // prototype, we should invoke it with the draft as context!
961
+ desc.get?.call(state.draft_)
962
+ ) : void 0;
963
+ }
964
+ function getDescriptorFromProto(source, prop) {
965
+ if (!(prop in source))
966
+ return void 0;
967
+ let proto = getPrototypeOf(source);
968
+ while (proto) {
969
+ const desc = Object.getOwnPropertyDescriptor(proto, prop);
970
+ if (desc)
971
+ return desc;
972
+ proto = getPrototypeOf(proto);
973
+ }
974
+ return void 0;
975
+ }
976
+ function markChanged(state) {
977
+ if (!state.modified_) {
978
+ state.modified_ = true;
979
+ if (state.parent_) {
980
+ markChanged(state.parent_);
981
+ }
982
+ }
983
+ }
984
+ function prepareCopy(state) {
985
+ if (!state.copy_) {
986
+ state.copy_ = shallowCopy(
987
+ state.base_,
988
+ state.scope_.immer_.useStrictShallowCopy_
989
+ );
990
+ }
991
+ }
992
+ var Immer2 = class {
993
+ constructor(config) {
994
+ this.autoFreeze_ = true;
995
+ this.useStrictShallowCopy_ = false;
996
+ this.useStrictIteration_ = true;
997
+ this.produce = (base, recipe, patchListener) => {
998
+ if (typeof base === "function" && typeof recipe !== "function") {
999
+ const defaultBase = recipe;
1000
+ recipe = base;
1001
+ const self = this;
1002
+ return function curriedProduce(base2 = defaultBase, ...args) {
1003
+ return self.produce(base2, (draft) => recipe.call(this, draft, ...args));
1004
+ };
1005
+ }
1006
+ if (typeof recipe !== "function")
1007
+ die(6);
1008
+ if (patchListener !== void 0 && typeof patchListener !== "function")
1009
+ die(7);
1010
+ let result;
1011
+ if (isDraftable(base)) {
1012
+ const scope = enterScope(this);
1013
+ const proxy = createProxy(base, void 0);
1014
+ let hasError = true;
1015
+ try {
1016
+ result = recipe(proxy);
1017
+ hasError = false;
1018
+ } finally {
1019
+ if (hasError)
1020
+ revokeScope(scope);
1021
+ else
1022
+ leaveScope(scope);
1023
+ }
1024
+ usePatchesInScope(scope, patchListener);
1025
+ return processResult(result, scope);
1026
+ } else if (!base || typeof base !== "object") {
1027
+ result = recipe(base);
1028
+ if (result === void 0)
1029
+ result = base;
1030
+ if (result === NOTHING)
1031
+ result = void 0;
1032
+ if (this.autoFreeze_)
1033
+ freeze(result, true);
1034
+ if (patchListener) {
1035
+ const p = [];
1036
+ const ip = [];
1037
+ getPlugin("Patches").generateReplacementPatches_(base, result, p, ip);
1038
+ patchListener(p, ip);
1039
+ }
1040
+ return result;
1041
+ } else
1042
+ die(1, base);
1043
+ };
1044
+ this.produceWithPatches = (base, recipe) => {
1045
+ if (typeof base === "function") {
1046
+ return (state, ...args) => this.produceWithPatches(state, (draft) => base(draft, ...args));
1047
+ }
1048
+ let patches, inversePatches;
1049
+ const result = this.produce(base, recipe, (p, ip) => {
1050
+ patches = p;
1051
+ inversePatches = ip;
1052
+ });
1053
+ return [result, patches, inversePatches];
1054
+ };
1055
+ if (typeof config?.autoFreeze === "boolean")
1056
+ this.setAutoFreeze(config.autoFreeze);
1057
+ if (typeof config?.useStrictShallowCopy === "boolean")
1058
+ this.setUseStrictShallowCopy(config.useStrictShallowCopy);
1059
+ if (typeof config?.useStrictIteration === "boolean")
1060
+ this.setUseStrictIteration(config.useStrictIteration);
1061
+ }
1062
+ createDraft(base) {
1063
+ if (!isDraftable(base))
1064
+ die(8);
1065
+ if (isDraft(base))
1066
+ base = current(base);
1067
+ const scope = enterScope(this);
1068
+ const proxy = createProxy(base, void 0);
1069
+ proxy[DRAFT_STATE].isManual_ = true;
1070
+ leaveScope(scope);
1071
+ return proxy;
1072
+ }
1073
+ finishDraft(draft, patchListener) {
1074
+ const state = draft && draft[DRAFT_STATE];
1075
+ if (!state || !state.isManual_)
1076
+ die(9);
1077
+ const { scope_: scope } = state;
1078
+ usePatchesInScope(scope, patchListener);
1079
+ return processResult(void 0, scope);
1080
+ }
1081
+ /**
1082
+ * Pass true to automatically freeze all copies created by Immer.
1083
+ *
1084
+ * By default, auto-freezing is enabled.
1085
+ */
1086
+ setAutoFreeze(value) {
1087
+ this.autoFreeze_ = value;
1088
+ }
1089
+ /**
1090
+ * Pass true to enable strict shallow copy.
1091
+ *
1092
+ * By default, immer does not copy the object descriptors such as getter, setter and non-enumrable properties.
1093
+ */
1094
+ setUseStrictShallowCopy(value) {
1095
+ this.useStrictShallowCopy_ = value;
1096
+ }
1097
+ /**
1098
+ * Pass false to use faster iteration that skips non-enumerable properties
1099
+ * but still handles symbols for compatibility.
1100
+ *
1101
+ * By default, strict iteration is enabled (includes all own properties).
1102
+ */
1103
+ setUseStrictIteration(value) {
1104
+ this.useStrictIteration_ = value;
1105
+ }
1106
+ shouldUseStrictIteration() {
1107
+ return this.useStrictIteration_;
1108
+ }
1109
+ applyPatches(base, patches) {
1110
+ let i;
1111
+ for (i = patches.length - 1; i >= 0; i--) {
1112
+ const patch = patches[i];
1113
+ if (patch.path.length === 0 && patch.op === "replace") {
1114
+ base = patch.value;
1115
+ break;
1116
+ }
1117
+ }
1118
+ if (i > -1) {
1119
+ patches = patches.slice(i + 1);
1120
+ }
1121
+ const applyPatchesImpl = getPlugin("Patches").applyPatches_;
1122
+ if (isDraft(base)) {
1123
+ return applyPatchesImpl(base, patches);
1124
+ }
1125
+ return this.produce(
1126
+ base,
1127
+ (draft) => applyPatchesImpl(draft, patches)
1128
+ );
1129
+ }
1130
+ };
1131
+ function createProxy(value, parent) {
1132
+ const draft = isMap(value) ? getPlugin("MapSet").proxyMap_(value, parent) : isSet(value) ? getPlugin("MapSet").proxySet_(value, parent) : createProxyProxy(value, parent);
1133
+ const scope = parent ? parent.scope_ : getCurrentScope();
1134
+ scope.drafts_.push(draft);
1135
+ return draft;
1136
+ }
1137
+ function current(value) {
1138
+ if (!isDraft(value))
1139
+ die(10, value);
1140
+ return currentImpl(value);
1141
+ }
1142
+ function currentImpl(value) {
1143
+ if (!isDraftable(value) || isFrozen(value))
1144
+ return value;
1145
+ const state = value[DRAFT_STATE];
1146
+ let copy;
1147
+ let strict = true;
1148
+ if (state) {
1149
+ if (!state.modified_)
1150
+ return state.base_;
1151
+ state.finalized_ = true;
1152
+ copy = shallowCopy(value, state.scope_.immer_.useStrictShallowCopy_);
1153
+ strict = state.scope_.immer_.shouldUseStrictIteration();
1154
+ } else {
1155
+ copy = shallowCopy(value, true);
1156
+ }
1157
+ each(
1158
+ copy,
1159
+ (key, childValue) => {
1160
+ set(copy, key, currentImpl(childValue));
1161
+ },
1162
+ strict
1163
+ );
1164
+ if (state) {
1165
+ state.finalized_ = false;
1166
+ }
1167
+ return copy;
1168
+ }
1169
+ var immer = new Immer2();
1170
+ var produce = immer.produce;
1171
+
1172
+ // node_modules/.pnpm/@deepseek-ai+dsh-client-store@0.1.2-alpha.2_@deepseek-ai+cordis@4.0.2_@types+react@19.2.18_react@18.3.1/node_modules/@deepseek-ai/dsh-client-store/lib/index.js
1173
+ function notifySubscribers(listeners, label, ...args) {
1174
+ for (const listener of [...listeners]) try {
1175
+ listener(...args);
1176
+ } catch (error2) {
1177
+ console.error(`${label} subscriber failed:`, error2);
1178
+ }
1179
+ }
1180
+ function rafBatch(notify) {
1181
+ const schedule = typeof requestAnimationFrame === "function" ? (fn) => {
1182
+ requestAnimationFrame(() => {
1183
+ fn();
1184
+ });
1185
+ } : (fn) => {
1186
+ queueMicrotask(fn);
1187
+ };
1188
+ let scheduled = false;
1189
+ return () => {
1190
+ if (scheduled) return;
1191
+ scheduled = true;
1192
+ schedule(() => {
1193
+ scheduled = false;
1194
+ notify();
1195
+ });
1196
+ };
1197
+ }
1198
+ function createSnapshotStore(init, opts) {
1199
+ const withSelector = subscribeWithSelector(() => init);
1200
+ const api = createStore()(withSelector);
1201
+ if (opts?.persist) attachPersistence(api, opts.persist.name);
1202
+ let subscribe = (fn) => api.subscribe(() => {
1203
+ notifySubscribers([fn], "[client-store]");
1204
+ });
1205
+ if (opts?.flush === "raf") {
1206
+ const listeners = /* @__PURE__ */ new Set();
1207
+ const flush = rafBatch(() => {
1208
+ notifySubscribers(listeners, "[client-store]");
1209
+ });
1210
+ api.subscribe(flush);
1211
+ subscribe = (fn) => {
1212
+ listeners.add(fn);
1213
+ return () => {
1214
+ listeners.delete(fn);
1215
+ };
1216
+ };
1217
+ }
1218
+ return {
1219
+ getSnapshot: () => api.getState(),
1220
+ subscribe: (fn) => subscribe(fn),
1221
+ update: (mutator) => {
1222
+ api.setState(produce(api.getState(), (draft) => {
1223
+ mutator(draft);
1224
+ }), true);
1225
+ },
1226
+ set: (next) => {
1227
+ api.setState(devFreeze(next), true);
1228
+ }
1229
+ };
1230
+ }
1231
+ function attachPersistence(api, name) {
1232
+ if (typeof localStorage === "undefined") return;
1233
+ try {
1234
+ const raw = localStorage.getItem(name);
1235
+ if (raw !== null) api.setState(devFreeze(JSON.parse(raw)), true);
1236
+ } catch (error2) {
1237
+ console.error(`snapshot store '${name}' rehydration failed:`, error2);
1238
+ }
1239
+ api.subscribe((state) => {
1240
+ try {
1241
+ localStorage.setItem(name, JSON.stringify(state));
1242
+ } catch (error2) {
1243
+ console.error(`snapshot store '${name}' persistence failed:`, error2);
1244
+ }
1245
+ });
1246
+ }
1247
+ function devFreeze(value) {
1248
+ return freeze(value, true);
1249
+ }
1250
+
1251
+ // src/client/store.ts
1252
+ function decodeLoopEngine(section) {
1253
+ if (typeof section !== "object" || section === null || Array.isArray(section)) return void 0;
1254
+ const { engine, showInComposer } = section;
1255
+ if (engine !== "in-process" && engine !== "claude-code" && engine !== "codex" && engine !== "pi") {
1256
+ return void 0;
1257
+ }
1258
+ return { engine, showInComposer: showInComposer !== false };
1259
+ }
1260
+ var LoopEngineStore = class {
1261
+ /**
1262
+ * @param scope - the loop engine settings namespace scope.
1263
+ */
1264
+ constructor(scope) {
1265
+ this.scope = scope;
1266
+ }
1267
+ scope;
1268
+ /** uSES-safe state source shared by the registered settings section. */
1269
+ store = createSnapshotStore({
1270
+ status: "loading",
1271
+ engine: "in-process",
1272
+ showInComposer: true,
1273
+ writable: false,
1274
+ error: null
1275
+ });
1276
+ following;
1277
+ saving = false;
1278
+ /** Begin following the bound scope and publish its current answer. */
1279
+ load() {
1280
+ this.following ??= this.scope.subscribe(() => {
1281
+ this.derive();
1282
+ });
1283
+ this.derive();
1284
+ }
1285
+ /**
1286
+ * Persist the selected engine. Success is judged against the snapshot the
1287
+ * write left behind, so a refused write reports error after its recovery.
1288
+ * @param engine - the engine to select for future Agent turns.
1289
+ * @returns whether the write landed.
1290
+ */
1291
+ async setEngine(engine) {
1292
+ this.saving = true;
1293
+ this.store.update((state) => {
1294
+ state.status = "saving";
1295
+ state.error = null;
1296
+ });
1297
+ try {
1298
+ await this.scope.set("engine", engine);
1299
+ } finally {
1300
+ this.saving = false;
1301
+ }
1302
+ this.derive();
1303
+ const { engine: settled } = this.store.getSnapshot();
1304
+ const landed = settled === engine;
1305
+ if (!landed) {
1306
+ this.store.update((state) => {
1307
+ state.status = "unavailable";
1308
+ state.error = "the loop engine selection did not persist";
1309
+ });
1310
+ }
1311
+ return landed;
1312
+ }
1313
+ /**
1314
+ * Persist whether the composer shows the engine picker. Success is judged
1315
+ * against the snapshot the write left behind, so a refused write reports
1316
+ * error after its recovery. Unlike {@link setEngine}, landing does not reload
1317
+ * the page — the toggle only changes composer visibility.
1318
+ * @param show - whether the chat page composer reveals the engine picker.
1319
+ * @returns whether the write landed.
1320
+ */
1321
+ async setShowInComposer(show) {
1322
+ this.saving = true;
1323
+ this.store.update((state) => {
1324
+ state.status = "saving";
1325
+ state.error = null;
1326
+ });
1327
+ try {
1328
+ await this.scope.set("showInComposer", show);
1329
+ } finally {
1330
+ this.saving = false;
1331
+ }
1332
+ this.derive();
1333
+ const { showInComposer: settled } = this.store.getSnapshot();
1334
+ const landed = settled === show;
1335
+ if (!landed) {
1336
+ this.store.update((state) => {
1337
+ state.status = "unavailable";
1338
+ state.error = "the loop engine display setting did not persist";
1339
+ });
1340
+ }
1341
+ return landed;
1342
+ }
1343
+ /** Stop following the scope. */
1344
+ dispose() {
1345
+ this.following?.();
1346
+ this.following = void 0;
1347
+ }
1348
+ derive() {
1349
+ if (this.saving) return;
1350
+ const scope = this.scope.getSnapshot();
1351
+ switch (scope.status) {
1352
+ case "loading":
1353
+ this.store.update((state) => {
1354
+ state.status = "loading";
1355
+ state.error = null;
1356
+ });
1357
+ return;
1358
+ case "unavailable":
1359
+ this.store.update((state) => {
1360
+ state.status = "unavailable";
1361
+ state.engine = "in-process";
1362
+ state.showInComposer = true;
1363
+ state.error = null;
1364
+ });
1365
+ return;
1366
+ case "ready": {
1367
+ const engine = scope.value?.engine ?? "in-process";
1368
+ const showInComposer = scope.value?.showInComposer ?? true;
1369
+ this.store.update((state) => {
1370
+ state.status = "ready";
1371
+ state.engine = engine;
1372
+ state.showInComposer = showInComposer;
1373
+ state.writable = scope.writable;
1374
+ state.error = null;
1375
+ });
1376
+ return;
1377
+ }
1378
+ default: {
1379
+ const exhaustive = scope.status;
1380
+ throw new Error(`unexpected loop engine scope status: ${String(exhaustive)}`);
1381
+ }
1382
+ }
1383
+ }
1384
+ };
1385
+
1386
+ // src/client/locales.ts
1387
+ var zh = {
1388
+ nav: "\u5FAA\u73AF\u5F15\u64CE",
1389
+ description: "\u9009\u62E9\u65B0\u5EFA\u4F1A\u8BDD\u9ED8\u8BA4\u4F7F\u7528\u7684 Agent \u6267\u884C\u5F15\u64CE\u3002\u5DF2\u5B58\u5728\u7684\u4F1A\u8BDD\u4E0D\u53D7\u5F71\u54CD\u2014\u2014\u5F15\u64CE\u5728\u4F1A\u8BDD\u521B\u5EFA\u65F6\u5C31\u5DF2\u56FA\u5B9A\u3002",
1390
+ engineInProcess: "\u8FDB\u7A0B\u5185\u5F15\u64CE\uFF08\u9ED8\u8BA4\uFF09",
1391
+ engineClaudeCode: "Claude Code CLI",
1392
+ engineCodex: "Codex CLI",
1393
+ enginePi: "Pi CLI",
1394
+ showInComposerLabel: "\u5728\u5BF9\u8BDD\u9875\u663E\u793A\u5F15\u64CE\u9009\u62E9\u5668",
1395
+ unavailable: "\u5FAA\u73AF\u5F15\u64CE\u8BBE\u7F6E\u4E0D\u53EF\u7528",
1396
+ switchNotice: "\u8FD9\u91CC\u8BBE\u7F6E\u7684\u662F**\u9ED8\u8BA4\u503C**\uFF1A\u53EA\u5F71\u54CD\u4E4B\u540E\u65B0\u5EFA\u3001\u4E14\u672A\u5355\u72EC\u6307\u5B9A\u5F15\u64CE\u7684\u4F1A\u8BDD\u3002\u5DF2\u6709\u4F1A\u8BDD\u7EE7\u7EED\u4F7F\u7528\u5404\u81EA\u7684\u5F15\u64CE\uFF0C\u65E0\u9700\u5237\u65B0\u6216\u91CD\u542F\u3002",
1397
+ switchCreatesSession: "\u5F53\u524D\u4F1A\u8BDD\u7684\u5F15\u64CE\u5728\u521B\u5EFA\u65F6\u5DF2\u56FA\u5B9A\u3002\u9009\u62E9\u5176\u5B83\u5F15\u64CE\u5C06\u7ACB\u5373\u65B0\u5EFA\u4E00\u4E2A\u4F1A\u8BDD\u5E76\u5207\u6362\u8FC7\u53BB\u3002",
1398
+ boundNotice: "\u672C\u4F1A\u8BDD\u5DF2\u7ED1\u5B9A\u8BE5\u5F15\u64CE\uFF0C\u521B\u5EFA\u540E\u4E0D\u53EF\u66F4\u6539\u3002\u8981\u6362\u5F15\u64CE\u8BF7\u65B0\u5EFA\u4F1A\u8BDD\u3002",
1399
+ engineResolving: "\u5F15\u64CE\u2026",
1400
+ engineUnknown: "\u5F15\u64CE",
1401
+ engineUnknownNotice: "\u8BFB\u53D6\u672C\u4F1A\u8BDD\u5F15\u64CE\u5931\u8D25\u3002\u9009\u62E9\u4E00\u4E2A\u5F15\u64CE\u4ECD\u53EF\u65B0\u5EFA\u4F1A\u8BDD\u5E76\u5207\u6362\u8FC7\u53BB\u3002",
1402
+ saving: "\u4FDD\u5B58\u4E2D\u2026",
1403
+ claudeModelNotice: "\u5F53\u524D\u4F7F\u7528 Claude Code \u5F15\u64CE\uFF1A\u5B9E\u9645\u6A21\u578B\u7531 Claude Code \u539F\u751F\u51B3\u5B9A\uFF0C\u9875\u9762\u4E0A\u7684\u6A21\u578B\u9009\u62E9\u4E0D\u751F\u6548\u3002"
1404
+ };
1405
+ var en = {
1406
+ nav: "Loop engine",
1407
+ description: "The default agent execution engine for new sessions. Existing sessions are unaffected \u2014 a session's engine is fixed when it is created.",
1408
+ engineInProcess: "In-process engine (default)",
1409
+ engineClaudeCode: "Claude Code CLI",
1410
+ engineCodex: "Codex CLI",
1411
+ enginePi: "Pi CLI",
1412
+ showInComposerLabel: "Show the engine selector in the chat page",
1413
+ unavailable: "Loop engine settings are unavailable",
1414
+ switchNotice: "This is a **default**: it applies only to sessions created later that do not pick an engine of their own. Existing sessions keep theirs \u2014 no reload, no restart.",
1415
+ switchCreatesSession: "This session's engine was fixed when it was created. Choosing another engine starts a new session and switches to it.",
1416
+ boundNotice: "This session is bound to this engine and cannot be changed. Start a new session to use a different one.",
1417
+ engineResolving: "Engine\u2026",
1418
+ engineUnknown: "Engine",
1419
+ engineUnknownNotice: "This session's engine could not be read. Choosing one still starts a new session on it.",
1420
+ saving: "Saving\u2026",
1421
+ claudeModelNotice: "Claude Code engine active: the actual model is decided natively by Claude Code; the model selector in this session has no effect."
1422
+ };
1423
+
1424
+ // src/client/index.ts
1425
+ var NS = "settings.loop-engine";
1426
+ var inject = ["slots", "locale", "settingsScope"];
1427
+ function apply(ctx) {
1428
+ ctx.effect(() => ctx.locale.register(NS, { zh, en }), "loop-engine: copy dictionaries");
1429
+ const scope = ctx.settingsScope.bind({
1430
+ namespace: LOOP_ENGINE_SETTINGS_NAMESPACE_LITERAL,
1431
+ decode: decodeLoopEngine
1432
+ });
1433
+ const controller = new LoopEngineStore(scope);
1434
+ ctx.effect(() => {
1435
+ controller.load();
1436
+ return () => {
1437
+ controller.dispose();
1438
+ };
1439
+ }, "loop-engine: store lifecycle");
1440
+ const t = ctx.locale.bind(NS);
1441
+ const injected = () => ({
1442
+ controller,
1443
+ hooks: { snapshot: controller.store },
1444
+ t
1445
+ });
1446
+ ctx.slots.inject("settings.section", () => ctx.slots.register({
1447
+ name: "settings.section",
1448
+ id: "loop-engine",
1449
+ order: 30,
1450
+ label: () => t("nav"),
1451
+ inject: injected
1452
+ }, LoopEngineSection));
1453
+ ctx.inject(["slots", "conversation", "connection"], (scope2) => {
1454
+ const rpc = new EngineRpc(scope2.get("connection"));
1455
+ const switcher = {
1456
+ async startSessionOn(engine) {
1457
+ const sessions = scope2.get("sessions");
1458
+ if (sessions === void 0) return false;
1459
+ const location = sessionLocation(
1460
+ sessions.list.getSnapshot(),
1461
+ scope2.get("workspaces")?.list.getSnapshot().items
1462
+ );
1463
+ const sessionId = crypto.randomUUID();
1464
+ if (!await rpc.bind(sessionId, engine)) return false;
1465
+ try {
1466
+ await sessions.create({ sessionId, ...location });
1467
+ } catch (error2) {
1468
+ console.warn("loop-engine: could not start a session on", engine, error2);
1469
+ return false;
1470
+ }
1471
+ sessions.open(sessionId);
1472
+ return true;
1473
+ }
1474
+ };
1475
+ const composerInjected = () => ({
1476
+ controller,
1477
+ rpc,
1478
+ switcher,
1479
+ hooks: { snapshot: controller.store },
1480
+ t
1481
+ });
1482
+ scope2.effect(() => {
1483
+ return scope2.slots.register({
1484
+ name: "conversation.input.right",
1485
+ id: "loop-engine",
1486
+ order: 0,
1487
+ locale: NS,
1488
+ inject: composerInjected
1489
+ }, LoopEngineComposerSelect);
1490
+ }, "loop-engine: composer engine select");
1491
+ });
1492
+ }
1493
+ return module.exports; } });
1494
+ //# sourceMappingURL=client.js.map