lody 0.103.0 → 0.104.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.
@@ -1,38 +1,82 @@
1
+ import { R as RequestError, j as DEEPSEEK_HARNESS_BASE_URL_ENV, l as DEEPSEEK_HARNESS_API_KEY_ENV, n as ndJsonStream, o as AgentSideConnection, a as DEEPSEEK_HARNESS_AGENT_PRESETS, p as ACP_EXTENSION_DSH_VERSION, P as PROTOCOL_VERSION, q as DEEPSEEK_HARNESS_DEFAULT_MODEL, r as DEEPSEEK_HARNESS_PROVIDER } from "./chunks/acp-C0LiROfB.js";
1
2
  import { resolve, isAbsolute } from "node:path";
2
- import { o as object, s as string, b as boolean, c as array, l as literal, u as unknown, n as number, a as _enum, r as record } from "./chunks/schemas-WuyisFi9.js";
3
+ import { o as object$1, s as string, c as boolean, b as array, l as literal, u as unknown, n as number, a as _enum, r as record } from "./chunks/schemas-D_XLKCXC.js";
3
4
  import { S as SessionUsageAccumulator, L as LODY_EXTENSION_METHODS, e as supportsLodySubagentEvents, d as LODY_SUBAGENT_EVENT_METHOD } from "./chunks/subagent-events-BJ9JwZva.js";
4
5
  import { randomUUID, createHash } from "node:crypto";
5
6
  import { Readable, Writable } from "node:stream";
6
- import { j as DEEPSEEK_HARNESS_BASE_URL_ENV, l as DEEPSEEK_HARNESS_API_KEY_ENV, n as ndJsonStream, o as AgentSideConnection, a as DEEPSEEK_HARNESS_AGENT_PRESETS, R as RequestError, p as ACP_EXTENSION_DSH_VERSION, P as PROTOCOL_VERSION, q as DEEPSEEK_HARNESS_DEFAULT_MODEL, r as DEEPSEEK_HARNESS_PROVIDER } from "./chunks/acp-BzvviK-N.js";
7
7
  import { c as createPlanModeConfigOption, L as LODY_PLAN_MODE_CONFIG_ID } from "./chunks/plan-mode-D0D5cnMs.js";
8
8
  import { L as LodySubagentEmitter } from "./chunks/subagent-emitter-BsTuVPDw.js";
9
9
  import "node:url";
