tmux-ide 2.6.0 → 2.6.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/bin/cli.js +13 -5
- package/bin/cli.ts +1 -1
- package/bunfig.toml +4 -0
- package/package.json +11 -3
- package/packages/contracts/package.json +22 -0
- package/packages/contracts/src/__tests__/ide-config.test.ts +46 -0
- package/packages/contracts/src/__tests__/terminals.test.ts +87 -0
- package/packages/contracts/src/actions-contract.ts +310 -0
- package/packages/contracts/src/actions-errors.ts +41 -0
- package/packages/contracts/src/domain.ts +36 -0
- package/packages/contracts/src/ide-config.ts +170 -0
- package/packages/contracts/src/index.ts +24 -0
- package/packages/contracts/src/lib-internal/auth.ts +13 -0
- package/packages/contracts/src/lib-internal/hq.ts +38 -0
- package/packages/contracts/src/terminals.ts +116 -0
- package/packages/contracts/src/tmux.ts +60 -0
- package/packages/contracts/src/workspace.ts +67 -0
- package/packages/daemon/src/agent-explain.ts +270 -0
- package/packages/daemon/src/attach.ts +20 -0
- package/packages/daemon/src/bin.ts +4 -0
- package/packages/daemon/src/canonical.ts +7 -0
- package/packages/daemon/src/cli.ts +499 -0
- package/packages/daemon/src/command-center/actions/contract.ts +2 -0
- package/packages/daemon/src/command-center/actions/dispatcher.ts +137 -0
- package/packages/daemon/src/command-center/actions/errors.ts +105 -0
- package/packages/daemon/src/command-center/actions/handlers/_project-context.ts +30 -0
- package/packages/daemon/src/command-center/actions/handlers/_resolve-project.ts +78 -0
- package/packages/daemon/src/command-center/actions/handlers/app-set-remote-access.ts +118 -0
- package/packages/daemon/src/command-center/actions/handlers/config-actions.ts +113 -0
- package/packages/daemon/src/command-center/actions/handlers/daemon-shutdown.ts +38 -0
- package/packages/daemon/src/command-center/actions/handlers/project-activate.ts +30 -0
- package/packages/daemon/src/command-center/actions/handlers/project-launch.ts +70 -0
- package/packages/daemon/src/command-center/actions/handlers/project-open-terminal.ts +87 -0
- package/packages/daemon/src/command-center/actions/handlers/project-restart.ts +38 -0
- package/packages/daemon/src/command-center/actions/handlers/project-stop.ts +62 -0
- package/packages/daemon/src/command-center/actions/handlers/terminal-respawn.ts +119 -0
- package/packages/daemon/src/command-center/actions/handlers/terminal-stop.ts +35 -0
- package/packages/daemon/src/command-center/actions/registry.ts +149 -0
- package/packages/daemon/src/command-center/discovery.ts +96 -0
- package/packages/daemon/src/command-center/index.ts +31 -0
- package/packages/daemon/src/command-center/schemas.ts +85 -0
- package/packages/daemon/src/command-center/server.ts +1260 -0
- package/packages/daemon/src/command-center/ws-events.ts +316 -0
- package/packages/daemon/src/config.ts +549 -0
- package/packages/daemon/src/detect.ts +248 -0
- package/packages/daemon/src/doctor.ts +242 -0
- package/packages/daemon/src/embed.ts +5 -0
- package/packages/daemon/src/index.ts +12 -0
- package/packages/daemon/src/init.ts +211 -0
- package/packages/daemon/src/inspect.ts +178 -0
- package/packages/daemon/src/js-yaml.d.ts +10 -0
- package/packages/daemon/src/launch.ts +349 -0
- package/packages/daemon/src/lib/active-projects.ts +49 -0
- package/packages/daemon/src/lib/agent-discovery.ts +121 -0
- package/packages/daemon/src/lib/app-config.ts +336 -0
- package/packages/daemon/src/lib/app-settings.ts +53 -0
- package/packages/daemon/src/lib/auth/auth-service.ts +227 -0
- package/packages/daemon/src/lib/auth/middleware.ts +56 -0
- package/packages/daemon/src/lib/auth/types.ts +2 -0
- package/packages/daemon/src/lib/auth-token.ts +5 -0
- package/packages/daemon/src/lib/authorship.ts +280 -0
- package/packages/daemon/src/lib/canonical-daemon.ts +122 -0
- package/packages/daemon/src/lib/cli-action-bridge.ts +216 -0
- package/packages/daemon/src/lib/daemon-embed.ts +782 -0
- package/packages/daemon/src/lib/daemon-watchdog.ts +111 -0
- package/packages/daemon/src/lib/daemon.ts +79 -0
- package/packages/daemon/src/lib/dot-path.ts +17 -0
- package/packages/daemon/src/lib/errors.ts +67 -0
- package/packages/daemon/src/lib/filesystem-browser.ts +292 -0
- package/packages/daemon/src/lib/launch-plan.ts +90 -0
- package/packages/daemon/src/lib/log.ts +134 -0
- package/packages/daemon/src/lib/output.ts +76 -0
- package/packages/daemon/src/lib/project-init-runner.ts +150 -0
- package/packages/daemon/src/lib/project-inspect.ts +80 -0
- package/packages/daemon/src/lib/project-onboard.ts +149 -0
- package/packages/daemon/src/lib/project-probe.ts +92 -0
- package/packages/daemon/src/lib/project-registry.ts +296 -0
- package/packages/daemon/src/lib/session-monitor.ts +122 -0
- package/packages/daemon/src/lib/session-options.ts +100 -0
- package/packages/daemon/src/lib/shell.ts +8 -0
- package/packages/daemon/src/lib/sizes.ts +36 -0
- package/packages/daemon/src/lib/skill-sync.ts +155 -0
- package/packages/daemon/src/lib/slugify.ts +10 -0
- package/packages/daemon/src/lib/terminals-store.ts +125 -0
- package/packages/daemon/src/lib/update-check.ts +298 -0
- package/packages/daemon/src/lib/update.ts +158 -0
- package/packages/daemon/src/lib/workspace-registry.ts +229 -0
- package/packages/daemon/src/lib/worktree.ts +289 -0
- package/packages/daemon/src/lib/yaml-io.ts +27 -0
- package/packages/daemon/src/ls.ts +40 -0
- package/packages/daemon/src/restart.ts +24 -0
- package/packages/daemon/src/restore.ts +514 -0
- package/packages/daemon/src/schemas/domain.ts +2 -0
- package/packages/daemon/src/schemas/filesystem.ts +34 -0
- package/packages/daemon/src/schemas/ide-config.ts +2 -0
- package/packages/daemon/src/schemas/index.ts +59 -0
- package/packages/daemon/src/schemas/inspect.ts +67 -0
- package/packages/daemon/src/schemas/registry.ts +55 -0
- package/packages/daemon/src/schemas/ws-events.ts +135 -0
- package/packages/daemon/src/send.ts +171 -0
- package/packages/daemon/src/server/README.md +15 -0
- package/packages/daemon/src/server/index.ts +74 -0
- package/packages/daemon/src/server/pty-bridge.ts +532 -0
- package/packages/daemon/src/server/standalone.ts +18 -0
- package/packages/daemon/src/server/ws-route.ts +483 -0
- package/packages/daemon/src/status.ts +59 -0
- package/packages/daemon/src/stop.ts +28 -0
- package/packages/daemon/src/terminal/NodePtyAdapter.ts +271 -0
- package/packages/daemon/src/terminal/PtyAdapter.ts +140 -0
- package/packages/daemon/src/terminal/README.md +92 -0
- package/packages/daemon/src/tui/chrome/cheatsheet.ts +260 -0
- package/packages/daemon/src/tui/chrome/chip.ts +30 -0
- package/packages/daemon/src/tui/chrome/events.ts +119 -0
- package/packages/daemon/src/tui/chrome/kitty-keys.ts +55 -0
- package/packages/daemon/src/tui/chrome/menu.ts +289 -0
- package/packages/daemon/src/tui/chrome/notify.ts +195 -0
- package/packages/daemon/src/tui/chrome/panels.ts +111 -0
- package/packages/daemon/src/tui/chrome/sidebar.ts +222 -0
- package/packages/daemon/src/tui/chrome/snapshot.ts +425 -0
- package/packages/daemon/src/tui/chrome/statusline.ts +595 -0
- package/packages/daemon/src/tui/chrome/updater.ts +428 -0
- package/packages/daemon/src/tui/chrome/welcome.ts +124 -0
- package/packages/daemon/src/tui/compiled.ts +113 -0
- package/packages/daemon/src/tui/detect/classify.ts +193 -0
- package/packages/daemon/src/tui/detect/manifest-loader.ts +192 -0
- package/packages/daemon/src/tui/detect/manifest.ts +184 -0
- package/packages/daemon/src/tui/detect/manifests.ts +226 -0
- package/packages/daemon/src/tui/detect/process-tree.ts +197 -0
- package/packages/daemon/src/tui/detect/snapshot.ts +70 -0
- package/packages/daemon/src/tui/integrations/claude.ts +176 -0
- package/packages/daemon/src/tui/integrations/offer.ts +145 -0
- package/packages/daemon/src/tui/main.ts +70 -0
- package/packages/daemon/src/tui/mirror/control-client.ts +143 -0
- package/packages/daemon/src/tui/mirror/control.ts +97 -0
- package/packages/daemon/src/tui/mirror/pane-mirror.ts +81 -0
- package/packages/daemon/src/tui/mirror/viewer.tsx +166 -0
- package/packages/daemon/src/tui/team/CONTROL.md +50 -0
- package/packages/daemon/src/tui/team/entry.ts +11 -0
- package/packages/daemon/src/tui/team/fuzzy.ts +133 -0
- package/packages/daemon/src/tui/team/home.ts +170 -0
- package/packages/daemon/src/tui/team/index.tsx +1521 -0
- package/packages/daemon/src/tui/team/input.ts +34 -0
- package/packages/daemon/src/tui/team/keymap.ts +127 -0
- package/packages/daemon/src/tui/team/mouse.ts +29 -0
- package/packages/daemon/src/tui/team/nav.ts +31 -0
- package/packages/daemon/src/tui/team/preview.ts +34 -0
- package/packages/daemon/src/tui/team/projects.ts +191 -0
- package/packages/daemon/src/tui/team/report.ts +73 -0
- package/packages/daemon/src/tui/team/sessions.ts +344 -0
- package/packages/daemon/src/tui/team/tree.ts +62 -0
- package/packages/daemon/src/types.ts +13 -0
- package/packages/daemon/src/ui/index.ts +32 -0
- package/packages/daemon/src/ui/terminal/index.ts +9 -0
- package/packages/daemon/src/ui/types.ts +91 -0
- package/packages/daemon/src/ui/web/base.css +80 -0
- package/packages/daemon/src/ui/web/components/Box.tsx +59 -0
- package/packages/daemon/src/ui/web/components/Input.tsx +32 -0
- package/packages/daemon/src/ui/web/components/ScrollBox.tsx +60 -0
- package/packages/daemon/src/ui/web/components/Text.tsx +28 -0
- package/packages/daemon/src/ui/web/hooks.ts +106 -0
- package/packages/daemon/src/ui/web/index.ts +27 -0
- package/packages/daemon/src/ui/web/render.ts +77 -0
- package/packages/daemon/src/ui/web/utils/color.ts +27 -0
- package/packages/daemon/src/validate.ts +217 -0
- package/packages/daemon/src/widgets/changes/README.md +3 -0
- package/packages/daemon/src/widgets/changes/index.tsx +691 -0
- package/packages/daemon/src/widgets/config/README.md +3 -0
- package/packages/daemon/src/widgets/config/index.tsx +481 -0
- package/packages/daemon/src/widgets/explorer/README.md +3 -0
- package/packages/daemon/src/widgets/explorer/breadcrumbs.tsx +77 -0
- package/packages/daemon/src/widgets/explorer/footer.tsx +20 -0
- package/packages/daemon/src/widgets/explorer/header.tsx +23 -0
- package/packages/daemon/src/widgets/explorer/index.tsx +456 -0
- package/packages/daemon/src/widgets/explorer/tree-model.ts +103 -0
- package/packages/daemon/src/widgets/explorer/tree.tsx +165 -0
- package/packages/daemon/src/widgets/lib/config-model.ts +116 -0
- package/packages/daemon/src/widgets/lib/files.ts +88 -0
- package/packages/daemon/src/widgets/lib/git.ts +88 -0
- package/packages/daemon/src/widgets/lib/grammar.ts +126 -0
- package/packages/daemon/src/widgets/lib/help-overlay.tsx +101 -0
- package/packages/daemon/src/widgets/lib/pane-comms.ts +209 -0
- package/packages/daemon/src/widgets/lib/theme.ts +194 -0
- package/packages/daemon/src/widgets/lib/watcher.ts +132 -0
- package/packages/daemon/src/widgets/preview/README.md +3 -0
- package/packages/daemon/src/widgets/preview/index.tsx +416 -0
- package/packages/daemon/src/widgets/resolve.ts +121 -0
- package/packages/daemon/src/widgets/setup/README.md +3 -0
- package/packages/daemon/src/widgets/setup/agent-naming.tsx +112 -0
- package/packages/daemon/src/widgets/setup/config-tree.tsx +246 -0
- package/packages/daemon/src/widgets/setup/detect-panel.tsx +72 -0
- package/packages/daemon/src/widgets/setup/field-editor.tsx +265 -0
- package/packages/daemon/src/widgets/setup/footer.tsx +107 -0
- package/packages/daemon/src/widgets/setup/index.tsx +341 -0
- package/packages/daemon/src/widgets/setup/layout-picker.tsx +96 -0
- package/packages/daemon/src/widgets/setup/orchestrator-panel.tsx +200 -0
- package/packages/daemon/src/widgets/setup/review-panel.tsx +140 -0
- package/packages/daemon/src/widgets/setup/setup-model.ts +188 -0
- package/packages/daemon/src/widgets/sidebar/index.tsx +527 -0
- package/packages/tmux-bridge/package.json +22 -0
- package/packages/tmux-bridge/src/errors.ts +28 -0
- package/packages/tmux-bridge/src/index.ts +31 -0
- package/packages/tmux-bridge/src/monitor.ts +77 -0
- package/packages/tmux-bridge/src/panes.ts +136 -0
- package/packages/tmux-bridge/src/runner.test.ts +501 -0
- package/packages/tmux-bridge/src/runner.ts +91 -0
- package/packages/tmux-bridge/src/sessions.ts +126 -0
- package/packages/tmux-bridge/src/targeting.test.ts +107 -0
- package/packages/tmux-bridge/src/targeting.ts +90 -0
- package/scripts/postinstall.js +26 -2
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AuthConfigSchema } from "./lib-internal/auth.ts";
|
|
3
|
+
import { HQConfigSchema } from "./lib-internal/hq.ts";
|
|
4
|
+
|
|
5
|
+
const sizeField = z
|
|
6
|
+
.string()
|
|
7
|
+
.regex(/^[1-9]\d*%$/)
|
|
8
|
+
.refine((v) => parseInt(v) <= 100);
|
|
9
|
+
|
|
10
|
+
export const ThemeConfigSchema = z.object({
|
|
11
|
+
accent: z.string().optional(),
|
|
12
|
+
border: z.string().optional(),
|
|
13
|
+
bg: z.string().optional(),
|
|
14
|
+
fg: z.string().optional(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
export const PaneSchema = z.object({
|
|
18
|
+
title: z.string().optional(),
|
|
19
|
+
command: z.string().optional(),
|
|
20
|
+
type: z
|
|
21
|
+
.enum([
|
|
22
|
+
"explorer",
|
|
23
|
+
"changes",
|
|
24
|
+
"preview",
|
|
25
|
+
"tasks",
|
|
26
|
+
"costs",
|
|
27
|
+
"config",
|
|
28
|
+
"mission-control",
|
|
29
|
+
"sidebar",
|
|
30
|
+
])
|
|
31
|
+
.optional(),
|
|
32
|
+
target: z.string().optional(),
|
|
33
|
+
dir: z.string().optional(),
|
|
34
|
+
size: sizeField.optional(),
|
|
35
|
+
focus: z.boolean().optional(),
|
|
36
|
+
env: z.record(z.string(), z.union([z.string(), z.number()])).optional(),
|
|
37
|
+
role: z.enum(["lead", "teammate", "planner", "validator", "researcher"]).optional(),
|
|
38
|
+
task: z.string().optional(),
|
|
39
|
+
specialty: z.string().optional(),
|
|
40
|
+
skill: z.string().optional(),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const RowSchema = z.object({
|
|
44
|
+
size: sizeField.optional(),
|
|
45
|
+
panes: z.array(PaneSchema).min(1),
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export const WebhookConfigSchema = z.object({
|
|
49
|
+
url: z.string(),
|
|
50
|
+
events: z.array(z.string()).optional(),
|
|
51
|
+
secret: z.string().optional(),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
export const OrchestratorYamlConfigSchema = z.object({
|
|
55
|
+
enabled: z.boolean().optional(),
|
|
56
|
+
port: z.number().int().positive().optional(),
|
|
57
|
+
auto_dispatch: z.boolean().optional(),
|
|
58
|
+
stall_timeout: z.number().optional(),
|
|
59
|
+
poll_interval: z.number().min(100).optional(),
|
|
60
|
+
master_pane: z.string().optional(),
|
|
61
|
+
before_run: z.string().optional(),
|
|
62
|
+
after_run: z.string().optional(),
|
|
63
|
+
dispatch_mode: z.enum(["tasks", "goals", "missions"]).optional(),
|
|
64
|
+
max_concurrent_agents: z.number().min(1).max(50).optional(),
|
|
65
|
+
widgets: z.boolean().optional(),
|
|
66
|
+
webhooks: z.array(WebhookConfigSchema).optional(),
|
|
67
|
+
services: z
|
|
68
|
+
.record(
|
|
69
|
+
z.string(),
|
|
70
|
+
z.object({
|
|
71
|
+
command: z.string(),
|
|
72
|
+
port: z.number().optional(),
|
|
73
|
+
healthcheck: z.string().optional(),
|
|
74
|
+
}),
|
|
75
|
+
)
|
|
76
|
+
.optional(),
|
|
77
|
+
research: z
|
|
78
|
+
.object({
|
|
79
|
+
enabled: z.boolean().optional(),
|
|
80
|
+
triggers: z
|
|
81
|
+
.object({
|
|
82
|
+
mission_start: z.boolean().optional(),
|
|
83
|
+
milestone_progress: z.number().min(0).optional(),
|
|
84
|
+
milestone_complete: z.boolean().optional(),
|
|
85
|
+
periodic_minutes: z.number().min(0).optional(),
|
|
86
|
+
retry_cluster: z.boolean().optional(),
|
|
87
|
+
stall_detected: z.boolean().optional(),
|
|
88
|
+
discovered_issue: z.boolean().optional(),
|
|
89
|
+
})
|
|
90
|
+
.optional(),
|
|
91
|
+
})
|
|
92
|
+
.optional(),
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
export const TunnelConfigSchema = z.object({
|
|
96
|
+
provider: z.enum(["tailscale", "ngrok", "cloudflare"]),
|
|
97
|
+
auto_start: z.boolean().optional(),
|
|
98
|
+
port: z.number().int().positive().optional(),
|
|
99
|
+
domain: z.string().optional(),
|
|
100
|
+
authtoken: z.string().optional(),
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export const CommandCenterConfigSchema = z.object({
|
|
104
|
+
port: z.number().optional(),
|
|
105
|
+
enabled: z.boolean().optional(),
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
export const DashboardConfigSchema = z.object({
|
|
109
|
+
port: z.number().int().positive().optional(),
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* The app nav-column sidebar sugar. `sidebar: true` injects a full-height left
|
|
114
|
+
* column (default width) at launch; `sidebar: { width: "30" }` sets its column
|
|
115
|
+
* width (in tmux cols, as a string to match the CLI/tmux world). `false` /
|
|
116
|
+
* omitted means no sidebar.
|
|
117
|
+
*/
|
|
118
|
+
export const SidebarConfigSchema = z.union([
|
|
119
|
+
z.boolean(),
|
|
120
|
+
z.object({ width: z.string().optional() }),
|
|
121
|
+
]);
|
|
122
|
+
|
|
123
|
+
export const IdeConfigSchema = z.object({
|
|
124
|
+
name: z.string().optional(),
|
|
125
|
+
before: z.string().optional(),
|
|
126
|
+
team: z
|
|
127
|
+
.object({
|
|
128
|
+
name: z.string(),
|
|
129
|
+
model: z.string().optional(),
|
|
130
|
+
permissions: z.array(z.string()).optional(),
|
|
131
|
+
})
|
|
132
|
+
.optional(),
|
|
133
|
+
rows: z.array(RowSchema).min(1),
|
|
134
|
+
sidebar: SidebarConfigSchema.optional(),
|
|
135
|
+
theme: ThemeConfigSchema.optional(),
|
|
136
|
+
orchestrator: OrchestratorYamlConfigSchema.optional(),
|
|
137
|
+
command_center: CommandCenterConfigSchema.optional(),
|
|
138
|
+
dashboard: DashboardConfigSchema.optional(),
|
|
139
|
+
auth: AuthConfigSchema.optional(),
|
|
140
|
+
tunnel: TunnelConfigSchema.optional(),
|
|
141
|
+
hq: HQConfigSchema.optional(),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
export const PaneActionSchema = z.object({
|
|
145
|
+
targetPane: z.string(),
|
|
146
|
+
title: z.string().nullable(),
|
|
147
|
+
chdir: z.string().nullable(),
|
|
148
|
+
exports: z.array(z.string()),
|
|
149
|
+
command: z.string().nullable(),
|
|
150
|
+
widgetType: z.string().nullable(),
|
|
151
|
+
widgetTarget: z.string().nullable(),
|
|
152
|
+
paneRole: z.string().nullable(),
|
|
153
|
+
paneType: z.string().nullable(),
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
export const SessionStateSchema = z.object({
|
|
157
|
+
running: z.boolean(),
|
|
158
|
+
reason: z.string().nullable(),
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
export type ThemeConfig = z.infer<typeof ThemeConfigSchema>;
|
|
162
|
+
export type Pane = z.infer<typeof PaneSchema>;
|
|
163
|
+
export type Row = z.infer<typeof RowSchema>;
|
|
164
|
+
export type OrchestratorYamlConfig = z.infer<typeof OrchestratorYamlConfigSchema>;
|
|
165
|
+
export type SidebarConfig = z.infer<typeof SidebarConfigSchema>;
|
|
166
|
+
export type CommandCenterConfig = z.infer<typeof CommandCenterConfigSchema>;
|
|
167
|
+
export type DashboardConfig = z.infer<typeof DashboardConfigSchema>;
|
|
168
|
+
export type IdeConfig = z.infer<typeof IdeConfigSchema>;
|
|
169
|
+
export type PaneAction = z.infer<typeof PaneActionSchema>;
|
|
170
|
+
export type SessionState = z.infer<typeof SessionStateSchema>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @tmux-ide/contracts — shared Zod schemas for the daemon ↔ dashboard
|
|
3
|
+
* boundary. Dashboard, packages/daemon, and any future v2 surfaces all
|
|
4
|
+
* import from this single source of truth.
|
|
5
|
+
*
|
|
6
|
+
* Adding a schema? Put it in either `domain.ts` (runtime data: tasks,
|
|
7
|
+
* missions, sessions, …) or `ide-config.ts` (the on-disk ide.yml
|
|
8
|
+
* shape). Both files are re-exported wholesale below — no manual
|
|
9
|
+
* registration needed.
|
|
10
|
+
*
|
|
11
|
+
* The `lib-internal/` directory holds schema-only helpers (auth, hq)
|
|
12
|
+
* that ide-config depends on — they are exported transitively here
|
|
13
|
+
* so consumers don't have to deep-import.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export * from "./lib-internal/auth.ts";
|
|
17
|
+
export * from "./lib-internal/hq.ts";
|
|
18
|
+
export * from "./ide-config.ts";
|
|
19
|
+
export * from "./domain.ts";
|
|
20
|
+
export * from "./tmux.ts";
|
|
21
|
+
export * from "./workspace.ts";
|
|
22
|
+
export * from "./actions-contract.ts";
|
|
23
|
+
export * from "./actions-errors.ts";
|
|
24
|
+
export * from "./terminals.ts";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Based on VibeTunnel (MIT) — github.com/amantus-ai/vibetunnel
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
|
|
4
|
+
export const AuthConfigSchema = z.object({
|
|
5
|
+
/** Auth method: "none" disables auth (default), "ssh" enables SSH key challenge-response. */
|
|
6
|
+
method: z.enum(["none", "ssh"]).default("none"),
|
|
7
|
+
/** JWT secret — auto-generated if omitted. */
|
|
8
|
+
secret: z.string().optional(),
|
|
9
|
+
/** Token expiry in seconds (default 86400 = 24h). */
|
|
10
|
+
token_expiry: z.number().min(60).default(86400),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export type AuthConfig = z.infer<typeof AuthConfigSchema>;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
// Based on VibeTunnel (MIT) — github.com/amantus-ai/vibetunnel
|
|
2
|
+
//
|
|
3
|
+
// Schemas + serializable interfaces only. The daemon-only `RemoteMachine`
|
|
4
|
+
// runtime type (Date / Set fields) lives in @tmux-ide/daemon's lib/hq —
|
|
5
|
+
// not here.
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
|
|
8
|
+
export interface HQConfig {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
role: "hq" | "remote";
|
|
11
|
+
hq_url?: string;
|
|
12
|
+
secret?: string;
|
|
13
|
+
heartbeat_interval?: number;
|
|
14
|
+
machine_name?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface RegistrationPayload {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
url: string;
|
|
21
|
+
token: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export const RegistrationPayloadSchema = z.object({
|
|
25
|
+
id: z.string().min(1),
|
|
26
|
+
name: z.string().min(1),
|
|
27
|
+
url: z.string().url(),
|
|
28
|
+
token: z.string().min(1),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const HQConfigSchema = z.object({
|
|
32
|
+
enabled: z.boolean().default(false),
|
|
33
|
+
role: z.enum(["hq", "remote"]),
|
|
34
|
+
hq_url: z.string().url().optional(),
|
|
35
|
+
secret: z.string().optional(),
|
|
36
|
+
heartbeat_interval: z.number().min(1000).default(15000),
|
|
37
|
+
machine_name: z.string().optional(),
|
|
38
|
+
});
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-terminal registry contracts (G20-P1).
|
|
3
|
+
*
|
|
4
|
+
* A `Terminal` is a *named pool entry* — metadata about a PTY the
|
|
5
|
+
* daemon may or may not have spawned yet. The daemon's existing
|
|
6
|
+
* `/ws/pty/:id` endpoint owns the actual process lifecycle; this
|
|
7
|
+
* registry exists so the UI can persist tab labels + restore them
|
|
8
|
+
* across reloads, and so deterministic scope/script tabs collapse to
|
|
9
|
+
* the same id (re-opens land on the running scrollback).
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
|
|
14
|
+
// ---------------------------------------------------------------------
|
|
15
|
+
// Types
|
|
16
|
+
// ---------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
export type TerminalKind = "shell" | "setup" | "run" | "teardown";
|
|
19
|
+
|
|
20
|
+
export interface Terminal {
|
|
21
|
+
/** Deterministic id for scope/script tabs; UUID for ad-hoc tabs. */
|
|
22
|
+
id: string;
|
|
23
|
+
/** Session name the terminal belongs to. */
|
|
24
|
+
projectId: string;
|
|
25
|
+
/** Sub-grouping inside a session (mission id, dir hash, …). Free-form. */
|
|
26
|
+
scopeId: string;
|
|
27
|
+
/** Free-text display name. The tab strip renames this without changing id. */
|
|
28
|
+
name: string;
|
|
29
|
+
kind: TerminalKind;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
updatedAt: string;
|
|
32
|
+
/** Set when the id was derived via `createScriptTerminalId` so the
|
|
33
|
+
* client can show a "shared script" badge in the tab strip. */
|
|
34
|
+
scripted?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Live runtime info — derived from the daemon's bridge registry, not
|
|
38
|
+
* the JSON store. Combined with `Terminal` for the list endpoint. */
|
|
39
|
+
export interface TerminalRuntime {
|
|
40
|
+
running: boolean;
|
|
41
|
+
cols?: number;
|
|
42
|
+
rows?: number;
|
|
43
|
+
/** Bytes available in the replay ring buffer when a client subscribes. */
|
|
44
|
+
replayBytes?: number;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface TerminalWithRuntime extends Terminal {
|
|
48
|
+
runtime: TerminalRuntime;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface TerminalListResponse {
|
|
52
|
+
terminals: TerminalWithRuntime[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// ---------------------------------------------------------------------
|
|
56
|
+
// Deterministic id
|
|
57
|
+
// ---------------------------------------------------------------------
|
|
58
|
+
|
|
59
|
+
/** Build a deterministic 32-char id from `(projectId, scopeId, kind,
|
|
60
|
+
* script)`. Two different callers asking for "the run script terminal
|
|
61
|
+
* for project X, scope Y, script Z" get the same id and land on the
|
|
62
|
+
* same bridge — which means scrollback survives a browser reload. */
|
|
63
|
+
export async function createScriptTerminalId(args: {
|
|
64
|
+
projectId: string;
|
|
65
|
+
scopeId?: string;
|
|
66
|
+
/** Backward-compat alias for `scopeId`. */
|
|
67
|
+
taskId?: string;
|
|
68
|
+
kind: TerminalKind;
|
|
69
|
+
script: string;
|
|
70
|
+
}): Promise<string> {
|
|
71
|
+
const scope = args.scopeId ?? args.taskId;
|
|
72
|
+
if (!scope) {
|
|
73
|
+
throw new Error("createScriptTerminalId: scopeId (or taskId) is required");
|
|
74
|
+
}
|
|
75
|
+
const key = `${args.projectId}::${scope}::${args.kind}::${args.script}`;
|
|
76
|
+
const data = new TextEncoder().encode(key);
|
|
77
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
|
78
|
+
return Array.from(new Uint8Array(digest))
|
|
79
|
+
.map((b) => b.toString(16).padStart(2, "0"))
|
|
80
|
+
.join("")
|
|
81
|
+
.slice(0, 32);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ---------------------------------------------------------------------
|
|
85
|
+
// Zod request schemas
|
|
86
|
+
// ---------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
export const terminalKindSchema = z.enum(["shell", "setup", "run", "teardown"]);
|
|
89
|
+
|
|
90
|
+
export const terminalCreateRequestSchema = z
|
|
91
|
+
.object({
|
|
92
|
+
scopeId: z.string().trim().min(1).max(256),
|
|
93
|
+
name: z.string().trim().min(1).max(120),
|
|
94
|
+
kind: terminalKindSchema.optional(),
|
|
95
|
+
/** Provide for script tabs to opt into deterministic id collapse. */
|
|
96
|
+
script: z.string().max(2048).optional(),
|
|
97
|
+
/** Explicit id wins. Used by the dashboard to reserve a known id
|
|
98
|
+
* (e.g. the default shell tab derived from session.dir). */
|
|
99
|
+
id: z
|
|
100
|
+
.string()
|
|
101
|
+
.trim()
|
|
102
|
+
.min(8)
|
|
103
|
+
.max(64)
|
|
104
|
+
.regex(/^[A-Za-z0-9_-]+$/u, "id may only contain alphanumerics, '-', '_'")
|
|
105
|
+
.optional(),
|
|
106
|
+
})
|
|
107
|
+
.refine((v) => v.kind !== undefined || v.script === undefined, {
|
|
108
|
+
message: "script requires kind",
|
|
109
|
+
path: ["script"],
|
|
110
|
+
});
|
|
111
|
+
export type TerminalCreateRequest = z.infer<typeof terminalCreateRequestSchema>;
|
|
112
|
+
|
|
113
|
+
export const terminalRenameRequestSchema = z.object({
|
|
114
|
+
name: z.string().trim().min(1).max(120),
|
|
115
|
+
});
|
|
116
|
+
export type TerminalRenameRequest = z.infer<typeof terminalRenameRequestSchema>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Tmux state schemas — the canonical typed surface for tmux sessions,
|
|
5
|
+
* windows, panes, and pane addressing.
|
|
6
|
+
*
|
|
7
|
+
* Used by:
|
|
8
|
+
* - packages/tmux-bridge — implementation that shells out to tmux.
|
|
9
|
+
* - packages/daemon (session-monitor, discovery, command-center) —
|
|
10
|
+
* materializes these shapes into the live runtime state.
|
|
11
|
+
* - dashboard — consumes them via the typed REST/SSE clients.
|
|
12
|
+
*
|
|
13
|
+
* Adding a new addressing mode (e.g. byRegex) is intentionally a one-line
|
|
14
|
+
* discriminant change here; bridge resolvers must update in lockstep.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
export const TmuxPaneSchemaZ = z.object({
|
|
18
|
+
/** Stable tmux pane id (e.g. `%23`). */
|
|
19
|
+
id: z.string(),
|
|
20
|
+
/** Pane index within its window (zero-based). */
|
|
21
|
+
paneIndex: z.number().int().nonnegative(),
|
|
22
|
+
/** Window index within the session (zero-based). */
|
|
23
|
+
windowIndex: z.number().int().nonnegative(),
|
|
24
|
+
title: z.string().nullable(),
|
|
25
|
+
command: z.string().nullable(),
|
|
26
|
+
active: z.boolean(),
|
|
27
|
+
});
|
|
28
|
+
export type TmuxPane = z.infer<typeof TmuxPaneSchemaZ>;
|
|
29
|
+
|
|
30
|
+
export const TmuxWindowSchemaZ = z.object({
|
|
31
|
+
index: z.number().int().nonnegative(),
|
|
32
|
+
name: z.string(),
|
|
33
|
+
panes: z.array(TmuxPaneSchemaZ),
|
|
34
|
+
});
|
|
35
|
+
export type TmuxWindow = z.infer<typeof TmuxWindowSchemaZ>;
|
|
36
|
+
|
|
37
|
+
export const TmuxSessionSchemaZ = z.object({
|
|
38
|
+
name: z.string(),
|
|
39
|
+
windows: z.array(TmuxWindowSchemaZ),
|
|
40
|
+
/** Session creation time (epoch milliseconds). */
|
|
41
|
+
created: z.number().int().nonnegative(),
|
|
42
|
+
attached: z.boolean(),
|
|
43
|
+
/** Project directory the session was launched from, when known. */
|
|
44
|
+
projectDir: z.string().nullable(),
|
|
45
|
+
});
|
|
46
|
+
export type TmuxSession = z.infer<typeof TmuxSessionSchemaZ>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Discriminated union for addressing a pane. The bridge's resolver
|
|
50
|
+
* implements byId/byIndex/byTitle directly; byRole is resolved at the
|
|
51
|
+
* daemon layer (it requires reading the ide.yml-driven role mapping)
|
|
52
|
+
* and translated into a concrete address before reaching the bridge.
|
|
53
|
+
*/
|
|
54
|
+
export const TmuxPaneTargetSchemaZ = z.discriminatedUnion("kind", [
|
|
55
|
+
z.object({ kind: z.literal("byId"), id: z.string() }),
|
|
56
|
+
z.object({ kind: z.literal("byIndex"), index: z.number().int().nonnegative() }),
|
|
57
|
+
z.object({ kind: z.literal("byTitle"), title: z.string() }),
|
|
58
|
+
z.object({ kind: z.literal("byRole"), role: z.string() }),
|
|
59
|
+
]);
|
|
60
|
+
export type TmuxPaneTarget = z.infer<typeof TmuxPaneTargetSchemaZ>;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A workspace is a project the daemon is actively serving — identified by
|
|
5
|
+
* its tmux session name and bound to a project directory.
|
|
6
|
+
*
|
|
7
|
+
* The workspace registry replaces the historical single-session
|
|
8
|
+
* TMUX_IDE_SESSION env coupling, letting the daemon serve N projects in
|
|
9
|
+
* one process. Goal 12 of the t3-style consolidation; see T065.
|
|
10
|
+
*/
|
|
11
|
+
export const WorkspaceSchemaZ = z.object({
|
|
12
|
+
/** Stable workspace name (typically equal to tmux session name). */
|
|
13
|
+
name: z.string().min(1),
|
|
14
|
+
/** Tmux session this workspace maps to. */
|
|
15
|
+
sessionName: z.string().min(1),
|
|
16
|
+
/** Absolute project directory. */
|
|
17
|
+
projectDir: z.string().min(1),
|
|
18
|
+
/** Absolute path to the ide.yml driving this workspace. */
|
|
19
|
+
ideConfigPath: z.string().nullable(),
|
|
20
|
+
/** ISO timestamp of when the workspace was added. */
|
|
21
|
+
addedAt: z.string(),
|
|
22
|
+
});
|
|
23
|
+
export type Workspace = z.infer<typeof WorkspaceSchemaZ>;
|
|
24
|
+
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
// HTTP request / response shapes for /api/workspaces
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
|
|
29
|
+
export const WorkspaceListResponseSchemaZ = z.object({
|
|
30
|
+
workspaces: z.array(WorkspaceSchemaZ),
|
|
31
|
+
});
|
|
32
|
+
export type WorkspaceListResponse = z.infer<typeof WorkspaceListResponseSchemaZ>;
|
|
33
|
+
|
|
34
|
+
export const AddWorkspaceRequestSchemaZ = z.object({
|
|
35
|
+
/** Absolute path to the project directory. */
|
|
36
|
+
projectDir: z.string().min(1),
|
|
37
|
+
/** Optional explicit workspace name. Auto-derived from basename when absent. */
|
|
38
|
+
name: z.string().min(1).optional(),
|
|
39
|
+
/** Optional override for the tmux session name (defaults to `name`). */
|
|
40
|
+
sessionName: z.string().min(1).optional(),
|
|
41
|
+
/** Optional ide.yml path the workspace was launched with. */
|
|
42
|
+
ideConfigPath: z.string().min(1).optional(),
|
|
43
|
+
});
|
|
44
|
+
export type AddWorkspaceRequest = z.infer<typeof AddWorkspaceRequestSchemaZ>;
|
|
45
|
+
|
|
46
|
+
export const AddWorkspaceResponseSchemaZ = z.object({
|
|
47
|
+
workspace: WorkspaceSchemaZ,
|
|
48
|
+
});
|
|
49
|
+
export type AddWorkspaceResponse = z.infer<typeof AddWorkspaceResponseSchemaZ>;
|
|
50
|
+
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
// WebSocket event frames — fired on registry add/remove (including the
|
|
53
|
+
// auto-reconcile loop that drops dead sessions). Kept here so dashboard /
|
|
54
|
+
// daemon consumers share the exact discriminator strings.
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
export const WorkspaceAddedFrameSchemaZ = z.object({
|
|
58
|
+
type: z.literal("workspace.added"),
|
|
59
|
+
workspace: WorkspaceSchemaZ,
|
|
60
|
+
});
|
|
61
|
+
export type WorkspaceAddedFrame = z.infer<typeof WorkspaceAddedFrameSchemaZ>;
|
|
62
|
+
|
|
63
|
+
export const WorkspaceRemovedFrameSchemaZ = z.object({
|
|
64
|
+
type: z.literal("workspace.removed"),
|
|
65
|
+
name: z.string(),
|
|
66
|
+
});
|
|
67
|
+
export type WorkspaceRemovedFrame = z.infer<typeof WorkspaceRemovedFrameSchemaZ>;
|