opencode-context-indicator 1.7.1 → 1.8.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/CHANGELOG.md +57 -0
- package/README.md +97 -94
- package/index.js +5 -4
- package/lib/contributors.js +5 -4
- package/lib/limits.js +19 -7
- package/lib/state.js +6 -5
- package/lib/tui-data.d.ts +0 -1
- package/lib/tui-data.js +5 -21
- package/lib/tui-h.ts +73 -0
- package/lib/{tui-panel.tsx → tui-panel.ts} +779 -713
- package/lib/tui-sidebar.ts +153 -0
- package/package.json +10 -12
- package/tui.ts +317 -0
- package/lib/tui-sidebar.tsx +0 -76
- package/tui.tsx +0 -206
package/lib/tui-data.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// lib/tui-data.js
|
|
2
2
|
//
|
|
3
|
-
// Data layer for the TUI entry (tui.
|
|
3
|
+
// Data layer for the TUI entry (tui.ts): the state.json bridge (readSnapshot /
|
|
4
4
|
// isEmptyEntry / collectFamily), the shared formatting helpers (fmt / num / fit
|
|
5
|
-
// / updatedAt) and the
|
|
6
|
-
//
|
|
7
|
-
//
|
|
5
|
+
// / updatedAt) and the family walk. Plain JS with JSDoc — same shape as
|
|
6
|
+
// lib/contributors.js — so tui.ts stays a thin setup shell and the node tooling
|
|
7
|
+
// (resolve gate, unit tests) can import it without a transform.
|
|
8
8
|
//
|
|
9
9
|
// These helpers must stay free of solid-js / @opentui imports: the TUI host
|
|
10
|
-
// bridges those modules only for the
|
|
10
|
+
// bridges those modules only for the plugin bundle, and keeping this file pure
|
|
11
11
|
// means it also loads anywhere node does.
|
|
12
12
|
//
|
|
13
13
|
// state.json shape (written by writeStateFile() in index.js, untrusted input):
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
import { readFileSync } from "node:fs";
|
|
21
21
|
import { tmpdir } from "node:os";
|
|
22
22
|
import { join } from "node:path";
|
|
23
|
-
import { fileURLToPath } from "node:url";
|
|
24
23
|
import { isSafeSessionKey, sumCategories } from "./estimate.js";
|
|
25
24
|
import { fmt, num } from "./format.js";
|
|
26
25
|
|
|
@@ -38,21 +37,6 @@ export const STATE_FILE =
|
|
|
38
37
|
|
|
39
38
|
export const POLL_MS = 1000;
|
|
40
39
|
|
|
41
|
-
// True when this package was loaded from an npm install, i.e. its own file
|
|
42
|
-
// path contains a `node_modules` segment (OpenCode's TUI loader skips the host
|
|
43
|
-
// Solid transform for such paths → slots mount once but never live-update; see
|
|
44
|
-
// the Graceful mode note in tui.tsx). Normalised to forward slashes for
|
|
45
|
-
// Windows paths. ANY file of the package yields the same answer, so checking
|
|
46
|
-
// from lib/ is equivalent to checking from the tui.tsx entry.
|
|
47
|
-
export function isNodeModulesInstall() {
|
|
48
|
-
try {
|
|
49
|
-
const selfPath = fileURLToPath(import.meta.url).replace(/\\/g, "/").toLowerCase()
|
|
50
|
-
return selfPath.includes("/node_modules/")
|
|
51
|
-
} catch {
|
|
52
|
-
return false
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
40
|
// Whole state.json snapshot ({ sessionID: entry }) or {} on any error. The
|
|
57
41
|
// sidebar resolves one entry from it and the breakdown panel walks the
|
|
58
42
|
// parentID family over it. Never throws — a missing / empty / corrupt
|
package/lib/tui-h.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// lib/tui-h.ts
|
|
2
|
+
//
|
|
3
|
+
// The two tree builders every TUI surface in this package uses instead of JSX.
|
|
4
|
+
//
|
|
5
|
+
// WHY NO JSX (do not "simplify" this back):
|
|
6
|
+
// OpenCode installs npm plugins inside a `node_modules` tree
|
|
7
|
+
// (~/.cache/opencode/npm/<name>@<version>/<ts>/node_modules/<name>). For such
|
|
8
|
+
// paths the host deliberately skips its Solid/Babel JSX transform (sourceFilter
|
|
9
|
+
// in @opentui/solid/scripts/solid-plugin.js excludes node_modules, upstream
|
|
10
|
+
// anomalyco/opencode#33884). A JSX-compiled file in that position also needs
|
|
11
|
+
// `@opentui/solid` to be installed next to it just to resolve its emitted
|
|
12
|
+
// jsx-runtime import. Files WITHOUT JSX syntax are unaffected: their literal
|
|
13
|
+
// `@opentui/solid/jsx-runtime` import IS rewritten by the host to the
|
|
14
|
+
// in-process OpenTUI module (`nodeModulesRuntimeSpecifiers: true` in
|
|
15
|
+
// DEFAULT_RUNTIME_PLUGIN_REWRITE_OPTIONS of @opentui/core), so the tree stays
|
|
16
|
+
// reactive and the package needs no runtime dependency at all.
|
|
17
|
+
//
|
|
18
|
+
// Therefore: no JSX syntax anywhere in this package's TUI files, and no
|
|
19
|
+
// `@jsxImportSource` pragma. Build the tree with jsx() and mark every DYNAMIC
|
|
20
|
+
// prop as a getter — that is exactly what the Solid compiler emits for
|
|
21
|
+
// `prop={expr}` in JSX, so the runtime semantics are identical:
|
|
22
|
+
//
|
|
23
|
+
// <text fg={base()}>{line}</text>
|
|
24
|
+
// -> h("text", { get fg() { return base() }, get children() { return line } })
|
|
25
|
+
//
|
|
26
|
+
// A plain (non-getter) value is read ONCE, like a literal attribute in JSX.
|
|
27
|
+
// Children follow the same rule: an array of elements is fine (it is diffed by
|
|
28
|
+
// the runtime), a function child is a reactive accessor.
|
|
29
|
+
//
|
|
30
|
+
// RELATIVE IMPORTS OF .ts FILES MUST CARRY THE EXTENSION (`./tui-h.ts`, not
|
|
31
|
+
// `./tui-h`): the host decides which files get the runtime-specifier rewrite by
|
|
32
|
+
// walking the import graph with `import.meta.resolve(specifier, importer)`,
|
|
33
|
+
// which does not probe extensions. An extensionless import is simply not
|
|
34
|
+
// followed, so that file keeps the literal `@opentui/solid/jsx-runtime` import
|
|
35
|
+
// and the npm install dies with `Cannot find package '@opentui/solid'`.
|
|
36
|
+
// test/prepublish.mjs gate (b) enforces this.
|
|
37
|
+
//
|
|
38
|
+
// This module is the only place that imports the jsx runtime, so the allowlist
|
|
39
|
+
// in test/prepublish.mjs stays short.
|
|
40
|
+
//
|
|
41
|
+
// NEVER pass a `key` prop to h()/c(). The jsx runtime's normalizeProps() sees
|
|
42
|
+
// `key`, strips it with `{ ...rest }`, and the spread turns every getter into a
|
|
43
|
+
// plain value read ONCE — the whole subtree freezes with no error. (No list in
|
|
44
|
+
// this package is keyed; if you ever need one, do not add `key` here.)
|
|
45
|
+
|
|
46
|
+
import { jsx } from "@opentui/solid/jsx-runtime"
|
|
47
|
+
import type { JSX } from "@opentui/solid/jsx-runtime"
|
|
48
|
+
|
|
49
|
+
/** An intrinsic OpenTUI element: `h("text", { fg, children })`. */
|
|
50
|
+
export function h<K extends string>(
|
|
51
|
+
tag: K,
|
|
52
|
+
props: K extends keyof JSX.IntrinsicElements ? JSX.IntrinsicElements[K] : never,
|
|
53
|
+
): JSX.Element {
|
|
54
|
+
return jsx(tag, props as unknown as Record<string, unknown>)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* A component: `c(Show, { get when() {...}, get fallback() {...} })`.
|
|
59
|
+
*
|
|
60
|
+
* The component's own prop type is intentionally not enforced here: host
|
|
61
|
+
* components (Show, and any OpenTUI component) are generic and their unions do
|
|
62
|
+
* not survive inference through a wrapper, while the shapes used in this
|
|
63
|
+
* package are small and covered by the e2e liveness check.
|
|
64
|
+
*/
|
|
65
|
+
export function c<C extends (props: any) => unknown, P extends object>(
|
|
66
|
+
component: C,
|
|
67
|
+
props: P,
|
|
68
|
+
): JSX.Element {
|
|
69
|
+
return jsx(
|
|
70
|
+
component as unknown as (props: Record<string, unknown>) => unknown,
|
|
71
|
+
props as unknown as Record<string, unknown>,
|
|
72
|
+
)
|
|
73
|
+
}
|