oh-my-opencode 5.1.13 → 5.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +18 -17
- package/dist/cli-node/index.js +18 -17
- package/dist/index.js +16 -16
- package/dist/skills/browser/SKILL.md +26 -2
- package/dist/skills/browser/references/commands.md +10 -1
- package/dist/skills/browser/references/install.md +7 -0
- package/dist/skills/browser/runtime/omowright/manifest.json +1 -1
- package/dist/skills/browser/scripts/browser-engine-guard.mjs +506 -0
- package/dist/skills/browser/scripts/omowright.mjs +29 -2
- package/dist/tui.js +16 -16
- package/package.json +14 -14
- package/packages/lsp-core/src/post-edit/not-installed.test.ts +2 -2
- package/packages/lsp-core/src/post-edit/orchestration.test.ts +13 -13
- package/packages/lsp-core/src/post-edit/orchestration.ts +9 -3
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +33 -19
- package/packages/omo-codex/plugin/components/lsp/dist/codex-hook.js +27 -17
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +36 -18
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook-not-installed.test.ts +203 -0
- package/packages/omo-codex/plugin/components/rules/CHANGELOG.md +1 -0
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-6.md +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/package-lock.json +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/skills/browser/SKILL.md +26 -2
- package/packages/omo-codex/plugin/skills/browser/references/commands.md +10 -1
- package/packages/omo-codex/plugin/skills/browser/references/install.md +7 -0
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/plugin/skills/browser/scripts/browser-engine-guard.mjs +506 -0
- package/packages/omo-codex/plugin/skills/browser/scripts/omowright.mjs +29 -2
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
- package/packages/shared-skills/skills/browser/SKILL.md +26 -2
- package/packages/shared-skills/skills/browser/references/commands.md +10 -1
- package/packages/shared-skills/skills/browser/references/install.md +7 -0
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/shared-skills/skills/browser/scripts/browser-engine-guard.mjs +506 -0
- package/packages/shared-skills/skills/browser/scripts/omowright.mjs +29 -2
|
@@ -152,7 +152,7 @@ describe("collectPostEditDiagnostics not-installed guidance", () => {
|
|
|
152
152
|
locateFile: at("project"),
|
|
153
153
|
});
|
|
154
154
|
|
|
155
|
-
expect(result.blocks).toEqual([{ filePath: "src/a.ts", diagnostics: `${FULL_NUDGE} (typescript)
|
|
155
|
+
expect(result.blocks).toEqual([{ filePath: "src/a.ts", diagnostics: `${FULL_NUDGE} (typescript)`, blocking: false }]);
|
|
156
156
|
});
|
|
157
157
|
|
|
158
158
|
it("#given no decision tool #when repeated edits hit missing servers #then each server is nudged once per session", async () => {
|
|
@@ -219,6 +219,6 @@ describe("collectPostEditDiagnostics not-installed guidance", () => {
|
|
|
219
219
|
runDiagnostics: async () => notInstalled("typescript"),
|
|
220
220
|
});
|
|
221
221
|
|
|
222
|
-
expect(result.blocks).toEqual([{ filePath: "a.ts", diagnostics: `${FULL_NUDGE} (typescript)
|
|
222
|
+
expect(result.blocks).toEqual([{ filePath: "a.ts", diagnostics: `${FULL_NUDGE} (typescript)`, blocking: false }]);
|
|
223
223
|
});
|
|
224
224
|
});
|
|
@@ -30,9 +30,9 @@ describe("collectPostEditDiagnostics", () => {
|
|
|
30
30
|
|
|
31
31
|
expect(calls).toBe(2);
|
|
32
32
|
expect(first.blocks).toEqual([
|
|
33
|
-
{ filePath: "a.foo", diagnostics: "No LSP server configured for extension: .foo\n\nordinary text from a renderer" },
|
|
33
|
+
{ filePath: "a.foo", diagnostics: "No LSP server configured for extension: .foo\n\nordinary text from a renderer", blocking: true },
|
|
34
34
|
]);
|
|
35
|
-
expect(second.blocks).toEqual([{ filePath: "b.foo", diagnostics: "diagnostic for b.foo" }]);
|
|
35
|
+
expect(second.blocks).toEqual([{ filePath: "b.foo", diagnostics: "diagnostic for b.foo", blocking: true }]);
|
|
36
36
|
expect([...cache.notConfiguredExtensions]).toEqual([]);
|
|
37
37
|
});
|
|
38
38
|
|
|
@@ -49,8 +49,8 @@ describe("collectPostEditDiagnostics", () => {
|
|
|
49
49
|
|
|
50
50
|
expect(calls).toEqual(["a.ts", "b.ts", "c.ts"]);
|
|
51
51
|
expect(result.blocks).toEqual([
|
|
52
|
-
{ filePath: "a.ts", diagnostics: "diagnostic for a.ts" },
|
|
53
|
-
{ filePath: "c.ts", diagnostics: "diagnostic for c.ts" },
|
|
52
|
+
{ filePath: "a.ts", diagnostics: "diagnostic for a.ts", blocking: true },
|
|
53
|
+
{ filePath: "c.ts", diagnostics: "diagnostic for c.ts", blocking: true },
|
|
54
54
|
]);
|
|
55
55
|
});
|
|
56
56
|
|
|
@@ -72,11 +72,11 @@ describe("collectPostEditDiagnostics", () => {
|
|
|
72
72
|
|
|
73
73
|
expect(maxActive).toBe(4);
|
|
74
74
|
expect(result.blocks).toEqual([
|
|
75
|
-
{ filePath: "a.ts", diagnostics: "diagnostic for a.ts" },
|
|
76
|
-
{ filePath: "b.ts", diagnostics: "diagnostic for b.ts" },
|
|
77
|
-
{ filePath: "c.ts", diagnostics: "server exploded" },
|
|
78
|
-
{ filePath: "d.ts", diagnostics: "diagnostic for d.ts" },
|
|
79
|
-
{ filePath: "f.ts", diagnostics: "diagnostic for f.ts" },
|
|
75
|
+
{ filePath: "a.ts", diagnostics: "diagnostic for a.ts", blocking: true },
|
|
76
|
+
{ filePath: "b.ts", diagnostics: "diagnostic for b.ts", blocking: true },
|
|
77
|
+
{ filePath: "c.ts", diagnostics: "server exploded", blocking: true },
|
|
78
|
+
{ filePath: "d.ts", diagnostics: "diagnostic for d.ts", blocking: true },
|
|
79
|
+
{ filePath: "f.ts", diagnostics: "diagnostic for f.ts", blocking: true },
|
|
80
80
|
]);
|
|
81
81
|
});
|
|
82
82
|
|
|
@@ -99,7 +99,7 @@ describe("collectPostEditDiagnostics", () => {
|
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
expect(calls).toEqual(["a.foo", "c.bar"]);
|
|
102
|
-
expect(first.blocks).toEqual([{ filePath: "c.bar", diagnostics: "LSP server 'bar' for .bar is NOT INSTALLED." }]);
|
|
102
|
+
expect(first.blocks).toEqual([{ filePath: "c.bar", diagnostics: "LSP server 'bar' for .bar is NOT INSTALLED.", blocking: true }]);
|
|
103
103
|
|
|
104
104
|
const cached = await collectPostEditDiagnostics({
|
|
105
105
|
filePaths: ["b.foo"],
|
|
@@ -124,7 +124,7 @@ describe("collectPostEditDiagnostics", () => {
|
|
|
124
124
|
},
|
|
125
125
|
});
|
|
126
126
|
|
|
127
|
-
expect(second.blocks).toEqual([{ filePath: "b.foo", diagnostics: "diagnostic should be skipped" }]);
|
|
127
|
+
expect(second.blocks).toEqual([{ filePath: "b.foo", diagnostics: "diagnostic should be skipped", blocking: true }]);
|
|
128
128
|
expect(calls).toEqual(["a.foo", "c.bar", "a.foo", "b.foo"]);
|
|
129
129
|
});
|
|
130
130
|
|
|
@@ -150,8 +150,8 @@ describe("collectPostEditDiagnostics", () => {
|
|
|
150
150
|
});
|
|
151
151
|
|
|
152
152
|
expect(calls).toBe(2);
|
|
153
|
-
expect(first.blocks).toEqual([{ filePath: "a.foo", diagnostics: "LSP server 'foo' for .foo is NOT INSTALLED." }]);
|
|
154
|
-
expect(second.blocks).toEqual([{ filePath: "b.foo", diagnostics: "daemon unavailable" }]);
|
|
153
|
+
expect(first.blocks).toEqual([{ filePath: "a.foo", diagnostics: "LSP server 'foo' for .foo is NOT INSTALLED.", blocking: true }]);
|
|
154
|
+
expect(second.blocks).toEqual([{ filePath: "b.foo", diagnostics: "daemon unavailable", blocking: true }]);
|
|
155
155
|
expect([...cache.notConfiguredExtensions]).toEqual([]);
|
|
156
156
|
});
|
|
157
157
|
});
|
|
@@ -19,6 +19,8 @@ export type DiagnosticsRunner = (filePath: string) => Promise<PostEditDiagnostic
|
|
|
19
19
|
export interface PostEditDiagnosticsBlock {
|
|
20
20
|
readonly filePath: string;
|
|
21
21
|
readonly diagnostics: string;
|
|
22
|
+
/** False for missing-server guidance: it is feedback for the model, not a defect in the edit. */
|
|
23
|
+
readonly blocking: boolean;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export interface PostEditDiagnosticsObservation {
|
|
@@ -91,7 +93,11 @@ export async function collectPostEditDiagnostics(
|
|
|
91
93
|
observations.push({ filePath: result.filePath, kind: "not_configured" });
|
|
92
94
|
break;
|
|
93
95
|
case "block":
|
|
94
|
-
blocks.push({ filePath: result.filePath, diagnostics: classification.diagnostics });
|
|
96
|
+
blocks.push({ filePath: result.filePath, diagnostics: classification.diagnostics, blocking: true });
|
|
97
|
+
observations.push({ filePath: result.filePath, kind: "block" });
|
|
98
|
+
break;
|
|
99
|
+
case "guidance":
|
|
100
|
+
blocks.push({ filePath: result.filePath, diagnostics: classification.text, blocking: false });
|
|
95
101
|
observations.push({ filePath: result.filePath, kind: "block" });
|
|
96
102
|
break;
|
|
97
103
|
default: {
|
|
@@ -166,8 +172,8 @@ function normalizeDiagnosticsOutcome(outcome: PostEditDiagnosticsOutcome): PostE
|
|
|
166
172
|
|
|
167
173
|
function classifyNotInstalled(
|
|
168
174
|
guidance: string | undefined,
|
|
169
|
-
): { readonly kind: "not_installed" } | { readonly kind: "
|
|
170
|
-
return guidance === undefined ? { kind: "not_installed" } : { kind: "
|
|
175
|
+
): { readonly kind: "not_installed" } | { readonly kind: "guidance"; readonly text: string } {
|
|
176
|
+
return guidance === undefined ? { kind: "not_installed" } : { kind: "guidance", text: guidance };
|
|
171
177
|
}
|
|
172
178
|
|
|
173
179
|
function normalizeDiagnosticsText(text: string): string {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/bootstrap/dist/cli.js\" hook session-start",
|
|
9
9
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1\"",
|
|
10
10
|
"timeout": 30,
|
|
11
|
-
"statusMessage": "(OmO 5.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.15) Checking Bootstrap Provisioning"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
|
|
10
10
|
"timeout": 5,
|
|
11
|
-
"statusMessage": "(OmO 5.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.15) Recommending Git Bash MCP"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"type": "command",
|
|
21
21
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
22
22
|
"timeout": 5,
|
|
23
|
-
"statusMessage": "(OmO 5.1.
|
|
23
|
+
"statusMessage": "(OmO 5.1.15) Resetting Git Bash MCP Reminder"
|
|
24
24
|
}
|
|
25
25
|
]
|
|
26
26
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/components/lazycodex-executor-verify/dist/cli.js\" hook subagent-stop",
|
|
10
10
|
"timeout": 10,
|
|
11
|
-
"statusMessage": "(OmO 5.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.15) Verifying LazyCodex Executor Evidence"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "5.1.
|
|
4
|
-
"inputDigest": "sha256:
|
|
3
|
+
"version": "5.1.15",
|
|
4
|
+
"inputDigest": "sha256:2a033aeb4eca6b2e5d55f0053c9cc5ab6a9708cfd06c7024eb7924de056bd8b3",
|
|
5
5
|
"outputs": [
|
|
6
6
|
{
|
|
7
7
|
"path": "cli.d.ts",
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
},
|
|
10
10
|
{
|
|
11
11
|
"path": "cli.js",
|
|
12
|
-
"sha256": "
|
|
12
|
+
"sha256": "f2776c0f9c2a893136e9e8e36c2e086172f10c0ab3566a730cff4443b712f956"
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
15
|
"path": "codex-hook-cli.d.ts",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
"path": "codex-hook.js",
|
|
28
|
-
"sha256": "
|
|
28
|
+
"sha256": "6e054189fe9efc941916d3469f1342344aadc20215c91fa6209e2f98139d6ed5"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"path": "daemon-cli-path.d.ts",
|
|
@@ -5958,7 +5958,11 @@ async function collectPostEditDiagnostics(input) {
|
|
|
5958
5958
|
observations.push({ filePath: result.filePath, kind: "not_configured" });
|
|
5959
5959
|
break;
|
|
5960
5960
|
case "block":
|
|
5961
|
-
blocks.push({ filePath: result.filePath, diagnostics: classification.diagnostics });
|
|
5961
|
+
blocks.push({ filePath: result.filePath, diagnostics: classification.diagnostics, blocking: true });
|
|
5962
|
+
observations.push({ filePath: result.filePath, kind: "block" });
|
|
5963
|
+
break;
|
|
5964
|
+
case "guidance":
|
|
5965
|
+
blocks.push({ filePath: result.filePath, diagnostics: classification.text, blocking: false });
|
|
5962
5966
|
observations.push({ filePath: result.filePath, kind: "block" });
|
|
5963
5967
|
break;
|
|
5964
5968
|
default: {
|
|
@@ -6020,7 +6024,7 @@ function normalizeDiagnosticsOutcome(outcome) {
|
|
|
6020
6024
|
return outcome;
|
|
6021
6025
|
}
|
|
6022
6026
|
function classifyNotInstalled(guidance) {
|
|
6023
|
-
return guidance === undefined ? { kind: "not_installed" } : { kind: "
|
|
6027
|
+
return guidance === undefined ? { kind: "not_installed" } : { kind: "guidance", text: guidance };
|
|
6024
6028
|
}
|
|
6025
6029
|
function normalizeDiagnosticsText(text) {
|
|
6026
6030
|
return text.trim();
|
|
@@ -6277,22 +6281,33 @@ async function runLspDiagnosticsText(filePath) {
|
|
|
6277
6281
|
return postEditOutcomeFromDaemonResult(result);
|
|
6278
6282
|
}
|
|
6279
6283
|
function postEditOutcomeFromDaemonResult(result) {
|
|
6280
|
-
const
|
|
6281
|
-
if (availability !== undefined)
|
|
6282
|
-
return { kind: "not_configured", extension: availability.extension };
|
|
6283
|
-
return result.content.map((block) => block.text).join(`
|
|
6284
|
+
const text = result.content.map((block) => block.text).join(`
|
|
6284
6285
|
`);
|
|
6286
|
+
const availability = availabilityDetails2(result.details);
|
|
6287
|
+
if (availability === undefined)
|
|
6288
|
+
return text;
|
|
6289
|
+
if (availability["kind"] === "not_configured") {
|
|
6290
|
+
const extension = availability["extension"];
|
|
6291
|
+
return typeof extension === "string" && extension.length > 0 ? { kind: "not_configured", extension } : text;
|
|
6292
|
+
}
|
|
6293
|
+
if (availability["kind"] === "not_installed")
|
|
6294
|
+
return notInstalledOutcome(availability, text) ?? text;
|
|
6295
|
+
return text;
|
|
6285
6296
|
}
|
|
6286
|
-
function
|
|
6297
|
+
function availabilityDetails2(details) {
|
|
6287
6298
|
if (!isRecord11(details))
|
|
6288
6299
|
return;
|
|
6289
6300
|
const availability = details["availability"];
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6301
|
+
return isRecord11(availability) ? availability : undefined;
|
|
6302
|
+
}
|
|
6303
|
+
function notInstalledOutcome(availability, text) {
|
|
6304
|
+
const serverId = availability["serverId"];
|
|
6305
|
+
const installDecisionTool = availability["installDecisionTool"];
|
|
6306
|
+
if (typeof serverId !== "string" || serverId.length === 0 || typeof installDecisionTool !== "boolean")
|
|
6293
6307
|
return;
|
|
6294
|
-
const
|
|
6295
|
-
|
|
6308
|
+
const decision = availability["decision"];
|
|
6309
|
+
const base = { kind: "not_installed", serverId, installDecisionTool, text };
|
|
6310
|
+
return decision === "declined" || decision === "allowed" ? { ...base, decision } : base;
|
|
6296
6311
|
}
|
|
6297
6312
|
function codexLspRequestContext(env = process.env, cwd = process.cwd()) {
|
|
6298
6313
|
const canonicalCwd = realpathSync7(resolve11(cwd));
|
|
@@ -6320,14 +6335,13 @@ async function runLspPostToolUseHook(input, runDiagnostics = runLspDiagnosticsTe
|
|
|
6320
6335
|
|
|
6321
6336
|
`);
|
|
6322
6337
|
const reason = limitHookText(rawReason, hookFeedbackLimit(input.transcript_path));
|
|
6323
|
-
const
|
|
6324
|
-
|
|
6325
|
-
reason,
|
|
6326
|
-
hookSpecificOutput: {
|
|
6327
|
-
hookEventName: "PostToolUse",
|
|
6328
|
-
additionalContext: reason
|
|
6329
|
-
}
|
|
6338
|
+
const context = {
|
|
6339
|
+
hookSpecificOutput: { hookEventName: "PostToolUse", additionalContext: reason }
|
|
6330
6340
|
};
|
|
6341
|
+
if (!blocks.some((block) => block.blocking))
|
|
6342
|
+
return `${JSON.stringify(context)}
|
|
6343
|
+
`;
|
|
6344
|
+
const output = { decision: "block", reason, ...context };
|
|
6331
6345
|
return `${JSON.stringify(output)}
|
|
6332
6346
|
`;
|
|
6333
6347
|
}
|
|
@@ -27,21 +27,32 @@ export async function runLspDiagnosticsText(filePath) {
|
|
|
27
27
|
return postEditOutcomeFromDaemonResult(result);
|
|
28
28
|
}
|
|
29
29
|
function postEditOutcomeFromDaemonResult(result) {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
const text = result.content.map((block) => block.text).join("\n");
|
|
31
|
+
const availability = availabilityDetails(result.details);
|
|
32
|
+
if (availability === undefined)
|
|
33
|
+
return text;
|
|
34
|
+
if (availability["kind"] === "not_configured") {
|
|
35
|
+
const extension = availability["extension"];
|
|
36
|
+
return typeof extension === "string" && extension.length > 0 ? { kind: "not_configured", extension } : text;
|
|
37
|
+
}
|
|
38
|
+
if (availability["kind"] === "not_installed")
|
|
39
|
+
return notInstalledOutcome(availability, text) ?? text;
|
|
40
|
+
return text;
|
|
34
41
|
}
|
|
35
|
-
function
|
|
42
|
+
function availabilityDetails(details) {
|
|
36
43
|
if (!isRecord(details))
|
|
37
44
|
return undefined;
|
|
38
45
|
const availability = details["availability"];
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
return isRecord(availability) ? availability : undefined;
|
|
47
|
+
}
|
|
48
|
+
function notInstalledOutcome(availability, text) {
|
|
49
|
+
const serverId = availability["serverId"];
|
|
50
|
+
const installDecisionTool = availability["installDecisionTool"];
|
|
51
|
+
if (typeof serverId !== "string" || serverId.length === 0 || typeof installDecisionTool !== "boolean")
|
|
42
52
|
return undefined;
|
|
43
|
-
const
|
|
44
|
-
|
|
53
|
+
const decision = availability["decision"];
|
|
54
|
+
const base = { kind: "not_installed", serverId, installDecisionTool, text };
|
|
55
|
+
return decision === "declined" || decision === "allowed" ? { ...base, decision } : base;
|
|
45
56
|
}
|
|
46
57
|
export function codexLspRequestContext(env = process.env, cwd = process.cwd()) {
|
|
47
58
|
const canonicalCwd = realpathSync(resolve(cwd));
|
|
@@ -67,14 +78,13 @@ export async function runLspPostToolUseHook(input, runDiagnostics = runLspDiagno
|
|
|
67
78
|
return "";
|
|
68
79
|
const rawReason = blocks.map(formatDiagnosticBlock).join("\n\n");
|
|
69
80
|
const reason = limitHookText(rawReason, hookFeedbackLimit(input.transcript_path));
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
reason,
|
|
73
|
-
hookSpecificOutput: {
|
|
74
|
-
hookEventName: "PostToolUse",
|
|
75
|
-
additionalContext: reason,
|
|
76
|
-
},
|
|
81
|
+
const context = {
|
|
82
|
+
hookSpecificOutput: { hookEventName: "PostToolUse", additionalContext: reason },
|
|
77
83
|
};
|
|
84
|
+
// Missing-server guidance alone is a note for the model; only real diagnostics block the edit.
|
|
85
|
+
if (!blocks.some((block) => block.blocking))
|
|
86
|
+
return `${JSON.stringify(context)}\n`;
|
|
87
|
+
const output = { decision: "block", reason, ...context };
|
|
78
88
|
return `${JSON.stringify(output)}\n`;
|
|
79
89
|
}
|
|
80
90
|
export async function runLspPostCompactHook(input) {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
|
|
10
10
|
"timeout": 60,
|
|
11
|
-
"statusMessage": "(OmO 5.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.15) Checking LSP Diagnostics"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"type": "command",
|
|
22
22
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
23
23
|
"timeout": 5,
|
|
24
|
-
"statusMessage": "(OmO 5.1.
|
|
24
|
+
"statusMessage": "(OmO 5.1.15) Resetting LSP Diagnostics Cache"
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
}
|
|
@@ -35,17 +35,21 @@ export interface CodexPostCompactInput {
|
|
|
35
35
|
interface DiagnosticBlock {
|
|
36
36
|
filePath: string;
|
|
37
37
|
diagnostics: string;
|
|
38
|
+
blocking: boolean;
|
|
38
39
|
}
|
|
39
40
|
|
|
40
|
-
interface
|
|
41
|
-
decision: "block";
|
|
42
|
-
reason: string;
|
|
41
|
+
interface PostToolUseHookContext {
|
|
43
42
|
hookSpecificOutput: {
|
|
44
43
|
hookEventName: "PostToolUse";
|
|
45
44
|
additionalContext: string;
|
|
46
45
|
};
|
|
47
46
|
}
|
|
48
47
|
|
|
48
|
+
interface PostToolUseHookOutput extends PostToolUseHookContext {
|
|
49
|
+
decision: "block";
|
|
50
|
+
reason: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
49
53
|
const DIAGNOSTIC_START_PATTERN = /(?:error|warning|information|hint)\[[^\]\r\n]+\] \(\d+\) at \d+:\d+:/g;
|
|
50
54
|
const DIAGNOSTIC_CHUNK_PATTERN = /^(?:error|warning|information|hint)\[[^\]\r\n]+\] \(\d+\) at \d+:\d+:/;
|
|
51
55
|
const DEFAULT_MAX_HOOK_FEEDBACK_CHARS = 8000;
|
|
@@ -70,18 +74,34 @@ function postEditOutcomeFromDaemonResult(result: {
|
|
|
70
74
|
readonly content: readonly { readonly type: string; readonly text?: string }[];
|
|
71
75
|
readonly details?: unknown;
|
|
72
76
|
}): PostEditDiagnosticsOutcome {
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
const text = result.content.map((block) => block.text).join("\n");
|
|
78
|
+
const availability = availabilityDetails(result.details);
|
|
79
|
+
if (availability === undefined) return text;
|
|
80
|
+
if (availability["kind"] === "not_configured") {
|
|
81
|
+
const extension = availability["extension"];
|
|
82
|
+
return typeof extension === "string" && extension.length > 0 ? { kind: "not_configured", extension } : text;
|
|
83
|
+
}
|
|
84
|
+
if (availability["kind"] === "not_installed") return notInstalledOutcome(availability, text) ?? text;
|
|
85
|
+
return text;
|
|
76
86
|
}
|
|
77
87
|
|
|
78
|
-
function
|
|
88
|
+
function availabilityDetails(details: unknown): Record<string, unknown> | undefined {
|
|
79
89
|
if (!isRecord(details)) return undefined;
|
|
80
90
|
const availability = details["availability"];
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
return isRecord(availability) ? availability : undefined;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function notInstalledOutcome(
|
|
95
|
+
availability: Record<string, unknown>,
|
|
96
|
+
text: string,
|
|
97
|
+
): PostEditDiagnosticsOutcome | undefined {
|
|
98
|
+
const serverId = availability["serverId"];
|
|
99
|
+
const installDecisionTool = availability["installDecisionTool"];
|
|
100
|
+
if (typeof serverId !== "string" || serverId.length === 0 || typeof installDecisionTool !== "boolean")
|
|
101
|
+
return undefined;
|
|
102
|
+
const decision = availability["decision"];
|
|
103
|
+
const base = { kind: "not_installed", serverId, installDecisionTool, text } as const;
|
|
104
|
+
return decision === "declined" || decision === "allowed" ? { ...base, decision } : base;
|
|
85
105
|
}
|
|
86
106
|
|
|
87
107
|
export function codexLspRequestContext(
|
|
@@ -116,14 +136,12 @@ export async function runLspPostToolUseHook(
|
|
|
116
136
|
|
|
117
137
|
const rawReason = blocks.map(formatDiagnosticBlock).join("\n\n");
|
|
118
138
|
const reason = limitHookText(rawReason, hookFeedbackLimit(input.transcript_path));
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
reason,
|
|
122
|
-
hookSpecificOutput: {
|
|
123
|
-
hookEventName: "PostToolUse",
|
|
124
|
-
additionalContext: reason,
|
|
125
|
-
},
|
|
139
|
+
const context: PostToolUseHookContext = {
|
|
140
|
+
hookSpecificOutput: { hookEventName: "PostToolUse", additionalContext: reason },
|
|
126
141
|
};
|
|
142
|
+
// Missing-server guidance alone is a note for the model; only real diagnostics block the edit.
|
|
143
|
+
if (!blocks.some((block) => block.blocking)) return `${JSON.stringify(context)}\n`;
|
|
144
|
+
const output: PostToolUseHookOutput = { decision: "block", reason, ...context };
|
|
127
145
|
return `${JSON.stringify(output)}\n`;
|
|
128
146
|
}
|
|
129
147
|
|