oh-my-opencode 5.1.61 → 5.1.62
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/command/remove-deadcode.md +1 -1
- package/.agents/skills/remove-deadcode/SKILL.md +1 -1
- package/.opencode/command/remove-deadcode.md +1 -1
- package/dist/cli/index.js +154 -27
- package/dist/cli/service-auth/index.d.ts +2 -1
- package/dist/cli/service-auth/session.d.ts +27 -0
- package/dist/cli/service-auth/sync-pin-retire.d.ts +7 -0
- package/dist/cli-node/index.js +154 -27
- package/dist/config/schema/agent-names.d.ts +1 -0
- package/dist/index.js +645 -189
- package/dist/skills/browser/references/owned-engine/README.md +1 -1
- package/dist/skills/browser/runtime/omowright/manifest.json +1 -1
- package/dist/skills/frontend/SKILL.md +2 -2
- package/dist/skills/frontend/references/design/README.md +2 -2
- package/dist/skills/frontend/references/design/component-catalogs.md +1 -1
- package/dist/skills/frontend/references/design/design-system-architecture.md +1 -1
- package/dist/skills/frontend/references/design/react-dev-tooling-skill.md +1 -1
- package/dist/skills/frontend/references/designpowers/lane-a-direction.md +5 -5
- package/dist/skills/frontend/references/designpowers/routing.md +2 -2
- package/dist/skills/frontend/references/perfection/README.md +1 -1
- package/dist/skills/programming/references/python/libraries.md +3 -3
- package/dist/skills/programming/references/python/one-liners.md +1 -1
- package/dist/skills/programming/references/python/pyproject-strict.md +1 -1
- package/dist/skills/programming/references/rust/libraries.md +2 -2
- package/dist/skills/refactor/SKILL.md +1 -1
- package/dist/skills/ultimate-browsing/SKILL.md +1 -1
- package/dist/skills/ultimate-browsing/references/insane-search/README.md +1 -1
- package/dist/skills/ulw-execute/SKILL.md +1 -1
- package/dist/skills/ulw-research/SKILL.md +2 -2
- package/dist/tui.js +15 -14
- package/package.json +14 -14
- 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/lcx/skills/lcx-doctor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- 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/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/references/owned-engine/README.md +1 -1
- package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/references/design/component-catalogs.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/design/react-dev-tooling-skill.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +5 -5
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +2 -2
- package/packages/omo-codex/plugin/skills/frontend/references/perfection/README.md +1 -1
- package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/programming/references/python/libraries.md +3 -3
- package/packages/omo-codex/plugin/skills/programming/references/python/one-liners.md +1 -1
- package/packages/omo-codex/plugin/skills/programming/references/python/pyproject-strict.md +1 -1
- package/packages/omo-codex/plugin/skills/programming/references/rust/libraries.md +2 -2
- package/packages/omo-codex/plugin/skills/refactor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-execute/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +2 -2
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
- package/packages/shared-skills/skills/browser/references/owned-engine/README.md +1 -1
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/shared-skills/skills/frontend/SKILL.md +2 -2
- package/packages/shared-skills/skills/frontend/references/design/README.md +2 -2
- package/packages/shared-skills/skills/frontend/references/design/component-catalogs.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +1 -1
- package/packages/shared-skills/skills/frontend/references/design/react-dev-tooling-skill.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +5 -5
- package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +2 -2
- package/packages/shared-skills/skills/frontend/references/perfection/README.md +1 -1
- package/packages/shared-skills/skills/programming/references/python/libraries.md +3 -3
- package/packages/shared-skills/skills/programming/references/python/one-liners.md +1 -1
- package/packages/shared-skills/skills/programming/references/python/pyproject-strict.md +1 -1
- package/packages/shared-skills/skills/programming/references/rust/libraries.md +2 -2
- package/packages/shared-skills/skills/refactor/SKILL.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +1 -1
- package/packages/shared-skills/skills/ulw-execute/SKILL.md +1 -1
- package/packages/shared-skills/skills/ulw-research/SKILL.md +2 -2
- package/.opencode/skills/hyperplan/SKILL.md +0 -450
|
@@ -114,7 +114,7 @@ For EACH batch, fire a deep agent:
|
|
|
114
114
|
```
|
|
115
115
|
task(
|
|
116
116
|
category="deep-low",
|
|
117
|
-
load_skills=["
|
|
117
|
+
load_skills=["programming", "git-master"],
|
|
118
118
|
run_in_background=true,
|
|
119
119
|
description="Remove dead code batch N: [brief description]",
|
|
120
120
|
prompt="[see template below]"
|
|
@@ -114,7 +114,7 @@ For EACH batch, fire a deep agent:
|
|
|
114
114
|
```
|
|
115
115
|
task(
|
|
116
116
|
category="deep-low",
|
|
117
|
-
load_skills=["
|
|
117
|
+
load_skills=["programming", "git-master"],
|
|
118
118
|
run_in_background=true,
|
|
119
119
|
description="Remove dead code batch N: [brief description]",
|
|
120
120
|
prompt="[see template below]"
|
|
@@ -114,7 +114,7 @@ For EACH batch, fire a deep agent:
|
|
|
114
114
|
```
|
|
115
115
|
task(
|
|
116
116
|
category="deep",
|
|
117
|
-
load_skills=["
|
|
117
|
+
load_skills=["programming", "git-master"],
|
|
118
118
|
run_in_background=true,
|
|
119
119
|
description="Remove dead code batch N: [brief description]",
|
|
120
120
|
prompt="[see template below]"
|
package/dist/cli/index.js
CHANGED
|
@@ -2132,7 +2132,7 @@ var package_default;
|
|
|
2132
2132
|
var init_package = __esm(() => {
|
|
2133
2133
|
package_default = {
|
|
2134
2134
|
name: "oh-my-opencode",
|
|
2135
|
-
version: "5.1.
|
|
2135
|
+
version: "5.1.62",
|
|
2136
2136
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
2137
2137
|
main: "./dist/index.js",
|
|
2138
2138
|
types: "dist/index.d.ts",
|
|
@@ -2319,7 +2319,7 @@ var init_package = __esm(() => {
|
|
|
2319
2319
|
},
|
|
2320
2320
|
devDependencies: {
|
|
2321
2321
|
"@clack/prompts": "^1.8.1",
|
|
2322
|
-
"@code-yeongyu/senpi": "2026.11.
|
|
2322
|
+
"@code-yeongyu/senpi": "2026.11.5-1",
|
|
2323
2323
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
2324
2324
|
"@oh-my-opencode/agents-md-core": "workspace:*",
|
|
2325
2325
|
"@oh-my-opencode/ast-grep-mcp": "workspace:*",
|
|
@@ -2384,18 +2384,18 @@ var init_package = __esm(() => {
|
|
|
2384
2384
|
typescript: "^7.0.2"
|
|
2385
2385
|
},
|
|
2386
2386
|
optionalDependencies: {
|
|
2387
|
-
"oh-my-opencode-darwin-arm64": "5.1.
|
|
2388
|
-
"oh-my-opencode-darwin-x64": "5.1.
|
|
2389
|
-
"oh-my-opencode-darwin-x64-baseline": "5.1.
|
|
2390
|
-
"oh-my-opencode-linux-arm64": "5.1.
|
|
2391
|
-
"oh-my-opencode-linux-arm64-musl": "5.1.
|
|
2392
|
-
"oh-my-opencode-linux-x64": "5.1.
|
|
2393
|
-
"oh-my-opencode-linux-x64-baseline": "5.1.
|
|
2394
|
-
"oh-my-opencode-linux-x64-musl": "5.1.
|
|
2395
|
-
"oh-my-opencode-linux-x64-musl-baseline": "5.1.
|
|
2396
|
-
"oh-my-opencode-windows-arm64": "5.1.
|
|
2397
|
-
"oh-my-opencode-windows-x64": "5.1.
|
|
2398
|
-
"oh-my-opencode-windows-x64-baseline": "5.1.
|
|
2387
|
+
"oh-my-opencode-darwin-arm64": "5.1.62",
|
|
2388
|
+
"oh-my-opencode-darwin-x64": "5.1.62",
|
|
2389
|
+
"oh-my-opencode-darwin-x64-baseline": "5.1.62",
|
|
2390
|
+
"oh-my-opencode-linux-arm64": "5.1.62",
|
|
2391
|
+
"oh-my-opencode-linux-arm64-musl": "5.1.62",
|
|
2392
|
+
"oh-my-opencode-linux-x64": "5.1.62",
|
|
2393
|
+
"oh-my-opencode-linux-x64-baseline": "5.1.62",
|
|
2394
|
+
"oh-my-opencode-linux-x64-musl": "5.1.62",
|
|
2395
|
+
"oh-my-opencode-linux-x64-musl-baseline": "5.1.62",
|
|
2396
|
+
"oh-my-opencode-windows-arm64": "5.1.62",
|
|
2397
|
+
"oh-my-opencode-windows-x64": "5.1.62",
|
|
2398
|
+
"oh-my-opencode-windows-x64-baseline": "5.1.62"
|
|
2399
2399
|
},
|
|
2400
2400
|
overrides: {
|
|
2401
2401
|
hono: "^4.13.8",
|
|
@@ -92710,7 +92710,7 @@ var package_default2;
|
|
|
92710
92710
|
var init_package2 = __esm(() => {
|
|
92711
92711
|
package_default2 = {
|
|
92712
92712
|
name: "@oh-my-opencode/omo-codex",
|
|
92713
|
-
version: "5.1.
|
|
92713
|
+
version: "5.1.62",
|
|
92714
92714
|
type: "module",
|
|
92715
92715
|
private: true,
|
|
92716
92716
|
description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
|
|
@@ -104373,6 +104373,7 @@ var BuiltinSkillNameSchema = _enum([
|
|
|
104373
104373
|
"debugging",
|
|
104374
104374
|
"security-research",
|
|
104375
104375
|
"security-review",
|
|
104376
|
+
"hyperplan",
|
|
104376
104377
|
"visual-qa",
|
|
104377
104378
|
"team-mode"
|
|
104378
104379
|
]);
|
|
@@ -109471,8 +109472,8 @@ var package_default3 = {
|
|
|
109471
109472
|
},
|
|
109472
109473
|
dependencies: {
|
|
109473
109474
|
"@clack/prompts": "^1.8.1",
|
|
109474
|
-
"@code-yeongyu/senpi": "2026.11.
|
|
109475
|
-
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.11.
|
|
109475
|
+
"@code-yeongyu/senpi": "2026.11.5-1",
|
|
109476
|
+
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.11.5-1",
|
|
109476
109477
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
109477
109478
|
"@oh-my-opencode/agents-md-core": "workspace:*",
|
|
109478
109479
|
"@oh-my-opencode/boulder-state": "workspace:*",
|
|
@@ -112744,6 +112745,24 @@ function retryOnEintrSync(operation) {
|
|
|
112744
112745
|
|
|
112745
112746
|
// packages/memory-core/src/fs/rename-contention.ts
|
|
112746
112747
|
var CONTENTION_CODES = new Set(["EPERM", "EBUSY", "EACCES"]);
|
|
112748
|
+
var CONTENTION_DELAYS_MS = [10, 25, 50, 100, 200, 400];
|
|
112749
|
+
var sleepFor = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
112750
|
+
async function renameWithContentionRetry(from, to, deps) {
|
|
112751
|
+
const delays = deps.platform === "win32" ? deps.delaysMs ?? CONTENTION_DELAYS_MS : [];
|
|
112752
|
+
const sleep = deps.sleep ?? sleepFor;
|
|
112753
|
+
for (let attempt = 0;; attempt += 1) {
|
|
112754
|
+
try {
|
|
112755
|
+
await retryOnEintr(() => deps.admit === undefined ? deps.rename(from, to) : deps.admit(() => deps.rename(from, to)));
|
|
112756
|
+
return;
|
|
112757
|
+
} catch (error) {
|
|
112758
|
+
const delay = delays[attempt];
|
|
112759
|
+
const code = fsErrorCode(error);
|
|
112760
|
+
if (delay === undefined || code === undefined || !CONTENTION_CODES.has(code))
|
|
112761
|
+
throw error;
|
|
112762
|
+
await sleep(delay);
|
|
112763
|
+
}
|
|
112764
|
+
}
|
|
112765
|
+
}
|
|
112747
112766
|
|
|
112748
112767
|
// packages/memory-core/src/fs/resilient.ts
|
|
112749
112768
|
function isFunction2(value) {
|
|
@@ -112776,6 +112795,13 @@ function resilientNamespace(namespace, kind) {
|
|
|
112776
112795
|
}
|
|
112777
112796
|
var IDEMPOTENT_HANDLE_METHODS = new Set(["stat", "sync", "datasync", "chmod", "chown", "utimes", "truncate"]);
|
|
112778
112797
|
var promises = resilientNamespace(fsp, "async");
|
|
112798
|
+
function rename8(from, to, admit) {
|
|
112799
|
+
return renameWithContentionRetry(from, to, {
|
|
112800
|
+
rename: (source, target) => fsp.rename(source, target),
|
|
112801
|
+
platform: process.platform,
|
|
112802
|
+
...admit === undefined ? {} : { admit }
|
|
112803
|
+
});
|
|
112804
|
+
}
|
|
112779
112805
|
var sync = resilientNamespace(fsSync, "sync");
|
|
112780
112806
|
var {
|
|
112781
112807
|
access: access3,
|
|
@@ -113671,15 +113697,60 @@ async function loginLoopback(session, options) {
|
|
|
113671
113697
|
}
|
|
113672
113698
|
}
|
|
113673
113699
|
|
|
113674
|
-
// packages/
|
|
113700
|
+
// packages/memory-core/src/sync/device-retire.ts
|
|
113701
|
+
import { createHash as createHash14, randomBytes as randomBytes6 } from "crypto";
|
|
113702
|
+
import { join as join109 } from "path";
|
|
113703
|
+
|
|
113704
|
+
// packages/memory-core/src/identity/layout.ts
|
|
113675
113705
|
import { homedir as homedir32 } from "os";
|
|
113706
|
+
import { join as join107, resolve as resolve31 } from "path";
|
|
113707
|
+
var MEMORY_ROOT_ENV_VAR = "OMO_MEMORY_HOME";
|
|
113708
|
+
function defaultMemoryRoot() {
|
|
113709
|
+
return join107(homedir32(), ".omo", "memory");
|
|
113710
|
+
}
|
|
113711
|
+
function resolveMemoryRoot(env, cwd) {
|
|
113712
|
+
const override = env[MEMORY_ROOT_ENV_VAR];
|
|
113713
|
+
if (override === undefined || override.trim() === "") {
|
|
113714
|
+
return defaultMemoryRoot();
|
|
113715
|
+
}
|
|
113716
|
+
return resolve31(cwd, override);
|
|
113717
|
+
}
|
|
113718
|
+
// packages/memory-core/src/sync/pin-dir.ts
|
|
113719
|
+
import { join as join108 } from "path";
|
|
113720
|
+
var syncPinDir = (memoryRoot) => join108(memoryRoot, "sync-device");
|
|
113721
|
+
|
|
113722
|
+
// packages/memory-core/src/sync/device-retire.ts
|
|
113723
|
+
var trustAnchorRoot = (pinDir) => join109(pinDir, "trust-anchor");
|
|
113724
|
+
var trustAnchorKey = (account) => createHash14("sha256").update(account, "utf8").digest("base64url");
|
|
113725
|
+
var trustAnchorDir = (pinDir, account) => join109(trustAnchorRoot(pinDir), trustAnchorKey(account));
|
|
113726
|
+
var hasLiveTrustAnchor = async (pinDir) => {
|
|
113727
|
+
try {
|
|
113728
|
+
return (await readdir17(trustAnchorRoot(pinDir))).some((name) => !name.includes(".retired-"));
|
|
113729
|
+
} catch (error) {
|
|
113730
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
113731
|
+
return false;
|
|
113732
|
+
throw error;
|
|
113733
|
+
}
|
|
113734
|
+
};
|
|
113735
|
+
var retireSyncDevice = async (input) => {
|
|
113736
|
+
const dir = trustAnchorDir(input.pinDir, input.account);
|
|
113737
|
+
try {
|
|
113738
|
+
await rename8(dir, `${dir}.retired-${Date.now()}-${randomBytes6(4).toString("hex")}`);
|
|
113739
|
+
} catch (error) {
|
|
113740
|
+
if (!(error instanceof Error && ("code" in error) && error.code === "ENOENT"))
|
|
113741
|
+
throw error;
|
|
113742
|
+
}
|
|
113743
|
+
};
|
|
113744
|
+
|
|
113745
|
+
// packages/omo-opencode/src/cli/service-auth/session.ts
|
|
113746
|
+
import { homedir as homedir33 } from "os";
|
|
113676
113747
|
|
|
113677
113748
|
// packages/omo-opencode/src/cli/service-auth/signed-out-marker.ts
|
|
113678
113749
|
init_zod();
|
|
113679
|
-
import { mkdir as mkdir12, readFile as readFile35, rename as
|
|
113680
|
-
import { dirname as dirname43, join as
|
|
113750
|
+
import { mkdir as mkdir12, readFile as readFile35, rename as rename9, rm as rm17, writeFile as writeFile17 } from "fs/promises";
|
|
113751
|
+
import { dirname as dirname43, join as join110 } from "path";
|
|
113681
113752
|
var markerSchema = object({ device: string2().nullable(), at: string2() });
|
|
113682
|
-
var signedOutMarkerPath = (home, credential) =>
|
|
113753
|
+
var signedOutMarkerPath = (home, credential) => join110(home, ".omo", "account-state", `${credential}.signed-out.json`);
|
|
113683
113754
|
async function readSignedOutMarker(path) {
|
|
113684
113755
|
const text = await readFile35(path, "utf8").catch(() => null);
|
|
113685
113756
|
if (text === null)
|
|
@@ -113697,7 +113768,7 @@ async function writeSignedOutMarker(path, device) {
|
|
|
113697
113768
|
await mkdir12(dirname43(path), { recursive: true, mode: 448 });
|
|
113698
113769
|
const staging = `${path}.${process.pid}.tmp`;
|
|
113699
113770
|
await writeFile17(staging, JSON.stringify({ device, at: new Date().toISOString() }), { mode: 384 });
|
|
113700
|
-
await
|
|
113771
|
+
await rename9(staging, path);
|
|
113701
113772
|
}
|
|
113702
113773
|
var clearSignedOutMarker = (path) => rm17(path, { force: true });
|
|
113703
113774
|
|
|
@@ -113712,11 +113783,18 @@ class SessionEnded extends SignInError {
|
|
|
113712
113783
|
}
|
|
113713
113784
|
}
|
|
113714
113785
|
var DEVICE_REVOKING_REFUSALS = new Set(["account_deleted", "reauth_required", "device_revoked"]);
|
|
113786
|
+
var discardedOf = (credentials, cause) => ({
|
|
113787
|
+
kind: "credential",
|
|
113788
|
+
deviceId: credentials.device.id,
|
|
113789
|
+
accountId: credentials.accountId,
|
|
113790
|
+
owner: credentials.owner,
|
|
113791
|
+
cause
|
|
113792
|
+
});
|
|
113715
113793
|
function createSession(options) {
|
|
113716
113794
|
const api = serviceOrigin(options.api);
|
|
113717
113795
|
const now = options.now ?? Date.now;
|
|
113718
|
-
const { store, signal } = options;
|
|
113719
|
-
const markerPath = signedOutMarkerPath(options.home ??
|
|
113796
|
+
const { store, signal, beforeKeysDiscarded } = options;
|
|
113797
|
+
const markerPath = signedOutMarkerPath(options.home ?? homedir33(), credentialId(api));
|
|
113720
113798
|
async function locked(action) {
|
|
113721
113799
|
signal?.throwIfAborted();
|
|
113722
113800
|
return withCredentialLock(api, async () => {
|
|
@@ -113725,6 +113803,11 @@ function createSession(options) {
|
|
|
113725
113803
|
}, options.home);
|
|
113726
113804
|
}
|
|
113727
113805
|
const request = (path, init) => requestApi(api, path, init, signal);
|
|
113806
|
+
const accountOf = async (access) => {
|
|
113807
|
+
const body = await request("/v1/me", { headers: { authorization: `Bearer ${access}` } }).catch(() => null);
|
|
113808
|
+
const id = typeof body === "object" && body !== null && "account" in body && typeof body.account === "object" && body.account !== null && "id" in body.account ? body.account.id : undefined;
|
|
113809
|
+
return typeof id === "string" && id !== "" ? id : undefined;
|
|
113810
|
+
};
|
|
113728
113811
|
async function refreshed(current) {
|
|
113729
113812
|
if (current.refreshState === "uncertain" || current.refreshAttempt !== undefined) {
|
|
113730
113813
|
throw new SessionEnded(`Refresh recovery can no longer be proved safe. ${signInHint("again")}`, false, "refresh_recovery_expired");
|
|
@@ -113741,6 +113824,7 @@ function createSession(options) {
|
|
|
113741
113824
|
if (error instanceof CredentialStoreError)
|
|
113742
113825
|
throw error;
|
|
113743
113826
|
if (error instanceof ApiRefusal && error.status < 500 && ["unauthorized", "account_deleted", "reauth_required", "invalid_grant", "device_revoked"].includes(error.code)) {
|
|
113827
|
+
await beforeKeysDiscarded(discardedOf(current, "refused"));
|
|
113744
113828
|
await store.clear();
|
|
113745
113829
|
throw new SessionEnded(error.code === "reauth_required" ? `This session was ended because its refresh token was reused. ${signInHint("again")}` : refusalMessage(refusalGuidance(error.code, error.status)), DEVICE_REVOKING_REFUSALS.has(error.code), error.code);
|
|
113746
113830
|
}
|
|
@@ -113766,6 +113850,17 @@ function createSession(options) {
|
|
|
113766
113850
|
},
|
|
113767
113851
|
async save(value) {
|
|
113768
113852
|
await locked(async () => {
|
|
113853
|
+
let stored;
|
|
113854
|
+
try {
|
|
113855
|
+
stored = await store.readAuthoritative();
|
|
113856
|
+
} catch (error) {
|
|
113857
|
+
if (!(error instanceof InvalidCredentialState))
|
|
113858
|
+
throw error;
|
|
113859
|
+
await beforeKeysDiscarded({ kind: "unreadable" });
|
|
113860
|
+
stored = null;
|
|
113861
|
+
}
|
|
113862
|
+
if (stored !== null && stored.device.id !== value.device.id)
|
|
113863
|
+
await beforeKeysDiscarded(discardedOf(stored, "replaced"));
|
|
113769
113864
|
await store.write(value);
|
|
113770
113865
|
await clearSignedOutMarker(markerPath);
|
|
113771
113866
|
});
|
|
@@ -113792,12 +113887,16 @@ function createSession(options) {
|
|
|
113792
113887
|
async logout() {
|
|
113793
113888
|
return locked(async () => {
|
|
113794
113889
|
let current = null;
|
|
113890
|
+
let account;
|
|
113795
113891
|
try {
|
|
113796
113892
|
current = await store.readAuthoritative();
|
|
113797
113893
|
if (current !== null) {
|
|
113798
113894
|
if (current.refreshState === "uncertain")
|
|
113799
113895
|
return false;
|
|
113800
113896
|
const access = Date.parse(current.accessTokenExpiresAt) <= now() ? (await refreshed(current)).accessToken : current.accessToken;
|
|
113897
|
+
if (current.accountId === undefined && current.owner === undefined && await beforeKeysDiscarded.wantsAccount?.() === true) {
|
|
113898
|
+
account = await accountOf(access);
|
|
113899
|
+
}
|
|
113801
113900
|
await request(`/v1/devices/${encodeURIComponent(current.device.id)}`, {
|
|
113802
113901
|
method: "DELETE",
|
|
113803
113902
|
headers: { authorization: `Bearer ${access}` }
|
|
@@ -113812,6 +113911,9 @@ function createSession(options) {
|
|
|
113812
113911
|
throw error;
|
|
113813
113912
|
} finally {
|
|
113814
113913
|
await writeSignedOutMarker(markerPath, current?.device.id ?? null);
|
|
113914
|
+
const stored = current === null ? null : await store.read().catch(() => current);
|
|
113915
|
+
if (stored !== null)
|
|
113916
|
+
await beforeKeysDiscarded(discardedOf(stored.accountId === undefined && account !== undefined ? { ...stored, accountId: account } : stored, "logout"));
|
|
113815
113917
|
await store.clear();
|
|
113816
113918
|
}
|
|
113817
113919
|
});
|
|
@@ -113848,6 +113950,26 @@ function createSession(options) {
|
|
|
113848
113950
|
};
|
|
113849
113951
|
}
|
|
113850
113952
|
|
|
113953
|
+
// packages/omo-opencode/src/cli/service-auth/sync-pin-retire.ts
|
|
113954
|
+
var reason = (error) => error instanceof Error && ("code" in error) && typeof error.code === "string" ? error.code : "unknown";
|
|
113955
|
+
function retireSyncPinOnDiscard(options) {
|
|
113956
|
+
const hook = async (discarded) => {
|
|
113957
|
+
if (discarded.kind === "unreadable") {
|
|
113958
|
+
options.log("memory sync: a stored sign-in could not be read while it was replaced; its sync pin was left in place");
|
|
113959
|
+
return;
|
|
113960
|
+
}
|
|
113961
|
+
const account = discarded.owner?.accountId ?? discarded.accountId;
|
|
113962
|
+
if (account === undefined)
|
|
113963
|
+
return;
|
|
113964
|
+
try {
|
|
113965
|
+
await retireSyncDevice({ pinDir: options.pinDir(), account });
|
|
113966
|
+
} catch (error) {
|
|
113967
|
+
options.log(`memory sync: the sync pin could not be retired (${reason(error)}); it was left in place`);
|
|
113968
|
+
}
|
|
113969
|
+
};
|
|
113970
|
+
return Object.assign(hook, { wantsAccount: () => hasLiveTrustAnchor(options.pinDir()).catch(() => false) });
|
|
113971
|
+
}
|
|
113972
|
+
|
|
113851
113973
|
// packages/omo-opencode/src/cli/service-auth/commands.ts
|
|
113852
113974
|
async function ensureServiceAvailable(session, api) {
|
|
113853
113975
|
try {
|
|
@@ -113890,7 +114012,12 @@ async function run2(action, options) {
|
|
|
113890
114012
|
try {
|
|
113891
114013
|
const api = serviceOrigin(options.api ?? process.env.OMO_SERVICE_API_URL ?? "https://api.omo.dev");
|
|
113892
114014
|
const store = createCredentialStore(api, { wait: INTERACTIVE_READ_WAIT });
|
|
113893
|
-
const session = createSession({
|
|
114015
|
+
const session = createSession({
|
|
114016
|
+
api,
|
|
114017
|
+
store,
|
|
114018
|
+
signal: controller.signal,
|
|
114019
|
+
beforeKeysDiscarded: retireSyncPinOnDiscard({ pinDir: () => syncPinDir(resolveMemoryRoot(process.env, process.cwd())), log: (line) => console.error(line) })
|
|
114020
|
+
});
|
|
113894
114021
|
if (action === "logout") {
|
|
113895
114022
|
const revoked = await session.logout();
|
|
113896
114023
|
console.log("Signed out of OmO. Stored credentials and device keys were removed.");
|
|
@@ -114158,11 +114285,11 @@ async function boulder(options) {
|
|
|
114158
114285
|
// packages/omo-opencode/src/cli/codex-ulw-loop.ts
|
|
114159
114286
|
import { spawn as spawn6 } from "child_process";
|
|
114160
114287
|
import { existsSync as existsSync67, readFileSync as readFileSync45, realpathSync as realpathSync14 } from "fs";
|
|
114161
|
-
import { homedir as
|
|
114288
|
+
import { homedir as homedir34 } from "os";
|
|
114162
114289
|
var ULW_LOOP_DELEGATION_SENTINEL = "OMO_ULW_LOOP_DELEGATED";
|
|
114163
114290
|
function resolveCodexUlwLoopCommand(input = {}) {
|
|
114164
114291
|
const env = input.env ?? process.env;
|
|
114165
|
-
const homeDir = input.homeDir ??
|
|
114292
|
+
const homeDir = input.homeDir ?? homedir34();
|
|
114166
114293
|
const localComponentBin = resolveLocalUlwLoopBin(env, homeDir);
|
|
114167
114294
|
if (localComponentBin !== null)
|
|
114168
114295
|
return { executable: localComponentBin, argsPrefix: [] };
|
|
@@ -2,4 +2,5 @@ export { credentialLockPaths, withCredentialLock } from "./credential-lock";
|
|
|
2
2
|
export { currentServiceDevice } from "./protocol";
|
|
3
3
|
export { CredentialIdentityChanged, type CredentialStore, createCredentialStore, KeychainApprovalPendingError, quietNotice } from "./keystore";
|
|
4
4
|
export { type Credentials, SignInError, serviceOrigin } from "./protocol";
|
|
5
|
-
export { createSession, type Session } from "./session";
|
|
5
|
+
export { type BeforeKeysDiscarded, createSession, type DiscardedCredential, type Session } from "./session";
|
|
6
|
+
export { retireSyncPinOnDiscard } from "./sync-pin-retire";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CredentialOwner } from "./credential-owner";
|
|
1
2
|
import { type CredentialStore } from "./keystore";
|
|
2
3
|
import { type ChooseDevice, type Credentials, SignInError } from "./protocol";
|
|
3
4
|
export declare class SessionEnded extends SignInError {
|
|
@@ -5,12 +6,33 @@ export declare class SessionEnded extends SignInError {
|
|
|
5
6
|
readonly code: string;
|
|
6
7
|
constructor(message: string, deviceRevoked: boolean, code: string);
|
|
7
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* A stored principal whose private keys are about to be discarded (#12280), or a stored item that
|
|
11
|
+
* could not be read when a save replaced it. The hook retires that principal's memory-sync pin; it
|
|
12
|
+
* never throws, so a failure to retire never blocks the discard.
|
|
13
|
+
*/
|
|
14
|
+
export type DiscardedCredential = {
|
|
15
|
+
readonly kind: "credential";
|
|
16
|
+
readonly deviceId: string;
|
|
17
|
+
readonly accountId: string | undefined;
|
|
18
|
+
readonly owner: CredentialOwner | undefined;
|
|
19
|
+
readonly cause: "refused" | "forget" | "logout" | "replaced";
|
|
20
|
+
} | {
|
|
21
|
+
readonly kind: "unreadable";
|
|
22
|
+
};
|
|
23
|
+
export type BeforeKeysDiscarded = ((discarded: DiscardedCredential) => Promise<void>) & {
|
|
24
|
+
/** Whether a sign-in that names no account should have it read before logout revokes the device. */
|
|
25
|
+
readonly wantsAccount?: () => Promise<boolean>;
|
|
26
|
+
};
|
|
27
|
+
export declare const discardedOf: (credentials: Credentials, cause: "refused" | "forget" | "logout" | "replaced") => DiscardedCredential;
|
|
8
28
|
export declare function createSession(options: {
|
|
9
29
|
readonly api: string;
|
|
10
30
|
readonly store: CredentialStore;
|
|
11
31
|
readonly home?: string;
|
|
12
32
|
readonly signal?: AbortSignal;
|
|
13
33
|
readonly now?: () => number;
|
|
34
|
+
/** Runs inside the credential lock immediately before a stored principal's keys are discarded. */
|
|
35
|
+
readonly beforeKeysDiscarded: BeforeKeysDiscarded;
|
|
14
36
|
}): {
|
|
15
37
|
request: (path: string, init: RequestInit) => Promise<unknown>;
|
|
16
38
|
signal: AbortSignal | undefined;
|
|
@@ -26,6 +48,11 @@ export declare function createSession(options: {
|
|
|
26
48
|
update<T>(action: (current: Credentials | null) => Promise<T>, options?: {
|
|
27
49
|
readonly replaceInvalid?: boolean;
|
|
28
50
|
}): Promise<T>;
|
|
51
|
+
/**
|
|
52
|
+
* Deletes the item without reading it (a corrupt or locked item must still be removable, with one
|
|
53
|
+
* native call), so it cannot name the account whose pin to retire: `omo account forget --device`
|
|
54
|
+
* and `logout` read first and retire; this one leaves the pin (a stale pin is harmless for keys).
|
|
55
|
+
*/
|
|
29
56
|
forget(): Promise<void>;
|
|
30
57
|
accessSnapshot: () => Promise<Credentials | null>;
|
|
31
58
|
logout(): Promise<boolean>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BeforeKeysDiscarded } from "./session";
|
|
2
|
+
export declare function retireSyncPinOnDiscard(options: {
|
|
3
|
+
/** The trust-pin directory of the memory root the caller already resolves. */
|
|
4
|
+
readonly pinDir: () => string;
|
|
5
|
+
/** The caller's own logger; one line per pin it could not retire. */
|
|
6
|
+
readonly log: (line: string) => void;
|
|
7
|
+
}): BeforeKeysDiscarded;
|