oh-my-codex 0.21.24 → 0.21.25
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/Cargo.lock +6 -6
- package/Cargo.toml +1 -1
- package/dist/team/__tests__/state.test.js +160 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/state/mailbox.d.ts.map +1 -1
- package/dist/team/state/mailbox.js +41 -4
- package/dist/team/state/mailbox.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
package/Cargo.lock
CHANGED
|
@@ -32,7 +32,7 @@ checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
|
32
32
|
|
|
33
33
|
[[package]]
|
|
34
34
|
name = "omx-api"
|
|
35
|
-
version = "0.21.
|
|
35
|
+
version = "0.21.25"
|
|
36
36
|
dependencies = [
|
|
37
37
|
"serde",
|
|
38
38
|
"serde_json",
|
|
@@ -40,14 +40,14 @@ dependencies = [
|
|
|
40
40
|
|
|
41
41
|
[[package]]
|
|
42
42
|
name = "omx-explore-harness"
|
|
43
|
-
version = "0.21.
|
|
43
|
+
version = "0.21.25"
|
|
44
44
|
dependencies = [
|
|
45
45
|
"libc",
|
|
46
46
|
]
|
|
47
47
|
|
|
48
48
|
[[package]]
|
|
49
49
|
name = "omx-mux"
|
|
50
|
-
version = "0.21.
|
|
50
|
+
version = "0.21.25"
|
|
51
51
|
dependencies = [
|
|
52
52
|
"serde",
|
|
53
53
|
"serde_json",
|
|
@@ -55,7 +55,7 @@ dependencies = [
|
|
|
55
55
|
|
|
56
56
|
[[package]]
|
|
57
57
|
name = "omx-runtime"
|
|
58
|
-
version = "0.21.
|
|
58
|
+
version = "0.21.25"
|
|
59
59
|
dependencies = [
|
|
60
60
|
"fs2",
|
|
61
61
|
"libc",
|
|
@@ -67,7 +67,7 @@ dependencies = [
|
|
|
67
67
|
|
|
68
68
|
[[package]]
|
|
69
69
|
name = "omx-runtime-core"
|
|
70
|
-
version = "0.21.
|
|
70
|
+
version = "0.21.25"
|
|
71
71
|
dependencies = [
|
|
72
72
|
"fs2",
|
|
73
73
|
"serde",
|
|
@@ -76,7 +76,7 @@ dependencies = [
|
|
|
76
76
|
|
|
77
77
|
[[package]]
|
|
78
78
|
name = "omx-sparkshell"
|
|
79
|
-
version = "0.21.
|
|
79
|
+
version = "0.21.25"
|
|
80
80
|
dependencies = [
|
|
81
81
|
"omx-mux",
|
|
82
82
|
]
|
package/Cargo.toml
CHANGED
|
@@ -2619,6 +2619,166 @@ exit 1
|
|
|
2619
2619
|
await rm(cwd, { recursive: true, force: true });
|
|
2620
2620
|
}
|
|
2621
2621
|
});
|
|
2622
|
+
it('rejects mailbox creation failures without publishing a successful fallback', async () => {
|
|
2623
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-mailbox-create-failure-'));
|
|
2624
|
+
const previousBinary = process.env.OMX_RUNTIME_BINARY;
|
|
2625
|
+
const previousBridge = process.env.OMX_RUNTIME_BRIDGE;
|
|
2626
|
+
try {
|
|
2627
|
+
const runtime = join(cwd, 'runtime');
|
|
2628
|
+
process.env.OMX_RUNTIME_BINARY = runtime;
|
|
2629
|
+
process.env.OMX_RUNTIME_BRIDGE = '1';
|
|
2630
|
+
await initTeamState('alpha', 'task', 'executor', 1, cwd);
|
|
2631
|
+
for (const failure of [
|
|
2632
|
+
"process.stderr.write('failed to load authoritative runtime state'); process.exit(1);",
|
|
2633
|
+
"process.stdout.write('truncated response'); process.exit(0);",
|
|
2634
|
+
"process.stdout.write('{}'); process.exit(0);",
|
|
2635
|
+
"process.stdout.write('null'); process.exit(0);",
|
|
2636
|
+
"process.stdout.write('[]'); process.exit(0);",
|
|
2637
|
+
"process.stdout.write(JSON.stringify({event:'SnapshotCaptured'})); process.exit(0);",
|
|
2638
|
+
"process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:'wrong-id',from_worker:command.from_worker,to_worker:command.to_worker})); process.exit(0);",
|
|
2639
|
+
"process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:command.message_id,from_worker:'other',to_worker:command.to_worker})); process.exit(0);",
|
|
2640
|
+
"process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:command.message_id,from_worker:command.from_worker,to_worker:'other'})); process.exit(0);",
|
|
2641
|
+
"process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:command.message_id,from_worker:command.from_worker,to_worker:command.to_worker,team_name:'other'})); process.exit(0);",
|
|
2642
|
+
"process.stdout.write(JSON.stringify({event:'MailboxMessageCreated',message_id:command.message_id,from_worker:command.from_worker,to_worker:command.to_worker,body:'other'})); process.exit(0);",
|
|
2643
|
+
]) {
|
|
2644
|
+
await writeCompatRuntimeFixture(runtime, join(cwd, 'runtime.log'));
|
|
2645
|
+
const fixture = await readFile(runtime, 'utf8');
|
|
2646
|
+
await writeFile(runtime, fixture.replace("const dir = stateDir();", `if (command.command === 'CreateMailboxMessage') { ${failure} }\nconst dir = stateDir();`));
|
|
2647
|
+
await assert.rejects(() => sendDirectMessage('alpha', 'leader-fixed', 'worker-1', failure, cwd), /failed to load authoritative runtime state|non-JSON output|invalid mailbox creation acknowledgement/);
|
|
2648
|
+
assert.deepEqual(await listMailboxMessages('alpha', 'worker-1', cwd), []);
|
|
2649
|
+
const shadow = JSON.parse(await readFile(join(cwd, '.omx/state/team/alpha/mailbox/worker-1.json'), 'utf8'));
|
|
2650
|
+
assert.deepEqual(shadow.messages, []);
|
|
2651
|
+
assert.doesNotMatch(await readFile(join(cwd, '.omx/state/team/alpha/events/events.ndjson'), 'utf8').catch(() => ''), /message_received/);
|
|
2652
|
+
}
|
|
2653
|
+
process.env.OMX_RUNTIME_BINARY = join(cwd, 'missing-runtime');
|
|
2654
|
+
const fallback = await sendDirectMessage('alpha', 'leader-fixed', 'worker-1', 'offline fallback', cwd);
|
|
2655
|
+
assert.equal((await listMailboxMessages('alpha', 'worker-1', cwd))[0]?.message_id, fallback.message_id);
|
|
2656
|
+
process.env.OMX_RUNTIME_BINARY = runtime;
|
|
2657
|
+
await writeCompatRuntimeFixture(runtime, join(cwd, 'runtime.log'));
|
|
2658
|
+
const native = await sendDirectMessage('alpha', 'leader-fixed', 'worker-1', 'runtime restored', cwd);
|
|
2659
|
+
assert.ok((await listMailboxMessages('alpha', 'worker-1', cwd)).some((message) => message.message_id === native.message_id));
|
|
2660
|
+
}
|
|
2661
|
+
finally {
|
|
2662
|
+
if (previousBinary === undefined)
|
|
2663
|
+
delete process.env.OMX_RUNTIME_BINARY;
|
|
2664
|
+
else
|
|
2665
|
+
process.env.OMX_RUNTIME_BINARY = previousBinary;
|
|
2666
|
+
if (previousBridge === undefined)
|
|
2667
|
+
delete process.env.OMX_RUNTIME_BRIDGE;
|
|
2668
|
+
else
|
|
2669
|
+
process.env.OMX_RUNTIME_BRIDGE = previousBridge;
|
|
2670
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2671
|
+
}
|
|
2672
|
+
});
|
|
2673
|
+
it('recovers a partially persisted mailbox creation before allowing a retry', async () => {
|
|
2674
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-mailbox-partial-persist-'));
|
|
2675
|
+
const keys = ['OMX_RUNTIME_BINARY', 'OMX_RUNTIME_BRIDGE', 'OMX_TEST_MATERIALIZE_MAILBOX_ON_CAPTURE'];
|
|
2676
|
+
const previous = Object.fromEntries(keys.map(key => [key, process.env[key]]));
|
|
2677
|
+
try {
|
|
2678
|
+
const runtime = join(cwd, 'runtime');
|
|
2679
|
+
const log = join(cwd, 'runtime.log');
|
|
2680
|
+
process.env.OMX_RUNTIME_BINARY = runtime;
|
|
2681
|
+
process.env.OMX_RUNTIME_BRIDGE = '1';
|
|
2682
|
+
process.env.OMX_TEST_MATERIALIZE_MAILBOX_ON_CAPTURE = '1';
|
|
2683
|
+
await initTeamState('alpha', 'task', 'executor', 1, cwd);
|
|
2684
|
+
await writeCompatRuntimeFixture(runtime, log);
|
|
2685
|
+
const fixture = await readFile(runtime, 'utf8');
|
|
2686
|
+
await writeFile(runtime, fixture.replace(" case 'CreateMailboxMessage': {", ` case 'CreateMailboxMessage': {
|
|
2687
|
+
writeJson(path.join(dir, 'events.json'), [{ ...command, event: 'MailboxMessageCreated' }]);
|
|
2688
|
+
process.stderr.write('persist failed: mailbox snapshot is read-only'); process.exit(1);`));
|
|
2689
|
+
const send = () => sendDirectMessage('alpha', 'leader-fixed', 'worker-1', 'partial creation', cwd);
|
|
2690
|
+
await assert.rejects(send, /persist failed/);
|
|
2691
|
+
const stateDir = join(cwd, '.omx/state');
|
|
2692
|
+
const eventsPath = join(stateDir, 'events.json');
|
|
2693
|
+
const committed = await readFile(eventsPath, 'utf8');
|
|
2694
|
+
const originalId = JSON.parse(committed)[0].message_id;
|
|
2695
|
+
assert.deepEqual(await listMailboxMessages('alpha', 'worker-1', cwd), []);
|
|
2696
|
+
await writeFile(join(stateDir, 'mailbox.json'), JSON.stringify({ records: [] }));
|
|
2697
|
+
for (const response of [
|
|
2698
|
+
"process.stderr.write('recovery unavailable'); process.exit(1);",
|
|
2699
|
+
"process.stdout.write('{}'); process.exit(0);",
|
|
2700
|
+
"process.stdout.write(JSON.stringify({event:'SnapshotCaptured'})); process.exit(0);",
|
|
2701
|
+
]) {
|
|
2702
|
+
await writeFile(runtime, fixture.replace(" case 'CaptureSnapshot': {", ` case 'CaptureSnapshot': { ${response}`));
|
|
2703
|
+
await assert.rejects(send, /recovery unavailable|mailbox creation recovery/);
|
|
2704
|
+
assert.equal(await readFile(eventsPath, 'utf8'), committed);
|
|
2705
|
+
}
|
|
2706
|
+
process.env.OMX_RUNTIME_BINARY = join(cwd, 'missing-runtime');
|
|
2707
|
+
await assert.rejects(send, /omx-runtime/);
|
|
2708
|
+
process.env.OMX_RUNTIME_BINARY = runtime;
|
|
2709
|
+
await writeFile(eventsPath, '{}');
|
|
2710
|
+
await assert.rejects(send, /invalid runtime mailbox event log/);
|
|
2711
|
+
await writeFile(eventsPath, committed);
|
|
2712
|
+
await writeFile(runtime, fixture);
|
|
2713
|
+
const retried = await Promise.all(Array.from({ length: 4 }, send));
|
|
2714
|
+
assert.ok(retried.every(message => message.message_id === originalId));
|
|
2715
|
+
assert.equal((await listMailboxMessages('alpha', 'worker-1', cwd)).length, 1);
|
|
2716
|
+
assert.equal(await readFile(eventsPath, 'utf8'), committed);
|
|
2717
|
+
assert.equal((await readFile(log, 'utf8')).split('"command":"CreateMailboxMessage"').length - 1, 1);
|
|
2718
|
+
assert.equal(await markMessageDelivered('alpha', 'worker-1', originalId, cwd), true);
|
|
2719
|
+
process.env.OMX_RUNTIME_BINARY = join(cwd, 'missing-runtime');
|
|
2720
|
+
const offline = await send();
|
|
2721
|
+
assert.notEqual(offline.message_id, originalId, 'a confirmed delivered message must not block normal offline fallback');
|
|
2722
|
+
assert.ok((await listMailboxMessages('alpha', 'worker-1', cwd)).some(message => message.message_id === offline.message_id));
|
|
2723
|
+
}
|
|
2724
|
+
finally {
|
|
2725
|
+
for (const key of keys) {
|
|
2726
|
+
if (previous[key] === undefined)
|
|
2727
|
+
delete process.env[key];
|
|
2728
|
+
else
|
|
2729
|
+
process.env[key] = previous[key];
|
|
2730
|
+
}
|
|
2731
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2732
|
+
}
|
|
2733
|
+
});
|
|
2734
|
+
it('deduplicates against the verified projection when another reader refreshes it', async () => {
|
|
2735
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-mailbox-refresh-race-'));
|
|
2736
|
+
const previousBinary = process.env.OMX_RUNTIME_BINARY;
|
|
2737
|
+
const previousBridge = process.env.OMX_RUNTIME_BRIDGE;
|
|
2738
|
+
try {
|
|
2739
|
+
process.env.OMX_RUNTIME_BINARY = join(cwd, 'missing-runtime');
|
|
2740
|
+
process.env.OMX_RUNTIME_BRIDGE = '1';
|
|
2741
|
+
const stateDir = join(cwd, '.omx/state');
|
|
2742
|
+
await mkdir(stateDir, { recursive: true });
|
|
2743
|
+
const message = {
|
|
2744
|
+
message_id: 'committed', from_worker: 'leader-fixed', to_worker: 'worker-1',
|
|
2745
|
+
body: 'retry', created_at: new Date().toISOString(),
|
|
2746
|
+
};
|
|
2747
|
+
await writeFile(join(stateDir, 'events.json'), JSON.stringify([{
|
|
2748
|
+
...message, event: 'MailboxMessageCreated', team_name: 'alpha',
|
|
2749
|
+
}]));
|
|
2750
|
+
let reads = 0;
|
|
2751
|
+
const result = await sendDirectMessageWithDeps('leader-fixed', 'worker-1', 'retry', {
|
|
2752
|
+
teamName: 'alpha', cwd,
|
|
2753
|
+
withMailboxLock: async (_team, _worker, _cwd, fn) => await fn(),
|
|
2754
|
+
readMailbox: async () => {
|
|
2755
|
+
assert.equal(++reads, 1, 'deduplication must use the same projection that was verified');
|
|
2756
|
+
await writeFile(join(stateDir, 'mailbox.json'), JSON.stringify({ records: [{
|
|
2757
|
+
...message, team_name: 'foreign', message_id: 'foreign', notified_at: null, delivered_at: null,
|
|
2758
|
+
}, {
|
|
2759
|
+
...message, team_name: 'alpha', notified_at: null, delivered_at: null,
|
|
2760
|
+
}] }));
|
|
2761
|
+
return { worker: 'worker-1', messages: [] };
|
|
2762
|
+
},
|
|
2763
|
+
readLegacyMailbox: async () => ({ worker: 'worker-1', messages: [] }),
|
|
2764
|
+
writeMailbox: async () => assert.fail('must not create a second provisional message'),
|
|
2765
|
+
appendTeamEvent: async () => assert.fail('must not publish a second creation'),
|
|
2766
|
+
readTeamConfig: async () => null,
|
|
2767
|
+
});
|
|
2768
|
+
assert.equal(result.message_id, message.message_id);
|
|
2769
|
+
}
|
|
2770
|
+
finally {
|
|
2771
|
+
if (previousBinary === undefined)
|
|
2772
|
+
delete process.env.OMX_RUNTIME_BINARY;
|
|
2773
|
+
else
|
|
2774
|
+
process.env.OMX_RUNTIME_BINARY = previousBinary;
|
|
2775
|
+
if (previousBridge === undefined)
|
|
2776
|
+
delete process.env.OMX_RUNTIME_BRIDGE;
|
|
2777
|
+
else
|
|
2778
|
+
process.env.OMX_RUNTIME_BRIDGE = previousBridge;
|
|
2779
|
+
await rm(cwd, { recursive: true, force: true });
|
|
2780
|
+
}
|
|
2781
|
+
});
|
|
2622
2782
|
it('rejects QueueDispatch schema failures without polluting existing runtime state', async () => {
|
|
2623
2783
|
const cwd = await mkdtemp(join(tmpdir(), 'omx-queue-schema-'));
|
|
2624
2784
|
const previousBinary = process.env.OMX_RUNTIME_BINARY;
|