codedeck 0.7.0 → 0.7.1

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 (121) hide show
  1. package/README.md +49 -34
  2. package/dist/cli/commands/claims.js +3 -2
  3. package/dist/cli/commands/claims.js.map +1 -1
  4. package/dist/cli/commands/doctor.js +8 -40
  5. package/dist/cli/commands/doctor.js.map +1 -1
  6. package/dist/cli/commands/logs.js +2 -2
  7. package/dist/cli/commands/logs.js.map +1 -1
  8. package/dist/cli/commands/open.js +8 -9
  9. package/dist/cli/commands/open.js.map +1 -1
  10. package/dist/cli/commands/ps.js +6 -6
  11. package/dist/cli/commands/ps.js.map +1 -1
  12. package/dist/cli/commands/review.js +36 -58
  13. package/dist/cli/commands/review.js.map +1 -1
  14. package/dist/cli/commands/run.js +27 -27
  15. package/dist/cli/commands/run.js.map +1 -1
  16. package/dist/cli/commands/setup.js +96 -314
  17. package/dist/cli/commands/setup.js.map +1 -1
  18. package/dist/cli/commands/show.js +2 -1
  19. package/dist/cli/commands/show.js.map +1 -1
  20. package/dist/cli/commands/ui.js +61 -0
  21. package/dist/cli/commands/ui.js.map +1 -0
  22. package/dist/cli/commands/usage.js +65 -42
  23. package/dist/cli/commands/usage.js.map +1 -1
  24. package/dist/cli/commands/wait.js +3 -2
  25. package/dist/cli/commands/wait.js.map +1 -1
  26. package/dist/cli/index.js +55 -39
  27. package/dist/cli/index.js.map +1 -1
  28. package/dist/cli/web-launch.js +126 -0
  29. package/dist/cli/web-launch.js.map +1 -0
  30. package/dist/config/config.js +0 -70
  31. package/dist/config/config.js.map +1 -1
  32. package/dist/config/paths.js +1 -0
  33. package/dist/config/paths.js.map +1 -1
  34. package/dist/config/setup.js +248 -0
  35. package/dist/config/setup.js.map +1 -0
  36. package/dist/config/web-host.js +31 -0
  37. package/dist/config/web-host.js.map +1 -0
  38. package/dist/config/web-port.js +24 -0
  39. package/dist/config/web-port.js.map +1 -0
  40. package/dist/core/claude-transcript.js +87 -0
  41. package/dist/core/claude-transcript.js.map +1 -1
  42. package/dist/core/errors.js +17 -0
  43. package/dist/core/errors.js.map +1 -1
  44. package/dist/core/models.js +4 -1
  45. package/dist/core/models.js.map +1 -1
  46. package/dist/core/pricing.js +73 -50
  47. package/dist/core/pricing.js.map +1 -1
  48. package/dist/core/roles.js +6 -5
  49. package/dist/core/roles.js.map +1 -1
  50. package/dist/core/run-skills.js +114 -0
  51. package/dist/core/run-skills.js.map +1 -0
  52. package/dist/core/run-usage.js +4 -1
  53. package/dist/core/run-usage.js.map +1 -1
  54. package/dist/core/session.js +6 -16
  55. package/dist/core/session.js.map +1 -1
  56. package/dist/core/usage-query.js +41 -0
  57. package/dist/core/usage-query.js.map +1 -0
  58. package/dist/daemon/build-id.js +30 -0
  59. package/dist/daemon/build-id.js.map +1 -0
  60. package/dist/daemon/daemon.js +1116 -767
  61. package/dist/daemon/daemon.js.map +1 -1
  62. package/dist/daemon/instance-lock.js +48 -0
  63. package/dist/daemon/instance-lock.js.map +1 -0
  64. package/dist/daemon/web-supervisor.js +251 -0
  65. package/dist/daemon/web-supervisor.js.map +1 -0
  66. package/dist/drivers/claude/driver.js +1 -0
  67. package/dist/drivers/claude/driver.js.map +1 -1
  68. package/dist/drivers/codex/driver.js +14 -3
  69. package/dist/drivers/codex/driver.js.map +1 -1
  70. package/dist/drivers/codex/host-skills.js +57 -0
  71. package/dist/drivers/codex/host-skills.js.map +1 -0
  72. package/dist/drivers/opencode/driver.js +6 -2
  73. package/dist/drivers/opencode/driver.js.map +1 -1
  74. package/dist/drivers/session-runtime.js +2 -0
  75. package/dist/drivers/session-runtime.js.map +1 -1
  76. package/dist/drivers/terminal.js +15 -0
  77. package/dist/drivers/terminal.js.map +1 -1
  78. package/dist/git/diff.js +29 -4
  79. package/dist/git/diff.js.map +1 -1
  80. package/dist/open/contract.js.map +1 -1
  81. package/dist/open/pty.js +330 -5
  82. package/dist/open/pty.js.map +1 -1
  83. package/dist/plugin/agents/general.md +33 -6
  84. package/dist/plugin/hooks/pane-ticker.ts +102 -0
  85. package/dist/plugin/hooks/register.tsx +33 -8
  86. package/dist/plugin/mods/agents/pane.ts +259 -136
  87. package/dist/plugin/mods/agents/types.ts +19 -3
  88. package/dist/plugin/statusline.sh +22 -34
  89. package/dist/store/database.js +5 -1
  90. package/dist/store/database.js.map +1 -1
  91. package/dist/store/sessions.js +55 -12
  92. package/dist/store/sessions.js.map +1 -1
  93. package/dist/utils/process.js +2 -16
  94. package/dist/utils/process.js.map +1 -1
  95. package/dist/web/brand.js +59 -0
  96. package/dist/web/brand.js.map +1 -0
  97. package/dist/web/child.js +67 -0
  98. package/dist/web/child.js.map +1 -0
  99. package/dist/web/home-page.js +48 -0
  100. package/dist/web/home-page.js.map +1 -0
  101. package/dist/web/review-page.js +12 -5
  102. package/dist/web/review-page.js.map +1 -1
  103. package/dist/web/security.js +170 -0
  104. package/dist/web/security.js.map +1 -0
  105. package/dist/web/server.js +198 -0
  106. package/dist/web/server.js.map +1 -0
  107. package/dist/web/setup-icons.js +37 -0
  108. package/dist/web/setup-icons.js.map +1 -0
  109. package/dist/web/setup-page.js +1795 -0
  110. package/dist/web/setup-page.js.map +1 -0
  111. package/dist/web/setup-routes.js +475 -0
  112. package/dist/web/setup-routes.js.map +1 -0
  113. package/dist/web/usage-page.js +609 -0
  114. package/dist/web/usage-page.js.map +1 -0
  115. package/dist/web/usage-routes.js +88 -0
  116. package/dist/web/usage-routes.js.map +1 -0
  117. package/dist/web/web-token.js +56 -0
  118. package/dist/web/web-token.js.map +1 -0
  119. package/package.json +1 -1
  120. package/dist/plugin/prompts/_partials/commit.md +0 -145
  121. package/dist/plugin/prompts/_partials/pr-writer.md +0 -186
