commandmate 0.40.1 → 0.41.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/BUILD_ID +1 -1
- package/.next/app-build-manifest.json +134 -134
- package/.next/app-path-routes-manifest.json +21 -21
- package/.next/build-manifest.json +2 -2
- package/.next/prerender-manifest.json +12 -12
- package/.next/required-server-files.json +1 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/agents/versions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/release-notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/app/update-check/route.js +1 -1
- package/.next/server/app/api/app/update-check/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/login/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/capabilities/route.js +1 -1
- package/.next/server/app/api/capabilities/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/daily-summary/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/health/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/external-apps/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/browse/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/fs/recent-paths/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/agent-event/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/claude-done/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route.js +1 -1
- package/.next/server/app/api/hooks/permission-request/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/metrics/vibe/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/ollama/models/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/escalation/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/subscriptions/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/push/vapid/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/[relayId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/relays/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/remote/pair/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/[jobId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/clone/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/excluded/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/restore/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/scan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/sync/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/repositories/validate-path/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/settings/default-surface-mode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/sidebar/group-order/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/installations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/operations/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/reindex/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/tasks/[taskId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/templates/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/verification/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/auto-yes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/capture/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/clear-composer/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-reference/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cli-tool/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/cmate/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route.js +1 -1
- package/.next/server/app/api/worktrees/[id]/current-output/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/direct-input/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/env/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/[logId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/execution-logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/files/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/create/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branch/delete/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/branches/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/checkout/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/commit/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/fetch/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/log/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/pull/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/reset/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/revert/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/show/[commitHash]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/staged/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/[index]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/apply/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/pop/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/push/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/stash/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/status/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/unstage/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/git/working-diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/notes/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/instances/opencode/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/interrupt/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/kill-session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/[filename]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/logs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/marp-render/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/[memoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/memos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/messages/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/diff/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/session/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/opencode/share/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/prompt-response/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/resolve-target/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/respond/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/[scheduleId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/active/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/schedules/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/search/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/send/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/git-workflow/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/install/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/uninstall-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/[skillId]/update-plan/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/skills/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/slash-commands/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/special-keys/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/terminal/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/history/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/timers/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/[todoId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/todos/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/tree/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/upload/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/config/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/cancel/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/[runId]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/verify/runs/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/[id]/viewed/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/apply-default-agents/route_client-reference-manifest.js +1 -1
- package/.next/server/app/api/worktrees/route.js +1 -1
- package/.next/server/app/api/worktrees/route_client-reference-manifest.js +1 -1
- package/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/server/app/manifest.webmanifest/route_client-reference-manifest.js +1 -1
- package/.next/server/app/more/page_client-reference-manifest.js +1 -1
- package/.next/server/app/offline/page_client-reference-manifest.js +1 -1
- package/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/server/app/proxy/[...path]/route_client-reference-manifest.js +1 -1
- package/.next/server/app/repositories/page_client-reference-manifest.js +1 -1
- package/.next/server/app/review/page_client-reference-manifest.js +1 -1
- package/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/[skillId]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/installed/page_client-reference-manifest.js +1 -1
- package/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/files/[...path]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/page.js +1 -1
- package/.next/server/app/worktrees/[id]/page_client-reference-manifest.js +1 -1
- package/.next/server/app/worktrees/[id]/terminal/page_client-reference-manifest.js +1 -1
- package/.next/server/app-paths-manifest.json +21 -21
- package/.next/server/chunks/4443.js +1 -1
- package/.next/server/chunks/5164.js +1 -1
- package/.next/server/chunks/6130.js +1 -1
- package/.next/server/chunks/650.js +1 -1
- package/.next/server/chunks/8581.js +2 -2
- package/.next/server/chunks/8728.js +1 -1
- package/.next/server/chunks/9627.js +30 -24
- package/.next/server/chunks/9882.js +3 -3
- package/.next/server/middleware-manifest.json +5 -5
- package/.next/server/pages/500.html +1 -1
- package/.next/server/server-reference-manifest.json +1 -1
- package/.next/static/chunks/{2407-d750620d0511e94f.js → 2407-99799e3c2ff03bae.js} +1 -1
- package/.next/static/chunks/{4768-979c8a03bed218e7.js → 4768-fc0aa1d0891cac08.js} +1 -1
- package/.next/static/chunks/{8606-9a381b996f9b6834.js → 8606-79c36d4c204bbd38.js} +1 -1
- package/.next/static/chunks/app/{layout-3d3fcc8aac7b3bb5.js → layout-1fb647d6df55c498.js} +1 -1
- package/.next/static/chunks/app/worktrees/[id]/{page-a91e812ad9d94697.js → page-f24da37453224716.js} +1 -1
- package/.next/trace +13 -13
- package/dist/server/src/lib/auto-yes-poller.js +72 -1
- package/dist/server/src/lib/db/chat-db.js +38 -0
- package/dist/server/src/lib/detection/cli-patterns.js +11 -0
- package/dist/server/src/lib/detection/selection-shape.js +76 -0
- package/dist/server/src/lib/detection/tools/antigravity/detect.js +64 -0
- package/dist/server/src/lib/detection/tools/claude/detect.js +28 -1
- package/dist/server/src/lib/detection/tools/codex/cli-patterns.js +51 -0
- package/dist/server/src/lib/detection/tools/codex/detect.js +21 -2
- package/dist/server/src/lib/detection/tools/command-code/detect.js +14 -3
- package/dist/server/src/lib/polling/antigravity-permission-receipts.js +113 -0
- package/dist/server/src/lib/polling/response-checker.js +73 -4
- package/dist/server/src/lib/session/current-output-builder.js +25 -0
- package/dist/server/src/lib/session/layer-disagreement.js +108 -0
- package/dist/server/src/types/sidebar.js +1 -0
- package/package.json +1 -1
- package/release-notes/0.41.0.json +29 -0
- /package/.next/static/{JfzIPPhL-ikSVcJYOKgfD → UoGuvKnR_kGftU9RHtebq}/_buildManifest.js +0 -0
- /package/.next/static/{JfzIPPhL-ikSVcJYOKgfD → UoGuvKnR_kGftU9RHtebq}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Short-lived record of the `PreToolUse` questions agy asked CommandMate
|
|
4
|
+
* (Issue #2849).
|
|
5
|
+
*
|
|
6
|
+
* ## Why this exists
|
|
7
|
+
*
|
|
8
|
+
* agy registers its permission hook on every tool call and waits for the reply
|
|
9
|
+
* before it either draws an approval dialog or runs the tool (#2848). A dialog
|
|
10
|
+
* that is really open on the pane therefore always follows a request that
|
|
11
|
+
* reached `POST /api/hooks/permission-request` a moment earlier. A dialog that
|
|
12
|
+
* agy only QUOTED in a reply — `Do you want to proceed?` and its four options
|
|
13
|
+
* in the model's prose — follows nothing. That asymmetry is the whole signal:
|
|
14
|
+
* "did agy ask us about a tool call just now" is a fact the screen cannot fake.
|
|
15
|
+
*
|
|
16
|
+
* ## Why no existing record can be used instead
|
|
17
|
+
*
|
|
18
|
+
* - `reportPermissionRequestPending` is not called for antigravity when
|
|
19
|
+
* `permissionHookPredictsDialog` is false, which is the ordinary case;
|
|
20
|
+
* - `pendingByInstance` is emptied by `closeDecisionSlot` the moment CommandMate
|
|
21
|
+
* answers, and the answer and the dialog belong to one causal chain — by the
|
|
22
|
+
* time the dialog is on the pane the slot is already gone.
|
|
23
|
+
*
|
|
24
|
+
* ## What is kept
|
|
25
|
+
*
|
|
26
|
+
* ONE entry per instance: the tool name and the arrival time of the most recent
|
|
27
|
+
* question. A second question replaces the first, because the only thing asked
|
|
28
|
+
* of this record is "was there one lately".
|
|
29
|
+
*
|
|
30
|
+
* The screen carries no tool name (only the option labels), so the caller that
|
|
31
|
+
* reads a frame asks {@link hasRecentAntigravityPermissionReceipt} without one
|
|
32
|
+
* and gets a time-only answer. The name is still stored and comparable, for a
|
|
33
|
+
* caller that does know it.
|
|
34
|
+
*
|
|
35
|
+
* In-memory and per-process, like the Auto-Yes state it is read beside: a server
|
|
36
|
+
* restart empties it, and the cost is that a dialog opened within
|
|
37
|
+
* {@link ANTIGRAVITY_PERMISSION_RECEIPT_WINDOW_MS} of the restart is left to a
|
|
38
|
+
* human — never that a quotation is answered.
|
|
39
|
+
*/
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.ANTIGRAVITY_PERMISSION_RECEIPT_WINDOW_MS = void 0;
|
|
42
|
+
exports.recordAntigravityPermissionReceipt = recordAntigravityPermissionReceipt;
|
|
43
|
+
exports.hasRecentAntigravityPermissionReceipt = hasRecentAntigravityPermissionReceipt;
|
|
44
|
+
exports.resetAntigravityPermissionReceiptsForTests = resetAntigravityPermissionReceiptsForTests;
|
|
45
|
+
const auto_yes_state_1 = require("../../lib/auto-yes-state");
|
|
46
|
+
/**
|
|
47
|
+
* How long after a `PreToolUse` question a dialog still counts as its dialog.
|
|
48
|
+
*
|
|
49
|
+
* The hook's own timeout is 5 seconds, and the frame the poller reads can lag the
|
|
50
|
+
* pane by a capture interval on top, so 8 seconds is the hook timeout plus the
|
|
51
|
+
* margin for that lag. A `PreToolUse` that timed out never produced a dialog at
|
|
52
|
+
* all (agy proceeds without one), so the window does not need to be longer to
|
|
53
|
+
* cover it.
|
|
54
|
+
*/
|
|
55
|
+
exports.ANTIGRAVITY_PERMISSION_RECEIPT_WINDOW_MS = 8_000;
|
|
56
|
+
const receipts = globalThis.__antigravityPermissionReceipts ??
|
|
57
|
+
(globalThis.__antigravityPermissionReceipts = new Map());
|
|
58
|
+
/**
|
|
59
|
+
* How long an entry is kept before it is dropped on the next write.
|
|
60
|
+
*
|
|
61
|
+
* Far beyond the window on purpose: an entry older than the window is already
|
|
62
|
+
* useless to the reader, so this only bounds the Map for sessions nobody asks
|
|
63
|
+
* about again (a removed worktree, a killed instance).
|
|
64
|
+
*/
|
|
65
|
+
const RECEIPT_IDLE_TTL_MS = 60 * 60 * 1000;
|
|
66
|
+
function pruneExpiredReceipts(now) {
|
|
67
|
+
for (const [key, receipt] of receipts) {
|
|
68
|
+
if (now - receipt.at > RECEIPT_IDLE_TTL_MS)
|
|
69
|
+
receipts.delete(key);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Record that agy asked CommandMate about a tool call.
|
|
74
|
+
*
|
|
75
|
+
* A null `toolName` is not recorded: the payload could not be read, so there is
|
|
76
|
+
* nothing to say the request was a `PreToolUse` at all.
|
|
77
|
+
*
|
|
78
|
+
* @param worktreeId - Worktree the request resolved to
|
|
79
|
+
* @param cliToolId - CLI tool the request came from
|
|
80
|
+
* @param instanceId - Agent instance id (the tool id itself for the primary)
|
|
81
|
+
* @param toolName - Tool the request named, or null when the payload had none
|
|
82
|
+
* @param at - Epoch ms the request arrived
|
|
83
|
+
*/
|
|
84
|
+
function recordAntigravityPermissionReceipt(worktreeId, cliToolId, instanceId, toolName, at = Date.now()) {
|
|
85
|
+
if (toolName === null)
|
|
86
|
+
return;
|
|
87
|
+
pruneExpiredReceipts(at);
|
|
88
|
+
receipts.set((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId), { toolName, at });
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Did agy ask CommandMate about a tool call, for this instance, within
|
|
92
|
+
* {@link ANTIGRAVITY_PERMISSION_RECEIPT_WINDOW_MS}?
|
|
93
|
+
*
|
|
94
|
+
* @param worktreeId - Worktree the frame belongs to
|
|
95
|
+
* @param cliToolId - CLI tool the frame belongs to
|
|
96
|
+
* @param instanceId - Agent instance id; the tool id itself or `undefined` for
|
|
97
|
+
* the primary (the spelling the Auto-Yes poller carries)
|
|
98
|
+
* @param toolName - When given, the question must have named this tool. Omit it
|
|
99
|
+
* to ask only "was there one lately" — a frame carries no tool name.
|
|
100
|
+
* @param now - Epoch ms to measure against
|
|
101
|
+
*/
|
|
102
|
+
function hasRecentAntigravityPermissionReceipt(worktreeId, cliToolId, instanceId, toolName, now = Date.now()) {
|
|
103
|
+
const receipt = receipts.get((0, auto_yes_state_1.buildCompositeKey)(worktreeId, cliToolId, instanceId));
|
|
104
|
+
if (!receipt)
|
|
105
|
+
return false;
|
|
106
|
+
if (toolName !== undefined && receipt.toolName !== toolName)
|
|
107
|
+
return false;
|
|
108
|
+
return now - receipt.at <= exports.ANTIGRAVITY_PERMISSION_RECEIPT_WINDOW_MS;
|
|
109
|
+
}
|
|
110
|
+
/** Empty the record. Tests only: production entries age out on their own. */
|
|
111
|
+
function resetAntigravityPermissionReceiptsForTests() {
|
|
112
|
+
receipts.clear();
|
|
113
|
+
}
|
|
@@ -18,6 +18,8 @@ const db_1 = require("../../lib/db");
|
|
|
18
18
|
const ws_server_1 = require("../../lib/ws-server");
|
|
19
19
|
const prompt_detector_1 = require("../../lib/detection/prompt-detector");
|
|
20
20
|
const dialog_1 = require("../../lib/detection/tools/antigravity/dialog");
|
|
21
|
+
const detect_1 = require("../../lib/detection/tools/antigravity/detect");
|
|
22
|
+
const frame_1 = require("../../lib/detection/tools/frame");
|
|
21
23
|
const dialog_2 = require("../../lib/detection/tools/command-code/dialog");
|
|
22
24
|
const conversation_logger_1 = require("../../lib/conversation-logger");
|
|
23
25
|
const types_1 = require("../../lib/cli-tools/types");
|
|
@@ -33,6 +35,7 @@ const response_cleaner_1 = require("../response-cleaner");
|
|
|
33
35
|
const copilot_constants_1 = require("../../config/copilot-constants");
|
|
34
36
|
const tui_accumulator_1 = require("../tui-accumulator");
|
|
35
37
|
const prompt_dedup_1 = require("./prompt-dedup");
|
|
38
|
+
const antigravity_permission_receipts_1 = require("./antigravity-permission-receipts");
|
|
36
39
|
// Issue #2457: the same rollout table, `hasDialogRules` cross-check and
|
|
37
40
|
// `detectDialog` seam Auto-Yes reads, reached through the presence helper rather
|
|
38
41
|
// than through `evaluateAutoYesDialogGate` — see `isNumberedDialogVouched`.
|
|
@@ -226,9 +229,14 @@ function buildPromptExtractionResult(lines, lastCapturedLine, totalLines, buffer
|
|
|
226
229
|
* (Issue #499 Item 4); must be the split of THIS string, not of the raw capture
|
|
227
230
|
* @param rawFrame - the SAME tick's capture with its box drawing intact (ANSI
|
|
228
231
|
* optional), for the tool readers anchored on it (Issue #2522)
|
|
232
|
+
* @param receiptScope - whose frame this is, when the caller answers it
|
|
233
|
+
* automatically (Issue #2849). For agy only: a frame that reads as a prompt is
|
|
234
|
+
* then handed back as no prompt unless agy asked CommandMate about a tool call
|
|
235
|
+
* for that instance a moment ago. Omitted, the reading is not gated — which is
|
|
236
|
+
* what every caller that only DISPLAYS the frame wants.
|
|
229
237
|
* @returns PromptDetectionResult with isPrompt, promptData, and cleanContent
|
|
230
238
|
*/
|
|
231
|
-
function detectPromptOnCleanFrame(cleanOutput, cliToolId, precomputedLines, rawFrame) {
|
|
239
|
+
function detectPromptOnCleanFrame(cleanOutput, cliToolId, precomputedLines, rawFrame, receiptScope) {
|
|
232
240
|
// Issue #2364: agy's `↑/↓ Navigate` dialogs are read by agy's own reader
|
|
233
241
|
// before the generic pass, on the same spelling `tools/antigravity/detect.ts`
|
|
234
242
|
// reads them on. The generic multiple-choice parser takes one row per option
|
|
@@ -246,8 +254,11 @@ function detectPromptOnCleanFrame(cleanOutput, cliToolId, precomputedLines, rawF
|
|
|
246
254
|
// API published the very same screen as an answerable four-option prompt.
|
|
247
255
|
if (cliToolId === 'antigravity') {
|
|
248
256
|
const dialog = (0, dialog_1.detectAntigravityNumberedDialogPrompt)(cleanOutput);
|
|
249
|
-
if (dialog !== null)
|
|
250
|
-
return
|
|
257
|
+
if (dialog !== null) {
|
|
258
|
+
return isWithheldForWantOfReceipt(receiptScope)
|
|
259
|
+
? { isPrompt: false, cleanContent: cleanOutput.trim() }
|
|
260
|
+
: dialog;
|
|
261
|
+
}
|
|
251
262
|
}
|
|
252
263
|
// Issue #2522: Command Code's footer-less `AskUserQuestion`, read by the same
|
|
253
264
|
// module `tools/command-code/detect.ts` publishes its status from — so the
|
|
@@ -275,7 +286,65 @@ function detectPromptOnCleanFrame(cleanOutput, cliToolId, precomputedLines, rawF
|
|
|
275
286
|
}
|
|
276
287
|
}
|
|
277
288
|
const promptOptions = (0, cli_patterns_1.buildDetectPromptOptions)(cliToolId);
|
|
278
|
-
|
|
289
|
+
const result = (0, prompt_detector_1.detectPrompt)(cleanOutput, precomputedLines ? { ...promptOptions, precomputedLines } : promptOptions);
|
|
290
|
+
// Issue #2851: agy's reader above declines a dialog quoted in a reply (#2845),
|
|
291
|
+
// and this generic pass then read the quotation itself — `Do you want to
|
|
292
|
+
// proceed?` and its four options, above a live `>` composer — as an answerable
|
|
293
|
+
// `multiple_choice`. agy's Auto-Yes gate row is `legacy`, so nothing after this
|
|
294
|
+
// point judges the frame again and the poller answered a dialog nobody had
|
|
295
|
+
// opened. The status side declines the same candidate with the same predicate
|
|
296
|
+
// (`isStalePrompt`, #2845): agy draws its numbered screens in place of the
|
|
297
|
+
// composer or below it, never above it, so a composer under the list's last
|
|
298
|
+
// row makes the list a quotation.
|
|
299
|
+
//
|
|
300
|
+
// `rawFrame` when the caller has it, and `cleanOutput` otherwise. The status
|
|
301
|
+
// side normalises the capture as captured and the predicate then strips box
|
|
302
|
+
// drawing exactly once; handing it `cleanOutput` — already stripped once, and
|
|
303
|
+
// `stripBoxDrawing` is not idempotent — would strip a second time and could
|
|
304
|
+
// read different rows.
|
|
305
|
+
if (cliToolId === 'antigravity' &&
|
|
306
|
+
result.isPrompt &&
|
|
307
|
+
(0, detect_1.isAntigravityQuotedNumberedList)((0, frame_1.normalizeFrame)(rawFrame ?? cleanOutput), result)) {
|
|
308
|
+
return { isPrompt: false, cleanContent: cleanOutput.trim() };
|
|
309
|
+
}
|
|
310
|
+
// Issue #2849: the same withholding on this exit. agy's reader answering `null`
|
|
311
|
+
// does not mean the frame is no dialog — the generic pass above reads shapes
|
|
312
|
+
// agy's reader declines, and #2851 showed it can read a quotation — so a gate
|
|
313
|
+
// that covered only the reader's exit would leave this one open.
|
|
314
|
+
if (cliToolId === 'antigravity' && result.isPrompt && isWithheldForWantOfReceipt(receiptScope)) {
|
|
315
|
+
return { isPrompt: false, cleanContent: cleanOutput.trim() };
|
|
316
|
+
}
|
|
317
|
+
return result;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Should an agy frame that reads as a prompt be treated as no prompt because
|
|
321
|
+
* agy asked CommandMate about no tool call lately? (Issue #2849)
|
|
322
|
+
*
|
|
323
|
+
* agy asks (`PreToolUse`) before it draws ANY approval dialog and waits for the
|
|
324
|
+
* reply, so a dialog that is really open follows a question a moment before it,
|
|
325
|
+
* and one that is only quoted in a reply follows nothing. The frame carries no
|
|
326
|
+
* tool name, so the check is time-only.
|
|
327
|
+
*
|
|
328
|
+
* Not gated (false) when there is no scope: a caller that only shows the frame —
|
|
329
|
+
* the status API, the response poller's stored `prompt` row, the notification —
|
|
330
|
+
* must keep showing a real dialog on a machine whose hook is not installed or
|
|
331
|
+
* did not reach us. Only the caller that ANSWERS the frame opts in, because for
|
|
332
|
+
* it a missed answer costs a human a keystroke and a wrong one is sent as an
|
|
333
|
+
* utterance nobody asked for.
|
|
334
|
+
*
|
|
335
|
+
* `debug`, not `info`: the poller re-reads a static pane every 2s, so a
|
|
336
|
+
* quotation left on screen would print this on every tick.
|
|
337
|
+
*/
|
|
338
|
+
function isWithheldForWantOfReceipt(scope) {
|
|
339
|
+
if (scope === undefined)
|
|
340
|
+
return false;
|
|
341
|
+
if ((0, antigravity_permission_receipts_1.hasRecentAntigravityPermissionReceipt)(scope.worktreeId, 'antigravity', scope.instanceId))
|
|
342
|
+
return false;
|
|
343
|
+
logger.debug('antigravity-dialog-no-recent-receipt', {
|
|
344
|
+
worktreeId: scope.worktreeId,
|
|
345
|
+
instanceId: scope.instanceId ?? 'antigravity',
|
|
346
|
+
});
|
|
347
|
+
return true;
|
|
279
348
|
}
|
|
280
349
|
/**
|
|
281
350
|
* Is the generic parser's numbered-list candidate a dialog the tool vouches for?
|
|
@@ -85,6 +85,7 @@ const prompt_waiting_composition_1 = require("../../lib/session/prompt-waiting-c
|
|
|
85
85
|
const provisional_turn_1 = require("../../lib/session/provisional-turn");
|
|
86
86
|
const status_evidence_1 = require("../../lib/session/status-evidence");
|
|
87
87
|
const ask_user_question_prompt_1 = require("../../lib/session/ask-user-question-prompt");
|
|
88
|
+
const layer_disagreement_1 = require("../../lib/session/layer-disagreement");
|
|
88
89
|
const structured_prompt_1 = require("../../lib/session/structured-prompt");
|
|
89
90
|
const logger = (0, logger_1.createLogger)('current-output-builder');
|
|
90
91
|
/**
|
|
@@ -1093,6 +1094,30 @@ async function buildPayload(db, worktreeId, cliToolId, instanceId) {
|
|
|
1093
1094
|
obstruction: paneObstruction,
|
|
1094
1095
|
});
|
|
1095
1096
|
}
|
|
1097
|
+
// Issue #2843: the opposite gap — the scraper reads a dialog on a turn the
|
|
1098
|
+
// agent's own `Stop` closed. Logged only (see `layer-disagreement.ts`); fed the
|
|
1099
|
+
// SCRAPER's verdict, because the merge lets a scraper `waiting` win and would
|
|
1100
|
+
// hide the very disagreement this records.
|
|
1101
|
+
const disagreement = (0, layer_disagreement_1.classifyLayerDisagreement)({
|
|
1102
|
+
supportedEvents: eventSource.capabilities.supportedEvents,
|
|
1103
|
+
scraperStatus: statusResult.status,
|
|
1104
|
+
scraperReason: statusResult.reason,
|
|
1105
|
+
hasActivePrompt: scraperPromptWaiting,
|
|
1106
|
+
lastEventType: structuredEvents.lastEventType,
|
|
1107
|
+
lastEventDetail: structuredEvents.lastEventDetail,
|
|
1108
|
+
});
|
|
1109
|
+
if (disagreement !== null) {
|
|
1110
|
+
(0, layer_disagreement_1.reportLayerDisagreement)({
|
|
1111
|
+
compositeKey,
|
|
1112
|
+
worktreeId,
|
|
1113
|
+
cliToolId,
|
|
1114
|
+
instanceId: resolvedInstanceId,
|
|
1115
|
+
turnId: structuredEvents.turnId,
|
|
1116
|
+
kind: disagreement,
|
|
1117
|
+
scraperReason: statusResult.reason,
|
|
1118
|
+
frame: output,
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1096
1121
|
// Issue #1725: the structured layer saw a dialog the scraper did not. That
|
|
1097
1122
|
// gap is the fact worth keeping — see recordStructuredPrompt.
|
|
1098
1123
|
if (promptWaiting !== null && structuredFacts !== null && !scraperPromptWaiting && !promptWaiting.recorded) {
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* The screen says "a dialog is open", the agent's own hooks say "the turn is
|
|
4
|
+
* over" — record it (Issue #2843).
|
|
5
|
+
*
|
|
6
|
+
* A tool's dialogs are read off the pane (`lib/detection/tools/*`), and the pane
|
|
7
|
+
* is free text: every few weeks a new wording, a new screen or a quoted
|
|
8
|
+
* paragraph was misread as a dialog, and each time the report came from a user
|
|
9
|
+
* who saw a card that should not have been there. The hook layer is an
|
|
10
|
+
* independent witness that already runs on every poll: the agent fires `Stop`
|
|
11
|
+
* when a turn ends, and a dialog that belongs to a turn (an approval, a
|
|
12
|
+
* question) only ever appears inside one. So a screen `waiting` whose newest
|
|
13
|
+
* hook event is `stop` is either a dialog the user opened themselves (`/model`,
|
|
14
|
+
* `/experimental` …) or a misreading.
|
|
15
|
+
*
|
|
16
|
+
* This module does NOT change any verdict. `mergeStructuredStatus` deliberately
|
|
17
|
+
* lets the screen's `waiting` win (Claude emits nothing while its picker is up,
|
|
18
|
+
* #1708), and overturning that is a separate decision that needs the numbers
|
|
19
|
+
* this module produces. What it does is leave one log line per turn, with the
|
|
20
|
+
* frame's tail, so the next misreading arrives as a fixture candidate instead
|
|
21
|
+
* of as a bug report.
|
|
22
|
+
*
|
|
23
|
+
* Which tools qualify is decided by what their hooks deliver, not by name: the
|
|
24
|
+
* rule needs BOTH ends of a turn. A tool whose hooks never announce the start of
|
|
25
|
+
* a turn (`user_prompt_submit` — antigravity, Command Code) keeps the previous
|
|
26
|
+
* turn's `stop` as its newest event while the next turn runs, so a genuine
|
|
27
|
+
* dialog in the middle of that turn would be logged as a disagreement.
|
|
28
|
+
* Likewise a `stop` whose detail is `self_resume_pending` says "the turn is
|
|
29
|
+
* closed but the agent wakes itself", not "the agent is done".
|
|
30
|
+
*
|
|
31
|
+
* The two kinds are logged separately because they mean different things:
|
|
32
|
+
*
|
|
33
|
+
* - `approval-after-stop` — the screen reads an ANSWERABLE prompt
|
|
34
|
+
* (`hasActivePrompt`). The agent asks for permission before it draws a
|
|
35
|
+
* dialog, inside a turn, so after `Stop` every line of this kind is a
|
|
36
|
+
* detector defect to fixture.
|
|
37
|
+
* - `menu-after-stop` — the screen reads a selection list / pager. A user who
|
|
38
|
+
* opened `/model` after the turn produces this legitimately, so these lines
|
|
39
|
+
* are triaged, not fixed on sight.
|
|
40
|
+
*/
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.DISAGREEMENT_FRAME_TAIL_ROWS = void 0;
|
|
43
|
+
exports.classifyLayerDisagreement = classifyLayerDisagreement;
|
|
44
|
+
exports.reportLayerDisagreement = reportLayerDisagreement;
|
|
45
|
+
exports.resetLayerDisagreementForTests = resetLayerDisagreementForTests;
|
|
46
|
+
const status_detector_1 = require("../../lib/detection/status-detector");
|
|
47
|
+
const cli_patterns_1 = require("../../lib/detection/cli-patterns");
|
|
48
|
+
const agent_event_types_1 = require("../../lib/hooks/agent-event-types");
|
|
49
|
+
const logger_1 = require("../../lib/logger");
|
|
50
|
+
const logger = (0, logger_1.createLogger)('layer-disagreement');
|
|
51
|
+
/**
|
|
52
|
+
* Classify one poll. Pure.
|
|
53
|
+
*
|
|
54
|
+
* Only tools whose hooks deliver both `user_prompt_submit` and `stop` qualify
|
|
55
|
+
* (claude, codex, copilot, gemini, opencode): without the turn's start, "the
|
|
56
|
+
* newest event is `stop`" cannot tell a closed turn from a running one.
|
|
57
|
+
*/
|
|
58
|
+
function classifyLayerDisagreement(input) {
|
|
59
|
+
if (!input.supportedEvents.includes('user_prompt_submit') ||
|
|
60
|
+
!input.supportedEvents.includes('stop')) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
if (input.scraperStatus !== 'waiting')
|
|
64
|
+
return null;
|
|
65
|
+
if (input.lastEventType !== 'stop')
|
|
66
|
+
return null;
|
|
67
|
+
if (input.lastEventDetail === agent_event_types_1.SELF_RESUME_PENDING_DETAIL)
|
|
68
|
+
return null;
|
|
69
|
+
if (input.hasActivePrompt)
|
|
70
|
+
return 'approval-after-stop';
|
|
71
|
+
if (status_detector_1.SELECTION_LIST_REASONS.has(input.scraperReason))
|
|
72
|
+
return 'menu-after-stop';
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
/** How many rows of the frame's tail go into the log line. */
|
|
76
|
+
exports.DISAGREEMENT_FRAME_TAIL_ROWS = 40;
|
|
77
|
+
const reported = globalThis.__layerDisagreementReported ??
|
|
78
|
+
(globalThis.__layerDisagreementReported = new Set());
|
|
79
|
+
/** Bound on {@link reported}; at the cap the set is cleared (worst case: one repeat line). */
|
|
80
|
+
const REPORTED_CAP = 512;
|
|
81
|
+
/**
|
|
82
|
+
* Log one disagreement, once per (session, turn, kind).
|
|
83
|
+
*
|
|
84
|
+
* @returns true when a line was written (for tests)
|
|
85
|
+
*/
|
|
86
|
+
function reportLayerDisagreement(report) {
|
|
87
|
+
const key = `${report.compositeKey}|${report.turnId ?? '-'}|${report.kind}`;
|
|
88
|
+
if (reported.has(key))
|
|
89
|
+
return false;
|
|
90
|
+
if (reported.size >= REPORTED_CAP)
|
|
91
|
+
reported.clear();
|
|
92
|
+
reported.add(key);
|
|
93
|
+
const rows = (0, cli_patterns_1.stripAnsi)(report.frame).split('\n').filter((row) => row.trim() !== '');
|
|
94
|
+
logger.warn('layerDisagreement', {
|
|
95
|
+
kind: report.kind,
|
|
96
|
+
worktreeId: report.worktreeId,
|
|
97
|
+
cliToolId: report.cliToolId,
|
|
98
|
+
instanceId: report.instanceId,
|
|
99
|
+
turnId: report.turnId,
|
|
100
|
+
scraperReason: report.scraperReason,
|
|
101
|
+
frameTail: rows.slice(-exports.DISAGREEMENT_FRAME_TAIL_ROWS).join('\n'),
|
|
102
|
+
});
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
/** Test-only: forget what has been reported. */
|
|
106
|
+
function resetLayerDisagreementForTests() {
|
|
107
|
+
reported.clear();
|
|
108
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.41.0",
|
|
3
|
+
"date": "2026-09-25",
|
|
4
|
+
"highlight": {
|
|
5
|
+
"ja": "エージェントが返答の中でダイアログの文面を引用しただけなのに、ダイアログが開いていると表示される問題を直しました。",
|
|
6
|
+
"en": "Fixed a dialog being shown as open when the agent had only quoted a dialog's text in its reply."
|
|
7
|
+
},
|
|
8
|
+
"added": [],
|
|
9
|
+
"improved": [
|
|
10
|
+
{
|
|
11
|
+
"ja": "Antigravity の Auto-Yes は、本当に確認を求められたときだけ承認に答えるようになりました。",
|
|
12
|
+
"en": "Antigravity's Auto-Yes now answers an approval only when the agent actually asked for one."
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"fixed": [
|
|
16
|
+
{
|
|
17
|
+
"ja": "Codex・Antigravity・Command Code・Claude で、入力待ちなのに選択リストやダイアログが開いていると表示される問題を直しました。",
|
|
18
|
+
"en": "Fixed Codex, Antigravity, Command Code and Claude showing an open selection list or dialog while waiting for input."
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"ja": "Antigravity の Auto-Yes が、返答に引用されたダイアログの文面に自動で答えてしまう問題を直しました。",
|
|
22
|
+
"en": "Fixed Antigravity's Auto-Yes answering dialog text that was only quoted in a reply."
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"ja": "サイドバーのセッション表示で、選んだ並び順どおりに並ぶようになりました。",
|
|
26
|
+
"en": "The session view in the sidebar now follows the sort order you choose."
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
File without changes
|
|
File without changes
|