cursor-opencode-provider 0.6.4 → 0.6.7

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.
@@ -653,6 +653,199 @@ export function createMessageTypes() {
653
653
  { id: 2, name: "working_directory", type: "string" },
654
654
  { id: 3, name: "error", type: "string" },
655
655
  ]);
656
+ // ── Soft-deny stubs for known unsupported Cursor-native exec variants ──
657
+ // These are encode-only: enough to emit a populated deny, not full success.
658
+ // Canonical field numbers from agent.proto ExecClientMessage.
659
+ // ShellResult is also the live reply for exec #2 shell_args (OpenCode bash).
660
+ addType(root, "ShellSuccess", [
661
+ { id: 1, name: "command", type: "string" },
662
+ { id: 2, name: "working_directory", type: "string" },
663
+ { id: 3, name: "exit_code", type: "int32" },
664
+ { id: 4, name: "signal", type: "string" },
665
+ { id: 5, name: "stdout", type: "string" },
666
+ { id: 6, name: "stderr", type: "string" },
667
+ { id: 7, name: "execution_time", type: "int32" },
668
+ { id: 9, name: "shell_id", type: "uint32" },
669
+ { id: 11, name: "pid", type: "uint32" },
670
+ { id: 12, name: "ms_to_wait", type: "int32" },
671
+ { id: 13, name: "local_execution_time_ms", type: "int32" },
672
+ { id: 14, name: "background_reason", type: "uint32" },
673
+ ]);
674
+ addType(root, "ShellFailure", [
675
+ { id: 1, name: "command", type: "string" },
676
+ { id: 2, name: "working_directory", type: "string" },
677
+ { id: 3, name: "exit_code", type: "int32" },
678
+ { id: 4, name: "signal", type: "string" },
679
+ { id: 5, name: "stdout", type: "string" },
680
+ { id: 6, name: "stderr", type: "string" },
681
+ { id: 7, name: "execution_time", type: "int32" },
682
+ { id: 10, name: "abort_reason", type: "uint32" },
683
+ { id: 11, name: "aborted", type: "bool" },
684
+ ]);
685
+ addType(root, "ShellTimeout", [
686
+ { id: 1, name: "command", type: "string" },
687
+ { id: 2, name: "working_directory", type: "string" },
688
+ { id: 3, name: "timeout_ms", type: "int32" },
689
+ ]);
690
+ addType(root, "ShellResult", [
691
+ { id: 1, name: "success", type: "ShellSuccess" },
692
+ { id: 2, name: "failure", type: "ShellFailure" },
693
+ { id: 3, name: "timeout", type: "ShellTimeout" },
694
+ { id: 4, name: "rejected", type: "ShellRejected" },
695
+ { id: 102, name: "is_background", type: "bool" },
696
+ { id: 104, name: "pid", type: "uint32" },
697
+ ], [{ name: "result", fields: ["success", "failure", "timeout", "rejected"] }]);
698
+ addType(root, "DiagnosticsError", [
699
+ { id: 1, name: "path", type: "string" },
700
+ { id: 2, name: "error", type: "string" },
701
+ ]);
702
+ addType(root, "DiagnosticsResult", [
703
+ { id: 2, name: "error", type: "DiagnosticsError" },
704
+ ], [{ name: "result", fields: ["error"] }]);
705
+ addType(root, "FetchError", [
706
+ { id: 1, name: "url", type: "string" },
707
+ { id: 2, name: "error", type: "string" },
708
+ ]);
709
+ addType(root, "FetchResult", [
710
+ { id: 2, name: "error", type: "FetchError" },
711
+ ], [{ name: "result", fields: ["error"] }]);
712
+ addType(root, "RecordScreenFailure", [
713
+ { id: 1, name: "error", type: "string" },
714
+ ]);
715
+ addType(root, "RecordScreenResult", [
716
+ { id: 4, name: "failure", type: "RecordScreenFailure" },
717
+ ], [{ name: "result", fields: ["failure"] }]);
718
+ addType(root, "ComputerUseError", [
719
+ { id: 1, name: "error", type: "string" },
720
+ ]);
721
+ addType(root, "ComputerUseResult", [
722
+ { id: 2, name: "error", type: "ComputerUseError" },
723
+ ], [{ name: "result", fields: ["error"] }]);
724
+ addType(root, "WriteShellStdinError", [
725
+ { id: 1, name: "error", type: "string" },
726
+ ]);
727
+ addType(root, "WriteShellStdinResult", [
728
+ { id: 2, name: "error", type: "WriteShellStdinError" },
729
+ ], [{ name: "result", fields: ["error"] }]);
730
+ addType(root, "SubagentAwaitError", [
731
+ { id: 1, name: "agent_id", type: "string" },
732
+ { id: 2, name: "error", type: "string" },
733
+ ]);
734
+ addType(root, "SubagentAwaitResult", [
735
+ { id: 4, name: "error", type: "SubagentAwaitError" },
736
+ ], [{ name: "result", fields: ["error"] }]);
737
+ addType(root, "SmartModeClassifierError", [
738
+ { id: 1, name: "error", type: "string" },
739
+ ]);
740
+ addType(root, "SmartModeClassifierResult", [
741
+ { id: 2, name: "error", type: "SmartModeClassifierError" },
742
+ ], [{ name: "result", fields: ["error"] }]);
743
+ addType(root, "CanvasDiagnosticsError", [
744
+ { id: 1, name: "path", type: "string" },
745
+ { id: 2, name: "error", type: "string" },
746
+ ]);
747
+ addType(root, "CanvasDiagnosticsResult", [
748
+ { id: 2, name: "error", type: "CanvasDiagnosticsError" },
749
+ ], [{ name: "result", fields: ["error"] }]);
750
+ addType(root, "ShellAllowlistPrecheckResult", [
751
+ { id: 1, name: "allowlisted", type: "bool" },
752
+ ]);
753
+ addType(root, "McpAllowlistPrecheckResult", [
754
+ { id: 1, name: "allowlisted", type: "bool" },
755
+ ]);
756
+ addType(root, "WebFetchAllowlistPrecheckResult", [
757
+ { id: 1, name: "allowlisted", type: "bool" },
758
+ ]);
759
+ addType(root, "ForceBackgroundShellResult", [
760
+ { id: 1, name: "status", type: "uint32" },
761
+ ]);
762
+ addType(root, "ForceBackgroundSubagentResult", [
763
+ { id: 1, name: "status", type: "uint32" },
764
+ ]);
765
+ addType(root, "ConversationSearchHit", [
766
+ { id: 1, name: "conversation_id", type: "string" },
767
+ { id: 2, name: "title", type: "string" },
768
+ { id: 3, name: "source", type: "uint32" },
769
+ { id: 4, name: "updated_at_ms", type: "int64" },
770
+ { id: 5, name: "snippet", type: "string" },
771
+ ]);
772
+ addType(root, "ConversationSearchSuccess", [
773
+ { id: 1, name: "hits", type: "ConversationSearchHit", repeated: true },
774
+ { id: 2, name: "truncated", type: "bool" },
775
+ { id: 3, name: "partial", type: "bool" },
776
+ { id: 4, name: "rebuilding", type: "bool" },
777
+ ]);
778
+ addType(root, "ConversationSearchError", [
779
+ { id: 1, name: "error", type: "string" },
780
+ ]);
781
+ addType(root, "ConversationSearchResult", [
782
+ { id: 1, name: "success", type: "ConversationSearchSuccess" },
783
+ { id: 2, name: "error", type: "ConversationSearchError" },
784
+ ], [{ name: "result", fields: ["success", "error"] }]);
785
+ addType(root, "AgentStoreConflictError", [
786
+ { id: 1, name: "error", type: "string" },
787
+ ]);
788
+ addType(root, "AgentStoreConflictResult", [
789
+ { id: 2, name: "error", type: "AgentStoreConflictError" },
790
+ ], [{ name: "result", fields: ["error"] }]);
791
+ addType(root, "AdoptResult", [
792
+ { id: 1, name: "source_agent_id", type: "string" },
793
+ { id: 2, name: "target_agent_id", type: "string" },
794
+ { id: 3, name: "project_root_id", type: "string" },
795
+ { id: 5, name: "error", type: "string" },
796
+ ], [{ name: "result", fields: ["error"] }]);
797
+ // aiserver.v1.GetDiffRequest / GetDiffResponse (exec #44). Enums as uint32
798
+ // so protobufjs json decode does not stringify output_format / diff_type.
799
+ addType(root, "GitDiffChunk", [
800
+ { id: 1, name: "content", type: "string" },
801
+ { id: 2, name: "lines", type: "string", repeated: true },
802
+ { id: 3, name: "old_start", type: "int32" },
803
+ { id: 4, name: "old_lines", type: "int32" },
804
+ { id: 5, name: "new_start", type: "int32" },
805
+ { id: 6, name: "new_lines", type: "int32" },
806
+ ]);
807
+ addType(root, "GitFileDiff", [
808
+ { id: 1, name: "from", type: "string" },
809
+ { id: 2, name: "to", type: "string" },
810
+ { id: 3, name: "chunks", type: "GitDiffChunk", repeated: true },
811
+ { id: 4, name: "added", type: "int32" },
812
+ { id: 5, name: "removed", type: "int32" },
813
+ { id: 6, name: "before_file_contents", type: "string" },
814
+ { id: 7, name: "after_file_contents", type: "string" },
815
+ { id: 8, name: "is_generated", type: "bool" },
816
+ ]);
817
+ addType(root, "GitDiff", [
818
+ { id: 1, name: "diffs", type: "GitFileDiff", repeated: true },
819
+ { id: 2, name: "diff_type", type: "uint32" },
820
+ ]);
821
+ addType(root, "GitDiffSubmoduleDiff", [
822
+ { id: 1, name: "relative_path", type: "string" },
823
+ { id: 2, name: "diff", type: "GitDiff" },
824
+ { id: 3, name: "errored", type: "bool" },
825
+ ]);
826
+ addType(root, "GetDiffRequest", [
827
+ { id: 1, name: "cwd", type: "string" },
828
+ { id: 2, name: "ref", type: "string" },
829
+ { id: 3, name: "base_ref", type: "string" },
830
+ { id: 4, name: "merge_base", type: "bool" },
831
+ { id: 5, name: "target_paths", type: "string", repeated: true },
832
+ { id: 6, name: "unified_context_lines", type: "int32" },
833
+ { id: 7, name: "max_untracked_files", type: "int32" },
834
+ { id: 8, name: "output_format", type: "uint32" },
835
+ { id: 9, name: "submodule_recurse_depth", type: "int32" },
836
+ { id: 10, name: "include_space_changes", type: "bool" },
837
+ { id: 11, name: "committed_only", type: "bool" },
838
+ { id: 12, name: "compute_patch_id", type: "bool" },
839
+ { id: 13, name: "return_head_sha", type: "bool" },
840
+ { id: 14, name: "max_response_bytes", type: "int32" },
841
+ ]);
842
+ addType(root, "GetDiffResponse", [
843
+ { id: 1, name: "diff", type: "GitDiff" },
844
+ { id: 2, name: "submodule_diffs", type: "GitDiffSubmoduleDiff", repeated: true },
845
+ { id: 3, name: "patch_id", type: "string" },
846
+ { id: 4, name: "head_sha", type: "string" },
847
+ { id: 5, name: "has_uncommitted_changes", type: "bool" },
848
+ ]);
656
849
  // Cursor's non-blocking shell path is a separate exec variant from the
