evil-omo 3.12.4 → 3.13.1

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.
Files changed (67) hide show
  1. package/dist/agents/authorized-research-framework.d.ts +4 -1
  2. package/dist/agents/prometheus/system-prompt.d.ts +1 -1
  3. package/dist/cli/index.js +76 -32
  4. package/dist/config/schema/evil-omo-config.d.ts +40 -15
  5. package/dist/config/schema/hooks.d.ts +1 -1
  6. package/dist/config/schema/openclaw.d.ts +64 -0
  7. package/dist/config/schema.d.ts +1 -0
  8. package/dist/create-hooks.d.ts +1 -1
  9. package/dist/evil-omo.schema.json +186 -48
  10. package/dist/features/background-agent/constants.d.ts +3 -3
  11. package/dist/features/boulder-state/index.d.ts +1 -0
  12. package/dist/features/boulder-state/storage.d.ts +10 -1
  13. package/dist/features/boulder-state/top-level-task.d.ts +2 -0
  14. package/dist/features/boulder-state/types.d.ts +28 -0
  15. package/dist/hooks/atlas/boulder-continuation-injector.d.ts +2 -0
  16. package/dist/hooks/atlas/subagent-session-id.d.ts +7 -1
  17. package/dist/hooks/atlas/tool-execute-after.d.ts +2 -1
  18. package/dist/hooks/atlas/tool-execute-before.d.ts +2 -0
  19. package/dist/hooks/atlas/types.d.ts +13 -1
  20. package/dist/hooks/index.d.ts +1 -1
  21. package/dist/hooks/keyword-detector/constants.d.ts +1 -1
  22. package/dist/hooks/keyword-detector/ultrawork/index.d.ts +1 -1
  23. package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +5 -0
  24. package/dist/hooks/openclaw.d.ts +11 -0
  25. package/dist/hooks/preemptive-compaction-degradation-monitor.d.ts +55 -0
  26. package/dist/hooks/preemptive-compaction-no-text-tail.d.ts +18 -0
  27. package/dist/hooks/session-recovery/storage/thinking-prepend.d.ts +27 -2
  28. package/dist/hooks/todo-continuation-enforcer/compaction-guard.d.ts +2 -0
  29. package/dist/hooks/todo-continuation-enforcer/handler.d.ts +0 -1
  30. package/dist/hooks/todo-continuation-enforcer/idle-event.d.ts +0 -1
  31. package/dist/hooks/todo-continuation-enforcer/types.d.ts +2 -1
  32. package/dist/hooks/webfetch-redirect-guard/constants.d.ts +6 -0
  33. package/dist/hooks/webfetch-redirect-guard/hook.d.ts +19 -0
  34. package/dist/hooks/webfetch-redirect-guard/index.d.ts +1 -0
  35. package/dist/hooks/webfetch-redirect-guard/redirect-resolution.d.ts +16 -0
  36. package/dist/index.js +1703 -843
  37. package/dist/openclaw/config.d.ts +8 -0
  38. package/dist/openclaw/daemon.d.ts +1 -0
  39. package/dist/openclaw/dispatcher.d.ts +16 -0
  40. package/dist/openclaw/index.d.ts +5 -0
  41. package/dist/openclaw/reply-listener.d.ts +31 -0
  42. package/dist/openclaw/session-registry.d.ts +17 -0
  43. package/dist/openclaw/tmux.d.ts +8 -0
  44. package/dist/openclaw/types.d.ts +38 -0
  45. package/dist/plugin/chat-params.d.ts +5 -1
  46. package/dist/plugin/hooks/create-continuation-hooks.d.ts +1 -2
  47. package/dist/plugin/hooks/create-core-hooks.d.ts +1 -0
  48. package/dist/plugin/hooks/create-tool-guard-hooks.d.ts +2 -1
  49. package/dist/plugin/normalize-tool-arg-schemas.d.ts +1 -0
  50. package/dist/plugin-handlers/prometheus-agent-config-builder.d.ts +1 -0
  51. package/dist/shared/jsonc-parser.d.ts +4 -0
  52. package/dist/shared/shell-env.d.ts +1 -1
  53. package/dist/tools/delegate-task/categories.d.ts +1 -0
  54. package/dist/tools/delegate-task/constants.d.ts +2 -2
  55. package/dist/tools/delegate-task/model-selection.d.ts +1 -0
  56. package/dist/tools/delegate-task/subagent-resolver.d.ts +1 -1
  57. package/dist/tools/hashline-edit/formatter-trigger.d.ts +38 -0
  58. package/dist/tools/hashline-edit/hashline-edit-executor.d.ts +2 -1
  59. package/dist/tools/hashline-edit/tools.d.ts +2 -1
  60. package/package.json +12 -12
  61. package/bin/evil-omo.test.ts +0 -82
  62. package/dist/hooks/gpt-permission-continuation/assistant-message.d.ts +0 -23
  63. package/dist/hooks/gpt-permission-continuation/constants.d.ts +0 -4
  64. package/dist/hooks/gpt-permission-continuation/detector.d.ts +0 -1
  65. package/dist/hooks/gpt-permission-continuation/handler.d.ts +0 -12
  66. package/dist/hooks/gpt-permission-continuation/index.d.ts +0 -13
  67. package/dist/hooks/gpt-permission-continuation/session-state.d.ts +0 -15
