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
|
@@ -9,6 +9,7 @@ import { AGENT_MODE, resolveSessionMode } from '../../runtime/agent/orchestrator
|
|
|
9
9
|
import { agentIdOfHomeSession } from '../../runtime/agent/orchestrator/session/agent-home.mjs';
|
|
10
10
|
import { turnHopOf } from '../../runtime/shared/bot-hops.mjs';
|
|
11
11
|
import { scheduleCallerScope } from '../services/schedule-access.mjs';
|
|
12
|
+
import { worktreeCallerScope } from '../services/worktree-access.mjs';
|
|
12
13
|
import { resolveHandoffAttachments, sessionRoots } from '../handoff-attachments.mjs';
|
|
13
14
|
|
|
14
15
|
const USER_TITLE_ERROR = 'session: the user already titled this session; the title was not changed';
|
|
@@ -44,9 +45,6 @@ export function createWorkspaceToolHandlers({
|
|
|
44
45
|
getLifecycleApi = () => null,
|
|
45
46
|
executeSessionControl = null,
|
|
46
47
|
}) {
|
|
47
|
-
// The Lead's own worktree, on the user's request: the same authority the
|
|
48
|
-
// branch chip menu drives, tolerating the calling turn but nothing else
|
|
49
|
-
// running (workers, background shells).
|
|
50
48
|
const assertLead = (action, callerCtx) => {
|
|
51
49
|
const callerSessionId = callerCtx?.callerSessionId || rt.session?.id || null;
|
|
52
50
|
if (!rt.session?.id || callerSessionId !== rt.session.id) {
|
|
@@ -55,24 +53,6 @@ export function createWorkspaceToolHandlers({
|
|
|
55
53
|
return rt.session.id;
|
|
56
54
|
};
|
|
57
55
|
|
|
58
|
-
const worktreeAction = async (action, args, callerCtx) => {
|
|
59
|
-
const workspace = getWorkspaceApi();
|
|
60
|
-
if (!workspace) throw new Error(`session: ${action} is unavailable in this runtime`);
|
|
61
|
-
assertLead(action, callerCtx);
|
|
62
|
-
let result;
|
|
63
|
-
if (action === 'merge-worktree') {
|
|
64
|
-
result = await workspace.mergeWorkspace({ confirmed: true }, { ownTurn: true });
|
|
65
|
-
} else if (action === 'remove-worktree') {
|
|
66
|
-
result = await workspace.removeWorktree({ force: args?.force === true }, { ownTurn: true });
|
|
67
|
-
} else if (action === 'list-worktrees') {
|
|
68
|
-
result = await workspace.listWorktrees();
|
|
69
|
-
} else {
|
|
70
|
-
result = await workspace.pruneWorktrees();
|
|
71
|
-
}
|
|
72
|
-
return JSON.stringify({ action, cwd: rt.currentCwd, result }, null, 2);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
const WORKTREE_ACTIONS = new Set(['merge-worktree', 'remove-worktree', 'list-worktrees', 'prune-worktrees']);
|
|
76
56
|
const SIDEBAR_ACTIONS = new Set(['favorite', 'archive']);
|
|
77
57
|
|
|
78
58
|
// Sidebar flags only (the desktop's favorite/archive metadata).
|
|
@@ -127,6 +107,8 @@ export function createWorkspaceToolHandlers({
|
|
|
127
107
|
callerAgentId,
|
|
128
108
|
callerCwd,
|
|
129
109
|
...(action === 'send' || action === 'create' ? { callerHop: turnHopOf(rt.session) } : {}),
|
|
110
|
+
// Whether a create may provision a worktree (worktree-access.mjs).
|
|
111
|
+
...(action === 'create' ? { callerScope: worktreeCallerScope(rt.session) } : {}),
|
|
130
112
|
// Which bots and sessions it may see (bot-status.mjs).
|
|
131
113
|
...(action === 'bots' || action === 'list' ? { callerScope: scheduleCallerScope(rt.session) } : {}),
|
|
132
114
|
...(attachmentParts.length ? { attachmentParts } : {}),
|
|
@@ -137,7 +119,6 @@ export function createWorkspaceToolHandlers({
|
|
|
137
119
|
if (target && target !== assertLead(action, callerCtx)) {
|
|
138
120
|
throw new Error(`session: action=${action} only applies to the current session`);
|
|
139
121
|
}
|
|
140
|
-
if (WORKTREE_ACTIONS.has(action)) return worktreeAction(action, args, callerCtx);
|
|
141
122
|
if (SIDEBAR_ACTIONS.has(action)) return sidebarAction(action, args, callerCtx);
|
|
142
123
|
let currentCwd = callerCwd;
|
|
143
124
|
if (action === 'status' || action === 'list-projects' || action === 'set-project') assertLead(action, callerCtx);
|
|
@@ -265,6 +246,8 @@ export function createWorkspaceToolHandlers({
|
|
|
265
246
|
clientHostPid: callerCtx?.clientHostPid || rt.session?.clientHostPid || process.pid,
|
|
266
247
|
signal: callerCtx?.signal,
|
|
267
248
|
notifyFn: notifyFnForSession(callerSessionId),
|
|
249
|
+
// The jobs it starts report back at this turn's bot-chain hop (bot-hops.mjs).
|
|
250
|
+
...(turnHopOf(rt.session) > 0 ? { hop: turnHopOf(rt.session) } : {}),
|
|
268
251
|
// The jobs this call starts are recorded under it (agent-task-starts.mjs).
|
|
269
252
|
...(callerCtx?.toolCallId ? { toolCallId: callerCtx.toolCallId } : {}),
|
|
270
253
|
});
|
|
@@ -11,6 +11,7 @@ function customRowFields(name, m) {
|
|
|
11
11
|
if (!isCustomProviderName(name)) return {};
|
|
12
12
|
return {
|
|
13
13
|
...(typeof m.name === 'string' && m.name ? { name: m.name } : {}),
|
|
14
|
+
...(typeof m.providerName === 'string' && m.providerName ? { providerName: m.providerName } : {}),
|
|
14
15
|
...(typeof m.hidden === 'boolean' ? { hidden: m.hidden } : {}),
|
|
15
16
|
...(typeof m.manual === 'boolean' ? { manual: m.manual } : {}),
|
|
16
17
|
...(m.customReasoning && typeof m.customReasoning === 'object' ? { customReasoning: m.customReasoning } : {}),
|
|
@@ -45,8 +45,15 @@ export function hydrateProviderModelRow(cfg, row) {
|
|
|
45
45
|
const modelParameterOptions = addedOptions.length
|
|
46
46
|
? [...existingOptions.filter((option) => !addedOptions.some((added) => added.id === option?.id)), ...addedOptions]
|
|
47
47
|
: row.modelParameterOptions;
|
|
48
|
+
const isCustom = row.provider?.startsWith?.('custom-');
|
|
49
|
+
const customName = isCustom ? String(cfg?.providers?.[row.provider]?.name || '').trim() : '';
|
|
50
|
+
// A custom provider's name always comes from the current configuration; a
|
|
51
|
+
// row's own (possibly renamed or removed) name is dropped.
|
|
52
|
+
const base = { ...row };
|
|
53
|
+
if (isCustom) delete base.providerName;
|
|
48
54
|
return {
|
|
49
|
-
...
|
|
55
|
+
...base,
|
|
56
|
+
...(customName ? { providerName: customName } : {}),
|
|
50
57
|
...(alias ? { display: alias, displayAlias: alias } : {}),
|
|
51
58
|
...(modelParameterOptions ? { modelParameterOptions } : {}),
|
|
52
59
|
effortOptions: effortItemsFor(row.provider, row, null),
|
|
@@ -5,10 +5,12 @@ import { getModelMetadataSync } from '../../runtime/agent/orchestrator/providers
|
|
|
5
5
|
import { isCustomProviderName } from '../../runtime/agent/orchestrator/providers/custom-reasoning.mjs';
|
|
6
6
|
|
|
7
7
|
const CUSTOM_DECLARED_FIELDS = [
|
|
8
|
+
'supportsVision',
|
|
8
9
|
'supportsReasoning',
|
|
9
10
|
'reasoningOptions',
|
|
10
11
|
'reasoningLevels',
|
|
11
12
|
'reasoningContentField',
|
|
13
|
+
'providerName',
|
|
12
14
|
'hidden',
|
|
13
15
|
'manual',
|
|
14
16
|
'customReasoning',
|
|
@@ -22,7 +22,10 @@ function customProviderModels(provider, providerConfig, discovered = providerCac
|
|
|
22
22
|
} catch {
|
|
23
23
|
return [];
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
const providerName = clean(config.name);
|
|
26
|
+
return effectiveCustomModelRows(config, discovered, { providerId: provider }).map((row) =>
|
|
27
|
+
providerName ? { ...row, providerName } : row
|
|
28
|
+
);
|
|
26
29
|
}
|
|
27
30
|
|
|
28
31
|
export function createQuickProviderRows({
|
|
@@ -53,6 +56,8 @@ export function createQuickProviderRows({
|
|
|
53
56
|
display: model.display || model.name || modelId,
|
|
54
57
|
contextWindow: model.contextWindow || meta.contextWindow || null,
|
|
55
58
|
outputTokens: model.outputTokens || meta.outputTokens || null,
|
|
59
|
+
// An explicit value (an override's false included) wins; the catalog fills the rest.
|
|
60
|
+
supportsVision: model.supportsVision ?? meta.supportsVision,
|
|
56
61
|
supportsReasoning: model.supportsReasoning === true || meta.supportsReasoning === true,
|
|
57
62
|
supportsFunctionCalling: model.supportsFunctionCalling === true || meta.supportsFunctionCalling === true,
|
|
58
63
|
supportsPromptCaching: model.supportsPromptCaching === true || meta.supportsPromptCaching === true,
|
|
@@ -78,6 +83,7 @@ export function createQuickProviderRows({
|
|
|
78
83
|
contextWindow: meta.contextWindow || null,
|
|
79
84
|
outputTokens: meta.outputTokens || null,
|
|
80
85
|
latest: routeLike.latest === true,
|
|
86
|
+
supportsVision: meta.supportsVision,
|
|
81
87
|
supportsReasoning: !!routeLike.effort || meta.supportsReasoning === true,
|
|
82
88
|
supportsFunctionCalling: meta.supportsFunctionCalling === true,
|
|
83
89
|
supportsPromptCaching: meta.supportsPromptCaching === true,
|
|
@@ -2,6 +2,7 @@ import { registerCacheInvalidationListener } from '../runtime/agent/orchestrator
|
|
|
2
2
|
import { turnReviewReply } from '../runtime/shared/turn-review-reply.mjs';
|
|
3
3
|
import {
|
|
4
4
|
clearSessionChangeHistory,
|
|
5
|
+
forgetTurnSnapshotSession,
|
|
5
6
|
getSessionReviewDiff,
|
|
6
7
|
getSessionReviewFilePatch,
|
|
7
8
|
getTurnChanges,
|
|
@@ -19,8 +20,10 @@ import { registerSessionPurgeHook } from '../runtime/agent/orchestrator/session/
|
|
|
19
20
|
|
|
20
21
|
// A deleted history stays deleted for as long as its session exists; the
|
|
21
22
|
// session's own deletion takes the marker — and its stored first-seen file
|
|
22
|
-
// contents — with it
|
|
23
|
+
// contents — with it, and its in-memory turn, parked worker reviews and
|
|
24
|
+
// bound worker trackers.
|
|
23
25
|
registerSessionPurgeHook((sessionId) => {
|
|
26
|
+
forgetTurnSnapshotSession(sessionId);
|
|
24
27
|
void forgetSessionChangeHistoryMarker(sessionId);
|
|
25
28
|
void forgetSessionBaselines(sessionId);
|
|
26
29
|
});
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
listBackgroundTasks,
|
|
6
6
|
taskIdFromArgs,
|
|
7
7
|
} from '../../../runtime/shared/background-tasks.mjs';
|
|
8
|
-
import { agentScope, clean, clearAgentStatuslineRoute } from './helpers.mjs';
|
|
8
|
+
import { agentScope, clean, clearAgentStatuslineRoute, sessionMatchesContext } from './helpers.mjs';
|
|
9
9
|
import { isLeadPoolAgent } from './worker-rows.mjs';
|
|
10
10
|
import { createCloseAll } from './close-flow/close-all.mjs';
|
|
11
11
|
import { closeManagedSession } from '../../lifecycle/shared.mjs';
|
|
@@ -20,6 +20,16 @@ export function createCloseFlow({ mgr, registry, views }) {
|
|
|
20
20
|
// Stale local metadata only: resolveTag found no session in this
|
|
21
21
|
// terminal/scope, so there is no sessionId-safe worker row to delete. Never
|
|
22
22
|
// turn it into a tag-wide persisted-row removal.
|
|
23
|
+
// `tags`/`tagAgents` are shared by every caller on the canonical agent, so a
|
|
24
|
+
// binding alone does not prove the caller owns it: only a live session or a
|
|
25
|
+
// persisted row inside the caller's scope does. Another session's tag must
|
|
26
|
+
// stay untouched.
|
|
27
|
+
function tagBoundByCaller(target, scopedContext) {
|
|
28
|
+
const live = registry.getLiveSession(tags.get(target));
|
|
29
|
+
if (live) return sessionMatchesContext(live, scopedContext);
|
|
30
|
+
return registry.readWorkerRows(scopedContext).some((row) => clean(row.tag) === target);
|
|
31
|
+
}
|
|
32
|
+
|
|
23
33
|
function forgetStaleLocalTag(target, task) {
|
|
24
34
|
registry.unbindTag(target);
|
|
25
35
|
if (task?.taskId) cancelBackgroundTask(task.taskId, CLOSE_REASON);
|
|
@@ -55,7 +65,9 @@ export function createCloseFlow({ mgr, registry, views }) {
|
|
|
55
65
|
}
|
|
56
66
|
const sessionId = registry.resolveTag(target, scopedContext, { scanSessions: registry.wantsSessionScan(args) });
|
|
57
67
|
if (!sessionId) {
|
|
58
|
-
if (!target.startsWith('sess_') && tagAgents.has(target)
|
|
68
|
+
if (!target.startsWith('sess_') && tagAgents.has(target) && tagBoundByCaller(target, scopedContext)) {
|
|
69
|
+
return forgetStaleLocalTag(target, task);
|
|
70
|
+
}
|
|
59
71
|
throw new Error(`agent close: target "${target}" not found`);
|
|
60
72
|
}
|
|
61
73
|
if (isLeadPoolAgent(registry.getLiveSession(sessionId)?.agent)) {
|
|
@@ -67,7 +67,12 @@ export function createAgentExecute({
|
|
|
67
67
|
}
|
|
68
68
|
// Targetless status is the same compact overview as list.
|
|
69
69
|
return renderResult({
|
|
70
|
-
workers
|
|
70
|
+
// Idle workers stay open for follow-ups; the model must see them to close them.
|
|
71
|
+
workers: views.list({
|
|
72
|
+
scanSessions: registry.wantsSessionScan(args),
|
|
73
|
+
context: scopedContext,
|
|
74
|
+
includeIdle: true,
|
|
75
|
+
}),
|
|
71
76
|
jobs: views.listJobs(scopedContext),
|
|
72
77
|
});
|
|
73
78
|
case 'read':
|
|
@@ -25,11 +25,24 @@ export function isActiveWorkerRow(row = {}) {
|
|
|
25
25
|
return !isTerminalWorkerStatus(effective);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
// A finished worker that is still open: it takes follow-ups and can be closed.
|
|
29
|
+
function isOpenIdleRow(row = {}) {
|
|
30
|
+
const status = String(row.status ?? '').trim().toLowerCase();
|
|
31
|
+
const stage = String(row.stage ?? '').trim().toLowerCase();
|
|
32
|
+
if (CANCELLED_WORKER_STATUS.test(stage) || CANCELLED_WORKER_STATUS.test(status)) return false;
|
|
33
|
+
return (status || stage) === 'idle';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function rowState(session, runtime) {
|
|
29
37
|
const status = session.closed === true ? 'closed' : session.status || 'idle';
|
|
30
38
|
const stage =
|
|
31
39
|
session.stage ||
|
|
32
40
|
(status === 'idle' || status === 'error' || status === 'closed' ? status : runtime?.stage || status);
|
|
41
|
+
return { status, stage };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function agentRow({ tag, session, runtime, progress, now, indexRow = null }) {
|
|
45
|
+
const { status, stage } = rowState(session, runtime);
|
|
33
46
|
// Additive: the current turn's start (worker index, stamped at dispatch) so
|
|
34
47
|
// surfaces time a continued worker from its turn, not from createdAt.
|
|
35
48
|
const turnStartedAt = indexRow?.turnStartedAt || session.turnStartedAt || null;
|
|
@@ -73,27 +86,38 @@ function agentRow({ tag, session, runtime, progress, now, indexRow = null }) {
|
|
|
73
86
|
}
|
|
74
87
|
|
|
75
88
|
export function createAgentList({ mgr, refreshTagsFromSessions, agentSessionEntries, progress }) {
|
|
76
|
-
return function list({ scanSessions = false, context = {}, includeTerminal = false } = {}) {
|
|
89
|
+
return function list({ scanSessions = false, context = {}, includeTerminal = false, includeIdle = false } = {}) {
|
|
77
90
|
refreshTagsFromSessions({ scanSessions, context });
|
|
78
91
|
const now = Date.now();
|
|
79
|
-
const rows =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
92
|
+
const rows = [];
|
|
93
|
+
for (const { tag, session, indexRow, loaded } of agentSessionEntries({ scanSessions, context })) {
|
|
94
|
+
const runtime = mgr.getSessionRuntime?.(session.id);
|
|
95
|
+
// Whether a row is listed depends on its status and stage alone, so a
|
|
96
|
+
// finished worker is dropped before its progress is read: that read
|
|
97
|
+
// loads the worker's stored session, and a Lead's status pulse (every
|
|
98
|
+
// 2 s) would otherwise read every worker it ever ran, whole transcripts
|
|
99
|
+
// on first sight, synchronously on the daemon loop.
|
|
100
|
+
const state = rowState(session, runtime);
|
|
101
|
+
if (!includeTerminal && !isActiveWorkerRow(state) && !(includeIdle && isOpenIdleRow(state))) continue;
|
|
102
|
+
rows.push(
|
|
103
|
+
agentRow({
|
|
104
|
+
tag,
|
|
105
|
+
session,
|
|
106
|
+
indexRow,
|
|
107
|
+
runtime,
|
|
108
|
+
// A tag-bound entry is the getSession answer itself; an index row or
|
|
109
|
+
// a scanned summary is only a projection and still reads the session.
|
|
110
|
+
progress: progress.sessionProgressExtras(
|
|
111
|
+
session.id,
|
|
112
|
+
session.agent || null,
|
|
113
|
+
now,
|
|
114
|
+
null,
|
|
115
|
+
loaded ? { loaded: session } : {}
|
|
116
|
+
),
|
|
90
117
|
now,
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
})
|
|
96
|
-
);
|
|
97
|
-
return includeTerminal ? rows : rows.filter((row) => isActiveWorkerRow(row));
|
|
118
|
+
})
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
return rows;
|
|
98
122
|
};
|
|
99
123
|
}
|
|
@@ -156,9 +156,11 @@ export function renderResult(value, { includeDiagnostics = false } = {}) {
|
|
|
156
156
|
if (typeof value === 'string') return value;
|
|
157
157
|
if (value && typeof value === 'object') {
|
|
158
158
|
if (Array.isArray(value.workers) || Array.isArray(value.jobs)) return renderRoster(value);
|
|
159
|
+
// close-flow results carry `closed` plus task_id: render the close outcome.
|
|
160
|
+
// close-flow results carry `closed` plus task_id: render the close outcome.
|
|
161
|
+
if (value.closed !== undefined) return renderClosed(value);
|
|
159
162
|
if (value.task_id) return renderTask(value, includeDiagnostics);
|
|
160
163
|
if (value.queued) return renderQueued(value);
|
|
161
|
-
if (value.closed !== undefined) return renderClosed(value);
|
|
162
164
|
if (value.content !== undefined) return renderContent(value);
|
|
163
165
|
}
|
|
164
166
|
return JSON.stringify(value, null, 2);
|
|
@@ -9,6 +9,7 @@ import { resourceAdmission } from '../../../../runtime/shared/resource-admission
|
|
|
9
9
|
import { clean, terminalPidForContext } from '../helpers.mjs';
|
|
10
10
|
import { renderResult } from '../render.mjs';
|
|
11
11
|
import { closeManagedSession } from '../../../lifecycle/shared.mjs';
|
|
12
|
+
import { hopOf } from '../../../../runtime/shared/bot-hops.mjs';
|
|
12
13
|
|
|
13
14
|
/** The completion callback that hands a worker's result back to its caller session; null without a handoff. */
|
|
14
15
|
function handoffNotifier(handoffSessionId, notifySessionCompletion) {
|
|
@@ -30,6 +31,8 @@ export function createJobStarter({ mgr, notifyStatusChange, notifySessionComplet
|
|
|
30
31
|
ownerSessionId: ownerSessionId || null,
|
|
31
32
|
clientHostPid: clientHostPid || null,
|
|
32
33
|
notifyFn: handoffNotifier(handoffSessionId, notifySessionCompletion),
|
|
34
|
+
// The turn that started the job: its completion returns at that bot-chain hop (bot-hops.mjs).
|
|
35
|
+
...(hopOf(notifyContext?.hop) ? { hop: notifyContext.hop } : {}),
|
|
33
36
|
};
|
|
34
37
|
const jobMeta = sanitizeTaskMeta({
|
|
35
38
|
...(meta || {}),
|
|
@@ -28,7 +28,7 @@ export const AGENT_TOOL = {
|
|
|
28
28
|
agentHidden: false,
|
|
29
29
|
},
|
|
30
30
|
description:
|
|
31
|
-
'Run scoped agent work as background tasks. spawn/send return task_id immediately. Reuse one tag for one scope for its whole lifetime; give distinct tags only to independent scopes. Never mint a new tag because a session expired or was lost — same-tag spawn respawns it with the full brief. Wait for completion notifications; use status/read only for manual recovery.',
|
|
31
|
+
'Run scoped agent work as background tasks. spawn/send return task_id immediately. Reuse one tag for one scope for its whole lifetime; give distinct tags only to independent scopes. Never mint a new tag because a session expired or was lost — same-tag spawn respawns it with the full brief. Wait for completion notifications; use status/read only for manual recovery. Close finished agents yourself.',
|
|
32
32
|
inputSchema: {
|
|
33
33
|
type: 'object',
|
|
34
34
|
properties: {
|
|
@@ -442,6 +442,7 @@ function publicCustomModelRows(rows) {
|
|
|
442
442
|
model.hidden = item.hidden === true;
|
|
443
443
|
model.manual = item.manual === true;
|
|
444
444
|
for (const key of [
|
|
445
|
+
'supportsVision',
|
|
445
446
|
'supportsReasoning',
|
|
446
447
|
'reasoningOptions',
|
|
447
448
|
'reasoningLevels',
|
|
@@ -588,7 +589,8 @@ async function modelProxyProviderSetup(options) {
|
|
|
588
589
|
});
|
|
589
590
|
const custom = Object.entries(providers)
|
|
590
591
|
.filter(([id, entry]) => isCustomProviderId(id) && entry?.type === 'custom')
|
|
591
|
-
|
|
592
|
+
// Older desktops advertise no name: the id is the fallback.
|
|
593
|
+
.map(([id, entry]) => ({ id, name: (typeof entry.name === 'string' && entry.name.trim()) || id }));
|
|
592
594
|
return {
|
|
593
595
|
managedByClient: true,
|
|
594
596
|
api: [...project(API_PROVIDERS, 'api', 'api-key'), ...project(custom, 'api', 'custom')],
|
|
@@ -1111,7 +1113,15 @@ export async function saveCustomProvider(cfgMod, rawInput) {
|
|
|
1111
1113
|
return typed ? serializeCustomKeySave(id, commit) : commit();
|
|
1112
1114
|
}
|
|
1113
1115
|
|
|
1114
|
-
const MODEL_PATCH_KEYS = new Set([
|
|
1116
|
+
const MODEL_PATCH_KEYS = new Set([
|
|
1117
|
+
'manual',
|
|
1118
|
+
'hidden',
|
|
1119
|
+
'name',
|
|
1120
|
+
'contextWindow',
|
|
1121
|
+
'maxOutputTokens',
|
|
1122
|
+
'supportsVision',
|
|
1123
|
+
'reasoning',
|
|
1124
|
+
]);
|
|
1115
1125
|
const REASONING_PATCH_KEYS = new Set(['levels', 'wireFormat', 'wireValues', 'replay']);
|
|
1116
1126
|
|
|
1117
1127
|
// Tri-state merge: undefined preserves, null deletes the property, a value replaces it.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Who may change worktrees from a chat (the git tool's managed-worktree
|
|
2
|
+
// operations, the daemon's cross-session `worktree` control). A worktree
|
|
3
|
+
// mutation — entering, returning, merging, removing, pruning, `git worktree
|
|
4
|
+
// add/remove`, a snapshot — runs only in a conversation session: a Lead
|
|
5
|
+
// session of the desktop or TUI, or a bot's chat. Unattended runs (schedules,
|
|
6
|
+
// webhooks, routines, room seats) are refused by the run's trusted identity;
|
|
7
|
+
// delegated workers have no worktree host at all. Listing stays open.
|
|
8
|
+
//
|
|
9
|
+
// The scope is the session-level caller scope (schedule-access.mjs
|
|
10
|
+
// scheduleCallerScope: the session's provenance and its unattended-run mark),
|
|
11
|
+
// never anything the model or a message supplies.
|
|
12
|
+
import { scheduleCallerScope } from './schedule-access.mjs';
|
|
13
|
+
|
|
14
|
+
/** `{ kind, agentId?, unattended?, attended }` of a calling session record. */
|
|
15
|
+
export function worktreeCallerScope(session) {
|
|
16
|
+
const scope = scheduleCallerScope(session);
|
|
17
|
+
const attended = (scope.kind === 'human' || scope.kind === 'agent') && scope.unattended !== true;
|
|
18
|
+
return { ...scope, attended };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Throws unless `scope` (worktreeCallerScope) may change worktrees; `what` names the refused action. */
|
|
22
|
+
export function assertWorktreeMutationAllowed(scope, what) {
|
|
23
|
+
if (scope?.attended === true) return;
|
|
24
|
+
throw new Error(
|
|
25
|
+
`${what} changes worktrees only in a conversation session (a Lead session or a bot chat); schedule, webhook, routine and room runs may only list them`
|
|
26
|
+
);
|
|
27
|
+
}
|
|
@@ -5,9 +5,6 @@
|
|
|
5
5
|
// facade's hookCommonPayload / currentCwd accessor + the session itself. All
|
|
6
6
|
// properties are non-enumerable/configurable/writable so the loop/manager can
|
|
7
7
|
// read them by name without changing session enumeration.
|
|
8
|
-
import { roomMemberOfSession } from '../runtime/agent/orchestrator/session/agent-room.mjs';
|
|
9
|
-
import { roomMemberToolDecision } from './room-member-gate.mjs';
|
|
10
|
-
|
|
11
8
|
export function attachSessionHooks(session, { hooks, hookCommonPayload, getCwd }) {
|
|
12
9
|
const identity = (input) => ({
|
|
13
10
|
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
@@ -28,26 +25,21 @@ export function attachSessionHooks(session, { hooks, hookCommonPayload, getCwd }
|
|
|
28
25
|
// rejection cannot escape the tool loop or the compaction flow.
|
|
29
26
|
const dispatcher = (event, payload) => (input) => hooks.dispatch(event, hookCommonPayload(payload(input)));
|
|
30
27
|
|
|
31
|
-
// PreToolUse bridge. A group-room member
|
|
32
|
-
//
|
|
33
|
-
define('beforeToolHook', async (input, options = {}) =>
|
|
34
|
-
|
|
35
|
-
const args = input?.args || input?.tool_input;
|
|
36
|
-
const cwd = input?.cwd || getCwd();
|
|
37
|
-
const decision = await hooks.beforeTool(
|
|
28
|
+
// PreToolUse bridge. A group-room member follows the same rules as its
|
|
29
|
+
// agent's home thread: no room-only approval on top.
|
|
30
|
+
define('beforeToolHook', async (input, options = {}) =>
|
|
31
|
+
hooks.beforeTool(
|
|
38
32
|
hookCommonPayload({
|
|
39
33
|
...input,
|
|
40
34
|
session_id: input?.sessionId || input?.session_id || session?.id,
|
|
41
|
-
tool_name: name,
|
|
42
|
-
tool_input: args,
|
|
35
|
+
tool_name: input?.name || input?.tool_name,
|
|
36
|
+
tool_input: input?.args || input?.tool_input,
|
|
43
37
|
tool_use_id: input?.toolCallId || input?.tool_use_id,
|
|
44
|
-
cwd,
|
|
38
|
+
cwd: input?.cwd || getCwd(),
|
|
45
39
|
}),
|
|
46
40
|
options
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
return roomMemberToolDecision({ name, args, cwd }, decision);
|
|
50
|
-
});
|
|
41
|
+
)
|
|
42
|
+
);
|
|
51
43
|
// PostToolUse: bridge runtime tool completions to the standard hook bus.
|
|
52
44
|
define('afterToolHook', dispatcher('PostToolUse', toolPayload));
|
|
53
45
|
// PostToolUseFailure: dispatched by loop.mjs only when a tool execution
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
effortJudgeAvailable,
|
|
20
20
|
effortJudgeInfo,
|
|
21
21
|
effortJudgeInstalling,
|
|
22
|
+
effortJudgeLastError,
|
|
22
23
|
effortJudgeReady,
|
|
23
24
|
shutdownEffortJudge,
|
|
24
25
|
} from '../runtime/effort-judge/judge-client.mjs';
|
|
@@ -178,6 +179,7 @@ export function createBuiltinToolSettings(
|
|
|
178
179
|
installed: effortJudgeAvailable(),
|
|
179
180
|
installing: effortJudgeInstalling(),
|
|
180
181
|
ready: effortJudgeReady(),
|
|
182
|
+
lastError: effortJudgeLastError(),
|
|
181
183
|
info: effortJudgeInfo(),
|
|
182
184
|
},
|
|
183
185
|
};
|
|
@@ -38,6 +38,10 @@ const PROFILE_VALUE_IDS = Object.freeze({
|
|
|
38
38
|
});
|
|
39
39
|
|
|
40
40
|
const ACTION_APPLIES_TO = {
|
|
41
|
+
set_agent_route:
|
|
42
|
+
"the bot's chats from their next turn (a running turn finishes on the old model); an agent switched on or off reaches open conversations from their next turn as an agent list reminder",
|
|
43
|
+
set_orchestration_mode:
|
|
44
|
+
"new sessions and an empty current one (the default mode); a conversation keeps its own mode until it is switched with the composer's mode selector",
|
|
41
45
|
set_recap_enabled: 'background Memory cycles; no restart required',
|
|
42
46
|
set_auto_update: 'subsequent automatic update checks',
|
|
43
47
|
set_worktree_settings: 'new tasks and worktrees created afterwards; existing worktrees are unchanged',
|
|
@@ -223,6 +223,9 @@ export const SETUP_EXTENDED_PROPERTIES = Object.freeze({
|
|
|
223
223
|
turnNotifications: boolean,
|
|
224
224
|
usagePinned: boolean,
|
|
225
225
|
usageRailShortLong: boolean,
|
|
226
|
+
usageAccountsExpanded: boolean,
|
|
227
|
+
usageRailSlotsThree: boolean,
|
|
228
|
+
usageRailSlotsAll: boolean,
|
|
226
229
|
computerObserveOnly: boolean,
|
|
227
230
|
browserAutoSignIn: boolean,
|
|
228
231
|
notificationVolume: {
|