mixdog 1.3.2 → 1.3.3
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 +7 -7
- 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/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/boot/apis.mjs +3 -0
- package/src/session-runtime/boot/facade.mjs +5 -6
- package/src/session-runtime/boot/tools.mjs +21 -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/job-views/agent-list.mjs +34 -19
- package/src/session-runtime/services/agent-tool/spawn-flow/job-start.mjs +3 -0
- 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/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 +92 -40
- 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/session-runtime/room-member-gate.mjs +0 -61
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
// Message selector ("jump back to a previous message"): rewind the
|
|
2
2
|
// conversation to just before a user prompt and hand its text back for
|
|
3
3
|
// editing. Idle-only — a live turn must be interrupted first.
|
|
4
|
+
import { restorableAttachmentsFromPrompt } from '../../../../runtime/attachments/prompt-restore.mjs';
|
|
4
5
|
import { promptHistoryWithout } from '../../prompt-history.mjs';
|
|
6
|
+
import { hydrateTolerantly } from './abort.mjs';
|
|
5
7
|
|
|
6
8
|
export function createRewindAction(bag) {
|
|
7
9
|
const { runtime, getState, set, flushEmitImmediate, replaceItems, syncContextStats } = bag;
|
|
8
10
|
|
|
9
11
|
return {
|
|
10
|
-
|
|
12
|
+
// `restoreFiles: false` is a composer that cannot hold PDF/Office file
|
|
13
|
+
// parts (the terminal one): a prompt carrying any is refused untouched.
|
|
14
|
+
rewindToItem: async (itemId, { restoreFiles = true } = {}) => {
|
|
11
15
|
const target = String(itemId ?? '').trim();
|
|
12
16
|
if (!target) return null;
|
|
13
17
|
if (getState().busy || getState().commandBusy) return null;
|
|
@@ -19,8 +23,31 @@ export function createRewindAction(bag) {
|
|
|
19
23
|
if (!text) return null;
|
|
20
24
|
set({ commandBusy: true });
|
|
21
25
|
try {
|
|
22
|
-
|
|
23
|
-
|
|
26
|
+
// Matched by the row's stable message id (the stored prompt is the
|
|
27
|
+
// expanded text); rows without one fall back to the text.
|
|
28
|
+
const messageId = String(items[index]?.messageId || '');
|
|
29
|
+
const rewindOptions = { text, ...(messageId ? { messageId } : {}) };
|
|
30
|
+
// Resolve the prompt and build the whole restore payload BEFORE any
|
|
31
|
+
// history changes: a refusal or an attachment read error then leaves the
|
|
32
|
+
// model history and the transcript both untouched.
|
|
33
|
+
const preview = await runtime.rewindMessages?.({ ...rewindOptions, dryRun: true });
|
|
34
|
+
if (!preview) return null;
|
|
35
|
+
// The stored prompt's attachment references become the restore payload
|
|
36
|
+
// the abort/queue restores use (pastedTexts / pastedImages / file parts).
|
|
37
|
+
const content = preview.message?.content;
|
|
38
|
+
if (!restoreFiles && Array.isArray(content) && content.some((part) => part?.type === 'file')) {
|
|
39
|
+
throw new Error(
|
|
40
|
+
'this message has PDF/Office attachments the terminal composer cannot restore; edit it in the desktop app'
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const refs = restorableAttachmentsFromPrompt(content, text);
|
|
44
|
+
const attachments = hydrateTolerantly(refs.pastedImages, refs.pastedTexts, content);
|
|
45
|
+
// Refused when the history changed since the preview.
|
|
46
|
+
const rewound = await runtime.rewindMessages?.({
|
|
47
|
+
...rewindOptions,
|
|
48
|
+
...(preview.historyMarker ? { expectedHistoryMarker: preview.historyMarker } : {}),
|
|
49
|
+
});
|
|
50
|
+
if (!rewound) throw new Error('the conversation changed; select the message again');
|
|
24
51
|
set({
|
|
25
52
|
items: replaceItems(items.slice(0, index), {
|
|
26
53
|
preserveSpill: true,
|
|
@@ -36,7 +63,15 @@ export function createRewindAction(bag) {
|
|
|
36
63
|
syncContextStats({ allowEstimated: true });
|
|
37
64
|
set({ stats: { ...getState().stats } });
|
|
38
65
|
flushEmitImmediate?.();
|
|
39
|
-
return {
|
|
66
|
+
return {
|
|
67
|
+
text,
|
|
68
|
+
removed: items.length - index,
|
|
69
|
+
messages: rewound.removed,
|
|
70
|
+
...(attachments.pastedImages ? { pastedImages: attachments.pastedImages } : {}),
|
|
71
|
+
...(attachments.pastedTexts ? { pastedTexts: attachments.pastedTexts } : {}),
|
|
72
|
+
...(attachments.content ? { content: attachments.content } : {}),
|
|
73
|
+
...(attachments.notice ? { notice: attachments.notice } : {}),
|
|
74
|
+
};
|
|
40
75
|
} finally {
|
|
41
76
|
set({ commandBusy: false });
|
|
42
77
|
}
|
|
@@ -55,6 +55,7 @@ export function createAgentDefinitionApi(runtime) {
|
|
|
55
55
|
saveLeadAgentBody: async (text) => runtime.saveLeadAgentBody?.(text) ?? '',
|
|
56
56
|
getLeadStatus: () =>
|
|
57
57
|
runtime.getLeadStatus?.() ?? { created: null, name: '', avatar: null, homeChatted: false, route: null },
|
|
58
|
+
getLeadHomeRoute: () => runtime.getLeadHomeRoute?.() ?? null,
|
|
58
59
|
saveLeadIdentity: async (payload) => runtime.saveLeadIdentity?.(payload) ?? null,
|
|
59
60
|
setLeadCreated: async (created, description) => runtime.setLeadCreated?.(created, description) ?? null,
|
|
60
61
|
saveAgentDefinition: async (payload, options) => runtime.saveAgentDefinition?.(payload, options) ?? null,
|
|
@@ -96,17 +96,14 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
96
96
|
// Settle one entry: drop its timeout, then hand the waiter its answer. The
|
|
97
97
|
// resolve stays guarded — a waiter whose caller already went away must never
|
|
98
98
|
// take the rest of the queue down with it.
|
|
99
|
-
function settleToolApproval(entry, approved, reason, answers, reply, extra, device = ''
|
|
99
|
+
function settleToolApproval(entry, approved, reason, answers, reply, extra, device = '') {
|
|
100
100
|
if (entry?.timer) clearTimeout(entry.timer);
|
|
101
101
|
const result = { approved, reason };
|
|
102
102
|
if (answers !== undefined) result.answers = answers;
|
|
103
103
|
if (reply !== undefined) result.reply = reply;
|
|
104
|
-
// A human-kind request answers with its canonical response (never a value)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const answered = forwarded ? entry?.full || entry?.request : entry?.request;
|
|
108
|
-
if (answered?.remember) {
|
|
109
|
-
Object.assign(result, normalizeHumanResponse(answered, approved, extra));
|
|
104
|
+
// A human-kind request answers with its canonical response (never a value).
|
|
105
|
+
if (entry?.request?.remember) {
|
|
106
|
+
Object.assign(result, normalizeHumanResponse(entry.request, approved, extra));
|
|
110
107
|
if (device) result.device = device;
|
|
111
108
|
}
|
|
112
109
|
if (extra?.timedOut === true) result.timedOut = true;
|
|
@@ -120,28 +117,15 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
120
117
|
* owner had already settled it. */
|
|
121
118
|
function forwardToOwner(entry, approved, reason, device, answers, reply, extra) {
|
|
122
119
|
try {
|
|
123
|
-
return entry.mirror.answer(approved, reason, device, answers, reply,
|
|
120
|
+
return entry.mirror.answer(approved, reason, device, answers, reply, extra) === true;
|
|
124
121
|
} catch {
|
|
125
122
|
return false;
|
|
126
123
|
}
|
|
127
124
|
}
|
|
128
|
-
/** `request` as this session shows it: a remembering scope is offered only
|
|
129
|
-
* in the one session the request names for it (`rememberAt`, the bot's own
|
|
130
|
-
* chat); everywhere else — and when it names none — it asks once. */
|
|
131
|
-
function viewFor(request) {
|
|
132
|
-
if (!Array.isArray(request?.remember) || request.remember.length <= 1) return request;
|
|
133
|
-
const here = ownSessionId();
|
|
134
|
-
return here && request.rememberAt === here ? request : { ...request, remember: ['once'] };
|
|
135
|
-
}
|
|
136
|
-
/** `extra` without a remember scope `view` did not offer. */
|
|
137
|
-
function onlyOffered(view, extra) {
|
|
138
|
-
if (!extra || extra.remember === undefined) return extra;
|
|
139
|
-
return (view?.remember || ['once']).includes(extra.remember) ? extra : { ...extra, remember: 'once' };
|
|
140
|
-
}
|
|
141
125
|
function offerDelegatedApproval(delegated) {
|
|
142
126
|
if (getDisposed() || delegated.sessionId !== ownSessionId()) return;
|
|
143
127
|
if (activeToolApproval?.id === delegated.id || toolApprovalQueue.some((entry) => entry.id === delegated.id)) return;
|
|
144
|
-
toolApprovalQueue.push({ id: delegated.id, request:
|
|
128
|
+
toolApprovalQueue.push({ id: delegated.id, request: delegated.request, mirror: delegated, timer: null });
|
|
145
129
|
presentNextToolApproval();
|
|
146
130
|
}
|
|
147
131
|
function withdrawDelegatedCopy(id, result) {
|
|
@@ -183,8 +167,7 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
183
167
|
device = '',
|
|
184
168
|
answers = undefined,
|
|
185
169
|
reply = undefined,
|
|
186
|
-
extra = undefined
|
|
187
|
-
{ forwarded = false } = {}
|
|
170
|
+
extra = undefined
|
|
188
171
|
) {
|
|
189
172
|
const targetId = String(id || '');
|
|
190
173
|
if (activeToolApproval && activeToolApproval.id === targetId) {
|
|
@@ -200,16 +183,7 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
200
183
|
if (entry.mirror) {
|
|
201
184
|
accepted = forwardToOwner(entry, approved, reason, device, answers, reply, extra);
|
|
202
185
|
} else {
|
|
203
|
-
settleToolApproval(
|
|
204
|
-
entry,
|
|
205
|
-
approved === true,
|
|
206
|
-
String(reason || ''),
|
|
207
|
-
answers,
|
|
208
|
-
reply,
|
|
209
|
-
extra,
|
|
210
|
-
String(device || ''),
|
|
211
|
-
forwarded
|
|
212
|
-
);
|
|
186
|
+
settleToolApproval(entry, approved === true, String(reason || ''), answers, reply, extra, String(device || ''));
|
|
213
187
|
}
|
|
214
188
|
presentNextToolApproval();
|
|
215
189
|
return accepted;
|
|
@@ -218,16 +192,7 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
218
192
|
if (index >= 0) {
|
|
219
193
|
const [entry] = toolApprovalQueue.splice(index, 1);
|
|
220
194
|
if (entry.mirror) return forwardToOwner(entry, approved, reason, device, answers, reply, extra);
|
|
221
|
-
settleToolApproval(
|
|
222
|
-
entry,
|
|
223
|
-
approved === true,
|
|
224
|
-
String(reason || ''),
|
|
225
|
-
answers,
|
|
226
|
-
reply,
|
|
227
|
-
extra,
|
|
228
|
-
String(device || ''),
|
|
229
|
-
forwarded
|
|
230
|
-
);
|
|
195
|
+
settleToolApproval(entry, approved === true, String(reason || ''), answers, reply, extra, String(device || ''));
|
|
231
196
|
return true;
|
|
232
197
|
}
|
|
233
198
|
return false;
|
|
@@ -265,9 +230,7 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
265
230
|
full.chain = surface.chain;
|
|
266
231
|
full.surfaceSessionId = surface.sessionId;
|
|
267
232
|
}
|
|
268
|
-
|
|
269
|
-
// `full` what the copy in the top-level chat is made from.
|
|
270
|
-
const entry = { id, request: viewFor(full), full, resolve, timer: null, delegated: Boolean(surface) };
|
|
233
|
+
const entry = { id, request: full, resolve, timer: null, delegated: Boolean(surface) };
|
|
271
234
|
toolApprovalQueue.push(entry);
|
|
272
235
|
armToolApprovalTimeout(entry);
|
|
273
236
|
presentNextToolApproval();
|
|
@@ -277,7 +240,7 @@ export function createToolApproval({ getState, set, nextId, getDisposed, timeout
|
|
|
277
240
|
sessionId: surface.sessionId,
|
|
278
241
|
request: full,
|
|
279
242
|
answer: (approved, reason, device, answers, reply, extra) =>
|
|
280
|
-
finishToolApproval(id, approved, reason, device, answers, reply, extra
|
|
243
|
+
finishToolApproval(id, approved, reason, device, answers, reply, extra),
|
|
281
244
|
});
|
|
282
245
|
}
|
|
283
246
|
});
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
// A group-room member's tool calls (session/agent-room.mjs). Reads run freely;
|
|
2
|
-
// anything that can change files or state asks the user through the ordinary
|
|
3
|
-
// approval flow, whatever the agent's own permission or hook rules say — even
|
|
4
|
-
// an agent that normally runs auto-approved. A hook's deny still wins.
|
|
5
|
-
// Opening a task session (`session create`) runs as freely as in the agent's
|
|
6
|
-
// home thread: it changes nothing itself, and the task session is the user's
|
|
7
|
-
// own coding Lead, whose every side effect follows its usual approval rules.
|
|
8
|
-
import { analyzeShellCommandEffects } from '../runtime/agent/orchestrator/tools/builtin/shell-analysis.mjs';
|
|
9
|
-
|
|
10
|
-
const READ_ONLY_TOOLS = new Set([
|
|
11
|
-
'read',
|
|
12
|
-
'grep',
|
|
13
|
-
'glob',
|
|
14
|
-
'find',
|
|
15
|
-
'list',
|
|
16
|
-
'code_graph',
|
|
17
|
-
'load_tool',
|
|
18
|
-
'skill',
|
|
19
|
-
'Skill',
|
|
20
|
-
'recall',
|
|
21
|
-
'search_memories',
|
|
22
|
-
'web_search',
|
|
23
|
-
'web_fetch',
|
|
24
|
-
'local_fetch',
|
|
25
|
-
'image_fetch',
|
|
26
|
-
'ask_user',
|
|
27
|
-
]);
|
|
28
|
-
|
|
29
|
-
export const ROOM_APPROVAL_REASON = 'Group-room members need your approval before changing anything.';
|
|
30
|
-
|
|
31
|
-
/** Whether `name(args)` only reads: a read-only tool, or a shell command whose
|
|
32
|
-
* every stage the shell analysis classifies as non-mutating. */
|
|
33
|
-
export async function isReadOnlyRoomCall({ name, args, cwd }, analyze = analyzeShellCommandEffects) {
|
|
34
|
-
if (READ_ONLY_TOOLS.has(name)) return true;
|
|
35
|
-
if (name !== 'shell' || typeof args?.command !== 'string') return false;
|
|
36
|
-
try {
|
|
37
|
-
return (await analyze(args.command, cwd))?.mutationMode === 'none';
|
|
38
|
-
} catch {
|
|
39
|
-
return false;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Whether `name(args)` opens a task session (session create). */
|
|
44
|
-
export function isTaskSessionCreate({ name, args }) {
|
|
45
|
-
return (
|
|
46
|
-
name === 'session' &&
|
|
47
|
-
String(args?.action ?? '')
|
|
48
|
-
.trim()
|
|
49
|
-
.toLowerCase() === 'create'
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/** The PreToolUse decision for a room member's call: the hook's own `decision`
|
|
54
|
-
* when it denies, the call only reads, or it opens a task session; otherwise
|
|
55
|
-
* an approval ask that keeps any rewrite the hook made. */
|
|
56
|
-
export async function roomMemberToolDecision(call, decision, analyze) {
|
|
57
|
-
const action = String(decision?.action || decision?.decision || '').toLowerCase();
|
|
58
|
-
if (action === 'deny' || action === 'block') return decision;
|
|
59
|
-
if (isTaskSessionCreate(call) || (await isReadOnlyRoomCall(call, analyze))) return decision;
|
|
60
|
-
return { ...(decision && typeof decision === 'object' ? decision : {}), action: 'ask', reason: ROOM_APPROVAL_REASON };
|
|
61
|
-
}
|