@@ -24,26 +24,22 @@
24
24
  "disabled_agents": {
25
25
  "type": "array",
26
26
  "items": {
27
- "type": "string"
27
+ "type": "string",
28
+ "minLength": 1
28
29
  }
29
30
  },
30
31
  "disabled_skills": {
31
32
  "type": "array",
32
33
  "items": {
33
34
  "type": "string",
34
- "enum": [
35
- "playwright",
36
- "agent-browser",
37
- "dev-browser",
38
- "frontend-ui-ux",
39
- "git-master"
40
- ]
35
+ "minLength": 1
41
36
  }
42
37
  },
43
38
  "disabled_hooks": {
44
39
  "type": "array",
45
40
  "items": {
46
- "type": "string"
41
+ "type": "string",
42
+ "minLength": 1
47
43
  }
48
44
  },
49
45
  "disabled_commands": {
@@ -64,7 +60,8 @@
64
60
  "disabled_tools": {
65
61
  "type": "array",
66
62
  "items": {
67
- "type": "string"
63
+ "type": "string",
64
+ "minLength": 1
68
65
  }
69
66
  },
70
67
  "hashline_edit": {
@@ -3613,44 +3610,6 @@
3613
3610
  ],
3614
3611
  "additionalProperties": false
3615
3612
  },
3616
- "runtime_fallback": {
3617
- "anyOf": [
3618
- {
3619
- "type": "boolean"
3620
- },
3621
- {
3622
- "type": "object",
3623
- "properties": {
3624
- "enabled": {
3625
- "type": "boolean"
3626
- },
3627
- "retry_on_errors": {
3628
- "type": "array",
3629
- "items": {
3630
- "type": "number"
3631
- }
3632
- },
3633
- "max_fallback_attempts": {
3634
- "type": "number",
3635
- "minimum": 1,
3636
- "maximum": 20
3637
- },
3638
- "cooldown_seconds": {
3639
- "type": "number",
3640
- "minimum": 0
3641
- },
3642
- "timeout_seconds": {
3643
- "type": "number",
3644
- "minimum": 0
3645
- },
3646
- "notify_on_fallback": {
3647
- "type": "boolean"
3648
- }
3649
- },
3650
- "additionalProperties": false
3651
- }
3652
- ]
3653
- },
3654
3613
  "background_task": {
3655
3614
  "type": "object",
3656
3615
  "properties": {
@@ -3736,6 +3695,147 @@
3736
3695
  },
3737
3696
  "additionalProperties": false
3738
3697
  },
