@logicseek/hello-cc 1.0.1 → 1.0.2

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 (97) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/README.md +4 -0
  3. package/README.zh-CN.md +4 -0
  4. package/docs/README.md +9 -0
  5. package/docs/README.zh-CN.md +9 -0
  6. package/docs/commands.md +53 -0
  7. package/docs/commands.zh-CN.md +48 -0
  8. package/docs/dsh.md +137 -0
  9. package/docs/dsh.zh-CN.md +139 -0
  10. package/docs/mcp.md +9 -0
  11. package/docs/mcp.zh-CN.md +23 -0
  12. package/docs/native.md +295 -0
  13. package/docs/native.zh-CN.md +253 -0
  14. package/docs/web-handoff.zh-CN.md +53 -0
  15. package/lib/cli/app.mjs +25 -6
  16. package/lib/cli/commands/doctor.mjs +17 -2
  17. package/lib/cli/commands/dsh.mjs +79 -0
  18. package/lib/cli/commands/hook.mjs +241 -90
  19. package/lib/cli/commands/lock.mjs +34 -19
  20. package/lib/cli/commands/mcp.mjs +28 -0
  21. package/lib/cli/commands/native.mjs +130 -0
  22. package/lib/cli/commands/run.mjs +66 -21
  23. package/lib/cli/commands/task.mjs +6 -3
  24. package/lib/cli-args.mjs +4 -0
  25. package/lib/coordination-state.mjs +15 -1
  26. package/lib/core/coordination/event-retention.mjs +14 -2
  27. package/lib/core/coordination/gc-plan.mjs +3 -13
  28. package/lib/core/coordination/locks.mjs +45 -0
  29. package/lib/core/coordination/results.mjs +79 -0
  30. package/lib/core/peers/bindings.mjs +9 -3
  31. package/lib/diagnostics/codex.mjs +121 -0
  32. package/lib/integrations/codex-interactions.mjs +114 -0
  33. package/lib/integrations/dsh-collaboration.mjs +170 -0
  34. package/lib/integrations/dsh-cordis.d.ts +19 -0
  35. package/lib/integrations/dsh-cordis.mjs +177 -0
  36. package/lib/integrations/dsh.bundle.yml +7 -0
  37. package/lib/integrations/dsh.mjs +287 -0
  38. package/lib/integrations/native/claude.mjs +451 -0
  39. package/lib/integrations/native/codex.mjs +242 -0
  40. package/lib/integrations/native/dsh-acp.mjs +343 -0
  41. package/lib/integrations/native/index.mjs +19 -0
  42. package/lib/integrations/native/interactions.mjs +53 -0
  43. package/lib/integrations/native/jsonrpc.mjs +185 -0
  44. package/lib/integrations/peers/identity.mjs +36 -10
  45. package/lib/integrations/peers/processes.mjs +22 -8
  46. package/lib/integrations/providers.mjs +6 -2
  47. package/lib/mcp/scope.mjs +104 -0
  48. package/lib/mcp/stdio.mjs +80 -0
  49. package/lib/mcp/tools.mjs +197 -0
  50. package/lib/process/identity.mjs +3 -1
  51. package/lib/release/release-notes.mjs +9 -0
  52. package/lib/runtime/native/client.mjs +38 -0
  53. package/lib/runtime/native/service.mjs +511 -0
  54. package/lib/runtime/native/store.mjs +121 -0
  55. package/lib/ui/help.mjs +5 -2
  56. package/lib/web/adoption-state.mjs +55 -0
  57. package/lib/web/auto-attach.mjs +18 -2
  58. package/lib/web/codex-app-server.mjs +557 -0
  59. package/lib/web/codex-sessions.mjs +287 -0
  60. package/lib/web/control-lease.mjs +204 -0
  61. package/lib/web/http-routes.mjs +197 -15
  62. package/lib/web/http.mjs +5 -4
  63. package/lib/web/native-sessions.mjs +286 -0
  64. package/lib/web/project-contexts.mjs +2 -1
  65. package/lib/web/pty-sessions.mjs +60 -33
  66. package/lib/web/runtime-main.mjs +98 -6
  67. package/lib/web/session-serialize.mjs +0 -0
  68. package/lib/web/task-results.mjs +76 -0
  69. package/lib/web/tmux-sessions.mjs +92 -11
  70. package/lib/web/tmux-stream.mjs +2 -2
  71. package/lib/web/ui-codex.mjs +550 -0
  72. package/lib/web/ui-command-palette.mjs +119 -0
  73. package/lib/web/ui-handoff.mjs +102 -0
  74. package/lib/web/ui-history.mjs +118 -0
  75. package/lib/web/ui-i18n.mjs +841 -0
  76. package/lib/web/ui-interactions.mjs +78 -0
  77. package/lib/web/ui-login.mjs +101 -0
  78. package/lib/web/ui-native.mjs +165 -0
  79. package/lib/web/ui-preferences.mjs +278 -0
  80. package/lib/web/ui-review.mjs +132 -0
  81. package/lib/web/ui-template.mjs +1106 -576
  82. package/lib/web/ui-terminal-find.mjs +98 -0
  83. package/lib/web/ui-workbench.mjs +94 -0
  84. package/lib/web/ui-workspace.mjs +222 -0
  85. package/package.json +11 -3
  86. package/scripts/check-free-identifiers.mjs +67 -8
  87. package/scripts/codex-diagnostics-installed-acceptance.mjs +72 -0
  88. package/scripts/dsh-cordis-acceptance.mjs +200 -0
  89. package/scripts/dsh-installed-acceptance.mjs +247 -0
  90. package/scripts/dsh-official-acceptance.mjs +180 -0
  91. package/scripts/dsh-web-startup-acceptance.mjs +87 -0
  92. package/scripts/github-release.mjs +3 -1
  93. package/scripts/native-live-acceptance.mjs +369 -0
  94. package/scripts/regression.mjs +243 -89
  95. package/scripts/web-handoff-installed-acceptance.mjs +98 -0
  96. package/scripts/web-native-interaction-acceptance.mjs +204 -0
  97. package/scripts/web-native-model-acceptance.mjs +138 -0
