Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions packages/extension/opencode.lock.json
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
{
"version": "1.18.29",
"source": "release",
"ref": "16747470f976aca3d362ad730bcd3fe82ecc2c9a",
"ref": "2144c84418663876456129f3dbaead164de5ef07",
"platforms": {
"darwin-arm64": {
"asset": "opencode-darwin-arm64.zip",
"sha256": "fe764f7f360c584a83e18dd5f23fb1a6b2725f5ee8854b0252fe558f7798e946"
"sha256": "684972c5cc5c801111256eadf1390cd9f7d58ac560b1b8397a0922964e262345"
},
"linux-arm64": {
"asset": "opencode-linux-arm64.tar.gz",
"sha256": "70baf769395ca4e7a68924026530c390eace194f3b7e4919d4efcb2aa2eed3c0"
"sha256": "a666bd008966a6819507dfdb6cc54f7738f0b962b925dd3a355312e8acd2642c"
},
"linux-x64": {
"asset": "opencode-linux-x64.tar.gz",
"sha256": "ea800b7ff56226b70952126c9fc1e2517ca4c4b5682fd9d3f9e87449697a1194"
"sha256": "6511e18db3495ba6cf2709237ba4ba3a2f6ef34e237b93543a3473e20ba42e84"
}
}
},
"tag": "v1.18.29-amicode.24",
"repo": "harmoniqs/opencode"
}
2 changes: 1 addition & 1 deletion packages/extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "amicode",
"displayName": "Amicode",
"description": "Open autonomous research in VS Code \u2014 vaults, fleet, and live solves for quantum control and physical intelligence.",
"version": "0.3.2",
"version": "0.3.4",
"publisher": "harmoniqs",
"license": "Apache-2.0",
"icon": "media/icon.png",
Expand Down
14 changes: 10 additions & 4 deletions packages/extension/scripts/opencode_probe.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,14 @@ export async function bootOpencodeAndProbe({ bin = vendoredOpencodeBin(), timeou
);

const port = await freePort();
const password = "amicode-probe-password";
const headers = { Authorization: `Basic ${Buffer.from(`opencode:${password}`).toString("base64")}` };
let log = "";
const child = spawn(bin, ["serve", "--port", String(port)], { cwd: proj, stdio: ["ignore", "pipe", "pipe"] });
const child = spawn(bin, ["serve", "--port", String(port)], {
cwd: proj,
env: { ...process.env, OPENCODE_SERVER_PASSWORD: password },
stdio: ["ignore", "pipe", "pipe"],
});
const onData = (d) => {
log += d;
};
Expand All @@ -78,7 +84,7 @@ export async function bootOpencodeAndProbe({ bin = vendoredOpencodeBin(), timeou
let up = false;
while (Date.now() < deadline && !up) {
try {
const r = await fetch(`http://127.0.0.1:${port}/`, { signal: AbortSignal.timeout(500) });
const r = await fetch(`http://127.0.0.1:${port}/`, { headers, signal: AbortSignal.timeout(500) });
if (r.status < 500) up = true;
} catch {
/* not up yet */
Expand All @@ -92,7 +98,7 @@ export async function bootOpencodeAndProbe({ bin = vendoredOpencodeBin(), timeou
eventCtype,
eventOk = false;
try {
const ev = await fetch(`http://127.0.0.1:${port}/event`, { signal: AbortSignal.timeout(10000) });
const ev = await fetch(`http://127.0.0.1:${port}/event`, { headers, signal: AbortSignal.timeout(10000) });
eventStatus = ev.status;
eventCtype = ev.headers.get("content-type") ?? "";
eventOk = ev.status === 200 && eventCtype.includes("text/event-stream");
Expand All @@ -105,7 +111,7 @@ export async function bootOpencodeAndProbe({ bin = vendoredOpencodeBin(), timeou
// still resolving providers right after the port opens (→ a false "creds
// unverifiable"); give it up to half the budget, capped at 15s.
const signalTimeoutMs = Math.min(15000, Math.max(4000, Math.floor(timeoutMs / 2)));
const signal = await fetchProviderSignal(`http://127.0.0.1:${port}`, { timeoutMs: signalTimeoutMs });
const signal = await fetchProviderSignal(`http://127.0.0.1:${port}`, { headers, timeoutMs: signalTimeoutMs });

return { up: true, eventOk, eventStatus, eventCtype, signal, log };
} finally {
Expand Down
14 changes: 10 additions & 4 deletions packages/extension/test/amicode_service_contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,11 +217,17 @@ describe("amicode service — golden-fixture parity with the fork", () => {
// recorded parity contract.
expect(meta.fork.tag).toBe("v1.18.10-amicode.21");
expect(meta.entries.length).toBeGreaterThan(0);
// And the vendored pin must never regress to the fork lineage: the stock
// shape (no repo/tag — the fetch path's anomalyco/opencode default).
// A normal mainline build uses the stock shape (no repo/tag — the fetch
// path's anomalyco/opencode default). A release candidate may instead pin
// one fully specified fork release before its alpha is cut.
const lock = JSON.parse(readFileSync(fileURLToPath(new URL("../opencode.lock.json", import.meta.url)), "utf8"));
expect(lock.repo).toBeUndefined();
expect(lock.tag).toBeUndefined();
if (!lock.repo) {
expect(lock.tag).toBeUndefined();
return;
}
expect(lock.repo).toBe("harmoniqs/opencode");
expect(lock.tag).toMatch(/^v1\.18\.29-amicode\.\d+$/);
expect(lock.ref).toMatch(/^[0-9a-f]{40}$/);
});

for (const [i, entry] of meta.entries.entries()) {
Expand Down
16 changes: 8 additions & 8 deletions packages/extension/test/fetch_opencode.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,16 @@ describe("loadManifest", () => {
it("the COMMITTED manifest's platforms match the runtime allow-list exactly", () => {
expect(Object.keys(loadManifest().platforms).sort()).toEqual([...SUPPORTED].sort());
});
// The #823 M3 cutover shape, pinned: the vendored engine is STOCK canonical
// opencode — the lock names no fork lineage (no repo/tag), so releaseCoords
// resolves the anomalyco/opencode@v<version> default and the download is a
// tokenless public fetch. A regression back to a fork pin would resurrect
// the retiring lineage through the default vendoring path.
it("the COMMITTED manifest is the stock canonical pin (#823: no fork repo/tag)", () => {
it("the committed manifest is either the stock pin or a fully specified release candidate", () => {
const m = loadManifest(); // defaults to the real packages/extension root
expect(m.repo).toBeUndefined();
expect(m.tag).toBeUndefined();
expect(m.version).toBe("1.18.29");
if (!m.repo) {
expect(m.tag).toBeUndefined();
return;
}
expect(m.repo).toBe("harmoniqs/opencode");
expect(m.tag).toMatch(/^v1\.18\.29-amicode\.\d+$/);
expect(m.ref).toMatch(/^[0-9a-f]{40}$/);
});
it("rejects missing version and short hashes", () => {
expect(() => loadManifest(rootWith({ ...GOOD, version: "" }))).toThrow(/version/);
Expand Down
Loading