mixdog 1.3.2 → 1.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -8
- package/scripts/verify-runtime-dependency-versions.mjs +158 -0
- package/src/agents/reviewer/AGENT.md +5 -7
- package/src/agents/reviewer/agent.json +1 -1
- package/src/defaults/shipped-history.json +4 -0
- package/src/defaults/skills/browser-use/SKILL.md +6 -3
- package/src/defaults/skills/local-provider/SKILL.md +33 -6
- package/src/rules/lead/LEAD.md +5 -8
- package/src/rules/shared/45-destructive.md +5 -1
- package/src/rules/shared/60-verification.md +6 -4
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +4 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-max-tokens.mjs +38 -11
- package/src/runtime/agent/orchestrator/providers/anthropic-messages.mjs +15 -3
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +17 -4
- package/src/runtime/agent/orchestrator/providers/anthropic.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/cursor-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/custom-provider-config.mjs +14 -1
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/registry.mjs +10 -0
- package/src/runtime/agent/orchestrator/providers/wire-gateway.mjs +13 -1
- package/src/runtime/agent/orchestrator/runtime-core/goal-runtime.mjs +5 -0
- package/src/runtime/agent/orchestrator/runtime-core/goal-turns.mjs +10 -1
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog.mjs +40 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +32 -11
- package/src/runtime/agent/orchestrator/runtime-core/workflow.mjs +6 -3
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +13 -0
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +68 -12
- package/src/runtime/agent/orchestrator/session/compact/continuation.mjs +15 -6
- package/src/runtime/agent/orchestrator/session/compact/execution-tail.mjs +31 -8
- package/src/runtime/agent/orchestrator/session/compact/messages.mjs +44 -0
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +117 -19
- package/src/runtime/agent/orchestrator/session/compact/text-utils.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/compact/user-message-kind.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/human-gate/delegation.mjs +147 -137
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +37 -74
- package/src/runtime/agent/orchestrator/session/human-gate/requests.mjs +0 -2
- package/src/runtime/agent/orchestrator/session/human-gate/run-policy.mjs +2 -2
- package/src/runtime/agent/orchestrator/session/loop/fresh-context.mjs +13 -7
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/continuation.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/empty-nudge.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/output-limit.mjs +62 -13
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +22 -6
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +7 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +12 -20
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/call-prep.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/dispatch.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/manager/agent-listing-notice.mjs +102 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-queue.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-session.mjs +13 -1
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-execute.mjs +24 -15
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-prepare.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-steering-drain.mjs +1 -0
- package/src/runtime/agent/orchestrator/session/manager/idle-cleanup.mjs +32 -1
- package/src/runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs +17 -1
- package/src/runtime/agent/orchestrator/session/manager/pending-message-entry.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/manager/prompt-utils.mjs +36 -0
- package/src/runtime/agent/orchestrator/session/manager/session-crud.mjs +28 -9
- package/src/runtime/agent/orchestrator/session/manager/session-prompt-composition.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/manager/session-record.mjs +7 -5
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +7 -3
- package/src/runtime/agent/orchestrator/session/pre-send-compact.mjs +10 -1
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +7 -4
- package/src/runtime/agent/orchestrator/session/runtime-user-context.mjs +3 -1
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/stale-sweep.mjs +5 -4
- package/src/runtime/agent/orchestrator/session/store/sweep/sub-agent-retention.mjs +140 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-plan.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-record.mjs +7 -2
- package/src/runtime/agent/orchestrator/session/store/sweep/sweep-row.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/store-summary-catalog.mjs +76 -0
- package/src/runtime/agent/orchestrator/session/store-summary-reader.mjs +33 -1
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.d.mts +5 -0
- package/src/runtime/agent/orchestrator/session/store-summary-visibility.mjs +37 -0
- package/src/runtime/agent/orchestrator/session/store.mjs +1 -0
- package/src/runtime/agent/orchestrator/tools/builtin/advisory-lock.mjs +18 -7
- package/src/runtime/agent/orchestrator/tools/builtin/bash-tool/backgrounded-result.mjs +2 -0
- package/src/runtime/agent/orchestrator/tools/builtin/git-command-tool.mjs +127 -20
- package/src/runtime/agent/orchestrator/tools/builtin/git-worktree-tool.mjs +557 -0
- package/src/runtime/agent/orchestrator/tools/builtin/lib/shell-job-records.mjs +6 -0
- package/src/runtime/agent/orchestrator/tools/builtin/shell-jobs.mjs +8 -2
- package/src/runtime/attachments/legacy-office.mjs +110 -0
- package/src/runtime/attachments/prompt-restore.mjs +70 -0
- package/src/runtime/attachments/store.mjs +60 -3
- package/src/runtime/effort-judge/judge-client.mjs +61 -14
- package/src/runtime/effort-judge/model-install.mjs +34 -2
- package/src/runtime/memory/lib/memory-chunk-quality.mjs +14 -2
- package/src/runtime/office/portable/portable-soffice.mjs +132 -30
- package/src/runtime/shared/agent-avatar-sprites.mjs +23 -8
- package/src/runtime/shared/agent-avatar.mjs +3 -2
- package/src/runtime/shared/agent-room-host.d.mts +31 -0
- package/src/runtime/shared/agent-room-host.mjs +58 -0
- package/src/runtime/shared/bot-hops.mjs +16 -11
- package/src/runtime/shared/llm/usage-rollup.mjs +4 -383
- package/src/runtime/shared/redact-directories.mjs +18 -0
- package/src/runtime/shared/remove-directory.mjs +28 -0
- package/src/runtime/shared/session-sidebar-host.d.mts +11 -2
- package/src/runtime/shared/session-sidebar-host.mjs +16 -3
- package/src/runtime/shared/tool-execution-contract.mjs +4 -0
- package/src/runtime/shared/tool-work-units.mjs +12 -9
- package/src/runtime/shared/turn-snapshot.mjs +233 -122
- package/src/runtime/shared/user-data-guard.mjs +51 -19
- package/src/runtime/shared/worktrees/activity-gate.mjs +209 -227
- package/src/runtime/shared/worktrees/contract.mjs +11 -3
- package/src/runtime/shared/worktrees/maintenance.mjs +11 -2
- package/src/runtime/shared/worktrees/manager.mjs +419 -52
- package/src/runtime/shared/worktrees/registry.mjs +3 -1
- package/src/runtime/shared/worktrees/tool-host.mjs +39 -0
- package/src/runtime/tidy/process.mjs +41 -8
- package/src/runtime/tidy/resolve.mjs +10 -7
- package/src/session-runtime/agent-home-delivery.mjs +73 -91
- package/src/session-runtime/agent-profile-changes.mjs +16 -0
- package/src/session-runtime/agent-room-delivery.mjs +2 -63
- package/src/session-runtime/agent-task-sessions.mjs +194 -64
- package/src/session-runtime/agent-tool-routing.mjs +49 -4
- package/src/session-runtime/boot/apis.mjs +3 -0
- package/src/session-runtime/boot/facade.mjs +5 -6
- package/src/session-runtime/boot/tools.mjs +23 -1
- package/src/session-runtime/held-requests.mjs +20 -25
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +5 -22
- package/src/session-runtime/model-recency.mjs +1 -0
- package/src/session-runtime/provider-models/row-hydration.mjs +8 -1
- package/src/session-runtime/quick-model-rows/model-meta.mjs +2 -0
- package/src/session-runtime/quick-model-rows/provider-rows.mjs +7 -1
- package/src/session-runtime/runtime-review-api.mjs +4 -1
- package/src/session-runtime/services/agent-tool/close-flow.mjs +14 -2
- package/src/session-runtime/services/agent-tool/execute.mjs +6 -1
- package/src/session-runtime/services/agent-tool/job-views/agent-list.mjs +44 -20
- package/src/session-runtime/services/agent-tool/render.mjs +3 -1
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -0
- package/src/session-runtime/services/agent-tool/tool-def.mjs +1 -1
- package/src/session-runtime/services/provider-admin.mjs +12 -2
- package/src/session-runtime/services/worktree-access.mjs +27 -0
- package/src/session-runtime/session-hooks.mjs +9 -17
- package/src/session-runtime/settings-builtin-tools-api.mjs +2 -0
- package/src/session-runtime/setup-tool/executor.mjs +4 -0
- package/src/session-runtime/setup-tool/settings-contract.mjs +3 -0
- package/src/session-runtime/tool-policy/agent-profile-fold.mjs +98 -14
- package/src/session-runtime/tool-policy/policy-stage.mjs +23 -5
- package/src/session-runtime/tool-policy-refresh.mjs +1 -0
- package/src/session-runtime/tool-surface.mjs +9 -5
- package/src/session-runtime/turn/session-ops.mjs +8 -0
- package/src/session-runtime/turn/turn-run.mjs +5 -1
- package/src/session-runtime/usage-stats-api.mjs +1 -1
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +10 -2
- package/src/session-runtime/workflow-agents-api/agent-route.mjs +39 -17
- package/src/session-runtime/workspace/transition-steps.mjs +1 -18
- package/src/session-runtime/workspace/transitions.mjs +279 -67
- package/src/session-runtime/workspace/worktree-tool.mjs +194 -0
- package/src/standalone/daemon-lag-profiler.mjs +3 -1
- package/src/standalone/daemon-session-control.mjs +140 -23
- package/src/standalone/daemon-telemetry.mjs +9 -0
- package/src/standalone/daemon.mjs +5 -0
- package/src/standalone/local-session-runtime.mjs +11 -2
- package/src/standalone/session-protocol.mjs +1 -0
- package/src/standalone/session-runtime-inline-host/boot-loaders.mjs +2 -0
- package/src/standalone/session-service/agent-route-follow.mjs +69 -0
- package/src/standalone/session-service/session-calls/session-turns.mjs +33 -4
- package/src/standalone/session-service.mjs +10 -0
- package/src/standalone/session-tool-output.mjs +1 -0
- package/src/standalone/staged-import.mjs +47 -0
- package/src/tui/App.jsx +2 -0
- package/src/tui/app/message-selector.mjs +15 -2
- package/src/tui/app/model-options.mjs +16 -2
- package/src/tui/app/model-picker.mjs +2 -1
- package/src/tui/app/route-pickers.mjs +3 -1
- package/src/tui/dist/index.mjs +403 -210
- package/src/tui/paste-attachments.mjs +0 -1
- package/src/tui/paste-text-policy.mjs +4 -5
- package/src/tui/session/agent-job-feed/execution-delivery.mjs +4 -1
- package/src/tui/session/notice-surface.mjs +3 -0
- package/src/tui/session/session-api/intake/abort.mjs +33 -17
- package/src/tui/session/session-api/intake/rewind.mjs +39 -4
- package/src/tui/session/session-api/routes-agent-definitions.mjs +1 -0
- package/src/tui/session/tool-approval.mjs +11 -48
- package/src/vendor/statusline/src/gateway/claude-current.mjs +0 -58
- package/src/vendor/statusline/src/gateway/route-meta.mjs +1 -361
- package/src/vendor/statusline/src/gateway/session-routes.mjs +0 -55
- package/src/session-runtime/room-member-gate.mjs +0 -61
- package/src/vendor/statusline/scripts/lib/gateway-settings.mjs +0 -285
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// changes (a switched workflow or mode, moved tool gates, changed shipped
|
|
3
3
|
// rules) in where the provider cache is cold anyway.
|
|
4
4
|
import { sessionHasConversationMessages } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
5
|
+
import { ORCHESTRATION_MODES } from '../../runtime/shared/orchestration.mjs';
|
|
6
|
+
import { orchestrationModeFromPrompt } from '../../runtime/agent/orchestrator/session/manager/orchestration-mode-switch-notice.mjs';
|
|
5
7
|
import { promptRulesRevision } from '../../runtime/agent/orchestrator/session/manager/rules-cache.mjs';
|
|
6
8
|
import { isAgentOwner } from '../../runtime/agent/orchestrator/agent-owner.mjs';
|
|
7
9
|
import { AGENT_MODE, sessionModeOf } from '../../runtime/agent/orchestrator/session/agent-mode.mjs';
|
|
@@ -15,6 +17,7 @@ import {
|
|
|
15
17
|
agentMcpToolPermission,
|
|
16
18
|
connectorPolicyAgentOf,
|
|
17
19
|
} from '../../runtime/agent/orchestrator/mcp/agent-connectors.mjs';
|
|
20
|
+
import { agentListEntries } from '../../runtime/agent/orchestrator/session/manager/prompt-utils.mjs';
|
|
18
21
|
import { markToolSurfaceMigrated } from '../../runtime/agent/orchestrator/session/loop/tool-exposure-migration.mjs';
|
|
19
22
|
import {
|
|
20
23
|
agentProfileRevision,
|
|
@@ -50,6 +53,27 @@ const promptPrefix = (session) =>
|
|
|
50
53
|
const rulesStale = (session) =>
|
|
51
54
|
sessionModeOf(session) === AGENT_MODE && session.rulesRevision !== promptRulesRevision();
|
|
52
55
|
|
|
56
|
+
// Before session-local modes were used by profile refreshes, changing the
|
|
57
|
+
// roster could replace a coding Lead's mode rules with the configured default
|
|
58
|
+
// while leaving its selected mode intact. This is not a normal mode overlay:
|
|
59
|
+
// repair only a known generated mismatch, with no user switch still pending.
|
|
60
|
+
function orchestrationRecoveryNeeded(session) {
|
|
61
|
+
if (
|
|
62
|
+
!session?.promptIdentity ||
|
|
63
|
+
session.promptIdentity.skipAgentRules ||
|
|
64
|
+
isAgentOwner(session) ||
|
|
65
|
+
sessionModeOf(session) === AGENT_MODE ||
|
|
66
|
+
!ORCHESTRATION_MODES.includes(session.orchestrationMode) ||
|
|
67
|
+
session.workflowOverlay ||
|
|
68
|
+
session.orchestrationModeOverlay ||
|
|
69
|
+
session.pendingWorkflowId !== undefined ||
|
|
70
|
+
session.pendingOrchestrationMode !== undefined
|
|
71
|
+
)
|
|
72
|
+
return false;
|
|
73
|
+
const presented = orchestrationModeFromPrompt(session);
|
|
74
|
+
return presented !== null && presented !== session.orchestrationMode;
|
|
75
|
+
}
|
|
76
|
+
|
|
53
77
|
// Changes the prompt does not carry yet: a workflow switched mid-conversation,
|
|
54
78
|
// a bot's tool gates that moved, or shipped rules a release changed.
|
|
55
79
|
const foldPending = (session) =>
|
|
@@ -130,6 +154,35 @@ function stageLiveToolChanges({ liveDeniedTools, modelStandaloneTools }, session
|
|
|
130
154
|
return true;
|
|
131
155
|
}
|
|
132
156
|
|
|
157
|
+
// A coding Lead keeps `agent` whichever agents exist (workflow.mjs
|
|
158
|
+
// workflowDisallowsAgentTool); a denial a session recorded under the older
|
|
159
|
+
// rule, because no agent was enabled, is lifted as the live policy no longer
|
|
160
|
+
// holds it: the tool becomes reachable by deferred loading and the next
|
|
161
|
+
// turn's deferred_tools_delta names it. Nothing in the request prefix moves.
|
|
162
|
+
// Returns true when the session changed.
|
|
163
|
+
function liftAgentDenial({ liveDeniedTools, modelStandaloneTools }, session) {
|
|
164
|
+
const disallowed = (session.disallowedTools || []).map(String);
|
|
165
|
+
const overlayDenied = (session.workflowOverlay?.deniedTools || []).includes('agent');
|
|
166
|
+
if (!disallowed.includes('agent') && !overlayDenied) return false;
|
|
167
|
+
if (liveDeniedTools(session, session.workflow).includes('agent')) return false;
|
|
168
|
+
const known = new Map(schemaTools(session).map((tool) => [toolName(tool), tool]));
|
|
169
|
+
if (!known.has('agent')) {
|
|
170
|
+
const fresh = modelStandaloneTools().filter((tool) => toolName(tool) === 'agent');
|
|
171
|
+
if (!fresh.length) return false;
|
|
172
|
+
session.deferredToolCatalog = [...(session.deferredToolCatalog || []), ...fresh];
|
|
173
|
+
known.set('agent', fresh[0]);
|
|
174
|
+
}
|
|
175
|
+
session.disallowedTools = disallowed.filter((name) => name !== 'agent');
|
|
176
|
+
if (overlayDenied) {
|
|
177
|
+
session.workflowOverlay.deniedTools = session.workflowOverlay.deniedTools.filter((name) => name !== 'agent');
|
|
178
|
+
}
|
|
179
|
+
mergePendingDeferredToolDelta(session, {
|
|
180
|
+
added: [{ name: 'agent', description: known.get('agent')?.description || '' }],
|
|
181
|
+
});
|
|
182
|
+
session.updatedAt = Date.now();
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
|
|
133
186
|
export function createAgentProfileFold({
|
|
134
187
|
getSession,
|
|
135
188
|
getConfig,
|
|
@@ -189,9 +242,11 @@ export function createAgentProfileFold({
|
|
|
189
242
|
* anything it embeds changed; a delegated worker keeps its prompt. The core
|
|
190
243
|
* is rebuilt like a workflow switch's (the session's own workflow, the
|
|
191
244
|
* workspace slices the model was told) and replaces the stored one, so the
|
|
192
|
-
* next turn sends it with one provider cache break
|
|
193
|
-
* turn
|
|
194
|
-
*
|
|
245
|
+
* next turn sends it with one provider cache break. The prompt is not re-embedded
|
|
246
|
+
* per turn, but currentAgents() does resolve the agent catalog at each
|
|
247
|
+
* turn's preparation (for the listing reminder). That rewrite is immediate
|
|
248
|
+
* (one tagged cache break) and takes every pending fold with it
|
|
249
|
+
* (foldPrompt), moving all stamps.
|
|
195
250
|
* What is not an edit never touches the prefix: a bot thread's feature gates
|
|
196
251
|
* and connectors are staged live (stageLiveToolChanges), and shipped rules a
|
|
197
252
|
* release changed wait silently; both are folded in at the next cold point
|
|
@@ -210,22 +265,29 @@ export function createAgentProfileFold({
|
|
|
210
265
|
const workflowConfig = configForSession(getConfig(), promptWorkflowOf(session)?.id, promptMode(session));
|
|
211
266
|
const { leadPromptParts, summary: workflow } = activeWorkflowContext(workflowConfig, getDataDir());
|
|
212
267
|
const roster = leadRosterRevision(leadPartsFor(session, leadPromptParts));
|
|
213
|
-
const
|
|
268
|
+
const recoverMode = orchestrationRecoveryNeeded(session);
|
|
269
|
+
// A coding Lead hears of its agents through the listing reminder each
|
|
270
|
+
// turn carries (agent-listing-notice.mjs), never a rewritten prompt;
|
|
271
|
+
// syncAgentListing only lifts a stale `agent` denial.
|
|
272
|
+
const edited =
|
|
273
|
+
recoverMode || session.agentProfileRevision !== revision || (agentMode && session.agentRosterRevision !== roster);
|
|
214
274
|
// At a turn's start its own turn is the one counted; nothing runs yet.
|
|
215
275
|
const busy = () => getSession?.() !== session || (trigger !== 'turn' && turnInFlight(session));
|
|
216
276
|
if (busy()) {
|
|
217
277
|
agentProfilePending = true;
|
|
218
278
|
return false;
|
|
219
279
|
}
|
|
220
|
-
const toolsChanged =
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
280
|
+
const toolsChanged = agentMode
|
|
281
|
+
? stageLiveToolChanges({ liveDeniedTools, modelStandaloneTools }, session, workflow, {
|
|
282
|
+
edited: session.agentProfileRevision !== revision,
|
|
283
|
+
})
|
|
284
|
+
: trigger === 'resume' && syncAgentListing(session);
|
|
225
285
|
if (!edited) return (trigger === 'resume' && (await foldPromptIfCold())) || toolsChanged;
|
|
226
286
|
// A coding session from before profile stamps keeps its prompt when it
|
|
227
287
|
// is reopened; a saved edit still reaches it.
|
|
228
|
-
if (session.agentProfileRevision === undefined && trigger === 'resume' && !agentMode)
|
|
288
|
+
if (session.agentProfileRevision === undefined && trigger === 'resume' && !agentMode && !recoverMode) {
|
|
289
|
+
return toolsChanged;
|
|
290
|
+
}
|
|
229
291
|
if (foldPending(session)) {
|
|
230
292
|
await foldPrompt(session, AGENT_PROFILE_INTENT);
|
|
231
293
|
return true;
|
|
@@ -241,7 +303,7 @@ export function createAgentProfileFold({
|
|
|
241
303
|
if (staged.core === presentedBp3Core(session)) return toolsChanged;
|
|
242
304
|
rewriteConversationBp3Core(session, staged.core);
|
|
243
305
|
// The request prefix changed: one cache break, tagged on the next send.
|
|
244
|
-
markToolSurfaceMigrated(session, AGENT_PROFILE_INTENT);
|
|
306
|
+
markToolSurfaceMigrated(session, recoverMode ? PROMPT_FOLD_INTENT : AGENT_PROFILE_INTENT);
|
|
245
307
|
return true;
|
|
246
308
|
}
|
|
247
309
|
|
|
@@ -254,12 +316,34 @@ export function createAgentProfileFold({
|
|
|
254
316
|
if (session?.id && sessionModeOf(session) === AGENT_MODE && !Array.isArray(session.agentConnectorTools)) {
|
|
255
317
|
session.agentConnectorTools = connectorTools(session, schemaTools(session).map(toolName));
|
|
256
318
|
}
|
|
257
|
-
if (agentProfilePending) {
|
|
319
|
+
if (agentProfilePending || orchestrationRecoveryNeeded(session)) {
|
|
258
320
|
agentProfilePending = false;
|
|
259
321
|
changed = await refreshAgentProfile({ trigger: 'turn' });
|
|
260
322
|
}
|
|
261
|
-
|
|
323
|
+
changed = (await foldPromptIfCold()) || changed;
|
|
324
|
+
return syncAgentListing(session) || changed;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// A coding Lead hears of its agents through the agent list reminder.
|
|
328
|
+
const codingLead = (session) =>
|
|
329
|
+
Boolean(session?.id && session.promptIdentity && !isAgentOwner(session) && sessionModeOf(session) !== AGENT_MODE);
|
|
330
|
+
|
|
331
|
+
/** A coding Lead keeps `agent` reachable (liftAgentDenial). Returns true
|
|
332
|
+
* when the session changed. */
|
|
333
|
+
function syncAgentListing(session) {
|
|
334
|
+
return codingLead(session) && liftAgentDenial({ liveDeniedTools, modelStandaloneTools }, session);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/** The agents a coding Lead may delegate to now, as its prompt would list
|
|
338
|
+
* them: the turn's input to the agent list reminder (manager/
|
|
339
|
+
* agent-listing-notice.mjs); undefined for any other session. */
|
|
340
|
+
function currentAgents() {
|
|
341
|
+
const session = getSession?.();
|
|
342
|
+
if (!codingLead(session)) return undefined;
|
|
343
|
+
const config = configForSession(getConfig(), session.workflow?.id, currentMode(session));
|
|
344
|
+
const { leadPromptParts } = activeWorkflowContext(config, getDataDir());
|
|
345
|
+
return agentListEntries(leadPartsFor(session, leadPromptParts).agentCatalogContext) || [];
|
|
262
346
|
}
|
|
263
347
|
|
|
264
|
-
return { refreshAgentProfile, applyPendingAgentProfile };
|
|
348
|
+
return { refreshAgentProfile, applyPendingAgentProfile, currentAgents };
|
|
265
349
|
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
// Staging and applying the tool/prompt policy a config gives a Lead session:
|
|
2
2
|
// the tools it is denied, its BP1 rules and its BP3 core.
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
toSessionWorkflowMeta,
|
|
5
|
+
workflowDisallowsAgentTool,
|
|
6
|
+
} from '../../runtime/agent/orchestrator/runtime-core/workflow.mjs';
|
|
4
7
|
import {
|
|
5
8
|
applyDeferredToolSurface,
|
|
6
9
|
filterDisallowedTools,
|
|
@@ -20,7 +23,10 @@ import { finalizeSessionToolList } from '../../runtime/agent/orchestrator/sessio
|
|
|
20
23
|
import { isAgentOwner } from '../../runtime/agent/orchestrator/agent-owner.mjs';
|
|
21
24
|
import { AGENT_MODE, sessionModeOf } from '../../runtime/agent/orchestrator/session/agent-mode.mjs';
|
|
22
25
|
import { unusedModelEditToolName } from '../../runtime/shared/edit-tool-dialect.mjs';
|
|
23
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
presentedAgentCatalogSlice,
|
|
28
|
+
withPresentedWorkspaceSlices,
|
|
29
|
+
} from '../../runtime/agent/orchestrator/session/manager/prompt-utils.mjs';
|
|
24
30
|
import { leadPartsFor, rewriteSystemHeading, toolNames } from './surface-helpers.mjs';
|
|
25
31
|
|
|
26
32
|
export function createPolicyStage({
|
|
@@ -34,12 +40,14 @@ export function createPolicyStage({
|
|
|
34
40
|
activeWorkflowContext,
|
|
35
41
|
}) {
|
|
36
42
|
// The tools `session` is denied now: its caller's denials, the feature gates
|
|
37
|
-
// as they stand, and
|
|
43
|
+
// as they stand, and an agent-mode Lead's agent tool when its workflow
|
|
44
|
+
// delegates to no one (a coding Lead keeps it: workflow.mjs
|
|
45
|
+
// workflowDisallowsAgentTool).
|
|
38
46
|
function liveDeniedTools(session, workflow) {
|
|
39
47
|
return [
|
|
40
48
|
...session.callerDisallowedTools,
|
|
41
49
|
...featureDisallowedTools(),
|
|
42
|
-
...(workflow
|
|
50
|
+
...(workflowDisallowsAgentTool(workflow, { agentMode: sessionModeOf(session) === AGENT_MODE }) ? ['agent'] : []),
|
|
43
51
|
]
|
|
44
52
|
.map((name) => String(name || ''))
|
|
45
53
|
.filter(Boolean);
|
|
@@ -100,7 +108,17 @@ export function createPolicyStage({
|
|
|
100
108
|
} = activeWorkflowContext(config, getDataDir());
|
|
101
109
|
const sessionMode = sessionModeOf(session);
|
|
102
110
|
const agentMode = sessionMode === AGENT_MODE;
|
|
103
|
-
|
|
111
|
+
// A coding Lead's conversation keeps the agent list it was built with, as
|
|
112
|
+
// it keeps the workspace slices: agents switched on or off since reach it
|
|
113
|
+
// as reminders on top of that list (agent-listing-notice.mjs). A slice
|
|
114
|
+
// that is not one generated list is rebuilt as before.
|
|
115
|
+
const presentedCatalog = conversation && !agentMode ? presentedAgentCatalogSlice(session) : null;
|
|
116
|
+
const leadWorkflowParts = ownerIsAgent
|
|
117
|
+
? {}
|
|
118
|
+
: {
|
|
119
|
+
...leadPartsFor(session, leadPromptParts),
|
|
120
|
+
...(presentedCatalog !== null ? { agentCatalogContext: presentedCatalog } : {}),
|
|
121
|
+
};
|
|
104
122
|
const denied = liveDeniedTools(session, workflow);
|
|
105
123
|
|
|
106
124
|
const baseRules =
|
|
@@ -101,5 +101,6 @@ export function createToolPolicyRefresh({
|
|
|
101
101
|
applyPendingSessionSwitches: switches.applyPendingSessionSwitches,
|
|
102
102
|
refreshAgentProfile: profile.refreshAgentProfile,
|
|
103
103
|
applyPendingAgentProfile: profile.applyPendingAgentProfile,
|
|
104
|
+
currentAgents: profile.currentAgents,
|
|
104
105
|
};
|
|
105
106
|
}
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
import { workflowDisallowsAgentTool } from '../runtime/agent/orchestrator/runtime-core/workflow.mjs';
|
|
18
18
|
import { promptWorkflowOf } from '../runtime/agent/orchestrator/session/manager/workflow-switch-notice.mjs';
|
|
19
19
|
import { configuredOrchestrationMode } from '../runtime/shared/orchestration.mjs';
|
|
20
|
+
import { isAgentModeSession } from '../runtime/agent/orchestrator/session/agent-mode.mjs';
|
|
20
21
|
|
|
21
22
|
export function createToolSurface({
|
|
22
23
|
mgr,
|
|
@@ -36,15 +37,18 @@ export function createToolSurface({
|
|
|
36
37
|
}) {
|
|
37
38
|
let preSessionSurface = null;
|
|
38
39
|
|
|
39
|
-
// A
|
|
40
|
-
//
|
|
41
|
-
//
|
|
40
|
+
// A coding Lead keeps `agent` whichever agents exist (the agents reach it as
|
|
41
|
+
// a listing reminder); Solo still offers it (deferred) for explicit user
|
|
42
|
+
// requests. An agent-mode Lead keeps its frozen capability once live (the
|
|
43
|
+
// workflow its prompt was built with, even after a mid-conversation switch)
|
|
44
|
+
// and a new one gets it with current agents.
|
|
42
45
|
function workflowAllowsAgents() {
|
|
43
46
|
const session = getSession();
|
|
47
|
+
const agentMode = isAgentModeSession(session || {});
|
|
44
48
|
if (session?.id || session?.workflow || session?.orchestrationMode) {
|
|
45
|
-
return !workflowDisallowsAgentTool(promptWorkflowOf(session));
|
|
49
|
+
return !workflowDisallowsAgentTool(promptWorkflowOf(session), { agentMode });
|
|
46
50
|
}
|
|
47
|
-
return (delegatableAgentIds?.(getConfig(), cfgMod.getPluginData?.() || dataDir).length ?? 1) > 0;
|
|
51
|
+
return !agentMode || (delegatableAgentIds?.(getConfig(), cfgMod.getPluginData?.() || dataDir).length ?? 1) > 0;
|
|
48
52
|
}
|
|
49
53
|
|
|
50
54
|
function modelStandaloneTools() {
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { normalizeToolMode } from '../../runtime/agent/orchestrator/runtime-core/effort.mjs';
|
|
6
6
|
import { interruptTaskWaitForSession } from '../../runtime/agent/orchestrator/session/task-wait-control.mjs';
|
|
7
7
|
import { markPendingGoalReminder } from '../../runtime/agent/orchestrator/runtime-core/goal-reminder.mjs';
|
|
8
|
+
import { rearmLateDeferredTools } from '../../runtime/agent/orchestrator/runtime-core/tool-catalog.mjs';
|
|
8
9
|
|
|
9
10
|
export function createSessionOps(deps) {
|
|
10
11
|
const {
|
|
@@ -55,6 +56,7 @@ export function createSessionOps(deps) {
|
|
|
55
56
|
if (!session?.id) return null;
|
|
56
57
|
const result = await mgr.rewindSessionMessagesTo?.(session.id, options);
|
|
57
58
|
if (!result) return null;
|
|
59
|
+
if (options.dryRun === true) return result;
|
|
58
60
|
setSession(mgr.getSession(session.id) || session);
|
|
59
61
|
invalidateContextStatusCache();
|
|
60
62
|
return result;
|
|
@@ -96,6 +98,12 @@ export function createSessionOps(deps) {
|
|
|
96
98
|
} catch {
|
|
97
99
|
/* best-effort: a Goal reminder must never break manual compact */
|
|
98
100
|
}
|
|
101
|
+
// The same compaction strips late MCP tool announcements from older turns.
|
|
102
|
+
try {
|
|
103
|
+
rearmLateDeferredTools(getSession());
|
|
104
|
+
} catch {
|
|
105
|
+
/* best-effort: a tool reminder must never break manual compact */
|
|
106
|
+
}
|
|
99
107
|
if (options.recoverAgent === true) recoverAgentWorkers();
|
|
100
108
|
invalidateContextStatusCache();
|
|
101
109
|
return result;
|
|
@@ -28,6 +28,7 @@ export function createTurnRunner(deps) {
|
|
|
28
28
|
completeTurnSnapshotForTurn = completeTurnSnapshot,
|
|
29
29
|
turnCleanupSettleMs = 2_000,
|
|
30
30
|
getConfig = () => null,
|
|
31
|
+
currentAgents,
|
|
31
32
|
} = deps;
|
|
32
33
|
const transcript = createTurnTranscript(deps);
|
|
33
34
|
const openTurn = createTurnOpener({
|
|
@@ -81,7 +82,10 @@ export function createTurnRunner(deps) {
|
|
|
81
82
|
plannedToolCalls(session0, options),
|
|
82
83
|
getCurrentCwd(),
|
|
83
84
|
options.prefetch || null,
|
|
84
|
-
|
|
85
|
+
// The agents enabled now (coding Leads), asked for each user turn
|
|
86
|
+
// the ask prepares, for its agent list reminder
|
|
87
|
+
// (manager/agent-listing-notice.mjs).
|
|
88
|
+
{ ...callbacks, agentsNow: currentAgents }
|
|
85
89
|
);
|
|
86
90
|
} finally {
|
|
87
91
|
releaseWebSearchUsage?.();
|
|
@@ -203,7 +203,7 @@ export function createUsageStatsApi({
|
|
|
203
203
|
// beyond a clock captured before the import started.
|
|
204
204
|
const now = Date.now();
|
|
205
205
|
const period = usagePeriodFor(options, now);
|
|
206
|
-
// The rollup query runs off the event loop (usage-
|
|
206
|
+
// The rollup query runs off the event loop (usage-ledger-worker.mjs).
|
|
207
207
|
const rollup = await store.rollupAsync(usageRollupQuery(period));
|
|
208
208
|
// The ledger returns the same rollup object while nothing was committed
|
|
209
209
|
// (and while a rolling window lost no record), so identical back-to-back
|
|
@@ -420,7 +420,7 @@ function customAvatarImages(dir, avatar) {
|
|
|
420
420
|
// from Mixy's identity folder: bots/mixy once the bot store is active,
|
|
421
421
|
// agents/lead before (mixyIdentityDir, agent-store.mjs). Saved empty, the
|
|
422
422
|
// file goes. `dataDirOf()` resolves the data folder on each call.
|
|
423
|
-
function createLeadIdentityApi(dataDirOf) {
|
|
423
|
+
function createLeadIdentityApi(dataDirOf, mainRoute) {
|
|
424
424
|
const leadDir = () => mixyIdentityDir(dataDirOf());
|
|
425
425
|
function readLeadFile(file) {
|
|
426
426
|
return readTextOrEmpty(join(leadDir(), file));
|
|
@@ -462,6 +462,8 @@ function createLeadIdentityApi(dataDirOf) {
|
|
|
462
462
|
route: readMixyRoute(dataDirOf()),
|
|
463
463
|
};
|
|
464
464
|
}
|
|
465
|
+
// The route Mixy's thread follows: its own, else Main's (an override cleared).
|
|
466
|
+
const getLeadHomeRoute = () => readMixyRoute(dataDirOf()) ?? mainRoute();
|
|
465
467
|
// Mixy's name and face, chosen in the 대표 에이전트 dialog or its profile:
|
|
466
468
|
// a name '' and an avatar null go back to the defaults; absent keys are kept.
|
|
467
469
|
function saveLeadIdentity(payload = {}) {
|
|
@@ -511,6 +513,7 @@ function createLeadIdentityApi(dataDirOf) {
|
|
|
511
513
|
getLeadAgentBody: () => readLeadFile('AGENT.md'),
|
|
512
514
|
saveLeadAgentBody: (text) => saveLeadFile('AGENT.md', text),
|
|
513
515
|
getLeadStatus,
|
|
516
|
+
getLeadHomeRoute,
|
|
514
517
|
saveLeadIdentity,
|
|
515
518
|
setLeadCreated,
|
|
516
519
|
// Mixy's connector policy, in its agent.json (`next` null removes it).
|
|
@@ -932,11 +935,15 @@ export function createAgentEditorApi(deps) {
|
|
|
932
935
|
getLeadAgentBody,
|
|
933
936
|
saveLeadAgentBody,
|
|
934
937
|
getLeadStatus,
|
|
938
|
+
getLeadHomeRoute,
|
|
935
939
|
saveLeadIdentity,
|
|
936
940
|
setLeadCreated,
|
|
937
941
|
getLeadConnectorPolicy,
|
|
938
942
|
setLeadConnectorPolicy,
|
|
939
|
-
} = createLeadIdentityApi(
|
|
943
|
+
} = createLeadIdentityApi(
|
|
944
|
+
() => resolveDataDir(deps),
|
|
945
|
+
() => normalizeWorkflowRoute(deps.resolveRoute(getConfig(), {}))
|
|
946
|
+
);
|
|
940
947
|
|
|
941
948
|
// The agent's connector policy (see runtime/.../mcp/agent-connectors.mjs),
|
|
942
949
|
// or null when its definition has none: every connector is on. Read as the
|
|
@@ -979,6 +986,7 @@ export function createAgentEditorApi(deps) {
|
|
|
979
986
|
getLeadAgentBody,
|
|
980
987
|
saveLeadAgentBody,
|
|
981
988
|
getLeadStatus,
|
|
989
|
+
getLeadHomeRoute,
|
|
982
990
|
setLeadCreated,
|
|
983
991
|
saveLeadIdentity,
|
|
984
992
|
saveAgentDefinition,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isDeepStrictEqual } from 'node:util';
|
|
1
2
|
import { clean } from '../../runtime/agent/orchestrator/runtime-core/session-text.mjs';
|
|
2
3
|
import { hasOwn } from '../../runtime/shared/object.mjs';
|
|
3
4
|
import { isHiddenAgent } from '../../runtime/agent/orchestrator/internal-agents.mjs';
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
withAgentDisabled,
|
|
11
12
|
} from '../../runtime/shared/agent-route-config.mjs';
|
|
12
13
|
import { agentEditorId, resolveDataDir } from './shared.mjs';
|
|
14
|
+
import { publishAgentRouteChange } from '../agent-profile-changes.mjs';
|
|
13
15
|
import {
|
|
14
16
|
isStoreBot,
|
|
15
17
|
readBotRoute,
|
|
@@ -101,21 +103,38 @@ export function createAgentRouteApi(deps) {
|
|
|
101
103
|
saveConfigAndAdopt(canonicalizeAgentRouteStorage(nextConfig));
|
|
102
104
|
}
|
|
103
105
|
|
|
106
|
+
// The route a bot saved of its own ({} when none).
|
|
107
|
+
function ownRoute(id) {
|
|
108
|
+
if (isMixy(id)) return readMixyRoute(dataDir()) || {};
|
|
109
|
+
if (storeBot(id)) return readBotRoute(dataDir(), id) || {};
|
|
110
|
+
return agentRouteFromConfig(getConfig(), id) || {};
|
|
111
|
+
}
|
|
112
|
+
// The route a bot's chats run on: its own, else Main's.
|
|
113
|
+
const chatRoute = (id) => {
|
|
114
|
+
const own = ownRoute(id);
|
|
115
|
+
return normalizeWorkflowRoute(own.provider ? own : resolveRoute(getConfig(), {}));
|
|
116
|
+
};
|
|
117
|
+
// Structural, so equivalent parameter objects in another key order are the same route.
|
|
118
|
+
const plainRoute = (route) => JSON.parse(JSON.stringify(normalizeWorkflowRoute(route) ?? null));
|
|
119
|
+
const sameRoute = (a, b) => isDeepStrictEqual(plainRoute(a), plainRoute(b));
|
|
120
|
+
|
|
104
121
|
// Only an explicitly empty provider removes an override: the agent inherits Main.
|
|
105
|
-
function clearOverride(id) {
|
|
122
|
+
async function clearOverride(id) {
|
|
123
|
+
const before = chatRoute(id);
|
|
106
124
|
if (isMixy(id) || storeBot(id)) {
|
|
107
125
|
if (isMixy(id)) writeMixyRoute(dataDir(), null);
|
|
108
126
|
else writeBotRoute(dataDir(), id, null);
|
|
109
|
-
|
|
110
|
-
|
|
127
|
+
} else {
|
|
128
|
+
const nextConfig = { ...getConfig() };
|
|
129
|
+
const agents = { ...(nextConfig.agents || {}) };
|
|
130
|
+
const hadOverride = Object.hasOwn(agents, id);
|
|
131
|
+
delete agents[id];
|
|
132
|
+
nextConfig.agents = agents;
|
|
133
|
+
if (hadOverride) saveConfigAndAdopt(canonicalizeAgentRouteStorage(nextConfig));
|
|
111
134
|
}
|
|
112
|
-
const nextConfig = { ...getConfig() };
|
|
113
|
-
const agents = { ...(nextConfig.agents || {}) };
|
|
114
|
-
const hadOverride = Object.hasOwn(agents, id);
|
|
115
|
-
delete agents[id];
|
|
116
|
-
nextConfig.agents = agents;
|
|
117
|
-
if (hadOverride) saveConfigAndAdopt(canonicalizeAgentRouteStorage(nextConfig));
|
|
118
135
|
const inherited = normalizeWorkflowRoute(resolveRoute(getConfig(), {}));
|
|
136
|
+
// The bot's chats follow Main from their next turn (unless they already do).
|
|
137
|
+
if (inherited && !sameRoute(before, inherited)) await publishAgentRouteChange(id, inherited);
|
|
119
138
|
return { ...(inherited || {}), inherited: true };
|
|
120
139
|
}
|
|
121
140
|
|
|
@@ -128,16 +147,16 @@ export function createAgentRouteApi(deps) {
|
|
|
128
147
|
// picked while the model resolved below stays (answered with `skipped`).
|
|
129
148
|
const onlyIfEmpty = requested.onlyIfEmpty === true;
|
|
130
149
|
delete requested.onlyIfEmpty;
|
|
131
|
-
const readStored = () =>
|
|
132
|
-
if (isMixy(id)) return readMixyRoute(dataDir()) || {};
|
|
133
|
-
if (storeBot(id)) return readBotRoute(dataDir(), id) || {};
|
|
134
|
-
return agentRouteFromConfig(getConfig(), id) || {};
|
|
135
|
-
};
|
|
150
|
+
const readStored = () => ownRoute(id);
|
|
136
151
|
const kept = () => ({ ...readStored(), id, skipped: true });
|
|
137
152
|
const stored = readStored();
|
|
138
153
|
if (onlyIfEmpty && clean(stored.provider)) return kept();
|
|
139
|
-
// Mixy is never off: its route request is a model pick alone
|
|
140
|
-
|
|
154
|
+
// Mixy is never off: its route request is a model pick alone, and an
|
|
155
|
+
// on/off request alone changes nothing.
|
|
156
|
+
if (isMixy(id) && hasOwn(requested, 'disabled')) {
|
|
157
|
+
delete requested.disabled;
|
|
158
|
+
if (!Object.keys(requested).length) return { ...stored, id };
|
|
159
|
+
}
|
|
141
160
|
// Off is an explicit state, stored apart from the route so the model the
|
|
142
161
|
// user picked survives and comes back when the agent is switched on. An
|
|
143
162
|
// off request that also carries a model saves that model and stays off.
|
|
@@ -147,7 +166,7 @@ export function createAgentRouteApi(deps) {
|
|
|
147
166
|
// An explicitly empty provider still asks to drop the override, as it
|
|
148
167
|
// does for an agent that stays on: off and inheriting Main.
|
|
149
168
|
if (hasOwn(requested, 'provider') && !clean(requested.provider)) {
|
|
150
|
-
return { ...clearOverride(id), id, disabled: true };
|
|
169
|
+
return { ...(await clearOverride(id)), id, disabled: true };
|
|
151
170
|
}
|
|
152
171
|
return { ...stored, id, disabled: true };
|
|
153
172
|
}
|
|
@@ -189,7 +208,10 @@ export function createAgentRouteApi(deps) {
|
|
|
189
208
|
if (onlyIfEmpty && clean(readStored().provider)) return kept();
|
|
190
209
|
const stayOff = onlyIfEmpty ? isAgentDisabled(getConfig(), id) : keepOff;
|
|
191
210
|
// Picking a model is also the "on" switch unless the request keeps it off.
|
|
211
|
+
const before = chatRoute(id);
|
|
192
212
|
saveRoute(id, routeToSave, stayOff);
|
|
213
|
+
// The bot's existing chats move onto it from their next turn (unless they already run it).
|
|
214
|
+
if (!sameRoute(before, routeToSave)) await publishAgentRouteChange(id, routeToSave);
|
|
193
215
|
return stayOff ? { ...routeToSave, id, disabled: true } : routeToSave;
|
|
194
216
|
}
|
|
195
217
|
|
|
@@ -251,7 +251,6 @@ export function createTransitionSteps({
|
|
|
251
251
|
const projectPath = previous.projectPath;
|
|
252
252
|
const project = await inspectProject(projectPath, { signal });
|
|
253
253
|
let entry = await backendApi.getSessionWorktree(session.id);
|
|
254
|
-
const created = !entry;
|
|
255
254
|
if (entry) {
|
|
256
255
|
if (!existsSync(entry.path)) {
|
|
257
256
|
throw worktreeError('WORKTREE_MISSING', undefined, { worktreeId: entry.id, path: entry.path });
|
|
@@ -333,18 +332,9 @@ export function createTransitionSteps({
|
|
|
333
332
|
await backendApi.dropCarryRecoveryRef({ projectPath, recoveryRef: entry.changes.recoveryRef }).catch(() => {});
|
|
334
333
|
}
|
|
335
334
|
// Creation notes (submodules, include entries missing or already present).
|
|
336
|
-
//
|
|
337
|
-
// (`prepared`: what creation did and what the turn still has to run).
|
|
335
|
+
// A new checkout's first-turn preparation stays pending in its registry entry.
|
|
338
336
|
return {
|
|
339
337
|
...entered,
|
|
340
|
-
...(created
|
|
341
|
-
? {
|
|
342
|
-
created: {
|
|
343
|
-
prepared: entry.prepared ?? null,
|
|
344
|
-
root: entry.prepared?.root || project.topLevel || projectPath,
|
|
345
|
-
},
|
|
346
|
-
}
|
|
347
|
-
: {}),
|
|
348
338
|
warnings: Array.isArray(entry.warnings) ? [...entry.warnings] : [],
|
|
349
339
|
...(entry.changes ? { changes: { mode: entry.changes.mode, count: entry.changes.count } } : {}),
|
|
350
340
|
};
|
|
@@ -395,13 +385,6 @@ export function createTransitionSteps({
|
|
|
395
385
|
journal.push(() => backendApi.claimWorktreeOwner(previous.worktreeId, owner(session.id)));
|
|
396
386
|
await releaseOwner(backendApi, previous.worktreeId, session.id, { forgetReference: true });
|
|
397
387
|
}
|
|
398
|
-
// A managed worktree made for the branch: its first-turn preparation awaits.
|
|
399
|
-
if (resolved.created === true && entry) {
|
|
400
|
-
return {
|
|
401
|
-
...result,
|
|
402
|
-
created: { prepared: entry.prepared ?? null, root: entry.prepared?.root || project.topLevel || projectPath },
|
|
403
|
-
};
|
|
404
|
-
}
|
|
405
388
|
return result;
|
|
406
389
|
}
|
|
407
390
|
|