@indianic/dialout 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (224) hide show
  1. package/README.md +429 -16
  2. package/bin/AGENTS.md +44 -0
  3. package/bin/devdash-agent.js +2 -0
  4. package/dist/ai-adapters/claude.d.ts +3 -0
  5. package/dist/ai-adapters/claude.d.ts.map +1 -0
  6. package/dist/ai-adapters/claude.js +98 -0
  7. package/dist/ai-adapters/claude.js.map +1 -0
  8. package/dist/ai-adapters/codex.d.ts +3 -0
  9. package/dist/ai-adapters/codex.d.ts.map +1 -0
  10. package/dist/ai-adapters/codex.js +147 -0
  11. package/dist/ai-adapters/codex.js.map +1 -0
  12. package/dist/ai-adapters/grok.d.ts +3 -0
  13. package/dist/ai-adapters/grok.d.ts.map +1 -0
  14. package/dist/ai-adapters/grok.js +164 -0
  15. package/dist/ai-adapters/grok.js.map +1 -0
  16. package/dist/ai-adapters/index.d.ts +5 -0
  17. package/dist/ai-adapters/index.d.ts.map +1 -0
  18. package/dist/ai-adapters/index.js +30 -0
  19. package/dist/ai-adapters/index.js.map +1 -0
  20. package/dist/ai-adapters/types.d.ts +3 -0
  21. package/dist/ai-adapters/types.d.ts.map +1 -0
  22. package/dist/ai-adapters/types.js +7 -0
  23. package/dist/ai-adapters/types.js.map +1 -0
  24. package/dist/ai-capabilities/claude.d.ts +4 -0
  25. package/dist/ai-capabilities/claude.d.ts.map +1 -0
  26. package/dist/ai-capabilities/claude.js +174 -0
  27. package/dist/ai-capabilities/claude.js.map +1 -0
  28. package/dist/ai-capabilities/describe.d.ts +2 -0
  29. package/dist/ai-capabilities/describe.d.ts.map +1 -0
  30. package/dist/ai-capabilities/describe.js +31 -0
  31. package/dist/ai-capabilities/describe.js.map +1 -0
  32. package/dist/ai-capabilities/fsdeps.d.ts +3 -0
  33. package/dist/ai-capabilities/fsdeps.d.ts.map +1 -0
  34. package/dist/ai-capabilities/fsdeps.js +71 -0
  35. package/dist/ai-capabilities/fsdeps.js.map +1 -0
  36. package/dist/ai-capabilities/grok.d.ts +5 -0
  37. package/dist/ai-capabilities/grok.d.ts.map +1 -0
  38. package/dist/ai-capabilities/grok.js +145 -0
  39. package/dist/ai-capabilities/grok.js.map +1 -0
  40. package/dist/ai-capabilities/index.d.ts +4 -0
  41. package/dist/ai-capabilities/index.d.ts.map +1 -0
  42. package/dist/ai-capabilities/index.js +94 -0
  43. package/dist/ai-capabilities/index.js.map +1 -0
  44. package/dist/ai-capabilities/redact.d.ts +2 -0
  45. package/dist/ai-capabilities/redact.d.ts.map +1 -0
  46. package/dist/ai-capabilities/redact.js +27 -0
  47. package/dist/ai-capabilities/redact.js.map +1 -0
  48. package/dist/ai-capabilities/types.d.ts +11 -0
  49. package/dist/ai-capabilities/types.d.ts.map +1 -0
  50. package/dist/ai-capabilities/types.js +3 -0
  51. package/dist/ai-capabilities/types.js.map +1 -0
  52. package/dist/ai-launch.d.ts +35 -0
  53. package/dist/ai-launch.d.ts.map +1 -0
  54. package/dist/ai-launch.js +211 -0
  55. package/dist/ai-launch.js.map +1 -0
  56. package/dist/ai-session-detector.d.ts +19 -0
  57. package/dist/ai-session-detector.d.ts.map +1 -0
  58. package/dist/ai-session-detector.js +79 -0
  59. package/dist/ai-session-detector.js.map +1 -0
  60. package/dist/ai-sessions.d.ts +36 -0
  61. package/dist/ai-sessions.d.ts.map +1 -0
  62. package/dist/ai-sessions.js +309 -0
  63. package/dist/ai-sessions.js.map +1 -0
  64. package/dist/ai-status.d.ts +6 -0
  65. package/dist/ai-status.d.ts.map +1 -0
  66. package/dist/ai-status.js +40 -0
  67. package/dist/ai-status.js.map +1 -0
  68. package/dist/ai-transcript-locator.d.ts +35 -0
  69. package/dist/ai-transcript-locator.d.ts.map +1 -0
  70. package/dist/ai-transcript-locator.js +268 -0
  71. package/dist/ai-transcript-locator.js.map +1 -0
  72. package/dist/ai-transcript-tail.d.ts +17 -0
  73. package/dist/ai-transcript-tail.d.ts.map +1 -0
  74. package/dist/ai-transcript-tail.js +120 -0
  75. package/dist/ai-transcript-tail.js.map +1 -0
  76. package/dist/checklist.d.ts +20 -0
  77. package/dist/checklist.d.ts.map +1 -0
  78. package/dist/checklist.js +51 -0
  79. package/dist/checklist.js.map +1 -0
  80. package/dist/cli.d.ts +2 -0
  81. package/dist/cli.d.ts.map +1 -0
  82. package/dist/cli.js +1427 -0
  83. package/dist/cli.js.map +1 -0
  84. package/dist/command-runner.d.ts +15 -0
  85. package/dist/command-runner.d.ts.map +1 -0
  86. package/dist/command-runner.js +84 -0
  87. package/dist/command-runner.js.map +1 -0
  88. package/dist/config.d.ts +41 -0
  89. package/dist/config.d.ts.map +1 -0
  90. package/dist/config.js +152 -0
  91. package/dist/config.js.map +1 -0
  92. package/dist/cowork.d.ts +26 -0
  93. package/dist/cowork.d.ts.map +1 -0
  94. package/dist/cowork.js +370 -0
  95. package/dist/cowork.js.map +1 -0
  96. package/dist/fs-browser.d.ts +6 -0
  97. package/dist/fs-browser.d.ts.map +1 -0
  98. package/dist/fs-browser.js +61 -0
  99. package/dist/fs-browser.js.map +1 -0
  100. package/dist/has-command.d.ts +12 -0
  101. package/dist/has-command.d.ts.map +1 -0
  102. package/dist/has-command.js +24 -0
  103. package/dist/has-command.js.map +1 -0
  104. package/dist/heartbeat.d.ts +7 -0
  105. package/dist/heartbeat.d.ts.map +1 -0
  106. package/dist/heartbeat.js +50 -0
  107. package/dist/heartbeat.js.map +1 -0
  108. package/dist/index.d.ts +2 -0
  109. package/dist/index.d.ts.map +1 -0
  110. package/dist/index.js +56 -0
  111. package/dist/index.js.map +1 -0
  112. package/dist/port-scanner.d.ts +4 -0
  113. package/dist/port-scanner.d.ts.map +1 -0
  114. package/dist/port-scanner.js +75 -0
  115. package/dist/port-scanner.js.map +1 -0
  116. package/dist/project-scanner.d.ts +15 -0
  117. package/dist/project-scanner.d.ts.map +1 -0
  118. package/dist/project-scanner.js +333 -0
  119. package/dist/project-scanner.js.map +1 -0
  120. package/dist/pty-manager.d.ts +28 -0
  121. package/dist/pty-manager.d.ts.map +1 -0
  122. package/dist/pty-manager.js +506 -0
  123. package/dist/pty-manager.js.map +1 -0
  124. package/dist/service-installer.d.ts +95 -0
  125. package/dist/service-installer.d.ts.map +1 -0
  126. package/dist/service-installer.js +911 -0
  127. package/dist/service-installer.js.map +1 -0
  128. package/dist/single-instance.d.ts +20 -0
  129. package/dist/single-instance.d.ts.map +1 -0
  130. package/dist/single-instance.js +151 -0
  131. package/dist/single-instance.js.map +1 -0
  132. package/dist/ssh-local-network.d.ts +26 -0
  133. package/dist/ssh-local-network.d.ts.map +1 -0
  134. package/dist/ssh-local-network.js +169 -0
  135. package/dist/ssh-local-network.js.map +1 -0
  136. package/dist/terminal-detect.d.ts +52 -0
  137. package/dist/terminal-detect.d.ts.map +1 -0
  138. package/dist/terminal-detect.js +147 -0
  139. package/dist/terminal-detect.js.map +1 -0
  140. package/dist/terminal-markers.d.ts +52 -0
  141. package/dist/terminal-markers.d.ts.map +1 -0
  142. package/dist/terminal-markers.js +174 -0
  143. package/dist/terminal-markers.js.map +1 -0
  144. package/dist/tmux-manager.d.ts +35 -0
  145. package/dist/tmux-manager.d.ts.map +1 -0
  146. package/dist/tmux-manager.js +274 -0
  147. package/dist/tmux-manager.js.map +1 -0
  148. package/dist/update-check.d.ts +3 -0
  149. package/dist/update-check.d.ts.map +1 -0
  150. package/dist/update-check.js +202 -0
  151. package/dist/update-check.js.map +1 -0
  152. package/dist/websocket.d.ts +8 -0
  153. package/dist/websocket.d.ts.map +1 -0
  154. package/dist/websocket.js +472 -0
  155. package/dist/websocket.js.map +1 -0
  156. package/node_modules/@dialout/shared/README.md +16 -0
  157. package/node_modules/@dialout/shared/dist/ai-chat-prefs.d.ts +8 -0
  158. package/node_modules/@dialout/shared/dist/ai-chat-prefs.d.ts.map +1 -0
  159. package/node_modules/@dialout/shared/dist/ai-chat-prefs.js +41 -0
  160. package/node_modules/@dialout/shared/dist/capabilities.d.ts +25 -0
  161. package/node_modules/@dialout/shared/dist/capabilities.d.ts.map +1 -0
  162. package/node_modules/@dialout/shared/dist/capabilities.js +2 -0
  163. package/node_modules/@dialout/shared/dist/chat-blocks.d.ts +33 -0
  164. package/node_modules/@dialout/shared/dist/chat-blocks.d.ts.map +1 -0
  165. package/node_modules/@dialout/shared/dist/chat-blocks.js +61 -0
  166. package/node_modules/@dialout/shared/dist/command-filter.d.ts +4 -0
  167. package/node_modules/@dialout/shared/dist/command-filter.d.ts.map +1 -0
  168. package/node_modules/@dialout/shared/dist/command-filter.js +49 -0
  169. package/node_modules/@dialout/shared/dist/composer-behaviour.d.ts +6 -0
  170. package/node_modules/@dialout/shared/dist/composer-behaviour.d.ts.map +1 -0
  171. package/node_modules/@dialout/shared/dist/composer-behaviour.js +24 -0
  172. package/node_modules/@dialout/shared/dist/events.d.ts +37 -0
  173. package/node_modules/@dialout/shared/dist/events.d.ts.map +1 -0
  174. package/node_modules/@dialout/shared/dist/events.js +13 -0
  175. package/node_modules/@dialout/shared/dist/index.d.ts +21 -0
  176. package/node_modules/@dialout/shared/dist/index.d.ts.map +1 -0
  177. package/node_modules/@dialout/shared/dist/index.js +37 -0
  178. package/node_modules/@dialout/shared/dist/kinds.d.ts +2 -0
  179. package/node_modules/@dialout/shared/dist/kinds.d.ts.map +1 -0
  180. package/node_modules/@dialout/shared/dist/kinds.js +2 -0
  181. package/node_modules/@dialout/shared/dist/notify.d.ts +3 -0
  182. package/node_modules/@dialout/shared/dist/notify.d.ts.map +1 -0
  183. package/node_modules/@dialout/shared/dist/notify.js +31 -0
  184. package/node_modules/@dialout/shared/dist/permission.d.ts +4 -0
  185. package/node_modules/@dialout/shared/dist/permission.d.ts.map +1 -0
  186. package/node_modules/@dialout/shared/dist/permission.js +8 -0
  187. package/node_modules/@dialout/shared/dist/scroll-pin.d.ts +3 -0
  188. package/node_modules/@dialout/shared/dist/scroll-pin.d.ts.map +1 -0
  189. package/node_modules/@dialout/shared/dist/scroll-pin.js +11 -0
  190. package/node_modules/@dialout/shared/dist/session.d.ts +19 -0
  191. package/node_modules/@dialout/shared/dist/session.d.ts.map +1 -0
  192. package/node_modules/@dialout/shared/dist/session.js +6 -0
  193. package/node_modules/@dialout/shared/dist/terminal-name.d.ts +25 -0
  194. package/node_modules/@dialout/shared/dist/terminal-name.d.ts.map +1 -0
  195. package/node_modules/@dialout/shared/dist/terminal-name.js +63 -0
  196. package/node_modules/@dialout/shared/dist/tool-appearance.d.ts +9 -0
  197. package/node_modules/@dialout/shared/dist/tool-appearance.d.ts.map +1 -0
  198. package/node_modules/@dialout/shared/dist/tool-appearance.js +30 -0
  199. package/node_modules/@dialout/shared/package.json +37 -0
  200. package/node_modules/@dialout/shared/src/ai-chat-prefs.test.ts +40 -0
  201. package/node_modules/@dialout/shared/src/ai-chat-prefs.ts +39 -0
  202. package/node_modules/@dialout/shared/src/capabilities.ts +30 -0
  203. package/node_modules/@dialout/shared/src/chat-blocks.test.ts +65 -0
  204. package/node_modules/@dialout/shared/src/chat-blocks.ts +79 -0
  205. package/node_modules/@dialout/shared/src/command-filter.test.ts +76 -0
  206. package/node_modules/@dialout/shared/src/command-filter.ts +45 -0
  207. package/node_modules/@dialout/shared/src/composer-behaviour.test.ts +31 -0
  208. package/node_modules/@dialout/shared/src/composer-behaviour.ts +22 -0
  209. package/node_modules/@dialout/shared/src/events.ts +27 -0
  210. package/node_modules/@dialout/shared/src/index.ts +32 -0
  211. package/node_modules/@dialout/shared/src/kinds.ts +5 -0
  212. package/node_modules/@dialout/shared/src/notify.test.ts +49 -0
  213. package/node_modules/@dialout/shared/src/notify.ts +30 -0
  214. package/node_modules/@dialout/shared/src/permission.ts +10 -0
  215. package/node_modules/@dialout/shared/src/scroll-pin.test.ts +23 -0
  216. package/node_modules/@dialout/shared/src/scroll-pin.ts +13 -0
  217. package/node_modules/@dialout/shared/src/session.ts +25 -0
  218. package/node_modules/@dialout/shared/src/terminal-name.ts +82 -0
  219. package/node_modules/@dialout/shared/src/tool-appearance.test.ts +41 -0
  220. package/node_modules/@dialout/shared/src/tool-appearance.ts +39 -0
  221. package/package.json +54 -14
  222. package/scripts/postinstall.js +79 -0
  223. package/scripts/prepack.js +45 -0
  224. package/bin/dialout.js +0 -13
