@surething/cockpit 1.0.216 → 1.0.217

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 (64) hide show
  1. package/.next-prod/BUILD_ID +1 -1
  2. package/.next-prod/app-path-routes-manifest.json +3 -3
  3. package/.next-prod/build-manifest.json +2 -2
  4. package/.next-prod/prerender-manifest.json +3 -3
  5. package/.next-prod/server/app/_global-error/page_client-reference-manifest.js +1 -1
  6. package/.next-prod/server/app/_global-error.html +1 -1
  7. package/.next-prod/server/app/_global-error.rsc +1 -1
  8. package/.next-prod/server/app/_global-error.segments/_full.segment.rsc +1 -1
  9. package/.next-prod/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  10. package/.next-prod/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  11. package/.next-prod/server/app/_global-error.segments/_head.segment.rsc +1 -1
  12. package/.next-prod/server/app/_global-error.segments/_index.segment.rsc +1 -1
  13. package/.next-prod/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next-prod/server/app/_not-found/page_client-reference-manifest.js +1 -1
  15. package/.next-prod/server/app/_not-found.html +1 -1
  16. package/.next-prod/server/app/_not-found.rsc +3 -3
  17. package/.next-prod/server/app/_not-found.segments/_full.segment.rsc +3 -3
  18. package/.next-prod/server/app/_not-found.segments/_head.segment.rsc +1 -1
  19. package/.next-prod/server/app/_not-found.segments/_index.segment.rsc +3 -3
  20. package/.next-prod/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  21. package/.next-prod/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  22. package/.next-prod/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  23. package/.next-prod/server/app/api/terminal/bubble-order/route.js +1 -1
  24. package/.next-prod/server/app/page_client-reference-manifest.js +1 -1
  25. package/.next-prod/server/app/project/page_client-reference-manifest.js +1 -1
  26. package/.next-prod/server/app/review/[id]/page_client-reference-manifest.js +1 -1
  27. package/.next-prod/server/app-paths-manifest.json +3 -3
  28. package/.next-prod/server/chunks/8916.js +1 -1
  29. package/.next-prod/server/chunks/9658.js +5 -5
  30. package/.next-prod/server/chunks/9877.js +1 -1
  31. package/.next-prod/server/functions-config-manifest.json +1 -0
  32. package/.next-prod/server/middleware-build-manifest.js +1 -1
  33. package/.next-prod/server/pages/404.html +1 -1
  34. package/.next-prod/server/pages/500.html +1 -1
  35. package/.next-prod/server/server-reference-manifest.json +1 -1
  36. package/.next-prod/static/chunks/6345-d477b8d5c682b1fb.js +14 -0
  37. package/.next-prod/static/chunks/6917-0a22d7764ca45244.js +29 -0
  38. package/.next-prod/static/chunks/app/{layout-a0362651ba6e6e6f.js → layout-8e3a54b794cb35b6.js} +1 -1
  39. package/.next-prod/static/chunks/app/{page-1b14cabf47df9ff7.js → page-3ab0a0f28cbdc8e2.js} +1 -1
  40. package/.next-prod/static/chunks/app/project/{page-1b14cabf47df9ff7.js → page-3ab0a0f28cbdc8e2.js} +1 -1
  41. package/.next-prod/static/css/fc2730c2dbe4866e.css +1 -0
  42. package/.next-prod/trace +13 -13
  43. package/.next-prod/trace-build +1 -1
  44. package/README.md +3 -2
  45. package/README.zh.md +3 -2
  46. package/bin/cock-codegraph.mjs +21 -6
  47. package/bin/cock-connection.mjs +151 -0
  48. package/bin/cock.mjs +12 -1
  49. package/bin/setup-dev.mjs +15 -13
  50. package/dist/{chunk-CZWJPTRO.mjs → chunk-GCYLMG43.mjs} +2486 -1047
  51. package/dist/chunk-O4P2J44N.mjs +314 -0
  52. package/dist/{chunk-KRTISG5I.mjs → chunk-W6G6X3FP.mjs} +196 -9
  53. package/dist/httpApi.mjs +75 -2
  54. package/dist/scheduledTasks.mjs +9 -1158
  55. package/dist/{server-OSOMFNXR.mjs → server-ZBUZ24TC.mjs} +4 -2
  56. package/dist/wsServer.mjs +24 -19
  57. package/package.json +1 -1
  58. package/server.mjs +5 -1
  59. package/.next-prod/static/chunks/5188-415582403ef0e29c.js +0 -29
  60. package/.next-prod/static/chunks/6345-e5ceeb2aeb698eb6.js +0 -14
  61. package/.next-prod/static/css/cc6d733cdf607b30.css +0 -1
  62. package/dist/chunk-ZJ6CC3MH.mjs +0 -223
  63. /package/.next-prod/static/{GAYKr2BmQpFqJgRJfvQ3D → 7pu1LXbRRLfg05VN3u39s}/_buildManifest.js +0 -0
  64. /package/.next-prod/static/{GAYKr2BmQpFqJgRJfvQ3D → 7pu1LXbRRLfg05VN3u39s}/_ssgManifest.js +0 -0
