@gajae-code/coding-agent 0.5.2 → 0.5.3

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 (78) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/types/async/job-manager.d.ts +6 -0
  3. package/dist/types/dap/client.d.ts +2 -1
  4. package/dist/types/edit/read-file.d.ts +6 -0
  5. package/dist/types/eval/js/context-manager.d.ts +3 -0
  6. package/dist/types/eval/js/executor.d.ts +1 -0
  7. package/dist/types/exec/bash-executor.d.ts +2 -0
  8. package/dist/types/gjc-runtime/tmux-sessions.d.ts +7 -1
  9. package/dist/types/lsp/types.d.ts +2 -0
  10. package/dist/types/modes/bridge/bridge-mode.d.ts +1 -0
  11. package/dist/types/modes/components/model-selector.d.ts +2 -0
  12. package/dist/types/modes/components/oauth-selector.d.ts +1 -0
  13. package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +1 -0
  14. package/dist/types/modes/components/tool-execution.d.ts +1 -0
  15. package/dist/types/runtime/process-lifecycle.d.ts +108 -0
  16. package/dist/types/runtime-mcp/transports/stdio.d.ts +1 -0
  17. package/dist/types/runtime-mcp/types.d.ts +2 -0
  18. package/dist/types/session/agent-session.d.ts +17 -1
  19. package/dist/types/session/artifacts.d.ts +4 -1
  20. package/dist/types/session/streaming-output.d.ts +5 -0
  21. package/dist/types/slash-commands/helpers/fast-status-report.d.ts +76 -0
  22. package/dist/types/tools/bash.d.ts +1 -0
  23. package/dist/types/tools/browser/tab-supervisor.d.ts +9 -0
  24. package/dist/types/tools/sqlite-reader.d.ts +2 -1
  25. package/package.json +7 -7
  26. package/src/async/job-manager.ts +153 -39
  27. package/src/config/file-lock.ts +9 -1
  28. package/src/dap/client.ts +105 -64
  29. package/src/dap/session.ts +44 -7
  30. package/src/edit/read-file.ts +19 -1
  31. package/src/eval/js/context-manager.ts +228 -65
  32. package/src/eval/js/executor.ts +2 -0
  33. package/src/eval/js/index.ts +1 -0
  34. package/src/eval/js/worker-core.ts +10 -6
  35. package/src/eval/py/executor.ts +68 -19
  36. package/src/eval/py/kernel.ts +46 -22
  37. package/src/eval/py/runner.py +68 -14
  38. package/src/exec/bash-executor.ts +49 -13
  39. package/src/gjc-runtime/tmux-gc.ts +86 -37
  40. package/src/gjc-runtime/tmux-sessions.ts +44 -6
  41. package/src/internal-urls/artifact-protocol.ts +10 -1
  42. package/src/internal-urls/docs-index.generated.ts +2 -2
  43. package/src/lsp/client.ts +64 -26
  44. package/src/lsp/index.ts +2 -1
  45. package/src/lsp/lspmux.ts +33 -9
  46. package/src/lsp/types.ts +2 -0
  47. package/src/modes/bridge/bridge-mode.ts +21 -0
  48. package/src/modes/components/assistant-message.ts +10 -2
  49. package/src/modes/components/bash-execution.ts +5 -1
  50. package/src/modes/components/eval-execution.ts +5 -1
  51. package/src/modes/components/model-selector.ts +34 -2
  52. package/src/modes/components/oauth-selector.ts +5 -0
  53. package/src/modes/components/runtime-mcp-add-wizard.ts +58 -7
  54. package/src/modes/components/skill-message.ts +24 -16
  55. package/src/modes/components/tool-execution.ts +6 -0
  56. package/src/modes/controllers/extension-ui-controller.ts +33 -6
  57. package/src/modes/controllers/input-controller.ts +5 -0
  58. package/src/modes/controllers/selector-controller.ts +6 -1
  59. package/src/modes/utils/ui-helpers.ts +5 -2
  60. package/src/runtime/process-lifecycle.ts +400 -0
  61. package/src/runtime-mcp/manager.ts +164 -50
  62. package/src/runtime-mcp/transports/http.ts +12 -11
  63. package/src/runtime-mcp/transports/stdio.ts +64 -38
  64. package/src/runtime-mcp/types.ts +3 -0
  65. package/src/sdk.ts +27 -0
  66. package/src/session/agent-session.ts +168 -22
  67. package/src/session/artifacts.ts +17 -2
  68. package/src/session/blob-store.ts +36 -2
  69. package/src/session/session-manager.ts +29 -13
  70. package/src/session/streaming-output.ts +54 -3
  71. package/src/slash-commands/builtin-registry.ts +30 -3
  72. package/src/slash-commands/helpers/fast-status-report.ts +111 -0
  73. package/src/tools/archive-reader.ts +10 -1
  74. package/src/tools/bash.ts +11 -4
  75. package/src/tools/browser/tab-supervisor.ts +22 -0
  76. package/src/tools/browser.ts +38 -4
  77. package/src/tools/read.ts +11 -12
  78. package/src/tools/sqlite-reader.ts +19 -5
