oh-my-opencode 3.0.0-beta.3 → 3.0.0-beta.5
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.md +42 -31
- package/README.md +23 -18
- package/README.zh-cn.md +43 -34
- package/dist/cli/index.js +10 -6
- package/dist/features/context-injector/injector.d.ts +1 -1
- package/dist/hooks/keyword-detector/index.d.ts +2 -1
- package/dist/hooks/prometheus-md-only/constants.d.ts +1 -1
- package/dist/hooks/prometheus-md-only/index.d.ts +1 -1
- package/dist/index.js +463 -405
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/lsp/client.d.ts +1 -0
- package/package.json +1 -1
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
|
|
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
|
-
} =
|
|
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 =
|
|
861
|
-
const EXTGLOB_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
|
-
} =
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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,
|
|
5323
|
+
function resolveComponent(base, relative5, options, skipNormalization) {
|
|
5324
5324
|
const target = {};
|
|
5325
5325
|
if (!skipNormalization) {
|
|
5326
5326
|
base = parse7(serialize(base, options), options);
|
|
5327
|
-
|
|
5327
|
+
relative5 = parse7(serialize(relative5, options), options);
|
|
5328
5328
|
}
|
|
5329
5329
|
options = options || {};
|
|
5330
|
-
if (!options.tolerant &&
|
|
5331
|
-
target.scheme =
|
|
5332
|
-
target.userinfo =
|
|
5333
|
-
target.host =
|
|
5334
|
-
target.port =
|
|
5335
|
-
target.path = removeDotSegments(
|
|
5336
|
-
target.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 (
|
|
5339
|
-
target.userinfo =
|
|
5340
|
-
target.host =
|
|
5341
|
-
target.port =
|
|
5342
|
-
target.path = removeDotSegments(
|
|
5343
|
-
target.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 (!
|
|
5345
|
+
if (!relative5.path) {
|
|
5346
5346
|
target.path = base.path;
|
|
5347
|
-
if (
|
|
5348
|
-
target.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 (
|
|
5354
|
-
target.path = removeDotSegments(
|
|
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 = "/" +
|
|
5357
|
+
target.path = "/" + relative5.path;
|
|
5358
5358
|
} else if (!base.path) {
|
|
5359
|
-
target.path =
|
|
5359
|
+
target.path = relative5.path;
|
|
5360
5360
|
} else {
|
|
5361
|
-
target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) +
|
|
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 =
|
|
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 =
|
|
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:
|
|
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(
|
|
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
|
-
|
|
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((
|
|
8493
|
+
const step = (i2) => new Promise((resolve10, reject) => {
|
|
8494
8494
|
if (i2 === pathEnv.length)
|
|
8495
|
-
return opt.all && found.length ?
|
|
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
|
-
|
|
8500
|
+
resolve10(subStep(p2, i2, 0));
|
|
8501
8501
|
});
|
|
8502
|
-
const subStep = (p2, i2, ii) => new Promise((
|
|
8502
|
+
const subStep = (p2, i2, ii) => new Promise((resolve10, reject) => {
|
|
8503
8503
|
if (ii === pathExt.length)
|
|
8504
|
-
return
|
|
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
|
|
8511
|
+
return resolve10(p2 + ext);
|
|
8512
8512
|
}
|
|
8513
|
-
return
|
|
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
|
-
|
|
18460
|
-
|
|
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 ${
|
|
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
|
|
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
|
|
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((
|
|
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((
|
|
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
|
|
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
|
|
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
|
|
21067
|
+
return resolve6(baseDir, filePath);
|
|
21068
21068
|
}
|
|
21069
21069
|
function loadSkillFromFile(filePath) {
|
|
21070
21070
|
try {
|
|
@@ -22699,13 +22699,12 @@ ${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/";
|
|
22709
22708
|
var BLOCKED_TOOLS = ["Write", "Edit", "write", "edit"];
|
|
22710
22709
|
var PLANNING_CONSULT_WARNING = `
|
|
22711
22710
|
|
|
@@ -22729,10 +22728,20 @@ Return your findings and recommendations. The actual implementation will be hand
|
|
|
22729
22728
|
`;
|
|
22730
22729
|
|
|
22731
22730
|
// src/hooks/prometheus-md-only/index.ts
|
|
22732
|
-
function isAllowedFile(filePath) {
|
|
22733
|
-
const
|
|
22734
|
-
const
|
|
22735
|
-
|
|
22731
|
+
function isAllowedFile(filePath, workspaceRoot) {
|
|
22732
|
+
const resolved = resolve7(workspaceRoot, filePath);
|
|
22733
|
+
const rel = relative4(workspaceRoot, resolved);
|
|
22734
|
+
if (rel.startsWith("..") || isAbsolute3(rel)) {
|
|
22735
|
+
return false;
|
|
22736
|
+
}
|
|
22737
|
+
if (!/\.sisyphus[/\\]/i.test(rel)) {
|
|
22738
|
+
return false;
|
|
22739
|
+
}
|
|
22740
|
+
const hasAllowedExtension = ALLOWED_EXTENSIONS.some((ext) => resolved.toLowerCase().endsWith(ext.toLowerCase()));
|
|
22741
|
+
if (!hasAllowedExtension) {
|
|
22742
|
+
return false;
|
|
22743
|
+
}
|
|
22744
|
+
return true;
|
|
22736
22745
|
}
|
|
22737
22746
|
function getMessageDir9(sessionID) {
|
|
22738
22747
|
if (!existsSync37(MESSAGE_STORAGE))
|
|
@@ -22754,7 +22763,7 @@ function getAgentFromSession(sessionID) {
|
|
|
22754
22763
|
return;
|
|
22755
22764
|
return findNearestMessageWithFields(messageDir)?.agent;
|
|
22756
22765
|
}
|
|
22757
|
-
function createPrometheusMdOnlyHook(
|
|
22766
|
+
function createPrometheusMdOnlyHook(ctx) {
|
|
22758
22767
|
return {
|
|
22759
22768
|
"tool.execute.before": async (input, output) => {
|
|
22760
22769
|
const agentName = getAgentFromSession(input.sessionID);
|
|
@@ -22781,7 +22790,7 @@ function createPrometheusMdOnlyHook(_ctx) {
|
|
|
22781
22790
|
if (!filePath) {
|
|
22782
22791
|
return;
|
|
22783
22792
|
}
|
|
22784
|
-
if (!isAllowedFile(filePath)) {
|
|
22793
|
+
if (!isAllowedFile(filePath, ctx.directory)) {
|
|
22785
22794
|
log(`[${HOOK_NAME4}] Blocked: Prometheus can only write to .sisyphus/*.md`, {
|
|
22786
22795
|
sessionID: input.sessionID,
|
|
22787
22796
|
tool: toolName,
|
|
@@ -23048,7 +23057,9 @@ import { execSync as execSync2 } from "child_process";
|
|
|
23048
23057
|
import { existsSync as existsSync39, readdirSync as readdirSync14 } from "fs";
|
|
23049
23058
|
import { join as join47 } from "path";
|
|
23050
23059
|
var HOOK_NAME6 = "sisyphus-orchestrator";
|
|
23051
|
-
|
|
23060
|
+
function isSisyphusPath(filePath) {
|
|
23061
|
+
return /\.sisyphus[/\\]/.test(filePath);
|
|
23062
|
+
}
|
|
23052
23063
|
var WRITE_EDIT_TOOLS = ["Write", "Edit", "write", "edit"];
|
|
23053
23064
|
var DIRECT_WORK_REMINDER = `
|
|
23054
23065
|
|
|
@@ -23493,7 +23504,7 @@ function createSisyphusOrchestratorHook(ctx, options) {
|
|
|
23493
23504
|
}
|
|
23494
23505
|
if (WRITE_EDIT_TOOLS.includes(input.tool)) {
|
|
23495
23506
|
const filePath = output.args.filePath ?? output.args.path ?? output.args.file;
|
|
23496
|
-
if (filePath && !filePath
|
|
23507
|
+
if (filePath && !isSisyphusPath(filePath)) {
|
|
23497
23508
|
if (input.callID) {
|
|
23498
23509
|
pendingFilePaths.set(input.callID, filePath);
|
|
23499
23510
|
}
|
|
@@ -23530,7 +23541,7 @@ function createSisyphusOrchestratorHook(ctx, options) {
|
|
|
23530
23541
|
if (!filePath) {
|
|
23531
23542
|
filePath = output.metadata?.filePath;
|
|
23532
23543
|
}
|
|
23533
|
-
if (filePath && !filePath
|
|
23544
|
+
if (filePath && !isSisyphusPath(filePath)) {
|
|
23534
23545
|
output.output = (output.output || "") + DIRECT_WORK_REMINDER;
|
|
23535
23546
|
log(`[${HOOK_NAME6}] Direct work reminder appended`, {
|
|
23536
23547
|
sessionID: input.sessionID,
|
|
@@ -23659,9 +23670,37 @@ class ContextCollector {
|
|
|
23659
23670
|
}
|
|
23660
23671
|
var contextCollector = new ContextCollector;
|
|
23661
23672
|
// src/features/context-injector/injector.ts
|
|
23673
|
+
function injectPendingContext(collector, sessionID, parts) {
|
|
23674
|
+
if (!collector.hasPending(sessionID)) {
|
|
23675
|
+
return { injected: false, contextLength: 0 };
|
|
23676
|
+
}
|
|
23677
|
+
const textPartIndex = parts.findIndex((p) => p.type === "text" && p.text !== undefined);
|
|
23678
|
+
if (textPartIndex === -1) {
|
|
23679
|
+
return { injected: false, contextLength: 0 };
|
|
23680
|
+
}
|
|
23681
|
+
const pending = collector.consume(sessionID);
|
|
23682
|
+
const originalText = parts[textPartIndex].text ?? "";
|
|
23683
|
+
parts[textPartIndex].text = `${pending.merged}
|
|
23684
|
+
|
|
23685
|
+
---
|
|
23686
|
+
|
|
23687
|
+
${originalText}`;
|
|
23688
|
+
return {
|
|
23689
|
+
injected: true,
|
|
23690
|
+
contextLength: pending.merged.length
|
|
23691
|
+
};
|
|
23692
|
+
}
|
|
23662
23693
|
function createContextInjectorHook(collector) {
|
|
23663
23694
|
return {
|
|
23664
|
-
"chat.message": async (
|
|
23695
|
+
"chat.message": async (input, output) => {
|
|
23696
|
+
const result = injectPendingContext(collector, input.sessionID, output.parts);
|
|
23697
|
+
if (result.injected) {
|
|
23698
|
+
log("[context-injector] Injected pending context via chat.message", {
|
|
23699
|
+
sessionID: input.sessionID,
|
|
23700
|
+
contextLength: result.contextLength
|
|
23701
|
+
});
|
|
23702
|
+
}
|
|
23703
|
+
}
|
|
23665
23704
|
};
|
|
23666
23705
|
}
|
|
23667
23706
|
function createContextInjectorMessagesTransformHook(collector) {
|
|
@@ -23977,8 +24016,8 @@ function startCallbackServer(timeoutMs = 5 * 60 * 1000) {
|
|
|
23977
24016
|
const actualPort = server.port;
|
|
23978
24017
|
const redirectUri = `http://localhost:${actualPort}/oauth-callback`;
|
|
23979
24018
|
const waitForCallback = () => {
|
|
23980
|
-
return new Promise((
|
|
23981
|
-
resolveCallback =
|
|
24019
|
+
return new Promise((resolve8, reject) => {
|
|
24020
|
+
resolveCallback = resolve8;
|
|
23982
24021
|
rejectCallback = reject;
|
|
23983
24022
|
timeoutId = setTimeout(() => {
|
|
23984
24023
|
cleanup();
|
|
@@ -24100,7 +24139,7 @@ async function refreshAccessToken(refreshToken, clientId = ANTIGRAVITY_CLIENT_ID
|
|
|
24100
24139
|
}
|
|
24101
24140
|
if (attempt < MAX_REFRESH_RETRIES) {
|
|
24102
24141
|
const delay = calculateRetryDelay(attempt);
|
|
24103
|
-
await new Promise((
|
|
24142
|
+
await new Promise((resolve8) => setTimeout(resolve8, delay));
|
|
24104
24143
|
}
|
|
24105
24144
|
} catch (error) {
|
|
24106
24145
|
if (error instanceof AntigravityTokenRefreshError) {
|
|
@@ -24113,7 +24152,7 @@ async function refreshAccessToken(refreshToken, clientId = ANTIGRAVITY_CLIENT_ID
|
|
|
24113
24152
|
});
|
|
24114
24153
|
if (attempt < MAX_REFRESH_RETRIES) {
|
|
24115
24154
|
const delay = calculateRetryDelay(attempt);
|
|
24116
|
-
await new Promise((
|
|
24155
|
+
await new Promise((resolve8) => setTimeout(resolve8, delay));
|
|
24117
24156
|
}
|
|
24118
24157
|
}
|
|
24119
24158
|
}
|
|
@@ -24179,7 +24218,7 @@ function isFreeTier(tierId) {
|
|
|
24179
24218
|
return lower === "free" || lower === "free-tier" || lower.startsWith("free");
|
|
24180
24219
|
}
|
|
24181
24220
|
function wait(ms) {
|
|
24182
|
-
return new Promise((
|
|
24221
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
24183
24222
|
}
|
|
24184
24223
|
async function callLoadCodeAssistAPI(accessToken, projectId) {
|
|
24185
24224
|
const metadata = { ...CODE_ASSIST_METADATA };
|
|
@@ -25596,7 +25635,7 @@ async function attemptFetch(options) {
|
|
|
25596
25635
|
if (attempt < maxPermissionRetries) {
|
|
25597
25636
|
const delay = calculateRetryDelay2(attempt);
|
|
25598
25637
|
debugLog7(`[RETRY] GCP permission error, retry ${attempt + 1}/${maxPermissionRetries} after ${delay}ms`);
|
|
25599
|
-
await new Promise((
|
|
25638
|
+
await new Promise((resolve8) => setTimeout(resolve8, delay));
|
|
25600
25639
|
continue;
|
|
25601
25640
|
}
|
|
25602
25641
|
debugLog7(`[RETRY] GCP permission error, max retries exceeded`);
|
|
@@ -26978,19 +27017,19 @@ var baseOpen = async (options) => {
|
|
|
26978
27017
|
}
|
|
26979
27018
|
const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
|
|
26980
27019
|
if (options.wait) {
|
|
26981
|
-
return new Promise((
|
|
27020
|
+
return new Promise((resolve8, reject) => {
|
|
26982
27021
|
subprocess.once("error", reject);
|
|
26983
27022
|
subprocess.once("close", (exitCode) => {
|
|
26984
27023
|
if (!options.allowNonzeroExitCode && exitCode !== 0) {
|
|
26985
27024
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
26986
27025
|
return;
|
|
26987
27026
|
}
|
|
26988
|
-
|
|
27027
|
+
resolve8(subprocess);
|
|
26989
27028
|
});
|
|
26990
27029
|
});
|
|
26991
27030
|
}
|
|
26992
27031
|
if (isFallbackAttempt) {
|
|
26993
|
-
return new Promise((
|
|
27032
|
+
return new Promise((resolve8, reject) => {
|
|
26994
27033
|
subprocess.once("error", reject);
|
|
26995
27034
|
subprocess.once("spawn", () => {
|
|
26996
27035
|
subprocess.once("close", (exitCode) => {
|
|
@@ -27000,17 +27039,17 @@ var baseOpen = async (options) => {
|
|
|
27000
27039
|
return;
|
|
27001
27040
|
}
|
|
27002
27041
|
subprocess.unref();
|
|
27003
|
-
|
|
27042
|
+
resolve8(subprocess);
|
|
27004
27043
|
});
|
|
27005
27044
|
});
|
|
27006
27045
|
});
|
|
27007
27046
|
}
|
|
27008
27047
|
subprocess.unref();
|
|
27009
|
-
return new Promise((
|
|
27048
|
+
return new Promise((resolve8, reject) => {
|
|
27010
27049
|
subprocess.once("error", reject);
|
|
27011
27050
|
subprocess.once("spawn", () => {
|
|
27012
27051
|
subprocess.off("error", reject);
|
|
27013
|
-
|
|
27052
|
+
resolve8(subprocess);
|
|
27014
27053
|
});
|
|
27015
27054
|
});
|
|
27016
27055
|
};
|
|
@@ -28143,7 +28182,7 @@ function getAllServers() {
|
|
|
28143
28182
|
// src/tools/lsp/client.ts
|
|
28144
28183
|
var {spawn: spawn5 } = globalThis.Bun;
|
|
28145
28184
|
import { readFileSync as readFileSync28 } from "fs";
|
|
28146
|
-
import { extname, resolve as
|
|
28185
|
+
import { extname, resolve as resolve8 } from "path";
|
|
28147
28186
|
class LSPServerManager {
|
|
28148
28187
|
static instance;
|
|
28149
28188
|
clients = new Map;
|
|
@@ -28289,6 +28328,25 @@ class LSPServerManager {
|
|
|
28289
28328
|
this.cleanupInterval = null;
|
|
28290
28329
|
}
|
|
28291
28330
|
}
|
|
28331
|
+
async cleanupTempDirectoryClients() {
|
|
28332
|
+
const keysToRemove = [];
|
|
28333
|
+
for (const [key, managed] of this.clients.entries()) {
|
|
28334
|
+
const isTempDir = key.startsWith("/tmp/") || key.startsWith("/var/folders/");
|
|
28335
|
+
const isIdle = managed.refCount === 0;
|
|
28336
|
+
if (isTempDir && isIdle) {
|
|
28337
|
+
keysToRemove.push(key);
|
|
28338
|
+
}
|
|
28339
|
+
}
|
|
28340
|
+
for (const key of keysToRemove) {
|
|
28341
|
+
const managed = this.clients.get(key);
|
|
28342
|
+
if (managed) {
|
|
28343
|
+
this.clients.delete(key);
|
|
28344
|
+
try {
|
|
28345
|
+
await managed.client.stop();
|
|
28346
|
+
} catch {}
|
|
28347
|
+
}
|
|
28348
|
+
}
|
|
28349
|
+
}
|
|
28292
28350
|
}
|
|
28293
28351
|
var lspManager = LSPServerManager.getInstance();
|
|
28294
28352
|
|
|
@@ -28323,7 +28381,7 @@ class LSPClient {
|
|
|
28323
28381
|
}
|
|
28324
28382
|
this.startReading();
|
|
28325
28383
|
this.startStderrReading();
|
|
28326
|
-
await new Promise((
|
|
28384
|
+
await new Promise((resolve9) => setTimeout(resolve9, 100));
|
|
28327
28385
|
if (this.proc.exitCode !== null) {
|
|
28328
28386
|
const stderr = this.stderrBuffer.join(`
|
|
28329
28387
|
`);
|
|
@@ -28460,8 +28518,8 @@ stderr: ${stderr}` : ""));
|
|
|
28460
28518
|
\r
|
|
28461
28519
|
`;
|
|
28462
28520
|
this.proc.stdin.write(header + msg);
|
|
28463
|
-
return new Promise((
|
|
28464
|
-
this.pending.set(id, { resolve:
|
|
28521
|
+
return new Promise((resolve9, reject) => {
|
|
28522
|
+
this.pending.set(id, { resolve: resolve9, reject });
|
|
28465
28523
|
setTimeout(() => {
|
|
28466
28524
|
if (this.pending.has(id)) {
|
|
28467
28525
|
this.pending.delete(id);
|
|
@@ -28569,7 +28627,7 @@ ${msg}`);
|
|
|
28569
28627
|
await new Promise((r2) => setTimeout(r2, 300));
|
|
28570
28628
|
}
|
|
28571
28629
|
async openFile(filePath) {
|
|
28572
|
-
const absPath =
|
|
28630
|
+
const absPath = resolve8(filePath);
|
|
28573
28631
|
if (this.openedFiles.has(absPath))
|
|
28574
28632
|
return;
|
|
28575
28633
|
const text = readFileSync28(absPath, "utf-8");
|
|
@@ -28587,7 +28645,7 @@ ${msg}`);
|
|
|
28587
28645
|
await new Promise((r2) => setTimeout(r2, 1000));
|
|
28588
28646
|
}
|
|
28589
28647
|
async hover(filePath, line, character) {
|
|
28590
|
-
const absPath =
|
|
28648
|
+
const absPath = resolve8(filePath);
|
|
28591
28649
|
await this.openFile(absPath);
|
|
28592
28650
|
return this.send("textDocument/hover", {
|
|
28593
28651
|
textDocument: { uri: `file://${absPath}` },
|
|
@@ -28595,7 +28653,7 @@ ${msg}`);
|
|
|
28595
28653
|
});
|
|
28596
28654
|
}
|
|
28597
28655
|
async definition(filePath, line, character) {
|
|
28598
|
-
const absPath =
|
|
28656
|
+
const absPath = resolve8(filePath);
|
|
28599
28657
|
await this.openFile(absPath);
|
|
28600
28658
|
return this.send("textDocument/definition", {
|
|
28601
28659
|
textDocument: { uri: `file://${absPath}` },
|
|
@@ -28603,7 +28661,7 @@ ${msg}`);
|
|
|
28603
28661
|
});
|
|
28604
28662
|
}
|
|
28605
28663
|
async references(filePath, line, character, includeDeclaration = true) {
|
|
28606
|
-
const absPath =
|
|
28664
|
+
const absPath = resolve8(filePath);
|
|
28607
28665
|
await this.openFile(absPath);
|
|
28608
28666
|
return this.send("textDocument/references", {
|
|
28609
28667
|
textDocument: { uri: `file://${absPath}` },
|
|
@@ -28612,7 +28670,7 @@ ${msg}`);
|
|
|
28612
28670
|
});
|
|
28613
28671
|
}
|
|
28614
28672
|
async documentSymbols(filePath) {
|
|
28615
|
-
const absPath =
|
|
28673
|
+
const absPath = resolve8(filePath);
|
|
28616
28674
|
await this.openFile(absPath);
|
|
28617
28675
|
return this.send("textDocument/documentSymbol", {
|
|
28618
28676
|
textDocument: { uri: `file://${absPath}` }
|
|
@@ -28622,7 +28680,7 @@ ${msg}`);
|
|
|
28622
28680
|
return this.send("workspace/symbol", { query });
|
|
28623
28681
|
}
|
|
28624
28682
|
async diagnostics(filePath) {
|
|
28625
|
-
const absPath =
|
|
28683
|
+
const absPath = resolve8(filePath);
|
|
28626
28684
|
const uri = `file://${absPath}`;
|
|
28627
28685
|
await this.openFile(absPath);
|
|
28628
28686
|
await new Promise((r2) => setTimeout(r2, 500));
|
|
@@ -28637,7 +28695,7 @@ ${msg}`);
|
|
|
28637
28695
|
return { items: this.diagnosticsStore.get(uri) ?? [] };
|
|
28638
28696
|
}
|
|
28639
28697
|
async prepareRename(filePath, line, character) {
|
|
28640
|
-
const absPath =
|
|
28698
|
+
const absPath = resolve8(filePath);
|
|
28641
28699
|
await this.openFile(absPath);
|
|
28642
28700
|
return this.send("textDocument/prepareRename", {
|
|
28643
28701
|
textDocument: { uri: `file://${absPath}` },
|
|
@@ -28645,7 +28703,7 @@ ${msg}`);
|
|
|
28645
28703
|
});
|
|
28646
28704
|
}
|
|
28647
28705
|
async rename(filePath, line, character, newName) {
|
|
28648
|
-
const absPath =
|
|
28706
|
+
const absPath = resolve8(filePath);
|
|
28649
28707
|
await this.openFile(absPath);
|
|
28650
28708
|
return this.send("textDocument/rename", {
|
|
28651
28709
|
textDocument: { uri: `file://${absPath}` },
|
|
@@ -28654,7 +28712,7 @@ ${msg}`);
|
|
|
28654
28712
|
});
|
|
28655
28713
|
}
|
|
28656
28714
|
async codeAction(filePath, startLine, startChar, endLine, endChar, only) {
|
|
28657
|
-
const absPath =
|
|
28715
|
+
const absPath = resolve8(filePath);
|
|
28658
28716
|
await this.openFile(absPath);
|
|
28659
28717
|
return this.send("textDocument/codeAction", {
|
|
28660
28718
|
textDocument: { uri: `file://${absPath}` },
|
|
@@ -28686,11 +28744,11 @@ ${msg}`);
|
|
|
28686
28744
|
}
|
|
28687
28745
|
}
|
|
28688
28746
|
// src/tools/lsp/utils.ts
|
|
28689
|
-
import { extname as extname2, resolve as
|
|
28747
|
+
import { extname as extname2, resolve as resolve9 } from "path";
|
|
28690
28748
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
28691
28749
|
import { existsSync as existsSync42, readFileSync as readFileSync29, writeFileSync as writeFileSync16 } from "fs";
|
|
28692
28750
|
function findWorkspaceRoot(filePath) {
|
|
28693
|
-
let dir =
|
|
28751
|
+
let dir = resolve9(filePath);
|
|
28694
28752
|
if (!existsSync42(dir) || !__require("fs").statSync(dir).isDirectory()) {
|
|
28695
28753
|
dir = __require("path").dirname(dir);
|
|
28696
28754
|
}
|
|
@@ -28703,7 +28761,7 @@ function findWorkspaceRoot(filePath) {
|
|
|
28703
28761
|
}
|
|
28704
28762
|
dir = __require("path").dirname(dir);
|
|
28705
28763
|
}
|
|
28706
|
-
return __require("path").dirname(
|
|
28764
|
+
return __require("path").dirname(resolve9(filePath));
|
|
28707
28765
|
}
|
|
28708
28766
|
function uriToPath(uri) {
|
|
28709
28767
|
return fileURLToPath3(uri);
|
|
@@ -28743,7 +28801,7 @@ function formatServerLookupError(result) {
|
|
|
28743
28801
|
`);
|
|
28744
28802
|
}
|
|
28745
28803
|
async function withLspClient(filePath, fn) {
|
|
28746
|
-
const absPath =
|
|
28804
|
+
const absPath = resolve9(filePath);
|
|
28747
28805
|
const ext = extname2(absPath);
|
|
28748
28806
|
const result = findServerForExtension(ext);
|
|
28749
28807
|
if (result.status !== "found") {
|
|
@@ -44079,7 +44137,7 @@ function formatDuration(start, end) {
|
|
|
44079
44137
|
}
|
|
44080
44138
|
}
|
|
44081
44139
|
function delay(ms) {
|
|
44082
|
-
return new Promise((
|
|
44140
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
44083
44141
|
}
|
|
44084
44142
|
function truncateText(text, maxLength) {
|
|
44085
44143
|
if (text.length <= maxLength)
|
|
@@ -44932,7 +44990,7 @@ Session ID: ${args.resume}`;
|
|
|
44932
44990
|
let lastMsgCount = 0;
|
|
44933
44991
|
let stablePolls = 0;
|
|
44934
44992
|
while (Date.now() - pollStart < 60000) {
|
|
44935
|
-
await new Promise((
|
|
44993
|
+
await new Promise((resolve10) => setTimeout(resolve10, POLL_INTERVAL_MS));
|
|
44936
44994
|
const elapsed = Date.now() - pollStart;
|
|
44937
44995
|
if (elapsed < MIN_STABILITY_TIME_MS)
|
|
44938
44996
|
continue;
|
|
@@ -45098,7 +45156,7 @@ System notifies on completion. Use \`background_output\` with task_id="${task.id
|
|
|
45098
45156
|
}).catch((error45) => {
|
|
45099
45157
|
promptError = error45 instanceof Error ? error45 : new Error(String(error45));
|
|
45100
45158
|
});
|
|
45101
|
-
await new Promise((
|
|
45159
|
+
await new Promise((resolve10) => setTimeout(resolve10, 100));
|
|
45102
45160
|
if (promptError) {
|
|
45103
45161
|
if (toastManager && taskId !== undefined) {
|
|
45104
45162
|
toastManager.removeTask(taskId);
|
|
@@ -45121,7 +45179,7 @@ Session ID: ${sessionID}`;
|
|
|
45121
45179
|
let lastMsgCount = 0;
|
|
45122
45180
|
let stablePolls = 0;
|
|
45123
45181
|
while (Date.now() - pollStart < MAX_POLL_TIME_MS) {
|
|
45124
|
-
await new Promise((
|
|
45182
|
+
await new Promise((resolve10) => setTimeout(resolve10, POLL_INTERVAL_MS));
|
|
45125
45183
|
const asyncError = promptError;
|
|
45126
45184
|
if (asyncError) {
|
|
45127
45185
|
if (toastManager && taskId !== undefined) {
|
|
@@ -45210,7 +45268,6 @@ ${textContent || "(No text output)"}`;
|
|
|
45210
45268
|
|
|
45211
45269
|
// src/tools/sisyphus-task/index.ts
|
|
45212
45270
|
init_constants();
|
|
45213
|
-
|
|
45214
45271
|
// src/tools/index.ts
|
|
45215
45272
|
function createBackgroundTools(manager, client2) {
|
|
45216
45273
|
return {
|
|
@@ -45273,9 +45330,9 @@ class ConcurrencyManager {
|
|
|
45273
45330
|
this.counts.set(model, current + 1);
|
|
45274
45331
|
return;
|
|
45275
45332
|
}
|
|
45276
|
-
return new Promise((
|
|
45333
|
+
return new Promise((resolve10) => {
|
|
45277
45334
|
const queue = this.queues.get(model) ?? [];
|
|
45278
|
-
queue.push(
|
|
45335
|
+
queue.push(resolve10);
|
|
45279
45336
|
this.queues.set(model, queue);
|
|
45280
45337
|
});
|
|
45281
45338
|
}
|
|
@@ -47293,7 +47350,7 @@ class Protocol {
|
|
|
47293
47350
|
return;
|
|
47294
47351
|
}
|
|
47295
47352
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1000;
|
|
47296
|
-
await new Promise((
|
|
47353
|
+
await new Promise((resolve10) => setTimeout(resolve10, pollInterval));
|
|
47297
47354
|
options?.signal?.throwIfAborted();
|
|
47298
47355
|
}
|
|
47299
47356
|
} catch (error45) {
|
|
@@ -47305,7 +47362,7 @@ class Protocol {
|
|
|
47305
47362
|
}
|
|
47306
47363
|
request(request2, resultSchema, options) {
|
|
47307
47364
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
47308
|
-
return new Promise((
|
|
47365
|
+
return new Promise((resolve10, reject) => {
|
|
47309
47366
|
const earlyReject = (error45) => {
|
|
47310
47367
|
reject(error45);
|
|
47311
47368
|
};
|
|
@@ -47383,7 +47440,7 @@ class Protocol {
|
|
|
47383
47440
|
if (!parseResult.success) {
|
|
47384
47441
|
reject(parseResult.error);
|
|
47385
47442
|
} else {
|
|
47386
|
-
|
|
47443
|
+
resolve10(parseResult.data);
|
|
47387
47444
|
}
|
|
47388
47445
|
} catch (error45) {
|
|
47389
47446
|
reject(error45);
|
|
@@ -47574,12 +47631,12 @@ class Protocol {
|
|
|
47574
47631
|
interval = task.pollInterval;
|
|
47575
47632
|
}
|
|
47576
47633
|
} catch {}
|
|
47577
|
-
return new Promise((
|
|
47634
|
+
return new Promise((resolve10, reject) => {
|
|
47578
47635
|
if (signal.aborted) {
|
|
47579
47636
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
47580
47637
|
return;
|
|
47581
47638
|
}
|
|
47582
|
-
const timeoutId = setTimeout(
|
|
47639
|
+
const timeoutId = setTimeout(resolve10, interval);
|
|
47583
47640
|
signal.addEventListener("abort", () => {
|
|
47584
47641
|
clearTimeout(timeoutId);
|
|
47585
47642
|
reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -48356,7 +48413,7 @@ class StdioClientTransport {
|
|
|
48356
48413
|
if (this._process) {
|
|
48357
48414
|
throw new Error("StdioClientTransport already started! If using Client class, note that connect() calls start() automatically.");
|
|
48358
48415
|
}
|
|
48359
|
-
return new Promise((
|
|
48416
|
+
return new Promise((resolve10, reject) => {
|
|
48360
48417
|
this._process = import_cross_spawn.default(this._serverParams.command, this._serverParams.args ?? [], {
|
|
48361
48418
|
env: {
|
|
48362
48419
|
...getDefaultEnvironment(),
|
|
@@ -48372,7 +48429,7 @@ class StdioClientTransport {
|
|
|
48372
48429
|
this.onerror?.(error45);
|
|
48373
48430
|
});
|
|
48374
48431
|
this._process.on("spawn", () => {
|
|
48375
|
-
|
|
48432
|
+
resolve10();
|
|
48376
48433
|
});
|
|
48377
48434
|
this._process.on("close", (_code) => {
|
|
48378
48435
|
this._process = undefined;
|
|
@@ -48419,20 +48476,20 @@ class StdioClientTransport {
|
|
|
48419
48476
|
if (this._process) {
|
|
48420
48477
|
const processToClose = this._process;
|
|
48421
48478
|
this._process = undefined;
|
|
48422
|
-
const closePromise = new Promise((
|
|
48479
|
+
const closePromise = new Promise((resolve10) => {
|
|
48423
48480
|
processToClose.once("close", () => {
|
|
48424
|
-
|
|
48481
|
+
resolve10();
|
|
48425
48482
|
});
|
|
48426
48483
|
});
|
|
48427
48484
|
try {
|
|
48428
48485
|
processToClose.stdin?.end();
|
|
48429
48486
|
} catch {}
|
|
48430
|
-
await Promise.race([closePromise, new Promise((
|
|
48487
|
+
await Promise.race([closePromise, new Promise((resolve10) => setTimeout(resolve10, 2000).unref())]);
|
|
48431
48488
|
if (processToClose.exitCode === null) {
|
|
48432
48489
|
try {
|
|
48433
48490
|
processToClose.kill("SIGTERM");
|
|
48434
48491
|
} catch {}
|
|
48435
|
-
await Promise.race([closePromise, new Promise((
|
|
48492
|
+
await Promise.race([closePromise, new Promise((resolve10) => setTimeout(resolve10, 2000).unref())]);
|
|
48436
48493
|
}
|
|
48437
48494
|
if (processToClose.exitCode === null) {
|
|
48438
48495
|
try {
|
|
@@ -48443,15 +48500,15 @@ class StdioClientTransport {
|
|
|
48443
48500
|
this._readBuffer.clear();
|
|
48444
48501
|
}
|
|
48445
48502
|
send(message) {
|
|
48446
|
-
return new Promise((
|
|
48503
|
+
return new Promise((resolve10) => {
|
|
48447
48504
|
if (!this._process?.stdin) {
|
|
48448
48505
|
throw new Error("Not connected");
|
|
48449
48506
|
}
|
|
48450
48507
|
const json3 = serializeMessage(message);
|
|
48451
48508
|
if (this._process.stdin.write(json3)) {
|
|
48452
|
-
|
|
48509
|
+
resolve10();
|
|
48453
48510
|
} else {
|
|
48454
|
-
this._process.stdin.once("drain",
|
|
48511
|
+
this._process.stdin.once("drain", resolve10);
|
|
48455
48512
|
}
|
|
48456
48513
|
});
|
|
48457
48514
|
}
|
|
@@ -56044,7 +56101,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
56044
56101
|
isSisyphusEnabled: pluginConfig.sisyphus_agent?.disabled !== true,
|
|
56045
56102
|
autoUpdate: pluginConfig.auto_update ?? true
|
|
56046
56103
|
}) : null;
|
|
56047
|
-
const keywordDetector = isHookEnabled("keyword-detector") ? createKeywordDetectorHook(ctx) : null;
|
|
56104
|
+
const keywordDetector = isHookEnabled("keyword-detector") ? createKeywordDetectorHook(ctx, contextCollector) : null;
|
|
56048
56105
|
const contextInjector = createContextInjectorHook(contextCollector);
|
|
56049
56106
|
const contextInjectorMessagesTransform = createContextInjectorMessagesTransformHook(contextCollector);
|
|
56050
56107
|
const agentUsageReminder = isHookEnabled("agent-usage-reminder") ? createAgentUsageReminderHook(ctx) : null;
|
|
@@ -56136,8 +56193,8 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
56136
56193
|
interactive_bash
|
|
56137
56194
|
},
|
|
56138
56195
|
"chat.message": async (input, output) => {
|
|
56139
|
-
await claudeCodeHooks["chat.message"]?.(input, output);
|
|
56140
56196
|
await keywordDetector?.["chat.message"]?.(input, output);
|
|
56197
|
+
await claudeCodeHooks["chat.message"]?.(input, output);
|
|
56141
56198
|
await contextInjector["chat.message"]?.(input, output);
|
|
56142
56199
|
await autoSlashCommand?.["chat.message"]?.(input, output);
|
|
56143
56200
|
await startWork?.["chat.message"]?.(input, output);
|
|
@@ -56208,6 +56265,7 @@ var OhMyOpenCodePlugin = async (ctx) => {
|
|
|
56208
56265
|
}
|
|
56209
56266
|
if (sessionInfo?.id) {
|
|
56210
56267
|
await skillMcpManager.disconnectSession(sessionInfo.id);
|
|
56268
|
+
await lspManager.cleanupTempDirectoryClients();
|
|
56211
56269
|
}
|
|
56212
56270
|
}
|
|
56213
56271
|
if (event.type === "session.error") {
|