oh-my-opencode 3.8.0 → 3.8.2

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 (48) hide show
  1. package/dist/agents/atlas/agent.d.ts +3 -2
  2. package/dist/agents/atlas/gemini.d.ts +11 -0
  3. package/dist/agents/atlas/index.d.ts +1 -0
  4. package/dist/agents/dynamic-agent-prompt-builder.d.ts +1 -0
  5. package/dist/agents/prometheus/gemini.d.ts +12 -0
  6. package/dist/agents/prometheus/index.d.ts +1 -0
  7. package/dist/agents/prometheus/system-prompt.d.ts +2 -1
  8. package/dist/agents/sisyphus-gemini-overlays.d.ts +15 -0
  9. package/dist/agents/sisyphus-junior/agent.d.ts +3 -2
  10. package/dist/agents/sisyphus-junior/gemini.d.ts +10 -0
  11. package/dist/agents/sisyphus-junior/index.d.ts +1 -0
  12. package/dist/agents/types.d.ts +1 -0
  13. package/dist/cli/index.js +8 -8
  14. package/dist/config/schema/categories.d.ts +1 -1
  15. package/dist/features/background-agent/compaction-aware-message-resolver.d.ts +3 -0
  16. package/dist/features/background-agent/error-classifier.d.ts +8 -0
  17. package/dist/features/background-agent/fallback-retry-handler.d.ts +16 -0
  18. package/dist/features/background-agent/manager.d.ts +0 -8
  19. package/dist/features/background-agent/process-cleanup.d.ts +8 -0
  20. package/dist/hooks/atlas/system-reminder-templates.d.ts +1 -0
  21. package/dist/hooks/session-notification.d.ts +2 -0
  22. package/dist/index.js +3204 -1293
  23. package/dist/shared/command-executor/execute-hook-command.d.ts +2 -0
  24. package/dist/shared/session-tools-store.d.ts +1 -0
  25. package/dist/tools/glob/constants.d.ts +1 -1
  26. package/dist/tools/glob/types.d.ts +1 -0
  27. package/dist/tools/grep/constants.d.ts +2 -1
  28. package/dist/tools/grep/types.d.ts +3 -0
  29. package/dist/tools/hashline-edit/autocorrect-replacement-lines.d.ts +6 -0
  30. package/dist/tools/hashline-edit/edit-deduplication.d.ts +5 -0
  31. package/dist/tools/hashline-edit/edit-operation-primitives.d.ts +12 -0
  32. package/dist/tools/hashline-edit/edit-operations.d.ts +7 -4
  33. package/dist/tools/hashline-edit/edit-ordering.d.ts +3 -0
  34. package/dist/tools/hashline-edit/edit-text-normalization.d.ts +7 -0
  35. package/dist/tools/hashline-edit/file-text-canonicalization.d.ts +7 -0
  36. package/dist/tools/hashline-edit/hash-computation.d.ts +7 -0
  37. package/dist/tools/hashline-edit/hashline-chunk-formatter.d.ts +10 -0
  38. package/dist/tools/hashline-edit/hashline-edit-diff.d.ts +1 -0
  39. package/dist/tools/hashline-edit/hashline-edit-executor.d.ts +10 -0
  40. package/dist/tools/hashline-edit/index.d.ts +3 -3
  41. package/dist/tools/hashline-edit/tool-description.d.ts +1 -0
  42. package/dist/tools/hashline-edit/types.d.ts +20 -1
  43. package/dist/tools/hashline-edit/validation.d.ts +12 -0
  44. package/dist/tools/lsp/lsp-manager-process-cleanup.d.ts +4 -1
  45. package/dist/tools/lsp/lsp-server.d.ts +2 -1
  46. package/dist/tools/shared/semaphore.d.ts +14 -0
  47. package/package.json +8 -8
  48. package/dist/features/background-agent/notification-builder.d.ts +0 -8
