oh-my-opencode-slim 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja-JP.md +108 -114
- package/README.ko-KR.md +135 -118
- package/README.md +91 -146
- package/README.zh-CN.md +107 -114
- package/dist/cli/index.js +8 -14
- package/dist/cli/providers.d.ts +11 -4
- package/dist/config/constants.d.ts +1 -1
- package/dist/hooks/phase-reminder/index.d.ts +6 -2
- package/dist/hooks/post-file-tool-nudge/index.d.ts +3 -5
- package/dist/hooks/session-lifecycle.d.ts +0 -1
- package/dist/hooks/types.d.ts +1 -0
- package/dist/index.js +110 -101
- package/dist/multiplexer/zellij/index.d.ts +1 -1
- package/dist/tui.js +1 -7
- package/dist/utils/background-job-board.d.ts +1 -1
- package/package.json +1 -1
- package/src/skills/codemap.md +0 -2
- package/src/skills/verification-planning/SKILL.md +2 -3
- package/src/skills/release-smoke-test/SKILL.md +0 -159
package/dist/index.js
CHANGED
|
@@ -18381,12 +18381,6 @@ var CUSTOM_SKILLS = [
|
|
|
18381
18381
|
allowedAgents: ["orchestrator"],
|
|
18382
18382
|
sourcePath: "src/skills/oh-my-opencode-slim"
|
|
18383
18383
|
},
|
|
18384
|
-
{
|
|
18385
|
-
name: "release-smoke-test",
|
|
18386
|
-
description: "Validate packed release candidates and bugfixes before public publish",
|
|
18387
|
-
allowedAgents: ["orchestrator"],
|
|
18388
|
-
sourcePath: "src/skills/release-smoke-test"
|
|
18389
|
-
},
|
|
18390
18384
|
{
|
|
18391
18385
|
name: "worktrees",
|
|
18392
18386
|
description: "Manage Git worktrees as OMO safe isolated coding lanes for complex/risky/parallel work",
|
|
@@ -18502,7 +18496,7 @@ var DEFAULT_MODELS = {
|
|
|
18502
18496
|
var POLL_INTERVAL_BACKGROUND_MS = 2000;
|
|
18503
18497
|
var MAX_POLL_TIME_MS = 5 * 60 * 1000;
|
|
18504
18498
|
var DEFAULT_MAX_SUBAGENT_DEPTH = 3;
|
|
18505
|
-
var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion → reconcile terminal results → verify. Do not poll running jobs, consume running-job output, or advance dependent work. !END!`;
|
|
18499
|
+
var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: First choose the lightest workflow that fits the work. If direct execution is justified, complete it and verify proportionately. Otherwise: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion → reconcile terminal results → verify. Do not poll running jobs, consume running-job output, or advance dependent work. !END!`;
|
|
18506
18500
|
function formatSystemReminder(text) {
|
|
18507
18501
|
return `<system-reminder>
|
|
18508
18502
|
${text}
|
|
@@ -19257,7 +19251,8 @@ var AGENT_DESCRIPTIONS = {
|
|
|
19257
19251
|
- Permissions: read_files
|
|
19258
19252
|
- Stats: 5x better decision maker, problem solver, investigator than orchestrator, 0.8x speed of orchestrator, same cost.
|
|
19259
19253
|
- Capabilities: Deep architectural reasoning, system-level trade-offs, complex debugging, code review, simplification, maintainability review
|
|
19260
|
-
- **Delegate when:** Major architectural decisions with long-term impact • Problems persisting after 2+ fix attempts • High-risk multi-system refactors • Costly trade-offs (performance vs maintainability) • Complex debugging with unclear root cause • Security/scalability/data integrity decisions • Genuinely uncertain and cost of wrong choice is high •
|
|
19254
|
+
- **Delegate when:** Major architectural decisions with long-term impact • Problems persisting after 2+ fix attempts • High-risk multi-system refactors • Costly trade-offs (performance vs maintainability) • Complex debugging with unclear root cause • Security/scalability/data integrity decisions • Genuinely uncertain and cost of wrong choice is high • Code needs simplification or YAGNI scrutiny
|
|
19255
|
+
- **Review use:** Oracle is an escalation, not a default verification step. Request independent Oracle review only when its analysis is expected to materially reduce risk or uncertainty.
|
|
19261
19256
|
- **Don't delegate when:** Routine decisions you're confident about • First bug fix attempt • Straightforward trade-offs • Tactical "how" vs strategic "should" • Time-sensitive good-enough decisions • Quick research/testing can answer
|
|
19262
19257
|
- **Rule of thumb:** Need senior architect review? → @oracle. Need code review or simplification? → @oracle. Routine coordination or final synthesis? → handle directly.`,
|
|
19263
19258
|
designer: `@designer
|
|
@@ -19323,6 +19318,10 @@ function buildOrchestratorPrompt(disabledAgents) {
|
|
|
19323
19318
|
return `<Role>
|
|
19324
19319
|
You are a workflow manager for coding work. Your job is to plan, schedule, delegate, monitor, reconcile, and verify specialist-agent work. You are not the default implementation worker.
|
|
19325
19320
|
|
|
19321
|
+
For non-trivial coding work, identify separable lanes first and delegate bounded work to the appropriate specialist. Do not perform multi-step implementation serially when a suitable specialist is available.
|
|
19322
|
+
|
|
19323
|
+
Handle work directly only when it is one isolated, clear, low-risk action and delegation overhead exceeds doing it yourself.
|
|
19324
|
+
|
|
19326
19325
|
Optimize for quality, speed, cost, and reliability by dispatching the right specialist lanes, tracking background task state, and integrating terminal results into one coherent outcome.
|
|
19327
19326
|
You have perfect understanding of agent's context management, understand well the cost of building content and reusing context of existing agents when it's best or when it's best to spawn a new agent.
|
|
19328
19327
|
</Role>
|
|
@@ -19343,12 +19342,17 @@ Evaluate approach by: quality, speed and cost.
|
|
|
19343
19342
|
Choose the path that optimizes all four.
|
|
19344
19343
|
|
|
19345
19344
|
## 3. Delegation Check
|
|
19346
|
-
Review available agents and lane rules.
|
|
19345
|
+
Review available agents and lane rules. Before beginning non-trivial work, identify which parts can proceed independently.
|
|
19346
|
+
|
|
19347
|
+
**Routing threshold:**
|
|
19348
|
+
- Handle directly only for one isolated, clear, low-risk action where delegation would cost more than execution.
|
|
19349
|
+
- For multi-step implementation, broad discovery, external research, visual work, or complex debugging, delegate to the suitable specialist.
|
|
19350
|
+
- If two or more parts can proceed independently, dispatch them in parallel before starting dependent work.
|
|
19351
|
+
- Do not delegate merely because an agent exists. Do not keep substantive work entirely in the orchestrator merely because each individual step seems easy.
|
|
19347
19352
|
|
|
19348
19353
|
**Dispatch efficiency:**
|
|
19349
19354
|
- Reference paths/lines, don't paste files (\`src/app.ts:42\` not full contents)
|
|
19350
19355
|
- Brief user on delegation goal before each call
|
|
19351
|
-
- For trivial conversational answers or tiny mechanical edits, direct execution is allowed when scheduling overhead would clearly dominate
|
|
19352
19356
|
- Record task IDs, state, and advisory ownership/dependency labels
|
|
19353
19357
|
- Do not immediately wait after spawning independent background tasks unless the next step truly depends on their result
|
|
19354
19358
|
- Reconcile results, resolve conflicts, and gate dependent lanes
|
|
@@ -19356,7 +19360,7 @@ Review available agents and lane rules.
|
|
|
19356
19360
|
${WRITABLE_FILE_OPERATIONS_RULES}
|
|
19357
19361
|
|
|
19358
19362
|
## 4. Plan and Parallelize
|
|
19359
|
-
|
|
19363
|
+
When the routing threshold calls for delegation, build a short work graph before dispatching:
|
|
19360
19364
|
- Independent lanes that can run now
|
|
19361
19365
|
- Dependency-ordered lanes that must wait
|
|
19362
19366
|
- Advisory ownership for write-capable lanes
|
|
@@ -19374,7 +19378,7 @@ Balance: respect dependencies, avoid parallelizing what must be sequential, and
|
|
|
19374
19378
|
|
|
19375
19379
|
### Background Task Discipline
|
|
19376
19380
|
- Prefer \`task(..., background: true)\` for delegated work that can run independently.
|
|
19377
|
-
-
|
|
19381
|
+
- For work already chosen for delegation, launch independent specialist lanes in the background so the orchestrator stays unblocked and can reconcile results when they return.
|
|
19378
19382
|
- Track each task's specialist, objective, task/session ID, and file/topic ownership.
|
|
19379
19383
|
- Continue orchestration only on non-overlapping work; otherwise briefly report what was launched and stop.
|
|
19380
19384
|
- Before local edits or another writer task, compare against running task scopes.
|
|
@@ -19401,11 +19405,12 @@ Balance: respect dependencies, avoid parallelizing what must be sequential, and
|
|
|
19401
19405
|
|
|
19402
19406
|
## 6. Verify
|
|
19403
19407
|
- Define the observable success criteria from the user's request.
|
|
19404
|
-
-
|
|
19405
|
-
-
|
|
19406
|
-
-
|
|
19407
|
-
-
|
|
19408
|
-
-
|
|
19408
|
+
- Choose the minimum verification that produces meaningful evidence for the change's scope, risk, uncertainty, and potential impact.
|
|
19409
|
+
- Start with the narrowest relevant validation. Broaden verification only when integration scope, uncertainty, risk, or a failed focused check justifies it.
|
|
19410
|
+
- Do not run project-wide checks by habit or merely because files changed.
|
|
19411
|
+
- Do not treat verification as a fixed checklist; select evidence that can actually confirm the requested behavior.
|
|
19412
|
+
- Request independent review only when its expected risk reduction justifies its coordination cost.
|
|
19413
|
+
- Report what was verified and any material remaining uncertainty.
|
|
19409
19414
|
|
|
19410
19415
|
</Workflow>
|
|
19411
19416
|
|
|
@@ -19421,6 +19426,8 @@ Balance: respect dependencies, avoid parallelizing what must be sequential, and
|
|
|
19421
19426
|
- Don't summarize what you did unless asked
|
|
19422
19427
|
- Don't explain code unless asked
|
|
19423
19428
|
- One-word answers are fine when appropriate
|
|
19429
|
+
- Default to the minimum response that fully resolves the user's request; expand only when detail is necessary or the user asks for it.
|
|
19430
|
+
- Do not restate the user's request or narrate routine work.
|
|
19424
19431
|
- Brief delegation notices: "Checking docs via @librarian..." not "I'm going to delegate to @librarian because..."
|
|
19425
19432
|
|
|
19426
19433
|
## No Flattery
|
|
@@ -25082,7 +25089,7 @@ class BackgroundJobBoard {
|
|
|
25082
25089
|
const timeouts = job.timeoutCount ?? 0;
|
|
25083
25090
|
return errors >= threshold || timeouts >= threshold;
|
|
25084
25091
|
}
|
|
25085
|
-
formatForPrompt(parentSessionID,
|
|
25092
|
+
formatForPrompt(parentSessionID, _now) {
|
|
25086
25093
|
const active = this.list(parentSessionID).filter((job) => job.state === "running" || job.terminalUnreconciled);
|
|
25087
25094
|
const reusable = this.list(parentSessionID).filter(isReusable);
|
|
25088
25095
|
if (active.length === 0 && reusable.length === 0)
|
|
@@ -25096,7 +25103,7 @@ class BackgroundJobBoard {
|
|
|
25096
25103
|
"Cancelled or errored sessions are not reusable.",
|
|
25097
25104
|
"",
|
|
25098
25105
|
"#### Active / Unreconciled",
|
|
25099
|
-
...active.length > 0 ? active.map(
|
|
25106
|
+
...active.length > 0 ? active.map(formatJob) : ["- none"],
|
|
25100
25107
|
"",
|
|
25101
25108
|
"#### Reusable Sessions",
|
|
25102
25109
|
...reusable.length > 0 ? reusable.map((job) => this.formatReusableJob(job)) : ["- none"]
|
|
@@ -25173,11 +25180,10 @@ function formatContextFiles(files, maxFiles) {
|
|
|
25173
25180
|
function normalizeWhitespace(value) {
|
|
25174
25181
|
return value.replace(/\s+/g, " ").trim();
|
|
25175
25182
|
}
|
|
25176
|
-
function formatJob(job
|
|
25177
|
-
const ageMs = now - job.lastLaunchedAt;
|
|
25183
|
+
function formatJob(job) {
|
|
25178
25184
|
const isResume = job.lastLaunchedAt !== job.launchedAt;
|
|
25179
|
-
const
|
|
25180
|
-
const status = job.terminalUnreconciled ? `${job.state}, unreconciled` : job.statusUncertain ? `${job.state}, status uncertain` : job.timedOut ? `${job.state}, timed out` :
|
|
25185
|
+
const displayState = job.state === "running" && isResume ? "running [resumed]" : job.state;
|
|
25186
|
+
const status = job.terminalUnreconciled ? `${job.state}, unreconciled` : job.statusUncertain ? `${job.state}, status uncertain` : job.timedOut ? `${job.state}, timed out` : displayState;
|
|
25181
25187
|
const lines = [
|
|
25182
25188
|
`- ${promptSafe(job.alias)} / ${promptSafe(job.taskID)} / ${promptSafe(job.agent)} / ${promptSafe(status)}`,
|
|
25183
25189
|
` Objective: ${promptSafe(job.objective || job.description)}`
|
|
@@ -25577,6 +25583,15 @@ function isMessageWithParts(message) {
|
|
|
25577
25583
|
function isUserMessageWithParts(message) {
|
|
25578
25584
|
return isMessageWithParts(message) && message.info.role === "user";
|
|
25579
25585
|
}
|
|
25586
|
+
function findLatestUserMessage(messages) {
|
|
25587
|
+
for (let index = messages.length - 1;index >= 0; index--) {
|
|
25588
|
+
const message = messages[index];
|
|
25589
|
+
if (isUserMessageWithParts(message)) {
|
|
25590
|
+
return message;
|
|
25591
|
+
}
|
|
25592
|
+
}
|
|
25593
|
+
return;
|
|
25594
|
+
}
|
|
25580
25595
|
|
|
25581
25596
|
// src/hooks/filter-available-skills/index.ts
|
|
25582
25597
|
var AVAILABLE_SKILLS_BLOCK_REGEX = /<available_skills>\s*([\s\S]*?)\s*<\/available_skills>/g;
|
|
@@ -26391,33 +26406,19 @@ function createLoopCommandHook() {
|
|
|
26391
26406
|
}
|
|
26392
26407
|
// src/hooks/phase-reminder/index.ts
|
|
26393
26408
|
var PHASE_REMINDER_METADATA_KEY = "oh-my-opencode-slim.phaseReminder";
|
|
26394
|
-
function
|
|
26409
|
+
function hasPhaseReminder(part) {
|
|
26410
|
+
return part.synthetic === true && isRecord2(part.metadata) && part.metadata[PHASE_REMINDER_METADATA_KEY] === true;
|
|
26411
|
+
}
|
|
26412
|
+
function createPhaseReminderHook(options = {}) {
|
|
26395
26413
|
return {
|
|
26396
26414
|
"experimental.chat.messages.transform": async (_input, output) => {
|
|
26397
26415
|
const messages = Array.isArray(output.messages) ? output.messages : [];
|
|
26398
|
-
|
|
26399
|
-
|
|
26400
|
-
}
|
|
26401
|
-
let lastUserMessageIndex = -1;
|
|
26402
|
-
for (let i = messages.length - 1;i >= 0; i--) {
|
|
26403
|
-
if (isUserMessageWithParts(messages[i])) {
|
|
26404
|
-
lastUserMessageIndex = i;
|
|
26405
|
-
break;
|
|
26406
|
-
}
|
|
26407
|
-
}
|
|
26408
|
-
if (lastUserMessageIndex === -1) {
|
|
26416
|
+
const lastUserMessage = findLatestUserMessage(messages);
|
|
26417
|
+
if (!lastUserMessage) {
|
|
26409
26418
|
return;
|
|
26410
26419
|
}
|
|
26411
|
-
const
|
|
26412
|
-
if (!
|
|
26413
|
-
return;
|
|
26414
|
-
}
|
|
26415
|
-
const agent = lastUserMessage.info.agent;
|
|
26416
|
-
if (agent && agent !== "orchestrator") {
|
|
26417
|
-
return;
|
|
26418
|
-
}
|
|
26419
|
-
const sessionId = lastUserMessage?.info?.sessionID;
|
|
26420
|
-
if (sessionId && coordinator?.hasPendingSession(sessionId)) {
|
|
26420
|
+
const { agent, sessionID } = lastUserMessage.info;
|
|
26421
|
+
if (agent !== "orchestrator" || !sessionID || options.shouldInject && !options.shouldInject(sessionID)) {
|
|
26421
26422
|
return;
|
|
26422
26423
|
}
|
|
26423
26424
|
const textPartIndex = lastUserMessage.parts.findIndex((p) => p.type === "text" && p.text !== undefined);
|
|
@@ -26428,7 +26429,7 @@ function createPhaseReminderHook(coordinator) {
|
|
|
26428
26429
|
if (isInternalInitiatorPart(originalPart)) {
|
|
26429
26430
|
return;
|
|
26430
26431
|
}
|
|
26431
|
-
if (lastUserMessage.parts.some(
|
|
26432
|
+
if (lastUserMessage.parts.some(hasPhaseReminder)) {
|
|
26432
26433
|
return;
|
|
26433
26434
|
}
|
|
26434
26435
|
lastUserMessage.parts.push({
|
|
@@ -26453,17 +26454,43 @@ function createPostFileToolNudgeHook(options = {}) {
|
|
|
26453
26454
|
return;
|
|
26454
26455
|
coordinator?.markPending(input.sessionID);
|
|
26455
26456
|
},
|
|
26456
|
-
"experimental.chat.
|
|
26457
|
-
if (!
|
|
26457
|
+
"experimental.chat.messages.transform": async (_input, output) => {
|
|
26458
|
+
if (!coordinator) {
|
|
26458
26459
|
return;
|
|
26459
26460
|
}
|
|
26460
|
-
|
|
26461
|
+
const messages = Array.isArray(output.messages) ? output.messages : [];
|
|
26462
|
+
const eligible = getEligibleMessage(findLatestUserMessage(messages));
|
|
26463
|
+
if (!eligible) {
|
|
26464
|
+
return;
|
|
26465
|
+
}
|
|
26466
|
+
const { message, sessionID } = eligible;
|
|
26467
|
+
const hasReminder = message.parts.some(hasPhaseReminder);
|
|
26468
|
+
if (options.shouldInject && !options.shouldInject(sessionID)) {
|
|
26461
26469
|
return;
|
|
26462
26470
|
}
|
|
26463
|
-
|
|
26471
|
+
if (!coordinator.consumePending(sessionID))
|
|
26472
|
+
return;
|
|
26473
|
+
if (hasReminder)
|
|
26474
|
+
return;
|
|
26475
|
+
message.parts.push({
|
|
26476
|
+
type: "text",
|
|
26477
|
+
synthetic: true,
|
|
26478
|
+
text: PHASE_REMINDER,
|
|
26479
|
+
metadata: { [PHASE_REMINDER_METADATA_KEY]: true }
|
|
26480
|
+
});
|
|
26464
26481
|
}
|
|
26465
26482
|
};
|
|
26466
26483
|
}
|
|
26484
|
+
function getEligibleMessage(message) {
|
|
26485
|
+
if (!isUserMessageWithParts(message) || !message.info.sessionID || message.info.agent !== "orchestrator") {
|
|
26486
|
+
return;
|
|
26487
|
+
}
|
|
26488
|
+
const textPart = message.parts.find((part) => part.type === "text" && part.text !== undefined);
|
|
26489
|
+
if (!textPart || isInternalInitiatorPart(textPart)) {
|
|
26490
|
+
return;
|
|
26491
|
+
}
|
|
26492
|
+
return { message, sessionID: message.info.sessionID };
|
|
26493
|
+
}
|
|
26467
26494
|
// src/hooks/reflect/index.ts
|
|
26468
26495
|
var COMMAND_NAME3 = "reflect";
|
|
26469
26496
|
function activationPrompt3(focus, isSessionMode = false, lastN = 50) {
|
|
@@ -26524,7 +26551,6 @@ function createReflectCommandHook() {
|
|
|
26524
26551
|
class SessionLifecycle {
|
|
26525
26552
|
#cleanupCallbacks = [];
|
|
26526
26553
|
#pendingSessionIds = new Set;
|
|
26527
|
-
#everPendingSessionIds = new Set;
|
|
26528
26554
|
#log;
|
|
26529
26555
|
constructor(log2) {
|
|
26530
26556
|
this.#log = log2;
|
|
@@ -26543,19 +26569,14 @@ class SessionLifecycle {
|
|
|
26543
26569
|
}
|
|
26544
26570
|
markPending(sessionId) {
|
|
26545
26571
|
this.#pendingSessionIds.add(sessionId);
|
|
26546
|
-
this.#everPendingSessionIds.add(sessionId);
|
|
26547
26572
|
}
|
|
26548
26573
|
consumePending(sessionId) {
|
|
26549
26574
|
const had = this.#pendingSessionIds.has(sessionId);
|
|
26550
26575
|
this.#pendingSessionIds.delete(sessionId);
|
|
26551
26576
|
return had;
|
|
26552
26577
|
}
|
|
26553
|
-
hasPendingSession(sessionId) {
|
|
26554
|
-
return this.#everPendingSessionIds.has(sessionId) && !this.#pendingSessionIds.has(sessionId);
|
|
26555
|
-
}
|
|
26556
26578
|
clearSession(sessionId) {
|
|
26557
26579
|
this.#pendingSessionIds.delete(sessionId);
|
|
26558
|
-
this.#everPendingSessionIds.delete(sessionId);
|
|
26559
26580
|
}
|
|
26560
26581
|
}
|
|
26561
26582
|
// src/hooks/task-session-manager/pending-call-tracker.ts
|
|
@@ -33327,6 +33348,7 @@ class ZellijMultiplexer {
|
|
|
33327
33348
|
this.firstPaneUsed = true;
|
|
33328
33349
|
return { success: true, paneId: this.firstPaneId };
|
|
33329
33350
|
}
|
|
33351
|
+
this.firstPaneUsed = true;
|
|
33330
33352
|
}
|
|
33331
33353
|
return await this.createPaneInAgentTab(zellij, sessionId, serverUrl, directory, description);
|
|
33332
33354
|
} catch {
|
|
@@ -33456,13 +33478,12 @@ class ZellijMultiplexer {
|
|
|
33456
33478
|
try {
|
|
33457
33479
|
const existingTab = await this.findTabByName(zellij, "opencode-agents");
|
|
33458
33480
|
if (existingTab) {
|
|
33459
|
-
const
|
|
33481
|
+
const firstPane2 = await this.getFirstPaneInTab(zellij, existingTab.tabId);
|
|
33460
33482
|
return {
|
|
33461
33483
|
tabId: existingTab.tabId,
|
|
33462
|
-
firstPaneId:
|
|
33484
|
+
firstPaneId: firstPane2
|
|
33463
33485
|
};
|
|
33464
33486
|
}
|
|
33465
|
-
const beforePanes = await this.listPanes(zellij);
|
|
33466
33487
|
const createProc = crossSpawn([zellij, "action", "new-tab", "--name", "opencode-agents"], { stdout: "pipe", stderr: "pipe" });
|
|
33467
33488
|
const createExit = await createProc.exited;
|
|
33468
33489
|
if (createExit !== 0)
|
|
@@ -33470,27 +33491,33 @@ class ZellijMultiplexer {
|
|
|
33470
33491
|
const newTab = await this.findTabByName(zellij, "opencode-agents");
|
|
33471
33492
|
if (!newTab)
|
|
33472
33493
|
return null;
|
|
33473
|
-
const
|
|
33474
|
-
|
|
33475
|
-
|
|
33494
|
+
const firstPane = await this.getFirstPaneInTab(zellij, newTab.tabId);
|
|
33495
|
+
return { tabId: newTab.tabId, firstPaneId: firstPane };
|
|
33496
|
+
} catch {
|
|
33497
|
+
return null;
|
|
33498
|
+
}
|
|
33499
|
+
}
|
|
33500
|
+
async listPanesJson(zellij) {
|
|
33501
|
+
try {
|
|
33502
|
+
const proc = crossSpawn([zellij, "action", "list-panes", "--json", "--tab", "--all"], { stdout: "pipe", stderr: "pipe" });
|
|
33503
|
+
if (await proc.exited !== 0)
|
|
33504
|
+
return null;
|
|
33505
|
+
const stdout = await proc.stdout();
|
|
33506
|
+
return JSON.parse(stdout);
|
|
33476
33507
|
} catch {
|
|
33477
33508
|
return null;
|
|
33478
33509
|
}
|
|
33479
33510
|
}
|
|
33480
33511
|
async getFirstPaneInTab(zellij, tabId) {
|
|
33481
|
-
|
|
33482
|
-
|
|
33483
|
-
|
|
33484
|
-
|
|
33485
|
-
|
|
33486
|
-
|
|
33487
|
-
|
|
33488
|
-
|
|
33489
|
-
stdout: "ignore",
|
|
33490
|
-
stderr: "ignore"
|
|
33491
|
-
}).exited;
|
|
33512
|
+
try {
|
|
33513
|
+
const panes = await this.listPanesJson(zellij);
|
|
33514
|
+
if (!panes)
|
|
33515
|
+
return null;
|
|
33516
|
+
const pane = panes.find((candidate) => !candidate.is_plugin && candidate.tab_id === Number(tabId));
|
|
33517
|
+
return pane ? `terminal_${pane.id}` : null;
|
|
33518
|
+
} catch {
|
|
33519
|
+
return null;
|
|
33492
33520
|
}
|
|
33493
|
-
return panes[0] || null;
|
|
33494
33521
|
}
|
|
33495
33522
|
async findTabByName(zellij, name) {
|
|
33496
33523
|
try {
|
|
@@ -33560,22 +33587,6 @@ class ZellijMultiplexer {
|
|
|
33560
33587
|
return null;
|
|
33561
33588
|
}
|
|
33562
33589
|
}
|
|
33563
|
-
async listPanes(zellij) {
|
|
33564
|
-
try {
|
|
33565
|
-
const proc = crossSpawn([zellij, "action", "list-panes"], {
|
|
33566
|
-
stdout: "pipe",
|
|
33567
|
-
stderr: "pipe"
|
|
33568
|
-
});
|
|
33569
|
-
const exitCode = await proc.exited;
|
|
33570
|
-
if (exitCode !== 0)
|
|
33571
|
-
return [];
|
|
33572
|
-
const stdout = await proc.stdout();
|
|
33573
|
-
return stdout.split(`
|
|
33574
|
-
`).slice(1).map((line) => line.trim().split(/\s+/)[0]).filter((id) => id?.startsWith("terminal_"));
|
|
33575
|
-
} catch {
|
|
33576
|
-
return [];
|
|
33577
|
-
}
|
|
33578
|
-
}
|
|
33579
33590
|
async closePane(paneId) {
|
|
33580
33591
|
const zellij = await this.getBinary();
|
|
33581
33592
|
return gracefulClosePane(zellij, paneId, {
|
|
@@ -33607,14 +33618,9 @@ class ZellijMultiplexer {
|
|
|
33607
33618
|
}
|
|
33608
33619
|
async findTabIdForPane(zellij, paneId) {
|
|
33609
33620
|
try {
|
|
33610
|
-
const
|
|
33611
|
-
|
|
33612
|
-
stderr: "pipe"
|
|
33613
|
-
});
|
|
33614
|
-
if (await proc.exited !== 0)
|
|
33621
|
+
const panes = await this.listPanesJson(zellij);
|
|
33622
|
+
if (!panes)
|
|
33615
33623
|
return null;
|
|
33616
|
-
const stdout = await proc.stdout();
|
|
33617
|
-
const panes = JSON.parse(stdout);
|
|
33618
33624
|
const normalizedPaneId = normalizePaneId(paneId);
|
|
33619
33625
|
const pane = panes.find((candidate) => !candidate.is_plugin && String(candidate.id) === normalizedPaneId);
|
|
33620
33626
|
return pane?.tab_id === undefined ? null : String(pane.tab_id);
|
|
@@ -39058,10 +39064,13 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
39058
39064
|
}
|
|
39059
39065
|
};
|
|
39060
39066
|
};
|
|
39061
|
-
|
|
39067
|
+
const shouldInjectOrchestratorReminder = (sessionID) => sessionAgentMap.get(sessionID) === "orchestrator";
|
|
39068
|
+
phaseReminder = createPhaseReminderHook({
|
|
39069
|
+
shouldInject: shouldInjectOrchestratorReminder
|
|
39070
|
+
});
|
|
39062
39071
|
filterAvailableSkills = createFilterAvailableSkillsHook(ctx, config);
|
|
39063
39072
|
postFileToolNudge = createPostFileToolNudgeHook({
|
|
39064
|
-
shouldInject:
|
|
39073
|
+
shouldInject: shouldInjectOrchestratorReminder,
|
|
39065
39074
|
coordinator: sessionLifecycle
|
|
39066
39075
|
});
|
|
39067
39076
|
delegateTaskRetry = createDelegateTaskRetryHook(ctx);
|
|
@@ -39466,7 +39475,6 @@ var OhMyOpenCodeLite = async (ctx) => {
|
|
|
39466
39475
|
${output.system[0]}` : "");
|
|
39467
39476
|
}
|
|
39468
39477
|
}
|
|
39469
|
-
await postFileToolNudge["experimental.chat.system.transform"](input, output);
|
|
39470
39478
|
collapseSystemInPlace(output.system);
|
|
39471
39479
|
},
|
|
39472
39480
|
"experimental.chat.messages.transform": async (input, output) => {
|
|
@@ -39492,9 +39500,10 @@ ${output.system[0]}` : "");
|
|
|
39492
39500
|
disabledAgents,
|
|
39493
39501
|
log
|
|
39494
39502
|
});
|
|
39503
|
+
await taskSessionManagerHook["experimental.chat.messages.transform"](input, typedOutput);
|
|
39504
|
+
await postFileToolNudge["experimental.chat.messages.transform"](input, typedOutput);
|
|
39495
39505
|
await phaseReminder["experimental.chat.messages.transform"](input, typedOutput);
|
|
39496
39506
|
await filterAvailableSkills["experimental.chat.messages.transform"](input, typedOutput);
|
|
39497
|
-
await taskSessionManagerHook["experimental.chat.messages.transform"](input, typedOutput);
|
|
39498
39507
|
},
|
|
39499
39508
|
"tool.execute.after": async (input, output) => {
|
|
39500
39509
|
await postFileToolNudgeAfter(input, output);
|
|
@@ -32,11 +32,11 @@ export declare class ZellijMultiplexer implements Multiplexer {
|
|
|
32
32
|
private createPaneInAgentTab;
|
|
33
33
|
private runInPane;
|
|
34
34
|
private ensureAgentTab;
|
|
35
|
+
private listPanesJson;
|
|
35
36
|
private getFirstPaneInTab;
|
|
36
37
|
private findTabByName;
|
|
37
38
|
private findTabByNameText;
|
|
38
39
|
private getCurrentTabId;
|
|
39
|
-
private listPanes;
|
|
40
40
|
closePane(paneId: string): Promise<boolean>;
|
|
41
41
|
applyLayout(_layout: MultiplexerLayout, _mainPaneSize: number): Promise<void>;
|
|
42
42
|
private directionArgs;
|
package/dist/tui.js
CHANGED
|
@@ -130,7 +130,7 @@ var DEFAULT_MODELS = {
|
|
|
130
130
|
var POLL_INTERVAL_BACKGROUND_MS = 2000;
|
|
131
131
|
var MAX_POLL_TIME_MS = 5 * 60 * 1000;
|
|
132
132
|
var DEFAULT_MAX_SUBAGENT_DEPTH = 3;
|
|
133
|
-
var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion → reconcile terminal results → verify. Do not poll running jobs, consume running-job output, or advance dependent work. !END!`;
|
|
133
|
+
var PHASE_REMINDER_TEXT = `!IMPORTANT! Scheduler workflow: First choose the lightest workflow that fits the work. If direct execution is justified, complete it and verify proportionately. Otherwise: plan lanes/dependencies → dispatch background specialists → track task IDs → wait for hook-driven completion → reconcile terminal results → verify. Do not poll running jobs, consume running-job output, or advance dependent work. !END!`;
|
|
134
134
|
function formatSystemReminder(text) {
|
|
135
135
|
return `<system-reminder>
|
|
136
136
|
${text}
|
|
@@ -582,12 +582,6 @@ var CUSTOM_SKILLS = [
|
|
|
582
582
|
allowedAgents: ["orchestrator"],
|
|
583
583
|
sourcePath: "src/skills/oh-my-opencode-slim"
|
|
584
584
|
},
|
|
585
|
-
{
|
|
586
|
-
name: "release-smoke-test",
|
|
587
|
-
description: "Validate packed release candidates and bugfixes before public publish",
|
|
588
|
-
allowedAgents: ["orchestrator"],
|
|
589
|
-
sourcePath: "src/skills/release-smoke-test"
|
|
590
|
-
},
|
|
591
585
|
{
|
|
592
586
|
name: "worktrees",
|
|
593
587
|
description: "Manage Git worktrees as OMO safe isolated coding lanes for complex/risky/parallel work",
|
|
@@ -95,7 +95,7 @@ export declare class BackgroundJobBoard implements BackgroundJobStore {
|
|
|
95
95
|
hasRunning(parentSessionID: string): boolean;
|
|
96
96
|
hasTerminalUnreconciled(parentSessionID: string): boolean;
|
|
97
97
|
hasConvergenceSignals(taskID: string, threshold?: number): boolean;
|
|
98
|
-
formatForPrompt(parentSessionID: string,
|
|
98
|
+
formatForPrompt(parentSessionID: string, _now?: number): string | undefined;
|
|
99
99
|
clearParent(parentSessionID: string): void;
|
|
100
100
|
drop(taskID: string): void;
|
|
101
101
|
deferIfRunning(_sessionId: string): boolean;
|
package/package.json
CHANGED
package/src/skills/codemap.md
CHANGED
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
| `deepwork/` | Orchestrator-only | Heavy coding sessions, multi-phase implementation, and risky refactors |
|
|
24
24
|
| `verification-planning/` | Orchestrator-only | Project-specific evidence planning and verification affordances before non-trivial implementation |
|
|
25
25
|
| `reflect/` | Orchestrator-only | Learning from repeated work and suggesting reusable improvements |
|
|
26
|
-
| `release-smoke-test/` | Orchestrator-only | Packed release-candidate and bugfix validation |
|
|
27
26
|
| `worktrees/` | Orchestrator-only | Safe Git worktree lanes for parallel, risky, or isolated work |
|
|
28
27
|
| `oh-my-opencode-slim/` | Orchestrator-only | Plugin configuration and self-improvement guidance |
|
|
29
28
|
|
|
@@ -60,7 +59,6 @@
|
|
|
60
59
|
- `src/skills/deepwork/SKILL.md`
|
|
61
60
|
- `src/skills/verification-planning/SKILL.md`
|
|
62
61
|
- `src/skills/reflect/SKILL.md`
|
|
63
|
-
- `src/skills/release-smoke-test/SKILL.md`
|
|
64
62
|
- `src/skills/worktrees/SKILL.md`
|
|
65
63
|
- `src/skills/oh-my-opencode-slim/SKILL.md`
|
|
66
64
|
- `package.json` scripts (`verify:release`, `build`) rely on these assets to ensure install-time skill availability
|
|
@@ -98,6 +98,5 @@ what remains outside its reach.
|
|
|
98
98
|
## Scope
|
|
99
99
|
|
|
100
100
|
Use this skill proportionately. Small mechanical changes can follow ordinary
|
|
101
|
-
project checks directly. For
|
|
102
|
-
|
|
103
|
-
evidence path that later work follows.
|
|
101
|
+
project checks directly. For larger multi-phase work, let this skill establish
|
|
102
|
+
the evidence path that later work follows.
|