package/lib/ui/help.mjs CHANGED
@@ -8,13 +8,15 @@ export function createHelpFunctions(config = {}) {
8
8
  helpMain() {
9
9
  console.log(`${productName} ${version}
10
10
 
11
- Project-local coordination bus for multiple Claude Code and Codex CLI sessions.
11
+ Project-local coordination bus for Claude Code, Codex, and DeepSeek Harness sessions.
12
12
 
13
13
  Usage:
14
14
  ${cliName} [--root DIR] [--db FILE] [--json] <command> [args]
15
15
 
16
16
  Commands:
17
17
  web Start coordination, shims, tmux, and browser console
18
+ dsh <setup|status|web> Connect DeepSeek Harness through project-local hooks
19
+ native <subcommand> Run owned Codex/Claude/dsh workers through native protocols
18
20
  up Initialize local coordination only
19
21
  down Stop the running hello-cc web runtime
20
22
  update Update the global npm install of hello-cc
@@ -44,7 +46,8 @@ Commands:
44
46
  gc [--older-than DAYS] [--history] [--yes] Clean technical state; opt in to history cleanup
45
47
  doctor Run a read-only database health check (integrity, sizes, row counts)
46
48
  Internal:
47
- hook Hook entrypoint used by Claude/Codex
49
+ mcp serve --peer ID Serve executor-authorized project coordination tools over stdio
50
+ hook Hook entrypoint used by Claude/Codex/dsh
48
51
  find-root Shim helper
49
52
  which-real Shim helper
50
53
 
@@ -0,0 +1,55 @@
1
+ // Persist Web terminal detachment separately from process liveness. Existing
2
+ // audit events survive a runtime restart without changing the database schema.
3
+
4
+ function identityFor(value = {}) {
5
+ const identity = value.adoptionIdentity || value.identity || value;
6
+ const processIdentity = identity.process_identity || identity.processIdentity || {};
7
+ return {
8
+ pid: identity.pid || processIdentity.pid || value.pid || null,
9
+ process_start_token: identity.process_start_token || processIdentity.startToken || null,
10
+ tmux_session_created: identity.tmux_session_created || identity.session_created || null,
11
+ tmux_session_id: identity.tmux_session_id || identity.session_id || null
12
+ };
13
+ }
14
+
15
+ export function writeAdoptionState(db, session, paused, time) {
16
+ const peer = session?.peerId || session?.peer || session?.id;
17
+ if (typeof peer !== 'string' || !peer || typeof paused !== 'boolean' ||
18
+ !Number.isSafeInteger(time) || time < 0) {
19
+ throw new TypeError('Adoption state requires a peer, a boolean paused value, and an integer timestamp');
20
+ }
21
+ const payload = {
22
+ peer,
23
+ pane: session.pane || null,
24
+ identity: identityFor(session),
25
+ source: 'web',
26
+ target_peer: peer,
27
+ runtime_session_id: session.id || null
28
+ };
29
+ db.prepare(`
30
+ INSERT INTO events(type, actor, task_id, payload, created_at)
31
+ VALUES (?, 'web', NULL, ?, ?)
32
+ `).run(paused ? 'web.adoption.paused' : 'web.adoption.resumed', JSON.stringify(payload), time);
33
+ return { ...payload, paused };
34
+ }
35
+
36
+ export function adoptionPaused(db, { peer, pane = null, ...observed } = {}) {
37
+ if (typeof peer !== 'string' || !peer) return false;
38
+ const event = db.prepare(`
39
+ SELECT type, payload FROM events
40
+ WHERE type IN ('web.adoption.paused', 'web.adoption.resumed')
41
+ AND json_valid(payload)
42
+ AND json_extract(payload, '$.peer') = ?
43
+ AND (? IS NULL OR json_extract(payload, '$.pane') = ? OR json_extract(payload, '$.pane') IS NULL)
44
+ ORDER BY id DESC LIMIT 1
45
+ `).get(peer, pane, pane);
46
+ if (!event || event.type !== 'web.adoption.paused') return false;
47
+ const stored = identityFor(JSON.parse(event.payload));
48
+ const current = identityFor(observed);
49
+ // Known identity changes mean a different live terminal. An unavailable
50
+ // observation cannot silently revoke an intentional pause.
51
+ for (const key of Object.keys(stored)) {
52
+ if (stored[key] !== null && current[key] !== null && String(stored[key]) !== String(current[key])) return false;
53
+ }
54
+ return true;
55
+ }
@@ -5,6 +5,9 @@
5
5
  import { inferPeerKind } from '../integrations/providers.mjs';
6
6
  import { runTmux } from '../tmux.mjs';
7
7
  import { inspectProviderProcess } from '../integrations/peers/processes.mjs';
8
+ import { isDshHookBinding } from '../core/peers/bindings.mjs';
9
+ import { inspectProcessIdentity } from '../process/identity.mjs';
10
+ import { adoptionPaused } from './adoption-state.mjs';
8
11
 
9
12
  export function createAutoAttach(deps) {
10
13
  const {
@@ -17,6 +20,8 @@ export function createAutoAttach(deps) {
17
20
  resolveSessionPeerId,
18
21
  reAdoptOrphanManagedTmuxSessions, reapDeadPeersForProject
19
22
  } = deps;
23
+ const execTmux = deps.runTmux || runTmux;
24
+ const inspectIdentity = deps.inspectProcessIdentity || inspectProcessIdentity;
20
25
 
21
26
  function listTmuxPanesOnce() {
22
27
  // Use '|' not '\t' as the field separator: older tmux (3.3a) replaces
@@ -25,7 +30,7 @@ export function createAutoAttach(deps) {
25
30
  // user-created session name could contain '|', corrupting the parse. Callers
26
31
  // that need the session name use tmuxSessionNameForPane(pane.pane) which
27
32
  // queries a single field with no separator issue.
28
- const result = runTmux([
33
+ const result = execTmux([
29
34
  'list-panes',
30
35
  '-a',
31
36
  '-F',
@@ -98,7 +103,7 @@ export function createAutoAttach(deps) {
98
103
  SELECT p.id, p.kind, p.role, p.worktree, p.pid,
99
104
  b.peer AS binding_peer, b.provider, b.provider_session_id,
100
105
  b.provider_session_name, b.resume_mode, b.resume_arg,
101
- b.command AS binding_command, b.runtime_session_id,
106
+ b.command AS binding_command, b.transport AS binding_transport, b.runtime_session_id,
102
107
  b.runtime_target
103
108
  FROM peers p
104
109
  LEFT JOIN peer_bindings b ON b.peer = p.id
@@ -130,12 +135,23 @@ export function createAutoAttach(deps) {
130
135
  const attached = attachedTmuxState(ctx, db);
131
136
 
132
137
  for (const row of rows) {
138
+ if (['native', 'app-server'].includes(row.binding_transport)) continue;
139
+ // A dsh PID/pane belongs to the service, which may host many Agent
140
+ // sessions. A hook's conversation binding grants no terminal control.
141
+ if (isDshHookBinding({ provider: row.provider || row.kind, transport: row.binding_transport })) continue;
133
142
  if (attached.peers.has(row.id)) continue;
134
143
  if (row.binding_peer && attached.peers.has(row.binding_peer)) continue;
135
144
  if (row.runtime_session_id && attached.peers.has(row.runtime_session_id)) continue;
136
145
 
137
146
  const pane = paneByPid.get(Number(row.pid));
138
147
  if (!pane || attached.panes.has(pane.pane)) continue;
148
+ const identity = inspectIdentity(pane.pid);
149
+ if (adoptionPaused(db, {
150
+ peer: row.id,
151
+ pane: pane.pane,
152
+ pid: pane.pid,
153
+ process_identity: identity?.state === 'live' ? identity.identity : null
154
+ })) continue;
139
155
 
140
156
  const binding = row.binding_peer ? {
141
157
  provider: row.provider,