zcode-acp-server 0.40.0 → 0.41.0
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/README.md +7 -5
- package/README.zh-CN.md +4 -2
- package/dist/backend/credentials.d.ts.map +1 -1
- package/dist/backend/credentials.js +14 -3
- package/dist/backend/credentials.js.map +1 -1
- package/dist/backend/resolve.d.ts +3 -3
- package/dist/backend/resolve.d.ts.map +1 -1
- package/dist/backend/resolve.js +22 -4
- package/dist/backend/resolve.js.map +1 -1
- package/dist/bin/quota.d.ts +1 -1
- package/dist/bin/quota.d.ts.map +1 -1
- package/dist/bin/quota.js +28 -17
- package/dist/bin/quota.js.map +1 -1
- package/dist/code-fingerprint.json +2 -2
- package/dist/config/options.d.ts +13 -0
- package/dist/config/options.d.ts.map +1 -1
- package/dist/config/options.js +1 -1
- package/dist/config/options.js.map +1 -1
- package/dist/config/user-config.d.ts +10 -0
- package/dist/config/user-config.d.ts.map +1 -1
- package/dist/config/user-config.js +31 -4
- package/dist/config/user-config.js.map +1 -1
- package/dist/handlers/account.d.ts +21 -6
- package/dist/handlers/account.d.ts.map +1 -1
- package/dist/handlers/account.js +25 -8
- package/dist/handlers/account.js.map +1 -1
- package/dist/handlers/background-tasks.d.ts +9 -0
- package/dist/handlers/background-tasks.d.ts.map +1 -1
- package/dist/handlers/background-tasks.js +42 -0
- package/dist/handlers/background-tasks.js.map +1 -1
- package/dist/handlers/extensions.d.ts.map +1 -1
- package/dist/handlers/extensions.js +8 -0
- package/dist/handlers/extensions.js.map +1 -1
- package/dist/handlers/session.d.ts.map +1 -1
- package/dist/handlers/session.js +55 -5
- package/dist/handlers/session.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/quota/combined.d.ts +13 -9
- package/dist/quota/combined.d.ts.map +1 -1
- package/dist/quota/combined.js +54 -29
- package/dist/quota/combined.js.map +1 -1
- package/dist/quota/ollama-cloud/cache.d.ts +16 -0
- package/dist/quota/ollama-cloud/cache.d.ts.map +1 -0
- package/dist/quota/ollama-cloud/cache.js +30 -0
- package/dist/quota/ollama-cloud/cache.js.map +1 -0
- package/dist/quota/ollama-cloud/client.d.ts +23 -0
- package/dist/quota/ollama-cloud/client.d.ts.map +1 -0
- package/dist/quota/ollama-cloud/client.js +33 -0
- package/dist/quota/ollama-cloud/client.js.map +1 -0
- package/dist/quota/ollama-cloud/config.d.ts +25 -0
- package/dist/quota/ollama-cloud/config.d.ts.map +1 -0
- package/dist/quota/ollama-cloud/config.js +31 -0
- package/dist/quota/ollama-cloud/config.js.map +1 -0
- package/dist/quota/ollama-cloud/format.d.ts +28 -0
- package/dist/quota/ollama-cloud/format.d.ts.map +1 -0
- package/dist/quota/ollama-cloud/format.js +53 -0
- package/dist/quota/ollama-cloud/format.js.map +1 -0
- package/dist/quota/ollama-cloud/index.d.ts +27 -0
- package/dist/quota/ollama-cloud/index.d.ts.map +1 -0
- package/dist/quota/ollama-cloud/index.js +91 -0
- package/dist/quota/ollama-cloud/index.js.map +1 -0
- package/dist/quota/ollama-cloud/types.d.ts +44 -0
- package/dist/quota/ollama-cloud/types.d.ts.map +1 -0
- package/dist/quota/ollama-cloud/types.js +15 -0
- package/dist/quota/ollama-cloud/types.js.map +1 -0
- package/dist/quota/opencode-go/config.d.ts +11 -11
- package/dist/quota/opencode-go/config.js +11 -11
- package/dist/quota/opencode-go/index.d.ts.map +1 -1
- package/dist/quota/opencode-go/index.js +16 -7
- package/dist/quota/opencode-go/index.js.map +1 -1
- package/dist/server.d.ts +15 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +25 -0
- package/dist/server.js.map +1 -1
- package/docs/BACKLOG.md +3 -1
- package/docs/CLI.md +45 -13
- package/docs/REMOTE-CLIENTS.md +16 -2
- package/package.json +1 -1
package/dist/quota/combined.js
CHANGED
|
@@ -2,20 +2,23 @@
|
|
|
2
2
|
* Combined multi-provider quota — the orchestration layer used by the
|
|
3
3
|
* `zcode-acp quota` CLI when no provider subcommand is given (default mode).
|
|
4
4
|
*
|
|
5
|
-
* Queries GLM Coding Plan
|
|
6
|
-
* merged card with one section per provider. The `/quota`
|
|
7
|
-
* NOT use this — it stays on the single-provider GLM
|
|
5
|
+
* Queries GLM Coding Plan, Opencode Go, and Ollama Cloud in parallel and
|
|
6
|
+
* renders a single merged card with one section per provider. The `/quota`
|
|
7
|
+
* slash command does NOT use this — it stays on the single-provider GLM
|
|
8
|
+
* {@link formatQuota}.
|
|
8
9
|
*
|
|
9
10
|
* Design notes:
|
|
10
|
-
* - `Promise.all` so a slow
|
|
11
|
-
* - A `not_configured`
|
|
12
|
-
* no error line) in `all` mode, so GLM-only users see no noise. In
|
|
13
|
-
* mode it surfaces as a help line because the user
|
|
11
|
+
* - `Promise.all` so a slow provider scrape doesn't delay the others.
|
|
12
|
+
* - A `not_configured` non-GLM result is silently dropped (no header,
|
|
13
|
+
* no error line) in `all` mode, so GLM-only users see no noise. In that
|
|
14
|
+
* provider's own mode it surfaces as a help line because the user
|
|
15
|
+
* explicitly asked.
|
|
14
16
|
* - The divider width is computed from the widest body line so the frame
|
|
15
17
|
* stays balanced regardless of which windows/counts are present.
|
|
16
18
|
*/
|
|
17
19
|
import { renderGlmSection } from "./format.js";
|
|
18
20
|
import { queryQuota } from "./index.js";
|
|
21
|
+
import { formatOcSection, queryOcUsage } from "./ollama-cloud/index.js";
|
|
19
22
|
import { formatGoSection, queryGoUsage } from "./opencode-go/index.js";
|
|
20
23
|
/**
|
|
21
24
|
* Which Opencode Go windows to render. All three (rolling + weekly + monthly)
|
|
@@ -38,28 +41,37 @@ export function defaultGoWindows(provider) {
|
|
|
38
41
|
* always resolves.
|
|
39
42
|
*/
|
|
40
43
|
export async function queryCombined(provider) {
|
|
41
|
-
//
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
44
|
+
// Single-provider modes skip the other fetches entirely. Skipping is
|
|
45
|
+
// cheaper and avoids touching credentials the user may not have set. We
|
|
46
|
+
// still return all fields so the formatter's shape is uniform.
|
|
47
|
+
const NONE_GLM = { kind: "unavailable" };
|
|
48
|
+
const NONE = { kind: "not_configured" };
|
|
49
|
+
const tasks = {
|
|
50
|
+
glm: provider === "go" || provider === "oc" ? Promise.resolve(NONE_GLM) : queryQuota(),
|
|
51
|
+
go: provider === "glm" || provider === "oc"
|
|
52
|
+
? Promise.resolve(NONE)
|
|
53
|
+
: queryGoUsage(),
|
|
54
|
+
oc: provider === "glm" || provider === "go"
|
|
55
|
+
? Promise.resolve(NONE)
|
|
56
|
+
: queryOcUsage(),
|
|
57
|
+
};
|
|
58
|
+
const [glm, go, oc] = await Promise.all([tasks.glm, tasks.go, tasks.oc]);
|
|
59
|
+
return { glm, go, oc };
|
|
51
60
|
}
|
|
52
61
|
/**
|
|
53
|
-
* Decide whether
|
|
62
|
+
* Decide whether a non-GLM section should appear at all in `all` mode.
|
|
54
63
|
*
|
|
55
64
|
* `not_configured` is silently dropped (the user hasn't set credentials and
|
|
56
|
-
* didn't explicitly ask for
|
|
57
|
-
* and `auth_error` — render so the user sees that something is
|
|
65
|
+
* didn't explicitly ask for that provider). All other kinds — including
|
|
66
|
+
* `unavailable` and `auth_error` — render so the user sees that something is
|
|
67
|
+
* wrong.
|
|
58
68
|
*/
|
|
59
|
-
function
|
|
60
|
-
|
|
69
|
+
function shouldShowSection(result, provider,
|
|
70
|
+
/** The single-provider token that explicitly selects this section. */
|
|
71
|
+
own) {
|
|
72
|
+
if (provider !== "all" && provider !== own)
|
|
61
73
|
return false;
|
|
62
|
-
if (
|
|
74
|
+
if (result.kind === "not_configured" && provider === "all")
|
|
63
75
|
return false;
|
|
64
76
|
return true;
|
|
65
77
|
}
|
|
@@ -109,7 +121,7 @@ function renderCombinedLines(combined, provider, glmOpts, goWindows, color = fal
|
|
|
109
121
|
/** Optional refresh countdown rendered on the separator line after the
|
|
110
122
|
* first section (e.g. `refresh in 29s`). */
|
|
111
123
|
refreshSuffix) {
|
|
112
|
-
const { glm, go } = combined;
|
|
124
|
+
const { glm, go, oc } = combined;
|
|
113
125
|
const sep = separatorLine(refreshSuffix);
|
|
114
126
|
// Fold the color flag into the GLM FormatOptions so it reaches renderGlmSection
|
|
115
127
|
// alongside detail/compact without each caller having to set it.
|
|
@@ -128,33 +140,46 @@ refreshSuffix) {
|
|
|
128
140
|
const lines = [section.header, ...section.body];
|
|
129
141
|
return sep ? [...lines, sep] : lines;
|
|
130
142
|
}
|
|
143
|
+
// Single-provider Ollama Cloud: header + body, no banner/divider.
|
|
144
|
+
if (provider === "oc") {
|
|
145
|
+
const section = formatOcSection(oc, color);
|
|
146
|
+
const lines = [section.header, ...section.body];
|
|
147
|
+
return sep ? [...lines, sep] : lines;
|
|
148
|
+
}
|
|
131
149
|
// Combined `all` mode. GLM renders full (MCP on its own line) — the layout
|
|
132
150
|
// is short enough now that compact mode isn't worth the lost detail.
|
|
133
151
|
const glmSection = renderGlmSection(glm, glmOptsColor);
|
|
134
|
-
const showGo =
|
|
152
|
+
const showGo = shouldShowSection(go, provider, "go");
|
|
135
153
|
const goSection = showGo
|
|
136
154
|
? formatGoSection(go, goWindows ?? defaultGoWindows("all"), Date.now(), color)
|
|
137
155
|
: null;
|
|
156
|
+
const ocSection = shouldShowSection(oc, provider, "oc") ? formatOcSection(oc, color) : null;
|
|
138
157
|
const hasGlm = glmSection.body.length > 0;
|
|
139
158
|
const hasGo = !!goSection && goSection.body.length > 0;
|
|
159
|
+
const hasOc = !!ocSection && ocSection.body.length > 0;
|
|
140
160
|
// The separator line always follows the FIRST rendered section, so its row
|
|
141
|
-
// is fixed
|
|
161
|
+
// is fixed regardless of how many sections follow.
|
|
142
162
|
const sections = [];
|
|
143
163
|
if (hasGlm)
|
|
144
164
|
sections.push([` ${glmSection.header}`, ...glmSection.body]);
|
|
145
165
|
if (hasGo)
|
|
146
166
|
sections.push([` ${goSection.header}`, ...goSection.body]);
|
|
167
|
+
if (hasOc)
|
|
168
|
+
sections.push([` ${ocSection.header}`, ...ocSection.body]);
|
|
147
169
|
if (sections.length === 0) {
|
|
148
170
|
return [" ⚠ no usage data available"];
|
|
149
171
|
}
|
|
150
172
|
// No banner or top divider — the section headers themselves identify each
|
|
151
173
|
// provider, and an extra banner line adds noise without information. The
|
|
152
|
-
// refresh countdown sits on the separator row
|
|
153
|
-
// the
|
|
174
|
+
// refresh countdown sits on the separator row after the FIRST section
|
|
175
|
+
// (right-aligned); later separators stay blank so the countdown is not
|
|
176
|
+
// duplicated across rows.
|
|
154
177
|
const body = [];
|
|
155
178
|
sections.forEach((sec, i) => {
|
|
156
|
-
if (i
|
|
179
|
+
if (i === 1)
|
|
157
180
|
body.push(sep);
|
|
181
|
+
if (i > 1)
|
|
182
|
+
body.push("");
|
|
158
183
|
body.push(...sec);
|
|
159
184
|
});
|
|
160
185
|
// If there's only one section, the separator still trails it so the refresh
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"combined.js","sourceRoot":"","sources":["../../src/quota/combined.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"combined.js","sourceRoot":"","sources":["../../src/quota/combined.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory TTL cache for Ollama Cloud results.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors {@link ../../cache.ts} but typed for {@link OcQueryResult}. Same
|
|
5
|
+
* 10s TTL — matches the quota cache and the CLI's minimum watch interval.
|
|
6
|
+
*/
|
|
7
|
+
import type { OcQueryResult } from "./types.js";
|
|
8
|
+
/** Return the cached result if still fresh, else `null`. */
|
|
9
|
+
export declare function getCached(): OcQueryResult | null;
|
|
10
|
+
/** Store a fresh result, stamping it with the current time. */
|
|
11
|
+
export declare function setCached(result: OcQueryResult): void;
|
|
12
|
+
/** Clear the cache (test helper, and used by CLI watch mode per tick). */
|
|
13
|
+
export declare function clearCache(): void;
|
|
14
|
+
/** Override the clock (test-only). Pass `undefined` to restore real time. */
|
|
15
|
+
export declare function setClock(fn?: () => number): void;
|
|
16
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAUhD,4DAA4D;AAC5D,wBAAgB,SAAS,IAAI,aAAa,GAAG,IAAI,CAGhD;AAED,+DAA+D;AAC/D,wBAAgB,SAAS,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAErD;AAED,0EAA0E;AAC1E,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAED,6EAA6E;AAC7E,wBAAgB,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,MAAM,GAAG,IAAI,CAEhD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory TTL cache for Ollama Cloud results.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors {@link ../../cache.ts} but typed for {@link OcQueryResult}. Same
|
|
5
|
+
* 10s TTL — matches the quota cache and the CLI's minimum watch interval.
|
|
6
|
+
*/
|
|
7
|
+
/** How long a cached result is served before re-querying. */
|
|
8
|
+
const TTL_MS = 10_000;
|
|
9
|
+
let slot = null;
|
|
10
|
+
/** Inject a fake clock — only tests should need this. */
|
|
11
|
+
let now = () => Date.now();
|
|
12
|
+
/** Return the cached result if still fresh, else `null`. */
|
|
13
|
+
export function getCached() {
|
|
14
|
+
if (slot && now() - slot.at < TTL_MS)
|
|
15
|
+
return slot.result;
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
/** Store a fresh result, stamping it with the current time. */
|
|
19
|
+
export function setCached(result) {
|
|
20
|
+
slot = { result, at: now() };
|
|
21
|
+
}
|
|
22
|
+
/** Clear the cache (test helper, and used by CLI watch mode per tick). */
|
|
23
|
+
export function clearCache() {
|
|
24
|
+
slot = null;
|
|
25
|
+
}
|
|
26
|
+
/** Override the clock (test-only). Pass `undefined` to restore real time. */
|
|
27
|
+
export function setClock(fn) {
|
|
28
|
+
now = fn ?? (() => Date.now());
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/cache.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,6DAA6D;AAC7D,MAAM,MAAM,GAAG,MAAM,CAAC;AAEtB,IAAI,IAAI,GAAiD,IAAI,CAAC;AAE9D,yDAAyD;AACzD,IAAI,GAAG,GAAiB,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;AAEzC,4DAA4D;AAC5D,MAAM,UAAU,SAAS;IACvB,IAAI,IAAI,IAAI,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,GAAG,MAAM;QAAE,OAAO,IAAI,CAAC,MAAM,CAAC;IACzD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,SAAS,CAAC,MAAqB;IAC7C,IAAI,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;AAC/B,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,UAAU;IACxB,IAAI,GAAG,IAAI,CAAC;AACd,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,QAAQ,CAAC,EAAiB;IACxC,GAAG,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Cloud usage HTTP client.
|
|
3
|
+
*
|
|
4
|
+
* Talks to `https://ollama.com/api/usage` — an undocumented but live endpoint
|
|
5
|
+
* that returns `{limits:{session:{usage},weekly:{usage}}}` with usage as a
|
|
6
|
+
* 0..1 fraction. Auth is a plain Bearer API key (docs.ollama.com). No
|
|
7
|
+
* rate-limit headers exist on any Ollama endpoint, so the body is the only
|
|
8
|
+
* data source.
|
|
9
|
+
*/
|
|
10
|
+
/** The undocumented usage endpoint (verified live 2026-09). */
|
|
11
|
+
export declare const USAGE_URL = "https://ollama.com/api/usage";
|
|
12
|
+
/**
|
|
13
|
+
* Fetch the usage JSON body.
|
|
14
|
+
*
|
|
15
|
+
* @throws on network errors or timeout. The caller maps these to
|
|
16
|
+
* `unavailable`. Auth failures are NOT thrown — the status is
|
|
17
|
+
* returned so the orchestrator can classify 401/403 as `auth_error`.
|
|
18
|
+
*/
|
|
19
|
+
export declare function fetchOcUsage(apiKey: string, fetchImpl?: typeof globalThis.fetch): Promise<{
|
|
20
|
+
status: number;
|
|
21
|
+
text: string;
|
|
22
|
+
}>;
|
|
23
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,+DAA+D;AAC/D,eAAO,MAAM,SAAS,iCAAiC,CAAC;AAExD;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,SAAS,GAAE,OAAO,UAAU,CAAC,KAAwB,GACpD,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAW3C"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Cloud usage HTTP client.
|
|
3
|
+
*
|
|
4
|
+
* Talks to `https://ollama.com/api/usage` — an undocumented but live endpoint
|
|
5
|
+
* that returns `{limits:{session:{usage},weekly:{usage}}}` with usage as a
|
|
6
|
+
* 0..1 fraction. Auth is a plain Bearer API key (docs.ollama.com). No
|
|
7
|
+
* rate-limit headers exist on any Ollama endpoint, so the body is the only
|
|
8
|
+
* data source.
|
|
9
|
+
*/
|
|
10
|
+
/** Request timeout (ms). Small JSON response; 10s is plenty. */
|
|
11
|
+
const TIMEOUT_MS = 10_000;
|
|
12
|
+
/** The undocumented usage endpoint (verified live 2026-09). */
|
|
13
|
+
export const USAGE_URL = "https://ollama.com/api/usage";
|
|
14
|
+
/**
|
|
15
|
+
* Fetch the usage JSON body.
|
|
16
|
+
*
|
|
17
|
+
* @throws on network errors or timeout. The caller maps these to
|
|
18
|
+
* `unavailable`. Auth failures are NOT thrown — the status is
|
|
19
|
+
* returned so the orchestrator can classify 401/403 as `auth_error`.
|
|
20
|
+
*/
|
|
21
|
+
export async function fetchOcUsage(apiKey, fetchImpl = globalThis.fetch) {
|
|
22
|
+
const resp = await fetchImpl(USAGE_URL, {
|
|
23
|
+
method: "GET",
|
|
24
|
+
headers: {
|
|
25
|
+
Authorization: `Bearer ${apiKey}`,
|
|
26
|
+
Accept: "application/json",
|
|
27
|
+
},
|
|
28
|
+
signal: AbortSignal.timeout(TIMEOUT_MS),
|
|
29
|
+
});
|
|
30
|
+
const text = await resp.text();
|
|
31
|
+
return { status: resp.status, text };
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,gEAAgE;AAChE,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1B,+DAA+D;AAC/D,MAAM,CAAC,MAAM,SAAS,GAAG,8BAA8B,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,MAAc,EACd,YAAqC,UAAU,CAAC,KAAK;IAErD,MAAM,IAAI,GAAG,MAAM,SAAS,CAAC,SAAS,EAAE;QACtC,MAAM,EAAE,KAAK;QACb,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,EAAE;YACjC,MAAM,EAAE,kBAAkB;SAC3B;QACD,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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Cloud credential discovery.
|
|
3
|
+
*
|
|
4
|
+
* The API key comes from two sources, with the **config file taking
|
|
5
|
+
* precedence** over the environment variable (the user-config convention —
|
|
6
|
+
* the file is the authoritative home for stable preferences):
|
|
7
|
+
* 1. `quota.ollamaApiKey` in `~/.config/zcode-acp/config.json`.
|
|
8
|
+
* 2. `OLLAMA_API_KEY` env var — the name Ollama's own docs use for cloud
|
|
9
|
+
* authentication (`Authorization: Bearer $OLLAMA_API_KEY`), kept as a
|
|
10
|
+
* full fallback for setups without a config file and one-off overrides.
|
|
11
|
+
*
|
|
12
|
+
* Unlike Opencode Go (which reuses `~/.pi/agent/` for historical reasons),
|
|
13
|
+
* the Ollama key is a plain static API key and belongs in our own config.
|
|
14
|
+
*
|
|
15
|
+
* A missing/blank key yields `not_configured` (the section is silently
|
|
16
|
+
* skipped in `all` mode).
|
|
17
|
+
*/
|
|
18
|
+
/** Env var name — documented in the CLI help and README. */
|
|
19
|
+
export declare const ENV_API_KEY = "OLLAMA_API_KEY";
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the API key: config file first, env var as fallback. Blank strings
|
|
22
|
+
* count as absent.
|
|
23
|
+
*/
|
|
24
|
+
export declare function loadApiKey(): string | null;
|
|
25
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,4DAA4D;AAC5D,eAAO,MAAM,WAAW,mBAAmB,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAI1C"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Cloud credential discovery.
|
|
3
|
+
*
|
|
4
|
+
* The API key comes from two sources, with the **config file taking
|
|
5
|
+
* precedence** over the environment variable (the user-config convention —
|
|
6
|
+
* the file is the authoritative home for stable preferences):
|
|
7
|
+
* 1. `quota.ollamaApiKey` in `~/.config/zcode-acp/config.json`.
|
|
8
|
+
* 2. `OLLAMA_API_KEY` env var — the name Ollama's own docs use for cloud
|
|
9
|
+
* authentication (`Authorization: Bearer $OLLAMA_API_KEY`), kept as a
|
|
10
|
+
* full fallback for setups without a config file and one-off overrides.
|
|
11
|
+
*
|
|
12
|
+
* Unlike Opencode Go (which reuses `~/.pi/agent/` for historical reasons),
|
|
13
|
+
* the Ollama key is a plain static API key and belongs in our own config.
|
|
14
|
+
*
|
|
15
|
+
* A missing/blank key yields `not_configured` (the section is silently
|
|
16
|
+
* skipped in `all` mode).
|
|
17
|
+
*/
|
|
18
|
+
import process from "node:process";
|
|
19
|
+
import { loadUserConfig } from "../../config/user-config.js";
|
|
20
|
+
/** Env var name — documented in the CLI help and README. */
|
|
21
|
+
export const ENV_API_KEY = "OLLAMA_API_KEY";
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the API key: config file first, env var as fallback. Blank strings
|
|
24
|
+
* count as absent.
|
|
25
|
+
*/
|
|
26
|
+
export function loadApiKey() {
|
|
27
|
+
const file = loadUserConfig().quota?.ollamaApiKey;
|
|
28
|
+
const key = (file ?? process.env[ENV_API_KEY] ?? "").trim();
|
|
29
|
+
return key.length > 0 ? key : null;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,4DAA4D;AAC5D,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAE5C;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,IAAI,GAAG,cAAc,EAAE,CAAC,KAAK,EAAE,YAAY,CAAC;IAClD,MAAM,GAAG,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5D,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Cloud usage formatting.
|
|
3
|
+
*
|
|
4
|
+
* Renders the plan's usage windows as progress bars in the same style as the
|
|
5
|
+
* GLM and Opencode Go sections, so all sections read as one card in the
|
|
6
|
+
* combined view. Which windows exist depends on the account's plan: legacy
|
|
7
|
+
* plans expose session (5h) + weekly; current credit plans expose monthly.
|
|
8
|
+
* The API exposes no reset timestamps, so — unlike the other providers — the
|
|
9
|
+
* lines carry no reset stamp, just the percent.
|
|
10
|
+
*/
|
|
11
|
+
import type { OcQueryResult } from "./types.js";
|
|
12
|
+
/** A rendered section: a header line and zero or more body lines. */
|
|
13
|
+
export interface RenderedSection {
|
|
14
|
+
header: string;
|
|
15
|
+
body: string[];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Render the Ollama Cloud section.
|
|
19
|
+
*
|
|
20
|
+
* Used by the combined formatter. The header is always `Ollama Cloud`; body
|
|
21
|
+
* has one bar line per window. Non-success kinds return a header + a single
|
|
22
|
+
* explanatory line.
|
|
23
|
+
*
|
|
24
|
+
* When `color` is true the bar is a heat-colored 24-bit ANSI bar with the
|
|
25
|
+
* percent overlaid inside, mirroring the other providers' color layout.
|
|
26
|
+
*/
|
|
27
|
+
export declare function formatOcSection(result: OcQueryResult, color?: boolean): RenderedSection;
|
|
28
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAWhD,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,UAAQ,GAAG,eAAe,CAwBrF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Cloud usage formatting.
|
|
3
|
+
*
|
|
4
|
+
* Renders the plan's usage windows as progress bars in the same style as the
|
|
5
|
+
* GLM and Opencode Go sections, so all sections read as one card in the
|
|
6
|
+
* combined view. Which windows exist depends on the account's plan: legacy
|
|
7
|
+
* plans expose session (5h) + weekly; current credit plans expose monthly.
|
|
8
|
+
* The API exposes no reset timestamps, so — unlike the other providers — the
|
|
9
|
+
* lines carry no reset stamp, just the percent.
|
|
10
|
+
*/
|
|
11
|
+
import { pickOverlay, renderColorBar } from "../color.js";
|
|
12
|
+
import { renderBar } from "../format.js";
|
|
13
|
+
import { roundTenth } from "../rounding.js";
|
|
14
|
+
/** Label + window metadata, in display order. Which rows appear depends on
|
|
15
|
+
* the account's plan: legacy plans carry session (5h) + weekly; current
|
|
16
|
+
* credit plans carry monthly only. */
|
|
17
|
+
const WINDOW_META = [
|
|
18
|
+
{ key: "session", label: "5h" },
|
|
19
|
+
{ key: "weekly", label: "Week" },
|
|
20
|
+
{ key: "monthly", label: "Month" },
|
|
21
|
+
];
|
|
22
|
+
/**
|
|
23
|
+
* Render the Ollama Cloud section.
|
|
24
|
+
*
|
|
25
|
+
* Used by the combined formatter. The header is always `Ollama Cloud`; body
|
|
26
|
+
* has one bar line per window. Non-success kinds return a header + a single
|
|
27
|
+
* explanatory line.
|
|
28
|
+
*
|
|
29
|
+
* When `color` is true the bar is a heat-colored 24-bit ANSI bar with the
|
|
30
|
+
* percent overlaid inside, mirroring the other providers' color layout.
|
|
31
|
+
*/
|
|
32
|
+
export function formatOcSection(result, color = false) {
|
|
33
|
+
const header = "Ollama Cloud";
|
|
34
|
+
if (result.kind !== "success") {
|
|
35
|
+
const msg = result.kind === "not_configured"
|
|
36
|
+
? "not configured (set OLLAMA_API_KEY)"
|
|
37
|
+
: result.kind === "auth_error"
|
|
38
|
+
? "auth failed — check your Ollama API key"
|
|
39
|
+
: "unavailable";
|
|
40
|
+
return { header, body: [msg] };
|
|
41
|
+
}
|
|
42
|
+
const body = WINDOW_META.filter((m) => result[m.key] !== undefined).map((m) => {
|
|
43
|
+
const fraction = result[m.key];
|
|
44
|
+
const pct = roundTenth(fraction * 100);
|
|
45
|
+
if (color) {
|
|
46
|
+
const bar = renderColorBar(pct, { overlay: pickOverlay({ usedPercent: pct }) });
|
|
47
|
+
return `${m.label.padEnd(5)} ${bar}`;
|
|
48
|
+
}
|
|
49
|
+
return `${m.label.padEnd(5)} ${renderBar(pct)} ${String(pct).padStart(2)}%`;
|
|
50
|
+
});
|
|
51
|
+
return { header, body };
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/format.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C;;uCAEuC;AACvC,MAAM,WAAW,GAAoE;IACnF,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE;IAC/B,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE;IAChC,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE;CACnC,CAAC;AAQF;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,MAAqB,EAAE,KAAK,GAAG,KAAK;IAClE,MAAM,MAAM,GAAG,cAAc,CAAC;IAE9B,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,GAAG,GACP,MAAM,CAAC,IAAI,KAAK,gBAAgB;YAC9B,CAAC,CAAC,qCAAqC;YACvC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,YAAY;gBAC5B,CAAC,CAAC,yCAAyC;gBAC3C,CAAC,CAAC,aAAa,CAAC;QACtB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC5E,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAE,CAAC;QAChC,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC;QACvC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,EAAE,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAChF,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;QACvC,CAAC;QACD,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Cloud usage orchestration — the entry point used by the
|
|
3
|
+
* `zcode-acp quota` CLI.
|
|
4
|
+
*
|
|
5
|
+
* Flow: credential (env + config file) → cache check → fetch → status/auth
|
|
6
|
+
* check → parse → cache write. Any thrown error degrades to `unavailable`
|
|
7
|
+
* rather than propagating, so the CLI always produces output.
|
|
8
|
+
*
|
|
9
|
+
* A missing API key yields `not_configured`, which the combined view silently
|
|
10
|
+
* skips — so users who only care about GLM see no noise.
|
|
11
|
+
*/
|
|
12
|
+
import type { OcQueryResult } from "./types.js";
|
|
13
|
+
/**
|
|
14
|
+
* Query Ollama Cloud usage and return a normalised {@link OcQueryResult}.
|
|
15
|
+
*
|
|
16
|
+
* - No key → `not_configured`.
|
|
17
|
+
* - Serves a cached result when fresh (< 10s).
|
|
18
|
+
* - HTTP 401/403 → `auth_error` (bad or revoked key).
|
|
19
|
+
* - Network/timeout/parse failure → `unavailable`.
|
|
20
|
+
*/
|
|
21
|
+
export declare function queryOcUsage(): Promise<OcQueryResult>;
|
|
22
|
+
export { clearCache, clearCache as clearOcCache } from "./cache.js";
|
|
23
|
+
export { fetchOcUsage, USAGE_URL } from "./client.js";
|
|
24
|
+
export { formatOcSection } from "./format.js";
|
|
25
|
+
export { loadApiKey, ENV_API_KEY } from "./config.js";
|
|
26
|
+
export type { OcQueryResult, OcUsageResponse } from "./types.js";
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAchD;;;;;;;GAOG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,aAAa,CAAC,CAoD3D;AAGD,OAAO,EAAE,UAAU,EAAE,UAAU,IAAI,YAAY,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ollama Cloud usage orchestration — the entry point used by the
|
|
3
|
+
* `zcode-acp quota` CLI.
|
|
4
|
+
*
|
|
5
|
+
* Flow: credential (env + config file) → cache check → fetch → status/auth
|
|
6
|
+
* check → parse → cache write. Any thrown error degrades to `unavailable`
|
|
7
|
+
* rather than propagating, so the CLI always produces output.
|
|
8
|
+
*
|
|
9
|
+
* A missing API key yields `not_configured`, which the combined view silently
|
|
10
|
+
* skips — so users who only care about GLM see no noise.
|
|
11
|
+
*/
|
|
12
|
+
import { log } from "../../utils.js";
|
|
13
|
+
import { getCached, setCached } from "./cache.js";
|
|
14
|
+
import { loadApiKey } from "./config.js";
|
|
15
|
+
import { fetchOcUsage } from "./client.js";
|
|
16
|
+
/**
|
|
17
|
+
* Validate a usage value from the response body: a finite number in [0, 1].
|
|
18
|
+
*
|
|
19
|
+
* Values > 1 are rejected on purpose: the endpoint is undocumented, and if
|
|
20
|
+
* Ollama ever switches to percent-valued numbers, silently treating 42 as a
|
|
21
|
+
* 4200% fraction would render a nonsensical full bar. The same guard is used
|
|
22
|
+
* by the pi-multi-account reference client.
|
|
23
|
+
*/
|
|
24
|
+
function validFraction(v) {
|
|
25
|
+
return typeof v === "number" && Number.isFinite(v) && v >= 0 && v <= 1;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Query Ollama Cloud usage and return a normalised {@link OcQueryResult}.
|
|
29
|
+
*
|
|
30
|
+
* - No key → `not_configured`.
|
|
31
|
+
* - Serves a cached result when fresh (< 10s).
|
|
32
|
+
* - HTTP 401/403 → `auth_error` (bad or revoked key).
|
|
33
|
+
* - Network/timeout/parse failure → `unavailable`.
|
|
34
|
+
*/
|
|
35
|
+
export async function queryOcUsage() {
|
|
36
|
+
const cached = getCached();
|
|
37
|
+
if (cached) {
|
|
38
|
+
log("ollama-cloud: serving cached result");
|
|
39
|
+
return cached;
|
|
40
|
+
}
|
|
41
|
+
const apiKey = loadApiKey();
|
|
42
|
+
if (!apiKey)
|
|
43
|
+
return { kind: "not_configured" };
|
|
44
|
+
let result;
|
|
45
|
+
try {
|
|
46
|
+
const resp = await fetchOcUsage(apiKey);
|
|
47
|
+
if (resp.status === 401 || resp.status === 403) {
|
|
48
|
+
result = { kind: "auth_error" };
|
|
49
|
+
}
|
|
50
|
+
else if (resp.status !== 200) {
|
|
51
|
+
// 429 = quota exhausted, 5xx = server-side; neither is a usage snapshot.
|
|
52
|
+
log(`ollama-cloud: unexpected status ${resp.status}`);
|
|
53
|
+
result = { kind: "unavailable" };
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const parsed = JSON.parse(resp.text);
|
|
57
|
+
const limits = parsed.limits ?? {};
|
|
58
|
+
const window = (key) => validFraction(limits[key]?.usage) ? limits[key].usage : undefined;
|
|
59
|
+
const session = window("session");
|
|
60
|
+
const weekly = window("weekly");
|
|
61
|
+
const monthly = window("monthly");
|
|
62
|
+
if (session !== undefined || weekly !== undefined || monthly !== undefined) {
|
|
63
|
+
// At least one recognised window — legacy plans carry session+weekly,
|
|
64
|
+
// current credit plans carry monthly only.
|
|
65
|
+
result = {
|
|
66
|
+
kind: "success",
|
|
67
|
+
...(session !== undefined && { session }),
|
|
68
|
+
...(weekly !== undefined && { weekly }),
|
|
69
|
+
...(monthly !== undefined && { monthly }),
|
|
70
|
+
fetchedAt: Date.now(),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
log("ollama-cloud: response shape not recognised (endpoint may have changed)");
|
|
75
|
+
result = { kind: "unavailable" };
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (e) {
|
|
80
|
+
log(`ollama-cloud: fetch failed (${e instanceof Error ? e.message : String(e)})`);
|
|
81
|
+
result = { kind: "unavailable" };
|
|
82
|
+
}
|
|
83
|
+
setCached(result);
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
// Re-exports for consumers (CLI + tests).
|
|
87
|
+
export { clearCache, clearCache as clearOcCache } from "./cache.js";
|
|
88
|
+
export { fetchOcUsage, USAGE_URL } from "./client.js";
|
|
89
|
+
export { formatOcSection } from "./format.js";
|
|
90
|
+
export { loadApiKey, ENV_API_KEY } from "./config.js";
|
|
91
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Ollama Cloud subscription usage feature.
|
|
3
|
+
*
|
|
4
|
+
* `zcode-acp quota` queries the undocumented-but-live
|
|
5
|
+
* `GET https://ollama.com/api/usage` endpoint with the user's API key. The
|
|
6
|
+
* response carries two usage fractions (session = 5h rolling window, weekly =
|
|
7
|
+
* 7d window) in [0, 1] and NO reset timestamps — the server does not expose
|
|
8
|
+
* them, so the card shows bars + percents only (no countdown stamps).
|
|
9
|
+
*
|
|
10
|
+
* Shape verified against live probes + the pi-multi-account reference client
|
|
11
|
+
* (2026-09); see `.zcode/scratch/research-ollama-cloud-usage.md`. Undocumented
|
|
12
|
+
* — treat parse failures as `unavailable`, never as a crash.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Result of querying Ollama Cloud usage — a 4-state sum type mirroring
|
|
16
|
+
* {@link ../opencode-go/types.js GoQueryResult}.
|
|
17
|
+
*
|
|
18
|
+
* `not_configured` is distinct from `unavailable`: the CLI uses it to silently
|
|
19
|
+
* skip the Ollama section in default (all-provider) mode when the user has not
|
|
20
|
+
* supplied an API key, rather than printing an error.
|
|
21
|
+
*/
|
|
22
|
+
export type OcQueryResult = {
|
|
23
|
+
kind: "success";
|
|
24
|
+
/** Present windows only — the account's plan decides which exist.
|
|
25
|
+
* Fractions in [0, 1]. Legacy plans expose session+weekly; current
|
|
26
|
+
* credit plans expose monthly (with per-model request counts). */
|
|
27
|
+
session?: number;
|
|
28
|
+
weekly?: number;
|
|
29
|
+
monthly?: number;
|
|
30
|
+
/** Epoch ms of the fetch (kept for symmetry with the other providers). */
|
|
31
|
+
fetchedAt: number;
|
|
32
|
+
} | {
|
|
33
|
+
kind: "not_configured";
|
|
34
|
+
} | {
|
|
35
|
+
kind: "auth_error";
|
|
36
|
+
} | {
|
|
37
|
+
kind: "unavailable";
|
|
38
|
+
};
|
|
39
|
+
/** Raw /api/usage fetch result — status + body text. */
|
|
40
|
+
export interface OcUsageResponse {
|
|
41
|
+
status: number;
|
|
42
|
+
text: string;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/quota/ollama-cloud/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GACrB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB;;uEAEmE;IACnE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;CACnB,GACD;IAAE,IAAI,EAAE,gBAAgB,CAAA;CAAE,GAC1B;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,CAAC;AAE5B,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd"}
|