@herdctl/core 5.6.0 → 5.7.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.
Files changed (54) hide show
  1. package/dist/config/__tests__/merge.test.js +1 -1
  2. package/dist/config/__tests__/merge.test.js.map +1 -1
  3. package/dist/config/schema.d.ts +10 -2
  4. package/dist/config/schema.d.ts.map +1 -1
  5. package/dist/config/schema.js +6 -2
  6. package/dist/config/schema.js.map +1 -1
  7. package/dist/scheduler/schedule-runner.d.ts.map +1 -1
  8. package/dist/scheduler/schedule-runner.js +6 -5
  9. package/dist/scheduler/schedule-runner.js.map +1 -1
  10. package/dist/state/__tests__/jsonl-parser.test.d.ts +5 -0
  11. package/dist/state/__tests__/jsonl-parser.test.d.ts.map +1 -0
  12. package/dist/state/__tests__/jsonl-parser.test.js +307 -0
  13. package/dist/state/__tests__/jsonl-parser.test.js.map +1 -0
  14. package/dist/state/__tests__/session-attribution.test.d.ts +2 -0
  15. package/dist/state/__tests__/session-attribution.test.d.ts.map +1 -0
  16. package/dist/state/__tests__/session-attribution.test.js +567 -0
  17. package/dist/state/__tests__/session-attribution.test.js.map +1 -0
  18. package/dist/state/__tests__/session-discovery.test.d.ts +2 -0
  19. package/dist/state/__tests__/session-discovery.test.d.ts.map +1 -0
  20. package/dist/state/__tests__/session-discovery.test.js +941 -0
  21. package/dist/state/__tests__/session-discovery.test.js.map +1 -0
  22. package/dist/state/__tests__/session-metadata.test.d.ts +2 -0
  23. package/dist/state/__tests__/session-metadata.test.d.ts.map +1 -0
  24. package/dist/state/__tests__/session-metadata.test.js +422 -0
  25. package/dist/state/__tests__/session-metadata.test.js.map +1 -0
  26. package/dist/state/__tests__/tool-parsing.test.d.ts +5 -0
  27. package/dist/state/__tests__/tool-parsing.test.d.ts.map +1 -0
  28. package/dist/state/__tests__/tool-parsing.test.js +315 -0
  29. package/dist/state/__tests__/tool-parsing.test.js.map +1 -0
  30. package/dist/state/index.d.ts +5 -0
  31. package/dist/state/index.d.ts.map +1 -1
  32. package/dist/state/index.js +10 -0
  33. package/dist/state/index.js.map +1 -1
  34. package/dist/state/jsonl-parser.d.ts +115 -0
  35. package/dist/state/jsonl-parser.d.ts.map +1 -0
  36. package/dist/state/jsonl-parser.js +437 -0
  37. package/dist/state/jsonl-parser.js.map +1 -0
  38. package/dist/state/session-attribution.d.ts +35 -0
  39. package/dist/state/session-attribution.d.ts.map +1 -0
  40. package/dist/state/session-attribution.js +179 -0
  41. package/dist/state/session-attribution.js.map +1 -0
  42. package/dist/state/session-discovery.d.ts +188 -0
  43. package/dist/state/session-discovery.d.ts.map +1 -0
  44. package/dist/state/session-discovery.js +513 -0
  45. package/dist/state/session-discovery.js.map +1 -0
  46. package/dist/state/session-metadata.d.ts +186 -0
  47. package/dist/state/session-metadata.d.ts.map +1 -0
  48. package/dist/state/session-metadata.js +297 -0
  49. package/dist/state/session-metadata.js.map +1 -0
  50. package/dist/state/tool-parsing.d.ts +88 -0
  51. package/dist/state/tool-parsing.d.ts.map +1 -0
  52. package/dist/state/tool-parsing.js +199 -0
  53. package/dist/state/tool-parsing.js.map +1 -0
  54. package/package.json +1 -1
