@ferris1225/pi-subagents 4.2.13 → 4.3.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.
package/src/setup.ts CHANGED
@@ -1,28 +1,30 @@
1
1
  /**
2
2
  * Interactive configuration wizard for /subagents-setup.
3
3
  *
4
- * The wizard stays one level deep and exposes only what most users touch:
5
- * which agents run and the model and thinking strength each runs on.
6
- * Everything else (agent scope, idle timeout, result lines, notifications) is
7
- * config-file-only; model failures hand directly to the current main model,
8
- * and thinking defaults to capability-aware Auto.
4
+ * The wizard stays one level deep: which agents run, then a model and an
5
+ * optional thinking override per agent. Role thinking defaults apply until
6
+ * the user picks a level. Everything else (agent scope, idle timeout, result
7
+ * lines) is config-file-only.
9
8
  */
10
9
 
11
10
  import { stat } from "node:fs/promises";
12
11
  import type { Api, Model } from "@earendil-works/pi-ai";
13
12
  import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
14
- import { discoverAgents } from "./agents.ts";
15
13
  import {
14
+ AGENT_PROFILES,
16
15
  BUILTIN_AGENT_NAMES,
17
16
  DEFAULT_CONFIG,
18
17
  DEFAULT_ENABLED_AGENTS,
19
- DEFAULT_THINKING_LEVEL,
20
- type SubagentsConfig,
21
- type ThinkingLevel,
18
+ REQUIRED_ENABLED_AGENTS,
19
+ agentProfile,
22
20
  errorMessage,
23
21
  getConfigPath,
24
22
  loadConfig,
23
+ roleThinkingLevel,
25
24
  saveConfig,
25
+ withRequiredAgents,
26
+ type SubagentsConfig,
27
+ type ThinkingLevel,
26
28
  } from "./config.ts";
