zcode-acp-server 0.43.2 → 0.43.4

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.
Files changed (46) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/quota.d.ts.map +1 -1
  3. package/dist/bin/quota.js +4 -3
  4. package/dist/bin/quota.js.map +1 -1
  5. package/dist/code-fingerprint.json +1 -1
  6. package/dist/config/user-config.d.ts +3 -0
  7. package/dist/config/user-config.d.ts.map +1 -1
  8. package/dist/config/user-config.js +1 -0
  9. package/dist/config/user-config.js.map +1 -1
  10. package/dist/handlers/session.d.ts +29 -2
  11. package/dist/handlers/session.d.ts.map +1 -1
  12. package/dist/handlers/session.js +107 -22
  13. package/dist/handlers/session.js.map +1 -1
  14. package/dist/quota/format.d.ts.map +1 -1
  15. package/dist/quota/format.js +6 -2
  16. package/dist/quota/format.js.map +1 -1
  17. package/dist/quota/opencode-go/client.d.ts +17 -16
  18. package/dist/quota/opencode-go/client.d.ts.map +1 -1
  19. package/dist/quota/opencode-go/client.js +25 -27
  20. package/dist/quota/opencode-go/client.js.map +1 -1
  21. package/dist/quota/opencode-go/config.d.ts +14 -9
  22. package/dist/quota/opencode-go/config.d.ts.map +1 -1
  23. package/dist/quota/opencode-go/config.js +14 -9
  24. package/dist/quota/opencode-go/config.js.map +1 -1
  25. package/dist/quota/opencode-go/format.js +2 -2
  26. package/dist/quota/opencode-go/format.js.map +1 -1
  27. package/dist/quota/opencode-go/index.d.ts +10 -10
  28. package/dist/quota/opencode-go/index.d.ts.map +1 -1
  29. package/dist/quota/opencode-go/index.js +42 -28
  30. package/dist/quota/opencode-go/index.js.map +1 -1
  31. package/dist/quota/opencode-go/parse.d.ts +17 -28
  32. package/dist/quota/opencode-go/parse.d.ts.map +1 -1
  33. package/dist/quota/opencode-go/parse.js +52 -66
  34. package/dist/quota/opencode-go/parse.js.map +1 -1
  35. package/dist/quota/opencode-go/types.d.ts +8 -9
  36. package/dist/quota/opencode-go/types.d.ts.map +1 -1
  37. package/dist/quota/opencode-go/types.js +6 -5
  38. package/dist/quota/opencode-go/types.js.map +1 -1
  39. package/dist/remote/endpoint.d.ts.map +1 -1
  40. package/dist/remote/endpoint.js +10 -0
  41. package/dist/remote/endpoint.js.map +1 -1
  42. package/dist/remote/hub-server.d.ts.map +1 -1
  43. package/dist/remote/hub-server.js +54 -20
  44. package/dist/remote/hub-server.js.map +1 -1
  45. package/docs/PROTOCOL.md +11 -0
  46. package/package.json +1 -1
@@ -1,48 +1,46 @@
1
1
  /**
2
- * Opencode Go dashboard HTTP client.
2
+ * Opencode Go status HTTP client.
3
3
  *
4
- * There is no JSON API for Go subscription usage. The only data source is the
5
- * authenticated web dashboard at `https://opencode.ai/workspace/<id>/go`,
6
- * which serves an HTML page with usage embedded in a SolidJS SSR hydration
7
- * payload. We fetch the HTML here and hand it to the parser.
4
+ * The Go dashboard moved off the legacy SSR page (`/workspace/<id>/go` — that
5
+ * URL now bounces EVERY cookie to the login page, observed 2026-09-19) onto
6
+ * the console at `https://opencode.ai/console/<org>/go`, backed by this JSON
7
+ * API. Usage arrives as micro-cents meter pairs per window; the parser turns
8
+ * them into percent + countdown.
8
9
  *
9
- * Credentials come from environment variables (set by the user) — not from
10
- * `~/.zcode/v2/config.json`, since Opencode Go is unrelated to the ZCode
11
- * provider the bridge talks to.
10
+ * Auth needs THREE pieces (verified against the live API 2026-09-19): the
11
+ * `auth` cookie, the `__Host-console_session` cookie, and the `x-org-id`
12
+ * header. Missing session cookie → 401, missing org header → 400; any
13
+ * User-Agent works (one is sent for parity with the console's own requests).
12
14
  */
