oh-my-opencode 3.0.0-beta.3 → 3.0.0-beta.4

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/dist/index.js CHANGED
@@ -818,7 +818,7 @@ var require_scan = __commonJS((exports, module) => {
818
818
 
819
819
  // node_modules/picomatch/lib/parse.js
820
820
  var require_parse = __commonJS((exports, module) => {
821
- var constants2 = require_constants();
821
+ var constants = require_constants();
822
822
  var utils = require_utils();
823
823
  var {
824
824
  MAX_LENGTH,
@@ -826,7 +826,7 @@ var require_parse = __commonJS((exports, module) => {
826
826
  REGEX_NON_SPECIAL_CHARS,
827
827
  REGEX_SPECIAL_CHARS_BACKREF,
828
828
  REPLACEMENTS
829
- } = constants2;
829
+ } = constants;
830
830
  var expandRange = (args, options) => {
831
831
  if (typeof options.expandRange === "function") {
832
832
  return options.expandRange(...args, options);
@@ -857,8 +857,8 @@ var require_parse = __commonJS((exports, module) => {
857
857
  const bos = { type: "bos", value: "", output: opts.prepend || "" };
858
858
  const tokens = [bos];
859
859
  const capture = opts.capture ? "" : "?:";
860
- const PLATFORM_CHARS = constants2.globChars(opts.windows);
861
- const EXTGLOB_CHARS = constants2.extglobChars(PLATFORM_CHARS);
860
+ const PLATFORM_CHARS = constants.globChars(opts.windows);
861
+ const EXTGLOB_CHARS = constants.extglobChars(PLATFORM_CHARS);
862
862
  const {
863
863
  DOT_LITERAL,
864
864
  PLUS_LITERAL,
@@ -1536,7 +1536,7 @@ var require_parse = __commonJS((exports, module) => {
1536
1536
  NO_DOTS_SLASH,
1537
1537
  STAR,
1538
1538
  START_ANCHOR
1539
- } = constants2.globChars(opts.windows);
1539
+ } = constants.globChars(opts.windows);
1540
1540
  const nodot = opts.dot ? NO_DOTS : NO_DOT;
1541
1541
  const slashDot = opts.dot ? NO_DOTS_SLASH : NO_DOT;
1542
1542
  const capture = opts.capture ? "" : "?:";
@@ -1594,7 +1594,7 @@ var require_picomatch = __commonJS((exports, module) => {
1594
1594
  var scan = require_scan();
1595
1595
  var parse3 = require_parse();
1596
1596
  var utils = require_utils();
1597
- var constants2 = require_constants();
1597
+ var constants = require_constants();
1598
1598
  var isObject2 = (val) => val && typeof val === "object" && !Array.isArray(val);
1599
1599
  var picomatch = (glob, options, returnState = false) => {
1600
1600
  if (Array.isArray(glob)) {
@@ -1725,7 +1725,7 @@ var require_picomatch = __commonJS((exports, module) => {
1725
1725
  return /$^/;
1726
1726
  }
1727
1727
  };
1728
- picomatch.constants = constants2;
1728
+ picomatch.constants = constants;
1729
1729
  module.exports = picomatch;
1730
1730
  });
1731
1731
 
@@ -4757,7 +4757,7 @@ var require_compile = __commonJS((exports) => {
4757
4757
  const schOrFunc = root.refs[ref];
4758
4758
  if (schOrFunc)
4759
4759
  return schOrFunc;
4760
- let _sch = resolve8.call(this, root, ref);
4760
+ let _sch = resolve10.call(this, root, ref);
4761
4761
  if (_sch === undefined) {
4762
4762
  const schema2 = (_a = root.localRefs) === null || _a === undefined ? undefined : _a[ref];
4763
4763
  const { schemaId } = this.opts;
@@ -4784,7 +4784,7 @@ var require_compile = __commonJS((exports) => {
4784
4784
  function sameSchemaEnv(s1, s2) {
4785
4785
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
4786
4786
  }
4787
- function resolve8(root, ref) {
4787
+ function resolve10(root, ref) {
4788
4788
  let sch;
4789
4789
  while (typeof (sch = this.refs[ref]) == "string")
4790
4790
  ref = sch;
@@ -5314,55 +5314,55 @@ var require_fast_uri = __commonJS((exports, module) => {
5314
5314
  }
5315
5315
  return uri;
5316
5316
  }
5317
- function resolve8(baseURI, relativeURI, options) {
5317
+ function resolve10(baseURI, relativeURI, options) {
5318
5318
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
5319
5319
  const resolved = resolveComponent(parse7(baseURI, schemelessOptions), parse7(relativeURI, schemelessOptions), schemelessOptions, true);
5320
5320
  schemelessOptions.skipEscape = true;
5321
5321
  return serialize(resolved, schemelessOptions);
5322
5322
  }
5323
- function resolveComponent(base, relative4, options, skipNormalization) {
5323
+ function resolveComponent(base, relative5, options, skipNormalization) {
5324
5324
  const target = {};
5325
5325
  if (!skipNormalization) {
5326
5326
  base = parse7(serialize(base, options), options);
5327
- relative4 = parse7(serialize(relative4, options), options);
5327
+ relative5 = parse7(serialize(relative5, options), options);
5328
5328
  }
5329
5329
  options = options || {};
5330
- if (!options.tolerant && relative4.scheme) {
5331
- target.scheme = relative4.scheme;
5332
- target.userinfo = relative4.userinfo;
5333
- target.host = relative4.host;
5334
- target.port = relative4.port;
5335
- target.path = removeDotSegments(relative4.path || "");
5336
- target.query = relative4.query;
5330
+ if (!options.tolerant && relative5.scheme) {
5331
+ target.scheme = relative5.scheme;
5332
+ target.userinfo = relative5.userinfo;
5333
+ target.host = relative5.host;
5334
+ target.port = relative5.port;
5335
+ target.path = removeDotSegments(relative5.path || "");
5336
+ target.query = relative5.query;
5337
5337
  } else {
5338
- if (relative4.userinfo !== undefined || relative4.host !== undefined || relative4.port !== undefined) {
5339
- target.userinfo = relative4.userinfo;
5340
- target.host = relative4.host;
5341
- target.port = relative4.port;
5342
- target.path = removeDotSegments(relative4.path || "");
5343
- target.query = relative4.query;
5338
+ if (relative5.userinfo !== undefined || relative5.host !== undefined || relative5.port !== undefined) {
5339
+ target.userinfo = relative5.userinfo;
5340
+ target.host = relative5.host;
5341
+ target.port = relative5.port;
5342
+ target.path = removeDotSegments(relative5.path || "");
5343
+ target.query = relative5.query;
5344
5344
  } else {
5345
- if (!relative4.path) {
5345
+ if (!relative5.path) {
5346
5346
  target.path = base.path;
5347
- if (relative4.query !== undefined) {
5348
- target.query = relative4.query;
5347
+ if (relative5.query !== undefined) {
5348
+ target.query = relative5.query;
5349
5349
  } else {
5350
5350
  target.query = base.query;
5351
5351
  }
5352
5352
  } else {
5353
- if (relative4.path[0] === "/") {
5354
- target.path = removeDotSegments(relative4.path);
5353
+ if (relative5.path[0] === "/") {
5354
+ target.path = removeDotSegments(relative5.path);
5355
5355
  } else {
5356
5356
  if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
5357
- target.path = "/" + relative4.path;
5357
+ target.path = "/" + relative5.path;
5358
5358
  } else if (!base.path) {
5359
- target.path = relative4.path;
5359
+ target.path = relative5.path;
5360
5360
  } else {
5361
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
5361
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative5.path;
5362
5362
  }
5363
5363
  target.path = removeDotSegments(target.path);
5364
5364
  }
5365
- target.query = relative4.query;
5365
+ target.query = relative5.query;
5366
5366
  }
5367
5367
  target.userinfo = base.userinfo;
5368
5368
  target.host = base.host;
@@ -5370,7 +5370,7 @@ var require_fast_uri = __commonJS((exports, module) => {
5370
5370
  }
5371
5371
  target.scheme = base.scheme;
5372
5372
  }
5373
- target.fragment = relative4.fragment;
5373
+ target.fragment = relative5.fragment;
5374
5374
  return target;
5375
5375
  }
5376
5376
  function equal(uriA, uriB, options) {
@@ -5542,7 +5542,7 @@ var require_fast_uri = __commonJS((exports, module) => {
5542
5542
  var fastUri = {
5543
5543
  SCHEMES,
5544
5544
  normalize,
5545
- resolve: resolve8,
5545
+ resolve: resolve10,
5546
5546
  resolveComponent,
5547
5547
  equal,
5548
5548
  serialize,
@@ -8423,12 +8423,12 @@ var require_isexe = __commonJS((exports, module) => {
8423
8423
  if (typeof Promise !== "function") {
8424
8424
  throw new TypeError("callback not provided");
8425
8425
  }
8426
- return new Promise(function(resolve8, reject) {
8426
+ return new Promise(function(resolve10, reject) {
8427
8427
  isexe(path9, options || {}, function(er, is) {
8428
8428
  if (er) {
8429
8429
  reject(er);
8430
8430
  } else {
8431
- resolve8(is);
8431
+ resolve10(is);
8432
8432
  }
8433
8433
  });
8434
8434
  });
@@ -8490,27 +8490,27 @@ var require_which = __commonJS((exports, module) => {
8490
8490
  opt = {};
8491
8491
  const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
8492
8492
  const found = [];
8493
- const step = (i2) => new Promise((resolve8, reject) => {
8493
+ const step = (i2) => new Promise((resolve10, reject) => {
8494
8494
  if (i2 === pathEnv.length)
8495
- return opt.all && found.length ? resolve8(found) : reject(getNotFoundError(cmd));
8495
+ return opt.all && found.length ? resolve10(found) : reject(getNotFoundError(cmd));
8496
8496
  const ppRaw = pathEnv[i2];
8497
8497
  const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
8498
8498
  const pCmd = path9.join(pathPart, cmd);
8499
8499
  const p2 = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
8500
- resolve8(subStep(p2, i2, 0));
8500
+ resolve10(subStep(p2, i2, 0));
8501
8501
  });
8502
- const subStep = (p2, i2, ii) => new Promise((resolve8, reject) => {
8502
+ const subStep = (p2, i2, ii) => new Promise((resolve10, reject) => {
8503
8503
  if (ii === pathExt.length)
8504
- return resolve8(step(i2 + 1));
8504
+ return resolve10(step(i2 + 1));
8505
8505
  const ext = pathExt[ii];
8506
8506
  isexe(p2 + ext, { pathExt: pathExtExe }, (er, is) => {
8507
8507
  if (!er && is) {
8508
8508
  if (opt.all)
8509
8509
  found.push(p2 + ext);
8510
8510
  else
8511
- return resolve8(p2 + ext);
8511
+ return resolve10(p2 + ext);
8512
8512
  }
8513
- return resolve8(subStep(p2, i2, ii + 1));
8513
+ return resolve10(subStep(p2, i2, ii + 1));
8514
8514
  });
8515
8515
  });
8516
8516
  return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
@@ -17053,7 +17053,7 @@ function migrateConfigFile(configPath, rawConfig) {
17053
17053
  // src/shared/opencode-config-dir.ts
17054
17054
  import { existsSync as existsSync21 } from "fs";
17055
17055
  import { homedir as homedir6 } from "os";
17056
- import { join as join26 } from "path";
17056
+ import { join as join26, resolve as resolve4 } from "path";
17057
17057
  var TAURI_APP_IDENTIFIER = "ai.opencode.desktop";
17058
17058
  var TAURI_APP_IDENTIFIER_DEV = "ai.opencode.desktop.dev";
17059
17059
  function isDevBuild(version) {
@@ -17078,6 +17078,10 @@ function getTauriConfigDir(identifier) {
17078
17078
  }
17079
17079
  }
17080
17080
  function getCliConfigDir() {
17081
+ const envConfigDir = process.env.OPENCODE_CONFIG_DIR?.trim();
17082
+ if (envConfigDir) {
17083
+ return resolve4(envConfigDir);
17084
+ }
17081
17085
  if (process.platform === "win32") {
17082
17086
  const crossPlatformDir = join26(homedir6(), ".config", "opencode");
17083
17087
  const crossPlatformConfig = join26(crossPlatformDir, "opencode.json");
@@ -18110,278 +18114,6 @@ setInterval(() => {
18110
18114
  }
18111
18115
  }, CACHE_TTL);
18112
18116
 
18113
- // src/hooks/keyword-detector/constants.ts
18114
- var CODE_BLOCK_PATTERN2 = /```[\s\S]*?```/g;
18115
- var INLINE_CODE_PATTERN2 = /`[^`]+`/g;
18116
- var ULTRAWORK_PLANNER_SECTION = `## CRITICAL: YOU ARE A PLANNER, NOT AN IMPLEMENTER
18117
-
18118
- **IDENTITY CONSTRAINT (NON-NEGOTIABLE):**
18119
- You ARE the planner. You ARE NOT an implementer. You DO NOT write code. You DO NOT execute tasks.
18120
-
18121
- **TOOL RESTRICTIONS (SYSTEM-ENFORCED):**
18122
- | Tool | Allowed | Blocked |
18123
- |------|---------|---------|
18124
- | Write/Edit | \`.sisyphus/**/*.md\` ONLY | Everything else |
18125
- | Read | All files | - |
18126
- | Bash | Research commands only | Implementation commands |
18127
- | sisyphus_task | explore, librarian | - |
18128
-
18129
- **IF YOU TRY TO WRITE/EDIT OUTSIDE \`.sisyphus/\`:**
18130
- - System will BLOCK your action
18131
- - You will receive an error
18132
- - DO NOT retry - you are not supposed to implement
18133
-
18134
- **YOUR ONLY WRITABLE PATHS:**
18135
- - \`.sisyphus/plans/*.md\` - Final work plans
18136
- - \`.sisyphus/drafts/*.md\` - Working drafts during interview
18137
-
18138
- **WHEN USER ASKS YOU TO IMPLEMENT:**
18139
- REFUSE. Say: "I'm a planner. I create work plans, not implementations. Run \`/start-work\` after I finish planning."
18140
-
18141
- ---
18142
-
18143
- ## CONTEXT GATHERING (MANDATORY BEFORE PLANNING)
18144
-
18145
- You ARE the planner. Your job: create bulletproof work plans.
18146
- **Before drafting ANY plan, gather context via explore/librarian agents.**
18147
-
18148
- ### Research Protocol
18149
- 1. **Fire parallel background agents** for comprehensive context:
18150
- \`\`\`
18151
- sisyphus_task(agent="explore", prompt="Find existing patterns for [topic] in codebase", background=true)
18152
- sisyphus_task(agent="explore", prompt="Find test infrastructure and conventions", background=true)
18153
- sisyphus_task(agent="librarian", prompt="Find official docs and best practices for [technology]", background=true)
18154
- \`\`\`
18155
- 2. **Wait for results** before planning - rushed plans fail
18156
- 3. **Synthesize findings** into informed requirements
18157
-
18158
- ### What to Research
18159
- - Existing codebase patterns and conventions
18160
- - Test infrastructure (TDD possible?)
18161
- - External library APIs and constraints
18162
- - Similar implementations in OSS (via librarian)
18163
-
18164
- **NEVER plan blind. Context first, plan second.**`;
18165
- function isPlannerAgent(agentName) {
18166
- if (!agentName)
18167
- return false;
18168
- const lowerName = agentName.toLowerCase();
18169
- return lowerName.includes("prometheus") || lowerName.includes("planner") || lowerName === "plan";
18170
- }
18171
- function getUltraworkMessage(agentName) {
18172
- const isPlanner = isPlannerAgent(agentName);
18173
- if (isPlanner) {
18174
- return `<ultrawork-mode>
18175
-
18176
- **MANDATORY**: You MUST say "ULTRAWORK MODE ENABLED!" to the user as your first response when this mode activates. This is non-negotiable.
18177
-
18178
- ${ULTRAWORK_PLANNER_SECTION}
18179
-
18180
- </ultrawork-mode>
18181
-
18182
- ---
18183
-
18184
- `;
18185
- }
18186
- return `<ultrawork-mode>
18187
-
18188
- **MANDATORY**: You MUST say "ULTRAWORK MODE ENABLED!" to the user as your first response when this mode activates. This is non-negotiable.
18189
-
18190
- [CODE RED] Maximum precision required. Ultrathink before acting.
18191
-
18192
- YOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL.
18193
- TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.
18194
-
18195
- ## AGENT UTILIZATION PRINCIPLES (by capability, not by name)
18196
- - **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS for file patterns, internal implementations, project structure
18197
- - **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS for API references, examples, external library docs
18198
- - **Planning & Strategy**: NEVER plan yourself - ALWAYS spawn a dedicated planning agent for work breakdown
18199
- - **High-IQ Reasoning**: Leverage specialized agents for architecture decisions, code review, strategic planning
18200
- - **Frontend/UI Tasks**: Delegate to UI-specialized agents for design and implementation
18201
-
18202
- ## EXECUTION RULES
18203
- - **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each.
18204
- - **PARALLEL**: Fire independent agent calls simultaneously via sisyphus_task(background=true) - NEVER wait sequentially.
18205
- - **BACKGROUND FIRST**: Use sisyphus_task for exploration/research agents (10+ concurrent if needed).
18206
- - **VERIFY**: Re-read request after completion. Check ALL requirements met before reporting done.
18207
- - **DELEGATE**: Don't do everything yourself - orchestrate specialized agents for their strengths.
18208
-
18209
- ## WORKFLOW
18210
- 1. Analyze the request and identify required capabilities
18211
- 2. Spawn exploration/librarian agents via sisyphus_task(background=true) in PARALLEL (10+ if needed)
18212
- 3. Always Use Plan agent with gathered context to create detailed work breakdown
18213
- 4. Execute with continuous verification against original requirements
18214
-
18215
- ## VERIFICATION GUARANTEE (NON-NEGOTIABLE)
18216
-
18217
- **NOTHING is "done" without PROOF it works.**
18218
-
18219
- ### Pre-Implementation: Define Success Criteria
18220
-
18221
- BEFORE writing ANY code, you MUST define:
18222
-
18223
- | Criteria Type | Description | Example |
18224
- |---------------|-------------|---------|
18225
- | **Functional** | What specific behavior must work | "Button click triggers API call" |
18226
- | **Observable** | What can be measured/seen | "Console shows 'success', no errors" |
18227
- | **Pass/Fail** | Binary, no ambiguity | "Returns 200 OK" not "should work" |
18228
-
18229
- Write these criteria explicitly. Share with user if scope is non-trivial.
18230
-
18231
- ### Test Plan Template (MANDATORY for non-trivial tasks)
18232
-
18233
- \`\`\`
18234
- ## Test Plan
18235
- ### Objective: [What we're verifying]
18236
- ### Prerequisites: [Setup needed]
18237
- ### Test Cases:
18238
- 1. [Test Name]: [Input] \u2192 [Expected Output] \u2192 [How to verify]
18239
- 2. ...
18240
- ### Success Criteria: ALL test cases pass
18241
- ### How to Execute: [Exact commands/steps]
18242
- \`\`\`
18243
-
18244
- ### Execution & Evidence Requirements
18245
-
18246
- | Phase | Action | Required Evidence |
18247
- |-------|--------|-------------------|
18248
- | **Build** | Run build command | Exit code 0, no errors |
18249
- | **Test** | Execute test suite | All tests pass (screenshot/output) |
18250
- | **Manual Verify** | Test the actual feature | Demonstrate it works (describe what you observed) |
18251
- | **Regression** | Ensure nothing broke | Existing tests still pass |
18252
-
18253
- **WITHOUT evidence = NOT verified = NOT done.**
18254
-
18255
- ### TDD Workflow (when test infrastructure exists)
18256
-
18257
- 1. **SPEC**: Define what "working" means (success criteria above)
18258
- 2. **RED**: Write failing test \u2192 Run it \u2192 Confirm it FAILS
18259
- 3. **GREEN**: Write minimal code \u2192 Run test \u2192 Confirm it PASSES
18260
- 4. **REFACTOR**: Clean up \u2192 Tests MUST stay green
18261
- 5. **VERIFY**: Run full test suite, confirm no regressions
18262
- 6. **EVIDENCE**: Report what you ran and what output you saw
18263
-
18264
- ### Verification Anti-Patterns (BLOCKING)
18265
-
18266
- | Violation | Why It Fails |
18267
- |-----------|--------------|
18268
- | "It should work now" | No evidence. Run it. |
18269
- | "I added the tests" | Did they pass? Show output. |
18270
- | "Fixed the bug" | How do you know? What did you test? |
18271
- | "Implementation complete" | Did you verify against success criteria? |
18272
- | Skipping test execution | Tests exist to be RUN, not just written |
18273
-
18274
- **CLAIM NOTHING WITHOUT PROOF. EXECUTE. VERIFY. SHOW EVIDENCE.**
18275
-
18276
- ## ZERO TOLERANCE FAILURES
18277
- - **NO Scope Reduction**: Never make "demo", "skeleton", "simplified", "basic" versions - deliver FULL implementation
18278
- - **NO MockUp Work**: When user asked you to do "port A", you must "port A", fully, 100%. No Extra feature, No reduced feature, no mock data, fully working 100% port.
18279
- - **NO Partial Completion**: Never stop at 60-80% saying "you can extend this..." - finish 100%
18280
- - **NO Assumed Shortcuts**: Never skip requirements you deem "optional" or "can be added later"
18281
- - **NO Premature Stopping**: Never declare done until ALL TODOs are completed and verified
18282
- - **NO TEST DELETION**: Never delete or skip failing tests to make the build pass. Fix the code, not the tests.
18283
-
18284
- THE USER ASKED FOR X. DELIVER EXACTLY X. NOT A SUBSET. NOT A DEMO. NOT A STARTING POINT.
18285
-
18286
- </ultrawork-mode>
18287
-
18288
- ---
18289
-
18290
- `;
18291
- }
18292
- var KEYWORD_DETECTORS = [
18293
- {
18294
- pattern: /(ultrawork|ulw)/i,
18295
- message: getUltraworkMessage
18296
- },
18297
- {
18298
- pattern: /\b(search|find|locate|lookup|look\s*up|explore|discover|scan|grep|query|browse|detect|trace|seek|track|pinpoint|hunt)\b|where\s+is|show\s+me|list\s+all|\uAC80\uC0C9|\uCC3E\uC544|\uD0D0\uC0C9|\uC870\uD68C|\uC2A4\uCE94|\uC11C\uCE58|\uB4A4\uC838|\uCC3E\uAE30|\uC5B4\uB514|\uCD94\uC801|\uD0D0\uC9C0|\uCC3E\uC544\uBD10|\uCC3E\uC544\uB0B4|\uBCF4\uC5EC\uC918|\uBAA9\uB85D|\u691C\u7D22|\u63A2\u3057\u3066|\u898B\u3064\u3051\u3066|\u30B5\u30FC\u30C1|\u63A2\u7D22|\u30B9\u30AD\u30E3\u30F3|\u3069\u3053|\u767A\u898B|\u635C\u7D22|\u898B\u3064\u3051\u51FA\u3059|\u4E00\u89A7|\u641C\u7D22|\u67E5\u627E|\u5BFB\u627E|\u67E5\u8BE2|\u68C0\u7D22|\u5B9A\u4F4D|\u626B\u63CF|\u53D1\u73B0|\u5728\u54EA\u91CC|\u627E\u51FA\u6765|\u5217\u51FA|t\u00ECm ki\u1EBFm|tra c\u1EE9u|\u0111\u1ECBnh v\u1ECB|qu\u00E9t|ph\u00E1t hi\u1EC7n|truy t\u00ECm|t\u00ECm ra|\u1EDF \u0111\u00E2u|li\u1EC7t k\u00EA/i,
18299
- message: `[search-mode]
18300
- MAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:
18301
- - explore agents (codebase patterns, file structures, ast-grep)
18302
- - librarian agents (remote repos, official docs, GitHub examples)
18303
- Plus direct tools: Grep, ripgrep (rg), ast-grep (sg)
18304
- NEVER stop at first result - be exhaustive.`
18305
- },
18306
- {
18307
- pattern: /\b(analyze|analyse|investigate|examine|research|study|deep[\s-]?dive|inspect|audit|evaluate|assess|review|diagnose|scrutinize|dissect|debug|comprehend|interpret|breakdown|understand)\b|why\s+is|how\s+does|how\s+to|\uBD84\uC11D|\uC870\uC0AC|\uD30C\uC545|\uC5F0\uAD6C|\uAC80\uD1A0|\uC9C4\uB2E8|\uC774\uD574|\uC124\uBA85|\uC6D0\uC778|\uC774\uC720|\uB72F\uC5B4\uBD10|\uB530\uC838\uBD10|\uD3C9\uAC00|\uD574\uC11D|\uB514\uBC84\uAE45|\uB514\uBC84\uADF8|\uC5B4\uB5BB\uAC8C|\uC65C|\uC0B4\uD3B4|\u5206\u6790|\u8ABF\u67FB|\u89E3\u6790|\u691C\u8A0E|\u7814\u7A76|\u8A3A\u65AD|\u7406\u89E3|\u8AAC\u660E|\u691C\u8A3C|\u7CBE\u67FB|\u7A76\u660E|\u30C7\u30D0\u30C3\u30B0|\u306A\u305C|\u3069\u3046|\u4ED5\u7D44\u307F|\u8C03\u67E5|\u68C0\u67E5|\u5256\u6790|\u6DF1\u5165|\u8BCA\u65AD|\u89E3\u91CA|\u8C03\u8BD5|\u4E3A\u4EC0\u4E48|\u539F\u7406|\u641E\u6E05\u695A|\u5F04\u660E\u767D|ph\u00E2n t\u00EDch|\u0111i\u1EC1u tra|nghi\u00EAn c\u1EE9u|ki\u1EC3m tra|xem x\u00E9t|ch\u1EA9n \u0111o\u00E1n|gi\u1EA3i th\u00EDch|t\u00ECm hi\u1EC3u|g\u1EE1 l\u1ED7i|t\u1EA1i sao/i,
18308
- message: `[analyze-mode]
18309
- ANALYSIS MODE. Gather context before diving deep:
18310
-
18311
- CONTEXT GATHERING (parallel):
18312
- - 1-2 explore agents (codebase patterns, implementations)
18313
- - 1-2 librarian agents (if external library involved)
18314
- - Direct tools: Grep, AST-grep, LSP for targeted searches
18315
-
18316
- IF COMPLEX (architecture, multi-system, debugging after 2+ failures):
18317
- - Consult oracle for strategic guidance
18318
-
18319
- SYNTHESIZE findings before proceeding.`
18320
- }
18321
- ];
18322
-
18323
- // src/hooks/keyword-detector/detector.ts
18324
- function removeCodeBlocks2(text) {
18325
- return text.replace(CODE_BLOCK_PATTERN2, "").replace(INLINE_CODE_PATTERN2, "");
18326
- }
18327
- function resolveMessage(message, agentName) {
18328
- return typeof message === "function" ? message(agentName) : message;
18329
- }
18330
- function detectKeywordsWithType(text, agentName) {
18331
- const textWithoutCode = removeCodeBlocks2(text);
18332
- const types3 = ["ultrawork", "search", "analyze"];
18333
- return KEYWORD_DETECTORS.map(({ pattern, message }, index) => ({
18334
- matches: pattern.test(textWithoutCode),
18335
- type: types3[index],
18336
- message: resolveMessage(message, agentName)
18337
- })).filter((result) => result.matches).map(({ type: type2, message }) => ({ type: type2, message }));
18338
- }
18339
- function extractPromptText2(parts) {
18340
- return parts.filter((p) => p.type === "text").map((p) => p.text || "").join(" ");
18341
- }
18342
-
18343
- // src/hooks/keyword-detector/index.ts
18344
- function createKeywordDetectorHook(ctx) {
18345
- return {
18346
- "chat.message": async (input, output) => {
18347
- const promptText = extractPromptText2(output.parts);
18348
- let detectedKeywords = detectKeywordsWithType(removeCodeBlocks2(promptText), input.agent);
18349
- if (detectedKeywords.length === 0) {
18350
- return;
18351
- }
18352
- const mainSessionID2 = getMainSessionID();
18353
- const isNonMainSession = mainSessionID2 && input.sessionID !== mainSessionID2;
18354
- if (isNonMainSession) {
18355
- detectedKeywords = detectedKeywords.filter((k) => k.type === "ultrawork");
18356
- if (detectedKeywords.length === 0) {
18357
- log(`[keyword-detector] Skipping non-ultrawork keywords in non-main session`, {
18358
- sessionID: input.sessionID,
18359
- mainSessionID: mainSessionID2
18360
- });
18361
- return;
18362
- }
18363
- }
18364
- const hasUltrawork = detectedKeywords.some((k) => k.type === "ultrawork");
18365
- if (hasUltrawork) {
18366
- log(`[keyword-detector] Ultrawork mode activated`, { sessionID: input.sessionID });
18367
- output.message.variant = "max";
18368
- ctx.client.tui.showToast({
18369
- body: {
18370
- title: "Ultrawork Mode Activated",
18371
- message: "Maximum precision engaged. All agents at your disposal.",
18372
- variant: "success",
18373
- duration: 3000
18374
- }
18375
- }).catch((err) => log(`[keyword-detector] Failed to show toast`, { error: err, sessionID: input.sessionID }));
18376
- }
18377
- log(`[keyword-detector] Detected ${detectedKeywords.length} keywords`, {
18378
- sessionID: input.sessionID,
18379
- types: detectedKeywords.map((k) => k.type)
18380
- });
18381
- }
18382
- };
18383
- }
18384
-
18385
18117
  // src/hooks/claude-code-hooks/index.ts
18386
18118
  var sessionFirstMessageProcessed = new Set;
18387
18119
  var sessionErrorState = new Map;
@@ -18456,24 +18188,11 @@ function createClaudeCodeHooksHook(ctx, config = {}, contextCollector) {
18456
18188
  log("chat.message injection skipped - interrupted during hooks", { sessionID: input.sessionID });
18457
18189
  return;
18458
18190
  }
18459
- const keywordMessages = [];
18460
- if (!config.keywordDetectorDisabled) {
18461
- const detectedKeywords = detectKeywordsWithType(removeCodeBlocks2(prompt), input.agent);
18462
- keywordMessages.push(...detectedKeywords.map((k) => k.message));
18463
- if (keywordMessages.length > 0) {
18464
- log("[claude-code-hooks] Detected keywords", {
18465
- sessionID: input.sessionID,
18466
- keywordCount: keywordMessages.length,
18467
- types: detectedKeywords.map((k) => k.type)
18468
- });
18469
- }
18470
- }
18471
- const allMessages = [...keywordMessages, ...result.messages];
18472
- if (allMessages.length > 0) {
18473
- const hookContent = allMessages.join(`
18191
+ if (result.messages.length > 0) {
18192
+ const hookContent = result.messages.join(`
18474
18193
 
18475
18194
  `);
18476
- log(`[claude-code-hooks] Injecting ${allMessages.length} messages (${keywordMessages.length} keyword + ${result.messages.length} hook)`, { sessionID: input.sessionID, contentLength: hookContent.length, isFirstMessage });
18195
+ log(`[claude-code-hooks] Injecting ${result.messages.length} hook messages`, { sessionID: input.sessionID, contentLength: hookContent.length, isFirstMessage });
18477
18196
  if (isFirstMessage) {
18478
18197
  const idx = output.parts.findIndex((p) => p.type === "text" && p.text);
18479
18198
  if (idx >= 0) {
@@ -18683,7 +18402,7 @@ ${result.message}`;
18683
18402
  // src/hooks/rules-injector/index.ts
18684
18403
  import { readFileSync as readFileSync16 } from "fs";
18685
18404
  import { homedir as homedir9 } from "os";
18686
- import { relative as relative3, resolve as resolve4 } from "path";
18405
+ import { relative as relative3, resolve as resolve5 } from "path";
18687
18406
 
18688
18407
  // src/hooks/rules-injector/finder.ts
18689
18408
  import {
@@ -19078,7 +18797,7 @@ function createRulesInjectorHook(ctx) {
19078
18797
  return null;
19079
18798
  if (path5.startsWith("/"))
19080
18799
  return path5;
19081
- return resolve4(ctx.directory, path5);
18800
+ return resolve5(ctx.directory, path5);
19082
18801
  }
19083
18802
  async function processFilePathForInjection(filePath, sessionID, output) {
19084
18803
  const resolved = resolveFilePath2(filePath);
@@ -19535,7 +19254,7 @@ async function runBunInstallWithDetails() {
19535
19254
  stdout: "pipe",
19536
19255
  stderr: "pipe"
19537
19256
  });
19538
- const timeoutPromise = new Promise((resolve5) => setTimeout(() => resolve5("timeout"), BUN_INSTALL_TIMEOUT_MS));
19257
+ const timeoutPromise = new Promise((resolve6) => setTimeout(() => resolve6("timeout"), BUN_INSTALL_TIMEOUT_MS));
19539
19258
  const exitPromise = proc.exited.then(() => "completed");
19540
19259
  const result = await Promise.race([exitPromise, timeoutPromise]);
19541
19260
  if (result === "timeout") {
@@ -19722,7 +19441,7 @@ async function showSpinnerToast(ctx, version, message) {
19722
19441
  duration: frameInterval + 50
19723
19442
  }
19724
19443
  }).catch(() => {});
19725
- await new Promise((resolve5) => setTimeout(resolve5, frameInterval));
19444
+ await new Promise((resolve6) => setTimeout(resolve6, frameInterval));
19726
19445
  }
19727
19446
  }
19728
19447
  async function showUpdateAvailableToast(ctx, latestVersion, getToastMessage) {
@@ -19905,6 +19624,287 @@ function createAgentUsageReminderHook(_ctx) {
19905
19624
  event: eventHandler
19906
19625
  };
19907
19626
  }
19627
+ // src/hooks/keyword-detector/constants.ts
19628
+ var CODE_BLOCK_PATTERN2 = /```[\s\S]*?```/g;
19629
+ var INLINE_CODE_PATTERN2 = /`[^`]+`/g;
19630
+ var ULTRAWORK_PLANNER_SECTION = `## CRITICAL: YOU ARE A PLANNER, NOT AN IMPLEMENTER
19631
+
19632
+ **IDENTITY CONSTRAINT (NON-NEGOTIABLE):**
19633
+ You ARE the planner. You ARE NOT an implementer. You DO NOT write code. You DO NOT execute tasks.
19634
+
19635
+ **TOOL RESTRICTIONS (SYSTEM-ENFORCED):**
19636
+ | Tool | Allowed | Blocked |
19637
+ |------|---------|---------|
19638
+ | Write/Edit | \`.sisyphus/**/*.md\` ONLY | Everything else |
19639
+ | Read | All files | - |
19640
+ | Bash | Research commands only | Implementation commands |
19641
+ | sisyphus_task | explore, librarian | - |
19642
+
19643
+ **IF YOU TRY TO WRITE/EDIT OUTSIDE \`.sisyphus/\`:**
19644
+ - System will BLOCK your action
19645
+ - You will receive an error
19646
+ - DO NOT retry - you are not supposed to implement
19647
+
19648
+ **YOUR ONLY WRITABLE PATHS:**
19649
+ - \`.sisyphus/plans/*.md\` - Final work plans
19650
+ - \`.sisyphus/drafts/*.md\` - Working drafts during interview
19651
+
19652
+ **WHEN USER ASKS YOU TO IMPLEMENT:**
19653
+ REFUSE. Say: "I'm a planner. I create work plans, not implementations. Run \`/start-work\` after I finish planning."
19654
+
19655
+ ---
19656
+
19657
+ ## CONTEXT GATHERING (MANDATORY BEFORE PLANNING)
19658
+
19659
+ You ARE the planner. Your job: create bulletproof work plans.
19660
+ **Before drafting ANY plan, gather context via explore/librarian agents.**
19661
+
19662
+ ### Research Protocol
19663
+ 1. **Fire parallel background agents** for comprehensive context:
19664
+ \`\`\`
19665
+ sisyphus_task(agent="explore", prompt="Find existing patterns for [topic] in codebase", background=true)
19666
+ sisyphus_task(agent="explore", prompt="Find test infrastructure and conventions", background=true)
19667
+ sisyphus_task(agent="librarian", prompt="Find official docs and best practices for [technology]", background=true)
19668
+ \`\`\`
19669
+ 2. **Wait for results** before planning - rushed plans fail
19670
+ 3. **Synthesize findings** into informed requirements
19671
+
19672
+ ### What to Research
19673
+ - Existing codebase patterns and conventions
19674
+ - Test infrastructure (TDD possible?)
19675
+ - External library APIs and constraints
19676
+ - Similar implementations in OSS (via librarian)
19677
+
19678
+ **NEVER plan blind. Context first, plan second.**`;
19679
+ function isPlannerAgent(agentName) {
19680
+ if (!agentName)
19681
+ return false;
19682
+ const lowerName = agentName.toLowerCase();
19683
+ return lowerName.includes("prometheus") || lowerName.includes("planner") || lowerName === "plan";
19684
+ }
19685
+ function getUltraworkMessage(agentName) {
19686
+ const isPlanner = isPlannerAgent(agentName);
19687
+ if (isPlanner) {
19688
+ return `<ultrawork-mode>
19689
+
19690
+ **MANDATORY**: You MUST say "ULTRAWORK MODE ENABLED!" to the user as your first response when this mode activates. This is non-negotiable.
19691
+
19692
+ ${ULTRAWORK_PLANNER_SECTION}
19693
+
19694
+ </ultrawork-mode>
19695
+
19696
+ ---
19697
+
19698
+ `;
19699
+ }
19700
+ return `<ultrawork-mode>
19701
+
19702
+ **MANDATORY**: You MUST say "ULTRAWORK MODE ENABLED!" to the user as your first response when this mode activates. This is non-negotiable.
19703
+
19704
+ [CODE RED] Maximum precision required. Ultrathink before acting.
19705
+
19706
+ YOU MUST LEVERAGE ALL AVAILABLE AGENTS TO THEIR FULLEST POTENTIAL.
19707
+ TELL THE USER WHAT AGENTS YOU WILL LEVERAGE NOW TO SATISFY USER'S REQUEST.
19708
+
19709
+ ## AGENT UTILIZATION PRINCIPLES (by capability, not by name)
19710
+ - **Codebase Exploration**: Spawn exploration agents using BACKGROUND TASKS for file patterns, internal implementations, project structure
19711
+ - **Documentation & References**: Use librarian-type agents via BACKGROUND TASKS for API references, examples, external library docs
19712
+ - **Planning & Strategy**: NEVER plan yourself - ALWAYS spawn a dedicated planning agent for work breakdown
19713
+ - **High-IQ Reasoning**: Leverage specialized agents for architecture decisions, code review, strategic planning
19714
+ - **Frontend/UI Tasks**: Delegate to UI-specialized agents for design and implementation
19715
+
19716
+ ## EXECUTION RULES
19717
+ - **TODO**: Track EVERY step. Mark complete IMMEDIATELY after each.
19718
+ - **PARALLEL**: Fire independent agent calls simultaneously via sisyphus_task(background=true) - NEVER wait sequentially.
19719
+ - **BACKGROUND FIRST**: Use sisyphus_task for exploration/research agents (10+ concurrent if needed).
19720
+ - **VERIFY**: Re-read request after completion. Check ALL requirements met before reporting done.
19721
+ - **DELEGATE**: Don't do everything yourself - orchestrate specialized agents for their strengths.
19722
+
19723
+ ## WORKFLOW
19724
+ 1. Analyze the request and identify required capabilities
19725
+ 2. Spawn exploration/librarian agents via sisyphus_task(background=true) in PARALLEL (10+ if needed)
19726
+ 3. Always Use Plan agent with gathered context to create detailed work breakdown
19727
+ 4. Execute with continuous verification against original requirements
19728
+
19729
+ ## VERIFICATION GUARANTEE (NON-NEGOTIABLE)
19730
+
19731
+ **NOTHING is "done" without PROOF it works.**
19732
+
19733
+ ### Pre-Implementation: Define Success Criteria
19734
+
19735
+ BEFORE writing ANY code, you MUST define:
19736
+
19737
+ | Criteria Type | Description | Example |
19738
+ |---------------|-------------|---------|
19739
+ | **Functional** | What specific behavior must work | "Button click triggers API call" |
19740
+ | **Observable** | What can be measured/seen | "Console shows 'success', no errors" |
19741
+ | **Pass/Fail** | Binary, no ambiguity | "Returns 200 OK" not "should work" |
19742
+
19743
+ Write these criteria explicitly. Share with user if scope is non-trivial.
19744
+
19745
+ ### Test Plan Template (MANDATORY for non-trivial tasks)
19746
+
19747
+ \`\`\`
19748
+ ## Test Plan
19749
+ ### Objective: [What we're verifying]
19750
+ ### Prerequisites: [Setup needed]
19751
+ ### Test Cases:
19752
+ 1. [Test Name]: [Input] \u2192 [Expected Output] \u2192 [How to verify]
19753
+ 2. ...
19754
+ ### Success Criteria: ALL test cases pass
19755
+ ### How to Execute: [Exact commands/steps]
19756
+ \`\`\`
19757
+
19758
+ ### Execution & Evidence Requirements
19759
+
19760
+ | Phase | Action | Required Evidence |
19761
+ |-------|--------|-------------------|
19762
+ | **Build** | Run build command | Exit code 0, no errors |
19763
+ | **Test** | Execute test suite | All tests pass (screenshot/output) |
19764
+ | **Manual Verify** | Test the actual feature | Demonstrate it works (describe what you observed) |
19765
+ | **Regression** | Ensure nothing broke | Existing tests still pass |
19766
+
19767
+ **WITHOUT evidence = NOT verified = NOT done.**
19768
+
19769
+ ### TDD Workflow (when test infrastructure exists)
19770
+
19771
+ 1. **SPEC**: Define what "working" means (success criteria above)
19772
+ 2. **RED**: Write failing test \u2192 Run it \u2192 Confirm it FAILS
19773
+ 3. **GREEN**: Write minimal code \u2192 Run test \u2192 Confirm it PASSES
19774
+ 4. **REFACTOR**: Clean up \u2192 Tests MUST stay green
19775
+ 5. **VERIFY**: Run full test suite, confirm no regressions
19776
+ 6. **EVIDENCE**: Report what you ran and what output you saw
19777
+
19778
+ ### Verification Anti-Patterns (BLOCKING)
19779
+
19780
+ | Violation | Why It Fails |
19781
+ |-----------|--------------|
19782
+ | "It should work now" | No evidence. Run it. |
19783
+ | "I added the tests" | Did they pass? Show output. |
19784
+ | "Fixed the bug" | How do you know? What did you test? |
19785
+ | "Implementation complete" | Did you verify against success criteria? |
19786
+ | Skipping test execution | Tests exist to be RUN, not just written |
19787
+
19788
+ **CLAIM NOTHING WITHOUT PROOF. EXECUTE. VERIFY. SHOW EVIDENCE.**
19789
+
19790
+ ## ZERO TOLERANCE FAILURES
19791
+ - **NO Scope Reduction**: Never make "demo", "skeleton", "simplified", "basic" versions - deliver FULL implementation
19792
+ - **NO MockUp Work**: When user asked you to do "port A", you must "port A", fully, 100%. No Extra feature, No reduced feature, no mock data, fully working 100% port.
19793
+ - **NO Partial Completion**: Never stop at 60-80% saying "you can extend this..." - finish 100%
19794
+ - **NO Assumed Shortcuts**: Never skip requirements you deem "optional" or "can be added later"
19795
+ - **NO Premature Stopping**: Never declare done until ALL TODOs are completed and verified
19796
+ - **NO TEST DELETION**: Never delete or skip failing tests to make the build pass. Fix the code, not the tests.
19797
+
19798
+ THE USER ASKED FOR X. DELIVER EXACTLY X. NOT A SUBSET. NOT A DEMO. NOT A STARTING POINT.
19799
+
19800
+ </ultrawork-mode>
19801
+
19802
+ ---
19803
+
19804
+ `;
19805
+ }
19806
+ var KEYWORD_DETECTORS = [
19807
+ {
19808
+ pattern: /(ultrawork|ulw)/i,
19809
+ message: getUltraworkMessage
19810
+ },
19811
+ {
19812
+ pattern: /\b(search|find|locate|lookup|look\s*up|explore|discover|scan|grep|query|browse|detect|trace|seek|track|pinpoint|hunt)\b|where\s+is|show\s+me|list\s+all|\uAC80\uC0C9|\uCC3E\uC544|\uD0D0\uC0C9|\uC870\uD68C|\uC2A4\uCE94|\uC11C\uCE58|\uB4A4\uC838|\uCC3E\uAE30|\uC5B4\uB514|\uCD94\uC801|\uD0D0\uC9C0|\uCC3E\uC544\uBD10|\uCC3E\uC544\uB0B4|\uBCF4\uC5EC\uC918|\uBAA9\uB85D|\u691C\u7D22|\u63A2\u3057\u3066|\u898B\u3064\u3051\u3066|\u30B5\u30FC\u30C1|\u63A2\u7D22|\u30B9\u30AD\u30E3\u30F3|\u3069\u3053|\u767A\u898B|\u635C\u7D22|\u898B\u3064\u3051\u51FA\u3059|\u4E00\u89A7|\u641C\u7D22|\u67E5\u627E|\u5BFB\u627E|\u67E5\u8BE2|\u68C0\u7D22|\u5B9A\u4F4D|\u626B\u63CF|\u53D1\u73B0|\u5728\u54EA\u91CC|\u627E\u51FA\u6765|\u5217\u51FA|t\u00ECm ki\u1EBFm|tra c\u1EE9u|\u0111\u1ECBnh v\u1ECB|qu\u00E9t|ph\u00E1t hi\u1EC7n|truy t\u00ECm|t\u00ECm ra|\u1EDF \u0111\u00E2u|li\u1EC7t k\u00EA/i,
19813
+ message: `[search-mode]
19814
+ MAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:
19815
+ - explore agents (codebase patterns, file structures, ast-grep)
19816
+ - librarian agents (remote repos, official docs, GitHub examples)
19817
+ Plus direct tools: Grep, ripgrep (rg), ast-grep (sg)
19818
+ NEVER stop at first result - be exhaustive.`
19819
+ },
19820
+ {
19821
+ pattern: /\b(analyze|analyse|investigate|examine|research|study|deep[\s-]?dive|inspect|audit|evaluate|assess|review|diagnose|scrutinize|dissect|debug|comprehend|interpret|breakdown|understand)\b|why\s+is|how\s+does|how\s+to|\uBD84\uC11D|\uC870\uC0AC|\uD30C\uC545|\uC5F0\uAD6C|\uAC80\uD1A0|\uC9C4\uB2E8|\uC774\uD574|\uC124\uBA85|\uC6D0\uC778|\uC774\uC720|\uB72F\uC5B4\uBD10|\uB530\uC838\uBD10|\uD3C9\uAC00|\uD574\uC11D|\uB514\uBC84\uAE45|\uB514\uBC84\uADF8|\uC5B4\uB5BB\uAC8C|\uC65C|\uC0B4\uD3B4|\u5206\u6790|\u8ABF\u67FB|\u89E3\u6790|\u691C\u8A0E|\u7814\u7A76|\u8A3A\u65AD|\u7406\u89E3|\u8AAC\u660E|\u691C\u8A3C|\u7CBE\u67FB|\u7A76\u660E|\u30C7\u30D0\u30C3\u30B0|\u306A\u305C|\u3069\u3046|\u4ED5\u7D44\u307F|\u8C03\u67E5|\u68C0\u67E5|\u5256\u6790|\u6DF1\u5165|\u8BCA\u65AD|\u89E3\u91CA|\u8C03\u8BD5|\u4E3A\u4EC0\u4E48|\u539F\u7406|\u641E\u6E05\u695A|\u5F04\u660E\u767D|ph\u00E2n t\u00EDch|\u0111i\u1EC1u tra|nghi\u00EAn c\u1EE9u|ki\u1EC3m tra|xem x\u00E9t|ch\u1EA9n \u0111o\u00E1n|gi\u1EA3i th\u00EDch|t\u00ECm hi\u1EC3u|g\u1EE1 l\u1ED7i|t\u1EA1i sao/i,
19822
+ message: `[analyze-mode]
19823
+ ANALYSIS MODE. Gather context before diving deep:
19824
+
19825
+ CONTEXT GATHERING (parallel):
19826
+ - 1-2 explore agents (codebase patterns, implementations)
19827
+ - 1-2 librarian agents (if external library involved)
19828
+ - Direct tools: Grep, AST-grep, LSP for targeted searches
19829
+
19830
+ IF COMPLEX (architecture, multi-system, debugging after 2+ failures):
19831
+ - Consult oracle for strategic guidance
19832
+
19833
+ SYNTHESIZE findings before proceeding.`
19834
+ }
19835
+ ];
19836
+
19837
+ // src/hooks/keyword-detector/detector.ts
19838
+ function removeCodeBlocks2(text) {
19839
+ return text.replace(CODE_BLOCK_PATTERN2, "").replace(INLINE_CODE_PATTERN2, "");
19840
+ }
19841
+ function resolveMessage(message, agentName) {
19842
+ return typeof message === "function" ? message(agentName) : message;
19843
+ }
19844
+ function detectKeywordsWithType(text, agentName) {
19845
+ const textWithoutCode = removeCodeBlocks2(text);
19846
+ const types3 = ["ultrawork", "search", "analyze"];
19847
+ return KEYWORD_DETECTORS.map(({ pattern, message }, index) => ({
19848
+ matches: pattern.test(textWithoutCode),
19849
+ type: types3[index],
19850
+ message: resolveMessage(message, agentName)
19851
+ })).filter((result) => result.matches).map(({ type: type2, message }) => ({ type: type2, message }));
19852
+ }
19853
+ function extractPromptText2(parts) {
19854
+ return parts.filter((p) => p.type === "text").map((p) => p.text || "").join(" ");
19855
+ }
19856
+
19857
+ // src/hooks/keyword-detector/index.ts
19858
+ function createKeywordDetectorHook(ctx, collector) {
19859
+ return {
19860
+ "chat.message": async (input, output) => {
19861
+ const promptText = extractPromptText2(output.parts);
19862
+ let detectedKeywords = detectKeywordsWithType(removeCodeBlocks2(promptText), input.agent);
19863
+ if (detectedKeywords.length === 0) {
19864
+ return;
19865
+ }
19866
+ const mainSessionID2 = getMainSessionID();
19867
+ const isNonMainSession = mainSessionID2 && input.sessionID !== mainSessionID2;
19868
+ if (isNonMainSession) {
19869
+ detectedKeywords = detectedKeywords.filter((k) => k.type === "ultrawork");
19870
+ if (detectedKeywords.length === 0) {
19871
+ log(`[keyword-detector] Skipping non-ultrawork keywords in non-main session`, {
19872
+ sessionID: input.sessionID,
19873
+ mainSessionID: mainSessionID2
19874
+ });
19875
+ return;
19876
+ }
19877
+ }
19878
+ const hasUltrawork = detectedKeywords.some((k) => k.type === "ultrawork");
19879
+ if (hasUltrawork) {
19880
+ log(`[keyword-detector] Ultrawork mode activated`, { sessionID: input.sessionID });
19881
+ output.message.variant = "max";
19882
+ ctx.client.tui.showToast({
19883
+ body: {
19884
+ title: "Ultrawork Mode Activated",
19885
+ message: "Maximum precision engaged. All agents at your disposal.",
19886
+ variant: "success",
19887
+ duration: 3000
19888
+ }
19889
+ }).catch((err) => log(`[keyword-detector] Failed to show toast`, { error: err, sessionID: input.sessionID }));
19890
+ }
19891
+ if (collector) {
19892
+ for (const keyword of detectedKeywords) {
19893
+ collector.register(input.sessionID, {
19894
+ id: `keyword-${keyword.type}`,
19895
+ source: "keyword-detector",
19896
+ content: keyword.message,
19897
+ priority: keyword.type === "ultrawork" ? "critical" : "high"
19898
+ });
19899
+ }
19900
+ }
19901
+ log(`[keyword-detector] Detected ${detectedKeywords.length} keywords`, {
19902
+ sessionID: input.sessionID,
19903
+ types: detectedKeywords.map((k) => k.type)
19904
+ });
19905
+ }
19906
+ };
19907
+ }
19908
19908
  // src/hooks/non-interactive-env/constants.ts
19909
19909
  var HOOK_NAME2 = "non-interactive-env";
19910
19910
  var NON_INTERACTIVE_ENV = {
@@ -21021,7 +21021,7 @@ async function discoverOpencodeProjectSkills() {
21021
21021
  }
21022
21022
  // src/features/opencode-skill-loader/merger.ts
21023
21023
  import { readFileSync as readFileSync23, existsSync as existsSync35 } from "fs";
21024
- import { dirname as dirname7, resolve as resolve5, isAbsolute as isAbsolute2 } from "path";
21024
+ import { dirname as dirname7, resolve as resolve6, isAbsolute as isAbsolute2 } from "path";
21025
21025
  import { homedir as homedir13 } from "os";
21026
21026
  var SCOPE_PRIORITY = {
21027
21027
  builtin: 1,
@@ -21058,13 +21058,13 @@ function resolveFilePath2(from, configDir) {
21058
21058
  filePath = filePath.slice(6, -1);
21059
21059
  }
21060
21060
  if (filePath.startsWith("~/")) {
21061
- return resolve5(homedir13(), filePath.slice(2));
21061
+ return resolve6(homedir13(), filePath.slice(2));
21062
21062
  }
21063
21063
  if (isAbsolute2(filePath)) {
21064
21064
  return filePath;
21065
21065
  }
21066
21066
  const baseDir = configDir || process.cwd();
21067
- return resolve5(baseDir, filePath);
21067
+ return resolve6(baseDir, filePath);
21068
21068
  }
21069
21069
  function loadSkillFromFile(filePath) {
21070
21070
  try {
@@ -22699,13 +22699,13 @@ ${EDIT_ERROR_REMINDER}`;
22699
22699
  }
22700
22700
  // src/hooks/prometheus-md-only/index.ts
22701
22701
  import { existsSync as existsSync37, readdirSync as readdirSync12 } from "fs";
22702
- import { join as join45 } from "path";
22702
+ import { join as join45, resolve as resolve7, relative as relative4, isAbsolute as isAbsolute3 } from "path";
22703
22703
 
22704
22704
  // src/hooks/prometheus-md-only/constants.ts
22705
22705
  var HOOK_NAME4 = "prometheus-md-only";
22706
22706
  var PROMETHEUS_AGENTS = ["Prometheus (Planner)"];
22707
22707
  var ALLOWED_EXTENSIONS = [".md"];
22708
- var ALLOWED_PATH_PREFIX = ".sisyphus/";
22708
+ var ALLOWED_PATH_PREFIX = ".sisyphus";
22709
22709
  var BLOCKED_TOOLS = ["Write", "Edit", "write", "edit"];
22710
22710
  var PLANNING_CONSULT_WARNING = `
22711
22711
 
@@ -22729,10 +22729,21 @@ Return your findings and recommendations. The actual implementation will be hand
22729
22729
  `;
22730
22730
 
22731
22731
  // src/hooks/prometheus-md-only/index.ts
22732
- function isAllowedFile(filePath) {
22733
- const hasAllowedExtension = ALLOWED_EXTENSIONS.some((ext) => filePath.endsWith(ext));
22734
- const isInAllowedPath = filePath.includes(ALLOWED_PATH_PREFIX);
22735
- return hasAllowedExtension && isInAllowedPath;
22732
+ function isAllowedFile(filePath, workspaceRoot) {
22733
+ const resolved = resolve7(workspaceRoot, filePath);
22734
+ const rel = relative4(workspaceRoot, resolved);
22735
+ if (rel.startsWith("..") || isAbsolute3(rel)) {
22736
+ return false;
22737
+ }
22738
+ const segments = rel.split(/[/\\]/);
22739
+ if (!segments[0] || segments[0].toLowerCase() !== ALLOWED_PATH_PREFIX.toLowerCase()) {
22740
+ return false;
22741
+ }
22742
+ const hasAllowedExtension = ALLOWED_EXTENSIONS.some((ext) => resolved.toLowerCase().endsWith(ext.toLowerCase()));
22743
+ if (!hasAllowedExtension) {
22744
+ return false;
22745
+ }
22746
+ return true;
22736
22747
  }
22737
22748
  function getMessageDir9(sessionID) {
22738
22749
  if (!existsSync37(MESSAGE_STORAGE))
@@ -22754,7 +22765,7 @@ function getAgentFromSession(sessionID) {
22754
22765
  return;
22755
22766
  return findNearestMessageWithFields(messageDir)?.agent;
22756
22767
  }
22757
- function createPrometheusMdOnlyHook(_ctx) {
22768
+ function createPrometheusMdOnlyHook(ctx) {
22758
22769
  return {
22759
22770
  "tool.execute.before": async (input, output) => {
22760
22771
  const agentName = getAgentFromSession(input.sessionID);
@@ -22781,7 +22792,7 @@ function createPrometheusMdOnlyHook(_ctx) {
22781
22792
  if (!filePath) {
22782
22793
  return;
22783
22794
  }
22784
- if (!isAllowedFile(filePath)) {
22795
+ if (!isAllowedFile(filePath, ctx.directory)) {
22785
22796
  log(`[${HOOK_NAME4}] Blocked: Prometheus can only write to .sisyphus/*.md`, {
22786
22797
  sessionID: input.sessionID,
22787
22798
  tool: toolName,
@@ -23048,7 +23059,9 @@ import { execSync as execSync2 } from "child_process";
23048
23059
  import { existsSync as existsSync39, readdirSync as readdirSync14 } from "fs";
23049
23060
  import { join as join47 } from "path";
23050
23061
  var HOOK_NAME6 = "sisyphus-orchestrator";
23051
- var ALLOWED_PATH_PREFIX2 = ".sisyphus/";
23062
+ function isSisyphusPath(filePath) {
23063
+ return /\.sisyphus[/\\]/.test(filePath);
23064
+ }
23052
23065
  var WRITE_EDIT_TOOLS = ["Write", "Edit", "write", "edit"];
23053
23066
  var DIRECT_WORK_REMINDER = `
23054
23067
 
@@ -23493,7 +23506,7 @@ function createSisyphusOrchestratorHook(ctx, options) {
23493
23506
  }
23494
23507
  if (WRITE_EDIT_TOOLS.includes(input.tool)) {
23495
23508
  const filePath = output.args.filePath ?? output.args.path ?? output.args.file;
23496
- if (filePath && !filePath.includes(ALLOWED_PATH_PREFIX2)) {
23509
+ if (filePath && !isSisyphusPath(filePath)) {
23497
23510
  if (input.callID) {
23498
23511
  pendingFilePaths.set(input.callID, filePath);
23499
23512
  }
@@ -23530,7 +23543,7 @@ function createSisyphusOrchestratorHook(ctx, options) {
23530
23543
  if (!filePath) {
23531
23544
  filePath = output.metadata?.filePath;
23532
23545
  }
23533
- if (filePath && !filePath.includes(ALLOWED_PATH_PREFIX2)) {
23546
+ if (filePath && !isSisyphusPath(filePath)) {
23534
23547
  output.output = (output.output || "") + DIRECT_WORK_REMINDER;
23535
23548
  log(`[${HOOK_NAME6}] Direct work reminder appended`, {
23536
23549
  sessionID: input.sessionID,
@@ -23659,9 +23672,37 @@ class ContextCollector {
23659
23672
  }
23660
23673
  var contextCollector = new ContextCollector;
23661
23674
  // src/features/context-injector/injector.ts
23675
+ function injectPendingContext(collector, sessionID, parts) {
23676
+ if (!collector.hasPending(sessionID)) {
23677
+ return { injected: false, contextLength: 0 };
23678
+ }
23679
+ const textPartIndex = parts.findIndex((p) => p.type === "text" && p.text !== undefined);
23680
+ if (textPartIndex === -1) {
23681
+ return { injected: false, contextLength: 0 };
23682
+ }
23683
+ const pending = collector.consume(sessionID);
23684
+ const originalText = parts[textPartIndex].text ?? "";
23685
+ parts[textPartIndex].text = `${pending.merged}
23686
+
23687
+ ---
23688
+
23689
+ ${originalText}`;
23690
+ return {
23691
+ injected: true,
23692
+ contextLength: pending.merged.length
23693
+ };
23694
+ }
23662
23695
  function createContextInjectorHook(collector) {
23663
23696
  return {
23664
- "chat.message": async (_input, _output) => {}
23697
+ "chat.message": async (input, output) => {
23698
+ const result = injectPendingContext(collector, input.sessionID, output.parts);
23699
+ if (result.injected) {
23700
+ log("[context-injector] Injected pending context via chat.message", {
23701
+ sessionID: input.sessionID,
23702
+ contextLength: result.contextLength
23703
+ });
23704
+ }
23705
+ }
23665
23706
  };
23666
23707
  }
23667
23708
  function createContextInjectorMessagesTransformHook(collector) {
@@ -23977,8 +24018,8 @@ function startCallbackServer(timeoutMs = 5 * 60 * 1000) {
23977
24018
  const actualPort = server.port;
23978
24019
  const redirectUri = `http://localhost:${actualPort}/oauth-callback`;
23979
24020
  const waitForCallback = () => {
23980
- return new Promise((resolve6, reject) => {
23981
- resolveCallback = resolve6;
24021
+ return new Promise((resolve8, reject) => {
24022
+ resolveCallback = resolve8;
23982
24023
  rejectCallback = reject;
23983
24024
  timeoutId = setTimeout(() => {
23984
24025
  cleanup();
@@ -24100,7 +24141,7 @@ async function refreshAccessToken(refreshToken, clientId = ANTIGRAVITY_CLIENT_ID
24100
24141
  }
24101
24142
  if (attempt < MAX_REFRESH_RETRIES) {
24102
24143
  const delay = calculateRetryDelay(attempt);
24103
- await new Promise((resolve6) => setTimeout(resolve6, delay));
24144
+ await new Promise((resolve8) => setTimeout(resolve8, delay));
24104
24145
  }
24105
24146
  } catch (error) {
24106
24147
  if (error instanceof AntigravityTokenRefreshError) {
@@ -24113,7 +24154,7 @@ async function refreshAccessToken(refreshToken, clientId = ANTIGRAVITY_CLIENT_ID
24113
24154
  });
24114
24155
  if (attempt < MAX_REFRESH_RETRIES) {
24115
24156
  const delay = calculateRetryDelay(attempt);
24116
- await new Promise((resolve6) => setTimeout(resolve6, delay));
24157
+ await new Promise((resolve8) => setTimeout(resolve8, delay));
24117
24158
  }
24118
24159
  }
24119
24160
  }
@@ -24179,7 +24220,7 @@ function isFreeTier(tierId) {
24179
24220
  return lower === "free" || lower === "free-tier" || lower.startsWith("free");
24180
24221
  }
24181
24222
  function wait(ms) {
24182
- return new Promise((resolve6) => setTimeout(resolve6, ms));
24223
+ return new Promise((resolve8) => setTimeout(resolve8, ms));
24183
24224
  }
24184
24225
  async function callLoadCodeAssistAPI(accessToken, projectId) {
24185
24226
  const metadata = { ...CODE_ASSIST_METADATA };
@@ -25596,7 +25637,7 @@ async function attemptFetch(options) {
25596
25637
  if (attempt < maxPermissionRetries) {
25597
25638
  const delay = calculateRetryDelay2(attempt);
25598
25639
  debugLog7(`[RETRY] GCP permission error, retry ${attempt + 1}/${maxPermissionRetries} after ${delay}ms`);
25599
- await new Promise((resolve6) => setTimeout(resolve6, delay));
25640
+ await new Promise((resolve8) => setTimeout(resolve8, delay));
25600
25641
  continue;
25601
25642
  }
25602
25643
  debugLog7(`[RETRY] GCP permission error, max retries exceeded`);
@@ -26978,19 +27019,19 @@ var baseOpen = async (options) => {
26978
27019
  }
26979
27020
  const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
26980
27021
  if (options.wait) {
26981
- return new Promise((resolve6, reject) => {
27022
+ return new Promise((resolve8, reject) => {
26982
27023
  subprocess.once("error", reject);
26983
27024
  subprocess.once("close", (exitCode) => {
26984
27025
  if (!options.allowNonzeroExitCode && exitCode !== 0) {
26985
27026
  reject(new Error(`Exited with code ${exitCode}`));
26986
27027
  return;
26987
27028
  }
26988
- resolve6(subprocess);
27029
+ resolve8(subprocess);
26989
27030
  });
26990
27031
  });
26991
27032
  }
26992
27033
  if (isFallbackAttempt) {
26993
- return new Promise((resolve6, reject) => {
27034
+ return new Promise((resolve8, reject) => {
26994
27035
  subprocess.once("error", reject);
26995
27036
  subprocess.once("spawn", () => {
26996
27037
  subprocess.once("close", (exitCode) => {
@@ -27000,17 +27041,17 @@ var baseOpen = async (options) => {
27000
27041
  return;
27001
27042
  }
27002
27043
  subprocess.unref();
27003
- resolve6(subprocess);
27044
+ resolve8(subprocess);
27004
27045
  });
27005
27046
  });
27006
27047
  });
27007
27048
  }
27008
27049
  subprocess.unref();
27009
- return new Promise((resolve6, reject) => {
27050
+ return new Promise((resolve8, reject) => {
27010
27051
  subprocess.once("error", reject);
27011
27052
  subprocess.once("spawn", () => {
27012
27053
  subprocess.off("error", reject);
27013
- resolve6(subprocess);
27054
+ resolve8(subprocess);
27014
27055
  });
27015
27056
  });
27016
27057
  };
@@ -28143,7 +28184,7 @@ function getAllServers() {
28143
28184
  // src/tools/lsp/client.ts
28144
28185
  var {spawn: spawn5 } = globalThis.Bun;
28145
28186
  import { readFileSync as readFileSync28 } from "fs";
28146
- import { extname, resolve as resolve6 } from "path";
28187
+ import { extname, resolve as resolve8 } from "path";
28147
28188
  class LSPServerManager {
28148
28189
  static instance;
28149
28190
  clients = new Map;
@@ -28289,6 +28330,25 @@ class LSPServerManager {
28289
28330
  this.cleanupInterval = null;
28290
28331
  }
28291
28332
  }
28333
+ async cleanupTempDirectoryClients() {
28334
+ const keysToRemove = [];
28335
+ for (const [key, managed] of this.clients.entries()) {
28336
+ const isTempDir = key.startsWith("/tmp/") || key.startsWith("/var/folders/");
28337
+ const isIdle = managed.refCount === 0;
28338
+ if (isTempDir && isIdle) {
28339
+ keysToRemove.push(key);
28340
+ }
28341
+ }
28342
+ for (const key of keysToRemove) {
28343
+ const managed = this.clients.get(key);
28344
+ if (managed) {
28345
+ this.clients.delete(key);
28346
+ try {
28347
+ await managed.client.stop();
28348
+ } catch {}
28349
+ }
28350
+ }
28351
+ }
28292
28352
  }
28293
28353
  var lspManager = LSPServerManager.getInstance();
28294
28354
 
@@ -28323,7 +28383,7 @@ class LSPClient {
28323
28383
  }
28324
28384
  this.startReading();
28325
28385
  this.startStderrReading();
28326
- await new Promise((resolve7) => setTimeout(resolve7, 100));
28386
+ await new Promise((resolve9) => setTimeout(resolve9, 100));
28327
28387
  if (this.proc.exitCode !== null) {
28328
28388
  const stderr = this.stderrBuffer.join(`
28329
28389
  `);
@@ -28460,8 +28520,8 @@ stderr: ${stderr}` : ""));
28460
28520
  \r
28461
28521
  `;
28462
28522
  this.proc.stdin.write(header + msg);
28463
- return new Promise((resolve7, reject) => {
28464
- this.pending.set(id, { resolve: resolve7, reject });
28523
+ return new Promise((resolve9, reject) => {
28524
+ this.pending.set(id, { resolve: resolve9, reject });
28465
28525
  setTimeout(() => {
28466
28526
  if (this.pending.has(id)) {
28467
28527
  this.pending.delete(id);
@@ -28569,7 +28629,7 @@ ${msg}`);
28569
28629
  await new Promise((r2) => setTimeout(r2, 300));
28570
28630
  }
28571
28631
  async openFile(filePath) {
28572
- const absPath = resolve6(filePath);
28632
+ const absPath = resolve8(filePath);
28573
28633
  if (this.openedFiles.has(absPath))
28574
28634
  return;
28575
28635
  const text = readFileSync28(absPath, "utf-8");
@@ -28587,7 +28647,7 @@ ${msg}`);
28587
28647
  await new Promise((r2) => setTimeout(r2, 1000));
28588
28648
  }
28589
28649
  async hover(filePath, line, character) {
28590
- const absPath = resolve6(filePath);
28650
+ const absPath = resolve8(filePath);
28591
28651
  await this.openFile(absPath);
28592
28652
  return this.send("textDocument/hover", {
28593
28653
  textDocument: { uri: `file://${absPath}` },
@@ -28595,7 +28655,7 @@ ${msg}`);
28595
28655
  });
28596
28656
  }
28597
28657
  async definition(filePath, line, character) {
28598
- const absPath = resolve6(filePath);
28658
+ const absPath = resolve8(filePath);
28599
28659
  await this.openFile(absPath);
28600
28660
  return this.send("textDocument/definition", {
28601
28661
  textDocument: { uri: `file://${absPath}` },
@@ -28603,7 +28663,7 @@ ${msg}`);
28603
28663
  });
28604
28664
  }
28605
28665
  async references(filePath, line, character, includeDeclaration = true) {
28606
- const absPath = resolve6(filePath);
28666
+ const absPath = resolve8(filePath);
28607
28667
  await this.openFile(absPath);
28608
28668
  return this.send("textDocument/references", {
28609
28669
  textDocument: { uri: `file://${absPath}` },
@@ -28612,7 +28672,7 @@ ${msg}`);
28612
28672
  });
28613
28673
  }
28614
28674
  async documentSymbols(filePath) {
28615
- const absPath = resolve6(filePath);
28675
+ const absPath = resolve8(filePath);
28616
28676
  await this.openFile(absPath);
28617
28677
  return this.send("textDocument/documentSymbol", {
28618
28678
  textDocument: { uri: `file://${absPath}` }
@@ -28622,7 +28682,7 @@ ${msg}`);
28622
28682
  return this.send("workspace/symbol", { query });
28623
28683
  }
28624
28684
  async diagnostics(filePath) {
28625
- const absPath = resolve6(filePath);
28685
+ const absPath = resolve8(filePath);
28626
28686
  const uri = `file://${absPath}`;
28627
28687
  await this.openFile(absPath);
28628
28688
  await new Promise((r2) => setTimeout(r2, 500));
@@ -28637,7 +28697,7 @@ ${msg}`);
28637
28697
  return { items: this.diagnosticsStore.get(uri) ?? [] };
28638
28698
  }
28639
28699
  async prepareRename(filePath, line, character) {
28640
- const absPath = resolve6(filePath);
28700
+ const absPath = resolve8(filePath);
28641
28701
  await this.openFile(absPath);
28642
28702
  return this.send("textDocument/prepareRename", {
28643
28703
  textDocument: { uri: `file://${absPath}` },
@@ -28645,7 +28705,7 @@ ${msg}`);
28645
28705
  });
28646
28706
  }
28647
28707
  async rename(filePath, line, character, newName) {
28648
- const absPath = resolve6(filePath);
28708
+ const absPath = resolve8(filePath);
28649
28709
  await this.openFile(absPath);
28650
28710
  return this.send("textDocument/rename", {
28651
28711
  textDocument: { uri: `file://${absPath}` },
@@ -28654,7 +28714,7 @@ ${msg}`);
28654
28714
  });
28655
28715
  }
28656
28716
  async codeAction(filePath, startLine, startChar, endLine, endChar, only) {
28657
- const absPath = resolve6(filePath);
28717
+ const absPath = resolve8(filePath);
28658
28718
  await this.openFile(absPath);
28659
28719
  return this.send("textDocument/codeAction", {
28660
28720
  textDocument: { uri: `file://${absPath}` },
@@ -28686,11 +28746,11 @@ ${msg}`);
28686
28746
  }
28687
28747
  }
28688
28748
  // src/tools/lsp/utils.ts
28689
- import { extname as extname2, resolve as resolve7 } from "path";
28749
+ import { extname as extname2, resolve as resolve9 } from "path";
28690
28750
  import { fileURLToPath as fileURLToPath3 } from "url";
28691
28751
  import { existsSync as existsSync42, readFileSync as readFileSync29, writeFileSync as writeFileSync16 } from "fs";
28692
28752
  function findWorkspaceRoot(filePath) {
28693
- let dir = resolve7(filePath);
28753
+ let dir = resolve9(filePath);
28694
28754
  if (!existsSync42(dir) || !__require("fs").statSync(dir).isDirectory()) {
28695
28755
  dir = __require("path").dirname(dir);
28696
28756
  }
@@ -28703,7 +28763,7 @@ function findWorkspaceRoot(filePath) {
28703
28763
  }
28704
28764
  dir = __require("path").dirname(dir);
28705
28765
  }
28706
- return __require("path").dirname(resolve7(filePath));
28766
+ return __require("path").dirname(resolve9(filePath));
28707
28767
  }
28708
28768
  function uriToPath(uri) {
28709
28769
  return fileURLToPath3(uri);
@@ -28743,7 +28803,7 @@ function formatServerLookupError(result) {
28743
28803
  `);
28744
28804
  }
28745
28805
  async function withLspClient(filePath, fn) {
28746
- const absPath = resolve7(filePath);
28806
+ const absPath = resolve9(filePath);
28747
28807
  const ext = extname2(absPath);
28748
28808
  const result = findServerForExtension(ext);
28749
28809
  if (result.status !== "found") {
@@ -44079,7 +44139,7 @@ function formatDuration(start, end) {
44079
44139
  }
44080
44140
  }
44081
44141
  function delay(ms) {
44082
- return new Promise((resolve8) => setTimeout(resolve8, ms));
44142
+ return new Promise((resolve10) => setTimeout(resolve10, ms));
44083
44143
  }
44084
44144
  function truncateText(text, maxLength) {
44085
44145
  if (text.length <= maxLength)
@@ -44932,7 +44992,7 @@ Session ID: ${args.resume}`;
44932
44992
  let lastMsgCount = 0;
44933
44993
  let stablePolls = 0;
44934
44994
  while (Date.now() - pollStart < 60000) {
44935
- await new Promise((resolve8) => setTimeout(resolve8, POLL_INTERVAL_MS));
44995
+ await new Promise((resolve10) => setTimeout(resolve10, POLL_INTERVAL_MS));
44936
44996
  const elapsed = Date.now() - pollStart;
44937
44997
  if (elapsed < MIN_STABILITY_TIME_MS)
44938
44998
  continue;
@@ -45098,7 +45158,7 @@ System notifies on completion. Use \`background_output\` with task_id="${task.id
45098
45158
  }).catch((error45) => {
45099
45159
  promptError = error45 instanceof Error ? error45 : new Error(String(error45));
45100
45160
  });
45101
- await new Promise((resolve8) => setTimeout(resolve8, 100));
45161
+ await new Promise((resolve10) => setTimeout(resolve10, 100));
45102
45162
  if (promptError) {
45103
45163
  if (toastManager && taskId !== undefined) {
45104
45164
  toastManager.removeTask(taskId);
@@ -45121,7 +45181,7 @@ Session ID: ${sessionID}`;
45121
45181
  let lastMsgCount = 0;
45122
45182
  let stablePolls = 0;
45123
45183
  while (Date.now() - pollStart < MAX_POLL_TIME_MS) {
45124
- await new Promise((resolve8) => setTimeout(resolve8, POLL_INTERVAL_MS));
45184
+ await new Promise((resolve10) => setTimeout(resolve10, POLL_INTERVAL_MS));
45125
45185
  const asyncError = promptError;
45126
45186
  if (asyncError) {
45127
45187
  if (toastManager && taskId !== undefined) {
@@ -45210,7 +45270,6 @@ ${textContent || "(No text output)"}`;
45210
45270
 
45211
45271
  // src/tools/sisyphus-task/index.ts
45212
45272
  init_constants();
45213
-
45214
45273
  // src/tools/index.ts
45215
45274
  function createBackgroundTools(manager, client2) {
45216
45275
  return {
@@ -45273,9 +45332,9 @@ class ConcurrencyManager {
45273
45332
  this.counts.set(model, current + 1);
45274
45333
  return;
45275
45334
  }
45276
- return new Promise((resolve8) => {
45335
+ return new Promise((resolve10) => {
45277
45336
  const queue = this.queues.get(model) ?? [];
45278
- queue.push(resolve8);
45337
+ queue.push(resolve10);
45279
45338
  this.queues.set(model, queue);
45280
45339
  });
45281
45340
  }
@@ -47293,7 +47352,7 @@ class Protocol {
47293
47352
  return;
47294
47353
  }
47295
47354
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
47296
- await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
47355
+ await new Promise((resolve10) => setTimeout(resolve10, pollInterval));
47297
47356
  options?.signal?.throwIfAborted();
47298
47357
  }
47299
47358
  } catch (error45) {
@@ -47305,7 +47364,7 @@ class Protocol {
47305
47364
  }
47306
47365
  request(request2, resultSchema, options) {
47307
47366
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
47308
- return new Promise((resolve8, reject) => {
47367
+ return new Promise((resolve10, reject) => {
47309
47368
  const earlyReject = (error45) => {
47310
47369
  reject(error45);
47311
47370
  };
@@ -47383,7 +47442,7 @@ class Protocol {
47383
47442
  if (!parseResult.success) {
47384
47443
  reject(parseResult.error);
47385
47444
  } else {
47386
- resolve8(parseResult.data);
47445
+ resolve10(parseResult.data);
47387
47446
  }
47388
47447
  } catch (error45) {
47389
47448
  reject(error45);
@@ -47574,12 +47633,12 @@ class Protocol {
47574
47633
  interval = task.pollInterval;
47575
47634
  }
47576
47635
  } catch {}
47577
- return new Promise((resolve8, reject) => {
47636
+ return new Promise((resolve10, reject) => {
47578
47637
  if (signal.aborted) {
47579
47638
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
47580
47639
  return;
47581
47640
  }
47582
- const timeoutId = setTimeout(resolve8, interval);
47641
+ const timeoutId = setTimeout(resolve10, interval);
47583
47642
  signal.addEventListener("abort", () => {
47584
47643
  clearTimeout(timeoutId);
47585
47644
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -48356,7 +48415,7 @@ class StdioClientTransport {
48356
48415
  if (this._process) {
48357
48416
  throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
48358
48417
  }
48359
- return new Promise((resolve8, reject) => {
48418
+ return new Promise((resolve10, reject) => {
48360
48419
  this._process = import_cross_spawn.default(this._serverParams.command, this._serverParams.args ?? [], {
48361
48420
  env: {
48362
48421
  ...getDefaultEnvironment(),
@@ -48372,7 +48431,7 @@ class StdioClientTransport {
48372
48431
  this.onerror?.(error45);
48373
48432
  });
48374
48433
  this._process.on("spawn", () => {
48375
- resolve8();
48434
+ resolve10();
48376
48435
  });
48377
48436
  this._process.on("close", (_code) => {
48378
48437
  this._process = undefined;
@@ -48419,20 +48478,20 @@ class StdioClientTransport {
48419
48478
  if (this._process) {
48420
48479
  const processToClose = this._process;
48421
48480
  this._process = undefined;
48422
- const closePromise = new Promise((resolve8) => {
48481
+ const closePromise = new Promise((resolve10) => {
48423
48482
  processToClose.once("close", () => {
48424
- resolve8();
48483
+ resolve10();
48425
48484
  });
48426
48485
  });
48427
48486
  try {
48428
48487
  processToClose.stdin?.end();
48429
48488
  } catch {}
48430
- await Promise.race([closePromise, new Promise((resolve8) => setTimeout(resolve8, 2000).unref())]);
48489
+ await Promise.race([closePromise, new Promise((resolve10) => setTimeout(resolve10, 2000).unref())]);
48431
48490
  if (processToClose.exitCode === null) {
48432
48491
  try {
48433
48492
  processToClose.kill("SIGTERM");
48434
48493
  } catch {}
48435
- await Promise.race([closePromise, new Promise((resolve8) => setTimeout(resolve8, 2000).unref())]);
48494
+ await Promise.race([closePromise, new Promise((resolve10) => setTimeout(resolve10, 2000).unref())]);
48436
48495
  }
48437
48496
  if (processToClose.exitCode === null) {
48438
48497
  try {
@@ -48443,15 +48502,15 @@ class StdioClientTransport {
48443
48502
  this._readBuffer.clear();
48444
48503
  }
48445
48504
  send(message) {
48446
- return new Promise((resolve8) => {
48505
+ return new Promise((resolve10) => {
48447
48506
  if (!this._process?.stdin) {
48448
48507
  throw new Error("Not connected");
48449
48508
  }
48450
48509
  const json3 = serializeMessage(message);
48451
48510
  if (this._process.stdin.write(json3)) {
48452
- resolve8();
48511
+ resolve10();
48453
48512
  } else {
48454
- this._process.stdin.once("drain", resolve8);
48513
+ this._process.stdin.once("drain", resolve10);
48455
48514
  }
48456
48515
  });
48457
48516
  }
@@ -56044,7 +56103,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
56044
56103
  isSisyphusEnabled: pluginConfig.sisyphus_agent?.disabled !== true,
56045
56104
  autoUpdate: pluginConfig.auto_update ?? true
56046
56105
  }) : null;
56047
- const keywordDetector = isHookEnabled("keyword-detector") ? createKeywordDetectorHook(ctx) : null;
56106
+ const keywordDetector = isHookEnabled("keyword-detector") ? createKeywordDetectorHook(ctx, contextCollector) : null;
56048
56107
  const contextInjector = createContextInjectorHook(contextCollector);
56049
56108
  const contextInjectorMessagesTransform = createContextInjectorMessagesTransformHook(contextCollector);
56050
56109
  const agentUsageReminder = isHookEnabled("agent-usage-reminder") ? createAgentUsageReminderHook(ctx) : null;
@@ -56136,8 +56195,8 @@ var OhMyOpenCodePlugin = async (ctx) => {
56136
56195
  interactive_bash
56137
56196
  },
56138
56197
  "chat.message": async (input, output) => {
56139
- await claudeCodeHooks["chat.message"]?.(input, output);
56140
56198
  await keywordDetector?.["chat.message"]?.(input, output);
56199
+ await claudeCodeHooks["chat.message"]?.(input, output);
56141
56200
  await contextInjector["chat.message"]?.(input, output);
56142
56201
  await autoSlashCommand?.["chat.message"]?.(input, output);
56143
56202
  await startWork?.["chat.message"]?.(input, output);
@@ -56208,6 +56267,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
56208
56267
  }
56209
56268
  if (sessionInfo?.id) {
56210
56269
  await skillMcpManager.disconnectSession(sessionInfo.id);
56270
+ await lspManager.cleanupTempDirectoryClients();
56211
56271
  }
56212
56272
  }
56213
56273
  if (event.type === "session.error") {