27
29
  import {
28
30
  CURRENT_MAIN_MODEL,
@@ -37,15 +39,31 @@ import {
37
39
  } from "./models.ts";
38
40
  import { promptSelectMany, promptSelectOne } from "./ui.ts";
39
41
 
40
- /** Short, selection-friendly descriptions for the built-in agents. */
41
- const MODULE_HINTS: Record<string, string> = {
42
- explorer: "read-only codebase recon (fast, read-only tools)",
43
- executor: "implement / fix / clean up / docs sync / merge results (full tools)",
42
+ const THINKING_LEVEL_HINTS: Record<ThinkingLevel, string> = {
43
+ off: "no reasoning tokens",
44
+ minimal: "minimal reasoning",
45
+ low: "light reasoning",
46
+ medium: "balanced reasoning",
47
+ high: "deep reasoning",
48
+ xhigh: "extra-deep reasoning",
49
+ max: "strongest reasoning",
44
50
  };
45
51
 
52
+ function agentPickerItems(): Array<{ value: string; label: string; description: string }> {
53
+ return BUILTIN_AGENT_NAMES.map((name) => {
54
+ const profile = AGENT_PROFILES[name];
55
+ const required = (REQUIRED_ENABLED_AGENTS as readonly string[]).includes(name);
56
+ return {
57
+ value: name,
58
+ label: required ? `${name} (always on)` : name,
59
+ description: `${profile.summary} — ${profile.remark}`,
60
+ };
61
+ });
62
+ }
63
+
46
64
  function moduleLabel(name: string): string {
47
- const hint = MODULE_HINTS[name];
48
- return hint ? `${name} — ${hint}` : name;
65
+ const profile = agentProfile(name);
66
+ return profile ? `${name} — ${profile.summary}` : name;
49
67
  }
50
68
 
51
69
  async function configExists(configPath: string): Promise<boolean> {
@@ -61,14 +79,23 @@ async function pickEnabledAgents(
61
79
  ctx: ExtensionCommandContext,
62
80
  current: readonly string[],
63
81
  ): Promise<string[] | undefined> {
64
- const items = BUILTIN_AGENT_NAMES.map((name) => ({ value: name, label: moduleLabel(name) }));
65
- return promptSelectMany(
82
+ const picked = await promptSelectMany(
66
83
  ctx,
67
- "Enable which sub-agents?",
68
- "Space toggles • Enter confirms • Esc returns to settings",
69
- items,
84
+ "Which agents should run?",
85
+ "Each line is a role and its job. All three stay on. Space toggles • Enter confirms • Esc back",
86
+ agentPickerItems(),
70
87
  current,
71
88
  );
89
+ if (picked === undefined) return undefined;
90
+ const enabled = withRequiredAgents(picked);
91
+ const forced = REQUIRED_ENABLED_AGENTS.filter((name) => !picked.includes(name));
92
+ if (forced.length > 0) {
93
+ ctx.ui.notify(
94
+ `pi-subagents: ${forced.join(", ")} stay enabled — the shipped team stays on.`,
95
+ "info",
96
+ );
97
+ }
98
+ return enabled;
72
99
  }
73
100
 
74
101
  async function pickConfiguredModel(
@@ -86,7 +113,7 @@ async function pickConfiguredModel(
86
113
  return promptSelectOne(
87
114
  ctx,
88
115
  title,
89
- `Type to filter by provider, model, capability, or thinking level • ↑/↓ • Enter selects • Esc ${escNote}`,
116
+ `Type to filter by provider, model, or capability • ↑/↓ • Enter selects • Esc ${escNote}`,
90
117
  items,
91
118
  configuredRef ?? CURRENT_MAIN_MODEL,
92
119
  );
@@ -98,34 +125,11 @@ async function pickAgentModel(
98
125
  currentRef: string | undefined,
99
126
  escNote = "cancels this setup pass",
100
127
  ): Promise<string | undefined> {
101
- return pickConfiguredModel(ctx, `Model for "${agentName}"?`, currentRef, escNote);
128
+ const profile = agentProfile(agentName);
129
+ const duty = profile ? ` — ${profile.summary}` : "";
130
+ return pickConfiguredModel(ctx, `Model for ${agentName}${duty}?`, currentRef, escNote);
102
131
  }
103
132
 
104
- const AUTO_THINKING = "__auto_thinking__";
105
-
106
- function actualAgentThinkingDefault(
107
- ctx: ExtensionCommandContext,
108
- config: SubagentsConfig,
109
- agentName: string,
110
- ): ThinkingLevel {
111
- const { agents } = discoverAgents(ctx.cwd, {
112
- scope: config.agentScope,
113
- enabledNames: config.enabledAgents,
114
- projectTrusted: ctx.isProjectTrusted(),
115
- });
116
- return agents.find((agent) => agent.name === agentName)?.thinking ?? DEFAULT_THINKING_LEVEL;
117
- }
118
-
119
- const THINKING_LEVEL_HINTS: Record<ThinkingLevel, string> = {
120
- off: "no reasoning tokens",
121
- minimal: "minimal reasoning",
122
- low: "light reasoning",
123
- medium: "balanced reasoning",
124
- high: "deep reasoning",
125
- xhigh: "extra-deep reasoning",
126
- max: "strongest reasoning",
127
- };
128
-
129
133
  function effectiveModelForChoice(
130
134
  ctx: ExtensionCommandContext,
131
135
  choice: string,
@@ -134,41 +138,37 @@ function effectiveModelForChoice(
134
138
  return findModelByRef(availableModelsInScope(ctx), choice);
135
139
  }
136
140
 
137
- /** Auto is the default. Manual rows are exactly the levels Pi exposes for the
138
- * selected model; unsupported xhigh/max entries never appear. */
141
+ /** Role default is the first row. Picking it clears a stored override. */
139
142
  async function pickAgentStrength(
140
143
  ctx: ExtensionCommandContext,
141
144
  agentName: string,
142
145
  model: Model<Api> | undefined,
143
146
  current: ThinkingLevel | undefined,
144
- agentDefault: ThinkingLevel,
145
147
  escNote = "cancels this setup pass",
146
- ): Promise<ThinkingLevel | typeof AUTO_THINKING | undefined> {
148
+ ): Promise<ThinkingLevel | undefined> {
147
149
  const supported = supportedThinkingLevels(model);
148
- const automatic = resolveThinkingLevel(model, agentDefault);
149
- // No model metadata, or a non-reasoning model whose only valid value is off:
150
- // Auto is already the complete and least surprising choice.
151
- if (supported.length <= 1) return AUTO_THINKING;
150
+ const roleDefault = resolveThinkingLevel(model, roleThinkingLevel(agentName));
151
+ if (supported.length <= 1) return roleDefault;
152
152
 
153
- const currentEffective = current ? resolveThinkingLevel(model, current) : undefined;
153
+ const currentEffective = current ? resolveThinkingLevel(model, current) : roleDefault;
154
154
  const modelName = model ? modelRef(model) : "current main model";
155
- const options = [
156
- {
157
- value: AUTO_THINKING,
158
- label: `auto ${automatic} for ${modelName}${current === undefined ? " (current, recommended)" : " (recommended)"}`,
159
- },
160
- ...supported.map((level) => ({
155
+ const options = supported.map((level) => {
156
+ const tags = [
157
+ level === roleDefault ? "role default" : "",
158
+ current !== undefined && currentEffective === level ? "current" : "",
159
+ ].filter(Boolean);
160
+ return {
161
161
  value: level,
162
- label: `${level} — ${THINKING_LEVEL_HINTS[level]}${current !== undefined && currentEffective === level ? " (current)" : ""}`,
163
- })),
164
- ];
162
+ label: `${level} — ${THINKING_LEVEL_HINTS[level]}${tags.length ? ` (${tags.join(", ")})` : ""}`,
163
+ };
164
+ });
165
165
  return promptSelectOne(
166
166
  ctx,
167
- `Thinking for "${agentName}"?`,
168
- `Only levels supported by ${modelName} are shown • Enter selects • Esc ${escNote}`,
167
+ `Thinking for ${agentName}?`,
168
+ `${agentName} defaults to ${roleDefault} on ${modelName} • Enter selects • Esc ${escNote}`,
169
169
  options,
170
- current === undefined ? AUTO_THINKING : currentEffective,
171
- ) as Promise<ThinkingLevel | typeof AUTO_THINKING | undefined>;
170
+ currentEffective,
171
+ ) as Promise<ThinkingLevel | undefined>;
172
172
  }
173
173
 
174
174
  async function pickAgentToConfigure(
@@ -182,19 +182,24 @@ async function pickAgentToConfigure(
182
182
  return promptSelectOne(
183
183
  ctx,
184
184
  "Configure which agent?",
185
- "Type to filter • ↑/↓ • Enter selects • Esc returns to settings",
186
- enabledAgents.map((name) => ({ value: name, label: moduleLabel(name) })),
185
+ "Name, then what it owns • ↑/↓ • Enter selects • Esc returns to settings",
186
+ enabledAgents.map((name) => {
187
+ const profile = agentProfile(name);
188
+ return {
189
+ value: name,
190
+ label: moduleLabel(name),
191
+ description: profile?.remark,
192
+ };
193
+ }),
187
194
  );
188
195
  }
189
196
 
190
197
  interface ConfiguredAgentChoice {
191
198
  name: string;
192
199
  model: string;
193
- strength: ThinkingLevel | typeof AUTO_THINKING;
200
+ strength: ThinkingLevel;
194
201
  }
195
202
 
196
- /** Configure one agent while preserving the UI back stack: thinking → model →
197
- * agent selection. Esc from agent selection ends this configuration pass. */
198
203
  async function configureOneAgent(
199
204
  ctx: ExtensionCommandContext,
200
205
  config: SubagentsConfig,
@@ -202,6 +207,8 @@ async function configureOneAgent(
202
207
  while (true) {
203
208
  const name = await pickAgentToConfigure(ctx, config.enabledAgents);
204
209
  if (name === undefined) return undefined;
210
+ const profile = agentProfile(name);
211
+ if (profile) ctx.ui.notify(`${name}: ${profile.remark}`, "info");
205
212
 
206
213
  while (true) {
207
214
  const modelChoice = await pickAgentModel(
@@ -217,7 +224,6 @@ async function configureOneAgent(
217
224
  name,
218
225
  model,
219
226
  config.agentThinkingLevels[name],
220
- actualAgentThinkingDefault(ctx, config, name),
221
227
  "returns to model selection",
222
228
  );
223
229
  if (strength === undefined) continue;
@@ -231,12 +237,43 @@ function keepAgentEntries<T>(record: Record<string, T>, enabled: readonly string
231
237
  return Object.fromEntries(Object.entries(record).filter(([name]) => keep.has(name)));
232
238
  }
233
239
 
240
+ function applyThinkingChoice(
241
+ levels: Record<string, ThinkingLevel>,
242
+ agentName: string,
243
+ strength: ThinkingLevel,
244
+ ): Record<string, ThinkingLevel> {
245
+ const next = { ...levels };
246
+ if (strength === roleThinkingLevel(agentName)) delete next[agentName];
247
+ else next[agentName] = strength;
248
+ return next;
249
+ }
250
+
251
+ async function introduceSetup(ctx: ExtensionCommandContext): Promise<boolean> {
252
+ const lines = BUILTIN_AGENT_NAMES.map((name) => {
253
+ const profile = AGENT_PROFILES[name];
254
+ const required = (REQUIRED_ENABLED_AGENTS as readonly string[]).includes(name) ? " · always on" : "";
255
+ return `${name} — ${profile.summary}${required}. ${profile.remark}`;
256
+ });
257
+ ctx.ui.notify(
258
+ `pi-subagents: ${lines.join(" ")} Pick a model for each role next. Thinking defaults per role (scout low, artisan high, steward medium); change it on a role when you want.`,
259
+ "info",
260
+ );
261
+ const choice = await ctx.ui.select("How to configure pi-subagents", [
262
+ "Continue — pick a model for each role (thinking has a role default you can change later)",
263
+ ]);
264
+ return choice !== undefined;
265
+ }
266
+
234
267
  async function runFullSetup(ctx: ExtensionCommandContext, configPath: string, base: SubagentsConfig): Promise<boolean> {
268
+ if (!(await introduceSetup(ctx))) return false;
269
+
235
270
  const enabled = await pickEnabledAgents(ctx, base.enabledAgents);
236
271
  if (enabled === undefined) return false;
237
272
 
238
273
  let agentModels = keepAgentEntries(base.agentModels, enabled);
239
274
  for (const agentName of enabled) {
275
+ const profile = agentProfile(agentName);
276
+ if (profile) ctx.ui.notify(`${agentName}: ${profile.remark}`, "info");
240
277
  const choice = await pickAgentModel(ctx, agentName, agentModels[agentName]);
241
278
  if (choice === undefined) return false;
242
279
  agentModels = applyAgentModelChoice(agentModels, agentName, choice);
@@ -244,27 +281,27 @@ async function runFullSetup(ctx: ExtensionCommandContext, configPath: string, ba
244
281
 
245
282
  const next: SubagentsConfig = {
246
283
  enabledAgents: enabled,
247
- // The wizard surfaces every built-in, so an untoggled one was seen and
248
- // deliberately left off — record them all as known.
249
284
  knownAgents: [...BUILTIN_AGENT_NAMES],
250
285
  agentModels,
251
- // Full setup returns every agent to capability-aware Auto thinking.
252
- agentThinkingLevels: {},
286
+ agentThinkingLevels: keepAgentEntries(base.agentThinkingLevels, enabled),
253
287
  maxResultLines: base.maxResultLines,
254
288
  agentScope: base.agentScope,
255
289
  idleTimeoutSec: base.idleTimeoutSec,
256
290
  };
257
291
  await saveConfig(next, configPath);
258
- ctx.ui.notify(`pi-subagents configured with Auto thinking. Saved to ${configPath}`, "info");
292
+ ctx.ui.notify(
293
+ `pi-subagents saved to ${configPath}. Role thinking defaults apply; open Configure an agent to change one.`,
294
+ "info",
295
+ );
259
296
  return true;
260
297
  }
261
298
 
262
299
  async function runMenu(ctx: ExtensionCommandContext, configPath: string, config: SubagentsConfig): Promise<void> {
263
300
  while (true) {
264
301
  const choice = await ctx.ui.select("pi-subagents settings", [
265
- "Enable/disable agents",
266
- "Configure an agent (model + thinking)",
267
- "Full re-setup",
302
+ "Enable/disable agents — scout, artisan, and steward stay on",
303
+ "Configure an agent model and thinking, with its job on the row",
304
+ "Full re-setup — walk through the team and pick models again",
268
305
  ]);
269
306
  if (choice === undefined) return;
270
307
  if (choice.startsWith("Full")) {
@@ -281,33 +318,16 @@ async function runMenu(ctx: ExtensionCommandContext, configPath: string, config:
281
318
  const enabled = await pickEnabledAgents(ctx, config.enabledAgents);
282
319
  if (enabled === undefined) continue;
283
320
  next.enabledAgents = enabled;
284
- // A newly enabled role inherits explorer's configured model and
285
- // thinking level, so the file reflects what it will actually run
286
- // instead of silently falling back to the current main model: these
287
- // roles do light migration-grade work on the fast explorer lane.
288
- for (const agent of enabled) {
289
- if (agent === "explorer" || config.enabledAgents.includes(agent)) continue;
290
- if (!next.agentModels[agent] && config.agentModels.explorer) {
291
- next.agentModels[agent] = config.agentModels.explorer;
292
- }
293
- if (!next.agentThinkingLevels[agent] && config.agentThinkingLevels.explorer) {
294
- next.agentThinkingLevels[agent] = config.agentThinkingLevels.explorer;
295
- }
296
- }
297
321
  next.agentModels = keepAgentEntries(next.agentModels, enabled);
298
322
  next.agentThinkingLevels = keepAgentEntries(next.agentThinkingLevels, enabled);
299
323
  } else {
300
- // Per-agent loop: thinking Esc returns to that agent's model picker;
301
- // model Esc returns to the agent picker; agent-picker Esc saves completed
302
- // choices and returns to this settings menu.
303
324
  let configuredAny = false;
304
325
  while (true) {
305
326
  const picked = await configureOneAgent(ctx, next);
306
327
  if (!picked) break;
307
328
  configuredAny = true;
308
329
  next.agentModels = applyAgentModelChoice(next.agentModels, picked.name, picked.model);
309
- if (picked.strength === AUTO_THINKING) delete next.agentThinkingLevels[picked.name];
310
- else next.agentThinkingLevels[picked.name] = picked.strength;
330
+ next.agentThinkingLevels = applyThinkingChoice(next.agentThinkingLevels, picked.name, picked.strength);
311
331
  }
312
332
  if (!configuredAny) continue;
313
333
  await saveConfig(next, configPath);
@@ -20,8 +20,8 @@ import {
20
20
  } from "./agents.ts";
21
21
  import { type CompletionMessageItem } from "./completion.ts";
22
22
  import {
23
- DEFAULT_THINKING_LEVEL,
24
23
  loadConfig,
24
+ roleThinkingLevel,
25
25
  type SubagentsConfig,
26
26
  type ThinkingLevel,
27
27
  } from "./config.ts";
@@ -265,11 +265,8 @@ export interface ResumeReservation {
265
265
  }
266
266
 
267
267
  /** The dispatcher's full internal entry point; the public tool surface only
268
- * uses the first four parameters plus the per-call `thinking` request. */
268
+ * uses the first four parameters. */
269
269
  export interface StartBackgroundOptions {
270
- /** Reasoning strength this dispatch asked for; the user's manual
271
- * `/subagents-setup` choice still outranks it (see resolveDispatchModelRoute). */
272
- thinking?: ThinkingLevel;
273
270
  /** Resume path only: the thread whose retained context continues. */
274
271
  existingThread?: SubagentThread;
275
272
  appendedObjectiveOnResume?: boolean;
@@ -307,7 +304,6 @@ export function resolveDispatchModelRoute(
307
304
  agent: AgentConfig,
308
305
  config: SubagentsConfig,
309
306
  ctx: ExtensionContext,
310
- requestedThinking?: ThinkingLevel,
311
307
  ): DispatchModelRoute {
312
308
  const availableModels = availableModelsInScope(ctx);
313
309
  const mainRef = currentModelRef(ctx);
@@ -316,11 +312,10 @@ export function resolveDispatchModelRoute(
316
312
  mainRef,
317
313
  availableRefs: availableModels.map(modelRef),
318
314
  });
319
- // agentThinkingLevels only holds a level the user picked by hand in
320
- // /subagents-setup (missing = Auto), so that deliberate setting outranks the
321
- // dispatching model's per-call guess, which in turn outranks frontmatter.
315
+ // A `/subagents-setup` override wins; otherwise the role default. No
316
+ // per-call or frontmatter thinking.
322
317
  const preferred =
323
- config.agentThinkingLevels[agent.name] ?? requestedThinking ?? agent.thinking ?? DEFAULT_THINKING_LEVEL;
318
+ config.agentThinkingLevels[agent.name] ?? roleThinkingLevel(agent.name);
324
319
  const thinkingLevelForModel = (ref?: string): ThinkingLevel => {
325
320
  const model = ref === mainRef && ctx.model
326
321
  ? ctx.model
@@ -372,7 +367,6 @@ export function createBackgroundDispatcher(options: BackgroundDispatcherOptions)
372
367
  startOptions: StartBackgroundOptions = {},
373
368
  ): Promise<SingleResult> => {
374
369
  const {
375
- thinking,
376
370
  existingThread,
377
371
  appendedObjectiveOnResume = false,
378
372
  environment,
@@ -396,7 +390,7 @@ export function createBackgroundDispatcher(options: BackgroundDispatcherOptions)
396
390
  const agent = resolveLiveAgentTools(discoveredAgent);
397
391
  if (isolation === "worktree" && !isWorktreeCapableAgent(agent)) {
398
392
  return {
399
- ...failedStartResult(agentName, task, `Agent "${agentName}" is read-only; worktree isolation is available only to write-capable agents such as executor.`),
393
+ ...failedStartResult(agentName, task, `Agent "${agentName}" is read-only; worktree isolation is available only to write-capable agents such as artisan.`),
400
394
  isolation,
401
395
  };
402
396
  }
@@ -431,8 +425,7 @@ export function createBackgroundDispatcher(options: BackgroundDispatcherOptions)
431
425
  const worktreeGroup = worktree ? worktreeGroupId(worktree) : undefined;
432
426
  // A resume re-runs at the strength its dispatch asked for, so the retained
433
427
  // request survives generations (and, via the durable record, restarts).
434
- const requestedThinking = thinking ?? existingThread?.requestedThinkingLevel;
435
- const resolvedRoute = resolveDispatchModelRoute(agent, runConfig, runCtx, requestedThinking);
428
+ const resolvedRoute = resolveDispatchModelRoute(agent, runConfig, runCtx);
436
429
  // Isolation is a persistent system-level invariant, not a one-shot task
437
430
  // prefix: resumes and main-model
438
431
  // handoffs all keep the same worktree boundary.
@@ -493,7 +486,6 @@ export function createBackgroundDispatcher(options: BackgroundDispatcherOptions)
493
486
  thread.cwd = originalCwd;
494
487
  thread.executionCwd = executionCwd;
495
488
  thread.thinkingLevel = thinkingLevel;
496
- thread.requestedThinkingLevel = requestedThinking;
497
489
  thread.isolation = isolation;
498
490
  thread.worktree = worktree;
499
491
  thread.state = "queued";
@@ -517,7 +509,6 @@ export function createBackgroundDispatcher(options: BackgroundDispatcherOptions)
517
509
  cwd: originalCwd,
518
510
  executionCwd,
519
511
  thinkingLevel,
520
- requestedThinkingLevel: requestedThinking,
521
512
  isolation,
522
513
  worktree,
523
514
  state: "queued",
@@ -557,7 +548,7 @@ export function createBackgroundDispatcher(options: BackgroundDispatcherOptions)
557
548
  let activeIdleTimeoutMs = runConfig.idleTimeoutSec * 1000;
558
549
  try {
559
550
  const startConfig = await loadConfig(runtime.configPath);
560
- const resolvedStart = resolveDispatchModelRoute(agent, startConfig, runCtx, requestedThinking);
551
+ const resolvedStart = resolveDispatchModelRoute(agent, startConfig, runCtx);
561
552
  activeRoute = isolation === "worktree"
562
553
  ? { ...resolvedStart, agent: withWorktreeSystemPrompt(resolvedStart.agent) }
563
554
  : resolvedStart;
@@ -1182,9 +1173,6 @@ function createRestoredThread(
1182
1173
  cwd: record.cwd,
1183
1174
  executionCwd: record.executionCwd,
1184
1175
  ...(record.thinkingLevel ? { thinkingLevel: record.thinkingLevel as ThinkingLevel } : {}),
1185
- ...(record.requestedThinkingLevel
1186
- ? { requestedThinkingLevel: record.requestedThinkingLevel as ThinkingLevel }
1187
- : {}),
1188
1176
  isolation: record.isolation,
1189
1177
  worktree,
1190
1178
  state,