10
- const blockSchema = object({ type: string() }).passthrough();
11
- const resultSchema = object({
10
+ function nativeTurnId(turn) {
11
+ return `dsh-turn:${turn}`;
12
+ }
13
+ function object(value) {
14
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
15
+ }
16
+ function forkTarget(meta2) {
17
+ const lody = object(object(meta2)?.lody);
18
+ if (!lody || !Object.hasOwn(lody, "forkAtTurn"))
19
+ return void 0;
20
+ const target = object(lody.forkAtTurn);
21
+ if (!target || target.version !== 1 || target.turnId !== void 0 && (typeof target.turnId !== "string" || !/^dsh-turn:(0|[1-9]\d*)$/.test(target.turnId) || !Number.isSafeInteger(Number(target.turnId.slice("dsh-turn:".length)))))
22
+ throw RequestError.invalidParams(void 0, "invalid _meta.lody.forkAtTurn");
23
+ return target?.turnId;
24
+ }
25
+ function forkSnapshot(source, target) {
26
+ const events = source.events;
27
+ const end = target === void 0 ? events.length - 1 : events.findIndex((event) => event.type === "turn/end" && typeof event.data.turn === "number" && nativeTurnId(event.data.turn) === target);
28
+ if (target !== void 0 && end === -1)
29
+ throw RequestError.invalidParams(void 0, "fork turn is unknown or has not ended");
30
+ const prefix = events.slice(0, end + 1);
31
+ const lastTurn = [...prefix].reverse().find((event) => event.type === "turn/start" || event.type === "turn/end");
32
+ if (lastTurn?.type === "turn/start")
33
+ throw RequestError.invalidParams(void 0, "cannot fork an unfinished turn; select an earlier completed turn");
34
+ let agentPreset = source.header.agentPreset;
35
+ let selection;
36
+ for (const [index, event] of prefix.entries()) {
37
+ if (event.seq !== index)
38
+ throw RequestError.invalidParams(void 0, "source session has a non-contiguous log");
39
+ if (event.type === "agent-preset/selected" && typeof event.data.agentPreset === "string")
40
+ agentPreset = event.data.agentPreset;
41
+ if (event.type === "request/header") {
42
+ const config = object(object(event.data.header)?.config);
43
+ if (!config || typeof config.provider !== "string" || typeof config.model !== "string")
44
+ throw RequestError.invalidParams(void 0, "source request header has no model route");
45
+ selection = {
46
+ provider: config.provider,
47
+ model: config.model,
48
+ ...typeof config.reasoningEffort === "string" ? { reasoningEffort: config.reasoningEffort } : {}
49
+ };
50
+ }
51
+ }
52
+ return { sourceId: source.header.id, seed: structuredClone(prefix), agentPreset, selection };
53
+ }
54
+ const blockSchema = object$1({ type: string() }).passthrough();
55
+ const resultSchema = object$1({
12
56
  type: literal("tool-result"),
13
57
  toolCallId: string().min(1),
14
58
  content: array(blockSchema),
15
59
  isError: boolean().optional()
16
60
  });
17
- const callSchema = object({
61
+ const callSchema = object$1({
18
62
  callId: string().min(1),
19
63
  name: string().min(1),
20
64
  arguments: string()
21
65
  });
22
- const ptcSchema = object({
66
+ const ptcSchema = object$1({
23
67
  subCallId: string().min(1),
24
68
  name: string().min(1),
25
69
  arguments: unknown(),
26
70
  parentCallId: string(),
27
71
  rootCallId: string()
28
72
  });
29
- const locationSchema = object({ path: string(), line: number().int().positive().optional() });
30
- const viewSchema = object({
73
+ const locationSchema = object$1({ path: string(), line: number().int().positive().optional() });
74
+ const viewSchema = object$1({
31
75
  card: _enum(["generic", "terminal", "diff", "read", "search", "web"]),
32
76
  title: string().optional(),
33
77
  kind: _enum(["read", "edit", "delete", "move", "search", "execute", "fetch", "other"]).optional(),
34
78
  locations: array(locationSchema).optional(),
35
- diffs: array(object({ path: string(), oldText: string().nullable(), newText: string() })).optional(),
79
+ diffs: array(object$1({ path: string(), oldText: string().nullable(), newText: string() })).optional(),
36
80
  output: string().optional(),
37
81
  content: array(blockSchema).optional()
38
82
  }).passthrough();
@@ -163,8 +207,8 @@ class ToolCallBridge {
163
207
  }
164
208
  await this.start(call.callId, call.name, args);
165
209
  } else if (type === "tool/result") {
166
- const event = object({
167
- message: object({ content: array(resultSchema) }),
210
+ const event = object$1({
211
+ message: object$1({ content: array(resultSchema) }),
168
212
  meta: unknown().optional()
169
213
  }).passthrough().parse(data);
170
214
  for (const block of event.message.content) {
@@ -174,7 +218,7 @@ class ToolCallBridge {
174
218
  const call = ptcSchema.parse(data);
175
219
  await this.start(call.subCallId, call.name, call.arguments);
176
220
  if (type === "tool/ptc-dispatch") {
177
- const result = object({ content: array(blockSchema), isError: boolean() }).passthrough().parse(data);
221
+ const result = object$1({ content: array(blockSchema), isError: boolean() }).passthrough().parse(data);
178
222
  await this.finish(call.subCallId, result, result);
179
223
  }
180
224
  } else if (type === "turn/end") {
@@ -234,17 +278,17 @@ class HarnessUsageTracker {
234
278
  return this.accumulator.update(sessionId, String(seq), { [this.route.model]: usage });
235
279
  }
236
280
  }
237
- const questionSchema = object({
281
+ const questionSchema = object$1({
238
282
  id: string().refine((value) => value.trim().length > 0),
239
283
  question: string().min(1),
240
284
  header: string().optional(),
241
285
  detail: string().optional(),
242
- options: array(object({
286
+ options: array(object$1({
243
287
  label: string().min(1),
244
288
  description: string().optional()
245
289
  })).optional(),
246
290
  multiSelect: boolean().optional(),
247
- intent: object({ kind: literal("plan-review"), approve: string() }).optional()
291
+ intent: object$1({ kind: literal("plan-review"), approve: string() }).optional()
248
292
  });
249
293
  function failure(code, message) {
250
294
  return Object.assign(new Error(message), { name: "UserQuestionError", code });
@@ -364,7 +408,7 @@ class UserQuestionBridge {
364
408
  throw failure("ASK_ABORTED", "The user cancelled the question");
365
409
  if (response.action === "decline")
366
410
  throw failure("ASK_DECLINED", "The user declined the question");
367
- const accepted = object({
411
+ const accepted = object$1({
368
412
  action: literal("accept"),
369
413
  content: record(string(), unknown())
370
414
  }).safeParse(response);
@@ -409,11 +453,13 @@ const inject = [
409
453
  "llm",
410
454
  "permissionPresets",
411
455
  "sessionPersistence",
456
+ "sessions",
412
457
  "sessionQuery",
413
458
  "sessionTitle",
414
459
  "userQuestions"
415
460
  ];
416
461
  const LODY_CAPABILITIES = {
462
+ forkAtTurn: { version: 1 },
417
463
  subagentEvents: { version: 1 },
418
464
  sessionTitle: { version: 1 },
419
465
  compaction: { version: 1 },
@@ -1140,6 +1186,11 @@ function apply(ctx, rawConfig) {
1140
1186
  });
1141
1187
  });
1142
1188
  });
1189
+ const flushSession = async (session) => {
1190
+ const store = ctx.get("sessions");
1191
+ if (!store || !await store.flush(session))
1192
+ throw new Error("no session durability listener is available");
1193
+ };
1143
1194
  const settleAfterQuiescence = (record2, inflight) => {
1144
1195
  if (inflight.settlementStarted)
1145
1196
  return;
@@ -1150,6 +1201,7 @@ function apply(ctx, rawConfig) {
1150
1201
  await record2.agent.whenIdle();
1151
1202
  await record2.outputTail;
1152
1203
  await record2.tools.interrupt();
1204
+ await flushSession(record2.agent.session);
1153
1205
  }
1154
1206
  if (record2.inflight !== inflight)
1155
1207
  return;
@@ -1328,7 +1380,11 @@ function apply(ctx, rawConfig) {
1328
1380
  continue;
1329
1381
  await notify({
1330
1382
  sessionId: record2.agent.session.id,
1331
- update: { sessionUpdate: "agent_message_chunk", content }
1383
+ update: {
1384
+ sessionUpdate: "agent_message_chunk",
1385
+ content,
1386
+ ...typeof event.data.turn === "number" ? { _meta: { lody: { turnId: nativeTurnId(event.data.turn) } } } : {}
1387
+ }
1332
1388
  });
1333
1389
  }
1334
1390
  }, inflight);
@@ -1375,9 +1431,19 @@ function apply(ctx, rawConfig) {
1375
1431
  }
1376
1432
  });
1377
1433
  ctx.on("agent/inbox/claimed", ({ agent, message, turn }) => {
1378
- const inflight = ownedRecord(agent)?.inflight;
1379
- if (inflight && inflight.messageId === message.id)
1434
+ const record2 = ownedRecord(agent);
1435
+ const inflight = record2?.inflight;
1436
+ if (record2 && inflight && inflight.messageId === message.id) {
1380
1437
  inflight.turn = turn;
1438
+ enqueueNotification(record2, {
1439
+ sessionId: agent.session.id,
1440
+ update: {
1441
+ sessionUpdate: "agent_message_chunk",
1442
+ content: { type: "text", text: "" },
1443
+ _meta: { lody: { turnId: nativeTurnId(turn) } }
1444
+ }
1445
+ }, inflight);
1446
+ }
1381
1447
  });
1382
1448
  ctx.on("agent/error", ({ agent, turn, error }) => {
1383
1449
  const record2 = ownedRecord(agent);
@@ -1504,6 +1570,150 @@ function apply(ctx, rawConfig) {
1504
1570
  }
1505
1571
  return { configOptions: configOptions(record2) };
1506
1572
  };
1573
+ const createSession = async (params, fork) => {
1574
+ assertOpen();
1575
+ validateSessionParams(params);
1576
+ let catalog;
1577
+ try {
1578
+ catalog = await loadModelCatalog();
1579
+ } catch (error) {
1580
+ throw internalError(`failed to discover models: ${errorChain(error)}`);
1581
+ }
1582
+ const models = [...catalog.models];
1583
+ const initialSelection = fork?.selection ?? catalog.initialSelection;
1584
+ if (fork?.selection) {
1585
+ const model = await resolveHarnessModel(llm, initialSelection.provider, initialSelection.model);
1586
+ const index = models.findIndex((candidate) => candidate.provider === model.provider && candidate.id === model.id);
1587
+ if (index < 0)
1588
+ models.push(model);
1589
+ else
1590
+ models[index] = model;
1591
+ }
1592
+ const sessionId = randomUUID();
1593
+ const questions = new UserQuestionBridge(sessionId, (request) => conn.unstable_createElicitation(request), () => questionCapabilities);
1594
+ const initialModel = models.find((model) => model.provider === initialSelection.provider && model.id === initialSelection.model);
1595
+ if (!initialModel)
1596
+ throw internalError("initial model metadata is unavailable");
1597
+ const reasoningEffort = resolveReasoningEffort(initialModel, fork?.selection ? fork.selection.reasoningEffort : config.reasoningEffort);
1598
+ const selection = {
1599
+ current: {
1600
+ provider: initialSelection.provider,
1601
+ model: initialSelection.model,
1602
+ ...reasoningEffort ? { reasoningEffort } : {}
1603
+ }
1604
+ };
1605
+ const agentPresetOptions = (await ctx.agentPresets.list()).filter((preset) => preset.broken === void 0);
1606
+ const requestedPreset = fork?.agentPreset ?? ctx.agentPresets.defaultId;
1607
+ if (!agentPresetOptions.some((preset) => preset.id === requestedPreset)) {
1608
+ throw internalError(`default agent preset ${JSON.stringify(requestedPreset)} is unavailable`);
1609
+ }
1610
+ const mcpServerNames = reserveMcpServerNames(params.mcpServers, sessionId, activeMcpServerNames);
1611
+ let mountedPreset = requestedPreset;
1612
+ let handle;
1613
+ try {
1614
+ handle = await ctx.agents.create({
1615
+ sessionId,
1616
+ meta: {
1617
+ cwd: params.cwd,
1618
+ agentPreset: requestedPreset,
1619
+ ...fork ? { parentSession: fork.sourceId, isSeeded: true } : {}
1620
+ },
1621
+ ...fork ? { seed: fork.seed, inheritedEventCount: fork.seed.length } : {},
1622
+ agentOptions: {
1623
+ provider: initialSelection.provider,
1624
+ model: initialSelection.model
1625
+ },
1626
+ setup: async (agentContext) => {
1627
+ if (subagentEvents && !carrierKeyOf) {
1628
+ const scope = await agentContext.loader.import("@deepseek-ai/dsh-scope");
1629
+ if (typeof scope.carrierKeyOf !== "function")
1630
+ throw new Error("Harness scope identity API is unavailable");
1631
+ carrierKeyOf = scope.carrierKeyOf;
1632
+ }
1633
+ installModelSelection(agentContext, selection);
1634
+ agentContext.on("user-questions/request", (request, next) => {
1635
+ if (!request.agent || ownedRecord(request.agent)?.questions !== questions)
1636
+ return next();
1637
+ return questions.ask(request);
1638
+ });
1639
+ mountedPreset = (await ctx.agentPresets.mount(agentContext, requestedPreset)).id;
1640
+ await mountMcpServers(agentContext, params.mcpServers, mcpServerNames.names, params.cwd);
1641
+ }
1642
+ });
1643
+ } catch (error) {
1644
+ mcpServerNames.release();
1645
+ if (error instanceof RequestError)
1646
+ throw error;
1647
+ throw internalError(`failed to create session: ${errorChain(error)}`);
1648
+ }
1649
+ const dispose = async () => {
1650
+ questions.cancel();
1651
+ try {
1652
+ await handle.dispose();
1653
+ } finally {
1654
+ mcpServerNames.release();
1655
+ }
1656
+ };
1657
+ if (closed) {
1658
+ await dispose();
1659
+ throw internalError("connection closed during session/new");
1660
+ }
1661
+ let permissionMode;
1662
+ let permissionOptions;
1663
+ try {
1664
+ permissionMode = ctx.permissionPresets.current(handle.agent.session);
1665
+ permissionOptions = permissionState(ctx, permissionMode);
1666
+ } catch (error) {
1667
+ await dispose();
1668
+ throw error;
1669
+ }
1670
+ const record2 = {
1671
+ cwd: params.cwd,
1672
+ tools: new ToolCallBridge({
1673
+ cwd: params.cwd,
1674
+ lookup: (name2) => {
1675
+ const tools = handle.agent.ctx.get("tools");
1676
+ return tools?.get(name2, handle.agent);
1677
+ },
1678
+ content: (block) => assistantBlockToAcp(block, attachments),
1679
+ emit: (update) => notify({ sessionId, update }),
1680
+ warn: (message) => ctx.logger.warn(`acp-extension-dsh: ${message}`)
1681
+ }),
1682
+ questions,
1683
+ usage: new HarnessUsageTracker(!baseUrl || /^https:\/\/api\.deepseek\.com(?:\/v1)?\/?$/.test(baseUrl)),
1684
+ agent: handle.agent,
1685
+ dispose,
1686
+ selection,
1687
+ permissionMode,
1688
+ permissionOptions,
1689
+ agentPreset: mountedPreset,
1690
+ agentPresetOptions,
1691
+ models,
1692
+ started: fork?.seed.some((event) => event.type === "turn/start") ?? false,
1693
+ outputTail: Promise.resolve()
1694
+ };
1695
+ if (fork) {
1696
+ try {
1697
+ await flushSession(handle.agent.session);
1698
+ assertOpen();
1699
+ } catch (error) {
1700
+ let cleanupError;
1701
+ try {
1702
+ await dispose();
1703
+ } catch (failure2) {
1704
+ cleanupError = failure2;
1705
+ }
1706
+ throw internalError(`fork child ${sessionId} could not be committed: ${errorChain(error)}${cleanupError ? `; cleanup: ${errorChain(cleanupError)}` : ""}`);
1707
+ }
1708
+ }
1709
+ sessions.set(sessionId, record2);
1710
+ return {
1711
+ sessionId,
1712
+ modes: modeState(record2),
1713
+ configOptions: configOptions(record2),
1714
+ models: legacyModels(record2)
1715
+ };
1716
+ };
1507
1717
  const makeAgent = (connection) => {
1508
1718
  conn = connection;
1509
1719
  return {
@@ -1530,7 +1740,7 @@ function apply(ctx, rawConfig) {
1530
1740
  embeddedContext: false
1531
1741
  },
1532
1742
  mcpCapabilities: { http: true },
1533
- sessionCapabilities: { close: {} },
1743
+ sessionCapabilities: { close: {}, fork: {} },
1534
1744
  _meta: { lody: LODY_CAPABILITIES }
1535
1745
  },
1536
1746
  authMethods: []
@@ -1539,121 +1749,36 @@ function apply(ctx, rawConfig) {
1539
1749
  authenticate(_params) {
1540
1750
  return Promise.resolve();
1541
1751
  },
1542
- async newSession(params) {
1752
+ newSession(params) {
1753
+ return createSession(params);
1754
+ },
1755
+ async unstable_forkSession(params) {
1543
1756
  assertOpen();
1544
- validateSessionParams(params);
1545
- let catalog;
1546
- try {
1547
- catalog = await loadModelCatalog();
1548
- } catch (error) {
1549
- throw internalError(`failed to discover models: ${errorChain(error)}`);
1550
- }
1551
- const { models, initialSelection } = catalog;
1552
- const sessionId = randomUUID();
1553
- const questions = new UserQuestionBridge(sessionId, (request) => conn.unstable_createElicitation(request), () => questionCapabilities);
1554
- const initialModel = models.find((model) => model.provider === initialSelection.provider && model.id === initialSelection.model);
1555
- if (!initialModel)
1556
- throw internalError("initial model metadata is unavailable");
1557
- const reasoningEffort = resolveReasoningEffort(initialModel, config.reasoningEffort);
1558
- const selection = {
1559
- current: {
1560
- provider: initialSelection.provider,
1561
- model: initialSelection.model,
1562
- ...reasoningEffort ? { reasoningEffort } : {}
1563
- }
1757
+ const target = forkTarget(params._meta);
1758
+ const creation = {
1759
+ cwd: params.cwd,
1760
+ mcpServers: params.mcpServers ?? [],
1761
+ additionalDirectories: params.additionalDirectories
1564
1762
  };
1565
- const agentPresetOptions = (await ctx.agentPresets.list()).filter((preset) => preset.broken === void 0);
1566
- const requestedPreset = ctx.agentPresets.defaultId;
1567
- if (!agentPresetOptions.some((preset) => preset.id === requestedPreset)) {
1568
- throw internalError(`default agent preset ${JSON.stringify(requestedPreset)} is unavailable`);
1569
- }
1570
- const mcpServerNames = reserveMcpServerNames(params.mcpServers, sessionId, activeMcpServerNames);
1571
- let mountedPreset = requestedPreset;
1572
- let handle;
1763
+ validateSessionParams(creation);
1764
+ const query = ctx.get("sessionQuery");
1765
+ if (!query)
1766
+ throw internalError("Harness session query is unavailable");
1767
+ let source;
1573
1768
  try {
1574
- handle = await ctx.agents.create({
1575
- sessionId,
1576
- meta: { cwd: params.cwd, agentPreset: requestedPreset },
1577
- agentOptions: {
1578
- provider: initialSelection.provider,
1579
- model: initialSelection.model
1580
- },
1581
- setup: async (agentContext) => {
1582
- if (subagentEvents && !carrierKeyOf) {
1583
- const scope = await agentContext.loader.import("@deepseek-ai/dsh-scope");
1584
- if (typeof scope.carrierKeyOf !== "function")
1585
- throw new Error("Harness scope identity API is unavailable");
1586
- carrierKeyOf = scope.carrierKeyOf;
1587
- }
1588
- installModelSelection(agentContext, selection);
1589
- agentContext.on("user-questions/request", (request, next) => {
1590
- if (!request.agent || ownedRecord(request.agent)?.questions !== questions)
1591
- return next();
1592
- return questions.ask(request);
1593
- });
1594
- mountedPreset = (await ctx.agentPresets.mount(agentContext, requestedPreset)).id;
1595
- await mountMcpServers(agentContext, params.mcpServers, mcpServerNames.names, params.cwd);
1596
- }
1597
- });
1769
+ source = await query.observeSession(params.sessionId);
1598
1770
  } catch (error) {
1599
- mcpServerNames.release();
1600
- if (error instanceof RequestError)
1601
- throw error;
1602
- throw internalError(`failed to create session: ${errorChain(error)}`);
1603
- }
1604
- const dispose = async () => {
1605
- questions.cancel();
1606
- try {
1607
- await handle.dispose();
1608
- } finally {
1609
- mcpServerNames.release();
1610
- }
1611
- };
1612
- if (closed) {
1613
- await dispose();
1614
- throw internalError("connection closed during session/new");
1771
+ throw invalidParams(`fork source unavailable: ${errorChain(error)}`);
1615
1772
  }
1616
- let permissionMode;
1617
- let permissionOptions;
1773
+ let snapshot;
1618
1774
  try {
1619
- permissionMode = ctx.permissionPresets.current(handle.agent.session);
1620
- permissionOptions = permissionState(ctx, permissionMode);
1621
- } catch (error) {
1622
- await dispose();
1623
- throw error;
1775
+ if (source.header.id !== params.sessionId)
1776
+ throw invalidParams("fork source identity mismatch");
1777
+ snapshot = forkSnapshot(source, target);
1778
+ } finally {
1779
+ source[Symbol.dispose]();
1624
1780
  }
1625
- const record2 = {
1626
- cwd: params.cwd,
1627
- tools: new ToolCallBridge({
1628
- cwd: params.cwd,
1629
- lookup: (name2) => {
1630
- const tools = handle.agent.ctx.get("tools");
1631
- return tools?.get(name2, handle.agent);
1632
- },
1633
- content: (block) => assistantBlockToAcp(block, attachments),
1634
- emit: (update) => notify({ sessionId, update }),
1635
- warn: (message) => ctx.logger.warn(`acp-extension-dsh: ${message}`)
1636
- }),
1637
- questions,
1638
- usage: new HarnessUsageTracker(!baseUrl || /^https:\/\/api\.deepseek\.com(?:\/v1)?\/?$/.test(baseUrl)),
1639
- agent: handle.agent,
1640
- dispose,
1641
- selection,
1642
- permissionMode,
1643
- permissionOptions,
1644
- agentPreset: mountedPreset,
1645
- agentPresetOptions,
1646
- models,
1647
- started: false,
1648
- outputTail: Promise.resolve()
1649
- };
1650
- sessions.set(sessionId, record2);
1651
- return {
1652
- sessionId,
1653
- modes: modeState(record2),
1654
- configOptions: configOptions(record2),
1655
- models: legacyModels(record2)
1656
- };
1781
+ return createSession(creation, snapshot);
1657
1782
  },
1658
1783
  setSessionMode(params) {
1659
1784
  const record2 = requireSession(params.sessionId);