@opencode-cockpit/shell 0.1.5 → 0.2.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 +100 -10
- package/dist/agent/plugin.js +180 -0
- package/dist/agent/tools/index.js +23 -0
- package/dist/agent/tools/list.js +68 -0
- package/dist/agent/tools/read.js +59 -0
- package/dist/agent/tools/restart.js +44 -0
- package/dist/agent/tools/send.js +71 -0
- package/dist/agent/tools/shared.js +94 -0
- package/dist/agent/tools/start.js +140 -0
- package/dist/agent/tools/stop.js +42 -0
- package/dist/agent/tools/wait.js +79 -0
- package/dist/agent/tools/watch-args.js +12 -0
- package/dist/agent/tools/watch.js +74 -0
- package/dist/core/config.js +97 -0
- package/dist/{tools → core}/find.js +3 -0
- package/dist/core/kind.js +31 -0
- package/dist/server.js +2 -152
- package/dist/tui/{badge.js → components/badge.js} +1 -1
- package/dist/tui/{console.js → components/console.js} +270 -139
- package/dist/tui/{dock.js → components/dock.js} +75 -19
- package/dist/tui/{sidebar.js → components/sidebar.js} +16 -1
- package/dist/tui/dialogs.js +163 -0
- package/dist/tui/index.js +35 -94
- package/dist/tui/lib/details.js +23 -0
- package/dist/tui/lib/search.js +39 -0
- package/dist/tui/lib/update.js +58 -0
- package/dist/tui/{view.js → lib/view.js} +38 -1
- package/dist/tui/{store.js → state/store.js} +4 -2
- package/package.json +4 -5
- package/types/agent/plugin.d.ts +12 -0
- package/types/agent/tools/index.d.ts +5 -0
- package/types/agent/tools/list.d.ts +3 -0
- package/types/agent/tools/read.d.ts +3 -0
- package/types/agent/tools/restart.d.ts +3 -0
- package/types/agent/tools/send.d.ts +3 -0
- package/types/agent/tools/shared.d.ts +40 -0
- package/types/agent/tools/start.d.ts +3 -0
- package/types/agent/tools/stop.d.ts +3 -0
- package/types/agent/tools/wait.d.ts +3 -0
- package/types/agent/tools/watch-args.d.ts +10 -0
- package/types/agent/tools/watch.d.ts +3 -0
- package/types/core/config.d.ts +59 -0
- package/types/{tools → core}/find.d.ts +5 -0
- package/types/core/kind.d.ts +9 -0
- package/types/server.d.ts +2 -12
- package/types/tui/{console.d.ts → components/console.d.ts} +7 -1
- package/types/tui/{dock.d.ts → components/dock.d.ts} +3 -1
- package/types/tui/{sidebar.d.ts → components/sidebar.d.ts} +1 -1
- package/types/tui/dialogs.d.ts +10 -0
- package/types/tui/index.d.ts +3 -9
- package/types/tui/lib/details.d.ts +3 -0
- package/types/tui/lib/search.d.ts +7 -0
- package/types/tui/lib/update.d.ts +25 -0
- package/types/tui/{view.d.ts → lib/view.d.ts} +14 -1
- package/types/tui/{store.d.ts → state/store.d.ts} +9 -0
- package/dist/tools/index.js +0 -433
- package/types/tools/index.d.ts +0 -17
- /package/dist/{tools → agent/tools}/keys.js +0 -0
- /package/dist/{tools → core}/format.js +0 -0
- /package/dist/tui/{keys.js → lib/keys.js} +0 -0
- /package/types/{tools → agent/tools}/keys.d.ts +0 -0
- /package/types/{tools → core}/format.d.ts +0 -0
- /package/types/tui/{badge.d.ts → components/badge.d.ts} +0 -0
- /package/types/tui/{keys.d.ts → lib/keys.d.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { duration } from "
|
|
1
|
+
import { duration } from "../../core/format.js";
|
|
2
2
|
|
|
3
3
|
/** What a human cares about, derived from status + exit code so every surface agrees. */
|
|
4
4
|
|
|
@@ -88,6 +88,24 @@ export function statusDetail(s, now) {
|
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
/** Short health label for a watched shell, e.g. "tsc ✗" — empty when nothing is watching it. */
|
|
92
|
+
export function watchLabel(s) {
|
|
93
|
+
const watch = s.watch;
|
|
94
|
+
if (!watch || watch.status === "pending") return "";
|
|
95
|
+
const mark = watch.status === "ok" ? "✓" : watch.status === "fail" ? "✗" : "?";
|
|
96
|
+
return `${watch.preset ?? "watch"} ${mark}`;
|
|
97
|
+
}
|
|
98
|
+
export function watchColor(theme, s) {
|
|
99
|
+
switch (s.watch?.status) {
|
|
100
|
+
case "ok":
|
|
101
|
+
return theme.success;
|
|
102
|
+
case "fail":
|
|
103
|
+
return theme.error;
|
|
104
|
+
default:
|
|
105
|
+
return theme.textMuted;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
91
109
|
/** Compact detail for narrow lists. */
|
|
92
110
|
export function shortDetail(s, now) {
|
|
93
111
|
switch (kindOf(s)) {
|
|
@@ -143,6 +161,25 @@ export function wrapText(text, width, maxLines) {
|
|
|
143
161
|
return lines;
|
|
144
162
|
}
|
|
145
163
|
|
|
164
|
+
/** Last `rows` styled rows, each cut to `cols`, so colour survives the same trimming as text. */
|
|
165
|
+
export function tailRuns(styled, rows, cols) {
|
|
166
|
+
if (!styled) return [];
|
|
167
|
+
return styled.slice(Math.max(0, styled.length - rows)).map(row => {
|
|
168
|
+
const out = [];
|
|
169
|
+
let width = 0;
|
|
170
|
+
for (const run of row) {
|
|
171
|
+
if (width >= cols) break;
|
|
172
|
+
const text = run.text.slice(0, cols - width);
|
|
173
|
+
width += text.length;
|
|
174
|
+
out.push({
|
|
175
|
+
...run,
|
|
176
|
+
text
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
return out;
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
|
|
146
183
|
/** Last `rows` lines of screen text, each cut to `cols`. */
|
|
147
184
|
export function tailLines(text, rows, cols) {
|
|
148
185
|
if (!text) return "";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { createEffect, createMemo, createRoot, createSignal, on, onCleanup } from "solid-js";
|
|
3
3
|
import { createStore, reconcile } from "solid-js/store";
|
|
4
|
-
import { order, partition } from "
|
|
4
|
+
import { order, partition } from "../lib/view.js";
|
|
5
5
|
export function createShellStore(api, client, options = {}) {
|
|
6
6
|
return createRoot(dispose => {
|
|
7
7
|
const [state, setState] = createStore({
|
|
@@ -76,8 +76,10 @@ export function createShellStore(api, client, options = {}) {
|
|
|
76
76
|
frame,
|
|
77
77
|
selected: pick,
|
|
78
78
|
select: id => setSelectedId(id),
|
|
79
|
+
// Cycles every shell in the project: folding only exists to keep the sidebar short, and a
|
|
80
|
+
// shell you cannot reach from the console would be a trap.
|
|
79
81
|
step(delta) {
|
|
80
|
-
const list =
|
|
82
|
+
const list = order(state.list);
|
|
81
83
|
if (list.length === 0) return;
|
|
82
84
|
const index = Math.max(0, list.findIndex(s => s.id === pick()?.id));
|
|
83
85
|
const next = list[(index + delta + list.length) % list.length];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opencode-cockpit/shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Background shells for OpenCode: the agent starts, waits on and drives PTYs; you watch them in a docked TUI panel",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -51,13 +51,12 @@
|
|
|
51
51
|
"access": "public"
|
|
52
52
|
},
|
|
53
53
|
"dependencies": {
|
|
54
|
-
"@opencode-cockpit/client": "0.
|
|
55
|
-
"@opencode-cockpit/daemon": "0.
|
|
56
|
-
"@opencode-cockpit/protocol": "0.
|
|
54
|
+
"@opencode-cockpit/client": "0.2.0",
|
|
55
|
+
"@opencode-cockpit/daemon": "0.2.0",
|
|
56
|
+
"@opencode-cockpit/protocol": "0.2.0",
|
|
57
57
|
"@opencode-ai/plugin": "1.18.31"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
-
"zod": "4.6.5",
|
|
61
60
|
"@opentui/core": "0.4.5",
|
|
62
61
|
"@opentui/keymap": "0.4.5",
|
|
63
62
|
"@opentui/solid": "0.4.5",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Plugin, PluginModule } from "@opencode-ai/plugin";
|
|
2
|
+
export declare const SHELL_PACKAGE = "@opencode-cockpit/shell";
|
|
3
|
+
export interface ShellServerOptions {
|
|
4
|
+
/** Package that loaded Shell, reported when a duplicate copy is skipped. */
|
|
5
|
+
source?: string;
|
|
6
|
+
}
|
|
7
|
+
/** Shell's server half as a factory, so bundles such as `opencode-cockpit` can include it. */
|
|
8
|
+
export declare function createShellServer({ source }?: ShellServerOptions): Plugin;
|
|
9
|
+
declare const plugin: PluginModule & {
|
|
10
|
+
id: string;
|
|
11
|
+
};
|
|
12
|
+
export default plugin;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ToolDefinition } from "@opencode-ai/plugin";
|
|
2
|
+
import { type ToolDeps } from "./shared.ts";
|
|
3
|
+
export type { ToolDeps } from "./shared.ts";
|
|
4
|
+
/** The shell tools an agent sees. One file per tool; `shared.ts` holds what they have in common. */
|
|
5
|
+
export declare function createTools(deps: ToolDeps): Record<string, ToolDefinition>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ToolContext } from "@opencode-ai/plugin";
|
|
2
|
+
import type { CockpitClient } from "@opencode-cockpit/client";
|
|
3
|
+
import type { ShellInfo } from "@opencode-cockpit/protocol/shell";
|
|
4
|
+
import type { CockpitConfig } from "../../core/config.ts";
|
|
5
|
+
export interface ToolDeps {
|
|
6
|
+
client: CockpitClient;
|
|
7
|
+
/** Identifies this OpenCode instance so only it notifies the owning session. */
|
|
8
|
+
instance: string;
|
|
9
|
+
/** Shells whose exit should not message the agent (it stopped them itself, or opted out). */
|
|
10
|
+
quiet: Set<string>;
|
|
11
|
+
shellCommand(command: string): {
|
|
12
|
+
command: string;
|
|
13
|
+
args: string[];
|
|
14
|
+
};
|
|
15
|
+
env(): Record<string, string>;
|
|
16
|
+
/** Settings that shape defaults, kinds and watch presets. */
|
|
17
|
+
config?: CockpitConfig;
|
|
18
|
+
/** Human title of an OpenCode session, for telling agents which session started a shell. */
|
|
19
|
+
sessionTitle?(sessionID: string): Promise<string | undefined>;
|
|
20
|
+
}
|
|
21
|
+
/** What every tool shares: the client, name resolution, permission prompts and abort handling. */
|
|
22
|
+
export interface ToolKit {
|
|
23
|
+
deps: ToolDeps;
|
|
24
|
+
/** Settings from ~/.config/opencode-cockpit/config.json, .cockpit.json and plugin options. */
|
|
25
|
+
config: CockpitConfig;
|
|
26
|
+
client: CockpitClient;
|
|
27
|
+
peek(info: ShellInfo, tail?: number): Promise<string>;
|
|
28
|
+
sessionLabel(shell: ShellInfo, ctx: ToolContext): Promise<string>;
|
|
29
|
+
resolve(args: {
|
|
30
|
+
id?: string | null;
|
|
31
|
+
name?: string | null;
|
|
32
|
+
}, ctx: ToolContext): Promise<{
|
|
33
|
+
id: string;
|
|
34
|
+
note: string;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
export declare function createToolKit(deps: ToolDeps): ToolKit;
|
|
38
|
+
export declare function askPermission(ctx: ToolContext, command: string): Promise<void>;
|
|
39
|
+
/** Resolves undefined when the tool call is aborted; the daemon keeps running the shell. */
|
|
40
|
+
export declare function abortable<T>(ctx: ToolContext, promise: Promise<T>): Promise<T | undefined>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { WatchRule } from "@opencode-cockpit/protocol/shell";
|
|
2
|
+
import type { CockpitConfig } from "../../core/config.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Turns a preset name into what `shell.watch` needs. A preset defined in config is sent as an
|
|
5
|
+
* explicit rule, so users can add tools or correct a built-in without touching the daemon.
|
|
6
|
+
*/
|
|
7
|
+
export declare function watchArgs(preset: string, config: CockpitConfig): {
|
|
8
|
+
preset?: string;
|
|
9
|
+
rule?: WatchRule;
|
|
10
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { WatchRule } from "@opencode-cockpit/protocol/shell";
|
|
2
|
+
/**
|
|
3
|
+
* Settings, read from one file so they are written once instead of twice (OpenCode keeps agent and
|
|
4
|
+
* TUI plugins in separate configs). Precedence, lowest first:
|
|
5
|
+
*
|
|
6
|
+
* ~/.config/opencode-cockpit/config.json → <project>/.cockpit.json → plugin-entry options
|
|
7
|
+
*
|
|
8
|
+
* Everything is optional, and an unreadable or invalid file is ignored rather than fatal: a typo in
|
|
9
|
+
* a config should never stop shells from working.
|
|
10
|
+
*/
|
|
11
|
+
export interface CockpitConfig {
|
|
12
|
+
/** Health watching (see shell_watch). */
|
|
13
|
+
watch?: {
|
|
14
|
+
/** Attach a matching preset to every new shell without being asked. Off by default. */
|
|
15
|
+
auto?: boolean;
|
|
16
|
+
/** Extra rules, or replacements for built-ins, keyed by preset name. */
|
|
17
|
+
presets?: Record<string, WatchRule>;
|
|
18
|
+
};
|
|
19
|
+
/** Extra shell kinds, or overrides, as name → regular expression matched against the command. */
|
|
20
|
+
kinds?: Record<string, string>;
|
|
21
|
+
/** Applied to every shell the agent starts, unless the call says otherwise. */
|
|
22
|
+
defaults?: {
|
|
23
|
+
watch?: boolean | string;
|
|
24
|
+
logFile?: boolean;
|
|
25
|
+
idleTimeoutSeconds?: number;
|
|
26
|
+
timeoutSeconds?: number;
|
|
27
|
+
notifyOnExit?: boolean;
|
|
28
|
+
};
|
|
29
|
+
/** What is allowed to interrupt the agent. */
|
|
30
|
+
notify?: {
|
|
31
|
+
exit?: boolean;
|
|
32
|
+
watch?: boolean;
|
|
33
|
+
/** Output lines included in an exit message. */
|
|
34
|
+
tailLines?: number;
|
|
35
|
+
};
|
|
36
|
+
/** The system-prompt guidance that teaches the agent to use shells (~120 tokens per request). */
|
|
37
|
+
guidance?: boolean;
|
|
38
|
+
/** Running shells listed in the system prompt each turn; 0 disables (~20 tokens each). */
|
|
39
|
+
listRunningShells?: number;
|
|
40
|
+
/** Interface options; also settable on the tui.json plugin entry. */
|
|
41
|
+
ui?: {
|
|
42
|
+
dockHeight?: number;
|
|
43
|
+
dockOpen?: boolean;
|
|
44
|
+
sidebarRows?: number;
|
|
45
|
+
historyMinutes?: number;
|
|
46
|
+
colors?: boolean;
|
|
47
|
+
defaultView?: "screen" | "log";
|
|
48
|
+
keybinds?: Record<string, string>;
|
|
49
|
+
updateCheck?: boolean;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export declare const CONFIG_FILE = "config.json";
|
|
53
|
+
export declare const PROJECT_FILE = ".cockpit.json";
|
|
54
|
+
export declare function globalConfigPath(env?: Record<string, string | undefined>): string;
|
|
55
|
+
/** Reads and merges every source. `options` is the plugin entry's own options object. */
|
|
56
|
+
export declare function loadConfig(directory: string, options?: unknown, env?: Record<string, string | undefined>): CockpitConfig;
|
|
57
|
+
export declare function readConfigFile(path: string): CockpitConfig;
|
|
58
|
+
/** Section-wise merge: later sources win key by key, and never lose a whole section. */
|
|
59
|
+
export declare function mergeConfig(base: CockpitConfig, over: CockpitConfig): CockpitConfig;
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import type { ShellInfo } from "@opencode-cockpit/protocol/shell";
|
|
2
|
+
import { type ShellKind } from "./kind.ts";
|
|
2
3
|
/** The command as written, without the `$SHELL -c` wrapper. */
|
|
3
4
|
export declare function commandOf(s: ShellInfo): string;
|
|
4
5
|
export type StatusFilter = "running" | "failed" | "finished" | "any";
|
|
5
6
|
export type SessionFilter = "this" | "others" | "any";
|
|
6
7
|
export interface ShellFilter {
|
|
8
|
+
/** What the shell is, derived from its command (server, tests, build, watcher, task). */
|
|
9
|
+
kind?: ShellKind | "any";
|
|
7
10
|
/** Case-insensitive text found in the name or the command. */
|
|
8
11
|
query?: string;
|
|
9
12
|
status?: StatusFilter;
|
|
10
13
|
session?: SessionFilter;
|
|
11
14
|
/** The asking agent's session, for `session` filtering. */
|
|
12
15
|
currentSession?: string;
|
|
16
|
+
/** Extra kind patterns from config, so a kind it defines is also filterable. */
|
|
17
|
+
kinds?: Record<string, string>;
|
|
13
18
|
}
|
|
14
19
|
export declare function isFailed(s: ShellInfo): boolean;
|
|
15
20
|
export declare function filterShells(list: readonly ShellInfo[], filter: ShellFilter): ShellInfo[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ShellInfo } from "@opencode-cockpit/protocol/shell";
|
|
2
|
+
/** What a shell is, derived from its command — never a label anyone has to maintain by hand. */
|
|
3
|
+
export type ShellKind = "server" | "tests" | "watcher" | "build" | "task" | (string & {});
|
|
4
|
+
/**
|
|
5
|
+
* Order matters: a test runner in watch mode is still about tests, and `vite build` is a build even
|
|
6
|
+
* though `vite` usually serves.
|
|
7
|
+
*/
|
|
8
|
+
export declare function classify(command: string, custom?: Record<string, string>): ShellKind;
|
|
9
|
+
export declare function kindOfShell(s: ShellInfo, custom?: Record<string, string>): ShellKind;
|
package/types/server.d.ts
CHANGED
|
@@ -1,12 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export
|
|
3
|
-
export interface ShellServerOptions {
|
|
4
|
-
/** Package that loaded Shell, reported when a duplicate copy is skipped. */
|
|
5
|
-
source?: string;
|
|
6
|
-
}
|
|
7
|
-
/** Shell's server half as a factory, so bundles such as `opencode-cockpit` can include it. */
|
|
8
|
-
export declare function createShellServer({ source }?: ShellServerOptions): Plugin;
|
|
9
|
-
declare const plugin: PluginModule & {
|
|
10
|
-
id: string;
|
|
11
|
-
};
|
|
12
|
-
export default plugin;
|
|
1
|
+
/** Published entry point: `@opencode-cockpit/shell/server`. */
|
|
2
|
+
export { createShellServer, default, SHELL_PACKAGE, type ShellServerOptions } from "./agent/plugin.ts";
|
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
/** @jsxImportSource @opentui/solid */
|
|
2
2
|
import type { TuiPluginApi } from "@opencode-ai/plugin/tui";
|
|
3
|
-
import { type ShellStore } from "
|
|
3
|
+
import { type ShellStore } from "../state/store.ts";
|
|
4
4
|
export interface ConsoleProps {
|
|
5
5
|
api: TuiPluginApi;
|
|
6
6
|
store: ShellStore;
|
|
7
7
|
/** Start in typing mode. */
|
|
8
8
|
typing?: boolean;
|
|
9
|
+
/** Paint the colours programs print (config: ui.colors). */
|
|
10
|
+
colors?: boolean;
|
|
11
|
+
/** Which view a freshly opened console shows (config: ui.defaultView). */
|
|
12
|
+
defaultView?: "screen" | "log";
|
|
9
13
|
onClose: () => void;
|
|
10
14
|
onNewShell: () => void;
|
|
11
15
|
}
|
|
16
|
+
/** Splits a line into plain and matching parts so a filtered log can highlight what matched. */
|
|
12
17
|
/**
|
|
13
18
|
* Keyboard-first shell console in an overlay. Normal mode: single-key actions. Typing mode:
|
|
14
19
|
* every key goes to the program (ctrl+c included); ctrl+] returns to normal mode.
|
|
15
20
|
*/
|
|
16
21
|
export declare function Console(props: ConsoleProps): import("solid-js").JSX.Element;
|
|
22
|
+
/** Everything about a shell, with the full command wrapped rather than cut. */
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/** @jsxImportSource @opentui/solid */
|
|
2
2
|
import type { TuiPluginApi } from "@opencode-ai/plugin/tui";
|
|
3
|
-
import type { ShellStore } from "
|
|
3
|
+
import type { ShellStore } from "../state/store.ts";
|
|
4
4
|
export interface DockProps {
|
|
5
5
|
api: TuiPluginApi;
|
|
6
6
|
store: ShellStore;
|
|
7
7
|
height: number;
|
|
8
|
+
/** Paint the colours programs print (config: ui.colors). */
|
|
9
|
+
colors?: boolean;
|
|
8
10
|
hint: () => string;
|
|
9
11
|
onOpenConsole: (id: string) => void;
|
|
10
12
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @jsxImportSource @opentui/solid */
|
|
2
2
|
import type { TuiPluginApi } from "@opencode-ai/plugin/tui";
|
|
3
|
-
import type { ShellStore } from "
|
|
3
|
+
import type { ShellStore } from "../state/store.ts";
|
|
4
4
|
export interface SidebarProps {
|
|
5
5
|
api: TuiPluginApi;
|
|
6
6
|
store: ShellStore;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** @jsxImportSource @opentui/solid */
|
|
2
|
+
import type { TuiPluginApi, TuiPluginMeta } from "@opencode-ai/plugin/tui";
|
|
3
|
+
import type { ShellStore } from "./state/store.ts";
|
|
4
|
+
/** One quiet registry check a day; a newer release is announced once per version. */
|
|
5
|
+
export declare function announceUpdate(api: TuiPluginApi, meta: TuiPluginMeta, current: string): Promise<void>;
|
|
6
|
+
/** Clears this plugin's cache entry so the next OpenCode start installs the newer release. */
|
|
7
|
+
export declare function offerUpdate(api: TuiPluginApi, meta: TuiPluginMeta, current: string): void;
|
|
8
|
+
export declare function newShell(api: TuiPluginApi, store: ShellStore, open: (id?: string) => void): void;
|
|
9
|
+
export declare function restartDaemon(api: TuiPluginApi, store: ShellStore): void;
|
|
10
|
+
export declare function pickShell(api: TuiPluginApi, store: ShellStore, open: (id?: string) => void): void;
|
package/types/tui/index.d.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
/** @jsxImportSource @opentui/solid */
|
|
2
2
|
import { type TuiPlugin, type TuiPluginModule } from "@opencode-ai/plugin/tui";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
sidebarRows?: number;
|
|
7
|
-
/** Failures stay visible this long after they end (default 30). */
|
|
8
|
-
historyMinutes?: number;
|
|
9
|
-
dockOpen?: boolean;
|
|
10
|
-
keybinds?: Record<string, string>;
|
|
11
|
-
}
|
|
3
|
+
import { type CockpitConfig } from "../core/config.ts";
|
|
4
|
+
/** Interface settings; the `ui` section of the config file (see core/config.ts). */
|
|
5
|
+
export type ShellTuiOptions = NonNullable<CockpitConfig["ui"]>;
|
|
12
6
|
/** Shell's TUI half as a factory, so bundles such as `opencode-cockpit` can include it. */
|
|
13
7
|
export declare function createShellTui({ source }?: {
|
|
14
8
|
source?: string;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Log search helpers: what matched, and how failures should read. */
|
|
2
|
+
export declare function splitMatches(text: string, query: string): {
|
|
3
|
+
text: string;
|
|
4
|
+
match: boolean;
|
|
5
|
+
}[];
|
|
6
|
+
/** Daemon errors name ids and internal states; say what happened instead. */
|
|
7
|
+
export declare function friendlyError(err: unknown): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update notice.
|
|
3
|
+
*
|
|
4
|
+
* OpenCode resolves an unpinned plugin spec (`@latest`) once and then reuses its cached copy, so
|
|
5
|
+
* an install never moves forward on its own. The plugin therefore checks the registry itself, at
|
|
6
|
+
* most once a day, and offers to clear its own cache entry so the next start installs the newer
|
|
7
|
+
* version.
|
|
8
|
+
*/
|
|
9
|
+
export interface UpdateState {
|
|
10
|
+
/** Version currently running. */
|
|
11
|
+
current: string;
|
|
12
|
+
/** Newest version on the registry. */
|
|
13
|
+
latest: string;
|
|
14
|
+
/** Cache entry to remove so OpenCode reinstalls, when this is an npm install. */
|
|
15
|
+
cacheDir?: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function shouldCheck(lastCheckedAt: number | undefined, now: number, everyMs?: number): boolean;
|
|
18
|
+
/** True when `latest` is a higher release than `current`. Pre-releases never look newer. */
|
|
19
|
+
export declare function isNewer(latest: string, current: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* The directory OpenCode installed this plugin into, given the resolved module path. Removing it
|
|
22
|
+
* makes the next start reinstall from the registry. Undefined for anything but an npm install.
|
|
23
|
+
*/
|
|
24
|
+
export declare function cacheDirFor(target: string | undefined, source: string): string | undefined;
|
|
25
|
+
export declare function fetchLatestVersion(pkg: string, timeoutMs?: number): Promise<string | undefined>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TuiThemeCurrent } from "@opencode-ai/plugin/tui";
|
|
2
|
-
import type { ShellInfo } from "@opencode-cockpit/protocol/shell";
|
|
2
|
+
import type { ScreenRun, ShellInfo } from "@opencode-cockpit/protocol/shell";
|
|
3
3
|
/** What a human cares about, derived from status + exit code so every surface agrees. */
|
|
4
4
|
export type Kind = "run" | "fail" | "stop" | "done";
|
|
5
5
|
export declare function kindOf(s: ShellInfo): Kind;
|
|
@@ -48,10 +48,21 @@ export declare function partition(list: readonly ShellInfo[], opts: PartitionOpt
|
|
|
48
48
|
last: number;
|
|
49
49
|
};
|
|
50
50
|
bytes: number;
|
|
51
|
+
watch?: {
|
|
52
|
+
preset?: string | undefined;
|
|
53
|
+
status: "fail" | "ok" | "pending" | "unknown";
|
|
54
|
+
summary?: string | undefined;
|
|
55
|
+
runs: number;
|
|
56
|
+
since: number;
|
|
57
|
+
} | undefined;
|
|
58
|
+
logFile?: string | undefined;
|
|
51
59
|
}[];
|
|
52
60
|
hidden: ShellInfo[];
|
|
53
61
|
};
|
|
54
62
|
export declare function statusDetail(s: ShellInfo, now: number): string;
|
|
63
|
+
/** Short health label for a watched shell, e.g. "tsc ✗" — empty when nothing is watching it. */
|
|
64
|
+
export declare function watchLabel(s: ShellInfo): string;
|
|
65
|
+
export declare function watchColor(theme: TuiThemeCurrent, s: ShellInfo): import("@opentui/core").RGBA;
|
|
55
66
|
/** Compact detail for narrow lists. */
|
|
56
67
|
export declare function shortDetail(s: ShellInfo, now: number): string;
|
|
57
68
|
/** Coarse relative time: "just now", "12s ago", "9m ago", "3h ago". */
|
|
@@ -62,6 +73,8 @@ export declare function displayCommand(s: ShellInfo): string;
|
|
|
62
73
|
export declare function relativeCwd(cwd: string, project: string, home?: string): string;
|
|
63
74
|
/** Hard-wraps to `width`, at most `maxLines`; the last line ends with … when text was cut. */
|
|
64
75
|
export declare function wrapText(text: string, width: number, maxLines: number): string[];
|
|
76
|
+
/** Last `rows` styled rows, each cut to `cols`, so colour survives the same trimming as text. */
|
|
77
|
+
export declare function tailRuns(styled: ScreenRun[][] | undefined, rows: number, cols: number): ScreenRun[][];
|
|
65
78
|
/** Last `rows` lines of screen text, each cut to `cols`. */
|
|
66
79
|
export declare function tailLines(text: string | undefined, rows: number, cols: number): string;
|
|
67
80
|
export declare function truncate(text: string, max: number): string;
|
|
@@ -41,6 +41,15 @@ export declare function useScreen(store: ShellStore, id: Accessor<string | undef
|
|
|
41
41
|
x: number;
|
|
42
42
|
y: number;
|
|
43
43
|
};
|
|
44
|
+
styled?: {
|
|
45
|
+
text: string;
|
|
46
|
+
fg?: string | undefined;
|
|
47
|
+
bg?: string | undefined;
|
|
48
|
+
bold?: boolean | undefined;
|
|
49
|
+
dim?: boolean | undefined;
|
|
50
|
+
italic?: boolean | undefined;
|
|
51
|
+
underline?: boolean | undefined;
|
|
52
|
+
}[][] | undefined;
|
|
44
53
|
} | undefined>;
|
|
45
54
|
refetch: () => void | "" | undefined;
|
|
46
55
|
};
|