13
- /** Request timeout (ms). The dashboard is a full HTML page; allow a bit more. */
15
+ /** Request timeout (ms). */
14
16
  const TIMEOUT_MS = 10_000;
15
- /**
16
- * Browser-like User-Agent. opencode.ai returns a login redirect for
17
- * unauthenticated requests; sending a real browser UA avoids any
18
- * bot-detection short-circuit that would bypass the dashboard route.
19
- */
17
+ /** Browser-like User-Agent, mirroring the console's own XHR requests. */
20
18
  const USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Gecko/20100101 Firefox/148.0";
21
- /** Build the dashboard URL for a workspace. */
22
- export function dashboardUrl(workspaceId) {
23
- return `https://opencode.ai/workspace/${workspaceId}/go`;
19
+ /** The console status API endpoint (the org rides the `x-org-id` header). */
20
+ export function goStatusUrl() {
21
+ return "https://opencode.ai/console/api/go/status";
24
22
  }
25
23
  /**
26
- * Fetch the Go dashboard HTML.
24
+ * Fetch the Go status JSON.
27
25
  *
28
- * @throws on non-2xx responses, network errors, or timeout. The caller maps
29
- * these to `unavailable`. A redirect-to-login is NOT thrown here —
30
- * the final URL is returned so the orchestrator can classify it as
26
+ * @throws on network errors or timeout; the caller maps these to
27
+ * `unavailable`. Auth failures are NOT thrown here — the HTTP status
28
+ * is returned so the orchestrator can classify 400/401/403 as
31
29
  * `auth_error`.
32
30
  */
33
- export async function fetchGoDashboard(workspaceId, authCookie, fetchImpl = globalThis.fetch) {
34
- const url = dashboardUrl(workspaceId);
35
- const resp = await fetchImpl(url, {
31
+ export async function fetchGoStatus(workspaceId, authCookie, sessionToken, fetchImpl = globalThis.fetch) {
32
+ const resp = await fetchImpl(goStatusUrl(), {
36
33
  method: "GET",
37
34
  headers: {
38
- Cookie: `auth=${authCookie}`,
35
+ Cookie: `auth=${authCookie}; __Host-console_session=${sessionToken}`,
36
+ "x-org-id": workspaceId,
37
+ Accept: "application/json",
39
38
  "User-Agent": USER_AGENT,
40
- Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
41
39
  },
42
40
  redirect: "follow",
43
41
  signal: AbortSignal.timeout(TIMEOUT_MS),
44
42
  });
45
43
  const text = await resp.text();
46
- return { status: resp.status, text, finalUrl: resp.url };
44
+ return { status: resp.status, text };
47
45
  }
48
46
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/quota/opencode-go/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,iFAAiF;AACjF,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B;;;;GAIG;AACH,MAAM,UAAU,GAAG,8EAA8E,CAAC;AAElG,+CAA+C;AAC/C,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,iCAAiC,WAAW,KAAK,CAAC;AAC3D,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,WAAmB,EACnB,UAAkB,EAClB,YAAqC,UAAU,CAAC,KAAK;IAErD,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,MAAM,EAAE,QAAQ,UAAU,EAAE;YAC5B,YAAY,EAAE,UAAU;YACxB,MAAM,EAAE,iEAAiE;SAC1E;QACD,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC;KACxC,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IAC/B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;AAC3D,CAAC"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/quota/opencode-go/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,4BAA4B;AAC5B,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,yEAAyE;AACzE,MAAM,UAAU,GAAG,8EAA8E,CAAC;AAElG,6EAA6E;AAC7E,MAAM,UAAU,WAAW;IACzB,OAAO,2CAA2C,CAAC;AACrD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,WAAmB,EACnB,UAAkB,EAClB,YAAoB,EACpB,YAAqC,UAAU,CAAC,KAAK;IAErD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,WAAW,EAAE,EAAE;QAC1C,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,MAAM,EAAE,QAAQ,UAAU,4BAA4B,YAAY,EAAE;YACpE,UAAU,EAAE,WAAW;YACvB,MAAM,EAAE,kBAAkB;YAC1B,YAAY,EAAE,UAAU;SACzB;QACD,QAAQ,EAAE,QAAQ;QAClB,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC;KACxC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IAC/B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;AACvC,CAAC"}
@@ -3,26 +3,31 @@
3
3
  * fallback source.
4
4
  *
5
5
  * Full precedence (highest first), resolved in ../index.ts:
6
- * 1. `quota.opencodeGoWorkspaceId` / `quota.opencodeGoAuthCookie` in
7
- * `~/.config/zcode-acp/config.json` (our own config).
8
- * 2. `OPENCODE_GO_WORKSPACE_ID` / `OPENCODE_GO_AUTH_COOKIE` env vars
9
- * (best for CI / scripts / temporary overrides).
10
- * 3. `~/.pi/agent/opencode-go.json` — `{ workspaceId, authCookie }`
11
- * (the convention used by the @beyona/pi-zai-usage Pi extension, kept so
12
- * users who already configured it there get reuse for free).
6
+ * 1. `quota.opencodeGoWorkspaceId` / `opencodeGoAuthCookie` /
7
+ * `opencodeGoSessionToken` in `~/.config/zcode-acp/config.json` (our own
8
+ * config).
9
+ * 2. `OPENCODE_GO_WORKSPACE_ID` / `OPENCODE_GO_AUTH_COOKIE` /
10
+ * `OPENCODE_GO_SESSION_TOKEN` env vars (best for CI / scripts /
11
+ * temporary overrides).
12
+ * 3. `~/.pi/agent/opencode-go.json` —
13
+ * `{ workspaceId, authCookie, sessionToken }` (the convention used by
14
+ * the @beyona/pi-zai-usage Pi extension, kept so users who already
15
+ * configured it there get reuse for free).
13
16
  *
14
- * Both fields must resolve to a valid pair — a missing/invalid one yields
15
- * `not_configured`.
17
+ * All three fields must resolve to a valid triple — a missing/invalid one
18
+ * yields `not_configured`.
16
19
  */
17
20
  /** Env var names — documented in the CLI help and README. */
18
21
  export declare const ENV_WORKSPACE_ID = "OPENCODE_GO_WORKSPACE_ID";
19
22
  export declare const ENV_AUTH_COOKIE = "OPENCODE_GO_AUTH_COOKIE";
23
+ export declare const ENV_SESSION_TOKEN = "OPENCODE_GO_SESSION_TOKEN";
20
24
  /** Config file path (matches the @beyona/pi-zai-usage convention). */
21
25
  export declare const CONFIG_PATH: string;
22
26
  /** Shape of the JSON config file. */
23
27
  interface OpencodeGoConfig {
24
28
  workspaceId?: string;
25
29
  authCookie?: string;
30
+ sessionToken?: string;
26
31
  }
27
32
  /**
28
33
  * Read (best-effort) the JSON config file. Returns an empty object on any
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/quota/opencode-go/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAQH,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAC3D,eAAO,MAAM,eAAe,4BAA4B,CAAC;AAEzD,sEAAsE;AACtE,eAAO,MAAM,WAAW,QAKvB,CAAC;AAEF,qCAAqC;AACrC,UAAU,gBAAgB;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAoB,GAAG,gBAAgB,CAsB/E"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/quota/opencode-go/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAQH,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,6BAA6B,CAAC;AAC3D,eAAO,MAAM,eAAe,4BAA4B,CAAC;AACzD,eAAO,MAAM,iBAAiB,8BAA8B,CAAC;AAE7D,sEAAsE;AACtE,eAAO,MAAM,WAAW,QAKvB,CAAC;AAEF,qCAAqC;AACrC,UAAU,gBAAgB;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,QAAQ,GAAE,MAAoB,GAAG,gBAAgB,CAuB/E"}
@@ -3,16 +3,19 @@
3
3
  * fallback source.
4
4
  *
5
5
  * Full precedence (highest first), resolved in ../index.ts:
6
- * 1. `quota.opencodeGoWorkspaceId` / `quota.opencodeGoAuthCookie` in
7
- * `~/.config/zcode-acp/config.json` (our own config).
8
- * 2. `OPENCODE_GO_WORKSPACE_ID` / `OPENCODE_GO_AUTH_COOKIE` env vars
9
- * (best for CI / scripts / temporary overrides).
10
- * 3. `~/.pi/agent/opencode-go.json` — `{ workspaceId, authCookie }`
11
- * (the convention used by the @beyona/pi-zai-usage Pi extension, kept so
12
- * users who already configured it there get reuse for free).
6
+ * 1. `quota.opencodeGoWorkspaceId` / `opencodeGoAuthCookie` /
7
+ * `opencodeGoSessionToken` in `~/.config/zcode-acp/config.json` (our own
8
+ * config).
9
+ * 2. `OPENCODE_GO_WORKSPACE_ID` / `OPENCODE_GO_AUTH_COOKIE` /
10
+ * `OPENCODE_GO_SESSION_TOKEN` env vars (best for CI / scripts /
11
+ * temporary overrides).
12
+ * 3. `~/.pi/agent/opencode-go.json` —
13
+ * `{ workspaceId, authCookie, sessionToken }` (the convention used by
14
+ * the @beyona/pi-zai-usage Pi extension, kept so users who already
15
+ * configured it there get reuse for free).
13
16
  *
14
- * Both fields must resolve to a valid pair — a missing/invalid one yields
15
- * `not_configured`.
17
+ * All three fields must resolve to a valid triple — a missing/invalid one
18
+ * yields `not_configured`.
16
19
  */
17
20
  import { readFileSync } from "node:fs";
18
21
  import path from "node:path";
@@ -21,6 +24,7 @@ import { log } from "../../utils.js";
21
24
  /** Env var names — documented in the CLI help and README. */
22
25
  export const ENV_WORKSPACE_ID = "OPENCODE_GO_WORKSPACE_ID";
23
26
  export const ENV_AUTH_COOKIE = "OPENCODE_GO_AUTH_COOKIE";
27
+ export const ENV_SESSION_TOKEN = "OPENCODE_GO_SESSION_TOKEN";
24
28
  /** Config file path (matches the @beyona/pi-zai-usage convention). */
25
29
  export const CONFIG_PATH = path.join(process.env.HOME || process.env.USERPROFILE || "~", ".pi", "agent", "opencode-go.json");
26
30
  /**
@@ -43,6 +47,7 @@ export function readConfigFile(filePath = CONFIG_PATH) {
43
47
  return {
44
48
  workspaceId: typeof cfg.workspaceId === "string" ? cfg.workspaceId : undefined,
45
49
  authCookie: typeof cfg.authCookie === "string" ? cfg.authCookie : undefined,
50
+ sessionToken: typeof cfg.sessionToken === "string" ? cfg.sessionToken : undefined,
46
51
  };
47
52
  }
48
53
  catch (e) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/quota/opencode-go/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,6DAA6D;AAC7D,MAAM,CAAC,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAC3D,MAAM,CAAC,MAAM,eAAe,GAAG,yBAAyB,CAAC;AAEzD,sEAAsE;AACtE,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAClC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,EAClD,KAAK,EACL,OAAO,EACP,kBAAkB,CACnB,CAAC;AAQF;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB,WAAW;IAC3D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,kDAAkD,QAAQ,GAAG,CAAC,CAAC;YACnE,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,GAAG,GAAG,MAAiC,CAAC;QAC9C,OAAO;YACL,WAAW,EAAE,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;YAC9E,UAAU,EAAE,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;SAC5E,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,uEAAuE;QACvE,oDAAoD;QACpD,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,GAAG,CAAC,oCAAoC,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/quota/opencode-go/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAErC,6DAA6D;AAC7D,MAAM,CAAC,MAAM,gBAAgB,GAAG,0BAA0B,CAAC;AAC3D,MAAM,CAAC,MAAM,eAAe,GAAG,yBAAyB,CAAC;AACzD,MAAM,CAAC,MAAM,iBAAiB,GAAG,2BAA2B,CAAC;AAE7D,sEAAsE;AACtE,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAClC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,GAAG,EAClD,KAAK,EACL,OAAO,EACP,kBAAkB,CACnB,CAAC;AASF;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,WAAmB,WAAW;IAC3D,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC3C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,CAAC;QAC1C,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnE,GAAG,CAAC,kDAAkD,QAAQ,GAAG,CAAC,CAAC;YACnE,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,GAAG,GAAG,MAAiC,CAAC;QAC9C,OAAO;YACL,WAAW,EAAE,OAAO,GAAG,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;YAC9E,UAAU,EAAE,OAAO,GAAG,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;YAC3E,YAAY,EAAE,OAAO,GAAG,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS;SAClF,CAAC;IACJ,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,uEAAuE;QACvE,oDAAoD;QACpD,MAAM,GAAG,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvD,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,GAAG,CAAC,oCAAoC,QAAQ,MAAM,GAAG,EAAE,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC"}
@@ -55,9 +55,9 @@ export function formatGoSection(result, windows, now = Date.now(), color = false
55
55
  const header = "Opencode Go";
56
56
  if (result.kind !== "success") {
57
57
  const msg = result.kind === "not_configured"
58
- ? "not configured (set OPENCODE_GO_WORKSPACE_ID + OPENCODE_GO_AUTH_COOKIE)"
58
+ ? "not configured (set quota.opencodeGo* or OPENCODE_GO_* — see zcode-acp quota --help)"
59
59
  : result.kind === "auth_error"
60
- ? "auth expired — refresh your opencode.ai cookie"
60
+ ? "auth expired — refresh your opencode.ai cookie + session token"
61
61
  : "unavailable";
62
62
  return { header, body: [msg] };
63
63
  }
@@ -1 +1 @@
1
- {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/quota/opencode-go/format.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/quota/opencode-go/format.ts"],"names":[],"mappings":"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"}
@@ -1,30 +1,30 @@
1
1
  /**
2
2
  * Opencode Go usage orchestration — the entry point used by the
3
- * `zcode-acp quota` CLI.
3
+ * `zcode-acp quota` CLI and the quota dock.
4
4
  *
5
- * Flow: credentials (env + config file) → cache check → fetch → redirect/auth
5
+ * Flow: credentials (env + config file) → cache check → fetch → status/auth
6
6
  * check → parse → cache write. Any thrown error degrades to `unavailable`
7
7
  * rather than propagating, so the CLI always produces output.
8
8
  *
9
- * A missing/invalid credential pair yields `not_configured`, which the
9
+ * A missing/invalid credential triple yields `not_configured`, which the
10
10
  * combined view silently skips (vs. `unavailable`, which renders an error
11
11
  * line) — so users who only care about GLM see no noise.
12
12
  */
13
13
  import type { GoQueryResult } from "./types.js";
14
14
  /**
15
- * Query the Opencode Go dashboard and return a normalised {@link GoQueryResult}.
15
+ * Query the Opencode Go console status API and return a normalised
16
+ * {@link GoQueryResult}.
16
17
  *
17
18
  * - No credentials / invalid → `not_configured`.
18
19
  * - Serves a cached result when fresh (< 10s).
19
- * - HTTP redirect to login (final URL no longer contains the workspace path)
20
- * → `auth_error`.
20
+ * - HTTP 400/401/403 → `auth_error` (bad/missing org id or cookie pair).
21
21
  * - Network/timeout/parse failure → `unavailable`.
22
22
  */
23
23
  export declare function queryGoUsage(): Promise<GoQueryResult>;
24
24
  export { clearCache, clearCache as clearGoCache } from "./cache.js";
25
- export { fetchGoDashboard, dashboardUrl } from "./client.js";
26
- export { parseGoDashboard, looksLikeDashboard } from "./parse.js";
25
+ export { fetchGoStatus, goStatusUrl } from "./client.js";
26
+ export { parseGoStatus, looksLikeGoStatus } from "./parse.js";
27
27
  export { formatDuration, formatGoSection } from "./format.js";
28
- export { readConfigFile, CONFIG_PATH, ENV_WORKSPACE_ID, ENV_AUTH_COOKIE } from "./config.js";
29
- export type { GoQueryResult, GoWindow, GoWindowKey, GoDashboardResponse } from "./types.js";
28
+ export { readConfigFile, CONFIG_PATH, ENV_WORKSPACE_ID, ENV_AUTH_COOKIE, ENV_SESSION_TOKEN, } from "./config.js";
29
+ export type { GoQueryResult, GoWindow, GoWindowKey, GoStatusResponse } from "./types.js";
30
30
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/quota/opencode-go/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAwChD;;;;;;;;GAQG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC,CA6C3D;AAGD,OAAO,EAAE,UAAU,EAAE,UAAU,IAAI,YAAY,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC7F,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/quota/opencode-go/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAQH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAyDhD;;;;;;;;GAQG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC,CAgD3D;AAGD,OAAO,EAAE,UAAU,EAAE,UAAU,IAAI,YAAY,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EACL,cAAc,EACd,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,iBAAiB,GAClB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
@@ -1,46 +1,52 @@
1
1
  /**
2
2
  * Opencode Go usage orchestration — the entry point used by the
3
- * `zcode-acp quota` CLI.
3
+ * `zcode-acp quota` CLI and the quota dock.
4
4
  *
5
- * Flow: credentials (env + config file) → cache check → fetch → redirect/auth
5
+ * Flow: credentials (env + config file) → cache check → fetch → status/auth
6
6
  * check → parse → cache write. Any thrown error degrades to `unavailable`
7
7
  * rather than propagating, so the CLI always produces output.
8
8
  *
9
- * A missing/invalid credential pair yields `not_configured`, which the
9
+ * A missing/invalid credential triple yields `not_configured`, which the
10
10
  * combined view silently skips (vs. `unavailable`, which renders an error
11
11
  * line) — so users who only care about GLM see no noise.
12
12
  */
13
13
  import { loadUserConfig } from "../../config/user-config.js";
14
14
  import { log } from "../../utils.js";
15
15
  import { getCached, setCached } from "./cache.js";
16
- import { ENV_AUTH_COOKIE, ENV_WORKSPACE_ID, readConfigFile } from "./config.js";
17
- import { fetchGoDashboard } from "./client.js";
18
- import { parseGoDashboard } from "./parse.js";
16
+ import { ENV_AUTH_COOKIE, ENV_SESSION_TOKEN, ENV_WORKSPACE_ID, readConfigFile } from "./config.js";
17
+ import { fetchGoStatus } from "./client.js";
18
+ import { parseGoStatus } from "./parse.js";
19
19
  /** Format validators (match pi-go-bars conventions). */
20
20
  const RE_WORKSPACE = /^wrk_[A-Za-z0-9]+$/;
21
21
  const COOKIE_PREFIX = "Fe26.2**";
22
+ /** Minimum plausible session-token length (console `st_…` values). */
23
+ const MIN_SESSION_TOKEN = 8;
22
24
  /**
23
25
  * Resolve & validate credentials.
24
26
  *
25
27
  * Three sources, merged field-by-field with the standard user-config
26
28
  * precedence (highest first):
27
- * 1. `quota.opencodeGoWorkspaceId` / `quota.opencodeGoAuthCookie` in
28
- * `~/.config/zcode-acp/config.json` (our own config — preferred home).
29
- * 2. `OPENCODE_GO_WORKSPACE_ID` / `OPENCODE_GO_AUTH_COOKIE` env vars.
29
+ * 1. `quota.opencodeGoWorkspaceId` / `opencodeGoAuthCookie` /
30
+ * `opencodeGoSessionToken` in `~/.config/zcode-acp/config.json` (our own
31
+ * config — preferred home).
32
+ * 2. `OPENCODE_GO_WORKSPACE_ID` / `OPENCODE_GO_AUTH_COOKIE` /
33
+ * `OPENCODE_GO_SESSION_TOKEN` env vars.
30
34
  * 3. `~/.pi/agent/opencode-go.json` (legacy — the @beyona/pi-zai-usage Pi
31
35
  * extension convention, kept so existing setups keep working).
32
36
  *
33
- * A field present in a higher-precedence source overrides the same field
34
- * below it; a field present only lower down still counts. Returns `null`
35
- * when the resolved pair is incomplete or malformed — `queryGoUsage` maps
36
- * that to `not_configured`.
37
+ * The session token is REQUIRED since the 2026-09 console migration: the
38
+ * status API answers 401 to an `auth` cookie alone. A field present in a
39
+ * higher-precedence source overrides the same field below it; a field present
40
+ * only lower down still counts. Returns `null` when the resolved triple is
41
+ * incomplete or malformed — `queryGoUsage` maps that to `not_configured`.
37
42
  */
38
43
  function loadCredentials() {
39
44
  const own = loadUserConfig().quota;
40
45
  const file = readConfigFile();
41
46
  const workspaceId = own?.opencodeGoWorkspaceId ?? process.env[ENV_WORKSPACE_ID] ?? file.workspaceId;
42
47
  const authCookie = own?.opencodeGoAuthCookie ?? process.env[ENV_AUTH_COOKIE] ?? file.authCookie;
43
- if (!workspaceId || !authCookie)
48
+ const sessionToken = own?.opencodeGoSessionToken ?? process.env[ENV_SESSION_TOKEN] ?? file.sessionToken;
49
+ if (!workspaceId || !authCookie || !sessionToken)
44
50
  return null;
45
51
  if (!RE_WORKSPACE.test(workspaceId)) {
46
52
  log(`opencode-go: invalid workspaceId format (expected wrk_…)`);
@@ -50,15 +56,19 @@ function loadCredentials() {
50
56
  log(`opencode-go: authCookie does not start with ${COOKIE_PREFIX}`);
51
57
  return null;
52
58
  }
53
- return { workspaceId, authCookie };
59
+ if (sessionToken.trim().length < MIN_SESSION_TOKEN) {
60
+ log(`opencode-go: sessionToken looks malformed (__Host-console_session value, st_…)`);
61
+ return null;
62
+ }
63
+ return { workspaceId, authCookie, sessionToken };
54
64
  }
55
65
  /**
56
- * Query the Opencode Go dashboard and return a normalised {@link GoQueryResult}.
66
+ * Query the Opencode Go console status API and return a normalised
67
+ * {@link GoQueryResult}.
57
68
  *
58
69
  * - No credentials / invalid → `not_configured`.
59
70
  * - Serves a cached result when fresh (< 10s).
60
- * - HTTP redirect to login (final URL no longer contains the workspace path)
61
- * → `auth_error`.
71
+ * - HTTP 400/401/403 → `auth_error` (bad/missing org id or cookie pair).
62
72
  * - Network/timeout/parse failure → `unavailable`.
63
73
  */
64
74
  export async function queryGoUsage() {
@@ -72,20 +82,24 @@ export async function queryGoUsage() {
72
82
  return { kind: "not_configured" };
73
83
  let result;
74
84
  try {
75
- const resp = await fetchGoDashboard(creds.workspaceId, creds.authCookie);
76
- // Redirect-to-login detection: an expired cookie silently bounces to the
77
- // login page with a 200, so we check the final URL rather than the status.
78
- if (!resp.finalUrl.includes(`/workspace/${creds.workspaceId}/go`)) {
85
+ const resp = await fetchGoStatus(creds.workspaceId, creds.authCookie, creds.sessionToken);
86
+ // 401/403 = bad cookie pair; 400 = missing/unknown org id (x-org-id).
87
+ // The remedy is the same for all three — re-grab credentials — so they
88
+ // share auth_error.
89
+ if (resp.status === 400 || resp.status === 401 || resp.status === 403) {
79
90
  result = { kind: "auth_error" };
80
91
  }
92
+ else if (resp.status < 200 || resp.status >= 300) {
93
+ result = { kind: "unavailable" };
94
+ }
81
95
  else {
82
- const parsed = parseGoDashboard(resp.text);
96
+ const parsed = parseGoStatus(resp.text);
83
97
  if (parsed.parserOutdated) {
84
- log("opencode-go: dashboard HTML recognised but no windows parsed (parser outdated)");
98
+ log("opencode-go: status JSON recognised but no windows parsed (parser outdated)");
85
99
  result = { kind: "unavailable" };
86
100
  }
87
101
  else if (!parsed.rolling && !parsed.weekly && !parsed.monthly) {
88
- // Not a dashboard page at all (e.g. error page the redirect check missed).
102
+ // Not a status payload at all (e.g. an HTML error page).
89
103
  result = { kind: "unavailable" };
90
104
  }
91
105
  else {
@@ -110,8 +124,8 @@ export async function queryGoUsage() {
110
124
  }
111
125
  // Re-exports for consumers (CLI + tests).
112
126
  export { clearCache, clearCache as clearGoCache } from "./cache.js";
113
- export { fetchGoDashboard, dashboardUrl } from "./client.js";
114
- export { parseGoDashboard, looksLikeDashboard } from "./parse.js";
127
+ export { fetchGoStatus, goStatusUrl } from "./client.js";
128
+ export { parseGoStatus, looksLikeGoStatus } from "./parse.js";
115
129
  export { formatDuration, formatGoSection } from "./format.js";
116
- export { readConfigFile, CONFIG_PATH, ENV_WORKSPACE_ID, ENV_AUTH_COOKIE } from "./config.js";
130
+ export { readConfigFile, CONFIG_PATH, ENV_WORKSPACE_ID, ENV_AUTH_COOKIE, ENV_SESSION_TOKEN, } from "./config.js";
117
131
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/quota/opencode-go/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/quota/opencode-go/index.ts"],"names":[],"mappings":"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"}
@@ -1,41 +1,30 @@
1
1
  /**
2
- * Opencode Go dashboard HTML parser.
2
+ * Opencode Go status JSON parser.
3
3
  *
4
- * The dashboard is a SolidJS SSR page. Usage data is embedded as hydration
5
- * assignments inside a `<script>`, in the shape:
4
+ * The console API (`/console/api/go/status`) returns meter pairs in
5
+ * micro-cents per window; we compute the percent (used/limit) and the reset
6
+ * countdown (resetsAt − now) here — the API gives absolute timestamps, the
7
+ * formatter wants a relative countdown captured at fetch time.
6
8
  *
7
- * rollingUsage:$R[N]={usagePercent:<n>,resetInSec:<n>}
8
- *
9
- * (field order may vary; `$R[N]` is a Solid hydration reference). This is JS
10
- * source, not JSON, so we extract with regexes rather than `JSON.parse`. Two
11
- * independent reference implementations (pi-go-bars, @beyona/pi-zai-usage)
12
- * use the same approach as of 2026-08, but the format has no stability
13
- * contract — a frontend change will silently break extraction, which is why
14
- * {@link looksLikeDashboard} guards against parser rot.
9
+ * Window mapping:
10
+ * rolling ← meters.fiveHour (resetsAt is null while the window is idle → 0)
11
+ * weekly ← meters.week
12
+ * monthly ← meters.month (carries no resetsAt — anchored to access.endsAt,
13
+ * the subscription renewal instant)
15
14
  */
16
15
  import type { GoWindow } from "./types.js";
17
- /**
18
- * Detect whether the HTML is a dashboard page (vs. a login redirect or error
19
- * page). Used to distinguish "parser is outdated" from "no windows present".
20
- */
21
- export declare function looksLikeDashboard(html: string): boolean;
22
- /** Result of parsing the dashboard — each window is independently optional. */
23
- export interface ParsedGoDashboard {
16
+ /** Result of parsing the status payload — each window is independently optional. */
17
+ export interface ParsedGoStatus {
24
18
  rolling: GoWindow | null;
25
19
  weekly: GoWindow | null;
26
20
  monthly: GoWindow | null;
27
21
  /**
28
- * Set when the HTML looks like a dashboard but no windows parsed — the SSR
29
- * format likely changed. The caller surfaces this as `unavailable`.
22
+ * True when the body parsed and carries the status shape but no window
23
+ * matched — the API layout changed (parser rot).
30
24
  */
31
25
  parserOutdated: boolean;
32
26
  }
33
- /**
34
- * Parse the dashboard HTML into the three windows.
35
- *
36
- * `parserOutdated` is true when the page looks like a dashboard (contains the
37
- * window variable names) but none of the three windows matched — signalling
38
- * that the SolidJS hydration format has drifted.
39
- */
40
- export declare function parseGoDashboard(html: string): ParsedGoDashboard;
27
+ /** Detect the status payload shape (`access.meters`) — the parser-rot guard. */
28
+ export declare function looksLikeGoStatus(parsed: unknown): boolean;
29
+ export declare function parseGoStatus(text: string, now?: number): ParsedGoStatus;
41
30
  //# sourceMappingURL=parse.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/quota/opencode-go/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgD3C;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIxD;AAED,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CAShE"}
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/quota/opencode-go/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAU3C,oFAAoF;AACpF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,QAAQ,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB;AAuBD,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAG1D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,cAAc,CAsBpF"}