@elaraai/e3-ui-cli 1.0.71 → 1.0.73
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 +46 -21
- package/dist/app/assets/{engine-BKZbmXkC-hslJZfFw.js → engine-Bm-cIDd_-DwUdGcTZ.js} +1 -1
- package/dist/app/assets/{index-8USNHP31.js → index-mj-YVVN1.js} +92 -92
- package/dist/app/index.html +1 -1
- package/dist/cli.js +36 -5
- package/dist/cli.js.map +1 -1
- package/dist/commands/tui.d.ts +84 -0
- package/dist/commands/tui.d.ts.map +1 -0
- package/dist/commands/tui.js +86 -0
- package/dist/commands/tui.js.map +1 -0
- package/dist/tui/api.d.ts +108 -0
- package/dist/tui/api.d.ts.map +1 -0
- package/dist/tui/api.js +130 -0
- package/dist/tui/api.js.map +1 -0
- package/dist/tui/app.d.ts +23 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +241 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/controller.d.ts +116 -0
- package/dist/tui/controller.d.ts.map +1 -0
- package/dist/tui/controller.js +620 -0
- package/dist/tui/controller.js.map +1 -0
- package/dist/tui/data/dataflow.d.ts +68 -0
- package/dist/tui/data/dataflow.d.ts.map +1 -0
- package/dist/tui/data/dataflow.js +137 -0
- package/dist/tui/data/dataflow.js.map +1 -0
- package/dist/tui/data/dataset.d.ts +80 -0
- package/dist/tui/data/dataset.d.ts.map +1 -0
- package/dist/tui/data/dataset.js +297 -0
- package/dist/tui/data/dataset.js.map +1 -0
- package/dist/tui/data/edit-buffer.d.ts +74 -0
- package/dist/tui/data/edit-buffer.d.ts.map +1 -0
- package/dist/tui/data/edit-buffer.js +120 -0
- package/dist/tui/data/edit-buffer.js.map +1 -0
- package/dist/tui/data/feeds.d.ts +45 -0
- package/dist/tui/data/feeds.d.ts.map +1 -0
- package/dist/tui/data/feeds.js +318 -0
- package/dist/tui/data/feeds.js.map +1 -0
- package/dist/tui/data/logs.d.ts +68 -0
- package/dist/tui/data/logs.d.ts.map +1 -0
- package/dist/tui/data/logs.js +134 -0
- package/dist/tui/data/logs.js.map +1 -0
- package/dist/tui/input/commands.d.ts +159 -0
- package/dist/tui/input/commands.d.ts.map +1 -0
- package/dist/tui/input/commands.js +259 -0
- package/dist/tui/input/commands.js.map +1 -0
- package/dist/tui/input/completion.d.ts +63 -0
- package/dist/tui/input/completion.d.ts.map +1 -0
- package/dist/tui/input/completion.js +128 -0
- package/dist/tui/input/completion.js.map +1 -0
- package/dist/tui/input/keymap.d.ts +153 -0
- package/dist/tui/input/keymap.d.ts.map +1 -0
- package/dist/tui/input/keymap.js +206 -0
- package/dist/tui/input/keymap.js.map +1 -0
- package/dist/tui/input/mouse.d.ts +52 -0
- package/dist/tui/input/mouse.d.ts.map +1 -0
- package/dist/tui/input/mouse.js +55 -0
- package/dist/tui/input/mouse.js.map +1 -0
- package/dist/tui/lifecycle.d.ts +61 -0
- package/dist/tui/lifecycle.d.ts.map +1 -0
- package/dist/tui/lifecycle.js +99 -0
- package/dist/tui/lifecycle.js.map +1 -0
- package/dist/tui/model/catalogue.d.ts +28 -0
- package/dist/tui/model/catalogue.d.ts.map +1 -0
- package/dist/tui/model/catalogue.js +94 -0
- package/dist/tui/model/catalogue.js.map +1 -0
- package/dist/tui/model/help.d.ts +37 -0
- package/dist/tui/model/help.d.ts.map +1 -0
- package/dist/tui/model/help.js +210 -0
- package/dist/tui/model/help.js.map +1 -0
- package/dist/tui/model/index.d.ts +42 -0
- package/dist/tui/model/index.d.ts.map +1 -0
- package/dist/tui/model/index.js +50 -0
- package/dist/tui/model/index.js.map +1 -0
- package/dist/tui/model/status.d.ts +88 -0
- package/dist/tui/model/status.d.ts.map +1 -0
- package/dist/tui/model/status.js +137 -0
- package/dist/tui/model/status.js.map +1 -0
- package/dist/tui/model/tree.d.ts +112 -0
- package/dist/tui/model/tree.d.ts.map +1 -0
- package/dist/tui/model/tree.js +178 -0
- package/dist/tui/model/tree.js.map +1 -0
- package/dist/tui/model/types.d.ts +21 -0
- package/dist/tui/model/types.d.ts.map +1 -0
- package/dist/tui/model/types.js +46 -0
- package/dist/tui/model/types.js.map +1 -0
- package/dist/tui/render/glyphs.d.ts +122 -0
- package/dist/tui/render/glyphs.d.ts.map +1 -0
- package/dist/tui/render/glyphs.js +122 -0
- package/dist/tui/render/glyphs.js.map +1 -0
- package/dist/tui/render/layout.d.ts +145 -0
- package/dist/tui/render/layout.d.ts.map +1 -0
- package/dist/tui/render/layout.js +209 -0
- package/dist/tui/render/layout.js.map +1 -0
- package/dist/tui/render/text.d.ts +149 -0
- package/dist/tui/render/text.d.ts.map +1 -0
- package/dist/tui/render/text.js +288 -0
- package/dist/tui/render/text.js.map +1 -0
- package/dist/tui/render/theme.d.ts +88 -0
- package/dist/tui/render/theme.d.ts.map +1 -0
- package/dist/tui/render/theme.js +145 -0
- package/dist/tui/render/theme.js.map +1 -0
- package/dist/tui/session.d.ts +78 -0
- package/dist/tui/session.d.ts.map +1 -0
- package/dist/tui/session.js +237 -0
- package/dist/tui/session.js.map +1 -0
- package/dist/tui/state/actions.d.ts +584 -0
- package/dist/tui/state/actions.d.ts.map +1 -0
- package/dist/tui/state/actions.js +62 -0
- package/dist/tui/state/actions.js.map +1 -0
- package/dist/tui/state/persist.d.ts +114 -0
- package/dist/tui/state/persist.d.ts.map +1 -0
- package/dist/tui/state/persist.js +187 -0
- package/dist/tui/state/persist.js.map +1 -0
- package/dist/tui/state/poll.d.ts +99 -0
- package/dist/tui/state/poll.d.ts.map +1 -0
- package/dist/tui/state/poll.js +160 -0
- package/dist/tui/state/poll.js.map +1 -0
- package/dist/tui/state/reducer.d.ts +16 -0
- package/dist/tui/state/reducer.d.ts.map +1 -0
- package/dist/tui/state/reducer.js +363 -0
- package/dist/tui/state/reducer.js.map +1 -0
- package/dist/tui/state/store.d.ts +37 -0
- package/dist/tui/state/store.d.ts.map +1 -0
- package/dist/tui/state/store.js +84 -0
- package/dist/tui/state/store.js.map +1 -0
- package/dist/tui/suspend.d.ts +17 -0
- package/dist/tui/suspend.d.ts.map +1 -0
- package/dist/tui/suspend.js +33 -0
- package/dist/tui/suspend.js.map +1 -0
- package/dist/tui/ui/App.d.ts +41 -0
- package/dist/tui/ui/App.d.ts.map +1 -0
- package/dist/tui/ui/App.js +92 -0
- package/dist/tui/ui/App.js.map +1 -0
- package/dist/tui/ui/frame.d.ts +86 -0
- package/dist/tui/ui/frame.d.ts.map +1 -0
- package/dist/tui/ui/frame.js +42 -0
- package/dist/tui/ui/frame.js.map +1 -0
- package/dist/tui/ui/lines.d.ts +92 -0
- package/dist/tui/ui/lines.d.ts.map +1 -0
- package/dist/tui/ui/lines.js +94 -0
- package/dist/tui/ui/lines.js.map +1 -0
- package/dist/tui/ui/shell/chrome.d.ts +61 -0
- package/dist/tui/ui/shell/chrome.d.ts.map +1 -0
- package/dist/tui/ui/shell/chrome.js +272 -0
- package/dist/tui/ui/shell/chrome.js.map +1 -0
- package/dist/tui/ui/shell/widgets.d.ts +75 -0
- package/dist/tui/ui/shell/widgets.d.ts.map +1 -0
- package/dist/tui/ui/shell/widgets.js +160 -0
- package/dist/tui/ui/shell/widgets.js.map +1 -0
- package/dist/tui/ui/views/about.d.ts +20 -0
- package/dist/tui/ui/views/about.d.ts.map +1 -0
- package/dist/tui/ui/views/about.js +40 -0
- package/dist/tui/ui/views/about.js.map +1 -0
- package/dist/tui/ui/views/all.d.ts +17 -0
- package/dist/tui/ui/views/all.d.ts.map +1 -0
- package/dist/tui/ui/views/all.js +17 -0
- package/dist/tui/ui/views/all.js.map +1 -0
- package/dist/tui/ui/views/dashboard.d.ts +156 -0
- package/dist/tui/ui/views/dashboard.d.ts.map +1 -0
- package/dist/tui/ui/views/dashboard.js +599 -0
- package/dist/tui/ui/views/dashboard.js.map +1 -0
- package/dist/tui/ui/views/help.d.ts +17 -0
- package/dist/tui/ui/views/help.d.ts.map +1 -0
- package/dist/tui/ui/views/help.js +65 -0
- package/dist/tui/ui/views/help.js.map +1 -0
- package/dist/tui/ui/views/index.d.ts +42 -0
- package/dist/tui/ui/views/index.d.ts.map +1 -0
- package/dist/tui/ui/views/index.js +42 -0
- package/dist/tui/ui/views/index.js.map +1 -0
- package/dist/tui/ui/views/input.d.ts +6 -0
- package/dist/tui/ui/views/input.d.ts.map +1 -0
- package/dist/tui/ui/views/input.js +494 -0
- package/dist/tui/ui/views/input.js.map +1 -0
- package/dist/tui/ui/views/launch.d.ts +16 -0
- package/dist/tui/ui/views/launch.d.ts.map +1 -0
- package/dist/tui/ui/views/launch.js +43 -0
- package/dist/tui/ui/views/launch.js.map +1 -0
- package/dist/tui/ui/views/refusal.d.ts +20 -0
- package/dist/tui/ui/views/refusal.d.ts.map +1 -0
- package/dist/tui/ui/views/refusal.js +47 -0
- package/dist/tui/ui/views/refusal.js.map +1 -0
- package/dist/tui/ui/views/repos.d.ts +10 -0
- package/dist/tui/ui/views/repos.d.ts.map +1 -0
- package/dist/tui/ui/views/repos.js +93 -0
- package/dist/tui/ui/views/repos.js.map +1 -0
- package/dist/tui/ui/views/task.d.ts +17 -0
- package/dist/tui/ui/views/task.d.ts.map +1 -0
- package/dist/tui/ui/views/task.js +309 -0
- package/dist/tui/ui/views/task.js.map +1 -0
- package/dist/tui/ui/views/wordmark.d.ts +15 -0
- package/dist/tui/ui/views/wordmark.d.ts.map +1 -0
- package/dist/tui/ui/views/wordmark.js +50 -0
- package/dist/tui/ui/views/wordmark.js.map +1 -0
- package/dist/tui/ui/views/workspaces.d.ts +17 -0
- package/dist/tui/ui/views/workspaces.d.ts.map +1 -0
- package/dist/tui/ui/views/workspaces.js +127 -0
- package/dist/tui/ui/views/workspaces.js.map +1 -0
- package/dist/tui/ui/widgets/leaf-editor.d.ts +58 -0
- package/dist/tui/ui/widgets/leaf-editor.d.ts.map +1 -0
- package/dist/tui/ui/widgets/leaf-editor.js +119 -0
- package/dist/tui/ui/widgets/leaf-editor.js.map +1 -0
- package/dist/tui/ui/widgets/logs.d.ts +99 -0
- package/dist/tui/ui/widgets/logs.d.ts.map +1 -0
- package/dist/tui/ui/widgets/logs.js +291 -0
- package/dist/tui/ui/widgets/logs.js.map +1 -0
- package/dist/tui/ui/widgets/reads.d.ts +62 -0
- package/dist/tui/ui/widgets/reads.d.ts.map +1 -0
- package/dist/tui/ui/widgets/reads.js +122 -0
- package/dist/tui/ui/widgets/reads.js.map +1 -0
- package/dist/tui/ui/widgets/runs.d.ts +51 -0
- package/dist/tui/ui/widgets/runs.d.ts.map +1 -0
- package/dist/tui/ui/widgets/runs.js +86 -0
- package/dist/tui/ui/widgets/runs.js.map +1 -0
- package/dist/tui/ui/widgets/tree.d.ts +149 -0
- package/dist/tui/ui/widgets/tree.d.ts.map +1 -0
- package/dist/tui/ui/widgets/tree.js +584 -0
- package/dist/tui/ui/widgets/tree.js.map +1 -0
- package/package.json +22 -12
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/** The state schema version this build reads and writes. */
|
|
6
|
+
export declare const STATE_VERSION = 1;
|
|
7
|
+
/** Tree entries kept (least recently used dropped first). */
|
|
8
|
+
export declare const MAX_TREE_ENTRIES = 200;
|
|
9
|
+
/** Debounce between a change and the write, in milliseconds. */
|
|
10
|
+
export declare const WRITE_DEBOUNCE_MS = 250;
|
|
11
|
+
/** A value tree's remembered UI state. */
|
|
12
|
+
export interface TreeState {
|
|
13
|
+
/** Per-row expansion overrides keyed by row id. */
|
|
14
|
+
open: Record<string, boolean>;
|
|
15
|
+
/** The first visible flat row. */
|
|
16
|
+
topRow: number;
|
|
17
|
+
/** The collapse-all / expand-all override of the open depth. */
|
|
18
|
+
baseDepth?: number | undefined;
|
|
19
|
+
/** Epoch milliseconds of the last touch (the LRU key). */
|
|
20
|
+
touched: number;
|
|
21
|
+
}
|
|
22
|
+
/** A repository's remembered state. */
|
|
23
|
+
export interface RepoState {
|
|
24
|
+
/** The last workspace opened. */
|
|
25
|
+
workspace?: string | undefined;
|
|
26
|
+
/** The last view (`dashboard`, `task:<name>`, `input:<name>`). */
|
|
27
|
+
view?: string | undefined;
|
|
28
|
+
/** Value trees by storage key (`${ws}:${path}`). */
|
|
29
|
+
trees: Record<string, TreeState>;
|
|
30
|
+
}
|
|
31
|
+
/** The whole state file. */
|
|
32
|
+
export interface PersistedState {
|
|
33
|
+
version: typeof STATE_VERSION;
|
|
34
|
+
/** The last repository argument opened. */
|
|
35
|
+
lastRepo?: string | undefined;
|
|
36
|
+
/** Repositories by key (the resolved local path or the remote URL). */
|
|
37
|
+
repos: Record<string, RepoState>;
|
|
38
|
+
}
|
|
39
|
+
/** An empty state file. */
|
|
40
|
+
export declare function emptyState(): PersistedState;
|
|
41
|
+
/**
|
|
42
|
+
* Resolves the state file path.
|
|
43
|
+
*
|
|
44
|
+
* @param env - The environment
|
|
45
|
+
* @param platform - `process.platform`
|
|
46
|
+
* @param home - The home directory
|
|
47
|
+
* @returns `$E3_UI_STATE`, else `$XDG_STATE_HOME/e3-ui/state.json`, else the platform default
|
|
48
|
+
*/
|
|
49
|
+
export declare function statePath(env: NodeJS.ProcessEnv, platform: NodeJS.Platform, home: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Whether a parsed value is a state file this build can read.
|
|
52
|
+
*
|
|
53
|
+
* @param value - The parsed JSON
|
|
54
|
+
* @returns `true` for a v1 object with a `repos` record
|
|
55
|
+
*/
|
|
56
|
+
export declare function isPersistedState(value: unknown): value is PersistedState;
|
|
57
|
+
/**
|
|
58
|
+
* Loads the state file. A missing file starts fresh; a corrupt or
|
|
59
|
+
* incompatible one is renamed to `<file>.bak` and started fresh.
|
|
60
|
+
*
|
|
61
|
+
* @param file - The state file path
|
|
62
|
+
* @returns The state and, when the file was set aside, the backup path
|
|
63
|
+
*/
|
|
64
|
+
export declare function loadState(file: string): {
|
|
65
|
+
state: PersistedState;
|
|
66
|
+
recoveredFrom?: string;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Writes the state file atomically (temp file + rename) with mode 0600,
|
|
70
|
+
* creating its directory (0700) as needed.
|
|
71
|
+
*
|
|
72
|
+
* @param file - The state file path
|
|
73
|
+
* @param state - The state
|
|
74
|
+
*/
|
|
75
|
+
export declare function writeStateSync(file: string, state: PersistedState): void;
|
|
76
|
+
/**
|
|
77
|
+
* Drops the least recently touched tree entries beyond the cap.
|
|
78
|
+
*
|
|
79
|
+
* @param state - The state (mutated)
|
|
80
|
+
* @param max - The cap
|
|
81
|
+
*/
|
|
82
|
+
export declare function pruneTrees(state: PersistedState, max?: number): void;
|
|
83
|
+
/** The debounced writer. */
|
|
84
|
+
export interface Persister {
|
|
85
|
+
/** The current state (read-only view). */
|
|
86
|
+
readonly state: PersistedState;
|
|
87
|
+
/** Applies a change and schedules a write. */
|
|
88
|
+
update(fn: (state: PersistedState) => void): void;
|
|
89
|
+
/** Writes now if anything is pending. */
|
|
90
|
+
flush(): void;
|
|
91
|
+
/** Whether a write is pending. */
|
|
92
|
+
readonly dirty: boolean;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Creates the debounced writer over a state file.
|
|
96
|
+
*
|
|
97
|
+
* @param file - The state file path
|
|
98
|
+
* @param initial - The loaded state
|
|
99
|
+
* @param options - `debounceMs` (default 250) and `onError` for write failures
|
|
100
|
+
* @returns The persister
|
|
101
|
+
*/
|
|
102
|
+
export declare function createPersister(file: string, initial: PersistedState, options?: {
|
|
103
|
+
debounceMs?: number;
|
|
104
|
+
onError?: (error: unknown) => void;
|
|
105
|
+
}): Persister;
|
|
106
|
+
/**
|
|
107
|
+
* The repository's state entry, created when missing.
|
|
108
|
+
*
|
|
109
|
+
* @param state - The state file
|
|
110
|
+
* @param repoKey - The repository key
|
|
111
|
+
* @returns The entry
|
|
112
|
+
*/
|
|
113
|
+
export declare function repoEntry(state: PersistedState, repoKey: string): RepoState;
|
|
114
|
+
//# sourceMappingURL=persist.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persist.d.ts","sourceRoot":"","sources":["../../../src/tui/state/persist.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAoBH,4DAA4D;AAC5D,eAAO,MAAM,aAAa,IAAI,CAAC;AAC/B,6DAA6D;AAC7D,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,gEAAgE;AAChE,eAAO,MAAM,iBAAiB,MAAM,CAAC;AAErC,0CAA0C;AAC1C,MAAM,WAAW,SAAS;IACtB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,0DAA0D;IAC1D,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,uCAAuC;AACvC,MAAM,WAAW,SAAS;IACtB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACpC;AAED,4BAA4B;AAC5B,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,OAAO,aAAa,CAAC;IAC9B,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACpC;AAED,2BAA2B;AAC3B,wBAAgB,UAAU,IAAI,cAAc,CAE3C;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAUjG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,cAAc,CAIxE;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG;IAAE,KAAK,EAAE,cAAc,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAoBzF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,IAAI,CAMxE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,SAAmB,GAAG,IAAI,CAU9E;AAED,4BAA4B;AAC5B,MAAM,WAAW,SAAS;IACtB,0CAA0C;IAC1C,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,8CAA8C;IAC9C,MAAM,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI,CAAC;IAClD,yCAAyC;IACzC,KAAK,IAAI,IAAI,CAAC;IACd,kCAAkC;IAClC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,cAAc,EACvB,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;CAAO,GAC1E,SAAS,CAgCX;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAO3E"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The state file — where `e3-ui` remembers the last repository, each
|
|
7
|
+
* repository's last workspace and view, and each value tree's expand-set
|
|
8
|
+
* and top row.
|
|
9
|
+
*
|
|
10
|
+
* Path: `$E3_UI_STATE`, else `$XDG_STATE_HOME/e3-ui/state.json`, else
|
|
11
|
+
* `~/.local/state/e3-ui/state.json` (`%LOCALAPPDATA%\e3-ui\state.json` on
|
|
12
|
+
* Windows). Mode 0600, written atomically (tmp + rename), debounced 250 ms,
|
|
13
|
+
* schema v1 with a `version` guard, tree entries bounded to 200 (LRU), a
|
|
14
|
+
* corrupt file renamed to `.bak` and started fresh. Never tokens — those
|
|
15
|
+
* stay in `~/.e3/credentials.json`.
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
import * as fs from 'node:fs';
|
|
20
|
+
import * as path from 'node:path';
|
|
21
|
+
/** The state schema version this build reads and writes. */
|
|
22
|
+
export const STATE_VERSION = 1;
|
|
23
|
+
/** Tree entries kept (least recently used dropped first). */
|
|
24
|
+
export const MAX_TREE_ENTRIES = 200;
|
|
25
|
+
/** Debounce between a change and the write, in milliseconds. */
|
|
26
|
+
export const WRITE_DEBOUNCE_MS = 250;
|
|
27
|
+
/** An empty state file. */
|
|
28
|
+
export function emptyState() {
|
|
29
|
+
return { version: STATE_VERSION, repos: {} };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the state file path.
|
|
33
|
+
*
|
|
34
|
+
* @param env - The environment
|
|
35
|
+
* @param platform - `process.platform`
|
|
36
|
+
* @param home - The home directory
|
|
37
|
+
* @returns `$E3_UI_STATE`, else `$XDG_STATE_HOME/e3-ui/state.json`, else the platform default
|
|
38
|
+
*/
|
|
39
|
+
export function statePath(env, platform, home) {
|
|
40
|
+
const explicit = env['E3_UI_STATE'];
|
|
41
|
+
if (explicit !== undefined && explicit !== '')
|
|
42
|
+
return explicit;
|
|
43
|
+
const xdg = env['XDG_STATE_HOME'];
|
|
44
|
+
if (xdg !== undefined && xdg !== '')
|
|
45
|
+
return path.join(xdg, 'e3-ui', 'state.json');
|
|
46
|
+
if (platform === 'win32') {
|
|
47
|
+
const local = env['LOCALAPPDATA'];
|
|
48
|
+
return path.join(local !== undefined && local !== '' ? local : path.join(home, 'AppData', 'Local'), 'e3-ui', 'state.json');
|
|
49
|
+
}
|
|
50
|
+
return path.join(home, '.local', 'state', 'e3-ui', 'state.json');
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Whether a parsed value is a state file this build can read.
|
|
54
|
+
*
|
|
55
|
+
* @param value - The parsed JSON
|
|
56
|
+
* @returns `true` for a v1 object with a `repos` record
|
|
57
|
+
*/
|
|
58
|
+
export function isPersistedState(value) {
|
|
59
|
+
if (typeof value !== 'object' || value === null)
|
|
60
|
+
return false;
|
|
61
|
+
const v = value;
|
|
62
|
+
return v['version'] === STATE_VERSION && typeof v['repos'] === 'object' && v['repos'] !== null;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Loads the state file. A missing file starts fresh; a corrupt or
|
|
66
|
+
* incompatible one is renamed to `<file>.bak` and started fresh.
|
|
67
|
+
*
|
|
68
|
+
* @param file - The state file path
|
|
69
|
+
* @returns The state and, when the file was set aside, the backup path
|
|
70
|
+
*/
|
|
71
|
+
export function loadState(file) {
|
|
72
|
+
let text;
|
|
73
|
+
try {
|
|
74
|
+
text = fs.readFileSync(file, 'utf8');
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
return { state: emptyState() };
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const parsed = JSON.parse(text);
|
|
81
|
+
if (isPersistedState(parsed))
|
|
82
|
+
return { state: parsed };
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// fall through to recovery
|
|
86
|
+
}
|
|
87
|
+
const backup = `${file}.bak`;
|
|
88
|
+
try {
|
|
89
|
+
fs.renameSync(file, backup);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// an unreadable file we cannot move: start fresh in memory
|
|
93
|
+
}
|
|
94
|
+
return { state: emptyState(), recoveredFrom: backup };
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Writes the state file atomically (temp file + rename) with mode 0600,
|
|
98
|
+
* creating its directory (0700) as needed.
|
|
99
|
+
*
|
|
100
|
+
* @param file - The state file path
|
|
101
|
+
* @param state - The state
|
|
102
|
+
*/
|
|
103
|
+
export function writeStateSync(file, state) {
|
|
104
|
+
const dir = path.dirname(file);
|
|
105
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
106
|
+
const tmp = path.join(dir, `.${path.basename(file)}.${process.pid}.${Date.now()}.tmp`);
|
|
107
|
+
fs.writeFileSync(tmp, JSON.stringify(state, null, 2), { mode: 0o600 });
|
|
108
|
+
fs.renameSync(tmp, file);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Drops the least recently touched tree entries beyond the cap.
|
|
112
|
+
*
|
|
113
|
+
* @param state - The state (mutated)
|
|
114
|
+
* @param max - The cap
|
|
115
|
+
*/
|
|
116
|
+
export function pruneTrees(state, max = MAX_TREE_ENTRIES) {
|
|
117
|
+
const all = [];
|
|
118
|
+
for (const [repo, r] of Object.entries(state.repos)) {
|
|
119
|
+
for (const [key, tree] of Object.entries(r.trees))
|
|
120
|
+
all.push({ repo, key, touched: tree.touched });
|
|
121
|
+
}
|
|
122
|
+
if (all.length <= max)
|
|
123
|
+
return;
|
|
124
|
+
all.sort((a, b) => a.touched - b.touched);
|
|
125
|
+
for (const drop of all.slice(0, all.length - max)) {
|
|
126
|
+
delete state.repos[drop.repo].trees[drop.key];
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Creates the debounced writer over a state file.
|
|
131
|
+
*
|
|
132
|
+
* @param file - The state file path
|
|
133
|
+
* @param initial - The loaded state
|
|
134
|
+
* @param options - `debounceMs` (default 250) and `onError` for write failures
|
|
135
|
+
* @returns The persister
|
|
136
|
+
*/
|
|
137
|
+
export function createPersister(file, initial, options = {}) {
|
|
138
|
+
const debounceMs = options.debounceMs ?? WRITE_DEBOUNCE_MS;
|
|
139
|
+
const state = initial;
|
|
140
|
+
let dirty = false;
|
|
141
|
+
let timer;
|
|
142
|
+
const write = () => {
|
|
143
|
+
if (timer !== undefined) {
|
|
144
|
+
clearTimeout(timer);
|
|
145
|
+
timer = undefined;
|
|
146
|
+
}
|
|
147
|
+
if (!dirty)
|
|
148
|
+
return;
|
|
149
|
+
dirty = false;
|
|
150
|
+
try {
|
|
151
|
+
pruneTrees(state);
|
|
152
|
+
writeStateSync(file, state);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
options.onError?.(error);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
return {
|
|
159
|
+
get state() { return state; },
|
|
160
|
+
get dirty() { return dirty; },
|
|
161
|
+
update(fn) {
|
|
162
|
+
fn(state);
|
|
163
|
+
dirty = true;
|
|
164
|
+
if (timer === undefined) {
|
|
165
|
+
timer = setTimeout(write, debounceMs);
|
|
166
|
+
timer.unref?.();
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
flush: write,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The repository's state entry, created when missing.
|
|
174
|
+
*
|
|
175
|
+
* @param state - The state file
|
|
176
|
+
* @param repoKey - The repository key
|
|
177
|
+
* @returns The entry
|
|
178
|
+
*/
|
|
179
|
+
export function repoEntry(state, repoKey) {
|
|
180
|
+
let entry = state.repos[repoKey];
|
|
181
|
+
if (entry === undefined) {
|
|
182
|
+
entry = { trees: {} };
|
|
183
|
+
state.repos[repoKey] = entry;
|
|
184
|
+
}
|
|
185
|
+
return entry;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=persist.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persist.js","sourceRoot":"","sources":["../../../src/tui/state/persist.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Pollers — one per data feed, with an interval, an `AbortController`, at
|
|
7
|
+
* most one request in flight, and exponential backoff on consecutive
|
|
8
|
+
* failures (1 → 2 → 4 → 8 → 15 s). A feed runs only while a view that needs
|
|
9
|
+
* it is mounted; the header's connection pill derives from the newest
|
|
10
|
+
* results across the running pollers ({@link connectionState}).
|
|
11
|
+
*
|
|
12
|
+
* @packageDocumentation
|
|
13
|
+
*/
|
|
14
|
+
/** The backoff ladder after consecutive failures, in milliseconds. */
|
|
15
|
+
export declare const BACKOFF_MS: readonly [1000, 2000, 4000, 8000, 15000];
|
|
16
|
+
/** Failures before the pill reads offline (the ladder's length). */
|
|
17
|
+
export declare const OFFLINE_AFTER: 5;
|
|
18
|
+
/** The timer surface a poller schedules with (injectable for tests). */
|
|
19
|
+
export interface PollClock {
|
|
20
|
+
now(): number;
|
|
21
|
+
setTimeout(fn: () => void, ms: number): unknown;
|
|
22
|
+
clearTimeout(handle: unknown): void;
|
|
23
|
+
}
|
|
24
|
+
/** The real timers. */
|
|
25
|
+
export declare const realClock: PollClock;
|
|
26
|
+
/** What a poller is built from. */
|
|
27
|
+
export interface PollerConfig<T> {
|
|
28
|
+
/** A name for diagnostics. */
|
|
29
|
+
key: string;
|
|
30
|
+
/** The steady-state interval between successful runs, in milliseconds. */
|
|
31
|
+
intervalMs: number;
|
|
32
|
+
/** The request; `signal` aborts when the poller stops or is superseded. */
|
|
33
|
+
run: (signal: AbortSignal) => Promise<T>;
|
|
34
|
+
/** Receives each successful result. */
|
|
35
|
+
onResult: (result: T) => void;
|
|
36
|
+
/** Receives each failure (after which the backoff applies). */
|
|
37
|
+
onError?: ((error: unknown, failures: number) => void) | undefined;
|
|
38
|
+
/** Timers (default: the real ones). */
|
|
39
|
+
clock?: PollClock | undefined;
|
|
40
|
+
}
|
|
41
|
+
/** A poller's observable state. */
|
|
42
|
+
export interface PollerStatus {
|
|
43
|
+
key: string;
|
|
44
|
+
running: boolean;
|
|
45
|
+
inFlight: boolean;
|
|
46
|
+
/** Consecutive failures since the last success. */
|
|
47
|
+
failures: number;
|
|
48
|
+
/** Epoch milliseconds of the last success, or null. */
|
|
49
|
+
lastOkAt: number | null;
|
|
50
|
+
/** Epoch milliseconds of the last attempt (success or failure), or null. */
|
|
51
|
+
lastAttemptAt: number | null;
|
|
52
|
+
}
|
|
53
|
+
/** A running feed. */
|
|
54
|
+
export interface Poller {
|
|
55
|
+
/** Starts polling (the first run is immediate). No-op when running. */
|
|
56
|
+
start(): void;
|
|
57
|
+
/** Stops polling and aborts the request in flight. */
|
|
58
|
+
stop(): void;
|
|
59
|
+
/** Pauses without discarding state (a later `resume` continues). */
|
|
60
|
+
pause(): void;
|
|
61
|
+
/** Resumes a paused poller with an immediate run. */
|
|
62
|
+
resume(): void;
|
|
63
|
+
/** Runs now, regardless of the schedule (a superseded request is ignored). */
|
|
64
|
+
fireNow(): void;
|
|
65
|
+
/** Changes the steady-state interval (takes effect at the next schedule). */
|
|
66
|
+
setInterval(ms: number): void;
|
|
67
|
+
/** The current status. */
|
|
68
|
+
status(): PollerStatus;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Creates a poller.
|
|
72
|
+
*
|
|
73
|
+
* @typeParam T - The result type
|
|
74
|
+
* @param config - The feed
|
|
75
|
+
* @returns The poller (not started)
|
|
76
|
+
*/
|
|
77
|
+
export declare function createPoller<T>(config: PollerConfig<T>): Poller;
|
|
78
|
+
/** The header pill's connection state. */
|
|
79
|
+
export type ConnectionState = {
|
|
80
|
+
kind: 'idle';
|
|
81
|
+
} | {
|
|
82
|
+
kind: 'connected';
|
|
83
|
+
} | {
|
|
84
|
+
kind: 'reconnecting';
|
|
85
|
+
attempt: number;
|
|
86
|
+
of: number;
|
|
87
|
+
} | {
|
|
88
|
+
kind: 'offline';
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Derives the connection pill from the running pollers: connected while the
|
|
92
|
+
* most recently attempted poller succeeded, reconnecting `n/of` after
|
|
93
|
+
* consecutive failures, offline once the backoff ladder is exhausted.
|
|
94
|
+
*
|
|
95
|
+
* @param pollers - The pollers (their statuses are read)
|
|
96
|
+
* @returns The connection state (`idle` with no running poller)
|
|
97
|
+
*/
|
|
98
|
+
export declare function connectionState(pollers: readonly Pick<Poller, 'status'>[]): ConnectionState;
|
|
99
|
+
//# sourceMappingURL=poll.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll.d.ts","sourceRoot":"","sources":["../../../src/tui/state/poll.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;GAQG;AAEH,sEAAsE;AACtE,eAAO,MAAM,UAAU,0CAAgD,CAAC;AAExE,oEAAoE;AACpE,eAAO,MAAM,aAAa,GAAoB,CAAC;AAE/C,wEAAwE;AACxE,MAAM,WAAW,SAAS;IACtB,GAAG,IAAI,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD,YAAY,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;CACvC;AAED,uBAAuB;AACvB,eAAO,MAAM,SAAS,EAAE,SAQvB,CAAC;AAEF,mCAAmC;AACnC,MAAM,WAAW,YAAY,CAAC,CAAC;IAC3B,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,UAAU,EAAE,MAAM,CAAC;IACnB,2EAA2E;IAC3E,GAAG,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;IACzC,uCAAuC;IACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,+DAA+D;IAC/D,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACnE,uCAAuC;IACvC,KAAK,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC;AAED,mCAAmC;AACnC,MAAM,WAAW,YAAY;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,mDAAmD;IACnD,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,4EAA4E;IAC5E,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,sBAAsB;AACtB,MAAM,WAAW,MAAM;IACnB,uEAAuE;IACvE,KAAK,IAAI,IAAI,CAAC;IACd,sDAAsD;IACtD,IAAI,IAAI,IAAI,CAAC;IACb,oEAAoE;IACpE,KAAK,IAAI,IAAI,CAAC;IACd,qDAAqD;IACrD,MAAM,IAAI,IAAI,CAAC;IACf,8EAA8E;IAC9E,OAAO,IAAI,IAAI,CAAC;IAChB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,0BAA0B;IAC1B,MAAM,IAAI,YAAY,CAAC;CAC1B;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,MAAM,CAoG/D;AAED,0CAA0C;AAC1C,MAAM,MAAM,eAAe,GACrB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,CAAC;AAE1B;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,SAAS,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,GAAG,eAAe,CAO3F"}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Pollers — one per data feed, with an interval, an `AbortController`, at
|
|
7
|
+
* most one request in flight, and exponential backoff on consecutive
|
|
8
|
+
* failures (1 → 2 → 4 → 8 → 15 s). A feed runs only while a view that needs
|
|
9
|
+
* it is mounted; the header's connection pill derives from the newest
|
|
10
|
+
* results across the running pollers ({@link connectionState}).
|
|
11
|
+
*
|
|
12
|
+
* @packageDocumentation
|
|
13
|
+
*/
|
|
14
|
+
/** The backoff ladder after consecutive failures, in milliseconds. */
|
|
15
|
+
export const BACKOFF_MS = [1_000, 2_000, 4_000, 8_000, 15_000];
|
|
16
|
+
/** Failures before the pill reads offline (the ladder's length). */
|
|
17
|
+
export const OFFLINE_AFTER = BACKOFF_MS.length;
|
|
18
|
+
/** The real timers. */
|
|
19
|
+
export const realClock = {
|
|
20
|
+
now: () => Date.now(),
|
|
21
|
+
setTimeout: (fn, ms) => {
|
|
22
|
+
const handle = setTimeout(fn, ms);
|
|
23
|
+
handle.unref?.();
|
|
24
|
+
return handle;
|
|
25
|
+
},
|
|
26
|
+
clearTimeout: (handle) => clearTimeout(handle),
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Creates a poller.
|
|
30
|
+
*
|
|
31
|
+
* @typeParam T - The result type
|
|
32
|
+
* @param config - The feed
|
|
33
|
+
* @returns The poller (not started)
|
|
34
|
+
*/
|
|
35
|
+
export function createPoller(config) {
|
|
36
|
+
const clock = config.clock ?? realClock;
|
|
37
|
+
let intervalMs = config.intervalMs;
|
|
38
|
+
let running = false;
|
|
39
|
+
let paused = false;
|
|
40
|
+
let inFlight = false;
|
|
41
|
+
let failures = 0;
|
|
42
|
+
let lastOkAt = null;
|
|
43
|
+
let lastAttemptAt = null;
|
|
44
|
+
let timer = undefined;
|
|
45
|
+
let controller = null;
|
|
46
|
+
let generation = 0;
|
|
47
|
+
const clearTimer = () => {
|
|
48
|
+
if (timer !== undefined) {
|
|
49
|
+
clock.clearTimeout(timer);
|
|
50
|
+
timer = undefined;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const schedule = (ms) => {
|
|
54
|
+
clearTimer();
|
|
55
|
+
if (!running || paused)
|
|
56
|
+
return;
|
|
57
|
+
timer = clock.setTimeout(() => {
|
|
58
|
+
timer = undefined;
|
|
59
|
+
void tick();
|
|
60
|
+
}, ms);
|
|
61
|
+
};
|
|
62
|
+
const tick = async () => {
|
|
63
|
+
if (!running || paused)
|
|
64
|
+
return;
|
|
65
|
+
if (inFlight)
|
|
66
|
+
return;
|
|
67
|
+
inFlight = true;
|
|
68
|
+
const myGeneration = ++generation;
|
|
69
|
+
controller = new AbortController();
|
|
70
|
+
const signal = controller.signal;
|
|
71
|
+
lastAttemptAt = clock.now();
|
|
72
|
+
try {
|
|
73
|
+
const result = await config.run(signal);
|
|
74
|
+
if (myGeneration !== generation || signal.aborted)
|
|
75
|
+
return;
|
|
76
|
+
inFlight = false;
|
|
77
|
+
failures = 0;
|
|
78
|
+
lastOkAt = clock.now();
|
|
79
|
+
config.onResult(result);
|
|
80
|
+
schedule(intervalMs);
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (myGeneration !== generation || signal.aborted)
|
|
84
|
+
return;
|
|
85
|
+
inFlight = false;
|
|
86
|
+
failures += 1;
|
|
87
|
+
config.onError?.(error, failures);
|
|
88
|
+
schedule(BACKOFF_MS[Math.min(failures, BACKOFF_MS.length) - 1]);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const abortInFlight = () => {
|
|
92
|
+
if (controller !== null) {
|
|
93
|
+
controller.abort();
|
|
94
|
+
controller = null;
|
|
95
|
+
}
|
|
96
|
+
inFlight = false;
|
|
97
|
+
generation += 1;
|
|
98
|
+
};
|
|
99
|
+
return {
|
|
100
|
+
start() {
|
|
101
|
+
if (running)
|
|
102
|
+
return;
|
|
103
|
+
running = true;
|
|
104
|
+
paused = false;
|
|
105
|
+
void tick();
|
|
106
|
+
},
|
|
107
|
+
stop() {
|
|
108
|
+
running = false;
|
|
109
|
+
paused = false;
|
|
110
|
+
clearTimer();
|
|
111
|
+
abortInFlight();
|
|
112
|
+
},
|
|
113
|
+
pause() {
|
|
114
|
+
if (!running)
|
|
115
|
+
return;
|
|
116
|
+
paused = true;
|
|
117
|
+
clearTimer();
|
|
118
|
+
abortInFlight();
|
|
119
|
+
},
|
|
120
|
+
resume() {
|
|
121
|
+
if (!running || !paused)
|
|
122
|
+
return;
|
|
123
|
+
paused = false;
|
|
124
|
+
void tick();
|
|
125
|
+
},
|
|
126
|
+
fireNow() {
|
|
127
|
+
if (!running || paused)
|
|
128
|
+
return;
|
|
129
|
+
clearTimer();
|
|
130
|
+
abortInFlight();
|
|
131
|
+
void tick();
|
|
132
|
+
},
|
|
133
|
+
setInterval(ms) {
|
|
134
|
+
intervalMs = ms;
|
|
135
|
+
},
|
|
136
|
+
status() {
|
|
137
|
+
return { key: config.key, running: running && !paused, inFlight, failures, lastOkAt, lastAttemptAt };
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Derives the connection pill from the running pollers: connected while the
|
|
143
|
+
* most recently attempted poller succeeded, reconnecting `n/of` after
|
|
144
|
+
* consecutive failures, offline once the backoff ladder is exhausted.
|
|
145
|
+
*
|
|
146
|
+
* @param pollers - The pollers (their statuses are read)
|
|
147
|
+
* @returns The connection state (`idle` with no running poller)
|
|
148
|
+
*/
|
|
149
|
+
export function connectionState(pollers) {
|
|
150
|
+
const statuses = pollers.map(p => p.status()).filter(s => s.running && s.lastAttemptAt !== null);
|
|
151
|
+
if (statuses.length === 0)
|
|
152
|
+
return { kind: 'idle' };
|
|
153
|
+
const worst = Math.max(...statuses.map(s => s.failures));
|
|
154
|
+
if (worst === 0)
|
|
155
|
+
return { kind: 'connected' };
|
|
156
|
+
if (worst >= OFFLINE_AFTER)
|
|
157
|
+
return { kind: 'offline' };
|
|
158
|
+
return { kind: 'reconnecting', attempt: worst, of: OFFLINE_AFTER - 1 };
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=poll.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"poll.js","sourceRoot":"","sources":["../../../src/tui/state/poll.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2025 Elara AI Pty Ltd
|
|
3
|
+
* Dual-licensed under AGPL-3.0 and commercial license. See LICENSE for details.
|
|
4
|
+
*/
|
|
5
|
+
import { type Action, type TuiState } from './actions.js';
|
|
6
|
+
/**
|
|
7
|
+
* The reducer.
|
|
8
|
+
*
|
|
9
|
+
* @param state - The current state
|
|
10
|
+
* @param action - The action
|
|
11
|
+
* @returns The next state (the same object when nothing changed)
|
|
12
|
+
*/
|
|
13
|
+
export declare function reduce(state: TuiState, action: Action): TuiState;
|
|
14
|
+
/** Whether the state has pending input edits (the `◆ N DIRTY` pill). */
|
|
15
|
+
export declare function dirtyCount(state: TuiState): number;
|
|
16
|
+
//# sourceMappingURL=reducer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../../src/tui/state/reducer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,OAAO,EACH,KAAK,MAAM,EAIX,KAAK,QAAQ,EAIhB,MAAM,cAAc,CAAC;AAkGtB;;;;;;GAMG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,QAAQ,CAsNhE;AAED,wEAAwE;AACxE,wBAAgB,UAAU,CAAC,KAAK,EAAE,QAAQ,GAAG,MAAM,CAElD"}
|