@@ -22,17 +22,23 @@ export interface GjcTmuxSessionStatus {
22
22
  branch?: string;
23
23
  branchSlug?: string;
24
24
  project?: string;
25
+ panePids: number[];
26
+ profile?: string;
25
27
  }
26
28
 
27
29
  export interface GjcTmuxSessionTagsForGc {
28
30
  profile?: string;
29
31
  project?: string;
30
32
  branch?: string;
33
+ branchSlug?: string;
34
+ createdAt?: string;
35
+ attached?: boolean;
36
+ panePids?: number[];
31
37
  }
32
38
 
33
39
  export interface GjcTmuxSessionsForGc {
34
40
  tagged: GjcTmuxSessionStatus[];
35
- untagged: string[];
41
+ untagged: GjcTmuxSessionStatus[];
36
42
  }
37
43
 
38
44
  function runTmux(args: string[], env: NodeJS.ProcessEnv = process.env): string {
@@ -68,21 +74,27 @@ function parseSessionLine(line: string): GjcTmuxSessionStatus | null {
68
74
  profile = "",
69
75
  bindings = "",
70
76
  panes = "0",
77
+ panePids = "",
71
78
  branch = "",
72
79
  branchSlug = "",
73
80
  project = "",
74
81
  ] = line.split("\t");
75
- if (!name || profile !== GJC_TMUX_PROFILE_VALUE) return null;
82
+ if (!name) return null;
76
83
  return {
77
84
  name,
78
85
  attached: parseBooleanFlag(attached),
79
86
  windows: parseNumber(windows),
80
87
  panes: parseNumber(panes),
88
+ panePids: panePids
89
+ .split(",")
90
+ .map(pid => parseNumber(pid))
91
+ .filter(pid => pid > 0),
81
92
  bindings,
82
93
  createdAt: normalizeTmuxCreatedAt(created),
83
94
  branch: branch || undefined,
84
95
  branchSlug: branchSlug || undefined,
85
96
  project: project || undefined,
97
+ profile: profile || undefined,
86
98
  };
87
99
  }
88
100
 
@@ -103,7 +115,7 @@ function runListSessions(format: string, env: NodeJS.ProcessEnv = process.env):
103
115
 
104
116
  function listSessionLines(env: NodeJS.ProcessEnv = process.env): string[] {
105
117
  return runListSessions(
106
- `#{session_name}\t#{session_windows}\t#{session_attached}\t#{session_created}\t#{${GJC_TMUX_PROFILE_OPTION}}\t#{session_key_table}\t#{session_panes}\t#{${GJC_TMUX_BRANCH_OPTION}}\t#{${GJC_TMUX_BRANCH_SLUG_OPTION}}\t#{${GJC_TMUX_PROJECT_OPTION}}`,
118
+ `#{session_name}\t#{session_windows}\t#{session_attached}\t#{session_created}\t#{${GJC_TMUX_PROFILE_OPTION}}\t#{session_key_table}\t#{session_panes}\t#{pane_pid}\t#{${GJC_TMUX_BRANCH_OPTION}}\t#{${GJC_TMUX_BRANCH_SLUG_OPTION}}\t#{${GJC_TMUX_PROJECT_OPTION}}`,
107
119
  env,
108
120
  );
109
121
  }
@@ -115,17 +127,35 @@ function listRawTmuxSessionNames(env: NodeJS.ProcessEnv = process.env): string[]
115
127
  export function listGjcTmuxSessions(env: NodeJS.ProcessEnv = process.env): GjcTmuxSessionStatus[] {
116
128
  return listSessionLines(env)
117
129
  .map(parseSessionLine)
118
- .filter((session): session is GjcTmuxSessionStatus => session != null)
130
+ .filter((session): session is GjcTmuxSessionStatus => session?.profile === GJC_TMUX_PROFILE_VALUE)
119
131
  .sort((a, b) => a.name.localeCompare(b.name));
120
132
  }
