tmux-ide 2.6.1 → 2.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/README.md +36 -14
- package/bin/cli.js +4174 -1235
- package/bin/cli.ts +426 -72
- package/package.json +10 -6
- package/packages/contracts/src/__tests__/control.test.ts +154 -0
- package/packages/contracts/src/control.ts +217 -0
- package/packages/contracts/src/index.ts +1 -0
- package/packages/daemon/dist/agent-explain.d.ts +8 -1
- package/packages/daemon/dist/agent-explain.js +19 -3
- package/packages/daemon/dist/control/client.d.ts +23 -0
- package/packages/daemon/dist/control/client.js +105 -0
- package/packages/daemon/dist/control/dispatch.d.ts +34 -0
- package/packages/daemon/dist/control/dispatch.js +83 -0
- package/packages/daemon/dist/control/fanout.d.ts +19 -0
- package/packages/daemon/dist/control/fanout.js +37 -0
- package/packages/daemon/dist/control/frames.d.ts +23 -0
- package/packages/daemon/dist/control/frames.js +37 -0
- package/packages/daemon/dist/control/lifecycle.d.ts +45 -0
- package/packages/daemon/dist/control/lifecycle.js +114 -0
- package/packages/daemon/dist/control/server.d.ts +16 -0
- package/packages/daemon/dist/control/server.js +214 -0
- package/packages/daemon/dist/control/verbs.d.ts +11 -0
- package/packages/daemon/dist/control/verbs.js +91 -0
- package/packages/daemon/dist/doctor.d.ts +18 -0
- package/packages/daemon/dist/doctor.js +105 -15
- package/packages/daemon/dist/lib/agent-discovery.d.ts +27 -2
- package/packages/daemon/dist/lib/agent-discovery.js +29 -14
- package/packages/daemon/dist/lib/app-config.d.ts +106 -0
- package/packages/daemon/dist/lib/app-config.js +104 -5
- package/packages/daemon/dist/lib/manifest-pack.d.ts +79 -0
- package/packages/daemon/dist/lib/manifest-pack.js +232 -0
- package/packages/daemon/dist/lib/state-home.d.ts +2 -0
- package/packages/daemon/dist/lib/state-home.js +12 -0
- package/packages/daemon/dist/lib/tui-binary.d.ts +57 -0
- package/packages/daemon/dist/lib/tui-binary.js +130 -0
- package/packages/daemon/dist/lib/update-check.js +5 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +34 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/PkgInfo +1 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/AppIcon.icns +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
- package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +139 -0
- package/packages/daemon/dist/restore.d.ts +35 -8
- package/packages/daemon/dist/restore.js +52 -15
- package/packages/daemon/dist/send.d.ts +33 -1
- package/packages/daemon/dist/send.js +32 -19
- package/packages/daemon/dist/widgets/explorer/breadcrumbs.d.ts +1 -1
- package/packages/daemon/dist/widgets/explorer/footer.d.ts +1 -1
- package/packages/daemon/dist/widgets/explorer/tree.d.ts +1 -1
- package/packages/daemon/dist/widgets/lib/help-overlay.d.ts +1 -1
- package/packages/daemon/dist/widgets/setup/agent-naming.d.ts +1 -1
- package/packages/daemon/dist/widgets/setup/config-tree.d.ts +1 -1
- package/packages/daemon/dist/widgets/setup/detect-panel.d.ts +1 -1
- package/packages/daemon/dist/widgets/setup/field-editor.d.ts +1 -1
- package/packages/daemon/dist/widgets/setup/footer.d.ts +1 -1
- package/packages/daemon/dist/widgets/setup/layout-picker.d.ts +1 -1
- package/packages/daemon/src/agent-explain.ts +34 -6
- package/packages/daemon/src/control/client.ts +128 -0
- package/packages/daemon/src/control/dispatch.ts +107 -0
- package/packages/daemon/src/control/fanout.ts +44 -0
- package/packages/daemon/src/control/frames.ts +40 -0
- package/packages/daemon/src/control/lifecycle.ts +151 -0
- package/packages/daemon/src/control/server.ts +237 -0
- package/packages/daemon/src/control/verbs.ts +118 -0
- package/packages/daemon/src/doctor.ts +113 -28
- package/packages/daemon/src/lib/agent-discovery.ts +53 -13
- package/packages/daemon/src/lib/app-config.ts +194 -5
- package/packages/daemon/src/lib/manifest-pack.ts +255 -0
- package/packages/daemon/src/lib/state-home.ts +13 -0
- package/packages/daemon/src/lib/tui-binary.ts +165 -0
- package/packages/daemon/src/lib/update-check.ts +5 -0
- package/packages/daemon/src/restore.ts +53 -15
- package/packages/daemon/src/send.ts +55 -21
- package/packages/daemon/src/tui/chrome/events.ts +4 -4
- package/packages/daemon/src/tui/chrome/front-door.ts +39 -0
- package/packages/daemon/src/tui/chrome/notify-prefs.ts +58 -0
- package/packages/daemon/src/tui/chrome/notify-state.ts +76 -0
- package/packages/daemon/src/tui/chrome/notify.ts +737 -52
- package/packages/daemon/src/tui/chrome/updater.ts +318 -30
- package/packages/daemon/src/tui/compiled.ts +11 -3
- package/packages/daemon/src/tui/detect/classify.ts +49 -0
- package/packages/daemon/src/tui/detect/manifest-loader.ts +56 -6
- package/packages/daemon/src/tui/detect/manifest.ts +39 -3
- package/packages/daemon/src/tui/detect/manifests.ts +395 -33
- package/packages/daemon/src/tui/detect/process-tree.ts +33 -3
- package/packages/daemon/src/tui/detect/session-id.ts +503 -0
- package/packages/daemon/src/tui/integrations/opencode.ts +121 -0
- package/packages/daemon/src/tui/main.ts +13 -1
- package/packages/daemon/src/tui/mirror/ack-writer.ts +77 -0
- package/packages/daemon/src/tui/mirror/agent-chip.ts +126 -0
- package/packages/daemon/src/tui/mirror/agent-lifecycle.ts +437 -0
- package/packages/daemon/src/tui/mirror/agent-rows.ts +155 -0
- package/packages/daemon/src/tui/mirror/app-state.ts +342 -0
- package/packages/daemon/src/tui/mirror/app.tsx +7048 -0
- package/packages/daemon/src/tui/mirror/attention.ts +110 -0
- package/packages/daemon/src/tui/mirror/blit.ts +186 -0
- package/packages/daemon/src/tui/mirror/control-client.ts +80 -9
- package/packages/daemon/src/tui/mirror/dialog-model.ts +298 -0
- package/packages/daemon/src/tui/mirror/dialog-stack.ts +367 -0
- package/packages/daemon/src/tui/mirror/diff-model.ts +387 -0
- package/packages/daemon/src/tui/mirror/editor-buffer.ts +117 -0
- package/packages/daemon/src/tui/mirror/file-tree.ts +322 -0
- package/packages/daemon/src/tui/mirror/focus-border.ts +57 -0
- package/packages/daemon/src/tui/mirror/folder-picker.ts +124 -0
- package/packages/daemon/src/tui/mirror/home-model.ts +174 -0
- package/packages/daemon/src/tui/mirror/host-terminal.ts +49 -0
- package/packages/daemon/src/tui/mirror/hosted.ts +205 -0
- package/packages/daemon/src/tui/mirror/input-coalescer.ts +105 -0
- package/packages/daemon/src/tui/mirror/layout-parse.ts +154 -0
- package/packages/daemon/src/tui/mirror/menu-model.ts +210 -0
- package/packages/daemon/src/tui/mirror/palette.ts +564 -0
- package/packages/daemon/src/tui/mirror/pane-mirror.ts +578 -20
- package/packages/daemon/src/tui/mirror/pane-surface.tsx +422 -0
- package/packages/daemon/src/tui/mirror/perf-tap.ts +186 -0
- package/packages/daemon/src/tui/mirror/resize-model.ts +85 -0
- package/packages/daemon/src/tui/mirror/scrollbar-model.ts +88 -0
- package/packages/daemon/src/tui/mirror/search-model.ts +70 -0
- package/packages/daemon/src/tui/mirror/selection.ts +376 -0
- package/packages/daemon/src/tui/mirror/session-mirror.ts +724 -0
- package/packages/daemon/src/tui/mirror/settings-model.ts +425 -0
- package/packages/daemon/src/tui/mirror/sidebar.tsx +218 -0
- package/packages/daemon/src/tui/mirror/size-truth.ts +130 -0
- package/packages/daemon/src/tui/mirror/spans.ts +46 -0
- package/packages/daemon/src/tui/mirror/status-grammar.ts +32 -0
- package/packages/daemon/src/tui/mirror/theme.ts +45 -0
- package/packages/daemon/src/tui/team/entry.ts +34 -7
- package/packages/daemon/src/tui/team/fuzzy.ts +20 -0
- package/packages/daemon/src/tui/team/report.ts +11 -1
- package/packages/daemon/src/tui/team/sessions.ts +184 -17
- package/packages/daemon/src/tui/team/wait.ts +144 -0
- package/scripts/build-macos-notifier.mjs +160 -0
- package/scripts/build-tui.mjs +11 -4
- package/scripts/perf-mirror.mjs +313 -0
- package/scripts/postinstall.js +8 -1
- package/scripts/prepublish-check.mjs +37 -1
- package/scripts/publish-tap.sh +55 -0
- package/skill/SKILL.md +110 -2
- package/templates/AGENTS.md +14 -7
- package/templates/agent-team-monorepo.yml +8 -0
- package/templates/agent-team-nextjs.yml +8 -0
- package/templates/agent-team.yml +10 -0
- package/templates/convex.yml +2 -0
- package/templates/default.yml +11 -5
- package/templates/go.yml +4 -0
- package/templates/missions.yml +6 -0
- package/templates/nextjs.yml +4 -0
- package/templates/python.yml +4 -0
- package/templates/skills/backend.md +5 -12
- package/templates/skills/frontend.md +5 -12
- package/templates/skills/general-worker.md +5 -12
- package/templates/skills/researcher.md +7 -12
- package/templates/skills/reviewer.md +7 -16
- package/templates/vite.yml +4 -0
- package/packages/daemon/src/tui/mirror/viewer.tsx +0 -166
|
@@ -30,9 +30,20 @@ import { join } from "node:path";
|
|
|
30
30
|
import type { AgentManifest, Rule, StateRules } from "./manifest.ts";
|
|
31
31
|
import { BUNDLED_MANIFESTS } from "./manifests.ts";
|
|
32
32
|
|
|
33
|
-
/** Directory scanned for user override manifests.
|
|
33
|
+
/** Directory scanned for user override manifests. Honors `TMUX_IDE_HOME` (the
|
|
34
|
+
* state-home override every other `~/.tmux-ide` consumer respects) so tests
|
|
35
|
+
* never read a real user's overrides. */
|
|
34
36
|
export function overrideDir(): string {
|
|
35
|
-
|
|
37
|
+
const home = process.env.TMUX_IDE_HOME ?? join(homedir(), ".tmux-ide");
|
|
38
|
+
return join(home, "agent-detection");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** The fetched manifest-pack file (`tmux-ide update --manifests` installs it;
|
|
42
|
+
* see `lib/manifest-pack.ts` for the format + publish contract). Lives in a
|
|
43
|
+
* SUBDIRECTORY so {@link readOverrideManifests}'s top-level `*.json` scan
|
|
44
|
+
* never sees it — that is what keeps user files ABOVE the pack. */
|
|
45
|
+
export function packFile(dir = overrideDir()): string {
|
|
46
|
+
return join(dir, "pack", "manifest-pack.json");
|
|
36
47
|
}
|
|
37
48
|
|
|
38
49
|
/**
|
|
@@ -156,7 +167,8 @@ function normalizeStates(m: AgentManifest): AgentManifest {
|
|
|
156
167
|
if (m.states.blocked) states.blocked = m.states.blocked;
|
|
157
168
|
if (m.states.working) states.working = m.states.working;
|
|
158
169
|
if (m.states.done) states.done = m.states.done;
|
|
159
|
-
|
|
170
|
+
const confidence = m.confidence === "tuned" ? "tuned" : "conservative";
|
|
171
|
+
return { id: m.id, commands: m.commands, states, confidence };
|
|
160
172
|
}
|
|
161
173
|
|
|
162
174
|
function warnOnce(path: string, reason: string): void {
|
|
@@ -166,11 +178,49 @@ function warnOnce(path: string, reason: string): void {
|
|
|
166
178
|
}
|
|
167
179
|
|
|
168
180
|
/**
|
|
169
|
-
*
|
|
170
|
-
*
|
|
181
|
+
* Read the installed manifest PACK (fetched by `tmux-ide update --manifests`),
|
|
182
|
+
* or `[]` when none is installed. Thin io — a malformed pack file is skipped
|
|
183
|
+
* with a one-time stderr warning, never a throw (the pack was schema-validated
|
|
184
|
+
* at install time; this guards a hand-edited/corrupted file). Each entry gets
|
|
185
|
+
* the same structural validation + normalization as a user override file.
|
|
186
|
+
*/
|
|
187
|
+
export function readPackManifests(dir = overrideDir()): AgentManifest[] {
|
|
188
|
+
const path = packFile(dir);
|
|
189
|
+
let raw: string;
|
|
190
|
+
try {
|
|
191
|
+
raw = readFileSync(path, "utf8");
|
|
192
|
+
} catch {
|
|
193
|
+
// No pack installed (the common case).
|
|
194
|
+
return [];
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const parsed: unknown = JSON.parse(raw);
|
|
198
|
+
const manifests = (parsed as { manifests?: unknown })?.manifests;
|
|
199
|
+
if (!Array.isArray(manifests)) {
|
|
200
|
+
warnOnce(path, "not a manifest pack (missing manifests[])");
|
|
201
|
+
return [];
|
|
202
|
+
}
|
|
203
|
+
const valid: AgentManifest[] = [];
|
|
204
|
+
for (const entry of manifests) {
|
|
205
|
+
if (validateManifestShape(entry)) valid.push(normalizeStates(entry));
|
|
206
|
+
else warnOnce(path, "pack entry is not a valid AgentManifest — entry skipped");
|
|
207
|
+
}
|
|
208
|
+
return valid;
|
|
209
|
+
} catch (err) {
|
|
210
|
+
warnOnce(path, err instanceof Error ? err.message : String(err));
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Load the full manifest set: bundled + pack + user overrides, merged in that
|
|
217
|
+
* PRECEDENCE order — a fetched pack refines the bundled set, and a user's own
|
|
218
|
+
* `agent-detection/*.json` file always beats both (it is merged LAST). Does io
|
|
219
|
+
* on every call — prefer {@link getManifests} for hot paths.
|
|
171
220
|
*/
|
|
172
221
|
export function loadManifests(): AgentManifest[] {
|
|
173
|
-
|
|
222
|
+
const withPack = mergeManifests(BUNDLED_MANIFESTS, readPackManifests());
|
|
223
|
+
return mergeManifests(withPack, readOverrideManifests());
|
|
174
224
|
}
|
|
175
225
|
|
|
176
226
|
/** Process-lifetime cache for the merged manifest set. */
|
|
@@ -40,6 +40,15 @@ export interface StateRules {
|
|
|
40
40
|
done?: Rule;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* How much trust the manifest's rules earn.
|
|
45
|
+
* - `tuned`: built from REAL captured screens (or the agent's own source
|
|
46
|
+
* strings) — the markers are verbatim, not guessed.
|
|
47
|
+
* - `conservative`: best-effort from public knowledge; high-precision only, so
|
|
48
|
+
* it can never false-positive on a plain prompt, but it may miss real states.
|
|
49
|
+
*/
|
|
50
|
+
export type ManifestConfidence = "tuned" | "conservative";
|
|
51
|
+
|
|
43
52
|
/** A detection manifest for one or more pane commands. */
|
|
44
53
|
export interface AgentManifest {
|
|
45
54
|
/** Stable manifest id. */
|
|
@@ -48,6 +57,12 @@ export interface AgentManifest {
|
|
|
48
57
|
commands: string[];
|
|
49
58
|
/** Evidence rules per detectable state. */
|
|
50
59
|
states: StateRules;
|
|
60
|
+
/**
|
|
61
|
+
* Evidence confidence (default `conservative` when omitted). Surfaced by
|
|
62
|
+
* `agent explain` so a user can see whether a verdict rests on real evidence
|
|
63
|
+
* or a best-effort heuristic. Purely informational — never affects matching.
|
|
64
|
+
*/
|
|
65
|
+
confidence?: ManifestConfidence;
|
|
51
66
|
}
|
|
52
67
|
|
|
53
68
|
/** The states a manifest can positively detect (idle is inferred elsewhere). */
|
|
@@ -160,10 +175,31 @@ export function explain(
|
|
|
160
175
|
return { state: winner ? winner.state : null, checked };
|
|
161
176
|
}
|
|
162
177
|
|
|
178
|
+
/** Escape a string for literal use inside a RegExp source. */
|
|
179
|
+
function escapeRegex(s: string): string {
|
|
180
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Does `haystack` contain `needle` as a WHOLE alphanumeric segment (delimited
|
|
185
|
+
* by start/end or any non-alphanumeric)? `grok-build` contains the segment
|
|
186
|
+
* `grok`; `pip` does NOT contain the segment `pi`. This is what keeps short
|
|
187
|
+
* manifest command tokens (pi, devin, kimi — M25.4) from substring-matching
|
|
188
|
+
* unrelated commands (`pip`, `vi`, `api-server`).
|
|
189
|
+
*/
|
|
190
|
+
function containsSegment(haystack: string, needle: string): boolean {
|
|
191
|
+
if (!haystack.includes(needle)) return false;
|
|
192
|
+
return new RegExp(`(^|[^a-z0-9])${escapeRegex(needle)}([^a-z0-9]|$)`).test(haystack);
|
|
193
|
+
}
|
|
194
|
+
|
|
163
195
|
/**
|
|
164
196
|
* Pick the manifest whose `commands` best match a pane's current command.
|
|
165
|
-
* Prefers an exact (case-insensitive) match, then a
|
|
166
|
-
* direction
|
|
197
|
+
* Prefers an exact (case-insensitive) match, then a SEGMENT match in either
|
|
198
|
+
* direction — the command contains a manifest token as a whole segment
|
|
199
|
+
* (`grok-build` → `grok`, `.kilo` → `kilo`) or vice versa (`cursor` →
|
|
200
|
+
* `cursor-agent`). Raw substring matching was retired in M25.4: it made every
|
|
201
|
+
* short token a false-positive machine (`pi` ⊂ `pip`, `vi` ⊂ `devin`).
|
|
202
|
+
* Returns undefined when nothing applies.
|
|
167
203
|
*/
|
|
168
204
|
export function pickManifest(
|
|
169
205
|
command: string,
|
|
@@ -178,7 +214,7 @@ export function pickManifest(
|
|
|
178
214
|
return manifests.find((m) =>
|
|
179
215
|
m.commands.some((c) => {
|
|
180
216
|
const name = c.toLowerCase();
|
|
181
|
-
return cmd
|
|
217
|
+
return containsSegment(cmd, name) || containsSegment(name, cmd);
|
|
182
218
|
}),
|
|
183
219
|
);
|
|
184
220
|
}
|