@@ -1 +1 @@
1
- [{"name":"run-webpack","duration":20691327,"timestamp":204749108,"id":14,"parentId":1,"tags":{},"startTime":1779801780173,"traceId":"2868cd35fd02ca16"},{"name":"run-typescript","duration":16713005,"timestamp":225450994,"id":1519,"parentId":1,"tags":{},"startTime":1779801800875,"traceId":"2868cd35fd02ca16"},{"name":"static-check","duration":1098623,"timestamp":242207653,"id":1522,"parentId":1,"tags":{},"startTime":1779801817632,"traceId":"2868cd35fd02ca16"},{"name":"static-generation","duration":6111104,"timestamp":243692459,"id":1778,"parentId":1,"tags":{},"startTime":1779801819116,"traceId":"2868cd35fd02ca16"},{"name":"collect-build-traces","duration":18808913,"timestamp":243307085,"id":1775,"parentId":1,"tags":{},"startTime":1779801818731,"traceId":"2868cd35fd02ca16"},{"name":"telemetry-flush","duration":54,"timestamp":262119910,"id":1787,"parentId":1,"tags":{},"startTime":1779801837544,"traceId":"2868cd35fd02ca16"},{"name":"next-build","duration":57539004,"timestamp":204580974,"id":1,"tags":{"buildMode":"default","version":"16.2.6","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1779801780005,"traceId":"2868cd35fd02ca16"}]
1
+ [{"name":"run-webpack","duration":19799218,"timestamp":143062609,"id":14,"parentId":1,"tags":{},"startTime":1779817892339,"traceId":"98826c66cc2d55a4"},{"name":"run-typescript","duration":16474894,"timestamp":162871841,"id":1519,"parentId":1,"tags":{},"startTime":1779817912148,"traceId":"98826c66cc2d55a4"},{"name":"static-check","duration":1046300,"timestamp":179379791,"id":1522,"parentId":1,"tags":{},"startTime":1779817928656,"traceId":"98826c66cc2d55a4"},{"name":"static-generation","duration":5774227,"timestamp":180539499,"id":1778,"parentId":1,"tags":{},"startTime":1779817929815,"traceId":"98826c66cc2d55a4"},{"name":"collect-build-traces","duration":18014017,"timestamp":180426813,"id":1775,"parentId":1,"tags":{},"startTime":1779817929703,"traceId":"98826c66cc2d55a4"},{"name":"telemetry-flush","duration":57,"timestamp":198445089,"id":1787,"parentId":1,"tags":{},"startTime":1779817947721,"traceId":"98826c66cc2d55a4"},{"name":"next-build","duration":55513834,"timestamp":142931325,"id":1,"tags":{"buildMode":"default","version":"16.2.6","bundler":"webpack","has-custom-webpack-config":"true","use-build-worker":"false"},"startTime":1779817892207,"traceId":"98826c66cc2d55a4"}]
package/README.md CHANGED
@@ -179,8 +179,9 @@ npm run setup # build + npm link (registers `cockpit` and `cock`)
179
179
  ```bash
180
180
  cockpit browser <id> snapshot # capture accessibility tree
181
181
  cockpit browser <id> click <uid> # click element
182
- cockpit terminal <id> exec "ls" # execute command
183
- cockpit terminal <id> output # get terminal output
182
+ cockpit terminal list # list terminal bubbles
183
+ cockpit terminal <id> output # read terminal output (filter, cursor)
184
+ cockpit connection list --cwd . # list ALL bubbles (term + browser) with user-set titles
184
185
  ```
185
186
 
186
187
  ## Read more
package/README.zh.md CHANGED
@@ -179,8 +179,9 @@ npm run setup # 构建 + npm link(注册 `cockpit` 与 `cock` 命令)
179
179
  ```bash
180
180
  cockpit browser <id> snapshot # 获取页面元素树
181
181
  cockpit browser <id> click <uid> # 点击元素
182
- cockpit terminal <id> exec "ls" # 执行命令
183
- cockpit terminal <id> output # 获取终端输出
182
+ cockpit terminal list # 列出终端气泡
183
+ cockpit terminal <id> output # 读取终端输出(支持过滤、游标)
184
+ cockpit connection list --cwd . # 列出当前项目所有气泡(terminal + browser)含用户起的 title
184
185
  ```
185
186
 
186
187
  ## 阅读更多
@@ -181,11 +181,17 @@ async function cmdSearch() {
181
181
  const pos = positional(subArgs);
182
182
  const q = pos[0];
183
183
  const limit = getInt(subArgs, '--limit') ?? 15;
184
+ // v1.0.216+: opt-in flag to also surface identifier-shaped string literals
185
+ // (tool names / event names / config keys / route paths) that only exist
186
+ // in source as strings, never as identifiers.
187
+ const includeLiterals = subArgs.includes('--include-literals');
184
188
  if (!q) {
185
189
  stderr.write('codegraph search: missing <query>\n');
186
190
  exit(2);
187
191
  }
188
- const resp = await get('/api/projectGraph/search', { q, limit });
192
+ const params = { q, limit };
193
+ if (includeLiterals) params.includeLiterals = 'true';
194
+ const resp = await get('/api/projectGraph/search', params);
189
195
  const data = await resp.json();
190
196
  if (wantJson) { emitJson(data); exit(0); }
191
197
 
@@ -616,15 +622,22 @@ Examples:
616
622
  // call (which runs before this declaration is reached in module order)
617
623
  // doesn't hit a const TDZ.
618
624
  function getSubHelp() { return {
619
- search: `Usage: cock codegraph search <query> [--limit N=15] [--json]
625
+ search: `Usage: cock codegraph search <query> [--limit N=15] [--include-literals] [--json]
620
626
 
621
627
  Purpose: Find symbols (and files) matching a name fragment. Tokenised
622
- match across name + qualifiedName + filePath. Use this when
623
- you know the symbol's name but not its location.
628
+ match across name + qualifiedName + filePath, with case +
629
+ word-separator folding (so 'build_code_index' 'buildCodeIndex'
630
+ ↔ 'BUILD-CODE-INDEX' all collide). Use this when you know the
631
+ symbol's name but not its location.
624
632
 
625
633
  Flags:
626
- --limit N Max symbol hits to return (default 15)
627
- --json Emit raw JSON {files: [...], symbols: [...]}
634
+ --limit N Max symbol hits to return (default 15)
635
+ --include-literals Also search identifier-shaped string literals
636
+ in source (tool names / event names / config
637
+ keys / route paths). Off by default to keep
638
+ results lean. Surfaces names that never appear
639
+ as identifiers, only as strings.
640
+ --json Emit raw JSON {files: [...], symbols: [...]}
628
641
 
629
642
  Output (plain, TAB-separated):
630
643
  sym <TAB> <file>:<line> <TAB> <kind> <TAB> <qname>
@@ -636,7 +649,9 @@ Exit: 0=hits, 1=no hits, 2=usage, 3=server unreachable
636
649
 
637
650
  Examples:
638
651
  cock codegraph search getCodeIndex
652
+ cock codegraph search build_code_index # snake-case query, still finds buildCodeIndex
639
653
  cock codegraph search useChatStore --limit 5
654
+ cock codegraph search 'agent.fork' --include-literals # find a name hiding in a literal
640
655
  cock codegraph search authenticate --json | jq '.symbols[].target'`,
641
656
 
642
657
  callers: `Usage: cock codegraph callers <qname> [--file PATH] [--json]
@@ -0,0 +1,151 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * cockpit connection — cross-type bubble enumeration.
5
+ *
6
+ * One subcommand:
7
+ *
8
+ * cockpit connection list [--cwd PATH] [--all] [--json]
9
+ *
10
+ * Returns a unified listing of terminal + browser bubbles, each with the
11
+ * user-set `title` (if any). Designed for /cc slash mode and ad-hoc
12
+ * "what bubbles exist in this project" lookups before driving them via
13
+ * `cockpit terminal <id> ...` / `cockpit browser <id> ...`.
14
+ *
15
+ * By default only alive bubbles (running terminal / connected browser)
16
+ * are returned. Pass `--all` to include stale entries.
17
+ */
18
+ import { readFileSync } from 'fs';
19
+ import { join, resolve } from 'path';
20
+ import { homedir } from 'os';
21
+
22
+ const argv = process.argv.slice(2);
23
+
24
+ function readServerPort() {
25
+ try {
26
+ return JSON.parse(readFileSync(join(homedir(), '.cockpit', 'server.json'), 'utf8')).port;
27
+ } catch {
28
+ return null;
29
+ }
30
+ }
31
+
32
+ const port = process.env.COCKPIT_PORT || readServerPort() || 3457;
33
+ const baseUrl = `http://localhost:${port}`;
34
+
35
+ const { stdout, stderr, exit } = process;
36
+
37
+ function printHelp() {
38
+ stdout.write(`Usage: cock connection list [--cwd PATH] [--all] [--json]
39
+
40
+ Purpose: Enumerate all bubbles (terminal + browser) across the running
41
+ Cockpit server. Each entry carries the user-set title if any
42
+ (set via the ✎ button next to the bubble's short id), so an
43
+ LLM can map cryptic 4-char ids to human-meaningful purposes.
44
+
45
+ Subcommands:
46
+ list List bubbles (the only subcommand)
47
+
48
+ Flags:
49
+ --cwd PATH Only list bubbles whose project cwd matches PATH
50
+ (canonicalised). Use \$PWD to scope to the
51
+ current shell.
52
+ --all Include dead entries (exited terminals,
53
+ disconnected browsers). Off by default.
54
+ --json Emit raw JSON instead of TAB-separated lines.
55
+
56
+ Output (plain, TAB-separated):
57
+ <type> <TAB> <shortId> <TAB> <title-or-(none)> <TAB> <projectCwd-or-?> <TAB> <command-or-empty>
58
+
59
+ JSON: array of { type, shortId, title?, projectCwd?, tabId?, command?, alive }
60
+
61
+ Exit: 0=hits, 1=no bubbles, 2=usage, 3=server unreachable
62
+
63
+ Examples:
64
+ cockpit connection list # all alive bubbles
65
+ cockpit connection list --cwd \$PWD # this project only
66
+ cockpit connection list --all --json | jq # everything, programmatic
67
+ `);
68
+ }
69
+
70
+ if (argv.length === 0 || argv.includes('--help') || argv.includes('-h')) {
71
+ printHelp();
72
+ exit(0);
73
+ }
74
+
75
+ const sub = argv[0];
76
+ if (sub !== 'list') {
77
+ stderr.write(`Unknown subcommand: ${sub}\n`);
78
+ stderr.write(`Run \`cockpit connection --help\` to see usage.\n`);
79
+ exit(2);
80
+ }
81
+
82
+ // Parse list-subcommand flags.
83
+ const rest = argv.slice(1);
84
+ const flags = { cwd: undefined, all: false, json: false };
85
+ for (let i = 0; i < rest.length; i++) {
86
+ const tok = rest[i];
87
+ if (tok === '--all') flags.all = true;
88
+ else if (tok === '--json') flags.json = true;
89
+ else if (tok === '--cwd') {
90
+ flags.cwd = rest[++i];
91
+ if (!flags.cwd) {
92
+ stderr.write('Missing value for --cwd\n');
93
+ exit(2);
94
+ }
95
+ } else if (tok === '--help' || tok === '-h') {
96
+ printHelp();
97
+ exit(0);
98
+ } else {
99
+ stderr.write(`Unknown flag: ${tok}\n`);
100
+ exit(2);
101
+ }
102
+ }
103
+
104
+ // Hit the server.
105
+ let data;
106
+ try {
107
+ const body = {};
108
+ if (flags.cwd) body.cwd = resolve(flags.cwd);
109
+ if (flags.all) body.all = true;
110
+ const res = await fetch(`${baseUrl}/api/connection/list`, {
111
+ method: 'POST',
112
+ headers: { 'Content-Type': 'application/json' },
113
+ body: JSON.stringify(body),
114
+ signal: AbortSignal.timeout(10_000),
115
+ });
116
+ const j = await res.json().catch(() => null);
117
+ if (!res.ok || !j?.ok) {
118
+ stderr.write(`HTTP ${res.status}: ${j?.error || 'unknown error'}\n`);
119
+ exit(3);
120
+ }
121
+ data = j.data;
122
+ } catch (err) {
123
+ if (err?.cause?.code === 'ECONNREFUSED') {
124
+ stderr.write(`Connection refused: Cockpit server not running at ${baseUrl}\n`);
125
+ } else {
126
+ stderr.write(`Error: ${err.message}\n`);
127
+ }
128
+ exit(3);
129
+ }
130
+
131
+ if (!Array.isArray(data) || data.length === 0) {
132
+ // Empty list — exit 1 so callers can short-circuit cleanly.
133
+ exit(1);
134
+ }
135
+
136
+ if (flags.json) {
137
+ stdout.write(JSON.stringify({ connections: data }, null, 2) + '\n');
138
+ exit(0);
139
+ }
140
+
141
+ // Plain text: TAB-separated, one line per bubble.
142
+ // <type> <shortId> <title> <projectCwd> <command-or-empty>
143
+ const TYPE_LABEL = { terminal: 'term', browser: 'brow' };
144
+ for (const c of data) {
145
+ const type = TYPE_LABEL[c.type] || c.type;
146
+ const title = c.title || '(none)';
147
+ const cwd = c.projectCwd || '?';
148
+ const command = (c.command || '').replace(/\s+/g, ' ').slice(0, 120);
149
+ stdout.write(`${type}\t${c.shortId}\t${title}\t${cwd}\t${command}\n`);
150
+ }
151
+ exit(0);
package/bin/cock.mjs CHANGED
@@ -22,6 +22,7 @@ Commands:
22
22
  browser <id> <action> Control browser bubbles
23
23
  terminal <id> <action> Control terminal bubbles
24
24
  codegraph <subcmd> [...] Query the project code graph (search/risk/affected/...)
25
+ connection list [--cwd …] List all bubbles (term + browser) with user-set titles
25
26
  update Update to latest version
26
27
 
27
28
  Options:
@@ -101,6 +102,16 @@ if (process.argv[2] === 'codegraph') {
101
102
  await flushAndExit(0);
102
103
  }
103
104
 
105
+ if (process.argv[2] === 'connection') {
106
+ process.argv.splice(2, 1);
107
+ // cock-connection.mjs handles flow + exit itself (single subcmd, simple).
108
+ await import('./cock-connection.mjs');
109
+ // import() resolves when the module finishes top-level await; that script
110
+ // already calls process.exit() on its own paths, so this fallback only
111
+ // fires for the 0-exit happy path that finished normally.
112
+ await flushAndExit(0);
113
+ }
114
+
104
115
  if (process.argv[2] === 'update') {
105
116
  console.log('Updating @surething/cockpit...');
106
117
  const result = spawnSync('npm', ['install', '-g', '@surething/cockpit@latest'], { stdio: 'inherit' });
@@ -118,7 +129,7 @@ if (process.argv[2] === 'update') {
118
129
  const { existsSync, mkdirSync } = await import('fs');
119
130
  const { homedir } = await import('os');
120
131
 
121
- const knownCommands = new Set(['browser', 'terminal', 'update', 'help', 'codegraph']);
132
+ const knownCommands = new Set(['browser', 'terminal', 'update', 'help', 'codegraph', 'connection']);
122
133
  const arg = process.argv[2];
123
134
  let projectDir = null;
124
135
 
package/bin/setup-dev.mjs CHANGED
@@ -27,7 +27,6 @@
27
27
  import { existsSync, lstatSync, unlinkSync, symlinkSync, chmodSync } from 'node:fs';
28
28
  import { resolve, dirname } from 'node:path';
29
29
  import { fileURLToPath } from 'node:url';
30
- import { execSync } from 'node:child_process';
31
30
 
32
31
  const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
33
32
  const REPO_ROOT = resolve(SCRIPT_DIR, '..');
@@ -39,15 +38,18 @@ if (!existsSync(SOURCE)) {
39
38
  process.exit(1);
40
39
  }
41
40
 
42
- // Resolve global npm bin dir.
43
- let prefix;
44
- try {
45
- prefix = execSync('npm config get prefix', { encoding: 'utf8' }).trim();
46
- } catch (err) {
47
- console.error('✗ Failed to resolve npm prefix:', err?.message);
48
- process.exit(1);
49
- }
50
- const TARGET = resolve(prefix, 'bin/cockpit-dev');
41
+ // Resolve the bin dir from process.execPath rather than `npm config get
42
+ // prefix`. Why: `sudo npm run setup-dev` runs npm under root's env, where
43
+ // `npm config get prefix` can resolve to a DIFFERENT path than the user's
44
+ // non-sudo npm (because of /root/.npmrc, HOME differences, or sudo's
45
+ // secure_path stripping). process.execPath is just `node`'s own absolute
46
+ // path node lives at `<prefix>/bin/node` on every normal install
47
+ // (brew, nvm, manual), so `dirname(dirname(execPath))` gives the right
48
+ // prefix regardless of sudo.
49
+ //
50
+ // Override with COCKPIT_BIN_DIR=... if you've got an exotic layout.
51
+ const BIN_DIR = process.env.COCKPIT_BIN_DIR || dirname(process.execPath);
52
+ const TARGET = resolve(BIN_DIR, 'cockpit-dev');
51
53
 
52
54
  // Ensure source is executable.
53
55
  try {
@@ -72,9 +74,9 @@ try {
72
74
  } catch (err) {
73
75
  if (err?.code === 'EACCES' || err?.code === 'EPERM') {
74
76
  console.error(`✗ Permission denied creating ${TARGET}`);
75
- console.error(` Either: sudo ln -sf ${SOURCE} ${TARGET}`);
76
- console.error(` Or: configure npm prefix to a user-writable dir`);
77
- console.error(` (e.g. npm config set prefix ~/.npm-global)`);
77
+ console.error(` Run with sudo: sudo npm run setup-dev`);
78
+ console.error(` Or one-liner: sudo ln -sf ${SOURCE} ${TARGET}`);
79
+ console.error(` Or override: COCKPIT_BIN_DIR=~/.local/bin npm run setup-dev`);
78
80
  process.exit(1);
79
81
  }
80
82
  console.error(`✗ Failed:`, err?.message);