@j-o-r/hello-dave 0.0.5 → 0.0.7
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/CHANGELOG.md +13 -26
- package/README.md +161 -522
- package/README.md.bak +144 -449
- package/{examples → agents}/ask_agent.js +5 -5
- package/{examples → agents}/codeserver.sh +14 -14
- package/{examples → agents}/daisy_agent.js +5 -5
- package/{examples → agents}/docs_agent.js +5 -5
- package/{examples → agents}/gpt_agent.js +5 -5
- package/{examples → agents}/grok_agent.js +5 -5
- package/agents/memory_agent.js +263 -0
- package/{examples → agents}/npm_agent.js +5 -5
- package/{examples → agents}/prompt_agent.js +5 -5
- package/agents/spawn_agent.js +137 -0
- package/{examples → agents}/test_agent.js +6 -8
- package/{examples → agents}/todo_agent.js +5 -5
- package/bin/codeDave +58 -0
- package/bin/dave.js +114 -96
- package/lib/AgentClient.js +111 -67
- package/lib/AgentManager.js +111 -80
- package/lib/AgentServer.js +144 -104
- package/lib/Cli.js +126 -93
- package/lib/Prompt.js +38 -5
- package/lib/Session.js +102 -79
- package/lib/ToolSet.js +79 -60
- package/lib/fafs.js +54 -19
- package/lib/genericToolset.js +109 -213
- package/lib/wsCli.js +50 -19
- package/lib/wsIO.js +11 -17
- package/package.json +2 -2
- package/types/AgentClient.d.ts +69 -35
- package/types/AgentManager.d.ts +50 -56
- package/types/AgentServer.d.ts +63 -16
- package/types/Cli.d.ts +56 -10
- package/types/Prompt.d.ts +36 -4
- package/types/Session.d.ts +23 -9
- package/types/ToolSet.d.ts +49 -32
- package/types/fafs.d.ts +68 -25
- package/types/wsCli.d.ts +14 -0
- package/types/wsIO.d.ts +9 -5
- package/utils/search_sessions.sh +100 -53
- package/README.md.backup +0 -269
- package/README.md.bak.1774780058 +0 -338
- package/README.md.bak2 +0 -531
- package/bin/spawn_agent.js +0 -293
- package/docs.bak.1774780058/agent-manager.md +0 -167
- package/docs.bak.1774780058/agent-manager.md.bak +0 -137
- package/docs.bak.1774780058/agent-manager.md.bak2 +0 -157
- package/docs.bak.1774780058/codeserver-pattern.md +0 -191
- package/docs.bak.1774780058/path-resolution-best-practices.md +0 -104
- package/docs.bak.1774780058/project-overview.md +0 -67
- package/docs.bak.1774780058/project-overview.md.bak +0 -67
- package/docs.bak.1774780058/prompt-class.md +0 -141
- package/docs.bak.1774780058/prompt-class.md.bak +0 -142
- package/docs.bak.1774780058/tools-syntax-validation.md +0 -121
- package/docs.bak.1774780058/tools-syntax-validation.md.bak2 +0 -125
- package/docs.bak.1774780058/tools-syntax-validation.md.bak3 +0 -125
- package/docs.bak.1774780058/tools-syntax-validation.md.bak4 +0 -106
- package/docs.bak.1774780058/tools-syntax-validation.md.bak_path +0 -106
- package/docs.bak.1774780058/toolset.md +0 -164
- package/docs.bak.1774780058/toolset.md.bak +0 -94
- package/docs.bak.1774780058/toolset.md.bak3 +0 -161
- package/docs.bak.1774780058/toolset.md.bak4 +0 -161
- package/docs.bak.1774780058/toolset.md.bak5 +0 -161
- package/docs.bak.1774780058/toolset.md.bak6 +0 -163
- package/docs.bak.1774780058/toolset.md.bak_path +0 -163
- package/docs.bak.1774780058/toolset.md.bak_syntax +0 -161
- package/docs.bak.1774780058/xai-responses.md +0 -111
- package/docs.bak.1774780058/xai-responses.md.bak +0 -107
- package/docs.bak.1774780058/xai-responses.md.bak2 +0 -107
- package/docs.bak.1774780058/xai_collections.md +0 -106
- package/examples/memory_agent.js +0 -152
- package/examples.bak.1774780058/ask_agent.js +0 -114
- package/examples.bak.1774780058/code_agent.js +0 -149
- package/examples.bak.1774780058/coderev_agent.js +0 -72
- package/examples.bak.1774780058/codeserver.sh +0 -47
- package/examples.bak.1774780058/daisy_agent.js +0 -177
- package/examples.bak.1774780058/docs_agent.js +0 -119
- package/examples.bak.1774780058/gpt_agent.js +0 -109
- package/examples.bak.1774780058/grok_agent.js +0 -98
- package/examples.bak.1774780058/memory_agent.js +0 -112
- package/examples.bak.1774780058/npm_agent.js +0 -175
- package/examples.bak.1774780058/prompt_agent.js +0 -112
- package/examples.bak.1774780058/readme_agent.js +0 -144
- package/examples.bak.1774780058/spawn_agent.js +0 -263
- package/examples.bak.1774780058/test_agent.js +0 -162
- package/examples.bak.1774780058/todo_agent.js +0 -138
- package/lib/genericToolset.js.bak_syntax +0 -402
- package/scenarios.bak.1774780058/data/eval_node_message.json +0 -9
- package/scenarios.bak.1774780058/data/hist_oa.json +0 -66
- package/scenarios.bak.1774780058/data/o3_response1.json +0 -96
- package/scenarios.bak.1774780058/data/oa_reasoning_parse.json +0 -112
- package/scenarios.bak.1774780058/data/tool_oa.json +0 -96
- package/scenarios.bak.1774780058/data/tool_xai.json +0 -59
- package/scenarios.bak.1774780058/data/tool_xai2.json +0 -40
- package/scenarios.bak.1774780058/data/xai-response-1.json +0 -59
- package/scenarios.bak.1774780058/data/xai-response-2.json +0 -10
- package/scenarios.bak.1774780058/data/xai_reasoning_tools_resp.json +0 -59
- package/scenarios.bak.1774780058/data/xai_search_response.json +0 -58
- package/scenarios.bak.1774780058/environment.js +0 -10
- package/scenarios.bak.1774780058/example.js +0 -17
- package/scenarios.bak.1774780058/genericToolset.test.js +0 -182
- package/scenarios.bak.1774780058/grok.js +0 -113
- package/scenarios.bak.1774780058/memory-tools.js +0 -51
- package/scenarios.bak.1774780058/openai-o3.js +0 -137
- package/scenarios.bak.1774780058/openai-prompt.js +0 -155
- package/scenarios.bak.1774780058/openai-session.js +0 -148
- package/scenarios.bak.1774780058/openai.js +0 -102
- package/scenarios.bak.1774780058/prompt.js +0 -118
- package/scenarios.bak.1774780058/promptFishbowl.js +0 -76
- package/scenarios.bak.1774780058/search.brave.com.js +0 -25
- package/scenarios.bak.1774780058/sh.js +0 -15
- package/scenarios.bak.1774780058/test-wsio.js +0 -26
- package/scenarios.bak.1774780058/testToolset.js +0 -42
- package/scenarios.bak.1774780058/toolset.js +0 -16
- package/scenarios.bak.1774780058/toolset.test.js +0 -141
- package/scenarios.bak.1774780058/write_file_syntax.test.js +0 -145
- package/scenarios.bak.1774780058/write_file_validation/README.md +0 -30
- package/scenarios.bak.1774780058/write_file_validation/bad.js +0 -3
- package/scenarios.bak.1774780058/write_file_validation/good.js +0 -4
- package/scenarios.bak.1774780058/write_file_validation/test.sh +0 -43
- package/scenarios.bak.1774780058/wsClient.js +0 -69
- package/scenarios.bak.1774780058/xai_responses.integration.test.js +0 -57
- package/scenarios.bak.1774780058/xai_responses.test.js +0 -154
- package/scenarios.bak.1774780058/xaicoll.js +0 -50
- package/scenarios.bak.1774780058/xaifiles.js +0 -48
- /package/{examples → agents}/code_agent.js +0 -0
- /package/{examples → agents}/readme_agent.js +0 -0
package/types/ToolSet.d.ts
CHANGED
|
@@ -22,6 +22,9 @@ export type TSTool = {
|
|
|
22
22
|
* - JS JSON schema
|
|
23
23
|
*/
|
|
24
24
|
parameters: TSSchema;
|
|
25
|
+
/**
|
|
26
|
+
* - The async method to execute
|
|
27
|
+
*/
|
|
25
28
|
method: (arg0: object) => Promise<any>;
|
|
26
29
|
};
|
|
27
30
|
export type TSToolListItem = {
|
|
@@ -38,57 +41,71 @@ export type TSToolListItem = {
|
|
|
38
41
|
*/
|
|
39
42
|
parameters: TSSchema;
|
|
40
43
|
};
|
|
44
|
+
/**
|
|
45
|
+
* @classdesc ToolSet manages a collection of tools (functions) that can be registered and executed, typically for AI agent function calling.
|
|
46
|
+
* Supports schema definition compatible with JSON Schema for parameters.
|
|
47
|
+
*/
|
|
41
48
|
declare class ToolSet {
|
|
42
49
|
/**
|
|
43
|
-
|
|
44
|
-
|
|
50
|
+
* Constructs a new ToolSet instance.
|
|
51
|
+
* @param {string} [choice='auto'] - Default tool choice: 'auto' | 'none' | 'required'
|
|
52
|
+
*/
|
|
45
53
|
constructor(choice?: string);
|
|
46
54
|
/**
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
55
|
+
* Getter for the number of registered tools.
|
|
56
|
+
* @returns {number} The count of tools in the set
|
|
57
|
+
*/
|
|
50
58
|
get length(): number;
|
|
51
59
|
/**
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
* Registers a new tool/command/function in the set.
|
|
61
|
+
* Overwrites if already exists (no error thrown).
|
|
62
|
+
* @param {string} name - The lowercase string name of the tool e.g. 'get_node_version'. Must match /^[#!a-z_0-9]{2,}$/
|
|
63
|
+
* @param {string} description - Human-readable description of what the tool does
|
|
64
|
+
* @param {TSSchema} parameters - JSON Schema object describing the input parameters
|
|
65
|
+
* @param {function(object): Promise<*>} method - The async function to call with parsed parameters
|
|
66
|
+
*/
|
|
58
67
|
add(name: string, description: string, parameters: TSSchema, method: (arg0: object) => Promise<any>): void;
|
|
59
68
|
/**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
* Retrieves a registered tool by name.
|
|
70
|
+
* @param {string} name - The name of the tool
|
|
71
|
+
* @returns {TSTool} The tool object
|
|
72
|
+
* @throws {Error} If tool not found
|
|
73
|
+
*/
|
|
64
74
|
get(name: string): TSTool;
|
|
65
75
|
/**
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
76
|
+
* Deletes a tool from the set by name.
|
|
77
|
+
* @param {string} name - The name of the tool to delete
|
|
78
|
+
*/
|
|
69
79
|
delete(name: string): void;
|
|
70
80
|
/**
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
81
|
+
* Checks if a tool with the given name is registered.
|
|
82
|
+
* @param {string} name - The tool name to check
|
|
83
|
+
* @returns {boolean} True if the tool exists
|
|
84
|
+
*/
|
|
75
85
|
has(name: string): boolean;
|
|
76
86
|
/**
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
87
|
+
* Returns a sorted list of all registered tools (excluding methods).
|
|
88
|
+
* @returns {TSToolListItem[]} Array of tool summaries, sorted by name
|
|
89
|
+
*/
|
|
80
90
|
list(): TSToolListItem[];
|
|
91
|
+
/**
|
|
92
|
+
* Getter for the current tool choice setting.
|
|
93
|
+
* @returns {string} The tool choice: 'auto', 'none', or 'required'
|
|
94
|
+
*/
|
|
81
95
|
get toolChoice(): string;
|
|
82
96
|
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
97
|
+
* Executes a specific tool by name with given parameters.
|
|
98
|
+
* @param {string} name - The tool name
|
|
99
|
+
* @param {object} params - The parameters object
|
|
100
|
+
* @returns {Promise<*>} The result from the tool method
|
|
101
|
+
* @throws {Error} If tool not found or execution fails
|
|
102
|
+
*/
|
|
88
103
|
call(name: string, params: object): Promise<any>;
|
|
89
104
|
/**
|
|
90
|
-
*
|
|
91
|
-
*
|
|
105
|
+
* Processes and executes function requests from the last message in a Prompt.
|
|
106
|
+
* Automatically handles multiple calls, emits events, and adds responses back to the prompt.
|
|
107
|
+
* @param {Prompt} prompt - The Prompt instance containing the last message with function_request(s)
|
|
108
|
+
* @returns {Promise<void>}
|
|
92
109
|
*/
|
|
93
110
|
execute(prompt: Prompt): Promise<void>;
|
|
94
111
|
#private;
|
package/types/fafs.d.ts
CHANGED
|
@@ -1,47 +1,90 @@
|
|
|
1
1
|
export type EnvironmentInfo = {
|
|
2
2
|
/**
|
|
3
|
-
* - User's name
|
|
3
|
+
* - User's full name (from passwd GECOS field)
|
|
4
4
|
*/
|
|
5
5
|
name: string;
|
|
6
6
|
/**
|
|
7
|
-
* -
|
|
7
|
+
* - System information (OS release, architecture, kernel, cwd)
|
|
8
8
|
*/
|
|
9
9
|
system: string;
|
|
10
|
+
/**
|
|
11
|
+
* - City from external IP geolocation
|
|
12
|
+
*/
|
|
10
13
|
city: string;
|
|
14
|
+
/**
|
|
15
|
+
* - Region/State from IP
|
|
16
|
+
*/
|
|
11
17
|
region: string;
|
|
18
|
+
/**
|
|
19
|
+
* - Country from IP
|
|
20
|
+
*/
|
|
12
21
|
country: string;
|
|
22
|
+
/**
|
|
23
|
+
* - Timezone from IP
|
|
24
|
+
*/
|
|
13
25
|
timezone: string;
|
|
26
|
+
/**
|
|
27
|
+
* - External IP address
|
|
28
|
+
*/
|
|
14
29
|
external_ip: string;
|
|
15
30
|
/**
|
|
16
|
-
* -
|
|
31
|
+
* - Current working directory (relative to home as ~)
|
|
17
32
|
*/
|
|
18
33
|
cwd: string;
|
|
19
34
|
};
|
|
20
35
|
import { jsType } from '@j-o-r/sh';
|
|
21
|
-
export namespace GLOBAL {
|
|
22
|
-
export let max_recursive_requests: number;
|
|
23
|
-
export { APP_CACHE as default_cache };
|
|
24
|
-
export let secret: string;
|
|
25
|
-
}
|
|
26
36
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
* Frequently Asked Functions (FAFS) - Utility module providing environment and system information utilities.
|
|
38
|
+
*
|
|
39
|
+
* Main features:
|
|
40
|
+
* - `env()`: Gathers user, system, location, and path info (cached 31 days).
|
|
41
|
+
* - `systemInfo()`: Detailed OS/architecture/working dir string.
|
|
42
|
+
* - `GLOBAL`: Shared config (max requests, cache path, secret).
|
|
43
|
+
*
|
|
44
|
+
* @module fafs
|
|
45
|
+
* @exports {function} env
|
|
46
|
+
* @exports {function} systemInfo
|
|
47
|
+
* @exports {Object} GLOBAL
|
|
48
|
+
* @exports {function} jsType
|
|
49
|
+
*/
|
|
31
50
|
/**
|
|
32
|
-
* @typedef {Object} EnvironmentInfo
|
|
33
|
-
* @property {string} name - User's name
|
|
34
|
-
* @property {string} system -
|
|
35
|
-
* @property {string} city
|
|
36
|
-
* @property {string} region
|
|
37
|
-
* @property {string} country
|
|
38
|
-
* @property {string} timezone
|
|
39
|
-
* @property {string} external_ip
|
|
40
|
-
* @property {string} cwd -
|
|
41
|
-
*/
|
|
51
|
+
* @typedef {Object} EnvironmentInfo
|
|
52
|
+
* @property {string} name - User's full name (from passwd GECOS field)
|
|
53
|
+
* @property {string} system - System information (OS release, architecture, kernel, cwd)
|
|
54
|
+
* @property {string} city - City from external IP geolocation
|
|
55
|
+
* @property {string} region - Region/State from IP
|
|
56
|
+
* @property {string} country - Country from IP
|
|
57
|
+
* @property {string} timezone - Timezone from IP
|
|
58
|
+
* @property {string} external_ip - External IP address
|
|
59
|
+
* @property {string} cwd - Current working directory (relative to home as ~)
|
|
60
|
+
*/
|
|
61
|
+
/**
|
|
62
|
+
* Global configuration and constants for the application.
|
|
63
|
+
* @type {Object}
|
|
64
|
+
* @property {number} max_recursive_requests - Maximum number of recursive requests allowed (default: 20)
|
|
65
|
+
* @property {string} default_cache - Path to the default application cache directory
|
|
66
|
+
* @property {string} secret - Secret key for cache encryption/security
|
|
67
|
+
*/
|
|
68
|
+
export const GLOBAL: Object;
|
|
69
|
+
/**
|
|
70
|
+
* Gathers comprehensive environment information: user name, fresh system details, IP-based geolocation,
|
|
71
|
+
* and normalized current working directory. Results are cached in ~/.cache/hello-dave/env for 31 days,
|
|
72
|
+
* refreshed on expiry. On cache hit, updates with fresh system info and cwd.
|
|
73
|
+
*
|
|
74
|
+
* @returns {Promise<EnvironmentInfo>} The environment information object.
|
|
75
|
+
* @example
|
|
76
|
+
* const envInfo = await env();
|
|
77
|
+
* console.log(envInfo.name, envInfo.city, envInfo.system);
|
|
78
|
+
*/
|
|
79
|
+
export function env(): Promise<EnvironmentInfo>;
|
|
42
80
|
/**
|
|
43
|
-
*
|
|
44
|
-
|
|
81
|
+
* Retrieves detailed system information including OS release (/etc/issue), machine architecture (uname -m),
|
|
82
|
+
* operating system (uname -o), and current working directory.
|
|
83
|
+
*
|
|
84
|
+
* @returns {Promise<string>} Formatted multi-line string with system details.
|
|
85
|
+
* @example
|
|
86
|
+
* const info = await systemInfo();
|
|
87
|
+
* // "system: Ubuntu 25.10 \n\nx86_64\nGNU/Linux\ncwd: /home/user/project"
|
|
88
|
+
*/
|
|
45
89
|
export function systemInfo(): Promise<string>;
|
|
46
|
-
declare const APP_CACHE: any;
|
|
47
90
|
export { jsType };
|
package/types/wsCli.d.ts
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env -S node
|
|
2
2
|
declare function _default(connectUrl: string, secret?: string): void;
|
|
3
3
|
export default _default;
|
|
4
|
+
export type WsMessage = {
|
|
5
|
+
/**
|
|
6
|
+
* - Action type (e.g., 'user_request')
|
|
7
|
+
*/
|
|
8
|
+
action: string;
|
|
9
|
+
/**
|
|
10
|
+
* - Message content
|
|
11
|
+
*/
|
|
12
|
+
content: string;
|
|
13
|
+
/**
|
|
14
|
+
* - Unique message ID
|
|
15
|
+
*/
|
|
16
|
+
id: number;
|
|
17
|
+
};
|
package/types/wsIO.d.ts
CHANGED
|
@@ -10,12 +10,16 @@
|
|
|
10
10
|
* Sends intro + action, awaits matching response by ID, closes, returns response.
|
|
11
11
|
*
|
|
12
12
|
* @param {string} connectUrl - Websocket server endpoint to connect to
|
|
13
|
-
* @param {string} [secret] - Secret websocket connection key
|
|
14
|
-
* @param {'user_request'|'user_info'|'user_reset'} action - Action
|
|
15
|
-
* @param {string} [input] -
|
|
16
|
-
* @returns {Promise
|
|
13
|
+
* @param {string} [secret=''] - Secret websocket connection key
|
|
14
|
+
* @param {'user_request'|'user_info'|'user_reset'} action - Action to perform
|
|
15
|
+
* @param {string} [input=''] - Input content (required for 'user_request')
|
|
16
|
+
* @returns {Promise<wsResponse>}
|
|
17
|
+
* @throws {Error} Invalid action or missing input for user_request
|
|
18
|
+
* @example
|
|
19
|
+
* const response = await wsio('ws://localhost:8080', 'secret', 'user_request', 'Hello!');
|
|
20
|
+
* console.log(response.content);
|
|
17
21
|
*/
|
|
18
|
-
export default function wsio(connectUrl: string, secret?: string, action: "user_request" | "user_info" | "user_reset", input?: string): Promise<
|
|
22
|
+
export default function wsio(connectUrl: string, secret?: string, action: "user_request" | "user_info" | "user_reset", input?: string): Promise<any> & lt;
|
|
19
23
|
export type wsResponse = {
|
|
20
24
|
action: string;
|
|
21
25
|
content: string;
|
package/utils/search_sessions.sh
CHANGED
|
@@ -1,73 +1,120 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
+
# v2: Role-filtered (user/assistant only), condense per-session/dir, ultra token-efficient.
|
|
3
|
+
# Usage: $0 <query> [--brief] [--all-roles] [--limit=10] [--max-snip=3]
|
|
2
4
|
|
|
3
|
-
# No set -e to avoid unexpected exits; use explicit checks
|
|
4
5
|
set -uo pipefail
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
usage() {
|
|
8
|
+
echo "Usage: $0 <query> [--brief] [--all-roles] [--limit=10] [--max-snip=3]"
|
|
9
|
+
echo " Role-filtered snippets (user/assistant), condensed per session dir."
|
|
10
|
+
exit 1
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
[ $# -eq 0 ] && usage
|
|
13
14
|
|
|
14
15
|
QUERY="$1"
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
LIMIT=10
|
|
17
|
+
MAX_SNIP=3
|
|
18
|
+
BRIEF=false
|
|
19
|
+
ROLE_FILTER=true # Default: user/assistant only
|
|
20
|
+
shift
|
|
21
|
+
|
|
22
|
+
while [ $# -gt 0 ]; do
|
|
23
|
+
case "$1" in
|
|
24
|
+
--brief) BRIEF=true; shift ;;
|
|
25
|
+
--all-roles) ROLE_FILTER=false; shift ;;
|
|
26
|
+
--limit=*) LIMIT="${1#*=}"; shift ;;
|
|
27
|
+
--max-snip=*) MAX_SNIP="${1#*=}"; shift ;;
|
|
28
|
+
--limit) LIMIT="$2"; shift 2 ;;
|
|
29
|
+
--max-snip) MAX_SNIP="$2"; shift 2 ;;
|
|
30
|
+
*) echo "Unknown: $1"; usage ;;
|
|
31
|
+
esac
|
|
32
|
+
done
|
|
18
33
|
|
|
19
|
-
|
|
20
|
-
|
|
34
|
+
# 1st pass: matching sessions/files
|
|
35
|
+
declare -a matching_sessions=()
|
|
36
|
+
total_files=0
|
|
37
|
+
scanned=0
|
|
21
38
|
|
|
22
|
-
|
|
23
|
-
while IFS= read -r -d '' sess_dir; do
|
|
39
|
+
while IFS= read -r -d '' sess_dir <&3; do
|
|
24
40
|
[ -d "$sess_dir" ] || continue
|
|
41
|
+
((scanned++))
|
|
42
|
+
|
|
43
|
+
files_matched=0
|
|
44
|
+
shopt -s nullglob
|
|
45
|
+
for file in "$sess_dir"/*.ndjson; do
|
|
46
|
+
base=$(basename "$file" .ndjson)
|
|
47
|
+
has_match=false
|
|
48
|
+
# Filename
|
|
49
|
+
if echo "$base" | grep -qiE "$QUERY"; then
|
|
50
|
+
has_match=true
|
|
51
|
+
# Content (role-filtered if enabled)
|
|
52
|
+
elif ! $BRIEF && [ "$ROLE_FILTER" = true ] && \
|
|
53
|
+
awk -v q="$QUERY" 'tolower($0) ~ tolower(q) && /"role"\s*:\s*"(user|assistant)"/ {exit 0} END{exit !NR}' "$file" 2>/dev/null; then
|
|
54
|
+
has_match=true
|
|
55
|
+
elif ! $BRIEF && [ "$ROLE_FILTER" = false ] && grep -qiE -m1 "$QUERY" "$file" 2>/dev/null; then
|
|
56
|
+
has_match=true
|
|
57
|
+
fi
|
|
58
|
+
[ "$has_match" = true ] && ((files_matched++))
|
|
59
|
+
done
|
|
60
|
+
shopt -u nullglob
|
|
61
|
+
[ $files_matched -gt 0 ] || continue
|
|
62
|
+
matching_sessions+=("$sess_dir")
|
|
63
|
+
((total_files += files_matched))
|
|
64
|
+
done 3< <(find .cache -mindepth 3 -maxdepth 5 -type d -name sessions -print0 2>/dev/null | sort -rz | head -"$LIMIT")
|
|
65
|
+
|
|
66
|
+
[ $total_files -eq 0 ] && exit 0
|
|
25
67
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
prompt_name=$(basename "$(dirname "$sess_dir")")
|
|
29
|
-
mod_time=$(stat -c %Y "$sess_dir" 2>/dev/null || echo 0)
|
|
30
|
-
date_str=$(date -d "@$mod_time" '+%Y-%m-%d %H:%M' 2>/dev/null || echo "unknown")
|
|
68
|
+
echo "🔍 $QUERY: $total_files files / ${#matching_sessions[@]} sessions (limit=$LIMIT)"
|
|
69
|
+
echo ===
|
|
31
70
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
71
|
+
# 2nd pass: condensed output
|
|
72
|
+
for sess_dir in "${matching_sessions[@]}"; do
|
|
73
|
+
app=$(basename "$(dirname "$(dirname "$sess_dir")")")
|
|
74
|
+
prompt=$(basename "$(dirname "$sess_dir")")
|
|
75
|
+
time=$(stat -c %Y "$sess_dir" 2>/dev/null | xargs -I{} date -d "@{}" '+%H:%M' 2>/dev/null || echo ??)
|
|
35
76
|
|
|
36
|
-
|
|
77
|
+
echo "📁 $app/$prompt ($time)"
|
|
78
|
+
echo ---
|
|
79
|
+
|
|
80
|
+
dir_count=0
|
|
81
|
+
all_snips="" # Condense all files' snippets here
|
|
37
82
|
shopt -s nullglob
|
|
38
|
-
for
|
|
39
|
-
[ -f "$
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
dir_matches=$((dir_matches + 1))
|
|
49
|
-
total_matches=$((total_matches + 1))
|
|
83
|
+
for file in "$sess_dir"/*.ndjson; do
|
|
84
|
+
[ -f "$file" ] || continue
|
|
85
|
+
base=$(basename "$file" .ndjson)
|
|
86
|
+
name=$(echo "$base" | sed 's/__/ /g; s/_[0-9]*$//' | fold -w30 | sed -E 's/(.{27}).*/\1.../') || name="$base..."
|
|
87
|
+
|
|
88
|
+
printed=false
|
|
89
|
+
# Filename
|
|
90
|
+
if echo "$base" | grep -qiE "$QUERY"; then
|
|
91
|
+
echo " 💾 $name"
|
|
92
|
+
printed=true
|
|
50
93
|
fi
|
|
51
94
|
|
|
52
|
-
# Content
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
95
|
+
# Content snippets (role-filtered awk)
|
|
96
|
+
if ! $BRIEF; then
|
|
97
|
+
if [ "$ROLE_FILTER" = true ]; then
|
|
98
|
+
snips=$(awk -v q="$QUERY" 'tolower($0) ~ tolower(q) && /"role"\s*:\s*"(user|assistant)"/ { print substr($0, 1, 100) }' "$file" 2>/dev/null | head -"$MAX_SNIP" | paste -sd'; ')
|
|
99
|
+
else
|
|
100
|
+
snips=$(grep -iE "$QUERY" "$file" 2>/dev/null | cut -c1-100 | head -"$MAX_SNIP" | paste -sd'; ')
|
|
101
|
+
fi
|
|
102
|
+
[ -n "$snips" ] && {
|
|
103
|
+
all_snips+="$snips; "
|
|
104
|
+
printed=true
|
|
105
|
+
}
|
|
60
106
|
fi
|
|
107
|
+
[ "$printed" = true ] && ((dir_count++))
|
|
61
108
|
done
|
|
62
109
|
shopt -u nullglob
|
|
63
110
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
111
|
+
# Condensed session block
|
|
112
|
+
[ -n "$all_snips" ] && {
|
|
113
|
+
echo " 📄 Session ($dir_count files): $(echo "$all_snips" | fold -w90 | sed ':a;N;$!ba;s/\n/ /g' | cut -c1-180)"
|
|
114
|
+
echo
|
|
115
|
+
}
|
|
116
|
+
echo " ($dir_count files)"
|
|
117
|
+
echo
|
|
118
|
+
done
|
|
69
119
|
|
|
70
|
-
echo "✅ $
|
|
71
|
-
if [ $total_matches -eq 0 ]; then
|
|
72
|
-
echo "💡 Tip: Broader query? e.g. 'todo', regex '(package|bin)' or check spelling."
|
|
73
|
-
fi
|
|
120
|
+
echo "✅ $total_files files / ${#matching_sessions[@]} sessions (scanned $scanned)"
|