oh-my-opencode-slim 2.0.0-beta.7 → 2.0.0-beta.9
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/README.ja-JP.md +636 -0
- package/README.md +19 -8
- package/README.zh-CN.md +625 -0
- package/dist/config/constants.d.ts +1 -1
- package/dist/hooks/phase-reminder/index.d.ts +1 -1
- package/dist/index.js +289 -82
- package/dist/multiplexer/session-manager.d.ts +4 -1
- package/dist/tools/ast-grep/tools.d.ts +1 -1
- package/dist/tools/cancel-task.d.ts +10 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tui.js +1 -1
- package/dist/utils/background-job-board.d.ts +4 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -18308,7 +18308,7 @@ var POLL_INTERVAL_BACKGROUND_MS = 2000;
|
|
|
18308
18308
|
var DEFAULT_TIMEOUT_MS = 2 * 60 * 1000;
|
|
18309
18309
|
var MAX_POLL_TIME_MS = 5 * 60 * 1000;
|
|
18310
18310
|
var DEFAULT_MAX_SUBAGENT_DEPTH = 3;
|
|
18311
|
-
var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: plan lanes/dependencies → dispatch background specialists → track task IDs →
|
|
18311
|
+
var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion or use task_status only when needed → reconcile terminal results → verify. Do not consume running-job output or advance dependent work. !END!`;
|
|
18312
18312
|
var TMUX_SPAWN_DELAY_MS = 500;
|
|
18313
18313
|
var COUNCILLOR_STAGGER_MS = 250;
|
|
18314
18314
|
var DEFAULT_DISABLED_AGENTS = ["observer"];
|
|
@@ -18964,51 +18964,48 @@ ${customAppendPrompt}`;
|
|
|
18964
18964
|
}
|
|
18965
18965
|
var AGENT_DESCRIPTIONS = {
|
|
18966
18966
|
explorer: `@explorer
|
|
18967
|
-
- Lane:
|
|
18968
|
-
-
|
|
18969
|
-
- Permissions: Read files
|
|
18967
|
+
- Lane: Fast codebase recon that returns compressed context
|
|
18968
|
+
- Permissions: read_files
|
|
18970
18969
|
- Stats: 2x faster codebase search than orchestrator, 1/2 cost of orchestrator
|
|
18971
18970
|
- Capabilities: Glob, grep, AST queries to locate files, symbols, patterns
|
|
18972
18971
|
- **Delegate when:** Need to discover what exists before planning • Parallel searches speed discovery • Need summarized map vs full contents • Broad/uncertain scope
|
|
18973
18972
|
- **Don't delegate when:** Know the path and need actual content • Need full file anyway • Single specific lookup • About to edit the file`,
|
|
18974
18973
|
librarian: `@librarian
|
|
18975
18974
|
- Lane: External knowledge and library research, fast web research
|
|
18976
|
-
- Role: Authoritative source for current library docs
|
|
18977
|
-
-
|
|
18978
|
-
- Stats: 10x better finding up-to-date library docs than orchestrator, 1/2 cost of orchestrator
|
|
18979
|
-
- Capabilities: Fetches latest official docs, examples, API signatures, version-specific behavior via grep_app MCP
|
|
18975
|
+
- Role: Authoritative source for current library docs, API references, examples, bug investigations, and web retrieval
|
|
18976
|
+
- Stats: 2x faster web research than orchestrator, 1/2 cost of orchestrator
|
|
18980
18977
|
- **Delegate when:** Libraries with frequent API changes (React, Next.js, AI SDKs) • Complex APIs needing official examples (ORMs, auth) • Version-specific behavior matters • Unfamiliar library • Edge cases or advanced features • Nuanced best practices • Working on fixing tricky bug or problem and need latest web research information
|
|
18981
18978
|
- **Don't delegate when:** Standard usage you're confident • Simple stable APIs • General programming knowledge • Info already in conversation • Built-in language features
|
|
18982
18979
|
- **Rule of thumb:** "How does this library work?" → @librarian. "How does programming work?" → answer directly. How does others solve or workaround this tricky issue?" → @librarian.`,
|
|
18983
18980
|
oracle: `@oracle
|
|
18984
18981
|
- Lane: Architecture, risk, debugging strategy, and review
|
|
18985
18982
|
- Role: Strategic advisor for high-stakes decisions and persistent problems, code reviewer
|
|
18986
|
-
- Permissions:
|
|
18983
|
+
- Permissions: read_files
|
|
18987
18984
|
- Stats: 5x better decision maker, problem solver, investigator than orchestrator, 0.8x speed of orchestrator, same cost.
|
|
18988
18985
|
- Capabilities: Deep architectural reasoning, system-level trade-offs, complex debugging, code review, simplification, maintainability review
|
|
18989
18986
|
- **Delegate when:** Major architectural decisions with long-term impact • Problems persisting after 2+ fix attempts • High-risk multi-system refactors • Costly trade-offs (performance vs maintainability) • Complex debugging with unclear root cause • Security/scalability/data integrity decisions • Genuinely uncertain and cost of wrong choice is high • When a workflow calls for a **reviewer** subagent • Code needs simplification or YAGNI scrutiny
|
|
18990
18987
|
- **Don't delegate when:** Routine decisions you're confident about • First bug fix attempt • Straightforward trade-offs • Tactical "how" vs strategic "should" • Time-sensitive good-enough decisions • Quick research/testing can answer
|
|
18991
18988
|
- **Rule of thumb:** Need senior architect review? → @oracle. Need code review or simplification? → @oracle. Routine coordination or final synthesis? → handle directly.`,
|
|
18992
18989
|
designer: `@designer
|
|
18993
|
-
- Lane: UI/UX design, related edits, design
|
|
18994
|
-
-
|
|
18995
|
-
- Permissions: Read/write files
|
|
18990
|
+
- Lane: UI/UX design, related edits, design polish and review
|
|
18991
|
+
- Permissions: read_files, write_files
|
|
18996
18992
|
- Stats: 10x better UI/UX than orchestrator
|
|
18997
18993
|
- Capabilities: Goot design taste, visual relevant edits, interactions, responsive layouts, design systems with aesthetic intent, deep UI/UX knowledge.
|
|
18998
|
-
- Weakness: copywriting,
|
|
18994
|
+
- Weakness: copywriting, when calling ask to use grounded, normal wording
|
|
18995
|
+
- Avoid: "Let me us designer how it should look and implement yourself" → instead: "Let me ask designer to design and implement the UI/UX changes for me"
|
|
18999
18996
|
- **Delegate when:** User-facing interfaces needing polish • Responsive layouts • UX-critical components (forms, nav, dashboards) • Visual consistency systems • Animations/micro-interactions • Landing/marketing pages • Refining functional→delightful • Reviewing existing UI/UX quality
|
|
19000
|
-
- **Don't delegate when:** Backend/logic with no visual • Quick prototypes where design doesn't matter yet
|
|
18997
|
+
- **Don't delegate when:** Backend/logic with no visual • Quick prototypes where design doesn't matter yet.
|
|
19001
18998
|
- **Rule of thumb:** Users see it and polish matters? → @designer. Headless/functional implementation? → schedule @fixer.`,
|
|
19002
18999
|
fixer: `@fixer
|
|
19003
|
-
- Lane: Bounded implementation and
|
|
19004
|
-
- Role: Fast execution specialist for well-defined tasks
|
|
19005
|
-
- Permissions:
|
|
19006
|
-
- Stats: 2x faster code edits, 1/2 cost of orchestrator
|
|
19007
|
-
- Weakness: design taste
|
|
19000
|
+
- Lane: Bounded implementation and executioner
|
|
19001
|
+
- Role: Fast execution specialist for well-defined tasks
|
|
19002
|
+
- Permissions: read_files, write_files
|
|
19003
|
+
- Stats: 2x faster code edits, 1/2 cost of orchestrator
|
|
19004
|
+
- Weakness: design, taste
|
|
19008
19005
|
- Tools/Constraints: Execution-focused—no research, no architectural decisions
|
|
19009
|
-
- **Delegate when:** For implementation work, think and triage first. If the change is non-trivial or multi-file, hand bounded execution to @fixer •
|
|
19010
|
-
- **Don't delegate when:** Needs discovery/research/decisions • Single small change (<20 lines, one file) • Unclear requirements needing iteration • Explaining to fixer > doing • Tight integration with your current work
|
|
19011
|
-
- **Rule of thumb:** Implementation are needed, schedule @fixer with clear scope. Bigger or lots of edits should be split by ownership and dispatched as parallel background fixer lanes when safe.`,
|
|
19006
|
+
- **Delegate when:** For implementation work, think and triage first. If the change is non-trivial or multi-file, hand bounded execution to @fixer • Parallelization benefits: Task involves multiple folders and multiple files modification, scoping work per folder and spawning parallel @fixers for each folder.
|
|
19007
|
+
- **Don't delegate when:** Needs discovery/research/decisions • Single small change (<20 lines, one file) • Unclear requirements needing iteration • Explaining to fixer > doing • Tight integration with your current work
|
|
19008
|
+
- **Rule of thumb:** Implementation are needed, schedule @fixer with clear scope. Bigger or lots of edits should be split by ownership and dispatched as parallel background @fixer lanes when safe. Editing files which includes design, ui, ux changes → schedule @designer.`,
|
|
19012
19009
|
council: `@council
|
|
19013
19010
|
- Lane: High-stakes multi-model decision support
|
|
19014
19011
|
- Role: Multi-LLM consensus engine that runs several councillors, synthesizes their views, and returns a structured council report.
|
|
@@ -19033,7 +19030,7 @@ var AGENT_DESCRIPTIONS = {
|
|
|
19033
19030
|
};
|
|
19034
19031
|
var VALIDATION_ROUTING = [
|
|
19035
19032
|
"- Route UI/UX validation and review to @designer",
|
|
19036
|
-
"- Route code review, simplification
|
|
19033
|
+
"- Route code review, code simplification and maintainability review checks to @oracle",
|
|
19037
19034
|
"- Route implementation to @fixer or multiple @fixer instances for maximum parallel execution",
|
|
19038
19035
|
"- Route visual/media analysis and interpretation to @observer",
|
|
19039
19036
|
"- If a request spans multiple lanes, delegate only the lanes that add clear value"
|
|
@@ -19066,6 +19063,7 @@ function buildOrchestratorPrompt(disabledAgents) {
|
|
|
19066
19063
|
You are a workflow manager for coding work. Your job is to plan, schedule, delegate, monitor, reconcile, and verify specialist-agent work. You are not the default implementation worker.
|
|
19067
19064
|
|
|
19068
19065
|
Optimize for quality, speed, cost, and reliability by dispatching the right specialist lanes, tracking background task state, and integrating terminal results into one coherent outcome.
|
|
19066
|
+
You have perfect understanding of agent's context management, understand well the cost of building content and reusing context of existing agents when it's best or when it's best to spawn a new agent.
|
|
19069
19067
|
</Role>
|
|
19070
19068
|
|
|
19071
19069
|
<Agents>
|
|
@@ -19080,22 +19078,26 @@ ${enabledAgents}
|
|
|
19080
19078
|
Parse request: explicit requirements + implicit needs.
|
|
19081
19079
|
|
|
19082
19080
|
## 2. Path Selection
|
|
19083
|
-
Evaluate approach by: quality, speed
|
|
19081
|
+
Evaluate approach by: quality, speed and cost.
|
|
19084
19082
|
Choose the path that optimizes all four.
|
|
19085
19083
|
|
|
19086
|
-
Classify work into lanes: discovery, external knowledge, implementation, UI/UX, review/risk, visual analysis, and final verification.
|
|
19087
|
-
|
|
19088
19084
|
## 3. Delegation Check
|
|
19089
|
-
|
|
19090
|
-
|
|
19091
|
-
!!! Review available agents and lane rules. Decide what to schedule, what depends on what, and what minimal direct coordination is needed. !!!
|
|
19085
|
+
Review available agents and lane rules.
|
|
19092
19086
|
|
|
19093
19087
|
**Dispatch efficiency:**
|
|
19094
19088
|
- Reference paths/lines, don't paste files (\`src/app.ts:42\` not full contents)
|
|
19095
|
-
- Provide context summaries, let specialists read what they need
|
|
19096
19089
|
- Brief user on delegation goal before each call
|
|
19097
|
-
- Keep direct work limited to clarification, minimal routing context, todos, synthesis, and final checks
|
|
19098
19090
|
- For trivial conversational answers or tiny mechanical edits, direct execution is allowed when scheduling overhead would clearly dominate
|
|
19091
|
+
- Record task IDs, state, and advisory ownership/dependency labels
|
|
19092
|
+
- Do not immediately wait after spawning independent background tasks unless the next step truly depends on their result
|
|
19093
|
+
- Reconcile results, resolve conflicts, and gate dependent lanes
|
|
19094
|
+
|
|
19095
|
+
**File operations rules:**
|
|
19096
|
+
- Always use dedicated file tools for file I/O.
|
|
19097
|
+
- Search files/code with \`glob\`, \`grep\`, or \`ast_grep_search\`.
|
|
19098
|
+
- Read files with \`read\`. Never use \`cat\`, \`head\`, \`tail\`, \`sed\`, \`awk\`, or bash commands to read file contents.
|
|
19099
|
+
- Edit files with \`apply_patch\`. Never use shell redirection, \`echo\`, \`printf\`, or heredocs for file content unless no file tool can do the job.
|
|
19100
|
+
- Use \`bash\` only for execution: git, package managers, tests, builds, scripts, or diagnostics.
|
|
19099
19101
|
|
|
19100
19102
|
## 4. Plan and Parallelize
|
|
19101
19103
|
Build a short work graph before dispatching:
|
|
@@ -19113,21 +19115,24 @@ Balance: respect dependencies, avoid parallelizing what must be sequential, and
|
|
|
19113
19115
|
- Delegated specialists should be launched as background tasks whenever work can run independently: use \`task(..., background: true)\`.
|
|
19114
19116
|
- A dispatch returns a task/session ID immediately; it does not mean completion.
|
|
19115
19117
|
- Track each task ID with specialist, objective, state, and any advisory ownership/dependency labels from the dispatch plan.
|
|
19116
|
-
-
|
|
19117
|
-
-
|
|
19118
|
+
- Background completion is event/hook-driven: when a background task finishes, OpenCode injects a follow-up message with the terminal result.
|
|
19119
|
+
- Continue orchestration while tasks run only when useful: planning, scheduling independent lanes, preparing synthesis, or asking needed user questions.
|
|
19120
|
+
- If no useful independent work remains, stop after a brief status response; do not call \`task_status\` just to wait. OpenCode will resume you when the background completion event arrives.
|
|
19121
|
+
- Use \`task_status(wait: true, timeout_ms: ...)\` only when you actively need a result before a dependent step or final response and no completion event has arrived yet.
|
|
19118
19122
|
- Parallel background tasks are allowed only when their write scopes do not conflict.
|
|
19119
19123
|
- Final response requires relevant tasks to be terminal and reconciled.
|
|
19120
19124
|
|
|
19121
|
-
|
|
19122
|
-
|
|
19123
|
-
|
|
19124
|
-
|
|
19125
|
-
|
|
19126
|
-
|
|
19127
|
-
|
|
19128
|
-
|
|
19129
|
-
|
|
19130
|
-
|
|
19125
|
+
### Background Job Discipline
|
|
19126
|
+
- Every background task owns its declared lane until terminal.
|
|
19127
|
+
- Do not duplicate, undermine, or race a running lane.
|
|
19128
|
+
- After dispatch, classify the next step:
|
|
19129
|
+
1. independent: continue,
|
|
19130
|
+
2. dependent: wait/poll,
|
|
19131
|
+
3. no useful independent work: stop and let hook-driven completion resume.
|
|
19132
|
+
- Before editing files or spawning another writer, compare against running job scopes.
|
|
19133
|
+
- Use \`cancel_task\` only when the user asks, or when a running lane is obsolete, wrong, or conflicts with a safer replacement plan.
|
|
19134
|
+
- Cancellation is not rollback: if cancelling a writer, inspect and reconcile partial file changes before launching a replacement lane.
|
|
19135
|
+
- Never finalize work that depends on unresolved background jobs.
|
|
19131
19136
|
|
|
19132
19137
|
### Session Reuse
|
|
19133
19138
|
- Smartly reuse an available specialist session - context reuse saves time and tokens
|
|
@@ -19242,6 +19247,12 @@ var COUNCIL_AGENT_PROMPT = `You are the Council agent — a multi-LLM orchestrat
|
|
|
19242
19247
|
- Be transparent about trade-offs when different approaches have valid pros/cons
|
|
19243
19248
|
- Don't just average responses — choose the best approach and improve upon it
|
|
19244
19249
|
|
|
19250
|
+
**File Operations Rules**:
|
|
19251
|
+
- Use dedicated tools for file I/O if local files must be inspected
|
|
19252
|
+
- Search files/code with glob, grep, or ast_grep_search
|
|
19253
|
+
- Read files with read. Never use cat, head, tail, sed, awk, or bash commands to read file contents
|
|
19254
|
+
- Use bash only for execution/diagnostics, never for file I/O
|
|
19255
|
+
|
|
19245
19256
|
**Required Output Format**:
|
|
19246
19257
|
Always include these sections in your final response:
|
|
19247
19258
|
|
|
@@ -19353,6 +19364,12 @@ var COUNCILLOR_PROMPT = `You are a councillor in a multi-model council.
|
|
|
19353
19364
|
|
|
19354
19365
|
You CANNOT edit files, write files, run shell commands, or delegate to other agents. You are an advisor, not an implementer.
|
|
19355
19366
|
|
|
19367
|
+
**File Operations Rules**:
|
|
19368
|
+
- READ-ONLY: do not modify files
|
|
19369
|
+
- Search files/code with glob, grep, or ast_grep_search
|
|
19370
|
+
- Read files with read. Never use cat, head, tail, sed, awk, or bash commands to read file contents
|
|
19371
|
+
- Do not use bash or shell commands
|
|
19372
|
+
|
|
19356
19373
|
**Behavior**:
|
|
19357
19374
|
- **Examine the codebase** before answering — your read access is what makes council valuable. Don't guess at code you can see.
|
|
19358
19375
|
- Analyze the problem thoroughly
|
|
@@ -19440,6 +19457,13 @@ var DESIGNER_PROMPT = `You are a Designer - a frontend UI/UX specialist who crea
|
|
|
19440
19457
|
- Leverage component libraries where available
|
|
19441
19458
|
- Prioritize visual excellence—code perfection comes second
|
|
19442
19459
|
|
|
19460
|
+
## File Operations Rules
|
|
19461
|
+
- Always use dedicated file tools for file I/O
|
|
19462
|
+
- Search files/code with glob, grep, or ast_grep_search
|
|
19463
|
+
- Read files with read. Never use cat, head, tail, sed, awk, or bash commands to read file contents
|
|
19464
|
+
- Edit/write files with write, edit, or apply_patch. Never use shell redirection, echo, printf, or heredocs for file content unless no file tool can do the job
|
|
19465
|
+
- Use bash only for execution: git, package managers, tests, builds, scripts, or diagnostics
|
|
19466
|
+
|
|
19443
19467
|
## Review Responsibilities
|
|
19444
19468
|
- Review existing UI for usability, responsiveness, visual consistency, and polish when asked
|
|
19445
19469
|
- Call out concrete UX issues and improvements, not just abstract design advice
|
|
@@ -19477,6 +19501,12 @@ var EXPLORER_PROMPT = `You are Explorer - a fast codebase navigation specialist.
|
|
|
19477
19501
|
- **Structural patterns** (function shapes, class structures): ast_grep_search
|
|
19478
19502
|
- **File discovery** (find by name/extension): glob
|
|
19479
19503
|
|
|
19504
|
+
**File Operations Rules**:
|
|
19505
|
+
- READ-ONLY: Search and report, don't modify files
|
|
19506
|
+
- Search files/code with glob, grep, or ast_grep_search
|
|
19507
|
+
- Read files with read. Never use cat, head, tail, sed, awk, or bash commands to read file contents
|
|
19508
|
+
- Use bash only for execution/diagnostics, never for file I/O
|
|
19509
|
+
|
|
19480
19510
|
**Behavior**:
|
|
19481
19511
|
- Be fast and thorough
|
|
19482
19512
|
- Fire multiple searches in parallel if needed
|
|
@@ -19531,6 +19561,13 @@ var FIXER_PROMPT = `You are Fixer - a fast, focused implementation specialist.
|
|
|
19531
19561
|
- Run relevant validation when requested or clearly applicable (otherwise note as skipped with reason)
|
|
19532
19562
|
- Report completion with summary of changes
|
|
19533
19563
|
|
|
19564
|
+
**File Operations Rules**:
|
|
19565
|
+
- Always use dedicated file tools for file I/O
|
|
19566
|
+
- Search files/code with glob, grep, or ast_grep_search
|
|
19567
|
+
- Read files with read. Never use cat, head, tail, sed, awk, or bash commands to read file contents
|
|
19568
|
+
- Edit/write files with write, edit, or apply_patch. Never use shell redirection, echo, printf, or heredocs for file content unless no file tool can do the job
|
|
19569
|
+
- Use bash only for execution: git, package managers, tests, builds, scripts, or diagnostics
|
|
19570
|
+
|
|
19534
19571
|
**Constraints**:
|
|
19535
19572
|
- NO external research (no websearch, context7, grep_app)
|
|
19536
19573
|
- NO delegation or spawning subagents
|
|
@@ -19596,6 +19633,12 @@ var LIBRARIAN_PROMPT = `You are Librarian - a research specialist for codebases
|
|
|
19596
19633
|
- grep_app: Search GitHub repositories
|
|
19597
19634
|
- websearch: General web search for docs
|
|
19598
19635
|
|
|
19636
|
+
**File Operations Rules**:
|
|
19637
|
+
- Use dedicated tools for file I/O when local files must be inspected
|
|
19638
|
+
- Search files/code with glob, grep, or ast_grep_search
|
|
19639
|
+
- Read files with read. Never use cat, head, tail, sed, awk, or bash commands to read file contents
|
|
19640
|
+
- Use bash only for execution/diagnostics, never for file I/O
|
|
19641
|
+
|
|
19599
19642
|
**Behavior**:
|
|
19600
19643
|
- Provide evidence-based answers with sources
|
|
19601
19644
|
- Quote relevant code snippets
|
|
@@ -19640,6 +19683,11 @@ var OBSERVER_PROMPT = `You are Observer — a visual analysis specialist.
|
|
|
19640
19683
|
- Save context tokens — the Orchestrator never processes the raw file
|
|
19641
19684
|
- Match the language of the request
|
|
19642
19685
|
- If info not found, state clearly what's missing
|
|
19686
|
+
|
|
19687
|
+
**File Operations Rules**:
|
|
19688
|
+
- READ-ONLY: do not modify files
|
|
19689
|
+
- Read files with read. Never use cat, head, tail, sed, awk, or bash commands to read file contents
|
|
19690
|
+
- Use bash only for execution/diagnostics, never for file I/O
|
|
19643
19691
|
`;
|
|
19644
19692
|
function createObserverAgent(model, customPrompt, customAppendPrompt) {
|
|
19645
19693
|
let prompt = OBSERVER_PROMPT;
|
|
@@ -19684,6 +19732,12 @@ var ORACLE_PROMPT = `You are Oracle - a strategic technical advisor and code rev
|
|
|
19684
19732
|
- READ-ONLY: You advise, you don't implement
|
|
19685
19733
|
- Focus on strategy, not execution
|
|
19686
19734
|
- Point to specific files/lines when relevant
|
|
19735
|
+
|
|
19736
|
+
**File Operations Rules**:
|
|
19737
|
+
- READ-ONLY: do not modify files
|
|
19738
|
+
- Search files/code with glob, grep, or ast_grep_search
|
|
19739
|
+
- Read files with read. Never use cat, head, tail, sed, awk, or bash commands to read file contents
|
|
19740
|
+
- Use bash only for execution/diagnostics, never for file I/O
|
|
19687
19741
|
`;
|
|
19688
19742
|
function createOracleAgent(model, customPrompt, customAppendPrompt) {
|
|
19689
19743
|
let prompt = ORACLE_PROMPT;
|
|
@@ -19707,6 +19761,7 @@ ${customAppendPrompt}`;
|
|
|
19707
19761
|
|
|
19708
19762
|
// src/agents/index.ts
|
|
19709
19763
|
var COUNCIL_TOOL_ALLOWED_AGENTS = new Set(["council"]);
|
|
19764
|
+
var CANCEL_TASK_ALLOWED_AGENTS = new Set(["orchestrator"]);
|
|
19710
19765
|
var SAFE_AGENT_ALIAS_RE = /^[a-z][a-z0-9_-]*$/i;
|
|
19711
19766
|
function normalizeDisplayName(displayName) {
|
|
19712
19767
|
const trimmed = displayName.trim();
|
|
@@ -19783,10 +19838,12 @@ function applyDefaultPermissions(agent, configuredSkills) {
|
|
|
19783
19838
|
const skillPermissions = getSkillPermissionsForAgent(agent.name, configuredSkills);
|
|
19784
19839
|
const questionPerm = existing.question === "deny" ? "deny" : "allow";
|
|
19785
19840
|
const councilSessionPerm = COUNCIL_TOOL_ALLOWED_AGENTS.has(agent.name) ? existing.council_session ?? "allow" : "deny";
|
|
19841
|
+
const cancelTaskPerm = CANCEL_TASK_ALLOWED_AGENTS.has(agent.name) ? existing.cancel_task ?? "allow" : "deny";
|
|
19786
19842
|
agent.config.permission = {
|
|
19787
19843
|
...existing,
|
|
19788
19844
|
question: questionPerm,
|
|
19789
19845
|
council_session: councilSessionPerm,
|
|
19846
|
+
cancel_task: cancelTaskPerm,
|
|
19790
19847
|
skill: {
|
|
19791
19848
|
...typeof existing.skill === "object" ? existing.skill : {},
|
|
19792
19849
|
...skillPermissions
|
|
@@ -22684,6 +22741,7 @@ class BackgroundJobBoard {
|
|
|
22684
22741
|
terminalUnreconciled: false,
|
|
22685
22742
|
completedAt: undefined,
|
|
22686
22743
|
resultSummary: undefined,
|
|
22744
|
+
lastLaunchedAt: now,
|
|
22687
22745
|
updatedAt: now
|
|
22688
22746
|
};
|
|
22689
22747
|
this.jobs.set(input.taskID, updated);
|
|
@@ -22699,6 +22757,7 @@ class BackgroundJobBoard {
|
|
|
22699
22757
|
timedOut: false,
|
|
22700
22758
|
terminalUnreconciled: false,
|
|
22701
22759
|
launchedAt: now,
|
|
22760
|
+
lastLaunchedAt: now,
|
|
22702
22761
|
updatedAt: now,
|
|
22703
22762
|
alias: this.nextAlias(input.parentSessionID, input.agent)
|
|
22704
22763
|
};
|
|
@@ -22709,7 +22768,7 @@ class BackgroundJobBoard {
|
|
|
22709
22768
|
const existing = this.jobs.get(input.taskID);
|
|
22710
22769
|
if (!existing)
|
|
22711
22770
|
return;
|
|
22712
|
-
if (existing.state === "reconciled") {
|
|
22771
|
+
if (existing.state === "reconciled" || existing.state === "cancelled" && input.state !== "cancelled" || TERMINAL_STATES.has(existing.state) && input.state === "running") {
|
|
22713
22772
|
return existing;
|
|
22714
22773
|
}
|
|
22715
22774
|
const now = input.now ?? Date.now();
|
|
@@ -22753,9 +22812,34 @@ class BackgroundJobBoard {
|
|
|
22753
22812
|
this.jobs.set(taskID, updated);
|
|
22754
22813
|
return updated;
|
|
22755
22814
|
}
|
|
22815
|
+
markCancelled(taskID, reason, now = Date.now()) {
|
|
22816
|
+
const existing = this.jobs.get(taskID);
|
|
22817
|
+
if (!existing)
|
|
22818
|
+
return;
|
|
22819
|
+
if (existing.state === "reconciled")
|
|
22820
|
+
return existing;
|
|
22821
|
+
if (TERMINAL_STATES.has(existing.state))
|
|
22822
|
+
return existing;
|
|
22823
|
+
const summary = normalizeCancelReason(reason);
|
|
22824
|
+
const updated = {
|
|
22825
|
+
...existing,
|
|
22826
|
+
state: "cancelled",
|
|
22827
|
+
timedOut: false,
|
|
22828
|
+
terminalUnreconciled: true,
|
|
22829
|
+
updatedAt: now,
|
|
22830
|
+
completedAt: existing.completedAt ?? now,
|
|
22831
|
+
resultSummary: summary
|
|
22832
|
+
};
|
|
22833
|
+
this.jobs.set(taskID, updated);
|
|
22834
|
+
return updated;
|
|
22835
|
+
}
|
|
22756
22836
|
get(taskID) {
|
|
22757
22837
|
return this.jobs.get(taskID);
|
|
22758
22838
|
}
|
|
22839
|
+
resolve(parentSessionID, taskIDOrAlias) {
|
|
22840
|
+
const value = taskIDOrAlias.trim();
|
|
22841
|
+
return this.list(parentSessionID).find((job) => job.taskID === value || job.alias === value);
|
|
22842
|
+
}
|
|
22759
22843
|
list(parentSessionID) {
|
|
22760
22844
|
const jobs = [...this.jobs.values()];
|
|
22761
22845
|
const filtered = parentSessionID ? jobs.filter((job) => job.parentSessionID === parentSessionID) : jobs;
|
|
@@ -22767,7 +22851,7 @@ class BackgroundJobBoard {
|
|
|
22767
22851
|
hasTerminalUnreconciled(parentSessionID) {
|
|
22768
22852
|
return this.list(parentSessionID).some((job) => job.terminalUnreconciled);
|
|
22769
22853
|
}
|
|
22770
|
-
formatForPrompt(parentSessionID) {
|
|
22854
|
+
formatForPrompt(parentSessionID, now = Date.now()) {
|
|
22771
22855
|
const jobs = this.list(parentSessionID).filter((job) => job.state === "running" || job.terminalUnreconciled);
|
|
22772
22856
|
if (jobs.length === 0)
|
|
22773
22857
|
return;
|
|
@@ -22775,7 +22859,7 @@ class BackgroundJobBoard {
|
|
|
22775
22859
|
"### Background Job Board",
|
|
22776
22860
|
"Use task_status before consuming running jobs. Reconcile terminal jobs before final response.",
|
|
22777
22861
|
"",
|
|
22778
|
-
...jobs.map(formatJob)
|
|
22862
|
+
...jobs.map((job) => formatJob(job, now))
|
|
22779
22863
|
].join(`
|
|
22780
22864
|
`);
|
|
22781
22865
|
}
|
|
@@ -22795,8 +22879,11 @@ class BackgroundJobBoard {
|
|
|
22795
22879
|
return `${prefix2}-${next}`;
|
|
22796
22880
|
}
|
|
22797
22881
|
}
|
|
22798
|
-
function formatJob(job) {
|
|
22799
|
-
const
|
|
22882
|
+
function formatJob(job, now = Date.now()) {
|
|
22883
|
+
const ageMs = now - job.lastLaunchedAt;
|
|
22884
|
+
const isResume = job.lastLaunchedAt !== job.launchedAt;
|
|
22885
|
+
const ageLabel = job.state === "running" && ageMs < 30000 ? ` [${isResume ? "resumed" : "just launched"}, ${Math.floor(ageMs / 1000)}s ago]` : "";
|
|
22886
|
+
const status = job.terminalUnreconciled ? `${job.state}, unreconciled` : job.timedOut ? `${job.state}, timed out` : `${job.state}${ageLabel}`;
|
|
22800
22887
|
const lines = [
|
|
22801
22888
|
`- ${job.alias} / ${job.taskID} / ${job.agent} / ${status}`,
|
|
22802
22889
|
` Objective: ${job.objective || job.description}`
|
|
@@ -22813,6 +22900,10 @@ function singleLine(value) {
|
|
|
22813
22900
|
return normalized;
|
|
22814
22901
|
return `${normalized.slice(0, 157)}...`;
|
|
22815
22902
|
}
|
|
22903
|
+
function normalizeCancelReason(reason) {
|
|
22904
|
+
const normalized = reason?.replace(/\s+/g, " ").trim();
|
|
22905
|
+
return normalized ? `cancelled: ${normalized}` : "cancelled";
|
|
22906
|
+
}
|
|
22816
22907
|
// src/utils/internal-initiator.ts
|
|
22817
22908
|
var SLIM_INTERNAL_INITIATOR_MARKER = "<!-- SLIM_INTERNAL_INITIATOR -->";
|
|
22818
22909
|
function isRecord(value) {
|
|
@@ -23441,7 +23532,7 @@ var RATE_LIMIT_PATTERNS = [
|
|
|
23441
23532
|
/usage limit/i,
|
|
23442
23533
|
/overloaded/i,
|
|
23443
23534
|
/resource.?exhausted/i,
|
|
23444
|
-
/insufficient.?quota/i,
|
|
23535
|
+
/insufficient.?(quota|balance)/i,
|
|
23445
23536
|
/high concurrency/i,
|
|
23446
23537
|
/reduce concurrency/i
|
|
23447
23538
|
];
|
|
@@ -23517,7 +23608,7 @@ class ForegroundFallbackManager {
|
|
|
23517
23608
|
if (!props?.sessionID || props.status?.type !== "retry")
|
|
23518
23609
|
break;
|
|
23519
23610
|
const msg = props.status.message?.toLowerCase() ?? "";
|
|
23520
|
-
if (msg.includes("rate limit") || msg.includes("usage limit") || msg.includes("usage exceeded") || msg.includes("quota exceeded") || msg.includes("exceededbudget") || msg.includes("over budget") || msg.includes("high concurrency") || msg.includes("reduce concurrency")) {
|
|
23611
|
+
if (msg.includes("rate limit") || msg.includes("usage limit") || msg.includes("usage exceeded") || msg.includes("quota exceeded") || msg.includes("exceededbudget") || msg.includes("over budget") || msg.includes("insufficient") || msg.includes("high concurrency") || msg.includes("reduce concurrency")) {
|
|
23521
23612
|
await this.tryFallback(props.sessionID);
|
|
23522
23613
|
}
|
|
23523
23614
|
break;
|
|
@@ -24737,7 +24828,7 @@ function createTaskSessionManagerHook(_ctx, options) {
|
|
|
24737
24828
|
};
|
|
24738
24829
|
}
|
|
24739
24830
|
// src/hooks/todo-continuation/index.ts
|
|
24740
|
-
import { tool } from "@opencode-ai/plugin
|
|
24831
|
+
import { tool } from "@opencode-ai/plugin";
|
|
24741
24832
|
|
|
24742
24833
|
// src/hooks/todo-continuation/todo-hygiene.ts
|
|
24743
24834
|
var TODO_HYGIENE_REMINDER = "If the active task changed or finished, update the todo list to match the current work state.";
|
|
@@ -29755,7 +29846,6 @@ function startAvailabilityCheck(config) {
|
|
|
29755
29846
|
}
|
|
29756
29847
|
}
|
|
29757
29848
|
// src/multiplexer/session-manager.ts
|
|
29758
|
-
var SESSION_TIMEOUT_MS = 10 * 60 * 1000;
|
|
29759
29849
|
var SESSION_MISSING_GRACE_MS = POLL_INTERVAL_BACKGROUND_MS * 3;
|
|
29760
29850
|
var SHARED_STATE_KEY = Symbol.for("oh-my-opencode-slim.multiplexer-session-manager.state");
|
|
29761
29851
|
function getSharedState() {
|
|
@@ -29769,6 +29859,7 @@ function getSharedState() {
|
|
|
29769
29859
|
return globalWithState[SHARED_STATE_KEY];
|
|
29770
29860
|
}
|
|
29771
29861
|
class MultiplexerSessionManager {
|
|
29862
|
+
backgroundJobBoard;
|
|
29772
29863
|
instanceId = Math.random().toString(36).slice(2, 8);
|
|
29773
29864
|
serverUrl;
|
|
29774
29865
|
directory;
|
|
@@ -29779,7 +29870,8 @@ class MultiplexerSessionManager {
|
|
|
29779
29870
|
closingSessions;
|
|
29780
29871
|
pollInterval;
|
|
29781
29872
|
enabled = false;
|
|
29782
|
-
constructor(ctx, config) {
|
|
29873
|
+
constructor(ctx, config, backgroundJobBoard) {
|
|
29874
|
+
this.backgroundJobBoard = backgroundJobBoard;
|
|
29783
29875
|
const sharedState = getSharedState();
|
|
29784
29876
|
this.sessions = sharedState.sessions;
|
|
29785
29877
|
this.knownSessions = sharedState.knownSessions;
|
|
@@ -29874,7 +29966,8 @@ class MultiplexerSessionManager {
|
|
|
29874
29966
|
title,
|
|
29875
29967
|
directory,
|
|
29876
29968
|
createdAt: now,
|
|
29877
|
-
lastSeenAt: now
|
|
29969
|
+
lastSeenAt: now,
|
|
29970
|
+
seenInStatus: false
|
|
29878
29971
|
});
|
|
29879
29972
|
log("[multiplexer-session-manager] pane spawned", {
|
|
29880
29973
|
instanceId: this.instanceId,
|
|
@@ -29966,16 +30059,26 @@ class MultiplexerSessionManager {
|
|
|
29966
30059
|
const isIdle = status?.type === "idle";
|
|
29967
30060
|
if (status) {
|
|
29968
30061
|
tracked.lastSeenAt = now;
|
|
30062
|
+
tracked.seenInStatus = true;
|
|
29969
30063
|
tracked.missingSince = undefined;
|
|
29970
30064
|
} else if (!tracked.missingSince) {
|
|
29971
30065
|
tracked.missingSince = now;
|
|
29972
30066
|
}
|
|
29973
30067
|
const missingTooLong = !!tracked.missingSince && now - tracked.missingSince >= SESSION_MISSING_GRACE_MS;
|
|
29974
|
-
const
|
|
29975
|
-
if (isIdle || missingTooLong
|
|
30068
|
+
const shouldKeepRunningBackgroundJob = missingTooLong && this.isRunningBackgroundJob(sessionId);
|
|
30069
|
+
if (isIdle || missingTooLong) {
|
|
30070
|
+
if (shouldKeepRunningBackgroundJob) {
|
|
30071
|
+
log("[multiplexer-session-manager] keeping running background pane", {
|
|
30072
|
+
instanceId: this.instanceId,
|
|
30073
|
+
sessionId,
|
|
30074
|
+
paneId: tracked.paneId,
|
|
30075
|
+
seenInStatus: tracked.seenInStatus
|
|
30076
|
+
});
|
|
30077
|
+
continue;
|
|
30078
|
+
}
|
|
29976
30079
|
sessionsToClose.push({
|
|
29977
30080
|
sessionId,
|
|
29978
|
-
reason: isIdle ? "idle" :
|
|
30081
|
+
reason: isIdle ? "idle" : "missing"
|
|
29979
30082
|
});
|
|
29980
30083
|
}
|
|
29981
30084
|
}
|
|
@@ -29992,7 +30095,15 @@ class MultiplexerSessionManager {
|
|
|
29992
30095
|
if (!response.ok) {
|
|
29993
30096
|
throw new Error(`session status request failed: ${response.status} ${response.statusText}`);
|
|
29994
30097
|
}
|
|
29995
|
-
|
|
30098
|
+
const body = await response.text();
|
|
30099
|
+
if (body.trim() === "") {
|
|
30100
|
+
throw new Error("session status response was empty");
|
|
30101
|
+
}
|
|
30102
|
+
try {
|
|
30103
|
+
return JSON.parse(body);
|
|
30104
|
+
} catch (err) {
|
|
30105
|
+
throw new Error(`session status response was not valid JSON: ${err}`);
|
|
30106
|
+
}
|
|
29996
30107
|
}
|
|
29997
30108
|
async closeSession(sessionId, reason) {
|
|
29998
30109
|
if (reason === "deleted") {
|
|
@@ -30092,7 +30203,8 @@ class MultiplexerSessionManager {
|
|
|
30092
30203
|
title: known.title,
|
|
30093
30204
|
directory: known.directory,
|
|
30094
30205
|
createdAt: now,
|
|
30095
|
-
lastSeenAt: now
|
|
30206
|
+
lastSeenAt: now,
|
|
30207
|
+
seenInStatus: false
|
|
30096
30208
|
});
|
|
30097
30209
|
log("[multiplexer-session-manager] pane respawned on busy", {
|
|
30098
30210
|
instanceId: this.instanceId,
|
|
@@ -30117,6 +30229,9 @@ class MultiplexerSessionManager {
|
|
|
30117
30229
|
getSessionId(event) {
|
|
30118
30230
|
return event.properties?.info?.id ?? event.properties?.sessionID;
|
|
30119
30231
|
}
|
|
30232
|
+
isRunningBackgroundJob(sessionId) {
|
|
30233
|
+
return this.backgroundJobBoard?.get(sessionId)?.state === "running";
|
|
30234
|
+
}
|
|
30120
30235
|
async cleanup() {
|
|
30121
30236
|
this.stopPolling();
|
|
30122
30237
|
if (this.closingSessions.size > 0) {
|
|
@@ -30162,7 +30277,7 @@ async function isServerRunning(serverUrl, timeoutMs = 3000, maxAttempts = 2) {
|
|
|
30162
30277
|
return false;
|
|
30163
30278
|
}
|
|
30164
30279
|
// src/tools/ast-grep/tools.ts
|
|
30165
|
-
import { tool as tool2 } from "@opencode-ai/plugin
|
|
30280
|
+
import { tool as tool2 } from "@opencode-ai/plugin";
|
|
30166
30281
|
|
|
30167
30282
|
// src/tools/ast-grep/cli.ts
|
|
30168
30283
|
import { existsSync as existsSync9 } from "node:fs";
|
|
@@ -30707,11 +30822,96 @@ var ast_grep_replace = tool2({
|
|
|
30707
30822
|
}
|
|
30708
30823
|
}
|
|
30709
30824
|
});
|
|
30710
|
-
// src/tools/
|
|
30825
|
+
// src/tools/cancel-task.ts
|
|
30711
30826
|
import {
|
|
30712
30827
|
tool as tool3
|
|
30713
30828
|
} from "@opencode-ai/plugin";
|
|
30714
30829
|
var z4 = tool3.schema;
|
|
30830
|
+
function createCancelTaskTool(options) {
|
|
30831
|
+
const cancel_task = tool3({
|
|
30832
|
+
description: `Cancel a tracked background specialist task.
|
|
30833
|
+
|
|
30834
|
+
Use only for obsolete, wrong, conflicting, or user-requested cancellation. Accepts either the native task_id/session ID or the parent-scoped alias shown in the Background Job Board. Cancellation is not rollback: if cancelling a writer, inspect and reconcile partial file changes before replacing the lane.`,
|
|
30835
|
+
args: {
|
|
30836
|
+
task_id: z4.string().describe("Tracked background task ID or Background Job Board alias"),
|
|
30837
|
+
reason: z4.string().optional().describe("Short cancellation reason")
|
|
30838
|
+
},
|
|
30839
|
+
async execute(args, toolContext) {
|
|
30840
|
+
const parentSessionID = toolContext?.sessionID;
|
|
30841
|
+
if (!parentSessionID)
|
|
30842
|
+
throw new Error("cancel_task requires sessionID");
|
|
30843
|
+
if (toolContext.agent && toolContext.agent !== "orchestrator") {
|
|
30844
|
+
throw new Error("cancel_task can only be used by orchestrator");
|
|
30845
|
+
}
|
|
30846
|
+
if (!options.shouldManageSession(parentSessionID)) {
|
|
30847
|
+
throw new Error("cancel_task can only be used in orchestrator sessions");
|
|
30848
|
+
}
|
|
30849
|
+
const requested = args.task_id.trim();
|
|
30850
|
+
if (!requested)
|
|
30851
|
+
throw new Error("cancel_task requires task_id");
|
|
30852
|
+
const job = options.backgroundJobBoard.resolve(parentSessionID, requested);
|
|
30853
|
+
if (!job) {
|
|
30854
|
+
return [
|
|
30855
|
+
`task_id: ${requested}`,
|
|
30856
|
+
"state: unknown",
|
|
30857
|
+
"",
|
|
30858
|
+
"<task_error>",
|
|
30859
|
+
"unknown or unowned background task",
|
|
30860
|
+
"</task_error>"
|
|
30861
|
+
].join(`
|
|
30862
|
+
`);
|
|
30863
|
+
}
|
|
30864
|
+
if (job.state !== "running") {
|
|
30865
|
+
return [
|
|
30866
|
+
`task_id: ${job.taskID}`,
|
|
30867
|
+
`state: ${job.state}`,
|
|
30868
|
+
"",
|
|
30869
|
+
"<task_result>",
|
|
30870
|
+
`not cancelled: task is already ${job.state}`,
|
|
30871
|
+
"</task_result>"
|
|
30872
|
+
].join(`
|
|
30873
|
+
`);
|
|
30874
|
+
}
|
|
30875
|
+
try {
|
|
30876
|
+
await abortSessionWithTimeout(options.client, job.taskID, options.abortTimeoutMs ?? 1e4);
|
|
30877
|
+
} catch (error) {
|
|
30878
|
+
const timedOut = error instanceof OperationTimeoutError;
|
|
30879
|
+
if (timedOut) {
|
|
30880
|
+
options.backgroundJobBoard.updateStatus({
|
|
30881
|
+
taskID: job.taskID,
|
|
30882
|
+
state: "error",
|
|
30883
|
+
resultSummary: error instanceof Error ? error.message : "cancel request timed out"
|
|
30884
|
+
});
|
|
30885
|
+
}
|
|
30886
|
+
return [
|
|
30887
|
+
`task_id: ${job.taskID}`,
|
|
30888
|
+
`state: ${timedOut ? "error" : "cancel_error"}`,
|
|
30889
|
+
"",
|
|
30890
|
+
"<task_error>",
|
|
30891
|
+
error instanceof Error ? error.message : String(error),
|
|
30892
|
+
"</task_error>"
|
|
30893
|
+
].join(`
|
|
30894
|
+
`);
|
|
30895
|
+
}
|
|
30896
|
+
const cancelled = options.backgroundJobBoard.markCancelled(job.taskID, args.reason);
|
|
30897
|
+
return [
|
|
30898
|
+
`task_id: ${job.taskID}`,
|
|
30899
|
+
`state: ${cancelled?.state ?? "cancelled"}`,
|
|
30900
|
+
"",
|
|
30901
|
+
"<task_error>",
|
|
30902
|
+
cancelled?.resultSummary ?? "cancelled",
|
|
30903
|
+
"</task_error>"
|
|
30904
|
+
].join(`
|
|
30905
|
+
`);
|
|
30906
|
+
}
|
|
30907
|
+
});
|
|
30908
|
+
return { cancel_task };
|
|
30909
|
+
}
|
|
30910
|
+
// src/tools/council.ts
|
|
30911
|
+
import {
|
|
30912
|
+
tool as tool4
|
|
30913
|
+
} from "@opencode-ai/plugin";
|
|
30914
|
+
var z5 = tool4.schema;
|
|
30715
30915
|
function formatModelComposition(councillorResults) {
|
|
30716
30916
|
return councillorResults.map((cr) => {
|
|
30717
30917
|
const shortModel = shortModelLabel(cr.model);
|
|
@@ -30719,15 +30919,15 @@ function formatModelComposition(councillorResults) {
|
|
|
30719
30919
|
}).join(", ");
|
|
30720
30920
|
}
|
|
30721
30921
|
function createCouncilTool(_ctx, councilManager) {
|
|
30722
|
-
const council_session =
|
|
30922
|
+
const council_session = tool4({
|
|
30723
30923
|
description: `Launch a multi-LLM council session for consensus-based analysis.
|
|
30724
30924
|
|
|
30725
30925
|
Sends the prompt to multiple models (councillors) in parallel and returns their formatted responses for you to synthesize.
|
|
30726
30926
|
|
|
30727
30927
|
Returns the councillor responses with a summary footer.`,
|
|
30728
30928
|
args: {
|
|
30729
|
-
prompt:
|
|
30730
|
-
preset:
|
|
30929
|
+
prompt: z5.string().describe("The prompt to send to all councillors"),
|
|
30930
|
+
preset: z5.string().optional().describe('Council preset to use (default: "default"). Must match a preset in the council config.')
|
|
30731
30931
|
},
|
|
30732
30932
|
async execute(args, toolContext) {
|
|
30733
30933
|
if (!toolContext || typeof toolContext !== "object" || !("sessionID" in toolContext)) {
|
|
@@ -31038,7 +31238,7 @@ var WEBFETCH_DESCRIPTION = "Fetch a URL with better extraction for static/docs p
|
|
|
31038
31238
|
import os6 from "node:os";
|
|
31039
31239
|
import path18 from "node:path";
|
|
31040
31240
|
import {
|
|
31041
|
-
tool as
|
|
31241
|
+
tool as tool5
|
|
31042
31242
|
} from "@opencode-ai/plugin";
|
|
31043
31243
|
|
|
31044
31244
|
// src/tools/smartfetch/binary.ts
|
|
@@ -31206,7 +31406,7 @@ var M = class u2 {
|
|
|
31206
31406
|
return this.#S;
|
|
31207
31407
|
}
|
|
31208
31408
|
constructor(e) {
|
|
31209
|
-
let { max: t = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: o, updateAgeOnHas: r, allowStale: h, dispose: l, onInsert: c, disposeAfter: f, noDisposeOnSet: g, noUpdateTTL: p, maxSize: T = 0, maxEntrySize: w = 0, sizeCalculation: y, fetchMethod: a, memoMethod: m, noDeleteOnFetchRejection: _, noDeleteOnStaleGet: b, allowStaleOnFetchRejection: d, allowStaleOnFetchAbort: A, ignoreFetchAbort:
|
|
31409
|
+
let { max: t = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: o, updateAgeOnHas: r, allowStale: h, dispose: l, onInsert: c, disposeAfter: f, noDisposeOnSet: g, noUpdateTTL: p, maxSize: T = 0, maxEntrySize: w = 0, sizeCalculation: y, fetchMethod: a, memoMethod: m, noDeleteOnFetchRejection: _, noDeleteOnStaleGet: b, allowStaleOnFetchRejection: d, allowStaleOnFetchAbort: A, ignoreFetchAbort: z6, perf: x } = e;
|
|
31210
31410
|
if (x !== undefined && typeof x?.now != "function")
|
|
31211
31411
|
throw new TypeError("perf option must have a now() method if specified");
|
|
31212
31412
|
if (this.#m = x ?? C, t !== 0 && !F(t))
|
|
@@ -31224,7 +31424,7 @@ var M = class u2 {
|
|
|
31224
31424
|
throw new TypeError("memoMethod must be a function if defined");
|
|
31225
31425
|
if (this.#U = m, a !== undefined && typeof a != "function")
|
|
31226
31426
|
throw new TypeError("fetchMethod must be a function if specified");
|
|
31227
|
-
if (this.#M = a, this.#W = !!a, this.#s = new Map, this.#i = Array.from({ length: t }).fill(undefined), this.#t = Array.from({ length: t }).fill(undefined), this.#a = new v(t), this.#c = new v(t), this.#l = 0, this.#h = 0, this.#y = R.create(t), this.#n = 0, this.#b = 0, typeof l == "function" && (this.#w = l), typeof c == "function" && (this.#x = c), typeof f == "function" ? (this.#S = f, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#j = !!this.#x, this.#f = !!this.#S, this.noDisposeOnSet = !!g, this.noUpdateTTL = !!p, this.noDeleteOnFetchRejection = !!_, this.allowStaleOnFetchRejection = !!d, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!
|
|
31427
|
+
if (this.#M = a, this.#W = !!a, this.#s = new Map, this.#i = Array.from({ length: t }).fill(undefined), this.#t = Array.from({ length: t }).fill(undefined), this.#a = new v(t), this.#c = new v(t), this.#l = 0, this.#h = 0, this.#y = R.create(t), this.#n = 0, this.#b = 0, typeof l == "function" && (this.#w = l), typeof c == "function" && (this.#x = c), typeof f == "function" ? (this.#S = f, this.#r = []) : (this.#S = undefined, this.#r = undefined), this.#T = !!this.#w, this.#j = !!this.#x, this.#f = !!this.#S, this.noDisposeOnSet = !!g, this.noUpdateTTL = !!p, this.noDeleteOnFetchRejection = !!_, this.allowStaleOnFetchRejection = !!d, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!z6, this.maxEntrySize !== 0) {
|
|
31228
31428
|
if (this.#u !== 0 && !F(this.#u))
|
|
31229
31429
|
throw new TypeError("maxSize must be a positive integer if specified");
|
|
31230
31430
|
if (!F(this.maxEntrySize))
|
|
@@ -31604,8 +31804,8 @@ var M = class u2 {
|
|
|
31604
31804
|
let A = this.#p(b);
|
|
31605
31805
|
if (!y && !A)
|
|
31606
31806
|
return a && (a.fetch = "hit"), this.#L(b), s && this.#D(b), a && this.#E(a, b), d;
|
|
31607
|
-
let
|
|
31608
|
-
return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ?
|
|
31807
|
+
let z6 = this.#P(e, b, _, w), v = z6.__staleWhileFetching !== undefined && i;
|
|
31808
|
+
return a && (a.fetch = A ? "stale" : "refresh", v && A && (a.returnedStale = true)), v ? z6.__staleWhileFetching : z6.__returned = z6;
|
|
31609
31809
|
}
|
|
31610
31810
|
}
|
|
31611
31811
|
forceFetch(e, t = {}) {
|
|
@@ -32820,20 +33020,20 @@ async function runSecondaryModelWithFallback(client, directory, models, prompt,
|
|
|
32820
33020
|
}
|
|
32821
33021
|
|
|
32822
33022
|
// src/tools/smartfetch/tool.ts
|
|
32823
|
-
var
|
|
33023
|
+
var z6 = tool5.schema;
|
|
32824
33024
|
function createWebfetchTool(pluginCtx, options = {}) {
|
|
32825
33025
|
const binaryDir = options.binaryDir || path18.join(os6.tmpdir(), "opencode-smartfetch");
|
|
32826
|
-
return
|
|
33026
|
+
return tool5({
|
|
32827
33027
|
description: WEBFETCH_DESCRIPTION,
|
|
32828
33028
|
args: {
|
|
32829
|
-
url:
|
|
32830
|
-
format:
|
|
32831
|
-
timeout:
|
|
32832
|
-
prompt:
|
|
32833
|
-
extract_main:
|
|
32834
|
-
prefer_llms_txt:
|
|
32835
|
-
include_metadata:
|
|
32836
|
-
save_binary:
|
|
33029
|
+
url: z6.httpUrl(),
|
|
33030
|
+
format: z6.enum(["text", "markdown", "html"]).default("markdown"),
|
|
33031
|
+
timeout: z6.number().positive().max(MAX_TIMEOUT_SECONDS).optional().describe("Timeout in seconds, max 120."),
|
|
33032
|
+
prompt: z6.string().optional().describe("Optional extraction task to run on the fetched content using a cheap secondary model."),
|
|
33033
|
+
extract_main: z6.boolean().default(true),
|
|
33034
|
+
prefer_llms_txt: z6.enum(["auto", "always", "never"]).default("auto"),
|
|
33035
|
+
include_metadata: z6.boolean().default(true),
|
|
33036
|
+
save_binary: z6.boolean().default(false).describe("Save binary payload to disk when it fits within the active download limit.")
|
|
32837
33037
|
},
|
|
32838
33038
|
async execute(args, ctx) {
|
|
32839
33039
|
const secondaryModels = await readSecondaryModelFromConfig(ctx.directory || pluginCtx.directory);
|
|
@@ -33423,6 +33623,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33423
33623
|
let presetManager;
|
|
33424
33624
|
let divoomManager;
|
|
33425
33625
|
let councilTools;
|
|
33626
|
+
let cancelTaskTools;
|
|
33426
33627
|
let webfetch;
|
|
33427
33628
|
let rewriteDisplayNameMentions;
|
|
33428
33629
|
let toolCount = 0;
|
|
@@ -33487,7 +33688,8 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33487
33688
|
councilTools = config.council ? createCouncilTool(ctx, new CouncilManager(ctx, config, depthTracker, multiplexerEnabled)) : {};
|
|
33488
33689
|
mcps = createBuiltinMcps(config.disabled_mcps, config.websearch);
|
|
33489
33690
|
webfetch = createWebfetchTool(ctx);
|
|
33490
|
-
|
|
33691
|
+
backgroundJobBoard = new BackgroundJobBoard;
|
|
33692
|
+
multiplexerSessionManager = new MultiplexerSessionManager(ctx, multiplexerConfig, backgroundJobBoard);
|
|
33491
33693
|
autoUpdateChecker = createAutoUpdateCheckerHook(ctx, {
|
|
33492
33694
|
autoUpdate: config.autoUpdate ?? true
|
|
33493
33695
|
});
|
|
@@ -33502,7 +33704,6 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33502
33704
|
applyPatchHook = createApplyPatchHook(ctx);
|
|
33503
33705
|
jsonErrorRecoveryHook = createJsonErrorRecoveryHook(ctx);
|
|
33504
33706
|
foregroundFallback = new ForegroundFallbackManager(ctx.client, runtimeChains, config.fallback?.enabled !== false && Object.keys(runtimeChains).length > 0);
|
|
33505
|
-
backgroundJobBoard = new BackgroundJobBoard;
|
|
33506
33707
|
todoContinuationHook = createTodoContinuationHook(ctx, {
|
|
33507
33708
|
maxContinuations: config.todoContinuation?.maxContinuations ?? 5,
|
|
33508
33709
|
cooldownMs: config.todoContinuation?.cooldownMs ?? 3000,
|
|
@@ -33524,7 +33725,12 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33524
33725
|
interviewManager = createInterviewManager(ctx, config);
|
|
33525
33726
|
presetManager = createPresetManager(ctx, config);
|
|
33526
33727
|
divoomManager = createDivoomManager(config.divoom);
|
|
33527
|
-
|
|
33728
|
+
cancelTaskTools = createCancelTaskTool({
|
|
33729
|
+
client: ctx.client,
|
|
33730
|
+
backgroundJobBoard,
|
|
33731
|
+
shouldManageSession: (sessionID) => sessionAgentMap.get(sessionID) === "orchestrator"
|
|
33732
|
+
});
|
|
33733
|
+
toolCount = Object.keys(councilTools).length + Object.keys(cancelTaskTools).length + Object.keys(todoContinuationHook.tool).length + 1 + 2;
|
|
33528
33734
|
} catch (err) {
|
|
33529
33735
|
log("[plugin] FATAL: init failed", String(err));
|
|
33530
33736
|
await appLog(ctx, "error", `INIT FAILED: ${String(err)}. Report at github.com/alvinunreal/oh-my-opencode-slim/issues/310`);
|
|
@@ -33566,6 +33772,7 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
33566
33772
|
agent: agents,
|
|
33567
33773
|
tool: {
|
|
33568
33774
|
...councilTools,
|
|
33775
|
+
...cancelTaskTools,
|
|
33569
33776
|
webfetch,
|
|
33570
33777
|
...todoContinuationHook.tool,
|
|
33571
33778
|
ast_grep_search,
|