@oharness/server 0.8.0 → 0.9.1
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/dist/account-usage.d.ts +29 -0
- package/dist/account-usage.js +56 -0
- package/dist/account-usage.js.map +1 -0
- package/dist/files.d.ts +40 -1
- package/dist/files.js +94 -3
- package/dist/files.js.map +1 -1
- package/dist/i18n.js +126 -2
- package/dist/i18n.js.map +1 -1
- package/dist/page/client/base.js +4 -0
- package/dist/page/client/base.js.map +1 -1
- package/dist/page/client/browser.js +3 -1
- package/dist/page/client/browser.js.map +1 -1
- package/dist/page/client/composer.js +20 -0
- package/dist/page/client/composer.js.map +1 -1
- package/dist/page/client/files.d.ts +7 -0
- package/dist/page/client/files.js +412 -0
- package/dist/page/client/files.js.map +1 -0
- package/dist/page/client/index.js +4 -0
- package/dist/page/client/index.js.map +1 -1
- package/dist/page/client/panels.js +1 -1
- package/dist/page/client/routines.js +19 -1
- package/dist/page/client/routines.js.map +1 -1
- package/dist/page/client/shell.js +12 -1
- package/dist/page/client/shell.js.map +1 -1
- package/dist/page/client/state.js +12 -4
- package/dist/page/client/state.js.map +1 -1
- package/dist/page/client/terminal.d.ts +7 -0
- package/dist/page/client/terminal.js +347 -0
- package/dist/page/client/terminal.js.map +1 -0
- package/dist/page/client/transcript.js +167 -0
- package/dist/page/client/transcript.js.map +1 -1
- package/dist/page/client/usage.js +400 -70
- package/dist/page/client/usage.js.map +1 -1
- package/dist/page/style.js +258 -3
- package/dist/page/style.js.map +1 -1
- package/dist/page.js +35 -1
- package/dist/page.js.map +1 -1
- package/dist/server.js +238 -31
- package/dist/server.js.map +1 -1
- package/dist/terminal.d.ts +34 -0
- package/dist/terminal.js +211 -0
- package/dist/terminal.js.map +1 -0
- package/package.json +9 -8
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the account spent, as the site's ledger has it.
|
|
3
|
+
*
|
|
4
|
+
* The usage page's own figures are summed from the transcripts on this
|
|
5
|
+
* machine, which is everything a key the person brought could ever have
|
|
6
|
+
* charged — and a fraction of what an OHarness account is billed for. Chat on
|
|
7
|
+
* another device is not here, and neither is an image, a video or a clip of
|
|
8
|
+
* audio: a generation is a tool call whose price the gateway settles later,
|
|
9
|
+
* and no transcript carries it. The ledger does, so for a signed-in account
|
|
10
|
+
* the page reads that, through the site, with the account's own token.
|
|
11
|
+
*/
|
|
12
|
+
export type AccountUsage = {
|
|
13
|
+
signedIn: false;
|
|
14
|
+
} | {
|
|
15
|
+
signedIn: true;
|
|
16
|
+
site: string;
|
|
17
|
+
/** Why there are no figures: a site that predates this, or one that cannot be reached. */
|
|
18
|
+
unavailable?: "outdated" | "unreachable";
|
|
19
|
+
error?: string;
|
|
20
|
+
[field: string]: unknown;
|
|
21
|
+
};
|
|
22
|
+
export declare function accountUsage(opts: {
|
|
23
|
+
token: string | undefined;
|
|
24
|
+
/** The team whose credits are being spent, when one is chosen. */
|
|
25
|
+
team: string | undefined;
|
|
26
|
+
site: string;
|
|
27
|
+
query: URLSearchParams;
|
|
28
|
+
fetchImpl?: typeof fetch;
|
|
29
|
+
}): Promise<AccountUsage>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the account spent, as the site's ledger has it.
|
|
3
|
+
*
|
|
4
|
+
* The usage page's own figures are summed from the transcripts on this
|
|
5
|
+
* machine, which is everything a key the person brought could ever have
|
|
6
|
+
* charged — and a fraction of what an OHarness account is billed for. Chat on
|
|
7
|
+
* another device is not here, and neither is an image, a video or a clip of
|
|
8
|
+
* audio: a generation is a tool call whose price the gateway settles later,
|
|
9
|
+
* and no transcript carries it. The ledger does, so for a signed-in account
|
|
10
|
+
* the page reads that, through the site, with the account's own token.
|
|
11
|
+
*/
|
|
12
|
+
/** The window and kind the page is asking about, passed through as asked. */
|
|
13
|
+
const PASSED = ["range", "from", "to", "kind"];
|
|
14
|
+
export async function accountUsage(opts) {
|
|
15
|
+
if (!opts.token)
|
|
16
|
+
return { signedIn: false };
|
|
17
|
+
const query = new URLSearchParams();
|
|
18
|
+
for (const key of PASSED) {
|
|
19
|
+
const value = opts.query.get(key);
|
|
20
|
+
if (value)
|
|
21
|
+
query.set(key, value);
|
|
22
|
+
}
|
|
23
|
+
// The team the next call is billed to is the one whose spend is shown: a
|
|
24
|
+
// page that showed personal figures while the credits went to a team would
|
|
25
|
+
// be answering a question nobody asked.
|
|
26
|
+
if (opts.team)
|
|
27
|
+
query.set("team", opts.team);
|
|
28
|
+
const send = opts.fetchImpl ?? fetch;
|
|
29
|
+
try {
|
|
30
|
+
const response = await send(`${opts.site}/api/usage?${query}`, {
|
|
31
|
+
headers: { authorization: `Bearer ${opts.token}`, accept: "application/json" },
|
|
32
|
+
signal: AbortSignal.timeout(15_000),
|
|
33
|
+
});
|
|
34
|
+
const body = (await response.json().catch(() => undefined));
|
|
35
|
+
if (!response.ok || !body || typeof body["summary"] !== "object") {
|
|
36
|
+
return {
|
|
37
|
+
signedIn: true,
|
|
38
|
+
site: opts.site,
|
|
39
|
+
// A 404 is a site that has not shipped this yet, not one that is down;
|
|
40
|
+
// the page says so rather than suggesting the network is at fault.
|
|
41
|
+
unavailable: response.status === 404 ? "outdated" : "unreachable",
|
|
42
|
+
...(typeof body?.["error"] === "string" ? { error: body["error"] } : {}),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return { ...body, signedIn: true, site: opts.site };
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
return {
|
|
49
|
+
signedIn: true,
|
|
50
|
+
site: opts.site,
|
|
51
|
+
unavailable: "unreachable",
|
|
52
|
+
error: error instanceof Error ? error.message : String(error),
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=account-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account-usage.js","sourceRoot":"","sources":["../src/account-usage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,6EAA6E;AAC7E,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAU,CAAC;AAaxD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAOlC;IACC,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAC5C,MAAM,KAAK,GAAG,IAAI,eAAe,EAAE,CAAC;IACpC,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,KAAK;YAAE,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACnC,CAAC;IACD,yEAAyE;IACzE,2EAA2E;IAC3E,wCAAwC;IACxC,IAAI,IAAI,CAAC,IAAI;QAAE,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAE5C,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,cAAc,KAAK,EAAE,EAAE;YAC7D,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;YAC9E,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;SACpC,CAAC,CAAC;QACH,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAwC,CAAC;QACnG,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,QAAQ,EAAE,CAAC;YACjE,OAAO;gBACL,QAAQ,EAAE,IAAI;gBACd,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,uEAAuE;gBACvE,mEAAmE;gBACnE,WAAW,EAAE,QAAQ,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa;gBACjE,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACzE,CAAC;QACJ,CAAC;QACD,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IACtD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,QAAQ,EAAE,IAAI;YACd,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,aAAa;YAC1B,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/dist/files.d.ts
CHANGED
|
@@ -30,7 +30,9 @@ export declare function within(root: string, target: string): string;
|
|
|
30
30
|
* A directory that cannot be read lists as empty rather than failing: the
|
|
31
31
|
* menu still shows the way back out of it.
|
|
32
32
|
*/
|
|
33
|
-
export declare function browseFiles(root: string, rel?: string
|
|
33
|
+
export declare function browseFiles(root: string, rel?: string, opts?: {
|
|
34
|
+
all?: boolean;
|
|
35
|
+
}): Promise<{
|
|
34
36
|
dir: string;
|
|
35
37
|
parent?: string;
|
|
36
38
|
entries: FileEntry[];
|
|
@@ -46,3 +48,40 @@ export declare function searchFiles(root: string, query: string, limit?: number)
|
|
|
46
48
|
entries: FileEntry[];
|
|
47
49
|
truncated: boolean;
|
|
48
50
|
}>;
|
|
51
|
+
/**
|
|
52
|
+
* What the pane shows by its bytes rather than its text, by extension: the
|
|
53
|
+
* kind of element it goes into, and the type it is served as.
|
|
54
|
+
*
|
|
55
|
+
* Video and audio are the formats Chromium plays without a codec pack; a .mov
|
|
56
|
+
* is usually H.264 inside, which it plays too. A PDF goes to the browser's own
|
|
57
|
+
* viewer.
|
|
58
|
+
*/
|
|
59
|
+
export declare const PREVIEW_MEDIA: Record<string, {
|
|
60
|
+
kind: MediaKind;
|
|
61
|
+
type: string;
|
|
62
|
+
}>;
|
|
63
|
+
export type MediaKind = "image" | "video" | "audio" | "pdf";
|
|
64
|
+
export type FilePreview = {
|
|
65
|
+
path: string;
|
|
66
|
+
size: number;
|
|
67
|
+
kind: "text";
|
|
68
|
+
content: string;
|
|
69
|
+
} | {
|
|
70
|
+
path: string;
|
|
71
|
+
size: number;
|
|
72
|
+
kind: MediaKind | "binary" | "large";
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* One file under `root`, as the files pane shows it.
|
|
76
|
+
*
|
|
77
|
+
* Text comes back whole; an image, a video, a sound or a PDF is only named,
|
|
78
|
+
* so the page fetches its bytes from the raw route into the element that
|
|
79
|
+
* shows it; anything else is described. Unlike
|
|
80
|
+
* the composer's menu this does read contents — it is a viewer the person
|
|
81
|
+
* opened themselves, and it shows them nothing the agent could not.
|
|
82
|
+
*/
|
|
83
|
+
export declare function previewFile(root: string, rel: string): Promise<FilePreview | {
|
|
84
|
+
error: string;
|
|
85
|
+
}>;
|
|
86
|
+
/** A client-supplied path under `root`, or undefined if it climbs out. */
|
|
87
|
+
export declare function resolveFile(root: string, rel: string): string | undefined;
|
package/dist/files.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readdir } from "node:fs/promises";
|
|
1
|
+
import { open, readdir, stat } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
/**
|
|
4
4
|
* Directories that are never what someone is reaching for, and are large
|
|
@@ -16,6 +16,14 @@ const SKIP = new Set([
|
|
|
16
16
|
"__pycache__",
|
|
17
17
|
"venv",
|
|
18
18
|
]);
|
|
19
|
+
/**
|
|
20
|
+
* What the files pane leaves out even when it shows everything.
|
|
21
|
+
*
|
|
22
|
+
* The pane is a tree someone opens one folder at a time, so size is no reason
|
|
23
|
+
* to hide node_modules or a dotfile from it — but git's object store is not a
|
|
24
|
+
* file anybody browses to, and Finder's litter is not the project's.
|
|
25
|
+
*/
|
|
26
|
+
const NEVER_SHOWN = new Set([".git", ".DS_Store"]);
|
|
19
27
|
/** How many directory entries one search may look at before it gives up. */
|
|
20
28
|
const VISIT_BUDGET = 15_000;
|
|
21
29
|
/** How deep a search descends; deeper than this is generated output. */
|
|
@@ -54,7 +62,7 @@ function skip(name) {
|
|
|
54
62
|
* A directory that cannot be read lists as empty rather than failing: the
|
|
55
63
|
* menu still shows the way back out of it.
|
|
56
64
|
*/
|
|
57
|
-
export async function browseFiles(root, rel = "") {
|
|
65
|
+
export async function browseFiles(root, rel = "", opts = {}) {
|
|
58
66
|
const base = path.resolve(root);
|
|
59
67
|
const full = inside(base, rel) ?? base;
|
|
60
68
|
const here = relative(base, full);
|
|
@@ -62,7 +70,7 @@ export async function browseFiles(root, rel = "") {
|
|
|
62
70
|
try {
|
|
63
71
|
const items = await readdir(full, { withFileTypes: true });
|
|
64
72
|
entries = items
|
|
65
|
-
.filter((item) => !skip(item.name))
|
|
73
|
+
.filter((item) => !(opts.all ? NEVER_SHOWN.has(item.name) : skip(item.name)))
|
|
66
74
|
.map((item) => ({
|
|
67
75
|
path: here ? `${here}/${item.name}` : item.name,
|
|
68
76
|
name: item.name,
|
|
@@ -165,4 +173,87 @@ function subsequence(text, needle) {
|
|
|
165
173
|
}
|
|
166
174
|
return score;
|
|
167
175
|
}
|
|
176
|
+
/** Past this a file is described rather than shown: a pane is not an editor. */
|
|
177
|
+
const MAX_PREVIEW_BYTES = 1024 * 1024;
|
|
178
|
+
/** How much of a file is looked at to decide whether it is text. */
|
|
179
|
+
const SNIFF_BYTES = 8000;
|
|
180
|
+
/**
|
|
181
|
+
* What the pane shows by its bytes rather than its text, by extension: the
|
|
182
|
+
* kind of element it goes into, and the type it is served as.
|
|
183
|
+
*
|
|
184
|
+
* Video and audio are the formats Chromium plays without a codec pack; a .mov
|
|
185
|
+
* is usually H.264 inside, which it plays too. A PDF goes to the browser's own
|
|
186
|
+
* viewer.
|
|
187
|
+
*/
|
|
188
|
+
export const PREVIEW_MEDIA = {
|
|
189
|
+
".png": { kind: "image", type: "image/png" },
|
|
190
|
+
".jpg": { kind: "image", type: "image/jpeg" },
|
|
191
|
+
".jpeg": { kind: "image", type: "image/jpeg" },
|
|
192
|
+
".gif": { kind: "image", type: "image/gif" },
|
|
193
|
+
".webp": { kind: "image", type: "image/webp" },
|
|
194
|
+
".avif": { kind: "image", type: "image/avif" },
|
|
195
|
+
".svg": { kind: "image", type: "image/svg+xml" },
|
|
196
|
+
".ico": { kind: "image", type: "image/x-icon" },
|
|
197
|
+
".bmp": { kind: "image", type: "image/bmp" },
|
|
198
|
+
".mp4": { kind: "video", type: "video/mp4" },
|
|
199
|
+
".m4v": { kind: "video", type: "video/mp4" },
|
|
200
|
+
".mov": { kind: "video", type: "video/mp4" },
|
|
201
|
+
".webm": { kind: "video", type: "video/webm" },
|
|
202
|
+
".ogv": { kind: "video", type: "video/ogg" },
|
|
203
|
+
".mp3": { kind: "audio", type: "audio/mpeg" },
|
|
204
|
+
".m4a": { kind: "audio", type: "audio/mp4" },
|
|
205
|
+
".aac": { kind: "audio", type: "audio/aac" },
|
|
206
|
+
".wav": { kind: "audio", type: "audio/wav" },
|
|
207
|
+
".ogg": { kind: "audio", type: "audio/ogg" },
|
|
208
|
+
".oga": { kind: "audio", type: "audio/ogg" },
|
|
209
|
+
".opus": { kind: "audio", type: "audio/ogg" },
|
|
210
|
+
".flac": { kind: "audio", type: "audio/flac" },
|
|
211
|
+
".pdf": { kind: "pdf", type: "application/pdf" },
|
|
212
|
+
};
|
|
213
|
+
/**
|
|
214
|
+
* One file under `root`, as the files pane shows it.
|
|
215
|
+
*
|
|
216
|
+
* Text comes back whole; an image, a video, a sound or a PDF is only named,
|
|
217
|
+
* so the page fetches its bytes from the raw route into the element that
|
|
218
|
+
* shows it; anything else is described. Unlike
|
|
219
|
+
* the composer's menu this does read contents — it is a viewer the person
|
|
220
|
+
* opened themselves, and it shows them nothing the agent could not.
|
|
221
|
+
*/
|
|
222
|
+
export async function previewFile(root, rel) {
|
|
223
|
+
const full = resolveFile(root, rel);
|
|
224
|
+
if (!full)
|
|
225
|
+
return { error: "outside the project" };
|
|
226
|
+
let info;
|
|
227
|
+
try {
|
|
228
|
+
info = await stat(full);
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return { error: "no such file" };
|
|
232
|
+
}
|
|
233
|
+
if (!info.isFile())
|
|
234
|
+
return { error: "not a file" };
|
|
235
|
+
const shown = relative(path.resolve(root), full);
|
|
236
|
+
const base = { path: shown, size: info.size };
|
|
237
|
+
const media = PREVIEW_MEDIA[path.extname(full).toLowerCase()];
|
|
238
|
+
if (media)
|
|
239
|
+
return { ...base, kind: media.kind };
|
|
240
|
+
if (info.size > MAX_PREVIEW_BYTES)
|
|
241
|
+
return { ...base, kind: "large" };
|
|
242
|
+
const handle = await open(full, "r");
|
|
243
|
+
try {
|
|
244
|
+
const bytes = await handle.readFile();
|
|
245
|
+
// A NUL near the start is the cheap, reliable tell: no text encoding a
|
|
246
|
+
// source file would use puts one there, and every binary format does.
|
|
247
|
+
if (bytes.subarray(0, SNIFF_BYTES).includes(0))
|
|
248
|
+
return { ...base, kind: "binary" };
|
|
249
|
+
return { ...base, kind: "text", content: bytes.toString("utf8") };
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
await handle.close();
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/** A client-supplied path under `root`, or undefined if it climbs out. */
|
|
256
|
+
export function resolveFile(root, rel) {
|
|
257
|
+
return inside(path.resolve(root), rel);
|
|
258
|
+
}
|
|
168
259
|
//# sourceMappingURL=files.js.map
|
package/dist/files.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"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"}
|
package/dist/i18n.js
CHANGED
|
@@ -478,7 +478,7 @@ export const STRINGS = {
|
|
|
478
478
|
// pickers and the providers all use, in every language.
|
|
479
479
|
"usage.title": "Usage",
|
|
480
480
|
"usage.value": "Tokens, cache hits and spend, per model and per session",
|
|
481
|
-
"usage.hint": "
|
|
481
|
+
"usage.hint": "Signed in, it shows every charge on your account, images, video and audio included. Otherwise it is totalled from the transcripts on this machine.",
|
|
482
482
|
"usage.open": "Open",
|
|
483
483
|
"usage.range.custom": "Custom",
|
|
484
484
|
"usage.range.apply": "Apply",
|
|
@@ -514,6 +514,39 @@ export const STRINGS = {
|
|
|
514
514
|
"usage.none": "Nothing has been spent yet.",
|
|
515
515
|
"usage.scope": "Every session stored on this machine, including ones started from the terminal.",
|
|
516
516
|
"usage.scopeCapped": "The {n} most recent sessions on this machine. Older ones are not counted.",
|
|
517
|
+
"usage.moreSessions": "View more",
|
|
518
|
+
"usage.allSessions": "Sessions",
|
|
519
|
+
"usage.backToUsage": "Back to usage",
|
|
520
|
+
"usage.searchSessions": "Search by title or model",
|
|
521
|
+
"usage.sessionsCount": "{n} sessions",
|
|
522
|
+
"usage.sessionsOne": "1 session",
|
|
523
|
+
"usage.sessionsNoMatch": "No sessions match.",
|
|
524
|
+
"usage.sessionsEnd": "That's every session.",
|
|
525
|
+
"usage.sessionsCapped": "That's as far back as this page reads.",
|
|
526
|
+
"usage.loading": "Loading…",
|
|
527
|
+
"usage.source.account": "Account",
|
|
528
|
+
"usage.source.device": "This device",
|
|
529
|
+
"usage.images": "{n} images",
|
|
530
|
+
"usage.videoSeconds": "{n} of video",
|
|
531
|
+
"usage.audioSeconds": "{n} of audio",
|
|
532
|
+
"usage.range.24h": "24 hours",
|
|
533
|
+
"usage.perHour": "per hour",
|
|
534
|
+
"usage.kind.all": "All",
|
|
535
|
+
"usage.kind.text": "LLM",
|
|
536
|
+
"usage.kind.image": "Images",
|
|
537
|
+
"usage.kind.video": "Video",
|
|
538
|
+
"usage.kind.audio": "Audio",
|
|
539
|
+
"usage.credits": "{n} credits",
|
|
540
|
+
"usage.calls": "{n} calls",
|
|
541
|
+
"usage.callOne": "1 call",
|
|
542
|
+
"usage.seconds": "{n} s",
|
|
543
|
+
"usage.characters": "{n} characters",
|
|
544
|
+
"usage.kindNone": "Nothing spent on this in the window.",
|
|
545
|
+
"usage.accountScope": "Every charge on your OHarness account, from any device: chat, images, video and audio.",
|
|
546
|
+
"usage.teamScope": "Charges to the team you are spending from, from any device: chat, images, video and audio.",
|
|
547
|
+
"usage.openSite": "Open on the web",
|
|
548
|
+
"usage.accountOutdated": "The site does not offer account usage yet. This device shows what was spent here.",
|
|
549
|
+
"usage.accountUnreachable": "Your account's usage could not be read. Check the connection, or see This device.",
|
|
517
550
|
"projects.title": "Projects",
|
|
518
551
|
"projects.search": "Search projects",
|
|
519
552
|
"projects.add": "Add project",
|
|
@@ -530,6 +563,30 @@ export const STRINGS = {
|
|
|
530
563
|
"projects.revealMac": "Show in Finder",
|
|
531
564
|
"projects.revealWin": "Show in File Explorer",
|
|
532
565
|
"projects.reveal": "Open in file manager",
|
|
566
|
+
"projects.files": "Files",
|
|
567
|
+
"projects.terminal": "Terminal",
|
|
568
|
+
"files.open": "Browse files",
|
|
569
|
+
"files.terminal": "Terminal",
|
|
570
|
+
"files.terminalTab": "Terminal",
|
|
571
|
+
"files.refresh": "Refresh",
|
|
572
|
+
"files.close": "Close",
|
|
573
|
+
"files.empty": "This folder is empty",
|
|
574
|
+
"files.pick": "Pick a file to preview it",
|
|
575
|
+
"files.binary": "This file isn't text, so there's nothing to preview.",
|
|
576
|
+
"files.large": "This file is {size}, too large to preview here.",
|
|
577
|
+
"files.source": "Source",
|
|
578
|
+
"files.rendered": "Preview",
|
|
579
|
+
"files.mention": "Mention in chat",
|
|
580
|
+
"files.resize": "Drag to resize",
|
|
581
|
+
"nav.collapse": "Collapse sidebar",
|
|
582
|
+
"nav.expand": "Expand sidebar",
|
|
583
|
+
"terminal.title": "Terminal",
|
|
584
|
+
"terminal.resize": "Drag to resize the terminal",
|
|
585
|
+
"terminal.new": "New terminal",
|
|
586
|
+
"terminal.close": "Close terminal",
|
|
587
|
+
"terminal.hide": "Hide terminal",
|
|
588
|
+
"terminal.exited": "Shell exited. Press any key to start a new one.",
|
|
589
|
+
"terminal.starting": "Starting shell…",
|
|
533
590
|
"projects.pin": "Pin",
|
|
534
591
|
"projects.unpin": "Unpin",
|
|
535
592
|
"projects.forget": "Remove from list",
|
|
@@ -795,6 +852,11 @@ export const STRINGS = {
|
|
|
795
852
|
"settings.section.sync": "Sync & memory",
|
|
796
853
|
"settings.section.activity": "Activity & privacy",
|
|
797
854
|
"settings.section.advanced": "Advanced",
|
|
855
|
+
"settings.section.about": "About",
|
|
856
|
+
"settings.version": "Version",
|
|
857
|
+
"settings.releaseNotes": "Release notes",
|
|
858
|
+
"settings.checkUpdates": "Check for updates",
|
|
859
|
+
"settings.releaseNotesHint": "What changed in each version of the app, on oharness.ai.",
|
|
798
860
|
"memory.review": "To tidy ({count})",
|
|
799
861
|
"memory.reviewIntro": "Checked on this machine without a model. Nothing changes until you choose.",
|
|
800
862
|
"memory.reviewAutoOn": "Background merging is on: notes about the same subject are merged by the small model, at most once per cooldown. Every other finding waits for you.",
|
|
@@ -1270,7 +1332,7 @@ export const STRINGS = {
|
|
|
1270
1332
|
"settings.cwdHint": "所有会话、工具调用和写入都以此为根目录。",
|
|
1271
1333
|
"usage.title": "用量",
|
|
1272
1334
|
"usage.value": "按模型和会话统计的 token、缓存命中与花费",
|
|
1273
|
-
"usage.hint": "
|
|
1335
|
+
"usage.hint": "登录后显示账户的全部扣费,包括图片、视频和音频;未登录时统计本机保存的对话记录。",
|
|
1274
1336
|
"usage.open": "查看",
|
|
1275
1337
|
"usage.range.custom": "自定义",
|
|
1276
1338
|
"usage.range.apply": "应用",
|
|
@@ -1306,6 +1368,39 @@ export const STRINGS = {
|
|
|
1306
1368
|
"usage.none": "还没有产生任何花费。",
|
|
1307
1369
|
"usage.scope": "包含本机保存的每一个会话,也包含从终端启动的那些。",
|
|
1308
1370
|
"usage.scopeCapped": "本机最近的 {n} 个会话。更早的没有计入。",
|
|
1371
|
+
"usage.moreSessions": "查看更多",
|
|
1372
|
+
"usage.allSessions": "全部会话",
|
|
1373
|
+
"usage.backToUsage": "返回用量",
|
|
1374
|
+
"usage.searchSessions": "按标题或模型搜索",
|
|
1375
|
+
"usage.sessionsCount": "{n} 个会话",
|
|
1376
|
+
"usage.sessionsOne": "1 个会话",
|
|
1377
|
+
"usage.sessionsNoMatch": "没有匹配的会话。",
|
|
1378
|
+
"usage.sessionsEnd": "已经是全部会话了。",
|
|
1379
|
+
"usage.sessionsCapped": "已显示本页能读取的最早会话。",
|
|
1380
|
+
"usage.loading": "加载中…",
|
|
1381
|
+
"usage.source.account": "账户",
|
|
1382
|
+
"usage.source.device": "本机",
|
|
1383
|
+
"usage.images": "{n} 张图片",
|
|
1384
|
+
"usage.videoSeconds": "视频 {n}",
|
|
1385
|
+
"usage.audioSeconds": "音频 {n}",
|
|
1386
|
+
"usage.range.24h": "24 小时",
|
|
1387
|
+
"usage.perHour": "每小时",
|
|
1388
|
+
"usage.kind.all": "全部",
|
|
1389
|
+
"usage.kind.text": "LLM",
|
|
1390
|
+
"usage.kind.image": "图片",
|
|
1391
|
+
"usage.kind.video": "视频",
|
|
1392
|
+
"usage.kind.audio": "音频",
|
|
1393
|
+
"usage.credits": "{n} 积分",
|
|
1394
|
+
"usage.calls": "{n} 次调用",
|
|
1395
|
+
"usage.callOne": "1 次调用",
|
|
1396
|
+
"usage.seconds": "{n} 秒",
|
|
1397
|
+
"usage.characters": "{n} 字符",
|
|
1398
|
+
"usage.kindNone": "这段时间里这一类没有花费。",
|
|
1399
|
+
"usage.accountScope": "你的 OHarness 账户在所有设备上的全部扣费:对话、图片、视频和音频。",
|
|
1400
|
+
"usage.teamScope": "当前使用积分的团队在所有设备上的扣费:对话、图片、视频和音频。",
|
|
1401
|
+
"usage.openSite": "在网页中查看",
|
|
1402
|
+
"usage.accountOutdated": "网站暂不支持账户用量。切换到「本机」可查看本机的花费。",
|
|
1403
|
+
"usage.accountUnreachable": "无法读取账户用量。请检查网络,或切换到「本机」查看。",
|
|
1309
1404
|
"projects.title": "项目",
|
|
1310
1405
|
"projects.search": "搜索项目",
|
|
1311
1406
|
"projects.add": "添加项目",
|
|
@@ -1322,6 +1417,30 @@ export const STRINGS = {
|
|
|
1322
1417
|
"projects.revealMac": "在访达中显示",
|
|
1323
1418
|
"projects.revealWin": "在文件资源管理器中显示",
|
|
1324
1419
|
"projects.reveal": "在文件管理器中打开",
|
|
1420
|
+
"projects.files": "文件",
|
|
1421
|
+
"projects.terminal": "终端",
|
|
1422
|
+
"files.open": "浏览文件",
|
|
1423
|
+
"files.terminal": "终端",
|
|
1424
|
+
"files.terminalTab": "终端",
|
|
1425
|
+
"files.refresh": "刷新",
|
|
1426
|
+
"files.close": "关闭",
|
|
1427
|
+
"files.empty": "这个文件夹是空的",
|
|
1428
|
+
"files.pick": "选择一个文件进行预览",
|
|
1429
|
+
"files.binary": "这不是文本文件,无法预览。",
|
|
1430
|
+
"files.large": "文件大小为 {size},太大了,无法在这里预览。",
|
|
1431
|
+
"files.source": "源码",
|
|
1432
|
+
"files.rendered": "预览",
|
|
1433
|
+
"files.mention": "在对话中引用",
|
|
1434
|
+
"files.resize": "拖动调整大小",
|
|
1435
|
+
"nav.collapse": "收起侧边栏",
|
|
1436
|
+
"nav.expand": "展开侧边栏",
|
|
1437
|
+
"terminal.title": "终端",
|
|
1438
|
+
"terminal.resize": "拖动调整终端高度",
|
|
1439
|
+
"terminal.new": "新建终端",
|
|
1440
|
+
"terminal.close": "关闭终端",
|
|
1441
|
+
"terminal.hide": "隐藏终端",
|
|
1442
|
+
"terminal.exited": "Shell 已退出,按任意键重新启动。",
|
|
1443
|
+
"terminal.starting": "正在启动 Shell…",
|
|
1325
1444
|
"projects.pin": "置顶",
|
|
1326
1445
|
"projects.unpin": "取消置顶",
|
|
1327
1446
|
"projects.forget": "从列表移除",
|
|
@@ -1585,6 +1704,11 @@ export const STRINGS = {
|
|
|
1585
1704
|
"settings.section.sync": "同步与记忆",
|
|
1586
1705
|
"settings.section.activity": "记录与隐私",
|
|
1587
1706
|
"settings.section.advanced": "高级",
|
|
1707
|
+
"settings.section.about": "关于",
|
|
1708
|
+
"settings.version": "版本",
|
|
1709
|
+
"settings.releaseNotes": "更新日志",
|
|
1710
|
+
"settings.checkUpdates": "检查更新",
|
|
1711
|
+
"settings.releaseNotesHint": "应用每个版本的改动,在 oharness.ai 上查看。",
|
|
1588
1712
|
"memory.review": "待整理({count})",
|
|
1589
1713
|
"memory.reviewIntro": "在本机检查,不调用模型。你确认之前不会改动任何记忆。",
|
|
1590
1714
|
"memory.reviewAutoOn": "后台整理已开启:同一主题的记忆会由小模型自动合并,每个冷却周期最多一次。其它问题都等你处理。",
|