@@ -0,0 +1,102 @@
1
+ import type { PaneSnapshot } from "../mods/agents/types.js";
2
+
3
+ const TICK_INTERVAL_MS = 1000;
4
+ const REFRESH_INTERVAL_MS = 5000;
5
+ const LIVE_STATUSES = new Set(["working", "starting", "needs_input"]);
6
+
7
+ export interface PaneTickerOptions {
8
+ now: () => number;
9
+ setInterval: (callback: () => void, milliseconds: number) => unknown;
10
+ clearInterval: (handle: unknown) => void;
11
+ invalidate: () => unknown;
12
+ refresh: () => unknown;
13
+ }
14
+
15
+ export interface PaneTicker {
16
+ update(paneOpen: boolean, snapshot: PaneSnapshot | undefined): void;
17
+ refreshed(): void;
18
+ }
19
+
20
+ /** Schedules pane redraws and refresh requests while any worker card is live. */
21
+ export function createPaneTicker(options: PaneTickerOptions): PaneTicker {
22
+ let running = false;
23
+ let handle: unknown;
24
+ let lastRefreshAt = 0;
25
+
26
+ const invoke = (action: () => unknown) => {
27
+ try {
28
+ void Promise.resolve(action()).catch(() => {});
29
+ } catch {
30
+ // Hook failures drop the drawing, so timer work must stay contained.
31
+ }
32
+ };
33
+
34
+ const tick = () => {
35
+ if (!running) return;
36
+ try {
37
+ invoke(options.invalidate);
38
+ const now = options.now();
39
+ if (!Number.isFinite(now) || now - lastRefreshAt < REFRESH_INTERVAL_MS) return;
40
+ lastRefreshAt = now;
41
+ invoke(options.refresh);
42
+ } catch {
43
+ // A failed timer callback must not escape into the hooks runtime.
44
+ }
45
+ };
46
+
47
+ const stop = () => {
48
+ if (!running) return;
49
+ running = false;
50
+ const currentHandle = handle;
51
+ handle = undefined;
52
+ try {
53
+ options.clearInterval(currentHandle);
54
+ } catch {
55
+ // Keep the module alive even if the timer host refuses a clear.
56
+ }
57
+ };
58
+
59
+ const start = () => {
60
+ if (running) return;
61
+ try {
62
+ const now = options.now();
63
+ if (!Number.isFinite(now)) return;
64
+ lastRefreshAt = now;
65
+ running = true;
66
+ handle = options.setInterval(tick, TICK_INTERVAL_MS);
67
+ } catch {
68
+ running = false;
69
+ handle = undefined;
70
+ }
71
+ };
72
+
73
+ const hasLiveRow = (snapshot: PaneSnapshot | undefined): boolean => {
74
+ try {
75
+ return (
76
+ snapshot !== undefined &&
77
+ Array.isArray(snapshot.rows) &&
78
+ snapshot.rows.some((row) => row != null && LIVE_STATUSES.has(row.status))
79
+ );
80
+ } catch {
81
+ return false;
82
+ }
83
+ };
84
+
85
+ return {
86
+ update(paneOpen, snapshot) {
87
+ if (paneOpen && hasLiveRow(snapshot)) {
88
+ start();
89
+ return;
90
+ }
91
+ stop();
92
+ },
93
+ refreshed() {
94
+ try {
95
+ const now = options.now();
96
+ if (Number.isFinite(now)) lastRefreshAt = now;
97
+ } catch {
98
+ // Keep the prior cadence if the injected clock fails.
99
+ }
100
+ },
101
+ };
102
+ }
@@ -7,6 +7,7 @@ import type { Register } from "claude-code";
7
7
  import { formatPane, paneButtonLabel, selectPane } from "../mods/agents/pane.js";