@@ -0,0 +1,186 @@
1
+ /**
2
+ * Session Metadata Store
3
+ *
4
+ * Manages user-customizable metadata for Claude Code sessions.
5
+ * Metadata is stored sparsely in .herdctl/session-metadata/{agent-qualified-name}.json
6
+ * Files are only created when the first custom name is set for an agent.
7
+ */
8
+ import { z } from "zod";
9
+ /**
10
+ * Schema for a single session's metadata entry
11
+ */
12
+ export declare const SessionMetadataEntrySchema: z.ZodObject<{
13
+ customName: z.ZodOptional<z.ZodString>;
14
+ /** Auto-generated session name (extracted from JSONL summary) */
15
+ autoName: z.ZodOptional<z.ZodString>;
16
+ /** ISO 8601 timestamp of when autoName was extracted (for cache invalidation) */
17
+ autoNameMtime: z.ZodOptional<z.ZodString>;
18
+ }, "strip", z.ZodTypeAny, {
19
+ customName?: string | undefined;
20
+ autoName?: string | undefined;
21
+ autoNameMtime?: string | undefined;
22
+ }, {
23
+ customName?: string | undefined;
24
+ autoName?: string | undefined;
25
+ autoNameMtime?: string | undefined;
26
+ }>;
27
+ /**
28
+ * Schema for the entire metadata file for an agent
29
+ */
30
+ export declare const SessionMetadataFileSchema: z.ZodObject<{
31
+ version: z.ZodLiteral<1>;
32
+ agentName: z.ZodString;
33
+ sessions: z.ZodRecord<z.ZodString, z.ZodObject<{
34
+ customName: z.ZodOptional<z.ZodString>;
35
+ /** Auto-generated session name (extracted from JSONL summary) */
36
+ autoName: z.ZodOptional<z.ZodString>;
37
+ /** ISO 8601 timestamp of when autoName was extracted (for cache invalidation) */
38
+ autoNameMtime: z.ZodOptional<z.ZodString>;
39
+ }, "strip", z.ZodTypeAny, {
40
+ customName?: string | undefined;
41
+ autoName?: string | undefined;
42
+ autoNameMtime?: string | undefined;
43
+ }, {
44
+ customName?: string | undefined;
45
+ autoName?: string | undefined;
46
+ autoNameMtime?: string | undefined;
47
+ }>>;
48
+ }, "strip", z.ZodTypeAny, {
49
+ version: 1;
50
+ sessions: Record<string, {
51
+ customName?: string | undefined;
52
+ autoName?: string | undefined;
53
+ autoNameMtime?: string | undefined;
54
+ }>;
55
+ agentName: string;
56
+ }, {
57
+ version: 1;
58
+ sessions: Record<string, {
59
+ customName?: string | undefined;
60
+ autoName?: string | undefined;
61
+ autoNameMtime?: string | undefined;
62
+ }>;
63
+ agentName: string;
64
+ }>;
65
+ export type SessionMetadataEntry = z.infer<typeof SessionMetadataEntrySchema>;
66
+ export type SessionMetadataFile = z.infer<typeof SessionMetadataFileSchema>;
67
+ /**
68
+ * Store for managing user-customizable session metadata.
69
+ *
70
+ * Provides operations for getting/setting custom names for sessions.
71
+ * Data is sparse - files are only created when metadata is first set.
72
+ *
73
+ * @example
74
+ * ```typescript
75
+ * const store = new SessionMetadataStore('/path/to/.herdctl');
76
+ *
77
+ * // Set a custom name for a session
78
+ * await store.setCustomName('my-agent', 'session-123', 'Feature Work');
79
+ *
80
+ * // Get the custom name
81
+ * const name = await store.getCustomName('my-agent', 'session-123');
82
+ * // Returns: 'Feature Work'
83
+ *
84
+ * // Remove custom name
85
+ * await store.removeCustomName('my-agent', 'session-123');
86
+ * ```
87
+ */
88
+ export declare class SessionMetadataStore {
89
+ private readonly metadataDir;
90
+ private readonly cache;
91
+ /**
92
+ * Create a new SessionMetadataStore
93
+ *
94
+ * @param stateDir - Path to the .herdctl state directory
95
+ */
96
+ constructor(stateDir: string);
97
+ /**
98
+ * Get the file path for an agent's metadata
99
+ */
100
+ private getFilePath;
101
+ /**
102
+ * Load metadata for an agent from disk (or cache)
103
+ */
104
+ private loadMetadata;
105
+ /**
106
+ * Save metadata for an agent to disk
107
+ */
108
+ private saveMetadata;
109
+ /**
110
+ * Create a new empty metadata file structure
111
+ */
112
+ private createEmptyMetadata;
113
+ /**
114
+ * Get custom name for a session
115
+ *
116
+ * @param agentName - The agent's qualified name
117
+ * @param sessionId - The session ID
118
+ * @returns The custom name if set, undefined otherwise
119
+ */
120
+ getCustomName(agentName: string, sessionId: string): Promise<string | undefined>;
121
+ /**
122
+ * Set custom name for a session
123
+ *
124
+ * Creates the metadata file if it doesn't exist.
125
+ *
126
+ * @param agentName - The agent's qualified name
127
+ * @param sessionId - The session ID
128
+ * @param name - The custom name to set
129
+ */
130
+ setCustomName(agentName: string, sessionId: string, name: string): Promise<void>;
131
+ /**
132
+ * Remove custom name for a session
133
+ *
134
+ * If this was the only metadata for the session, the session entry is removed.
135
+ * If this was the only session with metadata, the file is kept but empty
136
+ * (to avoid repeatedly creating/deleting files).
137
+ *
138
+ * @param agentName - The agent's qualified name
139
+ * @param sessionId - The session ID
140
+ */
141
+ removeCustomName(agentName: string, sessionId: string): Promise<void>;
142
+ /**
143
+ * Get all metadata for an agent's sessions
144
+ *
145
+ * Useful for batch operations or displaying metadata for all sessions.
146
+ *
147
+ * @param agentName - The agent's qualified name
148
+ * @returns The full metadata file, or null if no metadata exists
149
+ */
150
+ getAgentMetadata(agentName: string): Promise<SessionMetadataFile | null>;
151
+ /**
152
+ * Get auto-generated name and its mtime for a session
153
+ *
154
+ * @param agentName - The agent's qualified name (use "adhoc" for unattributed sessions)
155
+ * @param sessionId - The session ID
156
+ * @returns Object with autoName and autoNameMtime, or undefined if not cached
157
+ */
158
+ getAutoName(agentName: string, sessionId: string): Promise<{
159
+ autoName?: string;
160
+ autoNameMtime?: string;
161
+ } | undefined>;
162
+ /**
163
+ * Set auto-generated name for a session
164
+ *
165
+ * @param agentName - The agent's qualified name (use "adhoc" for unattributed sessions)
166
+ * @param sessionId - The session ID
167
+ * @param autoName - The auto-generated name to set
168
+ * @param mtime - ISO 8601 timestamp of the session file when the name was extracted
169
+ */
170
+ setAutoName(agentName: string, sessionId: string, autoName: string, mtime: string): Promise<void>;
171
+ /**
172
+ * Batch set auto-generated names for multiple sessions
173
+ *
174
+ * More efficient than calling setAutoName repeatedly since it performs
175
+ * a single file write for all updates.
176
+ *
177
+ * @param agentName - The agent's qualified name (use "adhoc" for unattributed sessions)
178
+ * @param entries - Array of { sessionId, autoName, mtime } objects
179
+ */
180
+ batchSetAutoNames(agentName: string, entries: Array<{
181
+ sessionId: string;
182
+ autoName: string;
183
+ mtime: string;
184
+ }>): Promise<void>;
185
+ }
186
+ //# sourceMappingURL=session-metadata.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-metadata.d.ts","sourceRoot":"","sources":["../../src/state/session-metadata.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB;;GAEG;AACH,eAAO,MAAM,0BAA0B;;IAErC,iEAAiE;;IAEjE,iFAAiF;;;;;;;;;;EAGjF,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,yBAAyB;;;;;QAVpC,iEAAiE;;QAEjE,iFAAiF;;;;;;;;;;;;;;;;;;;;;;;;;;;EAYjF,CAAC;AAEH,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAM5E;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IAEzD;;;;OAIG;gBACS,QAAQ,EAAE,MAAM;IAK5B;;OAEG;IACH,OAAO,CAAC,WAAW;IAInB;;OAEG;YACW,YAAY;IAkC1B;;OAEG;YACW,YAAY;IAe1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;;;;;OAMG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAStF;;;;;;;;OAQG;IACG,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBtF;;;;;;;;;OASG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6B3E;;;;;;;OAOG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAI9E;;;;;;OAMG;IACG,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IAiBrE;;;;;;;OAOG;IACG,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC;IAyBhB;;;;;;;;OAQG;IACG,iBAAiB,CACrB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GACrE,OAAO,CAAC,IAAI,CAAC;CA2BjB"}
@@ -0,0 +1,297 @@
1
+ /**
2
+ * Session Metadata Store
3
+ *
4
+ * Manages user-customizable metadata for Claude Code sessions.
5
+ * Metadata is stored sparsely in .herdctl/session-metadata/{agent-qualified-name}.json
6
+ * Files are only created when the first custom name is set for an agent.
7
+ */
8
+ import { mkdir } from "node:fs/promises";
9
+ import { join } from "node:path";
10
+ import { z } from "zod";
11
+ import { createLogger } from "../utils/logger.js";
12
+ import { atomicWriteJson } from "./utils/atomic.js";
13
+ import { safeReadJson } from "./utils/reads.js";
14
+ const logger = createLogger("SessionMetadataStore");
15
+ // =============================================================================
16
+ // Schemas
17
+ // =============================================================================
18
+ /**
19
+ * Schema for a single session's metadata entry
20
+ */
21
+ export const SessionMetadataEntrySchema = z.object({
22
+ customName: z.string().optional(),
23
+ /** Auto-generated session name (extracted from JSONL summary) */
24
+ autoName: z.string().optional(),
25
+ /** ISO 8601 timestamp of when autoName was extracted (for cache invalidation) */
26
+ autoNameMtime: z.string().optional(),
27
+ // Future: pinned, archived, tags
28
+ });
29
+ /**
30
+ * Schema for the entire metadata file for an agent
31
+ */
32
+ export const SessionMetadataFileSchema = z.object({
33
+ version: z.literal(1),
34
+ agentName: z.string(),
35
+ sessions: z.record(z.string(), SessionMetadataEntrySchema),
36
+ });
37
+ // =============================================================================
38
+ // SessionMetadataStore
39
+ // =============================================================================
40
+ /**
41
+ * Store for managing user-customizable session metadata.
42
+ *
43
+ * Provides operations for getting/setting custom names for sessions.
44
+ * Data is sparse - files are only created when metadata is first set.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const store = new SessionMetadataStore('/path/to/.herdctl');
49
+ *
50
+ * // Set a custom name for a session
51
+ * await store.setCustomName('my-agent', 'session-123', 'Feature Work');
52
+ *
53
+ * // Get the custom name
54
+ * const name = await store.getCustomName('my-agent', 'session-123');
55
+ * // Returns: 'Feature Work'
56
+ *
57
+ * // Remove custom name
58
+ * await store.removeCustomName('my-agent', 'session-123');
59
+ * ```
60
+ */
61
+ export class SessionMetadataStore {
62
+ metadataDir;
63
+ cache;
64
+ /**
65
+ * Create a new SessionMetadataStore
66
+ *
67
+ * @param stateDir - Path to the .herdctl state directory
68
+ */
69
+ constructor(stateDir) {
70
+ this.metadataDir = join(stateDir, "session-metadata");
71
+ this.cache = new Map();
72
+ }
73
+ /**
74
+ * Get the file path for an agent's metadata
75
+ */
76
+ getFilePath(agentName) {
77
+ return join(this.metadataDir, `${agentName}.json`);
78
+ }
79
+ /**
80
+ * Load metadata for an agent from disk (or cache)
81
+ */
82
+ async loadMetadata(agentName) {
83
+ // Check cache first
84
+ const cached = this.cache.get(agentName);
85
+ if (cached !== undefined) {
86
+ return cached;
87
+ }
88
+ const filePath = this.getFilePath(agentName);
89
+ const result = await safeReadJson(filePath);
90
+ if (!result.success) {
91
+ // File not found is expected for sparse storage
92
+ if (result.error.code === "ENOENT") {
93
+ return null;
94
+ }
95
+ logger.warn(`Failed to read metadata file for ${agentName}: ${result.error.message}`);
96
+ return null;
97
+ }
98
+ // Validate the file structure
99
+ const parseResult = SessionMetadataFileSchema.safeParse(result.data);
100
+ if (!parseResult.success) {
101
+ logger.warn(`Corrupted metadata file for ${agentName}: ${parseResult.error.message}. Returning null.`);
102
+ return null;
103
+ }
104
+ // Cache and return
105
+ this.cache.set(agentName, parseResult.data);
106
+ return parseResult.data;
107
+ }
108
+ /**
109
+ * Save metadata for an agent to disk
110
+ */
111
+ async saveMetadata(agentName, metadata) {
112
+ // Ensure directory exists
113
+ await mkdir(this.metadataDir, { recursive: true });
114
+ const filePath = this.getFilePath(agentName);
115
+ await atomicWriteJson(filePath, metadata);
116
+ // Update cache
117
+ this.cache.set(agentName, metadata);
118
+ logger.debug(`Saved metadata for agent ${agentName}`, {
119
+ sessionCount: Object.keys(metadata.sessions).length,
120
+ });
121
+ }
122
+ /**
123
+ * Create a new empty metadata file structure
124
+ */
125
+ createEmptyMetadata(agentName) {
126
+ return {
127
+ version: 1,
128
+ agentName,
129
+ sessions: {},
130
+ };
131
+ }
132
+ /**
133
+ * Get custom name for a session
134
+ *
135
+ * @param agentName - The agent's qualified name
136
+ * @param sessionId - The session ID
137
+ * @returns The custom name if set, undefined otherwise
138
+ */
139
+ async getCustomName(agentName, sessionId) {
140
+ const metadata = await this.loadMetadata(agentName);
141
+ if (!metadata) {
142
+ return undefined;
143
+ }
144
+ return metadata.sessions[sessionId]?.customName;
145
+ }
146
+ /**
147
+ * Set custom name for a session
148
+ *
149
+ * Creates the metadata file if it doesn't exist.
150
+ *
151
+ * @param agentName - The agent's qualified name
152
+ * @param sessionId - The session ID
153
+ * @param name - The custom name to set
154
+ */
155
+ async setCustomName(agentName, sessionId, name) {
156
+ let metadata = await this.loadMetadata(agentName);
157
+ if (!metadata) {
158
+ metadata = this.createEmptyMetadata(agentName);
159
+ }
160
+ // Get or create the session entry
161
+ const sessionEntry = metadata.sessions[sessionId] ?? {};
162
+ // Update the custom name
163
+ metadata.sessions[sessionId] = {
164
+ ...sessionEntry,
165
+ customName: name,
166
+ };
167
+ await this.saveMetadata(agentName, metadata);
168
+ logger.debug(`Set custom name for session ${sessionId}`, {
169
+ agentName,
170
+ customName: name,
171
+ });
172
+ }
173
+ /**
174
+ * Remove custom name for a session
175
+ *
176
+ * If this was the only metadata for the session, the session entry is removed.
177
+ * If this was the only session with metadata, the file is kept but empty
178
+ * (to avoid repeatedly creating/deleting files).
179
+ *
180
+ * @param agentName - The agent's qualified name
181
+ * @param sessionId - The session ID
182
+ */
183
+ async removeCustomName(agentName, sessionId) {
184
+ const metadata = await this.loadMetadata(agentName);
185
+ if (!metadata) {
186
+ // No metadata file exists, nothing to remove
187
+ return;
188
+ }
189
+ const sessionEntry = metadata.sessions[sessionId];
190
+ if (!sessionEntry) {
191
+ // No entry for this session, nothing to remove
192
+ return;
193
+ }
194
+ // Remove the customName
195
+ delete sessionEntry.customName;
196
+ // If the session entry is now empty, remove it entirely
197
+ if (Object.keys(sessionEntry).length === 0) {
198
+ delete metadata.sessions[sessionId];
199
+ }
200
+ else {
201
+ metadata.sessions[sessionId] = sessionEntry;
202
+ }
203
+ await this.saveMetadata(agentName, metadata);
204
+ logger.debug(`Removed custom name for session ${sessionId}`, { agentName });
205
+ }
206
+ /**
207
+ * Get all metadata for an agent's sessions
208
+ *
209
+ * Useful for batch operations or displaying metadata for all sessions.
210
+ *
211
+ * @param agentName - The agent's qualified name
212
+ * @returns The full metadata file, or null if no metadata exists
213
+ */
214
+ async getAgentMetadata(agentName) {
215
+ return this.loadMetadata(agentName);
216
+ }
217
+ /**
218
+ * Get auto-generated name and its mtime for a session
219
+ *
220
+ * @param agentName - The agent's qualified name (use "adhoc" for unattributed sessions)
221
+ * @param sessionId - The session ID
222
+ * @returns Object with autoName and autoNameMtime, or undefined if not cached
223
+ */
224
+ async getAutoName(agentName, sessionId) {
225
+ const metadata = await this.loadMetadata(agentName);
226
+ if (!metadata) {
227
+ return undefined;
228
+ }
229
+ const entry = metadata.sessions[sessionId];
230
+ if (!entry) {
231
+ return undefined;
232
+ }
233
+ return {
234
+ autoName: entry.autoName,
235
+ autoNameMtime: entry.autoNameMtime,
236
+ };
237
+ }
238
+ /**
239
+ * Set auto-generated name for a session
240
+ *
241
+ * @param agentName - The agent's qualified name (use "adhoc" for unattributed sessions)
242
+ * @param sessionId - The session ID
243
+ * @param autoName - The auto-generated name to set
244
+ * @param mtime - ISO 8601 timestamp of the session file when the name was extracted
245
+ */
246
+ async setAutoName(agentName, sessionId, autoName, mtime) {
247
+ let metadata = await this.loadMetadata(agentName);
248
+ if (!metadata) {
249
+ metadata = this.createEmptyMetadata(agentName);
250
+ }
251
+ // Get or create the session entry
252
+ const sessionEntry = metadata.sessions[sessionId] ?? {};
253
+ // Update the auto name fields
254
+ metadata.sessions[sessionId] = {
255
+ ...sessionEntry,
256
+ autoName,
257
+ autoNameMtime: mtime,
258
+ };
259
+ await this.saveMetadata(agentName, metadata);
260
+ logger.debug(`Set auto name for session ${sessionId}`, {
261
+ agentName,
262
+ autoName,
263
+ });
264
+ }
265
+ /**
266
+ * Batch set auto-generated names for multiple sessions
267
+ *
268
+ * More efficient than calling setAutoName repeatedly since it performs
269
+ * a single file write for all updates.
270
+ *
271
+ * @param agentName - The agent's qualified name (use "adhoc" for unattributed sessions)
272
+ * @param entries - Array of { sessionId, autoName, mtime } objects
273
+ */
274
+ async batchSetAutoNames(agentName, entries) {
275
+ if (entries.length === 0) {
276
+ return;
277
+ }
278
+ let metadata = await this.loadMetadata(agentName);
279
+ if (!metadata) {
280
+ metadata = this.createEmptyMetadata(agentName);
281
+ }
282
+ // Apply all updates
283
+ for (const { sessionId, autoName, mtime } of entries) {
284
+ const sessionEntry = metadata.sessions[sessionId] ?? {};
285
+ metadata.sessions[sessionId] = {
286
+ ...sessionEntry,
287
+ autoName,
288
+ autoNameMtime: mtime,
289
+ };
290
+ }
291
+ await this.saveMetadata(agentName, metadata);
292
+ logger.debug(`Batch set auto names for ${entries.length} sessions`, {
293
+ agentName,
294
+ });
295
+ }
296
+ }
297
+ //# sourceMappingURL=session-metadata.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-metadata.js","sourceRoot":"","sources":["../../src/state/session-metadata.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Tool call/result parsing utilities
3
+ *
4
+ * Extracts tool_use and tool_result blocks from Claude SDK messages.
5
+ * These were originally private methods on the Discord manager but are
6
+ * shared across Discord, Slack, and Web connectors.
7
+ */
8
+ /**
9
+ * A parsed tool_use block from an assistant message
10
+ */
11
+ export interface ToolUseBlock {
12
+ /** Tool use ID for pairing with results */
13
+ id?: string;
14
+ /** Tool name (e.g., "Bash", "Read", "Write") */
15
+ name: string;
16
+ /** Tool input object */
17
+ input?: unknown;
18
+ }
19
+ /**
20
+ * A parsed tool_result from a user message
21
+ */
22
+ export interface ToolResult {
23
+ /** Tool output text */
24
+ output: string;
25
+ /** Whether the tool returned an error */
26
+ isError: boolean;
27
+ /** ID of the tool_use this result corresponds to */
28
+ toolUseId?: string;
29
+ }
30
+ /**
31
+ * Emoji mapping for common tool names
32
+ */
33
+ export declare const TOOL_EMOJIS: Record<string, string>;
34
+ /**
35
+ * Extract tool_use blocks from an assistant message's content blocks
36
+ *
37
+ * Returns id, name, and input for each tool_use block so callers can
38
+ * track pending calls and pair them with results.
39
+ *
40
+ * @param message - SDK message object (assistant type)
41
+ * @returns Array of parsed tool use blocks
42
+ */
43
+ export declare function extractToolUseBlocks(message: {
44
+ type: string;
45
+ message?: {
46
+ content?: unknown;
47
+ };
48
+ }): ToolUseBlock[];
49
+ /**
50
+ * Get a human-readable summary of tool input
51
+ *
52
+ * Produces a short description based on the tool name and its input,
53
+ * e.g. the command for Bash, the file path for Read/Write, etc.
54
+ *
55
+ * @param name - Tool name
56
+ * @param input - Tool input object
57
+ * @returns Human-readable summary, or undefined if no summary available
58
+ */
59
+ export declare function getToolInputSummary(name: string, input?: unknown): string | undefined;
60
+ /**
61
+ * Extract tool results from a user message
62
+ *
63
+ * Returns output, error status, and the tool_use_id for matching
64
+ * to the pending tool_use that produced this result.
65
+ *
66
+ * @param message - SDK message object (user type with tool results)
67
+ * @returns Array of parsed tool results
68
+ */
69
+ export declare function extractToolResults(message: {
70
+ type: string;
71
+ message?: {
72
+ content?: unknown;
73
+ };
74
+ tool_use_result?: unknown;
75
+ }): ToolResult[];
76
+ /**
77
+ * Extract content from a top-level tool_use_result value
78
+ *
79
+ * Handles the various formats that a tool result value can take:
80
+ * - Plain string
81
+ * - Object with `content` string
82
+ * - Object with `content` array of text blocks
83
+ *
84
+ * @param result - Raw tool_use_result value from SDK
85
+ * @returns Parsed tool result, or undefined if content could not be extracted
86
+ */
87
+ export declare function extractToolResultContent(result: unknown): ToolResult | undefined;
88
+ //# sourceMappingURL=tool-parsing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-parsing.d.ts","sourceRoot":"","sources":["../../src/state/tool-parsing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,2CAA2C;IAC3C,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,wBAAwB;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,uBAAuB;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAU9C,CAAC;AAMF;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACjC,GAAG,YAAY,EAAE,CAwBjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CA4BrF;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAChC,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,GAAG,UAAU,EAAE,CAyDf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CA2ChF"}