121
133
 
122
134
  /** @internal */
123
135
  export function listTmuxSessionsForGc(env: NodeJS.ProcessEnv = process.env): GjcTmuxSessionsForGc {
124
- const tagged = listGjcTmuxSessions(env);
136
+ const sessions = listSessionLines(env)
137
+ .map(parseSessionLine)
138
+ .filter((session): session is GjcTmuxSessionStatus => session != null);
139
+ const tagged = sessions
140
+ .filter(session => session.profile === GJC_TMUX_PROFILE_VALUE)
141
+ .sort((a, b) => a.name.localeCompare(b.name));
125
142
  const taggedNames = new Set(tagged.map(session => session.name));
143
+ const byName = new Map(sessions.map(session => [session.name, session]));
126
144
  const untagged = listRawTmuxSessionNames(env)
127
145
  .filter(name => !taggedNames.has(name))
128
- .sort((a, b) => a.localeCompare(b));
146
+ .map(
147
+ name =>
148
+ byName.get(name) ?? {
149
+ name,
150
+ attached: false,
151
+ windows: 0,
152
+ panes: 0,
153
+ panePids: [],
154
+ bindings: "",
155
+ createdAt: "",
156
+ },
157
+ )
158
+ .sort((a, b) => a.name.localeCompare(b.name));
129
159
  return { tagged, untagged };
130
160
  }
131
161
 
@@ -192,15 +222,23 @@ export function readTmuxSessionTagsForGc(
192
222
  sessionName: string,
193
223
  env: NodeJS.ProcessEnv = process.env,
194
224
  ): GjcTmuxSessionTagsForGc {
225
+ const session = listGjcTmuxSessions(env).find(candidate => candidate.name === sessionName);
195
226
  return {
196
227
  profile: readExactOptionForGc(sessionName, GJC_TMUX_PROFILE_OPTION, env),
197
228
  project: readExactOptionForGc(sessionName, GJC_TMUX_PROJECT_OPTION, env),
198
229
  branch: readExactOptionForGc(sessionName, GJC_TMUX_BRANCH_OPTION, env),
230
+ branchSlug: readExactOptionForGc(sessionName, GJC_TMUX_BRANCH_SLUG_OPTION, env),
231
+ createdAt: session?.createdAt,
232
+ attached: session?.attached,
233
+ panePids: session?.panePids,
199
234
  };
200
235
  }
201
236
 
202
237
  export function removeGjcTmuxSession(sessionName: string, env: NodeJS.ProcessEnv = process.env): GjcTmuxSessionStatus {
203
238
  const session = statusGjcTmuxSession(sessionName, env);
239
+ if (session.attached || session.panePids.length > 0) {
240
+ throw new Error(`gjc_tmux_session_live:${sessionName}`);
241
+ }
204
242
  if (readProfileForExactTarget(session.name, env) !== GJC_TMUX_PROFILE_VALUE) {
205
243
  throw new Error(`gjc_tmux_session_not_managed:${sessionName}`);
206
244
  }
@@ -63,7 +63,16 @@ export class ArtifactProtocolHandler implements ProtocolHandler {
63
63
  throw new Error(`artifact://${id} not found`);
64
64
  }
65
65
 
66
- const content = await Bun.file(foundPath).text();
66
+ // F20: cap the materialized artifact so reading a huge spilled artifact cannot
67
+ // buffer GBs into memory (the range selector is applied downstream, so without a
68
+ // cap a `artifact://id:range` over a multi-GB artifact still reads it whole).
69
+ const MAX_ARTIFACT_READ_BYTES = 16 * 1024 * 1024;
70
+ const file = Bun.file(foundPath);
71
+ const fullSize = file.size;
72
+ const content =
73
+ fullSize > MAX_ARTIFACT_READ_BYTES
74
+ ? `${await file.slice(0, MAX_ARTIFACT_READ_BYTES).text()}\n\n[Artifact truncated: first ${MAX_ARTIFACT_READ_BYTES} of ${fullSize} bytes shown; use a narrower range or a specialized tool for the full content.]`
75
+ : await file.text();
67
76
  return {
68
77
  url: url.href,
69
78
  content,