package/dist/cowork.js ADDED
@@ -0,0 +1,370 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TOKEN_RE = exports.COWORK_END = exports.COWORK_BEGIN = void 0;
37
+ exports.sanitizeTokens = sanitizeTokens;
38
+ exports.renderMatchGate = renderMatchGate;
39
+ exports.renderCoworkBlock = renderCoworkBlock;
40
+ exports.removeCoworkBlock = removeCoworkBlock;
41
+ exports.installCoworkBlock = installCoworkBlock;
42
+ exports.unmatchableTokens = unmatchableTokens;
43
+ exports.coworkViability = coworkViability;
44
+ exports.pickTmuxInstall = pickTmuxInstall;
45
+ const fs = __importStar(require("fs"));
46
+ const terminal_markers_1 = require("./terminal-markers");
47
+ exports.COWORK_BEGIN = '# >>> dialout cowork wrapper >>>';
48
+ exports.COWORK_END = '# <<< dialout cowork wrapper <<<';
49
+ // The markers the agent wrote before the rename. New blocks use the names
50
+ // above, but removal has to recognise these too: the block lives in the user's
51
+ // shell rc, and a marker we no longer match is a block nobody can ever remove.
52
+ const LEGACY_COWORK_BEGIN = '# >>> devdash cowork wrapper >>>';
53
+ const LEGACY_COWORK_END = '# <<< devdash cowork wrapper <<<';
54
+ // Only tokens matching this may reach the shell `case` — rc-file injection
55
+ // defense. TERM_PROGRAM values and our marker tokens are all within this set.
56
+ // Note it also excludes every glob metacharacter, which is what makes a token
57
+ // safe to use as a `case` *pattern* and not just as a quoted value.
58
+ exports.TOKEN_RE = /^[A-Za-z0-9._-]+$/;
59
+ // Env var names are interpolated bare (inside ${...}), so they need the
60
+ // stricter shell-name rule on top of TOKEN_RE — "." and "-" are legal in a
61
+ // token but not in a variable name.
62
+ const ENV_NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
63
+ function sanitizeTokens(tokens) {
64
+ const seen = new Set();
65
+ const out = [];
66
+ for (const t of tokens) {
67
+ if (exports.TOKEN_RE.test(t) && !seen.has(t)) {
68
+ seen.add(t);
69
+ out.push(t);
70
+ }
71
+ }
72
+ return out;
73
+ }
74
+ // One `[ -n "$VAR" ] && _dd_tp="token"` probe per ENV_MARKERS entry, in table
75
+ // order. Each is additionally guarded on _dd_tp still being empty so the FIRST
76
+ // match wins — that is what makes TERM_PROGRAM (assigned above these lines)
77
+ // take precedence and keeps a specific marker from being overwritten by the
78
+ // generic vte catch-all, exactly reproducing tokenFromEnv's precedence.
79
+ function renderEnvProbes() {
80
+ return terminal_markers_1.ENV_MARKERS
81
+ .filter(({ envVar, token }) => ENV_NAME_RE.test(envVar) && exports.TOKEN_RE.test(token))
82
+ .map(({ envVar, token }) => `[ -z "$_dd_tp" ] && [ -n "\${${envVar}:-}" ] && _dd_tp="${token}"`)
83
+ .join('\n');
84
+ }
85
+ // The shell twin of tokenFromProcTree(): walk up from this shell's own pid,
86
+ // at most 10 levels (self + 9 ancestors), matching /proc/<pid>/comm against
87
+ // PROC_NAMES. Reached when no env marker identified the terminal (xterm, foot,
88
+ // st, urxvt set no marker at all) OR when only the generic vte catch-all did —
89
+ // xfce4-terminal is VTE-based, so "vte" is provisional and the walk must still
90
+ // get a chance to name it exactly. See the guard below and GENERIC_ENV_TOKEN.
91
+ //
92
+ // It runs on every interactive shell start, so it must stay cheap: `read`,
93
+ // `case` and parameter expansion are all shell builtins, so the whole walk
94
+ // forks nothing. The `[ -d /proc ]` guard makes it a zero-cost no-op on macOS.
95
+ //
96
+ // Silence on a failed read is enforced by `done 2>/dev/null` on the whole
97
+ // loop, NOT by a per-read `2>/dev/null`. Redirections are applied left to
98
+ // right, so in `read x < file 2>/dev/null` the input redirect fails *before*
99
+ // stderr is redirected and the shell's diagnostic still reaches the user's
100
+ // terminal. Reordering to `read x 2>/dev/null < file` fixes sh/dash/bash but
101
+ // NOT zsh, which reports redirection errors on the original stderr regardless
102
+ // of order — and .zshrc is half the blast radius. Redirecting the compound
103
+ // command is the only form verified silent in all four shells; it also covers
104
+ // the `[ "$_dd_pid" -gt 1 ]` "Illegal number" path. Failed reads still
105
+ // `|| break`, so the walk ends rather than spinning. stdout stays untouched.
106
+ //
107
+ // Not a theoretical path: /proc mounted with hidepid=1/2, or systemd's
108
+ // ProtectProc=, hides root-owned ancestors (login, agetty, gdm-session-worker),
109
+ // and the marker-less terminals that reach this walk are also the ones that
110
+ // run all 10 levels — so an unfixed walk printed an error on every new
111
+ // terminal, forever, until the user hand-edited their rc.
112
+ function renderProcWalk() {
113
+ const arms = Object.entries(terminal_markers_1.PROC_NAMES)
114
+ .filter(([comm, token]) => exports.TOKEN_RE.test(comm) && exports.TOKEN_RE.test(token))
115
+ .map(([comm, token]) => ` ${comm}) _dd_tp="${token}" ;;`)
116
+ .join('\n');
117
+ // The guard admits two states: nothing resolved at all, or ONLY the generic
118
+ // vte catch-all resolved. The second is what makes the walk reachable for
119
+ // VTE-based emulators that are in PROC_NAMES (xfce4-terminal) — see
120
+ // GENERIC_ENV_TOKEN. `_dd_prev` carries the provisional token across the
121
+ // walk so it can be restored when the walk names nothing; the walk itself is
122
+ // unchanged and still writes into an initially-empty `_dd_tp`, so a specific
123
+ // marker above VTE_VERSION in the table is still final. This is the shell
124
+ // twin of currentTerminalToken()'s `tokenFromProcTree(...) || token`.
125
+ return `if { [ -z "$_dd_tp" ] || [ "$_dd_tp" = "${terminal_markers_1.GENERIC_ENV_TOKEN}" ]; } && [ -d /proc ]; then
126
+ _dd_prev="$_dd_tp"
127
+ _dd_tp=""
128
+ _dd_pid=$$
129
+ _dd_lvl=0
130
+ while [ "$_dd_lvl" -lt 10 ]; do
131
+ _dd_lvl=$((_dd_lvl + 1))
132
+ [ "$_dd_pid" -gt 1 ] || break
133
+ read -r _dd_comm < "/proc/$_dd_pid/comm" || break
134
+ case "$_dd_comm" in
135
+ ${arms}
136
+ esac
137
+ [ -z "$_dd_tp" ] || break
138
+ read -r _dd_stat < "/proc/$_dd_pid/stat" || break
139
+ # ppid is the 2nd field after the LAST ")" (a comm may contain both).
140
+ _dd_rest="\${_dd_stat##*) }"
141
+ _dd_rest="\${_dd_rest#* }"
142
+ _dd_ppid="\${_dd_rest%% *}"
143
+ case "$_dd_ppid" in
144
+ ''|*[!0-9]*) break ;;
145
+ esac
146
+ _dd_pid="$_dd_ppid"
147
+ done 2>/dev/null
148
+ [ -n "$_dd_tp" ] || _dd_tp="$_dd_prev"
149
+ fi
150
+ unset _dd_pid _dd_lvl _dd_comm _dd_stat _dd_rest _dd_ppid _dd_prev`;
151
+ }
152
+ // The _dd_tp resolution + case that sets _dd_match. Column-0 so it can be
153
+ // unit-tested under `sh -c` in isolation; renderCoworkBlock indents it.
154
+ // Resolution order mirrors terminal-markers.ts exactly: TERM_PROGRAM (an Apple
155
+ // convention — unset under every Linux terminal), then ENV_MARKERS in table
156
+ // order, then the /proc process-tree walk.
157
+ function renderMatchGate(tokens) {
158
+ const clean = sanitizeTokens(tokens);
159
+ const arm = clean.length > 0
160
+ ? `${clean.join('|')}) _dd_match=1 ;;`
161
+ : '*) ;;';
162
+ return `_dd_tp="\${TERM_PROGRAM:-}"
163
+ ${renderEnvProbes()}
164
+ ${renderProcWalk()}
165
+ _dd_match=""
166
+ case "$_dd_tp" in
167
+ ${arm}
168
+ esac`;
169
+ }
170
+ // The verbatim tmux wrap body (carried over from the pre-gating COWORK_BLOCK).
171
+ // Do NOT add pane-scrollbars here — it wedges tmux at 100% CPU.
172
+ //
173
+ // The clipboard bindings are a SINGLE if/elif chain (pbcopy → wl-copy → xclip
174
+ // → xsel), never a pbcopy branch plus an independent Linux one. xclip and xsel
175
+ // are both installable on macOS via Homebrew, so two independent branches both
176
+ // ran on such a Mac; all four bind-key calls fired twice and the LATER binding
177
+ // won, routing copy-mode copy through `xclip -selection clipboard`, which then
178
+ // fails at runtime with no DISPLAY — macOS clipboard copy silently stops
179
+ // working (Constraint 1). bind-key is server-global, so an affected Mac also
180
+ // flip-flopped between xclip (after a native cowork shell started) and pbcopy
181
+ // (after a browser attach, whose bindings come from copyVerb() in
182
+ // pty-manager.ts — which returns pbcopy on darwin before probing anything).
183
+ // The chain here and copyVerb() must keep the same shape and the same order.
184
+ const WRAP_BODY = `_dd_base=$(basename "$PWD" 2>/dev/null | LC_ALL=C tr -cd 'a-zA-Z0-9_-' | cut -c1-20)
185
+ [ -n "$_dd_base" ] || _dd_base=shell
186
+ _dd_name="\${_dd_base}-$(( \${RANDOM:-$$} % 9000 + 1000 ))"
187
+ if tmux new-session -d -s "$_dd_name" 2>/dev/null; then
188
+ tmux set-option -t "$_dd_name" @term_program "\${TERM_PROGRAM:-\${TERMINAL_EMULATOR:-unknown}}" 2>/dev/null
189
+ tmux set-option -t "$_dd_name" @devdash_origin native 2>/dev/null
190
+ tmux set-window-option -t "$_dd_name" window-size latest 2>/dev/null
191
+ tmux set-window-option -t "$_dd_name" aggressive-resize on 2>/dev/null
192
+ tmux set-option -g mouse on 2>/dev/null
193
+ tmux set-option -s set-clipboard on 2>/dev/null
194
+ tmux set-option -g status on 2>/dev/null
195
+ tmux set-option -g history-limit 50000 2>/dev/null
196
+ tmux set-option -sg escape-time 10 2>/dev/null
197
+ tmux set-option -g allow-passthrough on 2>/dev/null
198
+ tmux set-option -g focus-events on 2>/dev/null
199
+ tmux show-options -g terminal-features 2>/dev/null | grep -q RGB || tmux set-option -sa terminal-features "*:RGB" 2>/dev/null
200
+ tmux unbind-key -n MouseDown3Pane 2>/dev/null
201
+ tmux unbind-key -n MouseDown3Status 2>/dev/null
202
+ # Clipboard: ONE chain, first available wins — pbcopy must EXCLUDE the Linux
203
+ # tools, which are installable on macOS too (see the note in cowork.ts).
204
+ # Each arm sets copy-command as well as the four bind-keys. The bind-keys
205
+ # only cover drag-release and the keyboard copies; copy-command is what makes
206
+ # tmux's own double-click-word / triple-click-line defaults — which call
207
+ # copy-pipe-and-cancel with NO argument — reach the system clipboard instead
208
+ # of stopping at the tmux paste buffer. See clipboardBindings() in
209
+ # pty-manager.ts for the measurements. Both files must stay in the same shape
210
+ # and the same order.
211
+ if command -v pbcopy >/dev/null 2>&1; then
212
+ tmux set-option -g copy-command pbcopy 2>/dev/null
213
+ tmux bind-key -T copy-mode MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel pbcopy 2>/dev/null
214
+ tmux bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel pbcopy 2>/dev/null
215
+ tmux bind-key -T copy-mode Enter send-keys -X copy-pipe-and-cancel pbcopy 2>/dev/null
216
+ tmux bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel pbcopy 2>/dev/null
217
+ elif command -v wl-copy >/dev/null 2>&1; then
218
+ tmux set-option -g copy-command wl-copy 2>/dev/null
219
+ tmux bind-key -T copy-mode MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel wl-copy 2>/dev/null
220
+ tmux bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel wl-copy 2>/dev/null
221
+ tmux bind-key -T copy-mode Enter send-keys -X copy-pipe-and-cancel wl-copy 2>/dev/null
222
+ tmux bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel wl-copy 2>/dev/null
223
+ elif command -v xclip >/dev/null 2>&1; then
224
+ tmux set-option -g copy-command "xclip -selection clipboard" 2>/dev/null
225
+ tmux bind-key -T copy-mode MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xclip -selection clipboard" 2>/dev/null
226
+ tmux bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xclip -selection clipboard" 2>/dev/null
227
+ tmux bind-key -T copy-mode Enter send-keys -X copy-pipe-and-cancel "xclip -selection clipboard" 2>/dev/null
228
+ tmux bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xclip -selection clipboard" 2>/dev/null
229
+ elif command -v xsel >/dev/null 2>&1; then
230
+ tmux set-option -g copy-command "xsel --clipboard --input" 2>/dev/null
231
+ tmux bind-key -T copy-mode MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xsel --clipboard --input" 2>/dev/null
232
+ tmux bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "xsel --clipboard --input" 2>/dev/null
233
+ tmux bind-key -T copy-mode Enter send-keys -X copy-pipe-and-cancel "xsel --clipboard --input" 2>/dev/null
234
+ tmux bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "xsel --clipboard --input" 2>/dev/null
235
+ fi
236
+ tmux set-option -t "$_dd_name" @devdash_folder "$(basename "$PWD" 2>/dev/null)" 2>/dev/null
237
+ tmux set-option -t "$_dd_name" @devdash_folder_path "$PWD" 2>/dev/null
238
+ tmux set-option -t "$_dd_name" @devdash_created "$(date +%Y-%m-%dT%H:%M:%S)" 2>/dev/null
239
+ tmux set-option -t "$_dd_name" @devdash_git "$(git rev-parse --abbrev-ref HEAD 2>/dev/null)" 2>/dev/null
240
+ exec tmux new-session -A -s "$_dd_name"
241
+ fi
242
+ unset _dd_base _dd_name`;
243
+ function indent(text, pad) {
244
+ return text.split('\n').map((l) => (l ? pad + l : l)).join('\n');
245
+ }
246
+ // Regenerate the full app-gated rc block from the allowlist. An empty (or
247
+ // fully-sanitized-away) list yields a block that never wraps.
248
+ function renderCoworkBlock(tokens) {
249
+ const gate = indent(renderMatchGate(tokens), ' ');
250
+ const body = indent(WRAP_BODY, ' ');
251
+ return `${exports.COWORK_BEGIN}
252
+ # Managed by "dialout setup-cowork" — do not edit inside the markers.
253
+ case $- in
254
+ *i*)
255
+ if [ -z "$TMUX" ] && [ -z "$DEVDASH_NO_WRAP" ] && [ -z "$SSH_TTY" ] && [ -t 1 ] \\
256
+ && command -v tmux >/dev/null 2>&1; then
257
+ ${gate}
258
+ if [ -n "$_dd_match" ]; then
259
+ ${body}
260
+ fi
261
+ unset _dd_tp _dd_match
262
+ fi
263
+ ;;
264
+ esac
265
+ ${exports.COWORK_END}`;
266
+ }
267
+ function stripBetween(content, begin, end) {
268
+ const b = content.indexOf(begin);
269
+ if (b === -1)
270
+ return content;
271
+ const e = content.indexOf(end);
272
+ if (e === -1)
273
+ return content;
274
+ return (content.slice(0, b) + content.slice(e + end.length)).replace(/\n{3,}/g, '\n\n');
275
+ }
276
+ function removeCoworkBlock(content) {
277
+ // Strip a pre-rename block first, so upgrading and then removing does not
278
+ // leave the old one behind.
279
+ content = stripBetween(content, LEGACY_COWORK_BEGIN, LEGACY_COWORK_END);
280
+ const begin = content.indexOf(exports.COWORK_BEGIN);
281
+ if (begin === -1)
282
+ return content;
283
+ const end = content.indexOf(exports.COWORK_END);
284
+ if (end === -1 || end < begin)
285
+ return content;
286
+ return (content.slice(0, begin) + content.slice(end + exports.COWORK_END.length))
287
+ .replace(/\n{3,}$/g, '\n\n');
288
+ }
289
+ function installCoworkBlock(rcPath, tokens) {
290
+ const existed = fs.existsSync(rcPath);
291
+ const content = existed ? fs.readFileSync(rcPath, 'utf-8') : '';
292
+ const had = content.includes(exports.COWORK_BEGIN) || content.includes(LEGACY_COWORK_BEGIN);
293
+ const cleaned = removeCoworkBlock(content);
294
+ const next = cleaned.replace(/\n*$/, '\n\n') + renderCoworkBlock(tokens) + '\n';
295
+ fs.writeFileSync(rcPath, next);
296
+ return had ? 'updated' : existed ? 'installed' : 'created';
297
+ }
298
+ // Linux package managers in preference order → install command.
299
+ const LINUX_MANAGERS = [
300
+ { bin: 'apt-get', command: 'sudo apt-get install -y tmux' },
301
+ { bin: 'dnf', command: 'sudo dnf install -y tmux' },
302
+ { bin: 'yum', command: 'sudo yum install -y tmux' },
303
+ { bin: 'pacman', command: 'sudo pacman -S --noconfirm tmux' },
304
+ { bin: 'zypper', command: 'sudo zypper install -y tmux' },
305
+ ];
306
+ // --- unmatchableTokens: the guard rail against the reported silent no-op ---
307
+ //
308
+ // The bug shipped a green "Cowork enabled." for GNOME Terminal on Linux, which
309
+ // then never wrapped because the gate keyed off $TERM_PROGRAM alone (GNOME
310
+ // Terminal never sets it). Tasks 1-5 fixed detection; this makes a selection
311
+ // that STILL can't match on this platform loud instead of silent.
312
+ //
313
+ // Derived from the shared tables (ENV_MARKERS, PROC_NAMES) rather than a
314
+ // second hand-maintained list, so it cannot drift from them the way the shell
315
+ // gate and terminal-detect.ts once drifted from each other.
316
+ //
317
+ // ENV_MARKERS' first three entries (kitty, alacritty, WezTerm) are terminal
318
+ // emulators that ship on both platforms and set the same env var on either —
319
+ // so they're excluded from "linux-only" even though they live in the table.
320
+ // Everything else in ENV_MARKERS (konsole, tilix, terminator, gnome-terminal,
321
+ // vte) and everything in PROC_NAMES (xfce4-terminal, foot, urxvt, xterm, st,
322
+ // plus the overlapping cross-platform entries, which the exclusion above
323
+ // removes again) is Linux desktop-environment-specific and cannot be produced
324
+ // on darwin.
325
+ const CROSS_PLATFORM_TOKENS = new Set(terminal_markers_1.ENV_MARKERS.slice(0, 3).map((m) => m.token));
326
+ const LINUX_ONLY_TOKENS = new Set([...terminal_markers_1.ENV_MARKERS.map((m) => m.token), ...Object.values(terminal_markers_1.PROC_NAMES)]
327
+ .filter((token) => !CROSS_PLATFORM_TOKENS.has(token)));
328
+ // TERM_PROGRAM values with no Linux equivalent. These can't be derived from
329
+ // ENV_MARKERS or PROC_NAMES — TERM_PROGRAM is an Apple convention read
330
+ // directly by tokenFromEnv, not a table entry — so they're named explicitly.
331
+ // Keep this list to exactly these two; anything else must come from the
332
+ // shared tables above.
333
+ const MACOS_ONLY_TOKENS = new Set(['Apple_Terminal', 'iTerm.app']);
334
+ /** Tokens that cannot be produced by tokenFromEnv/proc detection here. */
335
+ function unmatchableTokens(tokens, platform) {
336
+ if (platform === 'darwin')
337
+ return tokens.filter((t) => LINUX_ONLY_TOKENS.has(t));
338
+ if (platform === 'linux')
339
+ return tokens.filter((t) => MACOS_ONLY_TOKENS.has(t));
340
+ return [];
341
+ }
342
+ function coworkViability(env, anyEmulatorInstalled) {
343
+ const reasons = [];
344
+ if (env.SSH_TTY || env.SSH_CONNECTION)
345
+ reasons.push('ssh-session');
346
+ if (!anyEmulatorInstalled)
347
+ reasons.push('no-emulator');
348
+ return { usable: reasons.length === 0, reasons };
349
+ }
350
+ function pickTmuxInstall(platform, hasCommand) {
351
+ if (platform === 'darwin') {
352
+ if (hasCommand('brew'))
353
+ return { command: 'brew install tmux', canAuto: true };
354
+ return {
355
+ command: '',
356
+ canAuto: false,
357
+ manual: 'Homebrew is not installed. Install it from https://brew.sh then run: brew install tmux',
358
+ };
359
+ }
360
+ for (const m of LINUX_MANAGERS) {
361
+ if (hasCommand(m.bin))
362
+ return { command: m.command, canAuto: true };
363
+ }
364
+ return {
365
+ command: '',
366
+ canAuto: false,
367
+ manual: 'No supported package manager found. Install tmux with your distro\'s package manager (apt/dnf/yum/pacman/zypper).',
368
+ };
369
+ }
370
+ //# sourceMappingURL=cowork.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cowork.js","sourceRoot":"","sources":["../src/cowork.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export interface DirEntry {
2
+ name: string;
3
+ type: 'directory' | 'file';
4
+ }
5
+ export declare function listDirectory(dirPath: string): DirEntry[];
6
+ //# sourceMappingURL=fs-browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-browser.d.ts","sourceRoot":"","sources":["../src/fs-browser.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,GAAG,MAAM,CAAC;CAC5B;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,QAAQ,EAAE,CAwBzD"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.listDirectory = listDirectory;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ function listDirectory(dirPath) {
40
+ const resolvedPath = path.resolve(dirPath);
41
+ if (!fs.existsSync(resolvedPath)) {
42
+ return [];
43
+ }
44
+ const stat = fs.statSync(resolvedPath);
45
+ if (!stat.isDirectory()) {
46
+ return [];
47
+ }
48
+ const entries = fs.readdirSync(resolvedPath, { withFileTypes: true });
49
+ return entries
50
+ .filter((entry) => !entry.name.startsWith('.'))
51
+ .map((entry) => ({
52
+ name: entry.name,
53
+ type: entry.isDirectory() ? 'directory' : 'file',
54
+ }))
55
+ .sort((a, b) => {
56
+ if (a.type === b.type)
57
+ return a.name.localeCompare(b.name);
58
+ return a.type === 'directory' ? -1 : 1;
59
+ });
60
+ }
61
+ //# sourceMappingURL=fs-browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-browser.js","sourceRoot":"","sources":["../src/fs-browser.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,sCAwBC;AAhCD,uCAAyB;AACzB,2CAA6B;AAO7B,SAAgB,aAAa,CAAC,OAAe;IAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IACvC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtE,OAAO,OAAO;SACX,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;SAC9C,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACf,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,WAAoB,CAAC,CAAC,CAAC,MAAe;KACnE,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACb,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;YAAE,OAAO,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC3D,OAAO,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * True when `bin` resolves on PATH. Never throws.
3
+ *
4
+ * Deliberately does NOT pass an args array together with a `shell` option —
5
+ * that combination triggers Node 22+'s DEP0190 deprecation warning. Instead
6
+ * `/bin/sh` itself is the program, with a fixed `-c` script; `bin` is handed
7
+ * to the shell as `$1` (via the extra argv positions after the script),
8
+ * never concatenated into the command line, so it can't be interpreted as
9
+ * shell syntax either.
10
+ */
11
+ export declare function hasCommand(bin: string): boolean;
12
+ //# sourceMappingURL=has-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has-command.d.ts","sourceRoot":"","sources":["../src/has-command.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO/C"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasCommand = hasCommand;
4
+ const child_process_1 = require("child_process");
5
+ /**
6
+ * True when `bin` resolves on PATH. Never throws.
7
+ *
8
+ * Deliberately does NOT pass an args array together with a `shell` option —
9
+ * that combination triggers Node 22+'s DEP0190 deprecation warning. Instead
10
+ * `/bin/sh` itself is the program, with a fixed `-c` script; `bin` is handed
11
+ * to the shell as `$1` (via the extra argv positions after the script),
12
+ * never concatenated into the command line, so it can't be interpreted as
13
+ * shell syntax either.
14
+ */
15
+ function hasCommand(bin) {
16
+ try {
17
+ (0, child_process_1.execFileSync)('/bin/sh', ['-c', 'command -v "$1" >/dev/null 2>&1', 'sh', bin], { stdio: 'pipe' });
18
+ return true;
19
+ }
20
+ catch {
21
+ return false;
22
+ }
23
+ }
24
+ //# sourceMappingURL=has-command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"has-command.js","sourceRoot":"","sources":["../src/has-command.ts"],"names":[],"mappings":";;AAYA,gCAOC;AAnBD,iDAA6C;AAE7C;;;;;;;;;GASG;AACH,SAAgB,UAAU,CAAC,GAAW;IACpC,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,SAAS,EAAE,CAAC,IAAI,EAAE,iCAAiC,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QACjG,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
@@ -0,0 +1,7 @@
1
+ import WebSocket from 'ws';
2
+ export declare const STALE_MULTIPLIER = 2.5;
3
+ export declare function isConnectionStale(lastPong: number | null, now: number, intervalMs: number): boolean;
4
+ export declare function notePong(): void;
5
+ export declare function startHeartbeat(ws: WebSocket, intervalMs: number, onStale?: () => void): void;
6
+ export declare function stopHeartbeat(): void;
7
+ //# sourceMappingURL=heartbeat.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,IAAI,CAAC;AAO3B,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAKpC,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GACjB,OAAO,CAGT;AAED,wBAAgB,QAAQ,IAAI,IAAI,CAE/B;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,IAAI,CAa5F;AAED,wBAAgB,aAAa,IAAI,IAAI,CAMpC"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.STALE_MULTIPLIER = void 0;
7
+ exports.isConnectionStale = isConnectionStale;
8
+ exports.notePong = notePong;
9
+ exports.startHeartbeat = startHeartbeat;
10
+ exports.stopHeartbeat = stopHeartbeat;
11
+ const ws_1 = __importDefault(require("ws"));
12
+ let heartbeatTimer = null;
13
+ let lastPongAt = null;
14
+ // How many heartbeat intervals of silence before the socket is declared dead.
15
+ // 2.5 tolerates one dropped heartbeat plus jitter without a false positive.
16
+ exports.STALE_MULTIPLIER = 2.5;
17
+ // The server answers every `heartbeat` with a `pong`. If pongs stop arriving
18
+ // the socket is half-open: sends still "succeed" into a dead TCP connection and
19
+ // 'close' may not fire for many minutes, so nothing would trigger a reconnect.
20
+ function isConnectionStale(lastPong, now, intervalMs) {
21
+ if (lastPong === null)
22
+ return false; // no pong expected yet
23
+ return now - lastPong > intervalMs * exports.STALE_MULTIPLIER;
24
+ }
25
+ function notePong() {
26
+ lastPongAt = Date.now();
27
+ }
28
+ function startHeartbeat(ws, intervalMs, onStale) {
29
+ stopHeartbeat();
30
+ lastPongAt = Date.now(); // treat connect as a fresh pong
31
+ heartbeatTimer = setInterval(() => {
32
+ if (ws.readyState !== ws_1.default.OPEN)
33
+ return;
34
+ if (isConnectionStale(lastPongAt, Date.now(), intervalMs)) {
35
+ console.error('[dialout] No pong from server — connection is dead, reconnecting');
36
+ stopHeartbeat();
37
+ onStale?.();
38
+ return;
39
+ }
40
+ ws.send(JSON.stringify({ type: 'heartbeat', ts: Date.now() }));
41
+ }, intervalMs);
42
+ }
43
+ function stopHeartbeat() {
44
+ if (heartbeatTimer) {
45
+ clearInterval(heartbeatTimer);
46
+ heartbeatTimer = null;
47
+ }
48
+ lastPongAt = null;
49
+ }
50
+ //# sourceMappingURL=heartbeat.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../src/heartbeat.ts"],"names":[],"mappings":";;;;;;AAYA,8CAOC;AAED,4BAEC;AAED,wCAaC;AAED,sCAMC;AA9CD,4CAA2B;AAE3B,IAAI,cAAc,GAA0B,IAAI,CAAC;AACjD,IAAI,UAAU,GAAkB,IAAI,CAAC;AAErC,8EAA8E;AAC9E,4EAA4E;AAC/D,QAAA,gBAAgB,GAAG,GAAG,CAAC;AAEpC,6EAA6E;AAC7E,gFAAgF;AAChF,+EAA+E;AAC/E,SAAgB,iBAAiB,CAC/B,QAAuB,EACvB,GAAW,EACX,UAAkB;IAElB,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC,CAAC,uBAAuB;IAC5D,OAAO,GAAG,GAAG,QAAQ,GAAG,UAAU,GAAG,wBAAgB,CAAC;AACxD,CAAC;AAED,SAAgB,QAAQ;IACtB,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAC1B,CAAC;AAED,SAAgB,cAAc,CAAC,EAAa,EAAE,UAAkB,EAAE,OAAoB;IACpF,aAAa,EAAE,CAAC;IAChB,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,gCAAgC;IACzD,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;QAChC,IAAI,EAAE,CAAC,UAAU,KAAK,YAAS,CAAC,IAAI;YAAE,OAAO;QAC7C,IAAI,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,UAAU,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;YAClF,aAAa,EAAE,CAAC;YAChB,OAAO,EAAE,EAAE,CAAC;YACZ,OAAO;QACT,CAAC;QACD,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC,EAAE,UAAU,CAAC,CAAC;AACjB,CAAC;AAED,SAAgB,aAAa;IAC3B,IAAI,cAAc,EAAE,CAAC;QACnB,aAAa,CAAC,cAAc,CAAC,CAAC;QAC9B,cAAc,GAAG,IAAI,CAAC;IACxB,CAAC;IACD,UAAU,GAAG,IAAI,CAAC;AACpB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const path_1 = __importDefault(require("path"));
7
+ const config_1 = require("./config");
8
+ const websocket_1 = require("./websocket");
9
+ const single_instance_1 = require("./single-instance");
10
+ // LaunchDaemons / systemd units start with a bare PATH (/usr/bin:/bin:...) that
11
+ // omits Homebrew and /usr/local/bin, so `tmux` resolves to ENOENT at boot even
12
+ // when installed — breaking cowork wrapping and live-session reporting. Ensure
13
+ // the common tool locations (and our own node dir) are on PATH before any child
14
+ // spawn, regardless of how the agent was launched. Existing entries keep their
15
+ // priority; we only append what's missing.
16
+ (() => {
17
+ const extra = ['/opt/homebrew/bin', '/usr/local/bin', '/usr/bin', '/bin', path_1.default.dirname(process.execPath)];
18
+ const parts = (process.env.PATH || '').split(path_1.default.delimiter).filter(Boolean);
19
+ const seen = new Set(parts);
20
+ for (const p of extra)
21
+ if (p && !seen.has(p)) {
22
+ parts.push(p);
23
+ seen.add(p);
24
+ }
25
+ process.env.PATH = parts.join(path_1.default.delimiter);
26
+ })();
27
+ const config = (0, config_1.loadConfig)();
28
+ if (!config.serverUrl || !config.apiKey) {
29
+ console.error('[dialout] Not configured. Run: dialout init');
30
+ process.exit(1);
31
+ }
32
+ // Enforce one agent per server URL. A watchdog/service respawn or a stray
33
+ // manual start that lands while a healthy agent is already connected steps
34
+ // aside here instead of opening a second socket on the same key (which the
35
+ // server would drop with close 1006, flapping both). See single-instance.ts.
36
+ if (!(0, single_instance_1.acquireSingleInstanceLock)(config.serverUrl)) {
37
+ console.log(`[dialout] Already running for ${config.serverUrl} — exiting (single instance).`);
38
+ process.exit(0);
39
+ }
40
+ console.log(`[dialout] Starting...`);
41
+ console.log(`[dialout] Server: ${config.serverUrl}`);
42
+ (0, websocket_1.connect)(config, () => {
43
+ console.log('[dialout] Ready');
44
+ });
45
+ // Graceful shutdown
46
+ process.on('SIGINT', () => {
47
+ console.log('\n[dialout] Shutting down...');
48
+ (0, websocket_1.disconnect)();
49
+ process.exit(0);
50
+ });
51
+ process.on('SIGTERM', () => {
52
+ console.log('[dialout] Shutting down...');
53
+ (0, websocket_1.disconnect)();
54
+ process.exit(0);
55
+ });
56
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,gDAAwB;AACxB,qCAAsC;AACtC,2CAAkD;AAClD,uDAA8D;AAE9D,gFAAgF;AAChF,+EAA+E;AAC/E,+EAA+E;AAC/E,gFAAgF;AAChF,+EAA+E;AAC/E,2CAA2C;AAC3C,CAAC,GAAG,EAAE;IACJ,MAAM,KAAK,GAAG,CAAC,mBAAmB,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,EAAE,cAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC1G,MAAM,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,cAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IAC5B,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAAC,CAAC;IAC7E,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,cAAI,CAAC,SAAS,CAAC,CAAC;AAChD,CAAC,CAAC,EAAE,CAAC;AAEL,MAAM,MAAM,GAAG,IAAA,mBAAU,GAAE,CAAC;AAE5B,IAAI,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IACxC,OAAO,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,0EAA0E;AAC1E,2EAA2E;AAC3E,2EAA2E;AAC3E,6EAA6E;AAC7E,IAAI,CAAC,IAAA,2CAAyB,EAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,iCAAiC,MAAM,CAAC,SAAS,+BAA+B,CAAC,CAAC;IAC9F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AACrC,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;AAErD,IAAA,mBAAO,EAAC,MAAM,EAAE,GAAG,EAAE;IACnB,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACjC,CAAC,CAAC,CAAC;AAEH,oBAAoB;AACpB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;IAC5C,IAAA,sBAAU,GAAE,CAAC;IACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;IACzB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,IAAA,sBAAU,GAAE,CAAC;IACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}