@@ -6,5 +6,7 @@ export interface CommandResult {
6
6
  export interface ExecuteHookOptions {
7
7
  forceZsh?: boolean;
8
8
  zshPath?: string;
9
+ /** Timeout in milliseconds. Process is killed after this. Default: 30000 */
10
+ timeoutMs?: number;
9
11
  }
10
12
  export declare function executeHookCommand(command: string, stdin: string, cwd: string, options?: ExecuteHookOptions): Promise<CommandResult>;
@@ -1,3 +1,4 @@
1
1
  export declare function setSessionTools(sessionID: string, tools: Record<string, boolean>): void;
2
2
  export declare function getSessionTools(sessionID: string): Record<string, boolean> | undefined;
3
+ export declare function deleteSessionTools(sessionID: string): void;
3
4
  export declare function clearSessionTools(): void;
@@ -1,4 +1,4 @@
1
- export { resolveGrepCli, resolveGrepCliWithAutoInstall, type GrepBackend } from "../grep/constants";
1
+ export { resolveGrepCli, resolveGrepCliWithAutoInstall, type GrepBackend, DEFAULT_RG_THREADS } from "../grep/constants";
2
2
  export declare const DEFAULT_TIMEOUT_MS = 60000;
3
3
  export declare const DEFAULT_LIMIT = 100;
4
4
  export declare const DEFAULT_MAX_DEPTH = 20;
@@ -17,4 +17,5 @@ export interface GlobOptions {
17
17
  maxDepth?: number;
18
18
  timeout?: number;
19
19
  limit?: number;
20
+ threads?: number;
20
21
  }
@@ -10,8 +10,9 @@ export declare const DEFAULT_MAX_FILESIZE = "10M";
10
10
  export declare const DEFAULT_MAX_COUNT = 500;
11
11
  export declare const DEFAULT_MAX_COLUMNS = 1000;
12
12
  export declare const DEFAULT_CONTEXT = 2;
13
- export declare const DEFAULT_TIMEOUT_MS = 300000;
13
+ export declare const DEFAULT_TIMEOUT_MS = 60000;
14
14
  export declare const DEFAULT_MAX_OUTPUT_BYTES: number;
15
+ export declare const DEFAULT_RG_THREADS = 4;
15
16
  export declare const RG_SAFETY_FLAGS: readonly ["--no-follow", "--color=never", "--no-heading", "--line-number", "--with-filename"];
16
17
  export declare const GREP_SAFETY_FLAGS: readonly ["-n", "-H", "--color=never"];
17
18
  export {};
@@ -29,6 +29,9 @@ export interface GrepOptions {
29
29
  noIgnore?: boolean;
30
30
  fileType?: string[];
31
31
  timeout?: number;
32
+ threads?: number;
33
+ outputMode?: "content" | "files_with_matches" | "count";
34
+ headLimit?: number;
32
35
  }
33
36
  export interface CountResult {
34
37
  file: string;
@@ -0,0 +1,6 @@
1
+ export declare function stripTrailingContinuationTokens(text: string): string;
2
+ export declare function stripMergeOperatorChars(text: string): string;
3
+ export declare function restoreOldWrappedLines(originalLines: string[], replacementLines: string[]): string[];
4
+ export declare function maybeExpandSingleLineMerge(originalLines: string[], replacementLines: string[]): string[];
5
+ export declare function restoreIndentForPairedReplacement(originalLines: string[], replacementLines: string[]): string[];
6
+ export declare function autocorrectReplacementLines(originalLines: string[], replacementLines: string[]): string[];
@@ -0,0 +1,5 @@
1
+ import type { HashlineEdit } from "./types";
2
+ export declare function dedupeEdits(edits: HashlineEdit[]): {
3
+ edits: HashlineEdit[];
4
+ deduplicatedEdits: number;
5
+ };
@@ -0,0 +1,12 @@
1
+ interface EditApplyOptions {
2
+ skipValidation?: boolean;
3
+ }
4
+ export declare function applySetLine(lines: string[], anchor: string, newText: string | string[], options?: EditApplyOptions): string[];
5
+ export declare function applyReplaceLines(lines: string[], startAnchor: string, endAnchor: string, newText: string | string[], options?: EditApplyOptions): string[];
6
+ export declare function applyInsertAfter(lines: string[], anchor: string, text: string | string[], options?: EditApplyOptions): string[];
7
+ export declare function applyInsertBefore(lines: string[], anchor: string, text: string | string[], options?: EditApplyOptions): string[];
8
+ export declare function applyInsertBetween(lines: string[], afterAnchor: string, beforeAnchor: string, text: string | string[], options?: EditApplyOptions): string[];
9
+ export declare function applyAppend(lines: string[], text: string | string[]): string[];
10
+ export declare function applyPrepend(lines: string[], text: string | string[]): string[];
11
+ export declare function applyReplace(content: string, oldText: string, newText: string | string[]): string;
12
+ export {};
@@ -1,6 +1,9 @@
1
1
  import type { HashlineEdit } from "./types";
2
- export declare function applySetLine(lines: string[], anchor: string, newText: string | string[]): string[];
3
- export declare function applyReplaceLines(lines: string[], startAnchor: string, endAnchor: string, newText: string | string[]): string[];
4
- export declare function applyInsertAfter(lines: string[], anchor: string, text: string | string[]): string[];
5
- export declare function applyReplace(content: string, oldText: string, newText: string | string[]): string;
2
+ export interface HashlineApplyReport {
3
+ content: string;
4
+ noopEdits: number;
5
+ deduplicatedEdits: number;
6
+ }
7
+ export declare function applyHashlineEditsWithReport(content: string, edits: HashlineEdit[]): HashlineApplyReport;
6
8
  export declare function applyHashlineEdits(content: string, edits: HashlineEdit[]): string;
9
+ export { applySetLine, applyReplaceLines, applyInsertAfter, applyInsertBefore, applyInsertBetween, applyReplace, } from "./edit-operation-primitives";
@@ -0,0 +1,3 @@
1
+ import type { HashlineEdit } from "./types";
2
+ export declare function getEditLineNumber(edit: HashlineEdit): number;
3
+ export declare function collectLineRefs(edits: HashlineEdit[]): string[];
@@ -0,0 +1,7 @@
1
+ export declare function stripLinePrefixes(lines: string[]): string[];
2
+ export declare function toNewLines(input: string | string[]): string[];
3
+ export declare function restoreLeadingIndent(templateLine: string, line: string): string;
4
+ export declare function stripInsertAnchorEcho(anchorLine: string, newLines: string[]): string[];
5
+ export declare function stripInsertBeforeEcho(anchorLine: string, newLines: string[]): string[];
6
+ export declare function stripInsertBoundaryEcho(afterLine: string, beforeLine: string, newLines: string[]): string[];
7
+ export declare function stripRangeBoundaryEcho(lines: string[], startLine: number, endLine: number, newLines: string[]): string[];
@@ -0,0 +1,7 @@
1
+ export interface FileTextEnvelope {
2
+ content: string;
3
+ hadBom: boolean;
4
+ lineEnding: "\n" | "\r\n";
5
+ }
6
+ export declare function canonicalizeFileText(content: string): FileTextEnvelope;
7
+ export declare function restoreFileText(content: string, envelope: FileTextEnvelope): string;
@@ -1,3 +1,10 @@
1
1
  export declare function computeLineHash(lineNumber: number, content: string): string;
2
2
  export declare function formatHashLine(lineNumber: number, content: string): string;
3
3
  export declare function formatHashLines(content: string): string;
4
+ export interface HashlineStreamOptions {
5
+ startLine?: number;
6
+ maxChunkLines?: number;
7
+ maxChunkBytes?: number;
8
+ }
9
+ export declare function streamHashLinesFromUtf8(source: ReadableStream<Uint8Array> | AsyncIterable<Uint8Array>, options?: HashlineStreamOptions): AsyncGenerator<string>;
10
+ export declare function streamHashLinesFromLines(lines: Iterable<string> | AsyncIterable<string>, options?: HashlineStreamOptions): AsyncGenerator<string>;
@@ -0,0 +1,10 @@
1
+ export interface HashlineChunkFormatter {
2
+ push(formattedLine: string): string[];
3
+ flush(): string | undefined;
4
+ }
5
+ interface HashlineChunkFormatterOptions {
6
+ maxChunkLines: number;
7
+ maxChunkBytes: number;
8
+ }
9
+ export declare function createHashlineChunkFormatter(options: HashlineChunkFormatterOptions): HashlineChunkFormatter;
10
+ export {};
@@ -0,0 +1 @@
1
+ export declare function generateHashlineDiff(oldContent: string, newContent: string, filePath: string): string;
@@ -0,0 +1,10 @@
1
+ import type { ToolContext } from "@opencode-ai/plugin/tool";
2
+ import type { HashlineEdit } from "./types";
3
+ interface HashlineEditArgs {
4
+ filePath: string;
5
+ edits: HashlineEdit[];
6
+ delete?: boolean;
7
+ rename?: string;
8
+ }
9
+ export declare function executeHashlineEditTool(args: HashlineEditArgs, context: ToolContext): Promise<string>;
10
+ export {};
@@ -1,7 +1,7 @@
1
- export { computeLineHash, formatHashLine, formatHashLines } from "./hash-computation";
1
+ export { computeLineHash, formatHashLine, formatHashLines, streamHashLinesFromLines, streamHashLinesFromUtf8, } from "./hash-computation";
2
2
  export { parseLineRef, validateLineRef } from "./validation";
3
3
  export type { LineRef } from "./validation";
4
- export type { SetLine, ReplaceLines, InsertAfter, Replace, HashlineEdit } from "./types";
4
+ export type { SetLine, ReplaceLines, InsertAfter, InsertBefore, InsertBetween, Replace, Append, Prepend, HashlineEdit, } from "./types";
5
5
  export { NIBBLE_STR, HASHLINE_DICT, HASHLINE_REF_PATTERN, HASHLINE_OUTPUT_PATTERN } from "./constants";
6
- export { applyHashlineEdits, applyInsertAfter, applyReplace, applyReplaceLines, applySetLine, } from "./edit-operations";
6
+ export { applyHashlineEdits, applyInsertAfter, applyInsertBefore, applyInsertBetween, applyReplace, applyReplaceLines, applySetLine, } from "./edit-operations";
7
7
  export { createHashlineEditTool } from "./tools";
@@ -0,0 +1 @@
1
+ export declare const HASHLINE_EDIT_DESCRIPTION = "Edit files using LINE#ID format for precise, safe modifications.\n\nWORKFLOW:\n1. Read target file/range and copy exact LINE#ID tags.\n2. Pick the smallest operation per logical mutation site.\n3. Submit one edit call per file with all related operations.\n4. If same file needs another call, re-read first.\n5. Use anchors as \"LINE#ID\" only (never include trailing \":content\").\n\nVALIDATION:\n Payload shape: { \"filePath\": string, \"edits\": [...], \"delete\"?: boolean, \"rename\"?: string }\n Each edit must be one of: set_line, replace_lines, insert_after, insert_before, insert_between, replace, append, prepend\n text/new_text must contain plain replacement text only (no LINE#ID prefixes, no diff + markers)\n CRITICAL: all operations validate against the same pre-edit file snapshot and apply bottom-up. Refs/tags are interpreted against the last-read version of the file.\n\nLINE#ID FORMAT (CRITICAL):\n Each line reference must be in \"LINE#ID\" format where:\n LINE: 1-based line number\n ID: Two CID letters from the set ZPMQVRWSNKTXJBYH\n\nFILE MODES:\n delete=true deletes file and requires edits=[] with no rename\n rename moves final content to a new path and removes old path\n\nCONTENT FORMAT:\n text/new_text can be a string (single line) or string[] (multi-line, preferred).\n If you pass a multi-line string, it is split by real newline characters.\n Literal \"\\n\" is preserved as text.\n\nFILE CREATION:\n append: adds content at EOF. If file does not exist, creates it.\n prepend: adds content at BOF. If file does not exist, creates it.\n CRITICAL: append/prepend are the only operations that work without an existing file.\n\nOPERATION CHOICE:\n One line wrong -> set_line\n Adjacent block rewrite or swap/move -> replace_lines (prefer one range op over many single-line ops)\n Both boundaries known -> insert_between (ALWAYS prefer over insert_after/insert_before)\n One boundary known -> insert_after or insert_before\n New file or EOF/BOF addition -> append or prepend\n No LINE#ID available -> replace (last resort)\n\nRULES (CRITICAL):\n 1. Minimize scope: one logical mutation site per operation.\n 2. Preserve formatting: keep indentation, punctuation, line breaks, trailing commas, brace style.\n 3. Prefer insertion over neighbor rewrites: anchor to structural boundaries (}, ], },), not interior property lines.\n 4. No no-ops: replacement content must differ from current content.\n 5. Touch only requested code: avoid incidental edits.\n 6. Use exact current tokens: NEVER rewrite approximately.\n 7. For swaps/moves: prefer one range operation over multiple single-line operations.\n 8. Output tool calls only; no prose or commentary between them.\n\nTAG CHOICE (ALWAYS):\n - Copy tags exactly from read output or >>> mismatch output.\n - NEVER guess tags.\n - Prefer insert_between over insert_after/insert_before when both boundaries are known.\n - Anchor to structural lines (function/class/brace), NEVER blank lines.\n - Anti-pattern warning: blank/whitespace anchors are fragile.\n - Re-read after each successful edit call before issuing another on the same file.\n\nAUTOCORRECT (built-in - you do NOT need to handle these):\n Merged lines are auto-expanded back to original line count.\n Indentation is auto-restored from original lines.\n BOM and CRLF line endings are preserved automatically.\n Hashline prefixes and diff markers in text are auto-stripped.\n\nRECOVERY (when >>> mismatch error appears):\n Copy the updated LINE#ID tags shown in the error output directly.\n Re-read only if the needed tags are missing from the error snippet.\n ALWAYS batch all edits for one file in a single call.";
@@ -14,9 +14,28 @@ export interface InsertAfter {
14
14
  line: string;
15
15
  text: string | string[];
16
16
  }
17
+ export interface InsertBefore {
18
+ type: "insert_before";
19
+ line: string;
20
+ text: string | string[];
21
+ }
22
+ export interface InsertBetween {
23
+ type: "insert_between";
24
+ after_line: string;
25
+ before_line: string;
26
+ text: string | string[];
27
+ }
17
28
  export interface Replace {
18
29
  type: "replace";
19
30
  old_text: string;
20
31
  new_text: string | string[];
21
32
  }
22
- export type HashlineEdit = SetLine | ReplaceLines | InsertAfter | Replace;
33
+ export interface Append {
34
+ type: "append";
35
+ text: string | string[];
36
+ }
37
+ export interface Prepend {
38
+ type: "prepend";
39
+ text: string | string[];
40
+ }
41
+ export type HashlineEdit = SetLine | ReplaceLines | InsertAfter | InsertBefore | InsertBetween | Replace | Append | Prepend;
@@ -2,6 +2,18 @@ export interface LineRef {
2
2
  line: number;
3
3
  hash: string;
4
4
  }
5
+ interface HashMismatch {
6
+ line: number;
7
+ expected: string;
8
+ }
5
9
  export declare function parseLineRef(ref: string): LineRef;
6
10
  export declare function validateLineRef(lines: string[], ref: string): void;
11
+ export declare class HashlineMismatchError extends Error {
12
+ private readonly mismatches;
13
+ private readonly fileLines;
14
+ readonly remaps: ReadonlyMap<string, string>;
15
+ constructor(mismatches: HashMismatch[], fileLines: string[]);
16
+ static formatMessage(mismatches: HashMismatch[], fileLines: string[]): string;
17
+ }
7
18
  export declare function validateLineRefs(lines: string[], refs: string[]): void;
19
+ export {};
@@ -8,5 +8,8 @@ type ProcessCleanupOptions = {
8
8
  clearClients: () => void;
9
9
  clearCleanupInterval: () => void;
10
10
  };
11
- export declare function registerLspManagerProcessCleanup(options: ProcessCleanupOptions): void;
11
+ export type LspProcessCleanupHandle = {
12
+ unregister: () => void;
13
+ };
14
+ export declare function registerLspManagerProcessCleanup(options: ProcessCleanupOptions): LspProcessCleanupHandle;
12
15
  export {};
@@ -1,11 +1,12 @@
1
- import type { ResolvedServer } from "./types";
2
1
  import { LSPClient } from "./lsp-client";
2
+ import type { ResolvedServer } from "./types";
3
3
  declare class LSPServerManager {
4
4
  private static instance;
5
5
  private clients;
6
6
  private cleanupInterval;
7
7
  private readonly IDLE_TIMEOUT;
8
8
  private readonly INIT_TIMEOUT;
9
+ private cleanupHandle;
9
10
  private constructor();
10
11
  private registerProcessCleanup;
11
12
  static getInstance(): LSPServerManager;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Simple counting semaphore to limit concurrent process execution.
3
+ * Used to prevent multiple ripgrep processes from saturating CPU.
4
+ */
5
+ export declare class Semaphore {
6
+ private readonly max;
7
+ private queue;
8
+ private running;
9
+ constructor(max: number);
10
+ acquire(): Promise<void>;
11
+ release(): void;
12
+ }
13
+ /** Global semaphore limiting concurrent ripgrep processes to 2 */
14
+ export declare const rgSemaphore: Semaphore;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode",
3
- "version": "3.8.0",
3
+ "version": "3.8.2",
4
4
  "description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -74,13 +74,13 @@
74
74
  "typescript": "^5.7.3"
75
75
  },
76
76
  "optionalDependencies": {
77
- "oh-my-opencode-darwin-arm64": "3.8.0",
78
- "oh-my-opencode-darwin-x64": "3.8.0",
79
- "oh-my-opencode-linux-arm64": "3.8.0",
80
- "oh-my-opencode-linux-arm64-musl": "3.8.0",
81
- "oh-my-opencode-linux-x64": "3.8.0",
82
- "oh-my-opencode-linux-x64-musl": "3.8.0",
83
- "oh-my-opencode-windows-x64": "3.8.0"
77
+ "oh-my-opencode-darwin-arm64": "3.8.2",
78
+ "oh-my-opencode-darwin-x64": "3.8.2",
79
+ "oh-my-opencode-linux-arm64": "3.8.2",
80
+ "oh-my-opencode-linux-arm64-musl": "3.8.2",
81
+ "oh-my-opencode-linux-x64": "3.8.2",
82
+ "oh-my-opencode-linux-x64-musl": "3.8.2",
83
+ "oh-my-opencode-windows-x64": "3.8.2"
84
84
  },
85
85
  "trustedDependencies": [
86
86
  "@ast-grep/cli",
@@ -1,8 +0,0 @@
1
- import type { BackgroundTask } from "./types";
2
- export declare function buildBackgroundTaskNotificationText(args: {
3
- task: BackgroundTask;
4
- duration: string;
5
- allComplete: boolean;
6
- remainingCount: number;
7
- completedTasks: BackgroundTask[];
8
- }): string;