Official
codex
Codex agent provider: runs the Codex CLI's app-server for each account.
The app opens the listing; nothing installs until an agent in your Plugins workspace has read the files and you enable the plugin. In a terminal: cvg install convergence/codex@0.2.0
Permissions in 0.2.0
Files
legacy.test.ts2.8 KB
// Scripted scenarios for the codex conversion.
import { test } from "node:test";
import assert from "node:assert/strict";
import { mkdtemp, mkdir, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { activate } from "./main.ts";
import * as Effect from "effect/Effect";
import { liveLayer } from "convergence/effect";
import type { Api } from "convergence";
import { adoptLegacy as adoptLegacyEffect, legacyDir, mergeInstances } from "./legacy.ts";
import type { HostScript } from "../sdk/testing.ts";
import { diskFs, fakeApi, memoryStorage, settle } from "../sdk/testing.ts";
async function dataFolder(instances: string) {
const data = await mkdtemp(join(tmpdir(), "codex-legacy-"));
await mkdir(join(data, "legacy"), { recursive: true });
await writeFile(join(data, "legacy", "instances.json"), instances);
return data;
}
function apiWith(data: string, storage: HostScript, fs = diskFs()) {
const api = fakeApi({ onHost: storage, fs });
api.paths = { data };
return api;
}
test("the stored accounts keep theirs and gain the legacy ones they lack", () => {
assert.deepEqual(mergeInstances([{ id: "a", name: "Mine" }], [{ id: "a", name: "Old" }, { id: "b" }]), [
{ id: "a", name: "Mine" },
{ id: "b" },
]);
assert.equal(mergeInstances(null, { id: "a" }), null, "not a list");
});
test("the Rust plugin's accounts register, taken into storage once", async (t) => {
const data = await dataFolder(JSON.stringify([{ id: "work", name: "Codex Work", home: "~/.codex_work" }]));
const storage = memoryStorage();
const api = apiWith(data, storage);
t.after(activate(api));
await settle(20);
assert.deepEqual(
api.registered.map((def) => def.id),
["codex", "codex:work"],
);
assert.deepEqual(storage.values.get("instances"), [{ id: "work", name: "Codex Work", home: "~/.codex_work" }]);
assert.ok(storage.values.get("legacy"));
await writeFile(join(data, "legacy", "instances.json"), JSON.stringify([{ id: "late" }]));
assert.equal(await adoptLegacy(api), false, "read once");
});
test("a broken file is left out, a refused read is tried again", async () => {
const data = await dataFolder("{ not json");
const storage = memoryStorage();
assert.equal(await adoptLegacy(apiWith(data, storage)), false);
assert.equal(storage.values.has("instances"), false);
assert.ok(storage.values.get("legacy"));
const refused = memoryStorage();
assert.equal(await adoptLegacy(apiWith(data, refused, diskFs({ allow: () => false }))), false);
assert.equal(refused.values.has("legacy"), false);
});
const adoptLegacy = (api: Api) =>
Effect.runPromise(
adoptLegacyEffect(legacyDir(api)).pipe(
Effect.provide(
liveLayer(
api,
() => Promise.reject(new Error("unexpected handler")),
() => {},
),
),
),
);Versions
| Version | Published | Plugin API | Size | Permissions | Status |
|---|---|---|---|---|---|
| 0.2.0latest | Oct 5, 2026 | >=2 <3 | 78.1 KB | 4 permissions | Listed |
No comments yet.