aicodeman 0.9.14 → 1.1.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.
- package/README.md +5 -5
- package/dist/attachment-magic.d.ts +5 -0
- package/dist/attachment-magic.d.ts.map +1 -0
- package/dist/attachment-magic.js +34 -0
- package/dist/attachment-magic.js.map +1 -0
- package/dist/attachment-registry.d.ts +72 -0
- package/dist/attachment-registry.d.ts.map +1 -0
- package/dist/attachment-registry.js +166 -0
- package/dist/attachment-registry.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +85 -0
- package/dist/cli.js.map +1 -1
- package/dist/config/attachment-guard.d.ts +71 -0
- package/dist/config/attachment-guard.d.ts.map +1 -0
- package/dist/config/attachment-guard.js +118 -0
- package/dist/config/attachment-guard.js.map +1 -0
- package/dist/document-conversion-limiter.d.ts +27 -0
- package/dist/document-conversion-limiter.d.ts.map +1 -0
- package/dist/document-conversion-limiter.js +64 -0
- package/dist/document-conversion-limiter.js.map +1 -0
- package/dist/document-preview-cache.d.ts +15 -0
- package/dist/document-preview-cache.d.ts.map +1 -0
- package/dist/document-preview-cache.js +261 -0
- package/dist/document-preview-cache.js.map +1 -0
- package/dist/document-thumbnailer.d.ts +9 -0
- package/dist/document-thumbnailer.d.ts.map +1 -0
- package/dist/document-thumbnailer.js +70 -0
- package/dist/document-thumbnailer.js.map +1 -0
- package/dist/hooks-config.d.ts +17 -0
- package/dist/hooks-config.d.ts.map +1 -1
- package/dist/hooks-config.js +164 -73
- package/dist/hooks-config.js.map +1 -1
- package/dist/image-watcher.d.ts +6 -1
- package/dist/image-watcher.d.ts.map +1 -1
- package/dist/image-watcher.js +52 -7
- package/dist/image-watcher.js.map +1 -1
- package/dist/session-attachment-history.d.ts +19 -0
- package/dist/session-attachment-history.d.ts.map +1 -0
- package/dist/session-attachment-history.js +63 -0
- package/dist/session-attachment-history.js.map +1 -0
- package/dist/session.d.ts +11 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +45 -0
- package/dist/session.js.map +1 -1
- package/dist/tmux-manager.d.ts.map +1 -1
- package/dist/tmux-manager.js +6 -1
- package/dist/tmux-manager.js.map +1 -1
- package/dist/types/session.d.ts +35 -0
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/session.js.map +1 -1
- package/dist/types/tools.d.ts +35 -1
- package/dist/types/tools.d.ts.map +1 -1
- package/dist/types/tools.js +2 -1
- package/dist/types/tools.js.map +1 -1
- package/dist/usage-telemetry.d.ts +102 -0
- package/dist/usage-telemetry.d.ts.map +1 -0
- package/dist/usage-telemetry.js +130 -0
- package/dist/usage-telemetry.js.map +1 -0
- package/dist/web/middleware/auth.d.ts.map +1 -1
- package/dist/web/middleware/auth.js +4 -3
- package/dist/web/middleware/auth.js.map +1 -1
- package/dist/web/plan-usage-latest.d.ts +15 -0
- package/dist/web/plan-usage-latest.d.ts.map +1 -0
- package/dist/web/plan-usage-latest.js +20 -0
- package/dist/web/plan-usage-latest.js.map +1 -0
- package/dist/web/public/api-client.c9b1cddc.js.gz +0 -0
- package/dist/web/public/app.9daf49ad.js +37 -0
- package/dist/web/public/app.9daf49ad.js.br +0 -0
- package/dist/web/public/app.9daf49ad.js.gz +0 -0
- package/dist/web/public/{constants.8fa1a65f.js → constants.00fa5405.js} +2 -0
- package/dist/web/public/constants.00fa5405.js.br +0 -0
- package/dist/web/public/constants.00fa5405.js.gz +0 -0
- package/dist/web/public/fonts/jetbrains-mono-variable.woff2 +0 -0
- package/dist/web/public/fonts/manrope-variable.woff2 +0 -0
- package/dist/web/public/image-input.0ea86695.js.gz +0 -0
- package/dist/web/public/index.html +59 -35
- package/dist/web/public/index.html.br +0 -0
- package/dist/web/public/index.html.gz +0 -0
- package/dist/web/public/input-cjk.b8686b5e.js.gz +0 -0
- package/dist/web/public/keyboard-accessory.bc753cc7.js.gz +0 -0
- package/dist/web/public/mobile-handlers.763a7439.js.gz +0 -0
- package/dist/web/public/mobile.06b38d3a.css +1 -0
- package/dist/web/public/mobile.06b38d3a.css.br +0 -0
- package/dist/web/public/mobile.06b38d3a.css.gz +0 -0
- package/dist/web/public/notification-manager.9c984ac2.js.gz +0 -0
- package/dist/web/public/orchestrator-panel.js.gz +0 -0
- package/dist/web/public/{panels-ui.6bb3169f.js → panels-ui.2f467969.js} +141 -87
- package/dist/web/public/panels-ui.2f467969.js.br +0 -0
- package/dist/web/public/panels-ui.2f467969.js.gz +0 -0
- package/dist/web/public/ralph-panel.6de2d0f8.js.gz +0 -0
- package/dist/web/public/ralph-wizard.13a1831e.js.gz +0 -0
- package/dist/web/public/respawn-ui.2d249da9.js.gz +0 -0
- package/dist/web/public/session-ui.1463b824.js +36 -0
- package/dist/web/public/session-ui.1463b824.js.br +0 -0
- package/dist/web/public/session-ui.1463b824.js.gz +0 -0
- package/dist/web/public/settings-ui.44b99ce0.js +55 -0
- package/dist/web/public/settings-ui.44b99ce0.js.br +0 -0
- package/dist/web/public/settings-ui.44b99ce0.js.gz +0 -0
- package/dist/web/public/styles.c13845d5.css +1 -0
- package/dist/web/public/styles.c13845d5.css.br +0 -0
- package/dist/web/public/styles.c13845d5.css.gz +0 -0
- package/dist/web/public/subagent-windows.a366a4ad.js.gz +0 -0
- package/dist/web/public/sw.js.gz +0 -0
- package/dist/web/public/terminal-ui.5bf97f7e.js +3 -0
- package/dist/web/public/terminal-ui.5bf97f7e.js.br +0 -0
- package/dist/web/public/terminal-ui.5bf97f7e.js.gz +0 -0
- package/dist/web/public/upload.html.gz +0 -0
- package/dist/web/public/vendor/marked.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-fit.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js +2 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.br +0 -0
- package/dist/web/public/vendor/xterm-addon-serialize.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-unicode11.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-addon-webgl.min.js.gz +0 -0
- package/dist/web/public/vendor/xterm-zerolag-input.137ad9f0.js.gz +0 -0
- package/dist/web/public/vendor/xterm.css.gz +0 -0
- package/dist/web/public/vendor/xterm.min.js.gz +0 -0
- package/dist/web/public/voice-input.085e9e73.js.gz +0 -0
- package/dist/web/routes/file-routes.d.ts +2 -2
- package/dist/web/routes/file-routes.d.ts.map +1 -1
- package/dist/web/routes/file-routes.js +457 -17
- package/dist/web/routes/file-routes.js.map +1 -1
- package/dist/web/routes/index.d.ts +1 -0
- package/dist/web/routes/index.d.ts.map +1 -1
- package/dist/web/routes/index.js +1 -0
- package/dist/web/routes/index.js.map +1 -1
- package/dist/web/routes/session-routes.d.ts.map +1 -1
- package/dist/web/routes/session-routes.js +31 -2
- package/dist/web/routes/session-routes.js.map +1 -1
- package/dist/web/routes/status-telemetry-routes.d.ts +17 -0
- package/dist/web/routes/status-telemetry-routes.d.ts.map +1 -0
- package/dist/web/routes/status-telemetry-routes.js +57 -0
- package/dist/web/routes/status-telemetry-routes.js.map +1 -0
- package/dist/web/routes/system-routes.d.ts.map +1 -1
- package/dist/web/routes/system-routes.js +21 -1
- package/dist/web/routes/system-routes.js.map +1 -1
- package/dist/web/schemas.d.ts +30 -1
- package/dist/web/schemas.d.ts.map +1 -1
- package/dist/web/schemas.js +52 -0
- package/dist/web/schemas.js.map +1 -1
- package/dist/web/sensitive-path.d.ts +24 -0
- package/dist/web/sensitive-path.d.ts.map +1 -0
- package/dist/web/sensitive-path.js +39 -0
- package/dist/web/sensitive-path.js.map +1 -0
- package/dist/web/server.d.ts +13 -0
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +77 -2
- package/dist/web/server.js.map +1 -1
- package/dist/web/session-listener-wiring.d.ts +5 -1
- package/dist/web/session-listener-wiring.d.ts.map +1 -1
- package/dist/web/session-listener-wiring.js +9 -1
- package/dist/web/session-listener-wiring.js.map +1 -1
- package/dist/web/sse-events.d.ts +6 -0
- package/dist/web/sse-events.d.ts.map +1 -1
- package/dist/web/sse-events.js +6 -0
- package/dist/web/sse-events.js.map +1 -1
- package/package.json +2 -1
- package/scripts/postinstall.js +3 -0
- package/dist/web/public/app.a23f8bf6.js +0 -35
- package/dist/web/public/app.a23f8bf6.js.br +0 -0
- package/dist/web/public/app.a23f8bf6.js.gz +0 -0
- package/dist/web/public/constants.8fa1a65f.js.br +0 -0
- package/dist/web/public/constants.8fa1a65f.js.gz +0 -0
- package/dist/web/public/mobile.c7513aed.css +0 -1
- package/dist/web/public/mobile.c7513aed.css.br +0 -0
- package/dist/web/public/mobile.c7513aed.css.gz +0 -0
- package/dist/web/public/panels-ui.6bb3169f.js.br +0 -0
- package/dist/web/public/panels-ui.6bb3169f.js.gz +0 -0
- package/dist/web/public/session-ui.34f25fdf.js +0 -36
- package/dist/web/public/session-ui.34f25fdf.js.br +0 -0
- package/dist/web/public/session-ui.34f25fdf.js.gz +0 -0
- package/dist/web/public/settings-ui.3a341938.js +0 -55
- package/dist/web/public/settings-ui.3a341938.js.br +0 -0
- package/dist/web/public/settings-ui.3a341938.js.gz +0 -0
- package/dist/web/public/styles.c14ecd8a.css +0 -1
- package/dist/web/public/styles.c14ecd8a.css.br +0 -0
- package/dist/web/public/styles.c14ecd8a.css.gz +0 -0
- package/dist/web/public/terminal-ui.1f5b45cf.js +0 -3
- package/dist/web/public/terminal-ui.1f5b45cf.js.br +0 -0
- package/dist/web/public/terminal-ui.1f5b45cf.js.gz +0 -0
package/dist/hooks-config.js
CHANGED
|
@@ -27,6 +27,27 @@ import { existsSync } from 'node:fs';
|
|
|
27
27
|
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
28
28
|
import { join } from 'node:path';
|
|
29
29
|
import { HOOK_TIMEOUT_MS } from './config/auth-config.js';
|
|
30
|
+
/**
|
|
31
|
+
* Serializes read-modify-write access to a `settings.local.json` path. Every
|
|
32
|
+
* writer in this module (hooks, env, model, statusLine) shares this map, so
|
|
33
|
+
* concurrent updates to the SAME file — e.g. session-create writing hooks/model
|
|
34
|
+
* while an App-Settings toggle injects the statusLine into the same repo — can't
|
|
35
|
+
* lose each other's changes through interleaved read-then-write. Per-path chains
|
|
36
|
+
* are independent; the map self-prunes when a path's chain goes idle.
|
|
37
|
+
*/
|
|
38
|
+
const settingsWriteLocks = new Map();
|
|
39
|
+
function withSettingsLock(path, fn) {
|
|
40
|
+
const prev = settingsWriteLocks.get(path) ?? Promise.resolve();
|
|
41
|
+
const run = prev.then(fn, fn); // run after the prior writer, regardless of its outcome
|
|
42
|
+
// Tail never rejects, so a failed write doesn't poison subsequent writers.
|
|
43
|
+
const tail = run.then(() => { }, () => { });
|
|
44
|
+
settingsWriteLocks.set(path, tail);
|
|
45
|
+
void tail.then(() => {
|
|
46
|
+
if (settingsWriteLocks.get(path) === tail)
|
|
47
|
+
settingsWriteLocks.delete(path);
|
|
48
|
+
});
|
|
49
|
+
return run;
|
|
50
|
+
}
|
|
30
51
|
/**
|
|
31
52
|
* Generates the hooks section for .claude/settings.local.json
|
|
32
53
|
*
|
|
@@ -96,29 +117,31 @@ export async function stripCaseEnvKeys(casePath, keysToRemove) {
|
|
|
96
117
|
if (keysToRemove.length === 0)
|
|
97
118
|
return;
|
|
98
119
|
const settingsPath = join(casePath, '.claude', 'settings.local.json');
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
await withSettingsLock(settingsPath, async () => {
|
|
121
|
+
if (!existsSync(settingsPath))
|
|
122
|
+
return;
|
|
123
|
+
let existing;
|
|
124
|
+
try {
|
|
125
|
+
existing = JSON.parse(await readFile(settingsPath, 'utf-8'));
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return; // Malformed — don't rewrite it
|
|
129
|
+
}
|
|
130
|
+
const env = existing.env;
|
|
131
|
+
if (!env)
|
|
132
|
+
return;
|
|
133
|
+
let changed = false;
|
|
134
|
+
for (const key of keysToRemove) {
|
|
135
|
+
if (key in env) {
|
|
136
|
+
delete env[key];
|
|
137
|
+
changed = true;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (!changed)
|
|
141
|
+
return;
|
|
142
|
+
existing.env = env;
|
|
143
|
+
await writeFile(settingsPath, JSON.stringify(existing, null, 2) + '\n');
|
|
144
|
+
});
|
|
122
145
|
}
|
|
123
146
|
/**
|
|
124
147
|
* Updates env vars in .claude/settings.local.json for the given case path.
|
|
@@ -126,28 +149,30 @@ export async function stripCaseEnvKeys(casePath, keysToRemove) {
|
|
|
126
149
|
*/
|
|
127
150
|
export async function updateCaseEnvVars(casePath, envVars) {
|
|
128
151
|
const claudeDir = join(casePath, '.claude');
|
|
129
|
-
if (!existsSync(claudeDir)) {
|
|
130
|
-
await mkdir(claudeDir, { recursive: true });
|
|
131
|
-
}
|
|
132
152
|
const settingsPath = join(claudeDir, 'settings.local.json');
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
catch {
|
|
138
|
-
existing = {};
|
|
139
|
-
}
|
|
140
|
-
const currentEnv = existing.env || {};
|
|
141
|
-
for (const [key, value] of Object.entries(envVars)) {
|
|
142
|
-
if (value) {
|
|
143
|
-
currentEnv[key] = value;
|
|
153
|
+
await withSettingsLock(settingsPath, async () => {
|
|
154
|
+
if (!existsSync(claudeDir)) {
|
|
155
|
+
await mkdir(claudeDir, { recursive: true });
|
|
144
156
|
}
|
|
145
|
-
|
|
146
|
-
|
|
157
|
+
let existing = {};
|
|
158
|
+
try {
|
|
159
|
+
existing = JSON.parse(await readFile(settingsPath, 'utf-8'));
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
existing = {};
|
|
163
|
+
}
|
|
164
|
+
const currentEnv = existing.env || {};
|
|
165
|
+
for (const [key, value] of Object.entries(envVars)) {
|
|
166
|
+
if (value) {
|
|
167
|
+
currentEnv[key] = value;
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
delete currentEnv[key];
|
|
171
|
+
}
|
|
147
172
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
173
|
+
existing.env = currentEnv;
|
|
174
|
+
await writeFile(settingsPath, JSON.stringify(existing, null, 2) + '\n');
|
|
175
|
+
});
|
|
151
176
|
}
|
|
152
177
|
/**
|
|
153
178
|
* Updates the `model` field in .claude/settings.local.json for the given case path.
|
|
@@ -155,24 +180,26 @@ export async function updateCaseEnvVars(casePath, envVars) {
|
|
|
155
180
|
*/
|
|
156
181
|
export async function updateCaseModel(casePath, model) {
|
|
157
182
|
const claudeDir = join(casePath, '.claude');
|
|
158
|
-
if (!existsSync(claudeDir)) {
|
|
159
|
-
await mkdir(claudeDir, { recursive: true });
|
|
160
|
-
}
|
|
161
183
|
const settingsPath = join(claudeDir, 'settings.local.json');
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
184
|
+
await withSettingsLock(settingsPath, async () => {
|
|
185
|
+
if (!existsSync(claudeDir)) {
|
|
186
|
+
await mkdir(claudeDir, { recursive: true });
|
|
187
|
+
}
|
|
188
|
+
let existing = {};
|
|
189
|
+
try {
|
|
190
|
+
existing = JSON.parse(await readFile(settingsPath, 'utf-8'));
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
existing = {};
|
|
194
|
+
}
|
|
195
|
+
if (model) {
|
|
196
|
+
existing.model = model;
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
delete existing.model;
|
|
200
|
+
}
|
|
201
|
+
await writeFile(settingsPath, JSON.stringify(existing, null, 2) + '\n');
|
|
202
|
+
});
|
|
176
203
|
}
|
|
177
204
|
/**
|
|
178
205
|
* Writes hooks config to .claude/settings.local.json in the given case path.
|
|
@@ -180,20 +207,84 @@ export async function updateCaseModel(casePath, model) {
|
|
|
180
207
|
*/
|
|
181
208
|
export async function writeHooksConfig(casePath) {
|
|
182
209
|
const claudeDir = join(casePath, '.claude');
|
|
183
|
-
if (!existsSync(claudeDir)) {
|
|
184
|
-
await mkdir(claudeDir, { recursive: true });
|
|
185
|
-
}
|
|
186
210
|
const settingsPath = join(claudeDir, 'settings.local.json');
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
211
|
+
await withSettingsLock(settingsPath, async () => {
|
|
212
|
+
if (!existsSync(claudeDir)) {
|
|
213
|
+
await mkdir(claudeDir, { recursive: true });
|
|
214
|
+
}
|
|
215
|
+
let existing = {};
|
|
216
|
+
try {
|
|
217
|
+
existing = JSON.parse(await readFile(settingsPath, 'utf-8'));
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
// If file is malformed or doesn't exist, start fresh
|
|
221
|
+
existing = {};
|
|
222
|
+
}
|
|
223
|
+
const hooksConfig = generateHooksConfig();
|
|
224
|
+
const merged = { ...existing, ...hooksConfig };
|
|
225
|
+
await writeFile(settingsPath, JSON.stringify(merged, null, 2) + '\n');
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
/** Unique marker identifying Codeman's own statusLine command (vs a user's). */
|
|
229
|
+
const STATUSLINE_MARKER = '/api/status-telemetry';
|
|
230
|
+
/**
|
|
231
|
+
* The plan-usage statusLine exporter command. Mirrors the hook `curlCmd` pattern:
|
|
232
|
+
* reads Claude Code's statusline stdin JSON, POSTs `{sessionId,data}` to Codeman,
|
|
233
|
+
* and prints the response body (a compact "⟳ 5h 15% · 7d 34%" footer) back to
|
|
234
|
+
* stdout so the in-terminal statusline stays useful. Env vars resolve at runtime
|
|
235
|
+
* (present in every managed session via tmux setenv), so the config is static.
|
|
236
|
+
*/
|
|
237
|
+
export function generateStatusLineCommand() {
|
|
238
|
+
// `curl -sk`: CODEMAN_API_URL is loopback HTTPS with a self-signed cert in the
|
|
239
|
+
// production setup; without -k curl returns 000 and the statusline shows
|
|
240
|
+
// nothing. -k is safe here (loopback only). Falls back to a brand string so the
|
|
241
|
+
// footer is never blank if Codeman is unreachable.
|
|
242
|
+
return (`INPUT=$(cat 2>/dev/null || echo '{}'); ` +
|
|
243
|
+
`printf '{"sessionId":"%s","data":%s}' "$CODEMAN_SESSION_ID" "$INPUT" | ` +
|
|
244
|
+
`curl -sk -X POST "$CODEMAN_API_URL${STATUSLINE_MARKER}" ` +
|
|
245
|
+
`-H 'Content-Type: application/json' ` +
|
|
246
|
+
`-H "X-Codeman-Hook-Secret: $(cat "$CODEMAN_HOOK_SECRET_FILE" 2>/dev/null)" ` +
|
|
247
|
+
`--data @- 2>/dev/null || echo codeman`);
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Add or remove Codeman's plan-usage statusLine exporter in
|
|
251
|
+
* `.claude/settings.local.json`. Only ever touches a statusLine that is OURS
|
|
252
|
+
* (command targets `/api/status-telemetry`), so a user's hand-authored
|
|
253
|
+
* statusLine is never removed OR overwritten — on both the enable and disable
|
|
254
|
+
* paths we bail out when an existing statusLine isn't ours. Callers gate on
|
|
255
|
+
* Claude mode. Merges, preserving all other keys (hooks, env, model).
|
|
256
|
+
*/
|
|
257
|
+
export async function applyStatusLineConfig(casePath, enabled) {
|
|
258
|
+
const claudeDir = join(casePath, '.claude');
|
|
259
|
+
const settingsPath = join(claudeDir, 'settings.local.json');
|
|
260
|
+
await withSettingsLock(settingsPath, async () => {
|
|
261
|
+
let existing = {};
|
|
262
|
+
if (existsSync(settingsPath)) {
|
|
263
|
+
try {
|
|
264
|
+
existing = JSON.parse(await readFile(settingsPath, 'utf-8'));
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
return; // Malformed — don't rewrite it
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const current = existing.statusLine;
|
|
271
|
+
const isOurs = !!current && typeof current.command === 'string' && current.command.includes(STATUSLINE_MARKER);
|
|
272
|
+
if (enabled) {
|
|
273
|
+
const desired = generateStatusLineCommand();
|
|
274
|
+
if (isOurs && current?.command === desired)
|
|
275
|
+
return; // already current — skip rewrite
|
|
276
|
+
if (current && !isOurs)
|
|
277
|
+
return; // user has their OWN statusLine — never clobber it
|
|
278
|
+
if (!existsSync(claudeDir))
|
|
279
|
+
await mkdir(claudeDir, { recursive: true });
|
|
280
|
+
existing.statusLine = { type: 'command', command: desired }; // add, or update an out-of-date ours
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
if (!isOurs)
|
|
284
|
+
return; // nothing of ours to remove (leave a user's own statusLine alone)
|
|
285
|
+
delete existing.statusLine;
|
|
286
|
+
}
|
|
287
|
+
await writeFile(settingsPath, JSON.stringify(existing, null, 2) + '\n');
|
|
288
|
+
});
|
|
198
289
|
}
|
|
199
290
|
//# sourceMappingURL=hooks-config.js.map
|
package/dist/hooks-config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-config.js","sourceRoot":"","sources":["../src/hooks-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB;IACjC,kEAAkE;IAClE,mEAAmE;IACnE,iFAAiF;IACjF,gFAAgF;IAChF,kFAAkF;IAClF,+EAA+E;IAC/E,+EAA+E;IAC/E,wEAAwE;IACxE,MAAM,OAAO,GAAG,CAAC,KAAoB,EAAE,EAAE,CACvC,6CAA6C;QAC7C,qBAAqB,KAAK,sEAAsE;QAChG,oDAAoD;QACpD,sCAAsC;QACtC,6EAA6E;QAC7E,YAAY;QACZ,qBAAqB,CAAC;IAExB,OAAO;QACL,KAAK,EAAE;YACL,YAAY,EAAE;gBACZ;oBACE,OAAO,EAAE,aAAa;oBACtB,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;iBACxF;gBACD;oBACE,OAAO,EAAE,mBAAmB;oBAC5B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,mBAAmB,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;iBAC9F;gBACD;oBACE,OAAO,EAAE,oBAAoB;oBAC7B,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,oBAAoB,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;iBAC/F;aACF;YACD,IAAI,EAAE;gBACJ;oBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;iBACjF;aACF;YACD,YAAY,EAAE;gBACZ;oBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;iBAC1F;aACF;YACD,aAAa,EAAE;gBACb;oBACE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC;iBAC3F;aACF;SACF;KACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,QAAgB,EAAE,YAA+B;IACtF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAEtC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC;IACtE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"hooks-config.js","sourceRoot":"","sources":["../src/hooks-config.ts"],"names":[],"mappings":"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"}
|
package/dist/image-watcher.d.ts
CHANGED
|
@@ -69,13 +69,18 @@ export declare class ImageWatcher extends EventEmitter {
|
|
|
69
69
|
getWatchedSessions(): string[];
|
|
70
70
|
/**
|
|
71
71
|
* Handle a new file being detected.
|
|
72
|
-
* Verifies it's
|
|
72
|
+
* Verifies it's a previewable image/document and emits the detection event.
|
|
73
73
|
*/
|
|
74
74
|
private handleNewFile;
|
|
75
75
|
/**
|
|
76
76
|
* Emit the image:detected event with file metadata.
|
|
77
77
|
*/
|
|
78
78
|
private emitImageDetected;
|
|
79
|
+
/**
|
|
80
|
+
* Emit the attachment:detected event with file metadata.
|
|
81
|
+
*/
|
|
82
|
+
private emitAttachmentDetected;
|
|
83
|
+
private getAttachmentType;
|
|
79
84
|
}
|
|
80
85
|
export declare const imageWatcher: ImageWatcher;
|
|
81
86
|
//# sourceMappingURL=image-watcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-watcher.d.ts","sourceRoot":"","sources":["../src/image-watcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"image-watcher.d.ts","sourceRoot":"","sources":["../src/image-watcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAiC3C;;;;;;;;;;;;;;GAcG;AACH,qBAAa,YAAa,SAAQ,YAAY;IAC5C,uEAAuE;IACvE,OAAO,CAAC,eAAe,CAAgC;IAEvD,iDAAiD;IACjD,OAAO,CAAC,WAAW,CAA6B;IAEhD,kDAAkD;IAClD,OAAO,CAAC,OAAO,CAAyC;IAExD,iEAAiE;IACjE,OAAO,CAAC,aAAa,CAA6B;IAElD,sEAAsE;IACtE,OAAO,CAAC,aAAa,CAA6D;IAElF,+CAA+C;IAC/C,OAAO,CAAC,UAAU,CAAS;;IAS3B;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,IAAI,IAAI,IAAI;IAoBZ;;;;;OAKG;IACH,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IA8DzD;;;;OAIG;IACH,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA0BvC;;OAEG;IACH,kBAAkB,IAAI,MAAM,EAAE;IAM9B;;;OAGG;IACH,OAAO,CAAC,aAAa;IA0CrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAwBzB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAyB9B,OAAO,CAAC,iBAAiB;CAO1B;AAGD,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
package/dist/image-watcher.js
CHANGED
|
@@ -15,7 +15,9 @@ import { KeyedDebouncer } from './utils/index.js';
|
|
|
15
15
|
// ========== Types ==========
|
|
16
16
|
// ========== Constants ==========
|
|
17
17
|
/** Supported image file extensions (lowercase) */
|
|
18
|
-
const
|
|
18
|
+
const IMAGE_POPUP_EXTENSIONS = new Set(['.jpg', '.jpeg', '.gif', '.webp', '.bmp', '.svg']);
|
|
19
|
+
const ATTACHMENT_EXTENSIONS = new Set(['.png', '.pdf', '.docx', '.pptx']);
|
|
20
|
+
const DETECTED_FILE_EXTENSIONS = new Set([...IMAGE_POPUP_EXTENSIONS, ...ATTACHMENT_EXTENSIONS]);
|
|
19
21
|
/** Time to wait for file writes to stabilize (ms) */
|
|
20
22
|
const STABILITY_THRESHOLD_MS = 500;
|
|
21
23
|
/** Poll interval for checking file write stability (ms) */
|
|
@@ -139,8 +141,8 @@ export class ImageWatcher extends EventEmitter {
|
|
|
139
141
|
}
|
|
140
142
|
const ext = extname(path).toLowerCase();
|
|
141
143
|
// Don't ignore directories (needed for watching to work)
|
|
142
|
-
// Ignore files that aren't images
|
|
143
|
-
return ext !== '' && !
|
|
144
|
+
// Ignore files that aren't previewable images/documents
|
|
145
|
+
return ext !== '' && !DETECTED_FILE_EXTENSIONS.has(ext);
|
|
144
146
|
},
|
|
145
147
|
});
|
|
146
148
|
// Handle new file detection
|
|
@@ -196,14 +198,15 @@ export class ImageWatcher extends EventEmitter {
|
|
|
196
198
|
// ========== Private Methods ==========
|
|
197
199
|
/**
|
|
198
200
|
* Handle a new file being detected.
|
|
199
|
-
* Verifies it's
|
|
201
|
+
* Verifies it's a previewable image/document and emits the detection event.
|
|
200
202
|
*/
|
|
201
203
|
handleNewFile(sessionId, filePath) {
|
|
202
204
|
const ext = extname(filePath).toLowerCase();
|
|
203
|
-
// Double-check it's
|
|
204
|
-
if (!
|
|
205
|
+
// Double-check it's a supported extension
|
|
206
|
+
if (!DETECTED_FILE_EXTENSIONS.has(ext)) {
|
|
205
207
|
return;
|
|
206
208
|
}
|
|
209
|
+
const isAttachment = ATTACHMENT_EXTENSIONS.has(ext);
|
|
207
210
|
// Burst limit: skip if too many images detected for this session in a short window
|
|
208
211
|
const now = Date.now();
|
|
209
212
|
let burst = this.burstTrackers.get(sessionId);
|
|
@@ -224,7 +227,12 @@ export class ImageWatcher extends EventEmitter {
|
|
|
224
227
|
// Debounce rapid file creation (e.g., multiple screenshots quickly)
|
|
225
228
|
this.fileDeb.schedule(filePath, () => {
|
|
226
229
|
this.fileToSession.delete(filePath);
|
|
227
|
-
|
|
230
|
+
if (isAttachment) {
|
|
231
|
+
this.emitAttachmentDetected(sessionId, filePath);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
this.emitImageDetected(sessionId, filePath);
|
|
235
|
+
}
|
|
228
236
|
// Increment burst count on actual emission (not on detection)
|
|
229
237
|
const b = this.burstTrackers.get(sessionId);
|
|
230
238
|
if (b)
|
|
@@ -257,6 +265,43 @@ export class ImageWatcher extends EventEmitter {
|
|
|
257
265
|
this.emit('image:error', error instanceof Error ? error : new Error(String(error)), sessionId);
|
|
258
266
|
}
|
|
259
267
|
}
|
|
268
|
+
/**
|
|
269
|
+
* Emit the attachment:detected event with file metadata.
|
|
270
|
+
*/
|
|
271
|
+
emitAttachmentDetected(sessionId, filePath) {
|
|
272
|
+
try {
|
|
273
|
+
const stat = statSync(filePath);
|
|
274
|
+
const fileName = basename(filePath);
|
|
275
|
+
const workingDir = this.sessionDirs.get(sessionId);
|
|
276
|
+
const relativePath = workingDir ? relative(workingDir, filePath) : fileName;
|
|
277
|
+
const extension = extname(fileName).toLowerCase().replace(/^\./, '');
|
|
278
|
+
const event = {
|
|
279
|
+
sessionId,
|
|
280
|
+
filePath,
|
|
281
|
+
relativePath,
|
|
282
|
+
fileName,
|
|
283
|
+
extension,
|
|
284
|
+
attachmentType: this.getAttachmentType(extension),
|
|
285
|
+
timestamp: Date.now(),
|
|
286
|
+
size: stat.size,
|
|
287
|
+
};
|
|
288
|
+
this.emit('attachment:detected', event);
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
this.emit('image:error', error instanceof Error ? error : new Error(String(error)), sessionId);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
getAttachmentType(extension) {
|
|
295
|
+
if (extension === 'png')
|
|
296
|
+
return 'image';
|
|
297
|
+
if (extension === 'pdf')
|
|
298
|
+
return 'pdf';
|
|
299
|
+
if (extension === 'docx')
|
|
300
|
+
return 'document';
|
|
301
|
+
if (extension === 'pptx')
|
|
302
|
+
return 'presentation';
|
|
303
|
+
return 'document';
|
|
304
|
+
}
|
|
260
305
|
}
|
|
261
306
|
// Export singleton instance for convenience
|
|
262
307
|
export const imageWatcher = new ImageWatcher();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-watcher.js","sourceRoot":"","sources":["../src/image-watcher.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAkB,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,8BAA8B;AAE9B,kCAAkC;AAElC,kDAAkD;AAClD,MAAM,
|
|
1
|
+
{"version":3,"file":"image-watcher.js","sourceRoot":"","sources":["../src/image-watcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { SessionAttachmentHistoryItem } from './types/session.js';
|
|
2
|
+
import type { AttachmentDetectedEvent } from './types/tools.js';
|
|
3
|
+
export declare const ATTACHMENT_HISTORY_LIMIT = 100;
|
|
4
|
+
export interface ExternalAttachmentHistoryInput {
|
|
5
|
+
sessionId: string;
|
|
6
|
+
externalPath: string;
|
|
7
|
+
fileName?: string;
|
|
8
|
+
extension?: string;
|
|
9
|
+
size: number;
|
|
10
|
+
mtimeMs?: number;
|
|
11
|
+
timestamp?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function normalizeAttachmentExtension(extensionOrPath: string): string;
|
|
14
|
+
export declare function sanitizeAttachmentHistoryItem(item: SessionAttachmentHistoryItem): SessionAttachmentHistoryItem;
|
|
15
|
+
export declare function sanitizeAttachmentHistory(history: readonly SessionAttachmentHistoryItem[]): SessionAttachmentHistoryItem[];
|
|
16
|
+
export declare function upsertAttachmentHistory(history: readonly SessionAttachmentHistoryItem[], item: SessionAttachmentHistoryItem): SessionAttachmentHistoryItem[];
|
|
17
|
+
export declare function buildDetectedAttachmentHistoryItem(event: AttachmentDetectedEvent): SessionAttachmentHistoryItem;
|
|
18
|
+
export declare function buildExternalAttachmentHistoryItem(input: ExternalAttachmentHistoryInput): SessionAttachmentHistoryItem;
|
|
19
|
+
//# sourceMappingURL=session-attachment-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-attachment-history.d.ts","sourceRoot":"","sources":["../src/session-attachment-history.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAGhE,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAE5C,MAAM,WAAW,8BAA8B;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,4BAA4B,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAG5E;AAeD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,4BAA4B,GAAG,4BAA4B,CAM9G;AAED,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,SAAS,4BAA4B,EAAE,GAC/C,4BAA4B,EAAE,CAEhC;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,SAAS,4BAA4B,EAAE,EAChD,IAAI,EAAE,4BAA4B,GACjC,4BAA4B,EAAE,CAGhC;AAED,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,uBAAuB,GAAG,4BAA4B,CAa/G;AAED,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,8BAA8B,GACpC,4BAA4B,CAgB9B"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { basename, extname } from 'node:path';
|
|
3
|
+
import { getAttachmentType } from './attachment-registry.js';
|
|
4
|
+
export const ATTACHMENT_HISTORY_LIMIT = 100;
|
|
5
|
+
export function normalizeAttachmentExtension(extensionOrPath) {
|
|
6
|
+
const value = extensionOrPath.startsWith('.') ? extensionOrPath : extname(extensionOrPath) || extensionOrPath;
|
|
7
|
+
return value.toLowerCase().replace(/^\./, '');
|
|
8
|
+
}
|
|
9
|
+
function historyKey(item) {
|
|
10
|
+
if (item.source === 'external' && item.externalPath) {
|
|
11
|
+
return `external:${item.externalPath}`;
|
|
12
|
+
}
|
|
13
|
+
return `detected:${item.relativePath || item.fileName}`;
|
|
14
|
+
}
|
|
15
|
+
function safeExternalHistoryId(item) {
|
|
16
|
+
const source = item.externalPath || item.id || item.fileName;
|
|
17
|
+
const digest = createHash('sha256').update(source).digest('hex').slice(0, 16);
|
|
18
|
+
return `external:${digest}:${item.fileName}`;
|
|
19
|
+
}
|
|
20
|
+
export function sanitizeAttachmentHistoryItem(item) {
|
|
21
|
+
const { externalPath: _externalPath, ...safe } = item;
|
|
22
|
+
return {
|
|
23
|
+
...safe,
|
|
24
|
+
id: item.source === 'external' ? safeExternalHistoryId(item) : item.id,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export function sanitizeAttachmentHistory(history) {
|
|
28
|
+
return history.map(sanitizeAttachmentHistoryItem);
|
|
29
|
+
}
|
|
30
|
+
export function upsertAttachmentHistory(history, item) {
|
|
31
|
+
const nextKey = historyKey(item);
|
|
32
|
+
return [item, ...history.filter((existing) => historyKey(existing) !== nextKey)].slice(0, ATTACHMENT_HISTORY_LIMIT);
|
|
33
|
+
}
|
|
34
|
+
export function buildDetectedAttachmentHistoryItem(event) {
|
|
35
|
+
return {
|
|
36
|
+
id: `detected:${event.relativePath || event.fileName}`,
|
|
37
|
+
sessionId: event.sessionId,
|
|
38
|
+
fileName: event.fileName,
|
|
39
|
+
extension: normalizeAttachmentExtension(event.extension),
|
|
40
|
+
attachmentType: event.attachmentType,
|
|
41
|
+
size: event.size,
|
|
42
|
+
mtimeMs: 0,
|
|
43
|
+
timestamp: event.timestamp,
|
|
44
|
+
source: 'detected',
|
|
45
|
+
relativePath: event.relativePath,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function buildExternalAttachmentHistoryItem(input) {
|
|
49
|
+
const extension = normalizeAttachmentExtension(input.extension || input.fileName || input.externalPath);
|
|
50
|
+
return {
|
|
51
|
+
id: `external:${createHash('sha256').update(input.externalPath).digest('hex').slice(0, 16)}:${input.fileName || basename(input.externalPath)}`,
|
|
52
|
+
sessionId: input.sessionId,
|
|
53
|
+
fileName: input.fileName || basename(input.externalPath),
|
|
54
|
+
extension,
|
|
55
|
+
attachmentType: getAttachmentType(extension),
|
|
56
|
+
size: input.size,
|
|
57
|
+
mtimeMs: input.mtimeMs ?? 0,
|
|
58
|
+
timestamp: input.timestamp ?? Date.now(),
|
|
59
|
+
source: 'external',
|
|
60
|
+
externalPath: input.externalPath,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=session-attachment-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-attachment-history.js","sourceRoot":"","sources":["../src/session-attachment-history.ts"],"names":[],"mappings":"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"}
|
package/dist/session.d.ts
CHANGED
|
@@ -33,6 +33,7 @@ import type { TerminalMultiplexer, MuxSession } from './mux-interface.js';
|
|
|
33
33
|
import { TaskTracker, type BackgroundTask } from './task-tracker.js';
|
|
34
34
|
import { RalphTracker } from './ralph-tracker.js';
|
|
35
35
|
import { BashToolParser } from './bash-tool-parser.js';
|
|
36
|
+
import type { SessionAttachmentHistoryItem } from './types/session.js';
|
|
36
37
|
export type { BackgroundTask } from './task-tracker.js';
|
|
37
38
|
export type { RalphTrackerState, RalphTodoItem, ActiveBashTool } from './types.js';
|
|
38
39
|
export type ResizeViewportType = 'mobile' | 'tablet' | 'desktop';
|
|
@@ -171,6 +172,8 @@ export declare class Session extends EventEmitter {
|
|
|
171
172
|
private _ralphTracker;
|
|
172
173
|
private _parentAgentId;
|
|
173
174
|
private _childAgentIds;
|
|
175
|
+
private _attachmentMagicSeen;
|
|
176
|
+
private _attachmentHistory;
|
|
174
177
|
private _niceConfig;
|
|
175
178
|
private _model;
|
|
176
179
|
private _claudeMode;
|
|
@@ -216,6 +219,8 @@ export declare class Session extends EventEmitter {
|
|
|
216
219
|
envOverrides?: Record<string, string>;
|
|
217
220
|
/** Claude CLI effort level (soft default via --settings, switchable in-session via /effort) */
|
|
218
221
|
effort?: EffortLevel;
|
|
222
|
+
/** Restored per-session attachment history. May include server-private external paths. */
|
|
223
|
+
attachmentHistory?: SessionAttachmentHistoryItem[];
|
|
219
224
|
});
|
|
220
225
|
get status(): SessionStatus;
|
|
221
226
|
get currentTaskId(): string | null;
|
|
@@ -320,6 +325,10 @@ export declare class Session extends EventEmitter {
|
|
|
320
325
|
isIdle(): boolean;
|
|
321
326
|
isBusy(): boolean;
|
|
322
327
|
isRunning(): boolean;
|
|
328
|
+
get attachmentHistory(): SessionAttachmentHistoryItem[];
|
|
329
|
+
upsertAttachmentHistory(item: SessionAttachmentHistoryItem): void;
|
|
330
|
+
restoreAttachmentHistory(history: SessionAttachmentHistoryItem[] | undefined): void;
|
|
331
|
+
getAttachmentHistoryForPersist(): SessionAttachmentHistoryItem[] | undefined;
|
|
323
332
|
toState(): SessionState;
|
|
324
333
|
/**
|
|
325
334
|
* Returns a subset of env overrides safe for disk persistence (state.json).
|
|
@@ -413,6 +422,7 @@ export declare class Session extends EventEmitter {
|
|
|
413
422
|
codexConfig?: CodexConfig;
|
|
414
423
|
resumeSessionId?: string;
|
|
415
424
|
effort?: EffortLevel;
|
|
425
|
+
attachmentHistory?: SessionAttachmentHistoryItem[];
|
|
416
426
|
};
|
|
417
427
|
/**
|
|
418
428
|
* Lightweight detailed state that excludes heavy buffers (textOutput, terminalBuffer).
|
|
@@ -501,6 +511,7 @@ export declare class Session extends EventEmitter {
|
|
|
501
511
|
codexConfig?: CodexConfig;
|
|
502
512
|
resumeSessionId?: string;
|
|
503
513
|
effort?: EffortLevel;
|
|
514
|
+
attachmentHistory?: SessionAttachmentHistoryItem[];
|
|
504
515
|
};
|
|
505
516
|
/**
|
|
506
517
|
* Starts an interactive Claude CLI session with full terminal support.
|