oh-my-opencode 4.17.1 → 4.18.1
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/.agents/skills/codex-qa/SKILL.md +2 -0
- package/.agents/skills/codex-qa/scripts/lsp-e2e.sh +3654 -0
- package/.agents/skills/opencode-qa/scripts/lsp-e2e.sh +3071 -0
- package/.agents/skills/work-with-pr/SKILL.md +16 -37
- package/.agents/skills/work-with-pr-workspace/evals/evals.json +3 -3
- package/.opencode/skills/work-with-pr/SKILL.md +16 -37
- package/.opencode/skills/work-with-pr-workspace/evals/evals.json +3 -3
- package/dist/cli/get-local-version/types.d.ts +1 -1
- package/dist/cli/index.js +498 -165
- package/dist/cli-node/index.js +498 -165
- package/dist/index.js +425 -392
- package/dist/skills/frontend/SKILL.md +1 -1
- package/dist/skills/frontend/references/design/README.md +9 -0
- package/dist/skills/frontend/references/design/design-system-architecture.md +4 -2
- package/dist/skills/frontend/references/design/layout-skill.md +107 -0
- package/dist/skills/programming/SKILL.md +12 -2
- package/package.json +17 -16
- package/packages/lsp-core/package.json +4 -0
- package/packages/lsp-core/src/index.ts +1 -0
- package/packages/lsp-core/src/lsp/cleanup-errors.test.ts +18 -0
- package/packages/lsp-core/src/lsp/cleanup-errors.ts +12 -3
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +261 -0
- package/packages/lsp-core/src/lsp/client-wrapper.test.ts +63 -0
- package/packages/lsp-core/src/lsp/client-wrapper.ts +35 -5
- package/packages/lsp-core/src/lsp/client.ts +262 -80
- package/packages/lsp-core/src/lsp/config-loader.ts +5 -17
- package/packages/lsp-core/src/lsp/connection.ts +12 -6
- package/packages/lsp-core/src/lsp/directory-diagnostics.test.ts +104 -0
- package/packages/lsp-core/src/lsp/directory-diagnostics.ts +60 -27
- package/packages/lsp-core/src/lsp/errors.ts +11 -0
- package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +283 -0
- package/packages/lsp-core/src/lsp/fixtures/workspace-edit-contract-probe.ts +196 -0
- package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +215 -0
- package/packages/lsp-core/src/lsp/formatters.ts +3 -0
- package/packages/lsp-core/src/lsp/json-rpc-connection-cancellation.test.ts +97 -0
- package/packages/lsp-core/src/lsp/json-rpc-connection.ts +73 -5
- package/packages/lsp-core/src/lsp/server-install-state.ts +3 -6
- package/packages/lsp-core/src/lsp/transport-protocol.ts +52 -0
- package/packages/lsp-core/src/lsp/transport.ts +96 -70
- package/packages/lsp-core/src/lsp/workspace-apply-edit-failure.ts +19 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit-lease.integration.test.ts +214 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit-sync.integration.test.ts +113 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit-test-support.ts +163 -0
- package/packages/lsp-core/src/lsp/workspace-apply-edit.integration.test.ts +163 -0
- package/packages/lsp-core/src/lsp/workspace-document-state.test.ts +67 -0
- package/packages/lsp-core/src/lsp/workspace-document-state.ts +368 -0
- package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +113 -0
- package/packages/lsp-core/src/lsp/workspace-edit-commit.test.ts +140 -0
- package/packages/lsp-core/src/lsp/workspace-edit-commit.ts +220 -0
- package/packages/lsp-core/src/lsp/workspace-edit-contract-evidence.test.ts +56 -0
- package/packages/lsp-core/src/lsp/workspace-edit-contract-evidence.ts +30 -0
- package/packages/lsp-core/src/lsp/workspace-edit-fingerprint.ts +44 -0
- package/packages/lsp-core/src/lsp/workspace-edit-options.test.ts +147 -0
- package/packages/lsp-core/src/lsp/workspace-edit-parse-helpers.ts +59 -0
- package/packages/lsp-core/src/lsp/workspace-edit-parser.ts +130 -0
- package/packages/lsp-core/src/lsp/workspace-edit-path.ts +98 -0
- package/packages/lsp-core/src/lsp/workspace-edit-plan-types.ts +60 -0
- package/packages/lsp-core/src/lsp/workspace-edit-plan.ts +73 -0
- package/packages/lsp-core/src/lsp/workspace-edit-prevalidation.test.ts +174 -0
- package/packages/lsp-core/src/lsp/workspace-edit-resource-parser.ts +89 -0
- package/packages/lsp-core/src/lsp/workspace-edit-simulation.ts +183 -0
- package/packages/lsp-core/src/lsp/workspace-edit-snapshot.ts +53 -0
- package/packages/lsp-core/src/lsp/workspace-edit-text.ts +125 -0
- package/packages/lsp-core/src/lsp/workspace-edit-types.ts +121 -0
- package/packages/lsp-core/src/lsp/workspace-edit.characterization.test.ts +95 -0
- package/packages/lsp-core/src/lsp/workspace-edit.ts +49 -200
- package/packages/lsp-core/src/lsp/workspace-mutation-controller.ts +182 -0
- package/packages/lsp-core/src/mcp.ts +18 -7
- package/packages/lsp-core/src/missing-dependency-result.test.ts +105 -0
- package/packages/lsp-core/src/missing-dependency-result.ts +57 -0
- package/packages/lsp-core/src/post-edit/index.ts +1 -0
- package/packages/lsp-core/src/post-edit/orchestration.test.ts +157 -0
- package/packages/lsp-core/src/post-edit/orchestration.ts +178 -0
- package/packages/lsp-core/src/request-context.test.ts +171 -0
- package/packages/lsp-core/src/request-context.ts +222 -9
- package/packages/lsp-core/src/tool-surface.test.ts +4 -1
- package/packages/lsp-core/src/tools/diagnostics.ts +32 -13
- package/packages/lsp-core/src/tools/navigation.ts +12 -12
- package/packages/lsp-core/src/tools/rename.ts +10 -15
- package/packages/lsp-core/src/tools/symbols.ts +11 -11
- package/packages/lsp-core/src/tools/types.ts +2 -1
- package/packages/lsp-daemon/dist/cli.js +3114 -747
- package/packages/lsp-daemon/dist/client.d.ts +105 -0
- package/packages/lsp-daemon/dist/client.js +5851 -0
- package/packages/lsp-daemon/dist/daemon-client.d.ts +11 -6
- package/packages/lsp-daemon/dist/daemon-client.js +113 -30
- package/packages/lsp-daemon/dist/daemon-server.d.ts +1 -0
- package/packages/lsp-daemon/dist/daemon-server.js +40 -15
- package/packages/lsp-daemon/dist/ensure-daemon.d.ts +8 -7
- package/packages/lsp-daemon/dist/ensure-daemon.js +67 -44
- package/packages/lsp-daemon/dist/index.d.ts +2 -2
- package/packages/lsp-daemon/dist/index.js +2862 -754
- package/packages/lsp-daemon/dist/ipc-protocol.d.ts +46 -0
- package/packages/lsp-daemon/dist/ipc-protocol.js +187 -0
- package/packages/lsp-daemon/dist/lock.js +14 -4
- package/packages/lsp-daemon/dist/ownership.d.ts +49 -0
- package/packages/lsp-daemon/dist/ownership.js +168 -0
- package/packages/lsp-daemon/dist/paths.d.ts +33 -9
- package/packages/lsp-daemon/dist/paths.js +72 -33
- package/packages/lsp-daemon/dist/proxy.d.ts +3 -0
- package/packages/lsp-daemon/dist/proxy.js +54 -3
- package/packages/lsp-daemon/dist/request-routing.d.ts +7 -2
- package/packages/lsp-daemon/dist/request-routing.js +71 -22
- package/packages/lsp-daemon/dist/run-daemon.js +9 -2
- package/packages/lsp-daemon/dist/runtime-contract.d.ts +21 -0
- package/packages/lsp-daemon/dist/runtime-contract.js +58 -0
- package/packages/lsp-daemon/dist/socket-jsonrpc.js +6 -1
- package/packages/lsp-daemon/package.json +12 -3
- package/packages/lsp-tools-mcp/dist/cli.js +2115 -442
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +1741 -148
- package/packages/lsp-tools-mcp/dist/mcp.js +2127 -454
- package/packages/lsp-tools-mcp/dist/request-context.js +176 -6
- package/packages/lsp-tools-mcp/dist/tools.js +2118 -446
- 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/codegraph/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 +55 -0
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +2959 -944
- package/packages/omo-codex/plugin/components/lsp/dist/codex-hook-cli.js +0 -4
- package/packages/omo-codex/plugin/components/lsp/dist/codex-hook.d.ts +5 -2
- package/packages/omo-codex/plugin/components/lsp/dist/codex-hook.js +41 -62
- package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.d.ts +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +24 -15
- package/packages/omo-codex/plugin/components/lsp/dist/lsp-session-state.d.ts +3 -7
- package/packages/omo-codex/plugin/components/lsp/dist/lsp-session-state.js +23 -49
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +3 -2
- package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-daemon.mjs +31 -1
- package/packages/omo-codex/plugin/components/lsp/scripts/build-lsp-daemon.test.mjs +76 -0
- package/packages/omo-codex/plugin/components/lsp/scripts/build-runtime.mjs +201 -0
- package/packages/omo-codex/plugin/components/lsp/scripts/build-runtime.test.mjs +55 -0
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook-cli.ts +0 -4
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +49 -71
- package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +26 -15
- package/packages/omo-codex/plugin/components/lsp/src/lsp-session-state.ts +26 -64
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +16 -17
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +30 -4
- package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +19 -5
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.5.md +1 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.6.md +8 -6
- 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/start-work-continuation/directive.md +1 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/start-work-continuation/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/directive.md +37 -10
- 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/ultrawork/skills/ultrawork/SKILL.md +37 -10
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +37 -10
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +10 -9
- 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-codegraph-init-guidance.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/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-checking-codegraph-bootstrap.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-start-work-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-checking-start-work-continuation.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 +26 -14
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/build-bundled-mcp-runtimes.mjs +2 -3
- package/packages/omo-codex/plugin/scripts/build-components.mjs +13 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +1 -1
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +9 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +4 -2
- package/packages/omo-codex/plugin/skills/frontend/references/design/layout-skill.md +107 -0
- package/packages/omo-codex/plugin/skills/programming/SKILL.md +12 -2
- package/packages/omo-codex/plugin/skills/start-work/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +37 -10
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +10 -9
- package/packages/omo-codex/plugin/test/aggregate-build.test.mjs +8 -0
- package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +128 -15
- package/packages/omo-codex/plugin/test/install-time-build-runtime.test.mjs +10 -0
- package/packages/omo-codex/plugin/test/lsp-prebuild-layouts.test.mjs +2 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +1 -1
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +351 -74
- package/packages/shared-skills/skills/frontend/SKILL.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/README.md +9 -0
- package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +4 -2
- package/packages/shared-skills/skills/frontend/references/design/layout-skill.md +107 -0
- package/packages/shared-skills/skills/programming/SKILL.md +12 -2
|
@@ -96,14 +96,14 @@ var init_atomic_write = __esm(() => {
|
|
|
96
96
|
|
|
97
97
|
// packages/telemetry-core/src/activity-state.ts
|
|
98
98
|
import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
99
|
-
import { basename as
|
|
99
|
+
import { basename as basename7, join as join33 } from "node:path";
|
|
100
100
|
function resolveTelemetryStateDir(product, options = {}) {
|
|
101
101
|
const dataDir = resolveXdgDataDir(product.cacheDirName, {
|
|
102
102
|
env: options.env,
|
|
103
103
|
osProvider: options.osProvider
|
|
104
104
|
});
|
|
105
105
|
const xdgStateDir = options.env?.XDG_DATA_HOME === undefined ? undefined : join33(options.env.XDG_DATA_HOME, product.cacheDirName);
|
|
106
|
-
if (dataDir === xdgStateDir || xdgStateDir === undefined &&
|
|
106
|
+
if (dataDir === xdgStateDir || xdgStateDir === undefined && basename7(dataDir) === product.cacheDirName) {
|
|
107
107
|
return dataDir;
|
|
108
108
|
}
|
|
109
109
|
return join33(dataDir, product.cacheDirName);
|
|
@@ -337,18 +337,18 @@ var init_env = __esm(() => {
|
|
|
337
337
|
});
|
|
338
338
|
|
|
339
339
|
// packages/telemetry-core/src/machine-id.ts
|
|
340
|
-
import { createHash as
|
|
340
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
341
341
|
import os2 from "node:os";
|
|
342
342
|
function getDefaultTelemetryOsProvider() {
|
|
343
343
|
return os2;
|
|
344
344
|
}
|
|
345
345
|
function getTelemetryDistinctId(machineIdPrefix, osProvider = getDefaultTelemetryOsProvider()) {
|
|
346
|
-
return
|
|
346
|
+
return createHash3("sha256").update(`${machineIdPrefix}${osProvider.hostname()}`).digest("hex");
|
|
347
347
|
}
|
|
348
348
|
var init_machine_id = () => {};
|
|
349
349
|
|
|
350
350
|
// node_modules/.bun/posthog-node@5.35.12/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
|
|
351
|
-
import { dirname as dirname10, posix, sep as sep7 } from "node:path";
|
|
351
|
+
import { dirname as dirname10, posix as posix2, sep as sep7 } from "node:path";
|
|
352
352
|
function createModulerModifier() {
|
|
353
353
|
const getModuleFromFileName = createGetModuleFromFilename();
|
|
354
354
|
return async (frames) => {
|
|
@@ -363,7 +363,7 @@ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname10(proc
|
|
|
363
363
|
if (!filename)
|
|
364
364
|
return;
|
|
365
365
|
const normalizedFilename = isWindows ? normalizeWindowsPath(filename) : filename;
|
|
366
|
-
let { dir, base: file, ext } =
|
|
366
|
+
let { dir, base: file, ext } = posix2.parse(normalizedFilename);
|
|
367
367
|
if (ext === ".js" || ext === ".mjs" || ext === ".cjs")
|
|
368
368
|
file = file.slice(0, -1 * ext.length);
|
|
369
369
|
const decodedFile = decodeURIComponent(file);
|
|
@@ -5903,7 +5903,7 @@ var package_default;
|
|
|
5903
5903
|
var init_package = __esm(() => {
|
|
5904
5904
|
package_default = {
|
|
5905
5905
|
name: "@oh-my-opencode/omo-codex",
|
|
5906
|
-
version: "4.
|
|
5906
|
+
version: "4.18.1",
|
|
5907
5907
|
type: "module",
|
|
5908
5908
|
private: true,
|
|
5909
5909
|
description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
|
|
@@ -6122,7 +6122,7 @@ var init_telemetry = __esm(() => {
|
|
|
6122
6122
|
});
|
|
6123
6123
|
|
|
6124
6124
|
// packages/omo-codex/src/install/install-local-cli.ts
|
|
6125
|
-
import { readFile as
|
|
6125
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
6126
6126
|
import { dirname as dirname12, join as join39, resolve as resolve10 } from "node:path";
|
|
6127
6127
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
6128
6128
|
|
|
@@ -7519,9 +7519,11 @@ function collectCommands(value, commands) {
|
|
|
7519
7519
|
|
|
7520
7520
|
// packages/omo-codex/src/install/codex-cache-install.ts
|
|
7521
7521
|
async function installCachedPlugin(input) {
|
|
7522
|
+
const env = input.env ?? process.env;
|
|
7523
|
+
const npmInstallEnv = sanitizeNpmInstallEnv(env);
|
|
7522
7524
|
if (input.buildSource !== false) {
|
|
7523
|
-
await maybeRunNpmInstall(input.sourcePath, input.runCommand);
|
|
7524
|
-
await maybeRunNpmBuild(input.sourcePath, input.runCommand);
|
|
7525
|
+
await maybeRunNpmInstall(input.sourcePath, input.runCommand, npmInstallEnv);
|
|
7526
|
+
await maybeRunNpmBuild(input.sourcePath, input.runCommand, env);
|
|
7525
7527
|
}
|
|
7526
7528
|
const targetPath = join12(input.codexHome, "plugins", "cache", input.marketplaceName, input.name, input.version);
|
|
7527
7529
|
const tempPath = createTempSiblingPath(targetPath);
|
|
@@ -7531,10 +7533,10 @@ async function installCachedPlugin(input) {
|
|
|
7531
7533
|
await rewriteCachedPackageLocalFileDependencies(tempPath, input.sourcePath);
|
|
7532
7534
|
await copyBundledMcpRuntimeDists({ pluginRoot: tempPath, sourceRoot: input.sourcePath });
|
|
7533
7535
|
await copyRootRuntimeDists({ pluginRoot: tempPath, sourcePath: input.sourcePath });
|
|
7534
|
-
await maybeRunNpmInstall(tempPath, input.runCommand, ["ci", "--omit=dev"]);
|
|
7536
|
+
await maybeRunNpmInstall(tempPath, input.runCommand, npmInstallEnv, ["ci", "--omit=dev"]);
|
|
7535
7537
|
await removeCachedManagedNpmBinShims(tempPath);
|
|
7536
7538
|
if (input.buildSource === false)
|
|
7537
|
-
await maybeRunNpmSyncSkills(tempPath, input.runCommand);
|
|
7539
|
+
await maybeRunNpmSyncSkills(tempPath, input.runCommand, env);
|
|
7538
7540
|
await assertNoRemovedSparkshellPromptReferences(tempPath);
|
|
7539
7541
|
await rewriteCachedMcpManifest(tempPath, input.sourcePath);
|
|
7540
7542
|
await rewriteCachedManifestRoot(tempPath, tempPath, targetPath);
|
|
@@ -7546,12 +7548,12 @@ async function installCachedPlugin(input) {
|
|
|
7546
7548
|
}
|
|
7547
7549
|
return { name: input.name, version: input.version, path: targetPath };
|
|
7548
7550
|
}
|
|
7549
|
-
async function maybeRunNpmInstall(cwd, runCommand, args = ["install"]) {
|
|
7551
|
+
async function maybeRunNpmInstall(cwd, runCommand, env, args = ["install"]) {
|
|
7550
7552
|
if (!await fileExistsStrict(join12(cwd, "package.json")))
|
|
7551
7553
|
return;
|
|
7552
|
-
await runCommand("npm", args, { cwd });
|
|
7554
|
+
await runCommand("npm", args, { cwd, env });
|
|
7553
7555
|
}
|
|
7554
|
-
async function maybeRunNpmBuild(cwd, runCommand) {
|
|
7556
|
+
async function maybeRunNpmBuild(cwd, runCommand, env) {
|
|
7555
7557
|
if (!await fileExistsStrict(join12(cwd, "package.json")))
|
|
7556
7558
|
return;
|
|
7557
7559
|
const packageJson = JSON.parse(await readFile8(join12(cwd, "package.json"), "utf8"));
|
|
@@ -7560,9 +7562,9 @@ async function maybeRunNpmBuild(cwd, runCommand) {
|
|
|
7560
7562
|
const scripts = packageJson.scripts;
|
|
7561
7563
|
if (!isPlainRecord(scripts) || typeof scripts.build !== "string")
|
|
7562
7564
|
return;
|
|
7563
|
-
await runCommand("npm", ["run", "build"], { cwd });
|
|
7565
|
+
await runCommand("npm", ["run", "build"], { cwd, env });
|
|
7564
7566
|
}
|
|
7565
|
-
async function maybeRunNpmSyncSkills(cwd, runCommand) {
|
|
7567
|
+
async function maybeRunNpmSyncSkills(cwd, runCommand, env) {
|
|
7566
7568
|
if (!await fileExistsStrict(join12(cwd, "package.json")))
|
|
7567
7569
|
return;
|
|
7568
7570
|
const packageJson = JSON.parse(await readFile8(join12(cwd, "package.json"), "utf8"));
|
|
@@ -7571,7 +7573,10 @@ async function maybeRunNpmSyncSkills(cwd, runCommand) {
|
|
|
7571
7573
|
const scripts = packageJson.scripts;
|
|
7572
7574
|
if (!isPlainRecord(scripts) || typeof scripts["sync:skills"] !== "string")
|
|
7573
7575
|
return;
|
|
7574
|
-
await runCommand("npm", ["run", "sync:skills"], { cwd });
|
|
7576
|
+
await runCommand("npm", ["run", "sync:skills"], { cwd, env });
|
|
7577
|
+
}
|
|
7578
|
+
function sanitizeNpmInstallEnv(env) {
|
|
7579
|
+
return Object.fromEntries(Object.entries(env).filter(([key]) => key.toLowerCase() !== "npm_config_allow_scripts"));
|
|
7575
7580
|
}
|
|
7576
7581
|
function createTempSiblingPath(targetPath) {
|
|
7577
7582
|
return join12(dirname5(targetPath), `.tmp-${basename3(targetPath)}-${process.pid}-${Date.now()}`);
|
|
@@ -9600,6 +9605,10 @@ async function readDistributionManifest(repoRoot) {
|
|
|
9600
9605
|
}
|
|
9601
9606
|
}
|
|
9602
9607
|
function resolveLazyCodexPluginVersion(input) {
|
|
9608
|
+
const override = input.versionOverride?.trim();
|
|
9609
|
+
if (override !== undefined && override.length > 0) {
|
|
9610
|
+
return override;
|
|
9611
|
+
}
|
|
9603
9612
|
if (input.marketplaceName === "sisyphuslabs" && input.pluginName === "omo" && input.distributionManifest !== undefined) {
|
|
9604
9613
|
return input.distributionManifest.version;
|
|
9605
9614
|
}
|
|
@@ -9942,65 +9951,297 @@ function formatUnknownError(error) {
|
|
|
9942
9951
|
}
|
|
9943
9952
|
|
|
9944
9953
|
// packages/omo-codex/src/install/lsp-daemon-reaper.ts
|
|
9945
|
-
import {
|
|
9954
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
9955
|
+
import { lstat as lstat11, readFile as readFile19, readdir as readdir10, rm as rm10 } from "node:fs/promises";
|
|
9956
|
+
import { tmpdir } from "node:os";
|
|
9957
|
+
import { join as join27, posix } from "node:path";
|
|
9958
|
+
|
|
9959
|
+
// packages/omo-codex/src/install/lsp-daemon-reaper-attestation.ts
|
|
9960
|
+
import { execFile } from "node:child_process";
|
|
9961
|
+
import { readFile as readFile18, readdir as readdir9, readlink as readlink5 } from "node:fs/promises";
|
|
9946
9962
|
import { connect } from "node:net";
|
|
9947
|
-
import {
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
|
|
9963
|
+
import { basename as basename6 } from "node:path";
|
|
9964
|
+
var PROBE_TIMEOUT_MS = 500;
|
|
9965
|
+
async function probeLegacyJsonRpcEndpoint(endpoint, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
9966
|
+
return await new Promise((resolve8) => {
|
|
9967
|
+
const socket = connect(endpoint);
|
|
9968
|
+
let settled = false;
|
|
9969
|
+
let buffer = "";
|
|
9970
|
+
const finish = (value) => {
|
|
9971
|
+
if (settled)
|
|
9972
|
+
return;
|
|
9973
|
+
settled = true;
|
|
9974
|
+
clearTimeout(timer);
|
|
9975
|
+
socket.destroy();
|
|
9976
|
+
resolve8(value);
|
|
9977
|
+
};
|
|
9978
|
+
const timer = setTimeout(() => finish(false), timeoutMs);
|
|
9979
|
+
timer.unref?.();
|
|
9980
|
+
socket.once("connect", () => {
|
|
9981
|
+
socket.write(`${JSON.stringify(legacyStatusRequest())}
|
|
9982
|
+
`);
|
|
9983
|
+
});
|
|
9984
|
+
socket.on("data", (chunk) => {
|
|
9985
|
+
buffer += chunk.toString("utf8");
|
|
9986
|
+
const newlineIndex = buffer.indexOf(`
|
|
9987
|
+
`);
|
|
9988
|
+
if (newlineIndex < 0)
|
|
9989
|
+
return;
|
|
9990
|
+
finish(isJsonRpcResponse(buffer.slice(0, newlineIndex).trim()));
|
|
9991
|
+
});
|
|
9992
|
+
socket.once("error", () => finish(false));
|
|
9993
|
+
});
|
|
9994
|
+
}
|
|
9995
|
+
async function attestLegacyDaemonOwnership(input, deps = {}) {
|
|
9996
|
+
if (input.platform === "linux")
|
|
9997
|
+
return await attestLinuxOwnership(input, deps);
|
|
9998
|
+
if (input.platform === "darwin")
|
|
9999
|
+
return await attestMacOwnership(input, deps);
|
|
10000
|
+
return false;
|
|
10001
|
+
}
|
|
10002
|
+
async function attestLinuxOwnership(input, deps) {
|
|
10003
|
+
const readFileImpl = deps.readFile ?? readFile18;
|
|
10004
|
+
const readDirImpl = deps.readDir ?? readdir9;
|
|
10005
|
+
const readLinkImpl = deps.readLink ?? readlink5;
|
|
10006
|
+
const procNetUnix = await readText(readFileImpl, "/proc/net/unix");
|
|
10007
|
+
if (procNetUnix === null)
|
|
10008
|
+
return false;
|
|
10009
|
+
const inode = inodeForEndpoint(procNetUnix, input.endpoint);
|
|
10010
|
+
if (inode === null)
|
|
10011
|
+
return false;
|
|
10012
|
+
const fdEntries = await readDirImpl(`/proc/${input.pid}/fd`).catch(() => null);
|
|
10013
|
+
if (fdEntries === null)
|
|
10014
|
+
return false;
|
|
10015
|
+
let ownsEndpoint = false;
|
|
10016
|
+
for (const fdEntry of fdEntries) {
|
|
10017
|
+
const target = await readLinkImpl(`/proc/${input.pid}/fd/${fdEntry}`).catch(() => null);
|
|
10018
|
+
if (target !== `socket:[${inode}]`)
|
|
10019
|
+
continue;
|
|
10020
|
+
ownsEndpoint = true;
|
|
10021
|
+
break;
|
|
10022
|
+
}
|
|
10023
|
+
if (!ownsEndpoint)
|
|
10024
|
+
return false;
|
|
10025
|
+
const cmdline = await readBinary(readFileImpl, `/proc/${input.pid}/cmdline`);
|
|
10026
|
+
if (cmdline === null)
|
|
10027
|
+
return false;
|
|
10028
|
+
return isNodeCliDaemonArgv(splitCmdline(cmdline));
|
|
10029
|
+
}
|
|
10030
|
+
async function attestMacOwnership(input, deps) {
|
|
10031
|
+
const executeFileImpl = deps.executeFile ?? execFile;
|
|
10032
|
+
const filteredLsofOutput = await executeForStdout(executeFileImpl, "/usr/sbin/lsof", [
|
|
10033
|
+
"-a",
|
|
10034
|
+
"-n",
|
|
10035
|
+
"-P",
|
|
10036
|
+
"-p",
|
|
10037
|
+
String(input.pid),
|
|
10038
|
+
"-U",
|
|
10039
|
+
"-Fn",
|
|
10040
|
+
"--",
|
|
10041
|
+
input.endpoint
|
|
10042
|
+
]);
|
|
10043
|
+
const lsofOutput = filteredLsofOutput ?? await executeForStdout(executeFileImpl, "/usr/sbin/lsof", [
|
|
10044
|
+
"-a",
|
|
10045
|
+
"-n",
|
|
10046
|
+
"-P",
|
|
10047
|
+
"-p",
|
|
10048
|
+
String(input.pid),
|
|
10049
|
+
"-U",
|
|
10050
|
+
"-Fn"
|
|
10051
|
+
]);
|
|
10052
|
+
if (lsofOutput === null || !lsofShowsUnixEndpoint(lsofOutput, input.pid, input.endpoint))
|
|
10053
|
+
return false;
|
|
10054
|
+
const commandOutput = await executeForStdout(executeFileImpl, "/bin/ps", ["-p", String(input.pid), "-o", "command="]);
|
|
10055
|
+
if (commandOutput === null)
|
|
10056
|
+
return false;
|
|
10057
|
+
return isNodeCliDaemonCommand(commandOutput.trim());
|
|
10058
|
+
}
|
|
10059
|
+
function legacyStatusRequest() {
|
|
10060
|
+
return {
|
|
10061
|
+
jsonrpc: "2.0",
|
|
10062
|
+
id: 1,
|
|
10063
|
+
method: "tools/call",
|
|
10064
|
+
params: { name: "status", arguments: {} }
|
|
10065
|
+
};
|
|
10066
|
+
}
|
|
10067
|
+
function isJsonRpcResponse(line) {
|
|
10068
|
+
if (line.length === 0)
|
|
10069
|
+
return false;
|
|
9954
10070
|
try {
|
|
9955
|
-
|
|
10071
|
+
const parsed = JSON.parse(line);
|
|
10072
|
+
return parsed.jsonrpc === "2.0" && parsed.id === 1 && (Object.hasOwn(parsed, "result") || Object.hasOwn(parsed, "error"));
|
|
9956
10073
|
} catch {
|
|
9957
|
-
return
|
|
10074
|
+
return false;
|
|
9958
10075
|
}
|
|
9959
|
-
|
|
9960
|
-
|
|
9961
|
-
|
|
9962
|
-
const
|
|
9963
|
-
if (
|
|
9964
|
-
|
|
10076
|
+
}
|
|
10077
|
+
function inodeForEndpoint(procNetUnix, endpoint) {
|
|
10078
|
+
for (const line of procNetUnix.split(/\r?\n/)) {
|
|
10079
|
+
const trimmed = line.trim();
|
|
10080
|
+
if (trimmed.length === 0 || trimmed.startsWith("Num"))
|
|
10081
|
+
continue;
|
|
10082
|
+
const fields = trimmed.split(/\s+/);
|
|
10083
|
+
if (fields.length < 8 || fields[7] !== endpoint)
|
|
10084
|
+
continue;
|
|
10085
|
+
return fields[6] ?? null;
|
|
10086
|
+
}
|
|
10087
|
+
return null;
|
|
10088
|
+
}
|
|
10089
|
+
function splitCmdline(buffer) {
|
|
10090
|
+
return buffer.toString("utf8").split("\x00").filter((value) => value.length > 0);
|
|
10091
|
+
}
|
|
10092
|
+
function isNodeCliDaemonArgv(argv) {
|
|
10093
|
+
if (argv.length < 2 || !argv.includes("daemon"))
|
|
10094
|
+
return false;
|
|
10095
|
+
const executable = basename6(argv[0] ?? "");
|
|
10096
|
+
if (!/^node(?:\.exe)?$/i.test(executable))
|
|
10097
|
+
return false;
|
|
10098
|
+
return argv.some((value) => value === "cli.js" || value.endsWith("/cli.js") || value.endsWith("\\cli.js"));
|
|
10099
|
+
}
|
|
10100
|
+
function lsofShowsUnixEndpoint(output, pid, endpoint) {
|
|
10101
|
+
const lines = output.split(/\r?\n/).filter((line) => line.length > 0);
|
|
10102
|
+
const endpointName = basename6(endpoint);
|
|
10103
|
+
return lines.includes(`p${pid}`) && lines.some((line) => line === `n${endpoint}` || line === `n${endpointName}`);
|
|
10104
|
+
}
|
|
10105
|
+
function isNodeCliDaemonCommand(command) {
|
|
10106
|
+
return /\bnode(?:\.exe)?\b/i.test(command) && /\bcli\.js\b/.test(command) && /\bdaemon\b/.test(command);
|
|
10107
|
+
}
|
|
10108
|
+
async function executeForStdout(executeFileImpl, file, args) {
|
|
10109
|
+
return await new Promise((resolve8) => {
|
|
10110
|
+
executeFileImpl(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000 }, (error, stdout) => {
|
|
10111
|
+
if (error !== null) {
|
|
10112
|
+
resolve8(null);
|
|
10113
|
+
return;
|
|
10114
|
+
}
|
|
10115
|
+
resolve8(stdout);
|
|
10116
|
+
});
|
|
10117
|
+
});
|
|
10118
|
+
}
|
|
10119
|
+
async function readText(readFileImpl, path) {
|
|
10120
|
+
return await readFileImpl(path, "utf8").catch(() => null);
|
|
10121
|
+
}
|
|
10122
|
+
async function readBinary(readFileImpl, path) {
|
|
10123
|
+
return await readFileImpl(path).catch(() => null);
|
|
10124
|
+
}
|
|
10125
|
+
|
|
10126
|
+
// packages/omo-codex/src/install/lsp-daemon-reaper.ts
|
|
10127
|
+
var LEGACY_EXIT_WAIT_TIMEOUT_MS = 5000;
|
|
10128
|
+
var LEGACY_VERSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._+-]{0,127}$/;
|
|
10129
|
+
async function reapLspDaemons(codexHome, deps = {}) {
|
|
10130
|
+
const daemonRoot = join27(codexHome, "codex-lsp", "daemon");
|
|
10131
|
+
const platform = deps.platform ?? process.platform;
|
|
10132
|
+
const tmpDir = deps.tmpDir ?? tmpdir();
|
|
10133
|
+
const probe = deps.probeLegacyJsonRpc ?? probeLegacyJsonRpcEndpoint;
|
|
10134
|
+
const attest = deps.attestLegacyDaemonOwnership ?? ((input) => attestLegacyDaemonOwnership(input));
|
|
10135
|
+
const killProcess = deps.killProcess ?? sendSigterm;
|
|
10136
|
+
const waitForProcessExit = deps.waitForProcessExit ?? defaultWaitForProcessExit;
|
|
10137
|
+
const entries = await readdir10(daemonRoot, { withFileTypes: true }).catch(() => []);
|
|
10138
|
+
const results = [];
|
|
10139
|
+
for (const entry of [...entries].sort((left, right) => left.name.localeCompare(right.name))) {
|
|
10140
|
+
const versionPath = join27(daemonRoot, entry.name);
|
|
10141
|
+
const parsedVersion = parseVersionEntry(entry.name);
|
|
10142
|
+
if (parsedVersion === null || !entry.isDirectory()) {
|
|
10143
|
+
await removeVersionDir(versionPath);
|
|
10144
|
+
results.push(removed(entry.name, "removed invalid legacy version entry"));
|
|
10145
|
+
continue;
|
|
10146
|
+
}
|
|
10147
|
+
const metadata = await readLegacyMetadata({ versionPath, version: parsedVersion, codexHome, platform, tmpDir });
|
|
10148
|
+
if (metadata.kind === "remove") {
|
|
10149
|
+
await removeVersionDir(versionPath);
|
|
10150
|
+
results.push(removed(parsedVersion, metadata.reason));
|
|
10151
|
+
continue;
|
|
10152
|
+
}
|
|
10153
|
+
if (!await probe(metadata.endpoint)) {
|
|
10154
|
+
await removeVersionDir(versionPath);
|
|
10155
|
+
results.push(removed(parsedVersion, "removed stale legacy daemon state"));
|
|
10156
|
+
continue;
|
|
10157
|
+
}
|
|
10158
|
+
if (platform === "win32") {
|
|
10159
|
+
results.push(deferred(parsedVersion, "legacy named pipe responded but Windows cannot prove pid ownership safely"));
|
|
10160
|
+
continue;
|
|
9965
10161
|
}
|
|
9966
|
-
await
|
|
10162
|
+
const owned = await attest({ pid: metadata.pid, endpoint: metadata.endpoint, platform });
|
|
10163
|
+
if (!owned) {
|
|
10164
|
+
results.push(deferred(parsedVersion, "legacy endpoint responded but pid ownership was not proven"));
|
|
10165
|
+
continue;
|
|
10166
|
+
}
|
|
10167
|
+
if (!killProcess(metadata.pid)) {
|
|
10168
|
+
await removeVersionDir(versionPath);
|
|
10169
|
+
results.push(removed(parsedVersion, "removed stale legacy daemon state"));
|
|
10170
|
+
continue;
|
|
10171
|
+
}
|
|
10172
|
+
if (!await waitForProcessExit(metadata.pid, LEGACY_EXIT_WAIT_TIMEOUT_MS)) {
|
|
10173
|
+
results.push(deferred(parsedVersion, `timed out waiting ${LEGACY_EXIT_WAIT_TIMEOUT_MS}ms for the proven legacy daemon to exit`));
|
|
10174
|
+
continue;
|
|
10175
|
+
}
|
|
10176
|
+
await removeVersionDir(versionPath);
|
|
10177
|
+
results.push(terminated(parsedVersion, "terminated proven owned legacy daemon"));
|
|
9967
10178
|
}
|
|
9968
|
-
return
|
|
10179
|
+
return results;
|
|
9969
10180
|
}
|
|
9970
|
-
|
|
9971
|
-
|
|
9972
|
-
const content = (await readFile18(path, "utf8")).trim();
|
|
9973
|
-
return content.length > 0 ? content : null;
|
|
9974
|
-
} catch {
|
|
10181
|
+
function parseVersionEntry(entryName) {
|
|
10182
|
+
if (!entryName.startsWith("v"))
|
|
9975
10183
|
return null;
|
|
10184
|
+
const version = entryName.slice(1);
|
|
10185
|
+
return LEGACY_VERSION_PATTERN.test(version) ? version : null;
|
|
10186
|
+
}
|
|
10187
|
+
async function readLegacyMetadata(input) {
|
|
10188
|
+
const pidText = await readRegularTrimmedFile(join27(input.versionPath, "daemon.pid"));
|
|
10189
|
+
if (pidText === "non_regular")
|
|
10190
|
+
return { kind: "remove", reason: "removed non-regular legacy daemon metadata" };
|
|
10191
|
+
if (pidText === null)
|
|
10192
|
+
return { kind: "remove", reason: "removed malformed legacy daemon metadata" };
|
|
10193
|
+
const pid = Number.parseInt(pidText, 10);
|
|
10194
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
10195
|
+
return { kind: "remove", reason: "removed malformed legacy daemon metadata" };
|
|
10196
|
+
const endpointText = await readRegularTrimmedFile(join27(input.versionPath, "daemon.endpoint"));
|
|
10197
|
+
if (endpointText === "non_regular")
|
|
10198
|
+
return { kind: "remove", reason: "removed non-regular legacy daemon metadata" };
|
|
10199
|
+
if (endpointText === null)
|
|
10200
|
+
return { kind: "remove", reason: "removed malformed legacy daemon metadata" };
|
|
10201
|
+
const allowedEndpoints = legacyEndpointCandidates({
|
|
10202
|
+
version: input.version,
|
|
10203
|
+
versionPath: input.versionPath,
|
|
10204
|
+
platform: input.platform,
|
|
10205
|
+
tmpDir: input.tmpDir
|
|
10206
|
+
});
|
|
10207
|
+
if (!allowedEndpoints.includes(endpointText)) {
|
|
10208
|
+
return { kind: "remove", reason: "removed legacy daemon state with an endpoint outside the frozen vectors" };
|
|
9976
10209
|
}
|
|
10210
|
+
return { kind: "valid", pid, endpoint: endpointText };
|
|
9977
10211
|
}
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
const
|
|
9981
|
-
|
|
9982
|
-
|
|
9983
|
-
return null;
|
|
10212
|
+
function legacyEndpointCandidates(input) {
|
|
10213
|
+
if (input.platform === "win32") {
|
|
10214
|
+
const normalizedVersionPath = input.versionPath.replaceAll("/", "\\");
|
|
10215
|
+
const digest = shortDigest(normalizedVersionPath);
|
|
10216
|
+
return [`\\\\.\\pipe\\omo-lsp-${input.version}-${digest}`];
|
|
9984
10217
|
}
|
|
10218
|
+
const natural = posix.join(input.versionPath, "daemon.sock");
|
|
10219
|
+
const hashed = posix.join(input.tmpDir, `omo-lsp-${input.version}-${shortDigest(input.versionPath)}.sock`);
|
|
10220
|
+
return [natural, hashed];
|
|
9985
10221
|
}
|
|
9986
|
-
function
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10222
|
+
async function readRegularTrimmedFile(path) {
|
|
10223
|
+
const stats = await lstat11(path).catch(() => null);
|
|
10224
|
+
if (stats === null)
|
|
10225
|
+
return null;
|
|
10226
|
+
if (!stats.isFile())
|
|
10227
|
+
return "non_regular";
|
|
10228
|
+
const content = (await readFile19(path, "utf8")).trim();
|
|
10229
|
+
return content.length > 0 ? content : null;
|
|
10230
|
+
}
|
|
10231
|
+
function shortDigest(value) {
|
|
10232
|
+
return createHash2("sha256").update(value).digest("hex").slice(0, 16);
|
|
10233
|
+
}
|
|
10234
|
+
async function removeVersionDir(path) {
|
|
10235
|
+
await rm10(path, { recursive: true, force: true });
|
|
10236
|
+
}
|
|
10237
|
+
function removed(version, reason) {
|
|
10238
|
+
return { version, status: "removed", reason };
|
|
10239
|
+
}
|
|
10240
|
+
function terminated(version, reason) {
|
|
10241
|
+
return { version, status: "terminated", reason };
|
|
10242
|
+
}
|
|
10243
|
+
function deferred(version, reason) {
|
|
10244
|
+
return { version, status: "deferred", reason };
|
|
10004
10245
|
}
|
|
10005
10246
|
function sendSigterm(pid) {
|
|
10006
10247
|
try {
|
|
@@ -10010,6 +10251,24 @@ function sendSigterm(pid) {
|
|
|
10010
10251
|
return false;
|
|
10011
10252
|
}
|
|
10012
10253
|
}
|
|
10254
|
+
async function defaultWaitForProcessExit(pid, timeoutMs) {
|
|
10255
|
+
const deadline = Date.now() + timeoutMs;
|
|
10256
|
+
for (;; ) {
|
|
10257
|
+
if (!processIsRunning(pid))
|
|
10258
|
+
return true;
|
|
10259
|
+
if (Date.now() >= deadline)
|
|
10260
|
+
return false;
|
|
10261
|
+
await new Promise((resolve8) => setTimeout(resolve8, 100));
|
|
10262
|
+
}
|
|
10263
|
+
}
|
|
10264
|
+
function processIsRunning(pid) {
|
|
10265
|
+
try {
|
|
10266
|
+
process.kill(pid, 0);
|
|
10267
|
+
return true;
|
|
10268
|
+
} catch {
|
|
10269
|
+
return false;
|
|
10270
|
+
}
|
|
10271
|
+
}
|
|
10013
10272
|
|
|
10014
10273
|
// packages/omo-codex/src/install/codex-installer-bin-dir.ts
|
|
10015
10274
|
import { homedir } from "node:os";
|
|
@@ -10027,7 +10286,7 @@ function resolveCodexInstallerBinDir(input) {
|
|
|
10027
10286
|
}
|
|
10028
10287
|
|
|
10029
10288
|
// packages/omo-codex/src/install/codex-git-bash-hooks.ts
|
|
10030
|
-
import { readFile as
|
|
10289
|
+
import { readFile as readFile20, writeFile as writeFile11 } from "node:fs/promises";
|
|
10031
10290
|
import { join as join29 } from "node:path";
|
|
10032
10291
|
var WINDOWS_ONLY_GIT_BASH_HOOKS = new Set([
|
|
10033
10292
|
"./hooks/pre-tool-use-recommending-git-bash-mcp.json",
|
|
@@ -10037,7 +10296,7 @@ async function removeGitBashHooksOffWindows(input) {
|
|
|
10037
10296
|
if (input.platform === "win32")
|
|
10038
10297
|
return;
|
|
10039
10298
|
const manifestPath = join29(input.pluginRoot, ".codex-plugin", "plugin.json");
|
|
10040
|
-
const parsed = JSON.parse(await
|
|
10299
|
+
const parsed = JSON.parse(await readFile20(manifestPath, "utf8"));
|
|
10041
10300
|
if (!isPlainRecord(parsed) || !Array.isArray(parsed.hooks))
|
|
10042
10301
|
return;
|
|
10043
10302
|
const hooks = parsed.hooks.filter((hook) => typeof hook !== "string" || !WINDOWS_ONLY_GIT_BASH_HOOKS.has(hook));
|
|
@@ -10240,6 +10499,7 @@ async function runCodexInstaller(options = {}) {
|
|
|
10240
10499
|
return;
|
|
10241
10500
|
});
|
|
10242
10501
|
const buildSource = await shouldBuildSourcePackages(repoRoot);
|
|
10502
|
+
const versionOverride = env2.LAZYCODEX_DEV_VERSION?.trim() || undefined;
|
|
10243
10503
|
const gitBashResolution = await prepareGitBashForInstall({
|
|
10244
10504
|
platform,
|
|
10245
10505
|
env: env2,
|
|
@@ -10266,13 +10526,15 @@ async function runCodexInstaller(options = {}) {
|
|
|
10266
10526
|
manifestVersion: manifest.version,
|
|
10267
10527
|
marketplaceName: marketplace.name,
|
|
10268
10528
|
pluginName: entry.name,
|
|
10269
|
-
distributionManifest
|
|
10529
|
+
distributionManifest,
|
|
10530
|
+
versionOverride
|
|
10270
10531
|
});
|
|
10271
10532
|
validatePathSegment(version2, "plugin version");
|
|
10272
10533
|
log(`Building ${entry.name}@${version2}`);
|
|
10273
10534
|
const plugin = await installCachedPlugin({
|
|
10274
10535
|
buildSource,
|
|
10275
10536
|
codexHome,
|
|
10537
|
+
env: env2,
|
|
10276
10538
|
marketplaceName: marketplace.name,
|
|
10277
10539
|
name: entry.name,
|
|
10278
10540
|
runCommand,
|
|
@@ -10346,7 +10608,16 @@ async function runCodexInstaller(options = {}) {
|
|
|
10346
10608
|
pluginNames: marketplace.plugins.map((plugin) => plugin.name)
|
|
10347
10609
|
});
|
|
10348
10610
|
}
|
|
10349
|
-
await reapLspDaemons(codexHome).catch(() =>
|
|
10611
|
+
const legacyDaemonCleanup = await reapLspDaemons(codexHome).catch((error) => {
|
|
10612
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
10613
|
+
log(`Warning: skipped legacy Codex LSP daemon cleanup: ${message}`);
|
|
10614
|
+
return [];
|
|
10615
|
+
});
|
|
10616
|
+
for (const cleanup of legacyDaemonCleanup) {
|
|
10617
|
+
if (cleanup.status !== "deferred")
|
|
10618
|
+
continue;
|
|
10619
|
+
log(`Warning: deferred legacy Codex LSP daemon cleanup for v${cleanup.version}: ${cleanup.reason}`);
|
|
10620
|
+
}
|
|
10350
10621
|
const marketplaceRoot = join35(codexHome, "plugins", "cache", marketplace.name);
|
|
10351
10622
|
await writeCachedMarketplaceManifest({
|
|
10352
10623
|
marketplaceName: marketplace.name,
|
|
@@ -10986,7 +11257,7 @@ function readVersionManifest(path2) {
|
|
|
10986
11257
|
}
|
|
10987
11258
|
}
|
|
10988
11259
|
// packages/omo-codex/src/install/codex-git-bash-mcp-env.ts
|
|
10989
|
-
import { readFile as
|
|
11260
|
+
import { readFile as readFile21, writeFile as writeFile12 } from "node:fs/promises";
|
|
10990
11261
|
import { join as join38 } from "node:path";
|
|
10991
11262
|
var GIT_BASH_ENV_KEY2 = "OMO_CODEX_GIT_BASH_PATH";
|
|
10992
11263
|
var CODEGRAPH_RELATIVE_ARGS2 = new Set(["components/codegraph/dist/serve.js", "./components/codegraph/dist/serve.js"]);
|
|
@@ -10994,7 +11265,7 @@ async function stampGitBashMcpEnv(input) {
|
|
|
10994
11265
|
const manifestPath = join38(input.pluginRoot, ".mcp.json");
|
|
10995
11266
|
if (!await fileExistsStrict(manifestPath))
|
|
10996
11267
|
return false;
|
|
10997
|
-
const parsed = JSON.parse(await
|
|
11268
|
+
const parsed = JSON.parse(await readFile21(manifestPath, "utf8"));
|
|
10998
11269
|
if (!isPlainRecord(parsed) || !isPlainRecord(parsed["mcpServers"]))
|
|
10999
11270
|
return false;
|
|
11000
11271
|
let changed = stampCodegraphMcpPath(parsed["mcpServers"], input.pluginRoot);
|
|
@@ -11039,13 +11310,17 @@ function resolveDefaultRepoRoot() {
|
|
|
11039
11310
|
return resolveDefaultRepoRootForEntrypoint(fileURLToPath2(import.meta.url));
|
|
11040
11311
|
}
|
|
11041
11312
|
async function runLazyCodexInstallLocalCli(input) {
|
|
11313
|
+
const logWarning = (message) => {
|
|
11314
|
+
if (message.startsWith("Warning:"))
|
|
11315
|
+
input.log(message);
|
|
11316
|
+
};
|
|
11042
11317
|
const parsed = parseLazyCodexInstallCliArgs(input.argv);
|
|
11043
11318
|
if (parsed.kind === "help") {
|
|
11044
11319
|
input.log(formatLazyCodexInstallHelp());
|
|
11045
11320
|
return 0;
|
|
11046
11321
|
}
|
|
11047
11322
|
if (parsed.kind === "version") {
|
|
11048
|
-
const packageJson = JSON.parse(await
|
|
11323
|
+
const packageJson = JSON.parse(await readFile22(join39(input.defaultRepoRoot, "package.json"), "utf8"));
|
|
11049
11324
|
const version2 = typeof packageJson.version === "string" ? packageJson.version : "unknown";
|
|
11050
11325
|
input.log(`lazycodex-ai ${version2}`);
|
|
11051
11326
|
return 0;
|
|
@@ -11063,7 +11338,8 @@ async function runLazyCodexInstallLocalCli(input) {
|
|
|
11063
11338
|
const result2 = await installMarketplaceLocally({
|
|
11064
11339
|
repoRoot: resolve10(parsed.repoRoot),
|
|
11065
11340
|
autonomousPermissions: true,
|
|
11066
|
-
env: input.env
|
|
11341
|
+
env: input.env,
|
|
11342
|
+
log: logWarning
|
|
11067
11343
|
});
|
|
11068
11344
|
input.log(`Installed ${result2.installed.length} plugin(s) from ${result2.marketplaceName}.`);
|
|
11069
11345
|
return 0;
|
|
@@ -11074,7 +11350,8 @@ async function runLazyCodexInstallLocalCli(input) {
|
|
|
11074
11350
|
const result = await installMarketplaceLocally({
|
|
11075
11351
|
repoRoot,
|
|
11076
11352
|
autonomousPermissions: parsed.autonomousPermissions,
|
|
11077
|
-
env: input.env
|
|
11353
|
+
env: input.env,
|
|
11354
|
+
log: logWarning
|
|
11078
11355
|
});
|
|
11079
11356
|
input.log(`Installed ${result.installed.length} plugin(s) from ${result.marketplaceName}.`);
|
|
11080
11357
|
return 0;
|
|
@@ -32,7 +32,7 @@ Every implementation must choose one of these branches before UI code changes:
|
|
|
32
32
|
- **Embedded references:** use `references/design/_INDEX.md` to shortlist 2-3 plausible Layer B references, then read exactly one Layer A style skill and one Layer B reference in full — every line, no partial reads (they are 200-500 lines; a sliced read produces the flattened token set this gate exists to prevent). Log the shortlist, the pick, and why. Use `open-design` only when the curated set has no fit; add `ui-ux-db` lookups for palette/type/domain questions.
|
|
33
33
|
- **Lazyweb real-product screens:** READ `references/design/lazyweb.md` FIRST and run its recipe verbatim — do not improvise curl calls against lazyweb.com; the recipe mints its own anonymous token. Log the queries run, how many screens you actually VIEWED, and the layout grammar harvested — never pixel copies.
|
|
34
34
|
- **Imagen concept drafts:** generate 2-3 imagen concept drafts, each seeded with the loaded Layer A + Layer B tokens (palette, type, material); pick the strongest and treat the chosen draft as the reference-fidelity contract. Log the draft paths and the pick.
|
|
35
|
-
Synthesize every lane into `DESIGN.md`. Treat sources as source material, not mood labels: extract tokens, layout grammar, component anatomy, interaction states, motion, and taste decisions, then recombine them into project-specific primitives. Never freestyle past the selected references, never copy logos or brand-specific copy. Then run the Primitive Showcase Gate (`references/design/README.md` Phase 0) before any product screen.
|
|
35
|
+
Synthesize every lane into `DESIGN.md`. Treat sources as source material, not mood labels: extract tokens, layout grammar, component anatomy, interaction states, motion, and taste decisions, then recombine them into project-specific primitives. Before laying out sections, inventory the content blocks and assign each a job — hook, explain, prove, compare, convert, navigate, retain — then order sections by the visitor's decision path, not by visual symmetry. Never freestyle past the selected references, never copy logos or brand-specific copy. Then run the Primitive Showcase Gate (`references/design/README.md` Phase 0) before any product screen.
|
|
36
36
|
3. **Existing project with `DESIGN.md` or a component system:** read it, follow it, and update it before implementation only when the requested work needs a new token, primitive, state, motion rule, accessibility constraint, accepted debt, or reference-fidelity requirement.
|
|
37
37
|
4. **Existing project with UI but no `DESIGN.md` and no reusable component layer:** STOP and ask the user one focused question: should you preserve the current look with copy-nearby styling, or extract a real `DESIGN.md` plus reusable components before continuing? Do not silently choose.
|
|
38
38
|
|