8
8
  import { parseRows } from "../mods/agents/parse.js";
9
9
  import type { PaneSnapshot } from "../mods/agents/types.js";
10
+ import { createPaneTicker, type PaneTicker } from "./pane-ticker.js";
10
11
  import { togglePane } from "./pane-toggle.js";
11
12
 
12
13
  // Stable pane id: 1 to 64 letters, digits, "_" or "-". open carries it into
@@ -51,14 +52,17 @@ const toggleAgentsPane = async ($: Engine$, isOpen: boolean): Promise<boolean> =
51
52
 
52
53
  // Passing $ into a helper is allowed, verified. What the engine refuses is
53
54
  // pulling a namespace off it: `const P = $.process` fails to load the module.
54
- // So refresh takes $ as a parameter and the state register owns travels beside
55
- // it in this object. paneOpen never leaves register, so it stays a bare let.
55
+ // refresh takes $ as a parameter; its state and paneOpen stay in this register.
56
56
  type PaneState = {
57
57
  // Last good snapshot; undefined until one refresh has fully succeeded, which
58
58
  // is how the pane draws nothing rather than a guess.
59
59
  snapshot: PaneSnapshot | undefined;
60
60
  inFlight: boolean;
61
61
  lastRefreshEndedAt: number;
62
+ ticker: PaneTicker | undefined;
63
+ paneOpen: boolean;
64
+ tickInvalidate: () => unknown;
65
+ tickRefresh: () => unknown;
62
66
  // True once session.start saw a CODEDECK_RUN_ID. Cached because ui.render
63
67
  // fires on every drawing pass and must not await an env read to decide
64
68
  // whether to draw one button.
@@ -67,6 +71,13 @@ type PaneState = {
67
71
 
68
72
  const TOOL_REFRESH_GAP_MS = 1500;
69
73
 
74
+ function syncTicker($: Engine$, state: PaneState, refreshCompleted = false): void {
75
+ state.tickInvalidate = () => $.ui.invalidate("ui.render");
76
+ state.tickRefresh = () => refresh($, state);
77
+ if (refreshCompleted) state.ticker?.refreshed();
78
+ state.ticker?.update(state.paneOpen, state.snapshot);
79
+ }
80
+
70
81
  const refresh = async ($: Engine$, state: PaneState): Promise<void> => {
71
82
  // Claim the slot before the first await. Guard and set must not straddle a
72
83
  // yield point: with the `$.env.get` read in between, two tool.call firings
@@ -103,6 +114,7 @@ const refresh = async ($: Engine$, state: PaneState): Promise<void> => {
103
114
  } finally {
104
115
  state.inFlight = false;
105
116
  state.lastRefreshEndedAt = Date.now();
117
+ syncTicker($, state, true);
106
118
  }
107
119
  };
108
120
 
@@ -112,10 +124,21 @@ export const register: Register = (on) => {
112
124
  inFlight: false,
113
125
  lastRefreshEndedAt: 0,
114
126
  hasRun: false,
127
+ ticker: undefined,
128
+ paneOpen: false,
129
+ tickInvalidate: () => undefined,
130
+ tickRefresh: () => undefined,
115
131
  };
116
- let paneOpen = false;
132
+ state.ticker = createPaneTicker({
133
+ now: () => Date.now(),
134
+ setInterval: (callback, milliseconds) => setInterval(callback, milliseconds),
135
+ clearInterval: (handle) => clearInterval(handle as ReturnType<typeof setInterval>),
136
+ invalidate: () => state.tickInvalidate(),
137
+ refresh: () => state.tickRefresh(),
138
+ });
117
139
 
118
140
  on("session.start", async ($, e, next) => {
141
+ syncTicker($, state);
119
142
  // Not "agents": the engine refuses it with `$.command.register: "/agents"
120
143
  // refused: it is the built-in /agents`. "band", "deck" and
121
144
  // "codedeck-agents" were each verified free. The description is load
@@ -145,10 +168,11 @@ export const register: Register = (on) => {
145
168
  // is the one call here not yet verified in a PTY session, paneOpen stays
146
169
  // true and the next /band retries the close, instead of the flag and the
147
170
  // pane desyncing for the rest of the session.
148
- paneOpen = await toggleAgentsPane($, paneOpen);
171
+ state.paneOpen = await toggleAgentsPane($, state.paneOpen);
172
+ syncTicker($, state);
149
173
  await $.ui.invalidate("ui.render");
150
- if (paneOpen) void refresh($, state);
151
- return { text: paneOpen ? "agents pane open" : "agents pane closed" };
174
+ if (state.paneOpen) void refresh($, state);
175
+ return { text: state.paneOpen ? "agents pane open" : "agents pane closed" };
152
176
  });
153
177
 
154
178
  on("turn.complete", async ($, e, next) => {
@@ -172,9 +196,10 @@ export const register: Register = (on) => {
172
196
  // A $ captured from a past render does work, verified, but it outlives the
173
197
  // event it came from and nothing promises how long.
174
198
  if ((e as { element?: string }).element === BUTTON_KEY) {
175
- paneOpen = await toggleAgentsPane($, paneOpen);
199
+ state.paneOpen = await toggleAgentsPane($, state.paneOpen);
200
+ syncTicker($, state);
176
201
  await $.ui.invalidate("ui.render");
177
- if (paneOpen) void refresh($, state);
202
+ if (state.paneOpen) void refresh($, state);
178
203
  }
179
204
  return await next(e);
180
205
  });