3698
+ "openclaw": {
3699
+ "type": "object",
3700
+ "properties": {
3701
+ "enabled": {
3702
+ "default": false,
3703
+ "type": "boolean"
3704
+ },
3705
+ "gateways": {
3706
+ "default": {},
3707
+ "type": "object",
3708
+ "propertyNames": {
3709
+ "type": "string"
3710
+ },
3711
+ "additionalProperties": {
3712
+ "type": "object",
3713
+ "properties": {
3714
+ "type": {
3715
+ "default": "http",
3716
+ "type": "string",
3717
+ "enum": [
3718
+ "http",
3719
+ "command"
3720
+ ]
3721
+ },
3722
+ "url": {
3723
+ "type": "string"
3724
+ },
3725
+ "method": {
3726
+ "default": "POST",
3727
+ "type": "string"
3728
+ },
3729
+ "headers": {
3730
+ "type": "object",
3731
+ "propertyNames": {
3732
+ "type": "string"
3733
+ },
3734
+ "additionalProperties": {
3735
+ "type": "string"
3736
+ }
3737
+ },
3738
+ "command": {
3739
+ "type": "string"
3740
+ },
3741
+ "timeout": {
3742
+ "type": "number"
3743
+ }
3744
+ },
3745
+ "required": [
3746
+ "type",
3747
+ "method"
3748
+ ],
3749
+ "additionalProperties": false
3750
+ }
3751
+ },
3752
+ "hooks": {
3753
+ "default": {},
3754
+ "type": "object",
3755
+ "propertyNames": {
3756
+ "type": "string"
3757
+ },
3758
+ "additionalProperties": {
3759
+ "type": "object",
3760
+ "properties": {
3761
+ "enabled": {
3762
+ "default": true,
3763
+ "type": "boolean"
3764
+ },
3765
+ "gateway": {
3766
+ "type": "string"
3767
+ },
3768
+ "instruction": {
3769
+ "type": "string"
3770
+ }
3771
+ },
3772
+ "required": [
3773
+ "enabled",
3774
+ "gateway",
3775
+ "instruction"
3776
+ ],
3777
+ "additionalProperties": false
3778
+ }
3779
+ },
3780
+ "replyListener": {
3781
+ "type": "object",
3782
+ "properties": {
3783
+ "discordBotToken": {
3784
+ "type": "string"
3785
+ },
3786
+ "discordChannelId": {
3787
+ "type": "string"
3788
+ },
3789
+ "discordMention": {
3790
+ "type": "string"
3791
+ },
3792
+ "authorizedDiscordUserIds": {
3793
+ "default": [],
3794
+ "type": "array",
3795
+ "items": {
3796
+ "type": "string"
3797
+ }
3798
+ },
3799
+ "telegramBotToken": {
3800
+ "type": "string"
3801
+ },
3802
+ "telegramChatId": {
3803
+ "type": "string"
3804
+ },
3805
+ "pollIntervalMs": {
3806
+ "default": 3000,
3807
+ "type": "number"
3808
+ },
3809
+ "rateLimitPerMinute": {
3810
+ "default": 10,
3811
+ "type": "number"
3812
+ },
3813
+ "maxMessageLength": {
3814
+ "default": 500,
3815
+ "type": "number"
3816
+ },
3817
+ "includePrefix": {
3818
+ "default": true,
3819
+ "type": "boolean"
3820
+ }
3821
+ },
3822
+ "required": [
3823
+ "authorizedDiscordUserIds",
3824
+ "pollIntervalMs",
3825
+ "rateLimitPerMinute",
3826
+ "maxMessageLength",
3827
+ "includePrefix"
3828
+ ],
3829
+ "additionalProperties": false
3830
+ }
3831
+ },
3832
+ "required": [
3833
+ "enabled",
3834
+ "gateways",
3835
+ "hooks"
3836
+ ],
3837
+ "additionalProperties": false
3838
+ },
3739
3839
  "babysitting": {
3740
3840
  "type": "object",
3741
3841
  "properties": {
@@ -3880,6 +3980,44 @@
3880
3980
  },
3881
3981
  "additionalProperties": false
3882
3982
  },
