pi-observability 1.0.0 → 1.3.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.
@@ -0,0 +1,40 @@
1
+ export type SegmentKey =
2
+ | "modelThink"
3
+ | "runtime"
4
+ | "pwd"
5
+ | "git"
6
+ | "contextUsage"
7
+ | "contextProgress"
8
+ | "contextPercentage"
9
+ | "contextNumbers"
10
+ | "tokens"
11
+ | "tps"
12
+ | "cost";
13
+
14
+ export type PresetName = "minimal" | "standard" | "verbose" | "performance";
15
+
16
+ export interface SettingsConfig {
17
+ version: number;
18
+ preset: PresetName;
19
+ segments: Record<SegmentKey, boolean>;
20
+ contextZones: { expert: number; warning: number };
21
+ }
22
+
23
+ export interface SettingsListItem {
24
+ id: string;
25
+ label: string;
26
+ description: string;
27
+ currentValue: string;
28
+ values: string[];
29
+ }
30
+
31
+ export interface SettingsUpdateResult {
32
+ config: SettingsConfig;
33
+ derivedUpdates: Array<{ id: string; value: string }>;
34
+ }
35
+
36
+ export interface SegmentMetadata {
37
+ id: SegmentKey;
38
+ label: string;
39
+ description: string;
40
+ }
@@ -0,0 +1,62 @@
1
+ import { mkdir, readFile, rename, writeFile, appendFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import type { RawBackend } from "./types.js";
4
+
5
+ export interface FileBackendOptions {
6
+ dir: string;
7
+ }
8
+
9
+ export function createFileBackend(options: FileBackendOptions): RawBackend {
10
+ const { dir } = options;
11
+ let ensured = false;
12
+
13
+ async function ensureDir() {
14
+ if (ensured) return;
15
+ await mkdir(dir, { recursive: true });
16
+ ensured = true;
17
+ }
18
+
19
+ function pathFor(name: string): string {
20
+ return join(dir, name);
21
+ }
22
+
23
+ return {
24
+ async read(name) {
25
+ try {
26
+ return await readFile(pathFor(name), "utf8");
27
+ } catch {
28
+ return undefined;
29
+ }
30
+ },
31
+
32
+ async write(name, content) {
33
+ await ensureDir();
34
+ const target = pathFor(name);
35
+ const temp = `${target}.tmp`;
36
+ await writeFile(temp, content, "utf8");
37
+ await rename(temp, target);
38
+ },
39
+
40
+ async append(name, line) {
41
+ await ensureDir();
42
+ await appendFile(pathFor(name), `${line}\n`, "utf8");
43
+ },
44
+
45
+ async readLines(name, options) {
46
+ const text = await this.read(name);
47
+ if (!text) return [];
48
+ const lines = text.split("\n").filter((l) => l.trim());
49
+ if (options?.last !== undefined && options.last > 0) {
50
+ return lines.slice(-options.last);
51
+ }
52
+ return lines;
53
+ },
54
+
55
+ async trimLines(name, keepLast) {
56
+ const lines = await this.readLines(name);
57
+ if (lines.length <= keepLast) return;
58
+ const kept = lines.slice(-keepLast);
59
+ await this.write(name, kept.map((l) => `${l}\n`).join(""));
60
+ },
61
+ };
62
+ }
@@ -0,0 +1,33 @@
1
+ export { createJsonStore } from "./json-store.js";
2
+ export { createJsonlStore } from "./jsonl-store.js";
3
+ export { createFileBackend, type FileBackendOptions } from "./file-backend.js";
4
+ export { createMemoryBackend } from "./memory-backend.js";
5
+ export type { JsonStore, JsonlStore, Storage, RawBackend } from "./types.js";
6
+
7
+ import { createJsonStore } from "./json-store.js";
8
+ import { createJsonlStore } from "./jsonl-store.js";
9
+ import type { Storage, RawBackend } from "./types.js";
10
+
11
+ export function createStorage(backend: RawBackend): Storage {
12
+ return {
13
+ json<T>(name: string, options?: { defaults?: T }) {
14
+ return createJsonStore(backend, name, options);
15
+ },
16
+ jsonl(name: string) {
17
+ return createJsonlStore(backend, name);
18
+ },
19
+ };
20
+ }
21
+
22
+ import { createFileBackend } from "./file-backend.js";
23
+ import { createMemoryBackend } from "./memory-backend.js";
24
+
25
+ export function createFileStorage(options: { dir: string }): Storage {
26
+ const backend = createFileBackend(options);
27
+ return createStorage(backend);
28
+ }
29
+
30
+ export function createMemoryStorage(): Storage {
31
+ const backend = createMemoryBackend();
32
+ return createStorage(backend);
33
+ }
@@ -0,0 +1,32 @@
1
+ import type { JsonStore, RawBackend } from "./types.js";
2
+
3
+ export function createJsonStore<T>(
4
+ backend: RawBackend,
5
+ name: string,
6
+ options?: { defaults?: T },
7
+ ): JsonStore<T> {
8
+ const fileName = `${name}.json`;
9
+ const defaults = options?.defaults;
10
+
11
+ return {
12
+ async load(): Promise<T> {
13
+ const text = await backend.read(fileName);
14
+ if (text === undefined) {
15
+ if (defaults !== undefined) return defaults;
16
+ throw new Error(`Missing file and no defaults for ${fileName}`);
17
+ }
18
+ try {
19
+ return JSON.parse(text) as T;
20
+ } catch (err) {
21
+ console.error(`[storage] corrupt JSON in ${fileName}, using defaults:`, err);
22
+ if (defaults !== undefined) return defaults;
23
+ throw err;
24
+ }
25
+ },
26
+
27
+ async save(value: T): Promise<void> {
28
+ const text = JSON.stringify(value, null, 2);
29
+ await backend.write(fileName, text);
30
+ },
31
+ };
32
+ }
@@ -0,0 +1,29 @@
1
+ import type { JsonlStore, RawBackend } from "./types.js";
2
+
3
+ export function createJsonlStore<T>(backend: RawBackend, name: string): JsonlStore<T> {
4
+ const fileName = `${name}.jsonl`;
5
+
6
+ return {
7
+ async append(value: T): Promise<void> {
8
+ const line = JSON.stringify(value);
9
+ await backend.append(fileName, line);
10
+ },
11
+
12
+ async read(options?: { last?: number }): Promise<T[]> {
13
+ const lines = await backend.readLines(fileName, options);
14
+ const results: T[] = [];
15
+ for (const line of lines) {
16
+ try {
17
+ results.push(JSON.parse(line) as T);
18
+ } catch (err) {
19
+ console.error(`[storage] corrupt JSONL line in ${fileName}, skipping:`, err);
20
+ }
21
+ }
22
+ return results;
23
+ },
24
+
25
+ async trim(options: { keepLast: number }): Promise<void> {
26
+ await backend.trimLines(fileName, options.keepLast);
27
+ },
28
+ };
29
+ }
@@ -0,0 +1,37 @@
1
+ import type { RawBackend } from "./types.js";
2
+
3
+ export function createMemoryBackend(initial?: Map<string, string>): RawBackend {
4
+ const store = initial ?? new Map<string, string>();
5
+
6
+ return {
7
+ async read(name) {
8
+ return store.get(name);
9
+ },
10
+
11
+ async write(name, content) {
12
+ store.set(name, content);
13
+ },
14
+
15
+ async append(name, line) {
16
+ const existing = store.get(name) ?? "";
17
+ store.set(name, `${existing}${line}\n`);
18
+ },
19
+
20
+ async readLines(name, options) {
21
+ const text = store.get(name);
22
+ if (!text) return [];
23
+ const lines = text.split("\n").filter((l) => l.trim());
24
+ if (options?.last !== undefined && options.last > 0) {
25
+ return lines.slice(-options.last);
26
+ }
27
+ return lines;
28
+ },
29
+
30
+ async trimLines(name, keepLast) {
31
+ const lines = await this.readLines(name);
32
+ if (lines.length <= keepLast) return;
33
+ const kept = lines.slice(-keepLast);
34
+ store.set(name, kept.map((l) => `${l}\n`).join(""));
35
+ },
36
+ };
37
+ }
@@ -0,0 +1,23 @@
1
+ export interface JsonStore<T> {
2
+ load(): Promise<T>;
3
+ save(value: T): Promise<void>;
4
+ }
5
+
6
+ export interface JsonlStore<T> {
7
+ append(value: T): Promise<void>;
8
+ read(options?: { last?: number }): Promise<T[]>;
9
+ trim(options: { keepLast: number }): Promise<void>;
10
+ }
11
+
12
+ export interface Storage {
13
+ json<T>(name: string, options?: { defaults?: T }): JsonStore<T>;
14
+ jsonl<T>(name: string): JsonlStore<T>;
15
+ }
16
+
17
+ export interface RawBackend {
18
+ read(name: string): Promise<string | undefined>;
19
+ write(name: string, content: string): Promise<void>;
20
+ append(name: string, line: string): Promise<void>;
21
+ readLines(name: string, options?: { last?: number }): Promise<string[]>;
22
+ trimLines(name: string, keepLast: number): Promise<void>;
23
+ }