@gigaflow/gmux 0.15.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 +654 -0
- package/LICENSE +21 -0
- package/README.md +351 -0
- package/dist/adapters/claude-code.d.ts +52 -0
- package/dist/adapters/claude-code.js +315 -0
- package/dist/adapters/claude-code.js.map +1 -0
- package/dist/adapters/codex.d.ts +39 -0
- package/dist/adapters/codex.js +233 -0
- package/dist/adapters/codex.js.map +1 -0
- package/dist/adapters/jsonl.d.ts +40 -0
- package/dist/adapters/jsonl.js +92 -0
- package/dist/adapters/jsonl.js.map +1 -0
- package/dist/adapters/registry.d.ts +11 -0
- package/dist/adapters/registry.js +21 -0
- package/dist/adapters/registry.js.map +1 -0
- package/dist/adapters/types.d.ts +43 -0
- package/dist/adapters/types.js +2 -0
- package/dist/adapters/types.js.map +1 -0
- package/dist/cli/border-client.d.ts +8 -0
- package/dist/cli/border-client.js +11 -0
- package/dist/cli/border-client.js.map +1 -0
- package/dist/cli/commands/__ask-cancel.d.ts +35 -0
- package/dist/cli/commands/__ask-cancel.js +91 -0
- package/dist/cli/commands/__ask-cancel.js.map +1 -0
- package/dist/cli/commands/__ask-refresh.d.ts +40 -0
- package/dist/cli/commands/__ask-refresh.js +54 -0
- package/dist/cli/commands/__ask-refresh.js.map +1 -0
- package/dist/cli/commands/__ask-run.d.ts +43 -0
- package/dist/cli/commands/__ask-run.js +126 -0
- package/dist/cli/commands/__ask-run.js.map +1 -0
- package/dist/cli/commands/__ask-send.d.ts +50 -0
- package/dist/cli/commands/__ask-send.js +138 -0
- package/dist/cli/commands/__ask-send.js.map +1 -0
- package/dist/cli/commands/__preview-card.d.ts +31 -0
- package/dist/cli/commands/__preview-card.js +72 -0
- package/dist/cli/commands/__preview-card.js.map +1 -0
- package/dist/cli/commands/ask.d.ts +50 -0
- package/dist/cli/commands/ask.js +240 -0
- package/dist/cli/commands/ask.js.map +1 -0
- package/dist/cli/commands/auto.d.ts +12 -0
- package/dist/cli/commands/auto.js +28 -0
- package/dist/cli/commands/auto.js.map +1 -0
- package/dist/cli/commands/cockpit.d.ts +14 -0
- package/dist/cli/commands/cockpit.js +52 -0
- package/dist/cli/commands/cockpit.js.map +1 -0
- package/dist/cli/commands/daemon.d.ts +75 -0
- package/dist/cli/commands/daemon.js +258 -0
- package/dist/cli/commands/daemon.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +6 -0
- package/dist/cli/commands/doctor.js +159 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/grep.d.ts +2 -0
- package/dist/cli/commands/grep.js +52 -0
- package/dist/cli/commands/grep.js.map +1 -0
- package/dist/cli/commands/index-cmd.d.ts +2 -0
- package/dist/cli/commands/index-cmd.js +29 -0
- package/dist/cli/commands/index-cmd.js.map +1 -0
- package/dist/cli/commands/ls.d.ts +30 -0
- package/dist/cli/commands/ls.js +95 -0
- package/dist/cli/commands/ls.js.map +1 -0
- package/dist/cli/commands/overlay.d.ts +26 -0
- package/dist/cli/commands/overlay.js +216 -0
- package/dist/cli/commands/overlay.js.map +1 -0
- package/dist/cli/commands/pick.d.ts +59 -0
- package/dist/cli/commands/pick.js +254 -0
- package/dist/cli/commands/pick.js.map +1 -0
- package/dist/cli/commands/picker-rows.d.ts +17 -0
- package/dist/cli/commands/picker-rows.js +47 -0
- package/dist/cli/commands/picker-rows.js.map +1 -0
- package/dist/cli/commands/resume.d.ts +25 -0
- package/dist/cli/commands/resume.js +88 -0
- package/dist/cli/commands/resume.js.map +1 -0
- package/dist/cli/commands/run.d.ts +13 -0
- package/dist/cli/commands/run.js +78 -0
- package/dist/cli/commands/run.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +37 -0
- package/dist/cli/commands/setup.js +200 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/show.d.ts +2 -0
- package/dist/cli/commands/show.js +24 -0
- package/dist/cli/commands/show.js.map +1 -0
- package/dist/cli/commands/summarize.d.ts +2 -0
- package/dist/cli/commands/summarize.js +59 -0
- package/dist/cli/commands/summarize.js.map +1 -0
- package/dist/cli/commands/tmux.d.ts +11 -0
- package/dist/cli/commands/tmux.js +90 -0
- package/dist/cli/commands/tmux.js.map +1 -0
- package/dist/cli/commands/watch.d.ts +2 -0
- package/dist/cli/commands/watch.js +76 -0
- package/dist/cli/commands/watch.js.map +1 -0
- package/dist/cli/format.d.ts +74 -0
- package/dist/cli/format.js +242 -0
- package/dist/cli/format.js.map +1 -0
- package/dist/cli/gmux-render.d.ts +11 -0
- package/dist/cli/gmux-render.js +60 -0
- package/dist/cli/gmux-render.js.map +1 -0
- package/dist/cli/main.d.ts +8 -0
- package/dist/cli/main.js +145 -0
- package/dist/cli/main.js.map +1 -0
- package/dist/cli/overlay-ask.d.ts +13 -0
- package/dist/cli/overlay-ask.js +32 -0
- package/dist/cli/overlay-ask.js.map +1 -0
- package/dist/cli/overlay.d.ts +26 -0
- package/dist/cli/overlay.js +149 -0
- package/dist/cli/overlay.js.map +1 -0
- package/dist/cli/picker.d.ts +308 -0
- package/dist/cli/picker.js +642 -0
- package/dist/cli/picker.js.map +1 -0
- package/dist/cli/preview.d.ts +87 -0
- package/dist/cli/preview.js +292 -0
- package/dist/cli/preview.js.map +1 -0
- package/dist/cli/tmux-label.d.ts +50 -0
- package/dist/cli/tmux-label.js +146 -0
- package/dist/cli/tmux-label.js.map +1 -0
- package/dist/core/errors.d.ts +54 -0
- package/dist/core/errors.js +91 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/fingerprint.d.ts +21 -0
- package/dist/core/fingerprint.js +59 -0
- package/dist/core/fingerprint.js.map +1 -0
- package/dist/core/gmux-types.d.ts +102 -0
- package/dist/core/gmux-types.js +13 -0
- package/dist/core/gmux-types.js.map +1 -0
- package/dist/core/pane-state.d.ts +5 -0
- package/dist/core/pane-state.js +15 -0
- package/dist/core/pane-state.js.map +1 -0
- package/dist/core/paths.d.ts +68 -0
- package/dist/core/paths.js +106 -0
- package/dist/core/paths.js.map +1 -0
- package/dist/core/proc-tree.d.ts +9 -0
- package/dist/core/proc-tree.js +33 -0
- package/dist/core/proc-tree.js.map +1 -0
- package/dist/core/text.d.ts +34 -0
- package/dist/core/text.js +126 -0
- package/dist/core/text.js.map +1 -0
- package/dist/core/types.d.ts +322 -0
- package/dist/core/types.js +10 -0
- package/dist/core/types.js.map +1 -0
- package/dist/services/ask-transcript.d.ts +256 -0
- package/dist/services/ask-transcript.js +544 -0
- package/dist/services/ask-transcript.js.map +1 -0
- package/dist/services/ask.d.ts +54 -0
- package/dist/services/ask.js +161 -0
- package/dist/services/ask.js.map +1 -0
- package/dist/services/auto-summarize.d.ts +188 -0
- package/dist/services/auto-summarize.js +415 -0
- package/dist/services/auto-summarize.js.map +1 -0
- package/dist/services/concurrency.d.ts +2 -0
- package/dist/services/concurrency.js +16 -0
- package/dist/services/concurrency.js.map +1 -0
- package/dist/services/config.d.ts +131 -0
- package/dist/services/config.js +325 -0
- package/dist/services/config.js.map +1 -0
- package/dist/services/daemon-client.d.ts +9 -0
- package/dist/services/daemon-client.js +34 -0
- package/dist/services/daemon-client.js.map +1 -0
- package/dist/services/daemon-socket.d.ts +30 -0
- package/dist/services/daemon-socket.js +76 -0
- package/dist/services/daemon-socket.js.map +1 -0
- package/dist/services/daemon.d.ts +43 -0
- package/dist/services/daemon.js +106 -0
- package/dist/services/daemon.js.map +1 -0
- package/dist/services/distill.d.ts +39 -0
- package/dist/services/distill.js +93 -0
- package/dist/services/distill.js.map +1 -0
- package/dist/services/guardian.d.ts +26 -0
- package/dist/services/guardian.js +71 -0
- package/dist/services/guardian.js.map +1 -0
- package/dist/services/index-store.d.ts +36 -0
- package/dist/services/index-store.js +125 -0
- package/dist/services/index-store.js.map +1 -0
- package/dist/services/log-rotation.d.ts +3 -0
- package/dist/services/log-rotation.js +28 -0
- package/dist/services/log-rotation.js.map +1 -0
- package/dist/services/pane-links.d.ts +10 -0
- package/dist/services/pane-links.js +47 -0
- package/dist/services/pane-links.js.map +1 -0
- package/dist/services/pane-process.d.ts +95 -0
- package/dist/services/pane-process.js +183 -0
- package/dist/services/pane-process.js.map +1 -0
- package/dist/services/pane-registry.d.ts +24 -0
- package/dist/services/pane-registry.js +40 -0
- package/dist/services/pane-registry.js.map +1 -0
- package/dist/services/provider-process.d.ts +37 -0
- package/dist/services/provider-process.js +105 -0
- package/dist/services/provider-process.js.map +1 -0
- package/dist/services/providers.d.ts +76 -0
- package/dist/services/providers.js +104 -0
- package/dist/services/providers.js.map +1 -0
- package/dist/services/resolve.d.ts +3 -0
- package/dist/services/resolve.js +18 -0
- package/dist/services/resolve.js.map +1 -0
- package/dist/services/resources.d.ts +17 -0
- package/dist/services/resources.js +113 -0
- package/dist/services/resources.js.map +1 -0
- package/dist/services/search.d.ts +29 -0
- package/dist/services/search.js +135 -0
- package/dist/services/search.js.map +1 -0
- package/dist/services/semantic-gate.d.ts +13 -0
- package/dist/services/semantic-gate.js +23 -0
- package/dist/services/semantic-gate.js.map +1 -0
- package/dist/services/semantic.d.ts +113 -0
- package/dist/services/semantic.js +216 -0
- package/dist/services/semantic.js.map +1 -0
- package/dist/services/sensors.d.ts +92 -0
- package/dist/services/sensors.js +246 -0
- package/dist/services/sensors.js.map +1 -0
- package/dist/services/summarize.d.ts +84 -0
- package/dist/services/summarize.js +230 -0
- package/dist/services/summarize.js.map +1 -0
- package/dist/services/tmux-gateway.d.ts +17 -0
- package/dist/services/tmux-gateway.js +10 -0
- package/dist/services/tmux-gateway.js.map +1 -0
- package/dist/services/tmux-resolve.d.ts +54 -0
- package/dist/services/tmux-resolve.js +0 -0
- package/dist/services/tmux-resolve.js.map +1 -0
- package/dist/services/tmux.d.ts +32 -0
- package/dist/services/tmux.js +107 -0
- package/dist/services/tmux.js.map +1 -0
- package/dist/services/views.d.ts +7 -0
- package/dist/services/views.js +18 -0
- package/dist/services/views.js.map +1 -0
- package/dist/services/watch.d.ts +36 -0
- package/dist/services/watch.js +98 -0
- package/dist/services/watch.js.map +1 -0
- package/dist/services/workspace.d.ts +19 -0
- package/dist/services/workspace.js +88 -0
- package/dist/services/workspace.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error taxonomy.
|
|
3
|
+
*
|
|
4
|
+
* Harness-engineering rule: an error message carries the fix inline. A user —
|
|
5
|
+
* or an agent — should never have to guess the next command. `fix` is printed
|
|
6
|
+
* directly beneath the message and included in `--json` output.
|
|
7
|
+
*/
|
|
8
|
+
export class GmuxError extends Error {
|
|
9
|
+
/** The exact command or action that resolves this error. */
|
|
10
|
+
fix;
|
|
11
|
+
/** Process exit code. */
|
|
12
|
+
exitCode;
|
|
13
|
+
constructor(message, options = {}) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "GmuxError";
|
|
16
|
+
this.fix = options.fix;
|
|
17
|
+
this.exitCode = options.exitCode ?? 1;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** No session matched the given id or prefix. */
|
|
21
|
+
export class SessionNotFoundError extends GmuxError {
|
|
22
|
+
constructor(id) {
|
|
23
|
+
super(`No session matches "${id}".`, {
|
|
24
|
+
fix: "Run `gmux ls` to see recent sessions, or `gmux index --rebuild` if the cache is stale.",
|
|
25
|
+
exitCode: 4,
|
|
26
|
+
});
|
|
27
|
+
this.name = "SessionNotFoundError";
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** A prefix matched more than one session. */
|
|
31
|
+
export class AmbiguousSessionError extends GmuxError {
|
|
32
|
+
constructor(id, matches) {
|
|
33
|
+
const shown = matches.slice(0, 5).join(", ");
|
|
34
|
+
super(`"${id}" matches ${matches.length} sessions: ${shown}${matches.length > 5 ? ", …" : ""}`, {
|
|
35
|
+
fix: "Pass more characters of the session id to disambiguate.",
|
|
36
|
+
exitCode: 5,
|
|
37
|
+
});
|
|
38
|
+
this.name = "AmbiguousSessionError";
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** A required external binary is missing. */
|
|
42
|
+
export class MissingDependencyError extends GmuxError {
|
|
43
|
+
constructor(binary, fix) {
|
|
44
|
+
super(`Required command "${binary}" was not found on PATH.`, { fix, exitCode: 6 });
|
|
45
|
+
this.name = "MissingDependencyError";
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/** A summary provider returned something unusable. */
|
|
49
|
+
export class SummaryProviderError extends GmuxError {
|
|
50
|
+
constructor(provider, detail) {
|
|
51
|
+
super(`Summary provider "${provider}" failed: ${detail}`, {
|
|
52
|
+
fix: "Check the provider CLI works standalone, or run `gmux setup` to choose another.",
|
|
53
|
+
exitCode: 7,
|
|
54
|
+
});
|
|
55
|
+
this.name = "SummaryProviderError";
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* The chat provider behind `gmux ask` failed or said nothing.
|
|
60
|
+
*
|
|
61
|
+
* The fix names the provider that actually failed. It used to hardcode
|
|
62
|
+
* `claude -p`, which told a user who had configured Codex to go and test a
|
|
63
|
+
* binary they may not even have — non-negotiable #5 asks for the fix to the
|
|
64
|
+
* problem in front of you, not to the common case.
|
|
65
|
+
*/
|
|
66
|
+
export class AskProviderError extends GmuxError {
|
|
67
|
+
constructor(provider, detail) {
|
|
68
|
+
super(`Ask provider "${provider}" failed: ${detail}`, {
|
|
69
|
+
fix: `Check it works standalone: \`echo hi | ${provider}\`. Or run \`gmux setup\` to choose another.`,
|
|
70
|
+
exitCode: 7,
|
|
71
|
+
});
|
|
72
|
+
this.name = "AskProviderError";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* No provider is configured — because the user chose "none" in `gmux setup`.
|
|
77
|
+
*
|
|
78
|
+
* Distinct from a missing binary, and it must stay distinct: this is a choice
|
|
79
|
+
* being honored, not a fault. The fix says how to change your mind, not how to
|
|
80
|
+
* install something.
|
|
81
|
+
*/
|
|
82
|
+
export class NoProviderError extends GmuxError {
|
|
83
|
+
constructor(what) {
|
|
84
|
+
super(`${what} needs a model provider, and this machine is configured to make no model calls.`, {
|
|
85
|
+
fix: "Run `gmux setup` to choose one, or set GMUX_SUMMARY_CMD for a one-off.",
|
|
86
|
+
exitCode: 8,
|
|
87
|
+
});
|
|
88
|
+
this.name = "NoProviderError";
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,4DAA4D;IACnD,GAAG,CAAqB;IACjC,yBAAyB;IAChB,QAAQ,CAAS;IAE1B,YAAY,OAAe,EAAE,UAA+C,EAAE;QAC5E,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC;QACxB,IAAI,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IACxC,CAAC;CACF;AAED,iDAAiD;AACjD,MAAM,OAAO,oBAAqB,SAAQ,SAAS;IACjD,YAAY,EAAU;QACpB,KAAK,CAAC,uBAAuB,EAAE,IAAI,EAAE;YACnC,GAAG,EAAE,wFAAwF;YAC7F,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,8CAA8C;AAC9C,MAAM,OAAO,qBAAsB,SAAQ,SAAS;IAClD,YAAY,EAAU,EAAE,OAAiB;QACvC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,KAAK,CAAC,IAAI,EAAE,aAAa,OAAO,CAAC,MAAM,cAAc,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE;YAC9F,GAAG,EAAE,yDAAyD;YAC9D,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,6CAA6C;AAC7C,MAAM,OAAO,sBAAuB,SAAQ,SAAS;IACnD,YAAY,MAAc,EAAE,GAAW;QACrC,KAAK,CAAC,qBAAqB,MAAM,0BAA0B,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,sDAAsD;AACtD,MAAM,OAAO,oBAAqB,SAAQ,SAAS;IACjD,YAAY,QAAgB,EAAE,MAAc;QAC1C,KAAK,CAAC,qBAAqB,QAAQ,aAAa,MAAM,EAAE,EAAE;YACxD,GAAG,EAAE,iFAAiF;YACtF,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IAC7C,YAAY,QAAgB,EAAE,MAAc;QAC1C,KAAK,CAAC,iBAAiB,QAAQ,aAAa,MAAM,EAAE,EAAE;YACpD,GAAG,EAAE,0CAA0C,QAAQ,8CAA8C;YACrG,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;IACjC,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,OAAO,eAAgB,SAAQ,SAAS;IAC5C,YAAY,IAAY;QACtB,KAAK,CAAC,GAAG,IAAI,iFAAiF,EAAE;YAC9F,GAAG,EAAE,wEAAwE;YAC7E,QAAQ,EAAE,CAAC;SACZ,CAAC,CAAC;QACH,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A compact similarity fingerprint, for deciding whether a session has changed
|
|
3
|
+
* *enough* to re-summarise — not merely *at all*.
|
|
4
|
+
*
|
|
5
|
+
* SimHash reduces a document to a 64-bit value where similar text yields similar
|
|
6
|
+
* bits, so the Hamming distance between two fingerprints tracks how much the
|
|
7
|
+
* content moved. It's 16 hex characters no matter how long the session gets —
|
|
8
|
+
* which is the whole point: fixed, tiny metadata for an ever-growing transcript.
|
|
9
|
+
*
|
|
10
|
+
* `core` imports nothing internal; this is pure and deterministic.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* The 64-bit SimHash of `text`, as 16 lowercase hex characters.
|
|
14
|
+
*
|
|
15
|
+
* Each token votes on every bit (+1 if its hash has the bit set, −1 otherwise);
|
|
16
|
+
* the final bit is set when its column of votes is positive. Empty text is all
|
|
17
|
+
* zeros — a defined value the distance can compare against.
|
|
18
|
+
*/
|
|
19
|
+
export declare function simhash64(text: string): string;
|
|
20
|
+
/** The number of differing bits between two hex fingerprints. */
|
|
21
|
+
export declare function hammingDistance(a: string, b: string): number;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A compact similarity fingerprint, for deciding whether a session has changed
|
|
3
|
+
* *enough* to re-summarise — not merely *at all*.
|
|
4
|
+
*
|
|
5
|
+
* SimHash reduces a document to a 64-bit value where similar text yields similar
|
|
6
|
+
* bits, so the Hamming distance between two fingerprints tracks how much the
|
|
7
|
+
* content moved. It's 16 hex characters no matter how long the session gets —
|
|
8
|
+
* which is the whole point: fixed, tiny metadata for an ever-growing transcript.
|
|
9
|
+
*
|
|
10
|
+
* `core` imports nothing internal; this is pure and deterministic.
|
|
11
|
+
*/
|
|
12
|
+
const MASK64 = (1n << 64n) - 1n;
|
|
13
|
+
const FNV_OFFSET = 14695981039346656037n;
|
|
14
|
+
const FNV_PRIME = 1099511628211n;
|
|
15
|
+
/** FNV-1a over the bytes of a token → a 64-bit value. Deterministic, no deps. */
|
|
16
|
+
function hashToken(token) {
|
|
17
|
+
let hash = FNV_OFFSET;
|
|
18
|
+
for (let i = 0; i < token.length; i++) {
|
|
19
|
+
hash ^= BigInt(token.charCodeAt(i) & 0xff);
|
|
20
|
+
hash = (hash * FNV_PRIME) & MASK64;
|
|
21
|
+
}
|
|
22
|
+
return hash;
|
|
23
|
+
}
|
|
24
|
+
function tokenize(text) {
|
|
25
|
+
return text.toLowerCase().match(/[a-z0-9]+/g) ?? [];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The 64-bit SimHash of `text`, as 16 lowercase hex characters.
|
|
29
|
+
*
|
|
30
|
+
* Each token votes on every bit (+1 if its hash has the bit set, −1 otherwise);
|
|
31
|
+
* the final bit is set when its column of votes is positive. Empty text is all
|
|
32
|
+
* zeros — a defined value the distance can compare against.
|
|
33
|
+
*/
|
|
34
|
+
export function simhash64(text) {
|
|
35
|
+
const votes = new Array(64).fill(0);
|
|
36
|
+
for (const token of tokenize(text)) {
|
|
37
|
+
const h = hashToken(token);
|
|
38
|
+
for (let bit = 0; bit < 64; bit++) {
|
|
39
|
+
votes[bit] += (h >> BigInt(bit)) & 1n ? 1 : -1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
let fingerprint = 0n;
|
|
43
|
+
for (let bit = 0; bit < 64; bit++) {
|
|
44
|
+
if (votes[bit] > 0)
|
|
45
|
+
fingerprint |= 1n << BigInt(bit);
|
|
46
|
+
}
|
|
47
|
+
return fingerprint.toString(16).padStart(16, "0");
|
|
48
|
+
}
|
|
49
|
+
/** The number of differing bits between two hex fingerprints. */
|
|
50
|
+
export function hammingDistance(a, b) {
|
|
51
|
+
let xor = (BigInt(`0x${a}`) ^ BigInt(`0x${b}`)) & MASK64;
|
|
52
|
+
let count = 0;
|
|
53
|
+
while (xor > 0n) {
|
|
54
|
+
count += Number(xor & 1n);
|
|
55
|
+
xor >>= 1n;
|
|
56
|
+
}
|
|
57
|
+
return count;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/core/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,MAAM,MAAM,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;AAChC,MAAM,UAAU,GAAG,qBAAqB,CAAC;AACzC,MAAM,SAAS,GAAG,cAAc,CAAC;AAEjC,iFAAiF;AACjF,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,IAAI,GAAG,UAAU,CAAC;IACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QAC3C,IAAI,GAAG,CAAC,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAAC;IACrC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;AACtD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAS,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC5C,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QAC3B,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;YAClC,KAAK,CAAC,GAAG,CAAE,IAAI,CAAC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IACD,IAAI,WAAW,GAAG,EAAE,CAAC;IACrB,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC;QAClC,IAAI,KAAK,CAAC,GAAG,CAAE,GAAG,CAAC;YAAE,WAAW,IAAI,EAAE,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;AACpD,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,eAAe,CAAC,CAAS,EAAE,CAAS;IAClD,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC;IACzD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,OAAO,GAAG,GAAG,EAAE,EAAE,CAAC;QAChB,KAAK,IAAI,MAAM,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC;QAC1B,GAAG,KAAK,EAAE,CAAC;IACb,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import type { HarnessId } from "./types.js";
|
|
2
|
+
/** The five triage-critical pane states, ordered least→most attention-worthy for display. */
|
|
3
|
+
export declare const PANE_STATES: readonly ["working", "idle", "waiting", "error", "done"];
|
|
4
|
+
export type PaneState = (typeof PANE_STATES)[number];
|
|
5
|
+
export declare function isPaneState(value: string): value is PaneState;
|
|
6
|
+
/** A uniform reading from a sensor, regardless of source. */
|
|
7
|
+
export interface Observation {
|
|
8
|
+
paneId: string;
|
|
9
|
+
kind: "agent" | "terminal";
|
|
10
|
+
/** ms epoch when this observation was taken. */
|
|
11
|
+
ts: number;
|
|
12
|
+
/** Latest slice of lines (new transcript lines, or pipe-pane/capture tail). */
|
|
13
|
+
tailLines: string[];
|
|
14
|
+
/** ms epoch of the last content change seen for this pane (0 if never). */
|
|
15
|
+
lastActivityTs: number;
|
|
16
|
+
/** True when the agent transcript's final turn awaits human input (agent panes only). */
|
|
17
|
+
awaitingInput?: boolean;
|
|
18
|
+
/** True when the latest slice shows a tool/command failure. */
|
|
19
|
+
sawError?: boolean;
|
|
20
|
+
/** True when the agent transcript indicates the task ended/finished. */
|
|
21
|
+
ended?: boolean;
|
|
22
|
+
}
|
|
23
|
+
/** The human-readable "what it's doing" layer. */
|
|
24
|
+
export interface PaneSemantics {
|
|
25
|
+
label: string;
|
|
26
|
+
card: string | null;
|
|
27
|
+
/** SimHash of the source text the label was written from. */
|
|
28
|
+
fingerprint: string;
|
|
29
|
+
updatedAt: number;
|
|
30
|
+
stale: boolean;
|
|
31
|
+
}
|
|
32
|
+
/** Per-pane memory attribution. */
|
|
33
|
+
export interface PaneResources {
|
|
34
|
+
/** Subtree RSS sum in bytes. Reliable for ranking, not exact totals. */
|
|
35
|
+
perPaneRss: number;
|
|
36
|
+
ts: number;
|
|
37
|
+
}
|
|
38
|
+
/** Durable identity of a pane in the workspace. */
|
|
39
|
+
export interface PaneIdentity {
|
|
40
|
+
paneId: string;
|
|
41
|
+
windowId: string | null;
|
|
42
|
+
active: boolean;
|
|
43
|
+
harness: HarnessId | null;
|
|
44
|
+
sessionId: string | null;
|
|
45
|
+
cwd: string;
|
|
46
|
+
command: string;
|
|
47
|
+
pid: number;
|
|
48
|
+
}
|
|
49
|
+
/** One pane's complete state in the model. */
|
|
50
|
+
export interface PaneEntry {
|
|
51
|
+
identity: PaneIdentity;
|
|
52
|
+
state: PaneState;
|
|
53
|
+
semantics: PaneSemantics | null;
|
|
54
|
+
resources: PaneResources | null;
|
|
55
|
+
/** ms epoch of last observed activity. */
|
|
56
|
+
lastActivityTs: number;
|
|
57
|
+
/** ms epoch of last update to this entry. */
|
|
58
|
+
ts: number;
|
|
59
|
+
/** Marked true when the pane vanished; evicted next tick. */
|
|
60
|
+
gone: boolean;
|
|
61
|
+
}
|
|
62
|
+
/** Host-level memory pressure — the guardian's trigger. Not the sum of panes. */
|
|
63
|
+
export interface HostPressure {
|
|
64
|
+
/** Used fraction 0..1 (excludes reclaimable cache where the OS distinguishes). */
|
|
65
|
+
usedRatio: number;
|
|
66
|
+
/** Bytes not attributed to any tracked pane subtree. */
|
|
67
|
+
unattributed: number;
|
|
68
|
+
ts: number;
|
|
69
|
+
}
|
|
70
|
+
/** One guardian action, logged to the model. */
|
|
71
|
+
export interface GuardianLogEntry {
|
|
72
|
+
ts: number;
|
|
73
|
+
/** Host used fraction at fire time. */
|
|
74
|
+
pressure: number;
|
|
75
|
+
culpritPaneId: string | null;
|
|
76
|
+
/** Human label of the top consumer, or "source outside tracked panes". */
|
|
77
|
+
culpritLabel: string;
|
|
78
|
+
action: "broadcast" | "notify" | "log-only";
|
|
79
|
+
message: string;
|
|
80
|
+
}
|
|
81
|
+
/** Guardian autonomy policy. */
|
|
82
|
+
export type GuardianPolicy = "off" | "notify" | "auto";
|
|
83
|
+
/** The gmux config block, persisted under GmConfig. */
|
|
84
|
+
export interface GmuxConfig {
|
|
85
|
+
guardianPolicy: GuardianPolicy;
|
|
86
|
+
/** Host used fraction that trips the guardian, 0..1. */
|
|
87
|
+
memoryThreshold: number;
|
|
88
|
+
/** Minimum seconds between guardian fires. */
|
|
89
|
+
cooldownSeconds: number;
|
|
90
|
+
/** Daemon tick interval in ms. */
|
|
91
|
+
tickMs: number;
|
|
92
|
+
}
|
|
93
|
+
/** The serializable model handed to surfaces over the socket / snapshot file. */
|
|
94
|
+
export interface WorkspaceSnapshot {
|
|
95
|
+
version: number;
|
|
96
|
+
updatedAt: number;
|
|
97
|
+
panes: PaneEntry[];
|
|
98
|
+
hostPressure: HostPressure | null;
|
|
99
|
+
guardianLog: GuardianLogEntry[];
|
|
100
|
+
}
|
|
101
|
+
/** Defaults for a fresh install. */
|
|
102
|
+
export declare const DEFAULT_GMUX_CONFIG: GmuxConfig;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** The five triage-critical pane states, ordered least→most attention-worthy for display. */
|
|
2
|
+
export const PANE_STATES = ["working", "idle", "waiting", "error", "done"];
|
|
3
|
+
export function isPaneState(value) {
|
|
4
|
+
return PANE_STATES.includes(value);
|
|
5
|
+
}
|
|
6
|
+
/** Defaults for a fresh install. */
|
|
7
|
+
export const DEFAULT_GMUX_CONFIG = {
|
|
8
|
+
guardianPolicy: "auto",
|
|
9
|
+
memoryThreshold: 0.9,
|
|
10
|
+
cooldownSeconds: 300,
|
|
11
|
+
tickMs: 1500,
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=gmux-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gmux-types.js","sourceRoot":"","sources":["../../src/core/gmux-types.ts"],"names":[],"mappings":"AAEA,6FAA6F;AAC7F,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAU,CAAC;AAGpF,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,OAAQ,WAAiC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AA2GD,oCAAoC;AACpC,MAAM,CAAC,MAAM,mBAAmB,GAAe;IAC7C,cAAc,EAAE,MAAM;IACtB,eAAe,EAAE,GAAG;IACpB,eAAe,EAAE,GAAG;IACpB,MAAM,EAAE,IAAI;CACb,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Observation, PaneState } from "./gmux-types.js";
|
|
2
|
+
/** ms of quiet after which a pane is no longer "working". */
|
|
3
|
+
export declare const WORKING_WINDOW_MS = 10000;
|
|
4
|
+
/** Pure heuristic: latest observation → triage state. Deterministic; no I/O. */
|
|
5
|
+
export declare function classifyState(obs: Observation, now: number): PaneState;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** ms of quiet after which a pane is no longer "working". */
|
|
2
|
+
export const WORKING_WINDOW_MS = 10_000;
|
|
3
|
+
/** Pure heuristic: latest observation → triage state. Deterministic; no I/O. */
|
|
4
|
+
export function classifyState(obs, now) {
|
|
5
|
+
if (obs.sawError)
|
|
6
|
+
return "error";
|
|
7
|
+
if (obs.ended)
|
|
8
|
+
return "done";
|
|
9
|
+
if (obs.awaitingInput)
|
|
10
|
+
return "waiting";
|
|
11
|
+
if (now - obs.lastActivityTs < WORKING_WINDOW_MS)
|
|
12
|
+
return "working";
|
|
13
|
+
return "idle";
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=pane-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pane-state.js","sourceRoot":"","sources":["../../src/core/pane-state.ts"],"names":[],"mappings":"AAEA,6DAA6D;AAC7D,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAExC,gFAAgF;AAChF,MAAM,UAAU,aAAa,CAAC,GAAgB,EAAE,GAAW;IACzD,IAAI,GAAG,CAAC,QAAQ;QAAE,OAAO,OAAO,CAAC;IACjC,IAAI,GAAG,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IAC7B,IAAI,GAAG,CAAC,aAAa;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,GAAG,GAAG,GAAG,CAAC,cAAc,GAAG,iBAAiB;QAAE,OAAO,SAAS,CAAC;IACnE,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where gmux keeps its own state. It never writes anywhere else.
|
|
3
|
+
*
|
|
4
|
+
* Two directories and one narrow third category, and the split matters:
|
|
5
|
+
*
|
|
6
|
+
* - `cacheDir()` — derived data. Keyed by content hash, thrown away safely.
|
|
7
|
+
* - `configDir()` — what a human chose. `rm -rf` the cache and you should lose
|
|
8
|
+
* summaries, not your provider. Anything a person typed belongs here.
|
|
9
|
+
* - **Ephemeral IPC** — a scratch buffer one live process writes and its own
|
|
10
|
+
* children read, dead the moment that process is, never read by a later run,
|
|
11
|
+
* safe to `rm` at any instant. It lives under `cacheDir()` *even though it
|
|
12
|
+
* holds typed text*, because "disposable" is what the cache means and this is
|
|
13
|
+
* disposable by construction. `askTranscriptDir()` is its ONLY member. The
|
|
14
|
+
* category is named here and in AGENTS.md #1 rather than left as a habit,
|
|
15
|
+
* because a rule with an unwritten exception is a rule the next person
|
|
16
|
+
* "fixes".
|
|
17
|
+
*/
|
|
18
|
+
/** Root of gmux's config. Honors XDG_CONFIG_HOME. */
|
|
19
|
+
export declare function configDir(): string;
|
|
20
|
+
/** The one config file: provider choice and background-summary opt-in. */
|
|
21
|
+
export declare function configPath(): string;
|
|
22
|
+
/** Root of gmux's cache. Honors XDG_CACHE_HOME. */
|
|
23
|
+
export declare function cacheDir(): string;
|
|
24
|
+
/** The parsed-session index. */
|
|
25
|
+
export declare function indexPath(): string;
|
|
26
|
+
/** Directory of generated summaries, one JSON file per session. */
|
|
27
|
+
export declare function summaryDir(): string;
|
|
28
|
+
export declare function summaryPath(harness: string, sessionId: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* The pane→session links written by `gmux run`. Cache, not config: keyed by tmux
|
|
31
|
+
* pane ids that die with the server, disposable, regenerated by living in the
|
|
32
|
+
* tool. Worst case of deleting it: a pane falls back to the cwd heuristic.
|
|
33
|
+
*/
|
|
34
|
+
export declare function paneLinksPath(): string;
|
|
35
|
+
/**
|
|
36
|
+
* The picker's chat threads — one per live `gmux pick`, gone when it exits.
|
|
37
|
+
*
|
|
38
|
+
* The ephemeral-IPC category above, and its only member. Not `configDir()`: the
|
|
39
|
+
* thread dies with the picker, and config implies a retention policy nobody has
|
|
40
|
+
* written. Not `os.tmpdir()`: this module never writes outside gmux's two roots,
|
|
41
|
+
* `XDG_CACHE_HOME` is how the test suite redirects those writes, and a tmp
|
|
42
|
+
* reaper is free to delete a file mid-append.
|
|
43
|
+
*
|
|
44
|
+
* Its own subdirectory, so the orphan sweep is a `readdir` of a directory that
|
|
45
|
+
* holds nothing but transcripts and cannot mistake `index.json` for one.
|
|
46
|
+
*/
|
|
47
|
+
export declare function askTranscriptDir(): string;
|
|
48
|
+
/**
|
|
49
|
+
* `runId` is `<pid>-<rand8>`: the random half makes concurrent pickers
|
|
50
|
+
* collision-free, the pid half makes reaping a `readdir` plus a
|
|
51
|
+
* `process.kill(pid, 0)` with zero file reads.
|
|
52
|
+
*/
|
|
53
|
+
export declare function askTranscriptPath(runId: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* Home directory, overridable via GMUX_HOME so tests can point the
|
|
56
|
+
* adapters at fixture trees instead of the real one.
|
|
57
|
+
*/
|
|
58
|
+
export declare function harnessHome(): string;
|
|
59
|
+
/** Root of gmux's ephemeral daemon state (cache: dies with the tmux server). */
|
|
60
|
+
export declare function gmuxDir(): string;
|
|
61
|
+
/** Unix socket surfaces connect to for live model subscription. */
|
|
62
|
+
export declare function gmuxSocketPath(): string;
|
|
63
|
+
/** Snapshot file written every tick; the fallback when the daemon is down. */
|
|
64
|
+
export declare function gmuxSnapshotPath(): string;
|
|
65
|
+
/** Directory of per-pane pipe-pane logs (non-agent tail). */
|
|
66
|
+
export declare function paneLogDir(): string;
|
|
67
|
+
/** One pane's pipe-pane log. `%3` → `pane-3.log` (tmux ids carry a `%`). */
|
|
68
|
+
export declare function paneLogPath(paneId: string): string;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where gmux keeps its own state. It never writes anywhere else.
|
|
3
|
+
*
|
|
4
|
+
* Two directories and one narrow third category, and the split matters:
|
|
5
|
+
*
|
|
6
|
+
* - `cacheDir()` — derived data. Keyed by content hash, thrown away safely.
|
|
7
|
+
* - `configDir()` — what a human chose. `rm -rf` the cache and you should lose
|
|
8
|
+
* summaries, not your provider. Anything a person typed belongs here.
|
|
9
|
+
* - **Ephemeral IPC** — a scratch buffer one live process writes and its own
|
|
10
|
+
* children read, dead the moment that process is, never read by a later run,
|
|
11
|
+
* safe to `rm` at any instant. It lives under `cacheDir()` *even though it
|
|
12
|
+
* holds typed text*, because "disposable" is what the cache means and this is
|
|
13
|
+
* disposable by construction. `askTranscriptDir()` is its ONLY member. The
|
|
14
|
+
* category is named here and in AGENTS.md #1 rather than left as a habit,
|
|
15
|
+
* because a rule with an unwritten exception is a rule the next person
|
|
16
|
+
* "fixes".
|
|
17
|
+
*/
|
|
18
|
+
import { homedir } from "node:os";
|
|
19
|
+
import { join } from "node:path";
|
|
20
|
+
/** Root of gmux's config. Honors XDG_CONFIG_HOME. */
|
|
21
|
+
export function configDir() {
|
|
22
|
+
const xdg = process.env.XDG_CONFIG_HOME;
|
|
23
|
+
const base = xdg && xdg.trim() !== "" ? xdg : join(homedir(), ".config");
|
|
24
|
+
return join(base, "gmux");
|
|
25
|
+
}
|
|
26
|
+
/** The one config file: provider choice and background-summary opt-in. */
|
|
27
|
+
export function configPath() {
|
|
28
|
+
return join(configDir(), "config.json");
|
|
29
|
+
}
|
|
30
|
+
/** Root of gmux's cache. Honors XDG_CACHE_HOME. */
|
|
31
|
+
export function cacheDir() {
|
|
32
|
+
const xdg = process.env.XDG_CACHE_HOME;
|
|
33
|
+
const base = xdg && xdg.trim() !== "" ? xdg : join(homedir(), ".cache");
|
|
34
|
+
return join(base, "gmux");
|
|
35
|
+
}
|
|
36
|
+
/** The parsed-session index. */
|
|
37
|
+
export function indexPath() {
|
|
38
|
+
return join(cacheDir(), "index.json");
|
|
39
|
+
}
|
|
40
|
+
/** Directory of generated summaries, one JSON file per session. */
|
|
41
|
+
export function summaryDir() {
|
|
42
|
+
return join(cacheDir(), "summaries");
|
|
43
|
+
}
|
|
44
|
+
export function summaryPath(harness, sessionId) {
|
|
45
|
+
return join(summaryDir(), `${harness}-${sessionId}.json`);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The pane→session links written by `gmux run`. Cache, not config: keyed by tmux
|
|
49
|
+
* pane ids that die with the server, disposable, regenerated by living in the
|
|
50
|
+
* tool. Worst case of deleting it: a pane falls back to the cwd heuristic.
|
|
51
|
+
*/
|
|
52
|
+
export function paneLinksPath() {
|
|
53
|
+
return join(cacheDir(), "pane-links.json");
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The picker's chat threads — one per live `gmux pick`, gone when it exits.
|
|
57
|
+
*
|
|
58
|
+
* The ephemeral-IPC category above, and its only member. Not `configDir()`: the
|
|
59
|
+
* thread dies with the picker, and config implies a retention policy nobody has
|
|
60
|
+
* written. Not `os.tmpdir()`: this module never writes outside gmux's two roots,
|
|
61
|
+
* `XDG_CACHE_HOME` is how the test suite redirects those writes, and a tmp
|
|
62
|
+
* reaper is free to delete a file mid-append.
|
|
63
|
+
*
|
|
64
|
+
* Its own subdirectory, so the orphan sweep is a `readdir` of a directory that
|
|
65
|
+
* holds nothing but transcripts and cannot mistake `index.json` for one.
|
|
66
|
+
*/
|
|
67
|
+
export function askTranscriptDir() {
|
|
68
|
+
return join(cacheDir(), "ask");
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* `runId` is `<pid>-<rand8>`: the random half makes concurrent pickers
|
|
72
|
+
* collision-free, the pid half makes reaping a `readdir` plus a
|
|
73
|
+
* `process.kill(pid, 0)` with zero file reads.
|
|
74
|
+
*/
|
|
75
|
+
export function askTranscriptPath(runId) {
|
|
76
|
+
return join(askTranscriptDir(), `${runId}.jsonl`);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Home directory, overridable via GMUX_HOME so tests can point the
|
|
80
|
+
* adapters at fixture trees instead of the real one.
|
|
81
|
+
*/
|
|
82
|
+
export function harnessHome() {
|
|
83
|
+
const override = process.env.GMUX_HOME;
|
|
84
|
+
return override && override.trim() !== "" ? override : homedir();
|
|
85
|
+
}
|
|
86
|
+
/** Root of gmux's ephemeral daemon state (cache: dies with the tmux server). */
|
|
87
|
+
export function gmuxDir() {
|
|
88
|
+
return join(cacheDir(), "gmux");
|
|
89
|
+
}
|
|
90
|
+
/** Unix socket surfaces connect to for live model subscription. */
|
|
91
|
+
export function gmuxSocketPath() {
|
|
92
|
+
return join(gmuxDir(), "daemon.sock");
|
|
93
|
+
}
|
|
94
|
+
/** Snapshot file written every tick; the fallback when the daemon is down. */
|
|
95
|
+
export function gmuxSnapshotPath() {
|
|
96
|
+
return join(gmuxDir(), "snapshot.json");
|
|
97
|
+
}
|
|
98
|
+
/** Directory of per-pane pipe-pane logs (non-agent tail). */
|
|
99
|
+
export function paneLogDir() {
|
|
100
|
+
return join(gmuxDir(), "panes");
|
|
101
|
+
}
|
|
102
|
+
/** One pane's pipe-pane log. `%3` → `pane-3.log` (tmux ids carry a `%`). */
|
|
103
|
+
export function paneLogPath(paneId) {
|
|
104
|
+
return join(paneLogDir(), `pane-${paneId.replace(/^%/, "")}.log`);
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/core/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ProcRow {
|
|
2
|
+
pid: number;
|
|
3
|
+
ppid: number;
|
|
4
|
+
rss: number;
|
|
5
|
+
comm: string;
|
|
6
|
+
}
|
|
7
|
+
/** Parse `ps -axo pid,ppid,rss,comm`. RSS is KB on macOS/Linux → convert to bytes. */
|
|
8
|
+
export declare function parsePsOutput(raw: string): ProcRow[];
|
|
9
|
+
export declare function subtreeRss(rootPid: number, rows: ProcRow[]): number;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** Parse `ps -axo pid,ppid,rss,comm`. RSS is KB on macOS/Linux → convert to bytes. */
|
|
2
|
+
export function parsePsOutput(raw) {
|
|
3
|
+
const rows = [];
|
|
4
|
+
for (const line of raw.split("\n")) {
|
|
5
|
+
const m = line.trim().match(/^(\d+)\s+(\d+)\s+(\d+)\s+(.*)$/);
|
|
6
|
+
if (!m)
|
|
7
|
+
continue; // skips the header and blanks
|
|
8
|
+
rows.push({ pid: Number(m[1]), ppid: Number(m[2]), rss: Number(m[3]) * 1024, comm: m[4].trim() });
|
|
9
|
+
}
|
|
10
|
+
return rows;
|
|
11
|
+
}
|
|
12
|
+
export function subtreeRss(rootPid, rows) {
|
|
13
|
+
const children = new Map();
|
|
14
|
+
const rss = new Map();
|
|
15
|
+
for (const r of rows) {
|
|
16
|
+
rss.set(r.pid, r.rss);
|
|
17
|
+
(children.get(r.ppid) ?? children.set(r.ppid, []).get(r.ppid)).push(r.pid);
|
|
18
|
+
}
|
|
19
|
+
let total = 0;
|
|
20
|
+
const stack = [rootPid];
|
|
21
|
+
const seen = new Set();
|
|
22
|
+
while (stack.length) {
|
|
23
|
+
const pid = stack.pop();
|
|
24
|
+
if (seen.has(pid))
|
|
25
|
+
continue;
|
|
26
|
+
seen.add(pid);
|
|
27
|
+
total += rss.get(pid) ?? 0;
|
|
28
|
+
for (const c of children.get(pid) ?? [])
|
|
29
|
+
stack.push(c);
|
|
30
|
+
}
|
|
31
|
+
return total;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=proc-tree.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proc-tree.js","sourceRoot":"","sources":["../../src/core/proc-tree.ts"],"names":[],"mappings":"AAEA,sFAAsF;AACtF,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,IAAI,GAAc,EAAE,CAAC;IAC3B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC;YAAE,SAAS,CAAC,8BAA8B;QAChD,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACrG,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,IAAe;IACzD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC7C,MAAM,GAAG,GAAG,IAAI,GAAG,EAAkB,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC;IACxB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,KAAK,CAAC,MAAM,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,EAAG,CAAC;QACzB,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,SAAS;QAC5B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3B,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Small pure string/time helpers. No I/O, no internal imports. */
|
|
2
|
+
/** Collapse whitespace and clip to `max`, appending an ellipsis when clipped. */
|
|
3
|
+
export declare function truncate(input: string, max: number): string;
|
|
4
|
+
/** Stable content hash used as a cache key. */
|
|
5
|
+
export declare function hash(input: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Compact relative age, e.g. "2h", "3d". Deliberately terse: it is a column in
|
|
8
|
+
* a list, not prose.
|
|
9
|
+
*/
|
|
10
|
+
export declare function relativeAge(iso: string, now?: Date): string;
|
|
11
|
+
/**
|
|
12
|
+
* Parse a duration like "3d", "2w", "24h" into an ISO cutoff timestamp.
|
|
13
|
+
* Returns null for unparseable input.
|
|
14
|
+
*/
|
|
15
|
+
export declare function parseSince(input: string, now?: Date): string | null;
|
|
16
|
+
/**
|
|
17
|
+
* Greedy word wrap. Returns at least one line, even for empty input, so callers
|
|
18
|
+
* can always render a row.
|
|
19
|
+
*
|
|
20
|
+
* A word longer than the width (a URL, a long path) is hard-split rather than
|
|
21
|
+
* allowed to overflow — overflowing is the bug this exists to fix.
|
|
22
|
+
*/
|
|
23
|
+
export declare function wrapText(input: string, width: number): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Single-quote for POSIX shells, escaping any embedded single quote.
|
|
26
|
+
*
|
|
27
|
+
* Lives in core because two callers need it: `gmux resume --print` emits a line
|
|
28
|
+
* meant to be pasted into a shell, and the picker's fzf reload binding is a
|
|
29
|
+
* shell command string. In both, an unquoted path with a space silently runs
|
|
30
|
+
* the wrong thing rather than failing loudly.
|
|
31
|
+
*/
|
|
32
|
+
export declare function shellQuote(value: string): string;
|
|
33
|
+
/** Pad or clip a cell to an exact display width. */
|
|
34
|
+
export declare function cell(input: string, width: number): string;
|