3983
+ "runtime_fallback": {
3984
+ "anyOf": [
3985
+ {
3986
+ "type": "boolean"
3987
+ },
3988
+ {
3989
+ "type": "object",
3990
+ "properties": {
3991
+ "enabled": {
3992
+ "type": "boolean"
3993
+ },
3994
+ "retry_on_errors": {
3995
+ "type": "array",
3996
+ "items": {
3997
+ "type": "number"
3998
+ }
3999
+ },
4000
+ "max_fallback_attempts": {
4001
+ "type": "number",
4002
+ "minimum": 1,
4003
+ "maximum": 20
4004
+ },
4005
+ "cooldown_seconds": {
4006
+ "type": "number",
4007
+ "minimum": 0
4008
+ },
4009
+ "timeout_seconds": {
4010
+ "type": "number",
4011
+ "minimum": 0
4012
+ },
4013
+ "notify_on_fallback": {
4014
+ "type": "boolean"
4015
+ }
4016
+ },
4017
+ "additionalProperties": false
4018
+ }
4019
+ ]
4020
+ },
3883
4021
  "start_work": {
3884
4022
  "type": "object",
3885
4023
  "properties": {
@@ -3,11 +3,11 @@ import type { BackgroundTask, LaunchInput } from "./types";
3
3
  export declare const TASK_TTL_MS: number;
4
4
  export declare const TERMINAL_TASK_TTL_MS: number;
5
5
  export declare const MIN_STABILITY_TIME_MS: number;
6
- export declare const DEFAULT_STALE_TIMEOUT_MS = 1200000;
7
- export declare const DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 1800000;
6
+ export declare const DEFAULT_STALE_TIMEOUT_MS = 2700000;
7
+ export declare const DEFAULT_MESSAGE_STALENESS_TIMEOUT_MS = 3600000;
8
8
  export declare const DEFAULT_MAX_TOOL_CALLS = 4000;
9
9
  export declare const DEFAULT_CIRCUIT_BREAKER_CONSECUTIVE_THRESHOLD = 20;
10
- export declare const DEFAULT_CIRCUIT_BREAKER_ENABLED = false;
10
+ export declare const DEFAULT_CIRCUIT_BREAKER_ENABLED = true;
11
11
  export declare const MIN_RUNTIME_BEFORE_STALE_MS = 30000;
12
12
  export declare const MIN_IDLE_TIME_MS = 5000;
13
13
  export declare const POLLING_INTERVAL_MS = 3000;
@@ -1,3 +1,4 @@
1
1
  export * from "./types";
2
2
  export * from "./constants";
3
3
  export * from "./storage";
4
+ export * from "./top-level-task";
@@ -3,12 +3,21 @@
3
3
  *
4
4
  * Handles reading/writing boulder.json for active plan tracking.
5
5
  */
6
- import type { BoulderState, PlanProgress } from "./types";
6
+ import type { BoulderState, PlanProgress, TaskSessionState } from "./types";
7
7
  export declare function getBoulderFilePath(directory: string): string;
8
8
  export declare function readBoulderState(directory: string): BoulderState | null;
9
9
  export declare function writeBoulderState(directory: string, state: BoulderState): boolean;
10
10
  export declare function appendSessionId(directory: string, sessionId: string): BoulderState | null;
11
11
  export declare function clearBoulderState(directory: string): boolean;
12
+ export declare function getTaskSessionState(directory: string, taskKey: string): TaskSessionState | null;
13
+ export declare function upsertTaskSessionState(directory: string, input: {
14
+ taskKey: string;
15
+ taskLabel: string;
16
+ taskTitle: string;
17
+ sessionId: string;
18
+ agent?: string;
19
+ category?: string;
20
+ }): BoulderState | null;
12
21
  /**
13
22
  * Find Prometheus plan files for this project.
14
23
  * Prometheus stores plans at: {project}/.sisyphus/plans/{name}.md
@@ -0,0 +1,2 @@
1
+ import type { TopLevelTaskRef } from "./types";
2
+ export declare function readCurrentTopLevelTask(planPath: string): TopLevelTaskRef | null;
@@ -17,6 +17,8 @@ export interface BoulderState {
17
17
  agent?: string;
18
18
  /** Absolute path to the git worktree root where work happens */
19
19
  worktree_path?: string;
20
+ /** Preferred reusable subagent sessions keyed by current top-level plan task */
21
+ task_sessions?: Record<string, TaskSessionState>;
20
22
  }
21
23
  export interface PlanProgress {
22
24
  /** Total number of checkboxes */
@@ -26,3 +28,29 @@ export interface PlanProgress {
26
28
  /** Whether all tasks are done */
27
29
  isComplete: boolean;
28
30
  }
31
+ export interface TaskSessionState {
32
+ /** Stable identifier for the current top-level plan task (e.g. todo:1 / final-wave:F1) */
33
+ task_key: string;
34
+ /** Original task label from the plan file */
35
+ task_label: string;
36
+ /** Full task title from the plan file */
37
+ task_title: string;
38
+ /** Preferred reusable subagent session */
39
+ session_id: string;
40
+ /** Agent associated with the task session, when known */
41
+ agent?: string;
42
+ /** Category associated with the task session, when known */
43
+ category?: string;
44
+ /** Last update timestamp */
45
+ updated_at: string;
46
+ }
47
+ export interface TopLevelTaskRef {
48
+ /** Stable identifier for the current top-level plan task */
49
+ key: string;
50
+ /** Task section in the Prometheus plan */
51
+ section: "todo" | "final-wave";
52
+ /** Original label token (e.g. 1 / F1) */
53
+ label: string;
54
+ /** Full task title extracted from the checkbox line */
55
+ title: string;
56
+ }
@@ -9,6 +9,8 @@ export declare function injectBoulderContinuation(input: {
9
9
  total: number;
10
10
  agent?: string;
11
11
  worktreePath?: string;
12
+ preferredTaskSessionId?: string;
13
+ preferredTaskTitle?: string;
12
14
  backgroundManager?: BackgroundManager;
13
15
  sessionState: SessionState;
14
16
  }): Promise<void>;
@@ -1 +1,7 @@
1
- export declare function extractSessionIdFromOutput(output: string): string;
1
+ import type { PluginInput } from "@opencode-ai/plugin";
2
+ export declare function extractSessionIdFromOutput(output: string): string | undefined;
3
+ export declare function validateSubagentSessionId(input: {
4
+ client: PluginInput["client"];
5
+ sessionID?: string;
6
+ lineageSessionIDs: string[];
7
+ }): Promise<string | undefined>;
@@ -1,9 +1,10 @@
1
1
  import type { PluginInput } from "@opencode-ai/plugin";
2
- import type { SessionState } from "./types";
2
+ import type { PendingTaskRef, SessionState } from "./types";
3
3
  import type { ToolExecuteAfterInput, ToolExecuteAfterOutput } from "./types";
4
4
  export declare function createToolExecuteAfterHandler(input: {
5
5
  ctx: PluginInput;
6
6
  pendingFilePaths: Map<string, string>;
7
+ pendingTaskRefs: Map<string, PendingTaskRef>;
7
8
  autoCommit: boolean;
8
9
  getState: (sessionID: string) => SessionState;
9
10
  }): (toolInput: ToolExecuteAfterInput, toolOutput: ToolExecuteAfterOutput) => Promise<void>;
@@ -1,7 +1,9 @@
1
1
  import type { PluginInput } from "@opencode-ai/plugin";
2
+ import type { PendingTaskRef } from "./types";
2
3
  export declare function createToolExecuteBeforeHandler(input: {
3
4
  ctx: PluginInput;
4
5
  pendingFilePaths: Map<string, string>;
6
+ pendingTaskRefs: Map<string, PendingTaskRef>;
5
7
  }): (toolInput: {
6
8
  tool: string;
7
9
  sessionID?: string;
@@ -1,5 +1,6 @@
1
1
  import type { AgentOverrides } from "../../config";
2
2
  import type { BackgroundManager } from "../../features/background-agent";
3
+ import type { TopLevelTaskRef } from "../../features/boulder-state";
3
4
  export type ModelInfo = {
4
5
  providerID: string;
5
6
  modelID: string;
@@ -8,7 +9,6 @@ export interface AtlasHookOptions {
8
9
  directory: string;
9
10
  backgroundManager?: BackgroundManager;
10
11
  isContinuationStopped?: (sessionID: string) => boolean;
11
- shouldSkipContinuation?: (sessionID: string) => boolean;
12
12
  agentOverrides?: AgentOverrides;
13
13
  /** Enable auto-commit after each atomic task completion (default: true) */
14
14
  autoCommit?: boolean;
@@ -23,6 +23,18 @@ export interface ToolExecuteAfterOutput {
23
23
  output: string;
24
24
  metadata: Record<string, unknown>;
25
25
  }
26
+ export type TrackedTopLevelTaskRef = Pick<TopLevelTaskRef, "key" | "label" | "title">;
27
+ export type PendingTaskRef = {
28
+ kind: "track";
29
+ task: TrackedTopLevelTaskRef;
30
+ } | {
31
+ kind: "skip";
32
+ reason: "explicit_resume";
33
+ } | {
34
+ kind: "skip";
35
+ reason: "ambiguous_task_key";
36
+ task: TrackedTopLevelTaskRef;
37
+ };
26
38
  export interface SessionState {
27
39
  lastEventWasAbortError?: boolean;
28
40
  lastContinuationInjectedAt?: number;
@@ -27,7 +27,6 @@ export { createCategorySkillReminderHook } from "./category-skill-reminder";
27
27
  export { createRalphLoopHook, type RalphLoopHook } from "./ralph-loop";
28
28
  export { createNoSisyphusGptHook } from "./no-sisyphus-gpt";
29
29
  export { createNoHephaestusNonGptHook } from "./no-hephaestus-non-gpt";
30
- export { createGptPermissionContinuationHook, type GptPermissionContinuationHook } from "./gpt-permission-continuation";
31
30
  export { createAutoSlashCommandHook } from "./auto-slash-command";
32
31
  export { createEditErrorRecoveryHook } from "./edit-error-recovery";
33
32
  export { createPrometheusMdOnlyHook } from "./prometheus-md-only";
@@ -49,3 +48,4 @@ export { createHashlineReadEnhancerHook } from "./hashline-read-enhancer";
49
48
  export { createJsonErrorRecoveryHook, JSON_ERROR_TOOL_EXCLUDE_LIST, JSON_ERROR_PATTERNS, JSON_ERROR_REMINDER } from "./json-error-recovery";
50
49
  export { createReadImageResizerHook } from "./read-image-resizer";
51
50
  export { createTodoDescriptionOverrideHook } from "./todo-description-override";
51
+ export { createWebFetchRedirectGuardHook } from "./webfetch-redirect-guard";
@@ -1,6 +1,6 @@
1
1
  export declare const CODE_BLOCK_PATTERN: RegExp;
2
2
  export declare const INLINE_CODE_PATTERN: RegExp;
3
- export { isPlannerAgent, getUltraworkMessage } from "./ultrawork";
3
+ export { isPlannerAgent, isNonOmoAgent, getUltraworkMessage } from "./ultrawork";
4
4
  export { SEARCH_PATTERN, SEARCH_MESSAGE } from "./search";
5
5
  export { ANALYZE_PATTERN, ANALYZE_MESSAGE } from "./analyze";
6
6
  export type KeywordDetector = {
@@ -7,7 +7,7 @@
7
7
  * 3. Gemini models → gemini.ts
8
8
  * 4. Default (Claude, etc.) → default.ts (optimized for Claude series)
9
9
  */
10
- export { isPlannerAgent, isGptModel, isGeminiModel, getUltraworkSource, } from "./source-detector";
10
+ export { isPlannerAgent, isNonOmoAgent, isGptModel, isGeminiModel, getUltraworkSource, } from "./source-detector";
11
11
  export type { UltraworkSource } from "./source-detector";
12
12
  export { ULTRAWORK_PLANNER_SECTION, getPlannerUltraworkMessage, } from "./planner";
13
13
  export { ULTRAWORK_GPT_MESSAGE, getGptUltraworkMessage } from "./gpt";
@@ -13,6 +13,11 @@ import { isGptModel, isGeminiModel } from "../../../agents/types";
13
13
  * Planners don't need ultrawork injection (they ARE the planner).
14
14
  */
15
15
  export declare function isPlannerAgent(agentName?: string): boolean;
16
+ /**
17
+ * Checks if agent is a non-OMO agent (e.g., OpenCode's built-in Builder/Plan).
18
+ * Non-OMO agents should not receive keyword injection (search-mode, analyze-mode, etc.).
19
+ */
20
+ export declare function isNonOmoAgent(agentName?: string): boolean;
16
21
  export { isGptModel, isGeminiModel };
17
22
  /** Ultrawork message source type */
18
23
  export type UltraworkSource = "planner" | "gpt" | "gemini" | "default";
@@ -0,0 +1,11 @@
1
+ import type { PluginContext } from "../plugin/types";
2
+ import type { OhMyOpenCodeConfig } from "../config";
3
+ export declare function createOpenClawHook(ctx: PluginContext, pluginConfig: OhMyOpenCodeConfig): {
4
+ event: (input: any) => Promise<void>;
5
+ "tool.execute.before": (input: {
6
+ tool: string;
7
+ sessionID: string;
8
+ }, output: {
9
+ args: Record<string, unknown>;
10
+ }) => Promise<void>;
11
+ } | null;
@@ -0,0 +1,55 @@
1
+ import type { OhMyOpenCodeConfig } from "../config";
2
+ interface CompactionTargetState {
3
+ providerID: string;
4
+ modelID: string;
5
+ }
6
+ interface ClientLike {
7
+ session: {
8
+ summarize: (input: {
9
+ path: {
10
+ id: string;
11
+ };
12
+ body: {
13
+ providerID: string;
14
+ modelID: string;
15
+ };
16
+ query: {
17
+ directory: string;
18
+ };
19
+ }) => Promise<unknown>;
20
+ messages: (input: {
21
+ path: {
22
+ id: string;
23
+ };
24
+ query?: {
25
+ directory: string;
26
+ };
27
+ }) => Promise<unknown>;
28
+ };
29
+ tui: {
30
+ showToast: (input: {
31
+ body: {
32
+ title: string;
33
+ message: string;
34
+ variant: "warning";
35
+ duration: number;
36
+ };
37
+ }) => Promise<unknown>;
38
+ };
39
+ }
40
+ export interface AssistantCompactionMessageInfo {
41
+ sessionID: string;
42
+ id?: string;
43
+ }
44
+ export declare function createPostCompactionDegradationMonitor(args: {
45
+ client: ClientLike;
46
+ directory: string;
47
+ pluginConfig: OhMyOpenCodeConfig;
48
+ tokenCache: Map<string, CompactionTargetState>;
49
+ compactionInProgress: Set<string>;
50
+ }): {
51
+ clear: (sessionID: string) => void;
52
+ onSessionCompacted: (sessionID: string) => void;
53
+ onAssistantMessageUpdated: (info: AssistantCompactionMessageInfo) => Promise<void>;
54
+ };
55
+ export {};
@@ -0,0 +1,18 @@
1
+ export declare function isStepOnlyNoTextParts(parts: unknown): boolean;
2
+ export declare function resolveNoTextTailFromSession(args: {
3
+ client: {
4
+ session: {
5
+ messages: (input: {
6
+ path: {
7
+ id: string;
8
+ };
9
+ query?: {
10
+ directory: string;
11
+ };
12
+ }) => Promise<unknown>;
13
+ };
14
+ };
15
+ sessionID: string;
16
+ messageID?: string;
17
+ directory: string;
18
+ }): Promise<boolean>;
@@ -1,5 +1,30 @@
1
1
  import type { PluginInput } from "@opencode-ai/plugin";
2
+ import type { MessageData, StoredPart } from "../types";
3
+ import { log, isSqliteBackend, patchPart } from "../../../shared";
2
4
  type OpencodeClient = PluginInput["client"];
3
- export declare function prependThinkingPart(sessionID: string, messageID: string): boolean;
4
- export declare function prependThinkingPartAsync(client: OpencodeClient, sessionID: string, messageID: string): Promise<boolean>;
5
+ type StoredSignedThinkingPart = StoredPart & {
6
+ type: "thinking" | "redacted_thinking";
7
+ signature: string;
8
+ };
9
+ type SDKMessagePart = NonNullable<MessageData["parts"]>[number];
10
+ type SDKSignedThinkingPart = SDKMessagePart & {
11
+ id: string;
12
+ type: "thinking" | "redacted_thinking";
13
+ signature: string;
14
+ };
15
+ type ThinkingPrependDeps = {
16
+ isSqliteBackend: typeof isSqliteBackend;
17
+ patchPart: typeof patchPart;
18
+ log: typeof log;
19
+ findLastThinkingPart: typeof findLastThinkingPart;
20
+ findLastThinkingPartFromSDK: typeof findLastThinkingPartFromSDK;
21
+ readTargetPartIDs: typeof readTargetPartIDs;
22
+ readTargetPartIDsFromSDK: typeof readTargetPartIDsFromSDK;
23
+ };
24
+ declare function readTargetPartIDs(messageID: string): string[];
25
+ declare function readTargetPartIDsFromSDK(client: OpencodeClient, sessionID: string, messageID: string): Promise<string[]>;
26
+ declare function findLastThinkingPart(sessionID: string, beforeMessageID: string): StoredSignedThinkingPart | null;
27
+ export declare function prependThinkingPart(sessionID: string, messageID: string, deps?: ThinkingPrependDeps): boolean;
28
+ declare function findLastThinkingPartFromSDK(client: OpencodeClient, sessionID: string, beforeMessageID: string): Promise<SDKSignedThinkingPart | null>;
29
+ export declare function prependThinkingPartAsync(client: OpencodeClient, sessionID: string, messageID: string, deps?: ThinkingPrependDeps): Promise<boolean>;
5
30
  export {};
@@ -1,2 +1,4 @@
1
1
  import type { SessionState } from "./types";
2
+ export declare function armCompactionGuard(state: SessionState, now: number): number;
3
+ export declare function acknowledgeCompactionGuard(state: SessionState, compactionEpoch: number | undefined): boolean;
2
4
  export declare function isCompactionGuardActive(state: SessionState, now: number): boolean;
@@ -7,7 +7,6 @@ export declare function createTodoContinuationHandler(args: {
7
7
  backgroundManager?: BackgroundManager;
8
8
  skipAgents?: string[];
9
9
  isContinuationStopped?: (sessionID: string) => boolean;
10
- shouldSkipContinuation?: (sessionID: string) => boolean;
11
10
  }): (input: {
12
11
  event: {
13
12
  type: string;
@@ -8,5 +8,4 @@ export declare function handleSessionIdle(args: {
8
8
  backgroundManager?: BackgroundManager;
9
9
  skipAgents?: string[];
10
10
  isContinuationStopped?: (sessionID: string) => boolean;
11
- shouldSkipContinuation?: (sessionID: string) => boolean;
12
11
  }): Promise<void>;
@@ -4,7 +4,6 @@ export interface TodoContinuationEnforcerOptions {
4
4
  backgroundManager?: BackgroundManager;
5
5
  skipAgents?: string[];
6
6
  isContinuationStopped?: (sessionID: string) => boolean;
7
- shouldSkipContinuation?: (sessionID: string) => boolean;
8
7
  }
9
8
  export interface TodoContinuationEnforcer {
10
9
  handler: (input: {
@@ -37,6 +36,8 @@ export interface SessionState {
37
36
  stagnationCount: number;
38
37
  consecutiveFailures: number;
39
38
  recentCompactionAt?: number;
39
+ recentCompactionEpoch?: number;
40
+ acknowledgedCompactionEpoch?: number;
40
41
  }
41
42
  export interface MessageInfo {
42
43
  id?: string;
@@ -0,0 +1,6 @@
1
+ export declare const DEFAULT_WEBFETCH_TIMEOUT_MS = 30000;
2
+ export declare const MAX_WEBFETCH_TIMEOUT_MS = 120000;
3
+ export declare const MAX_WEBFETCH_REDIRECTS = 10;
4
+ export declare const WEBFETCH_REDIRECT_GUARD_STALE_TIMEOUT_MS: number;
5
+ export declare const WEBFETCH_REDIRECT_ERROR_PATTERNS: readonly [RegExp, RegExp];
6
+ export declare const WEBFETCH_REDIRECT_STATUSES: Set<number>;