657
850
  // foreground ShellStream above. The host only needs the fields used at the
658
851
  // OpenCode boundary; protobufjs safely skips the richer classifier/approval
@@ -965,6 +1158,7 @@ export function createMessageTypes() {
965
1158
  { id: 1, name: "id", type: "uint32" },
966
1159
  { id: 15, name: "exec_id", type: "string" },
967
1160
  { id: 19, name: "span", type: "string" },
1161
+ { id: 2, name: "shell_args", type: "ShellArgs" },
968
1162
  { id: 3, name: "write_args", type: "WriteArgs" },
969
1163
  { id: 4, name: "delete_args", type: "DeleteArgs" },
970
1164
  { id: 5, name: "grep_args", type: "GrepArgs" },
@@ -978,6 +1172,7 @@ export function createMessageTypes() {
978
1172
  { id: 18, name: "read_mcp_resource_exec_args", type: "ReadMcpResourceExecArgs" },
979
1173
  { id: 28, name: "subagent_args", type: "SubagentArgs" },
980
1174
  { id: 36, name: "mcp_state_exec_args", type: "McpStateExecArgs" },
1175
+ { id: 44, name: "git_diff_request", type: "GetDiffRequest" },
981
1176
  { id: 45, name: "pi_read_args", type: "PiReadToolArgs" },
982
1177
  { id: 46, name: "pi_bash_args", type: "PiBashToolArgs" },
983
1178
  { id: 47, name: "pi_edit_args", type: "PiEditToolArgs" },
@@ -986,10 +1181,10 @@ export function createMessageTypes() {
986
1181
  { id: 50, name: "pi_find_args", type: "PiFindToolArgs" },
987
1182
  { id: 51, name: "pi_ls_args", type: "PiLsToolArgs" },
988
1183
  ], [{ name: "args", fields: [
989
- "write_args", "delete_args", "grep_args", "read_args", "ls_args",
1184
+ "shell_args", "write_args", "delete_args", "grep_args", "read_args", "ls_args",
990
1185
  "request_context_args", "mcp_args", "shell_stream_args", "background_shell_spawn_args",
991
1186
  "list_mcp_resources_exec_args", "read_mcp_resource_exec_args", "mcp_state_exec_args",
992
- "subagent_args",
1187
+ "subagent_args", "git_diff_request",
993
1188
  "pi_read_args", "pi_bash_args", "pi_edit_args", "pi_write_args",
994
1189
  "pi_grep_args", "pi_find_args", "pi_ls_args",
995
1190
  ] }]);
@@ -998,19 +1193,35 @@ export function createMessageTypes() {
998
1193
  { id: 1, name: "id", type: "uint32" },
999
1194
  { id: 15, name: "exec_id", type: "string" },
1000
1195
  { id: 39, name: "local_execution_time_ms", type: "uint64" },
1196
+ { id: 2, name: "shell_result", type: "ShellResult" },
1001
1197
  { id: 3, name: "write_result", type: "WriteResult" },
1002
1198
  { id: 4, name: "delete_result", type: "DeleteResult" },
1003
1199
  { id: 5, name: "grep_result", type: "GrepResult" },
1004
1200
  { id: 7, name: "read_result", type: "ReadResult" },
1005
1201
  { id: 8, name: "ls_result", type: "LsResult" },
1202
+ { id: 9, name: "diagnostics_result", type: "DiagnosticsResult" },
1006
1203
  { id: 10, name: "request_context_result", type: "RequestContextResult" },
1007
1204
  { id: 11, name: "mcp_result", type: "McpResult" },
1008
1205
  { id: 14, name: "shell_stream", type: "ShellStream" },
1009
1206
  { id: 16, name: "background_shell_spawn_result", type: "BackgroundShellSpawnResult" },
1010
1207
  { id: 17, name: "list_mcp_resources_exec_result", type: "ListMcpResourcesExecResult" },
1011
1208
  { id: 18, name: "read_mcp_resource_exec_result", type: "ReadMcpResourceExecResult" },
1209
+ { id: 20, name: "fetch_result", type: "FetchResult" },
1210
+ { id: 21, name: "record_screen_result", type: "RecordScreenResult" },
1211
+ { id: 22, name: "computer_use_result", type: "ComputerUseResult" },
1212
+ { id: 23, name: "write_shell_stdin_result", type: "WriteShellStdinResult" },
1012
1213
  { id: 28, name: "subagent_result", type: "SubagentResult" },
1214
+ { id: 29, name: "redacted_read_result", type: "ReadResult" },
1215
+ { id: 30, name: "force_background_shell_result", type: "ForceBackgroundShellResult" },
1216
+ { id: 31, name: "force_background_subagent_result", type: "ForceBackgroundSubagentResult" },
1013
1217
  { id: 36, name: "mcp_state_exec_result", type: "McpStateExecResult" },
1218
+ { id: 37, name: "subagent_await_result", type: "SubagentAwaitResult" },
1219
+ { id: 38, name: "smart_mode_classifier_result", type: "SmartModeClassifierResult" },
1220
+ { id: 40, name: "canvas_diagnostics_result", type: "CanvasDiagnosticsResult" },
1221
+ { id: 41, name: "shell_allowlist_precheck_result", type: "ShellAllowlistPrecheckResult" },
1222
+ { id: 42, name: "mcp_allowlist_precheck_result", type: "McpAllowlistPrecheckResult" },
1223
+ { id: 43, name: "web_fetch_allowlist_precheck_result", type: "WebFetchAllowlistPrecheckResult" },
1224
+ { id: 44, name: "git_diff_response", type: "GetDiffResponse" },
1014
1225
  { id: 46, name: "pi_read_result", type: "PiReadExecResult" },
1015
1226
  { id: 47, name: "pi_bash_result", type: "PiBashExecResult" },
1016
1227
  { id: 48, name: "pi_edit_result", type: "PiEditExecResult" },
@@ -1018,13 +1229,25 @@ export function createMessageTypes() {
1018
1229
  { id: 50, name: "pi_grep_result", type: "PiGrepExecResult" },
1019
1230
  { id: 51, name: "pi_find_result", type: "PiFindExecResult" },
1020
1231
  { id: 52, name: "pi_ls_result", type: "PiLsExecResult" },
1232
+ { id: 53, name: "conversation_search_result", type: "ConversationSearchResult" },
1233
+ { id: 54, name: "agent_store_conflict_result", type: "AgentStoreConflictResult" },
1234
+ { id: 55, name: "mini_swe_agent_bash_result", type: "ShellResult" },
1235
+ { id: 56, name: "adopt_result", type: "AdoptResult" },
1021
1236
  ], [{ name: "result", fields: [
1022
- "write_result", "delete_result", "grep_result", "read_result", "ls_result",
1023
- "request_context_result", "mcp_result", "shell_stream", "background_shell_spawn_result",
1024
- "list_mcp_resources_exec_result", "read_mcp_resource_exec_result", "mcp_state_exec_result",
1025
- "subagent_result",
1237
+ "shell_result", "write_result", "delete_result", "grep_result", "read_result", "ls_result",
1238
+ "diagnostics_result", "request_context_result", "mcp_result", "shell_stream", "background_shell_spawn_result",
1239
+ "list_mcp_resources_exec_result", "read_mcp_resource_exec_result",
1240
+ "fetch_result", "record_screen_result", "computer_use_result", "write_shell_stdin_result",
1241
+ "subagent_result", "redacted_read_result",
1242
+ "force_background_shell_result", "force_background_subagent_result",
1243
+ "mcp_state_exec_result",
1244
+ "subagent_await_result", "smart_mode_classifier_result", "canvas_diagnostics_result",
1245
+ "shell_allowlist_precheck_result", "mcp_allowlist_precheck_result", "web_fetch_allowlist_precheck_result",
1246
+ "git_diff_response",
1026
1247
  "pi_read_result", "pi_bash_result", "pi_edit_result", "pi_write_result",
1027
1248
  "pi_grep_result", "pi_find_result", "pi_ls_result",
1249
+ "conversation_search_result", "agent_store_conflict_result",
1250
+ "mini_swe_agent_bash_result", "adopt_result",
1028
1251
  ] }]);
1029
1252
  addType(root, "ExecServerControlMessage", [
1030
1253
  { id: 1, name: "abort", type: "ExecServerAbort" },
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Prefixes that can introduce a progress fragment. These are not complete
3
+ * answers by themselves; `isProgressOnlyAssistantText` still requires a
4
+ * fragment (no sentence punctuation) and, for most verbs, an inspection object.
5
+ */
6
+ export declare const PROGRESS_ONLY_PATTERNS: readonly RegExp[];
7
+ /**
8
+ * True only for a short progress *fragment* that ended the turn without tools.
9
+ *
10
+ * Complete answers that happen to start with a progress verb ("Looking at the
11
+ * code, the bug is in X", "Reviewing this PR: LGTM") must not match. A trailing
12
+ * ellipsis is allowed; any other `.!?`, colon, semicolon, or comma is not.
13
+ * Inspection verbs also need an inspection object ("the workspace", "this PR"),
14
+ * not copulas such as "is not needed".
15
+ */
16
+ export declare function isProgressOnlyAssistantText(text: string): boolean;
17
+ export declare function shouldContinueProgressOnlyTurn(input: {
18
+ allowTools: boolean;
19
+ advertisedToolCount: number;
20
+ assistantText: string;
21
+ emittedHostTools: number;
22
+ continuationAttempts: number;
23
+ pendingExecs: number;
24
+ }): boolean;
25
+ export declare function progressOnlyContinuationPrompt(workspaceRoot?: string): string;
@@ -0,0 +1,92 @@
1
+ import { appendWorkspaceRootGrounding } from "./workspace-grounding.js";
2
+ /**
3
+ * Prefixes that can introduce a progress fragment. These are not complete
4
+ * answers by themselves; `isProgressOnlyAssistantText` still requires a
5
+ * fragment (no sentence punctuation) and, for most verbs, an inspection object.
6
+ */
7
+ export const PROGRESS_ONLY_PATTERNS = [
8
+ /^checking\b/i,
9
+ /^inspecting\b/i,
10
+ /^let me check\b/i,
11
+ /^looking into\b/i,
12
+ /^looking at\b/i,
13
+ /^reviewing\b/i,
14
+ /^scanning\b/i,
15
+ /^verifying\b/i,
16
+ /^examining\b/i,
17
+ /^investigating\b/i,
18
+ ];
19
+ const PREFIXES_WITH_OBJECT = [
20
+ /^checking\b/i,
21
+ /^inspecting\b/i,
22
+ /^reviewing\b/i,
23
+ /^scanning\b/i,
24
+ /^verifying\b/i,
25
+ /^examining\b/i,
26
+ /^investigating\b/i,
27
+ ];
28
+ const INSPECTION_OBJECT = /^(?:the|how|whether|if|for|on|this|that|it)\b/i;
29
+ const MAX_PROGRESS_FRAGMENT_WORDS = 8;
30
+ function normalizeWhitespace(text) {
31
+ return text.trim().replace(/\s+/g, " ");
32
+ }
33
+ function restAfterPrefix(text, prefix) {
34
+ return text.slice(prefix.length).trim();
35
+ }
36
+ /**
37
+ * True only for a short progress *fragment* that ended the turn without tools.
38
+ *
39
+ * Complete answers that happen to start with a progress verb ("Looking at the
40
+ * code, the bug is in X", "Reviewing this PR: LGTM") must not match. A trailing
41
+ * ellipsis is allowed; any other `.!?`, colon, semicolon, or comma is not.
42
+ * Inspection verbs also need an inspection object ("the workspace", "this PR"),
43
+ * not copulas such as "is not needed".
44
+ */
45
+ export function isProgressOnlyAssistantText(text) {
46
+ const trimmed = text.trim();
47
+ if (!trimmed)
48
+ return false;
49
+ if (trimmed.length > 240)
50
+ return false;
51
+ if (/\n\s*\n/.test(trimmed))
52
+ return false;
53
+ const normalized = normalizeWhitespace(trimmed);
54
+ const withoutEllipsis = normalized.replace(/(?:\.{3}|…)+\s*$/u, "").trim();
55
+ if (!withoutEllipsis)
56
+ return false;
57
+ if (/[.!?;:]/.test(withoutEllipsis))
58
+ return false;
59
+ if (withoutEllipsis.includes(","))
60
+ return false;
61
+ if (withoutEllipsis.split(" ").length > MAX_PROGRESS_FRAGMENT_WORDS)
62
+ return false;
63
+ if (!PROGRESS_ONLY_PATTERNS.some((pattern) => pattern.test(withoutEllipsis)))
64
+ return false;
65
+ const lower = withoutEllipsis.toLowerCase();
66
+ if (lower.startsWith("let me check")) {
67
+ return withoutEllipsis.length > "let me check".length;
68
+ }
69
+ if (lower.startsWith("looking into") || lower.startsWith("looking at")) {
70
+ const prefix = lower.startsWith("looking into") ? "looking into" : "looking at";
71
+ return INSPECTION_OBJECT.test(restAfterPrefix(withoutEllipsis, prefix));
72
+ }
73
+ if (PREFIXES_WITH_OBJECT.some((pattern) => pattern.test(withoutEllipsis))) {
74
+ const rest = withoutEllipsis.replace(/^\S+\s+/i, "");
75
+ return INSPECTION_OBJECT.test(rest);
76
+ }
77
+ return false;
78
+ }
79
+ export function shouldContinueProgressOnlyTurn(input) {
80
+ return (input.allowTools &&
81
+ input.advertisedToolCount > 0 &&
82
+ input.pendingExecs === 0 &&
83
+ input.emittedHostTools === 0 &&
84
+ input.continuationAttempts < 1 &&
85
+ isProgressOnlyAssistantText(input.assistantText));
86
+ }
87
+ export function progressOnlyContinuationPrompt(workspaceRoot) {
88
+ const base = "Continue the same turn now. Your previous assistant message was only progress narration and ended without a tool call or a complete answer. Do not repeat the progress update. If evidence is still needed, call an available listed tool immediately; otherwise provide the complete user-facing answer now. Do not finish until the requested work or answer is complete.";
89
+ if (!workspaceRoot || !workspaceRoot.trim())
90
+ return base;
91
+ return appendWorkspaceRootGrounding(base, workspaceRoot);
92
+ }
@@ -1,3 +1,4 @@
1
+ import { type CursorExecVariant } from "./exec-variants.js";
1
2
  import { type CursorShellOutcome } from "../shell-timeout.js";
2
3
  export declare const REQUEST_CONTEXT_RESULT_FIELD = 10;
3
4
  export type OpencodeToolDef = {
@@ -255,6 +256,11 @@ export type ToolResultInput = {
255
256
  export declare function buildExecClientMessages(input: ToolResultInput): Uint8Array[];
256
257
  /** ACM #5 exec_client_control_message { stream_close { id } }. */
257
258
  export declare function buildExecStreamClose(execId: number): Uint8Array;
259
+ export declare function buildUnsupportedExecDeny(input: {
260
+ execId: number;
261
+ variant: CursorExecVariant;
262
+ reason: string;
263
+ }): Uint8Array[];
258
264
  /**
259
265
  * Strip opencode's `read` envelope, leaving raw file content.
260
266
  *