@zds-ai/cli 0.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/LICENSE +21 -0
- package/README.md +497 -0
- package/dist/agent/grok-agent.d.ts +250 -0
- package/dist/agent/grok-agent.js +2480 -0
- package/dist/agent/grok-agent.js.map +1 -0
- package/dist/agent/index.d.ts +14 -0
- package/dist/agent/index.js +136 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/commands/mcp.d.ts +2 -0
- package/dist/commands/mcp.js +239 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/grok/client.d.ts +55 -0
- package/dist/grok/client.js +276 -0
- package/dist/grok/client.js.map +1 -0
- package/dist/grok/tools.d.ts +8 -0
- package/dist/grok/tools.js +878 -0
- package/dist/grok/tools.js.map +1 -0
- package/dist/hooks/use-enhanced-input.d.ts +38 -0
- package/dist/hooks/use-enhanced-input.js +228 -0
- package/dist/hooks/use-enhanced-input.js.map +1 -0
- package/dist/hooks/use-input-handler.d.ts +36 -0
- package/dist/hooks/use-input-handler.js +1099 -0
- package/dist/hooks/use-input-handler.js.map +1 -0
- package/dist/hooks/use-input-history.d.ts +9 -0
- package/dist/hooks/use-input-history.js +61 -0
- package/dist/hooks/use-input-history.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +869 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +41 -0
- package/dist/mcp/client.js +224 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/config.d.ts +13 -0
- package/dist/mcp/config.js +56 -0
- package/dist/mcp/config.js.map +1 -0
- package/dist/mcp/transports.d.ts +53 -0
- package/dist/mcp/transports.js +256 -0
- package/dist/mcp/transports.js.map +1 -0
- package/dist/tools/character-tool.d.ts +27 -0
- package/dist/tools/character-tool.js +194 -0
- package/dist/tools/character-tool.js.map +1 -0
- package/dist/tools/clear-cache-tool.d.ts +14 -0
- package/dist/tools/clear-cache-tool.js +82 -0
- package/dist/tools/clear-cache-tool.js.map +1 -0
- package/dist/tools/confirmation-tool.d.ts +16 -0
- package/dist/tools/confirmation-tool.js +72 -0
- package/dist/tools/confirmation-tool.js.map +1 -0
- package/dist/tools/env-tool.d.ts +17 -0
- package/dist/tools/env-tool.js +89 -0
- package/dist/tools/env-tool.js.map +1 -0
- package/dist/tools/file-conversion-tool.d.ts +16 -0
- package/dist/tools/file-conversion-tool.js +181 -0
- package/dist/tools/file-conversion-tool.js.map +1 -0
- package/dist/tools/image-tool.d.ts +22 -0
- package/dist/tools/image-tool.js +268 -0
- package/dist/tools/image-tool.js.map +1 -0
- package/dist/tools/index.d.ts +14 -0
- package/dist/tools/index.js +15 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/internet-tool.d.ts +11 -0
- package/dist/tools/internet-tool.js +108 -0
- package/dist/tools/internet-tool.js.map +1 -0
- package/dist/tools/introspect-tool.d.ts +11 -0
- package/dist/tools/introspect-tool.js +243 -0
- package/dist/tools/introspect-tool.js.map +1 -0
- package/dist/tools/morph-editor.d.ts +38 -0
- package/dist/tools/morph-editor.js +318 -0
- package/dist/tools/morph-editor.js.map +1 -0
- package/dist/tools/restart-tool.d.ts +7 -0
- package/dist/tools/restart-tool.js +24 -0
- package/dist/tools/restart-tool.js.map +1 -0
- package/dist/tools/search.d.ts +71 -0
- package/dist/tools/search.js +340 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/task-tool.d.ts +19 -0
- package/dist/tools/task-tool.js +115 -0
- package/dist/tools/task-tool.js.map +1 -0
- package/dist/tools/text-editor.d.ts +35 -0
- package/dist/tools/text-editor.js +669 -0
- package/dist/tools/text-editor.js.map +1 -0
- package/dist/tools/tool-discovery.d.ts +20 -0
- package/dist/tools/tool-discovery.js +45 -0
- package/dist/tools/tool-discovery.js.map +1 -0
- package/dist/tools/zsh.d.ts +13 -0
- package/dist/tools/zsh.js +168 -0
- package/dist/tools/zsh.js.map +1 -0
- package/dist/types/index.d.ts +31 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/ui/app.d.ts +7 -0
- package/dist/ui/app.js +99 -0
- package/dist/ui/app.js.map +1 -0
- package/dist/ui/components/active-task-status.d.ts +7 -0
- package/dist/ui/components/active-task-status.js +37 -0
- package/dist/ui/components/active-task-status.js.map +1 -0
- package/dist/ui/components/api-key-input.d.ts +7 -0
- package/dist/ui/components/api-key-input.js +80 -0
- package/dist/ui/components/api-key-input.js.map +1 -0
- package/dist/ui/components/backend-status.d.ts +7 -0
- package/dist/ui/components/backend-status.js +85 -0
- package/dist/ui/components/backend-status.js.map +1 -0
- package/dist/ui/components/chat-history.d.ts +8 -0
- package/dist/ui/components/chat-history.js +187 -0
- package/dist/ui/components/chat-history.js.map +1 -0
- package/dist/ui/components/chat-input.d.ts +9 -0
- package/dist/ui/components/chat-input.js +63 -0
- package/dist/ui/components/chat-input.js.map +1 -0
- package/dist/ui/components/chat-interface.d.ts +9 -0
- package/dist/ui/components/chat-interface.js +389 -0
- package/dist/ui/components/chat-interface.js.map +1 -0
- package/dist/ui/components/command-suggestions.d.ts +17 -0
- package/dist/ui/components/command-suggestions.js +22 -0
- package/dist/ui/components/command-suggestions.js.map +1 -0
- package/dist/ui/components/confirmation-dialog.d.ts +11 -0
- package/dist/ui/components/confirmation-dialog.js +105 -0
- package/dist/ui/components/confirmation-dialog.js.map +1 -0
- package/dist/ui/components/context-status.d.ts +7 -0
- package/dist/ui/components/context-status.js +36 -0
- package/dist/ui/components/context-status.js.map +1 -0
- package/dist/ui/components/diff-renderer.d.ts +13 -0
- package/dist/ui/components/diff-renderer.js +206 -0
- package/dist/ui/components/diff-renderer.js.map +1 -0
- package/dist/ui/components/loading-spinner.d.ts +8 -0
- package/dist/ui/components/loading-spinner.js +64 -0
- package/dist/ui/components/loading-spinner.js.map +1 -0
- package/dist/ui/components/mcp-status.d.ts +5 -0
- package/dist/ui/components/mcp-status.js +57 -0
- package/dist/ui/components/mcp-status.js.map +1 -0
- package/dist/ui/components/model-selection.d.ts +12 -0
- package/dist/ui/components/model-selection.js +17 -0
- package/dist/ui/components/model-selection.js.map +1 -0
- package/dist/ui/components/mood-status.d.ts +7 -0
- package/dist/ui/components/mood-status.js +34 -0
- package/dist/ui/components/mood-status.js.map +1 -0
- package/dist/ui/components/persona-status.d.ts +7 -0
- package/dist/ui/components/persona-status.js +34 -0
- package/dist/ui/components/persona-status.js.map +1 -0
- package/dist/ui/shared/max-sized-box.d.ts +8 -0
- package/dist/ui/shared/max-sized-box.js +6 -0
- package/dist/ui/shared/max-sized-box.js.map +1 -0
- package/dist/ui/utils/code-colorizer.d.ts +2 -0
- package/dist/ui/utils/code-colorizer.js +7 -0
- package/dist/ui/utils/code-colorizer.js.map +1 -0
- package/dist/ui/utils/colors.d.ts +14 -0
- package/dist/ui/utils/colors.js +15 -0
- package/dist/ui/utils/colors.js.map +1 -0
- package/dist/ui/utils/markdown-renderer.d.ts +4 -0
- package/dist/ui/utils/markdown-renderer.js +40 -0
- package/dist/ui/utils/markdown-renderer.js.map +1 -0
- package/dist/utils/auth-helper.d.ts +63 -0
- package/dist/utils/auth-helper.js +129 -0
- package/dist/utils/auth-helper.js.map +1 -0
- package/dist/utils/chat-history-manager-sqlite.d.ts +92 -0
- package/dist/utils/chat-history-manager-sqlite.js +334 -0
- package/dist/utils/chat-history-manager-sqlite.js.map +1 -0
- package/dist/utils/chat-history-manager.d.ts +87 -0
- package/dist/utils/chat-history-manager.js +273 -0
- package/dist/utils/chat-history-manager.js.map +1 -0
- package/dist/utils/chat-history-manager.json-backup.d.ts +69 -0
- package/dist/utils/chat-history-manager.json-backup.js +215 -0
- package/dist/utils/chat-history-manager.json-backup.js.map +1 -0
- package/dist/utils/confirmation-service.d.ts +46 -0
- package/dist/utils/confirmation-service.js +165 -0
- package/dist/utils/confirmation-service.js.map +1 -0
- package/dist/utils/custom-instructions.d.ts +1 -0
- package/dist/utils/custom-instructions.js +30 -0
- package/dist/utils/custom-instructions.js.map +1 -0
- package/dist/utils/database-connection.d.ts +27 -0
- package/dist/utils/database-connection.js +81 -0
- package/dist/utils/database-connection.js.map +1 -0
- package/dist/utils/database-schema.d.ts +17 -0
- package/dist/utils/database-schema.js +93 -0
- package/dist/utils/database-schema.js.map +1 -0
- package/dist/utils/error-logger.d.ts +13 -0
- package/dist/utils/error-logger.js +56 -0
- package/dist/utils/error-logger.js.map +1 -0
- package/dist/utils/hook-executor.d.ts +59 -0
- package/dist/utils/hook-executor.js +351 -0
- package/dist/utils/hook-executor.js.map +1 -0
- package/dist/utils/model-config.d.ts +28 -0
- package/dist/utils/model-config.js +42 -0
- package/dist/utils/model-config.js.map +1 -0
- package/dist/utils/path-utils.d.ts +4 -0
- package/dist/utils/path-utils.js +12 -0
- package/dist/utils/path-utils.js.map +1 -0
- package/dist/utils/settings-manager.d.ts +169 -0
- package/dist/utils/settings-manager.js +403 -0
- package/dist/utils/settings-manager.js.map +1 -0
- package/dist/utils/settings.d.ts +1 -0
- package/dist/utils/settings.js +4 -0
- package/dist/utils/settings.js.map +1 -0
- package/dist/utils/slash-commands.d.ts +25 -0
- package/dist/utils/slash-commands.js +454 -0
- package/dist/utils/slash-commands.js.map +1 -0
- package/dist/utils/startup-hook.d.ts +13 -0
- package/dist/utils/startup-hook.js +44 -0
- package/dist/utils/startup-hook.js.map +1 -0
- package/dist/utils/text-utils.d.ts +80 -0
- package/dist/utils/text-utils.js +182 -0
- package/dist/utils/text-utils.js.map +1 -0
- package/dist/utils/token-counter.d.ts +33 -0
- package/dist/utils/token-counter.js +78 -0
- package/dist/utils/token-counter.js.map +1 -0
- package/package.json +102 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import * as path from "path";
|
|
3
|
+
import * as os from "os";
|
|
4
|
+
import * as fs from "fs";
|
|
5
|
+
const ENV_PREFIX = "ZDS_AI_AGENT_";
|
|
6
|
+
/**
|
|
7
|
+
* Parse hook output for command directives
|
|
8
|
+
* Lines starting with "ENV ", "TOOL_RESULT ", "ECHO ", "RUN ", "BACKEND ", "MODEL ", "SYSTEM ", "SYSTEM_FILE ", "BASE_URL ", or "API_KEY_ENV_VAR " are commands
|
|
9
|
+
* Other lines are treated as TOOL_RESULT if present
|
|
10
|
+
*/
|
|
11
|
+
function parseHookOutput(stdout) {
|
|
12
|
+
const commands = [];
|
|
13
|
+
const lines = stdout.split("\n").filter((line) => line.trim());
|
|
14
|
+
for (const line of lines) {
|
|
15
|
+
if (line.startsWith("ENV ")) {
|
|
16
|
+
commands.push({ type: "ENV", value: line.slice(4) });
|
|
17
|
+
}
|
|
18
|
+
else if (line.startsWith("TOOL_RESULT ")) {
|
|
19
|
+
commands.push({ type: "TOOL_RESULT", value: line.slice(12) });
|
|
20
|
+
}
|
|
21
|
+
else if (line.startsWith("ECHO ")) {
|
|
22
|
+
commands.push({ type: "ECHO", value: line.slice(5) });
|
|
23
|
+
}
|
|
24
|
+
else if (line.startsWith("RUN ")) {
|
|
25
|
+
commands.push({ type: "RUN", value: line.slice(4) });
|
|
26
|
+
}
|
|
27
|
+
else if (line.startsWith("BACKEND ")) {
|
|
28
|
+
commands.push({ type: "BACKEND", value: line.slice(8) });
|
|
29
|
+
}
|
|
30
|
+
else if (line.startsWith("MODEL ")) {
|
|
31
|
+
commands.push({ type: "MODEL", value: line.slice(6) });
|
|
32
|
+
}
|
|
33
|
+
else if (line.startsWith("SYSTEM_FILE ")) {
|
|
34
|
+
commands.push({ type: "SYSTEM_FILE", value: line.slice(12) });
|
|
35
|
+
}
|
|
36
|
+
else if (line.startsWith("SYSTEM ")) {
|
|
37
|
+
commands.push({ type: "SYSTEM", value: line.slice(7) });
|
|
38
|
+
}
|
|
39
|
+
else if (line.startsWith("BASE_URL ")) {
|
|
40
|
+
commands.push({ type: "BASE_URL", value: line.slice(9) });
|
|
41
|
+
}
|
|
42
|
+
else if (line.startsWith("API_KEY_ENV_VAR ")) {
|
|
43
|
+
commands.push({ type: "API_KEY_ENV_VAR", value: line.slice(16) });
|
|
44
|
+
}
|
|
45
|
+
else if (line.trim()) {
|
|
46
|
+
// Non-empty lines without a command prefix are treated as TOOL_RESULT
|
|
47
|
+
commands.push({ type: "TOOL_RESULT", value: line });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return commands;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Apply hook commands and return extracted values
|
|
54
|
+
* ENV commands are applied to process.env (auto-prefixes ENV_PREFIX if not present)
|
|
55
|
+
* ENV VAR= (empty value) will unset the variable
|
|
56
|
+
* TOOL_RESULT commands are aggregated into a single string
|
|
57
|
+
* SYSTEM commands are aggregated into a single string
|
|
58
|
+
* SYSTEM_FILE commands read file contents (up to 20k) and add to system string
|
|
59
|
+
* MODEL commands set the model to use (last one wins if multiple)
|
|
60
|
+
* BACKEND commands set the backend to use (last one wins if multiple)
|
|
61
|
+
* BASE_URL commands set the base URL to use (last one wins if multiple)
|
|
62
|
+
* API_KEY_ENV_VAR commands set the env var name for API key (last one wins if multiple)
|
|
63
|
+
* Returns extracted values for caller to use
|
|
64
|
+
*/
|
|
65
|
+
export function applyHookCommands(commands) {
|
|
66
|
+
const env = {};
|
|
67
|
+
const toolResultLines = [];
|
|
68
|
+
const systemLines = [];
|
|
69
|
+
let model = undefined;
|
|
70
|
+
let backend = undefined;
|
|
71
|
+
let baseUrl = undefined;
|
|
72
|
+
let apiKeyEnvVar = undefined;
|
|
73
|
+
for (const cmd of commands) {
|
|
74
|
+
if (cmd.type === "ENV") {
|
|
75
|
+
// Parse "KEY=VALUE" - DO NOT apply to process.env yet, just extract
|
|
76
|
+
const match = cmd.value.match(/^([A-Z_]+)=(.*)$/);
|
|
77
|
+
if (match) {
|
|
78
|
+
let [, key, value] = match;
|
|
79
|
+
// If key doesn't start with ENV_PREFIX, prepend it
|
|
80
|
+
if (!key.startsWith(ENV_PREFIX)) {
|
|
81
|
+
key = `${ENV_PREFIX}${key}`;
|
|
82
|
+
}
|
|
83
|
+
// Store ALL env variables for caller to apply after test succeeds
|
|
84
|
+
env[key] = value;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
else if (cmd.type === "TOOL_RESULT") {
|
|
88
|
+
toolResultLines.push(cmd.value);
|
|
89
|
+
}
|
|
90
|
+
else if (cmd.type === "SYSTEM") {
|
|
91
|
+
systemLines.push(cmd.value);
|
|
92
|
+
}
|
|
93
|
+
else if (cmd.type === "SYSTEM_FILE") {
|
|
94
|
+
// Read file contents and add to system lines
|
|
95
|
+
const filePath = cmd.value.trim();
|
|
96
|
+
try {
|
|
97
|
+
// Expand ~ to home directory
|
|
98
|
+
const expandedPath = filePath.startsWith("~/")
|
|
99
|
+
? path.join(os.homedir(), filePath.slice(2))
|
|
100
|
+
: filePath;
|
|
101
|
+
const MAX_FILE_SIZE = 20000;
|
|
102
|
+
// Check file size first
|
|
103
|
+
const stats = fs.statSync(expandedPath);
|
|
104
|
+
if (stats.size > MAX_FILE_SIZE) {
|
|
105
|
+
// File is too large - read only first 20k bytes
|
|
106
|
+
const fd = fs.openSync(expandedPath, 'r');
|
|
107
|
+
const buffer = Buffer.alloc(MAX_FILE_SIZE);
|
|
108
|
+
fs.readSync(fd, buffer, 0, MAX_FILE_SIZE, 0);
|
|
109
|
+
fs.closeSync(fd);
|
|
110
|
+
const truncated = buffer.toString('utf-8');
|
|
111
|
+
systemLines.push(`${truncated}\n\n[File truncated at ${MAX_FILE_SIZE} characters]`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
// File is small enough - read entire file
|
|
115
|
+
const fileContents = fs.readFileSync(expandedPath, 'utf-8');
|
|
116
|
+
systemLines.push(fileContents);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
// Add error message to system lines if file can't be read
|
|
121
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
122
|
+
systemLines.push(`[Error reading file ${filePath}: ${errorMsg}]`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else if (cmd.type === "MODEL") {
|
|
126
|
+
model = cmd.value.trim();
|
|
127
|
+
}
|
|
128
|
+
else if (cmd.type === "BACKEND") {
|
|
129
|
+
backend = cmd.value.trim();
|
|
130
|
+
}
|
|
131
|
+
else if (cmd.type === "BASE_URL") {
|
|
132
|
+
baseUrl = cmd.value.trim();
|
|
133
|
+
}
|
|
134
|
+
else if (cmd.type === "API_KEY_ENV_VAR") {
|
|
135
|
+
apiKeyEnvVar = cmd.value.trim();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return {
|
|
139
|
+
env,
|
|
140
|
+
toolResult: toolResultLines.join("\n"),
|
|
141
|
+
system: systemLines.join("\n"),
|
|
142
|
+
model,
|
|
143
|
+
backend,
|
|
144
|
+
baseUrl,
|
|
145
|
+
apiKeyEnvVar,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Apply extracted ENV variables to process.env
|
|
150
|
+
* Should be called AFTER model/backend tests succeed
|
|
151
|
+
* @param env Environment variables to apply
|
|
152
|
+
*/
|
|
153
|
+
export function applyEnvVariables(env) {
|
|
154
|
+
for (const [key, value] of Object.entries(env)) {
|
|
155
|
+
if (value === '') {
|
|
156
|
+
// Empty value means unset the variable
|
|
157
|
+
delete process.env[key];
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
process.env[key] = value;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Execute a hook with operation details passed via environment variables
|
|
166
|
+
* Generic hook executor for operations that need validation
|
|
167
|
+
* @param hookPath Path to hook script (supports ~/ expansion)
|
|
168
|
+
* @param operation Operation type (e.g., "tool", "task", "persona", "mood")
|
|
169
|
+
* @param data Key-value pairs to pass as environment variables
|
|
170
|
+
* @param timeoutMs Timeout in milliseconds (default 30000)
|
|
171
|
+
* @param mandatory If true, timeout rejects instead of auto-approving
|
|
172
|
+
* @returns Promise<HookResult>
|
|
173
|
+
*/
|
|
174
|
+
export async function executeOperationHook(hookPath, operation, data, timeoutMs = 30000, mandatory = false, contextCurrent, contextMax) {
|
|
175
|
+
// Expand ~ to home directory
|
|
176
|
+
const expandedPath = hookPath.startsWith("~/")
|
|
177
|
+
? path.join(os.homedir(), hookPath.slice(2))
|
|
178
|
+
: hookPath;
|
|
179
|
+
// Build environment using ZDS_AI_AGENT_* naming convention
|
|
180
|
+
// Note: These variables are only set in the child process and are automatically
|
|
181
|
+
// cleaned up when the child process exits. They do NOT modify the parent process environment.
|
|
182
|
+
const env = {
|
|
183
|
+
...process.env,
|
|
184
|
+
[`${ENV_PREFIX}OPERATION`]: operation,
|
|
185
|
+
};
|
|
186
|
+
// Add context information if provided
|
|
187
|
+
if (contextCurrent !== undefined) {
|
|
188
|
+
env[`${ENV_PREFIX}CONTEXT_CURRENT`] = contextCurrent.toString();
|
|
189
|
+
}
|
|
190
|
+
if (contextMax !== undefined) {
|
|
191
|
+
env[`${ENV_PREFIX}CONTEXT_MAX`] = contextMax.toString();
|
|
192
|
+
}
|
|
193
|
+
// Add each data field as ZDS_AI_AGENT_PARAM_<KEY>=<VALUE>
|
|
194
|
+
for (const [key, value] of Object.entries(data)) {
|
|
195
|
+
const envKey = `${ENV_PREFIX}PARAM_${key.toUpperCase()}`;
|
|
196
|
+
env[envKey] = typeof value === 'string' ? value : JSON.stringify(value);
|
|
197
|
+
}
|
|
198
|
+
return new Promise((resolve) => {
|
|
199
|
+
// Execute hook with isolated environment (child process only)
|
|
200
|
+
const child = exec(expandedPath, { env, timeout: timeoutMs }, (error, stdout, stderr) => {
|
|
201
|
+
if (error) {
|
|
202
|
+
// Check if it was a timeout
|
|
203
|
+
if (error.killed && error.signal === "SIGTERM") {
|
|
204
|
+
// Timeout behavior depends on whether hook is mandatory
|
|
205
|
+
if (mandatory) {
|
|
206
|
+
// Mandatory hook timeout = reject
|
|
207
|
+
resolve({
|
|
208
|
+
approved: false,
|
|
209
|
+
reason: "Hook timed out and is mandatory",
|
|
210
|
+
timedOut: true,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// Non-mandatory hook timeout = auto-approve (don't block the agent)
|
|
215
|
+
resolve({
|
|
216
|
+
approved: true,
|
|
217
|
+
timedOut: true,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
// Non-zero exit code = rejected
|
|
223
|
+
if (error.code && error.code > 0) {
|
|
224
|
+
// Parse commands even on rejection
|
|
225
|
+
const commands = parseHookOutput(stdout);
|
|
226
|
+
// Extract TOOL_RESULT commands as the denial reason
|
|
227
|
+
const toolResultLines = [];
|
|
228
|
+
for (const cmd of commands) {
|
|
229
|
+
if (cmd.type === "TOOL_RESULT") {
|
|
230
|
+
toolResultLines.push(cmd.value);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const reason = toolResultLines.length > 0
|
|
234
|
+
? toolResultLines.join("\n")
|
|
235
|
+
: (stdout.trim() || stderr.trim() || "Operation denied by hook");
|
|
236
|
+
resolve({
|
|
237
|
+
approved: false,
|
|
238
|
+
reason,
|
|
239
|
+
timedOut: false,
|
|
240
|
+
commands,
|
|
241
|
+
});
|
|
242
|
+
return;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
// Exit code 0 = approved
|
|
246
|
+
const commands = parseHookOutput(stdout);
|
|
247
|
+
resolve({
|
|
248
|
+
approved: true,
|
|
249
|
+
timedOut: false,
|
|
250
|
+
commands,
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
// Handle timeout explicitly
|
|
254
|
+
setTimeout(() => {
|
|
255
|
+
try {
|
|
256
|
+
child.kill("SIGTERM");
|
|
257
|
+
}
|
|
258
|
+
catch (e) {
|
|
259
|
+
// Process may have already exited
|
|
260
|
+
}
|
|
261
|
+
}, timeoutMs);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Execute a tool approval hook with tool name and parameters passed via environment
|
|
266
|
+
* @param hookPath Path to hook script (supports ~/ expansion)
|
|
267
|
+
* @param toolName Name of the tool being executed
|
|
268
|
+
* @param parameters Tool parameters as key-value pairs
|
|
269
|
+
* @param timeoutMs Timeout in milliseconds (default 30000)
|
|
270
|
+
* @returns Promise<HookResult>
|
|
271
|
+
*/
|
|
272
|
+
export async function executeToolApprovalHook(hookPath, toolName, parameters, timeoutMs = 30000, contextCurrent, contextMax) {
|
|
273
|
+
// Expand ~ to home directory
|
|
274
|
+
const expandedPath = hookPath.startsWith("~/")
|
|
275
|
+
? path.join(os.homedir(), hookPath.slice(2))
|
|
276
|
+
: hookPath;
|
|
277
|
+
// Build environment with tool info using ZDS_AI_AGENT_* naming convention
|
|
278
|
+
// Note: These variables are only set in the child process and are automatically
|
|
279
|
+
// cleaned up when the child process exits. They do NOT modify the parent process environment.
|
|
280
|
+
const env = {
|
|
281
|
+
...process.env,
|
|
282
|
+
[`${ENV_PREFIX}TOOL_NAME`]: toolName,
|
|
283
|
+
};
|
|
284
|
+
// Add context information if provided
|
|
285
|
+
if (contextCurrent !== undefined) {
|
|
286
|
+
env[`${ENV_PREFIX}CONTEXT_CURRENT`] = contextCurrent.toString();
|
|
287
|
+
}
|
|
288
|
+
if (contextMax !== undefined) {
|
|
289
|
+
env[`${ENV_PREFIX}CONTEXT_MAX`] = contextMax.toString();
|
|
290
|
+
}
|
|
291
|
+
// Add each parameter as ZDS_AI_AGENT_PARAM_<KEY>=<VALUE>
|
|
292
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
293
|
+
const envKey = `${ENV_PREFIX}PARAM_${key.toUpperCase()}`;
|
|
294
|
+
env[envKey] = typeof value === 'string' ? value : JSON.stringify(value);
|
|
295
|
+
}
|
|
296
|
+
return new Promise((resolve) => {
|
|
297
|
+
// Execute hook with isolated environment (child process only)
|
|
298
|
+
const child = exec(expandedPath, { env, timeout: timeoutMs }, (error, stdout, stderr) => {
|
|
299
|
+
if (error) {
|
|
300
|
+
// Check if it was a timeout
|
|
301
|
+
if (error.killed && error.signal === "SIGTERM") {
|
|
302
|
+
// Timeout = auto-approve (don't block the agent)
|
|
303
|
+
resolve({
|
|
304
|
+
approved: true,
|
|
305
|
+
timedOut: true,
|
|
306
|
+
});
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
// Non-zero exit code = rejected
|
|
310
|
+
if (error.code && error.code > 0) {
|
|
311
|
+
// Parse commands even on rejection
|
|
312
|
+
const commands = parseHookOutput(stdout);
|
|
313
|
+
// Extract TOOL_RESULT commands as the denial reason
|
|
314
|
+
const toolResultLines = [];
|
|
315
|
+
for (const cmd of commands) {
|
|
316
|
+
if (cmd.type === "TOOL_RESULT") {
|
|
317
|
+
toolResultLines.push(cmd.value);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const reason = toolResultLines.length > 0
|
|
321
|
+
? toolResultLines.join("\n")
|
|
322
|
+
: (stdout.trim() || stderr.trim() || "Tool execution denied by hook");
|
|
323
|
+
resolve({
|
|
324
|
+
approved: false,
|
|
325
|
+
reason,
|
|
326
|
+
timedOut: false,
|
|
327
|
+
commands,
|
|
328
|
+
});
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// Exit code 0 = approved
|
|
333
|
+
const commands = parseHookOutput(stdout);
|
|
334
|
+
resolve({
|
|
335
|
+
approved: true,
|
|
336
|
+
timedOut: false,
|
|
337
|
+
commands,
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
// Handle timeout explicitly
|
|
341
|
+
setTimeout(() => {
|
|
342
|
+
try {
|
|
343
|
+
child.kill("SIGTERM");
|
|
344
|
+
}
|
|
345
|
+
catch (e) {
|
|
346
|
+
// Process may have already exited
|
|
347
|
+
}
|
|
348
|
+
}, timeoutMs);
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=hook-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-executor.js","sourceRoot":"","sources":["../../src/utils/hook-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { UserSettings, ProjectSettings } from './settings-manager.js';
|
|
2
|
+
export interface ModelOption {
|
|
3
|
+
model: string;
|
|
4
|
+
}
|
|
5
|
+
export type ModelConfig = string;
|
|
6
|
+
export { UserSettings, ProjectSettings };
|
|
7
|
+
/**
|
|
8
|
+
* Get the effective current model
|
|
9
|
+
* Priority: project current model > user default model > system default
|
|
10
|
+
*/
|
|
11
|
+
export declare function getCurrentModel(): string;
|
|
12
|
+
/**
|
|
13
|
+
* Load model configuration
|
|
14
|
+
* Priority: user-settings.json models > default hardcoded
|
|
15
|
+
*/
|
|
16
|
+
export declare function loadModelConfig(): ModelOption[];
|
|
17
|
+
/**
|
|
18
|
+
* Get default models list
|
|
19
|
+
*/
|
|
20
|
+
export declare function getDefaultModels(): string[];
|
|
21
|
+
/**
|
|
22
|
+
* Update the current model in project settings
|
|
23
|
+
*/
|
|
24
|
+
export declare function updateCurrentModel(modelName: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Update the user's default model preference
|
|
27
|
+
*/
|
|
28
|
+
export declare function updateDefaultModel(modelName: string): void;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getSettingsManager } from './settings-manager.js';
|
|
2
|
+
/**
|
|
3
|
+
* Get the effective current model
|
|
4
|
+
* Priority: project current model > user default model > system default
|
|
5
|
+
*/
|
|
6
|
+
export function getCurrentModel() {
|
|
7
|
+
const manager = getSettingsManager();
|
|
8
|
+
return manager.getCurrentModel();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Load model configuration
|
|
12
|
+
* Priority: user-settings.json models > default hardcoded
|
|
13
|
+
*/
|
|
14
|
+
export function loadModelConfig() {
|
|
15
|
+
const manager = getSettingsManager();
|
|
16
|
+
const models = manager.getAvailableModels();
|
|
17
|
+
return models.map(model => ({
|
|
18
|
+
model: model.trim()
|
|
19
|
+
}));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get default models list
|
|
23
|
+
*/
|
|
24
|
+
export function getDefaultModels() {
|
|
25
|
+
const manager = getSettingsManager();
|
|
26
|
+
return manager.getAvailableModels();
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Update the current model in project settings
|
|
30
|
+
*/
|
|
31
|
+
export function updateCurrentModel(modelName) {
|
|
32
|
+
const manager = getSettingsManager();
|
|
33
|
+
manager.setCurrentModel(modelName);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Update the user's default model preference
|
|
37
|
+
*/
|
|
38
|
+
export function updateDefaultModel(modelName) {
|
|
39
|
+
const manager = getSettingsManager();
|
|
40
|
+
manager.updateUserSetting('defaultModel', modelName);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=model-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-config.js","sourceRoot":"","sources":["../../src/utils/model-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAiC,MAAM,uBAAuB,CAAC;AAW1F;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,OAAO,OAAO,CAAC,eAAe,EAAE,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,MAAM,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAE5C,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC1B,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE;KACpB,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,OAAO,OAAO,CAAC,kBAAkB,EAAE,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,OAAO,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiB;IAClD,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,OAAO,CAAC,iBAAiB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;AACvD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as os from 'os';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Expands ~ in file paths to the user's home directory
|
|
5
|
+
*/
|
|
6
|
+
export function expandHomeDir(filePath) {
|
|
7
|
+
if (filePath.startsWith('~')) {
|
|
8
|
+
return path.join(os.homedir(), filePath.slice(1));
|
|
9
|
+
}
|
|
10
|
+
return filePath;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=path-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-utils.js","sourceRoot":"","sources":["../../src/utils/path-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,IAAI,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User-level settings stored in ~/.grok/user-settings.json
|
|
3
|
+
* These are global settings that apply across all projects
|
|
4
|
+
*/
|
|
5
|
+
export interface UserSettings {
|
|
6
|
+
apiKey?: string;
|
|
7
|
+
baseURL?: string;
|
|
8
|
+
defaultModel?: string;
|
|
9
|
+
models?: string[];
|
|
10
|
+
temperature?: number;
|
|
11
|
+
maxTokens?: number;
|
|
12
|
+
startupHook?: string;
|
|
13
|
+
instanceHook?: string;
|
|
14
|
+
taskApprovalHook?: string;
|
|
15
|
+
toolApprovalHook?: string;
|
|
16
|
+
personaHook?: string;
|
|
17
|
+
personaHookMandatory?: boolean;
|
|
18
|
+
moodHook?: string;
|
|
19
|
+
moodHookMandatory?: boolean;
|
|
20
|
+
contextViewHelper?: string;
|
|
21
|
+
contextViewHelperGui?: string;
|
|
22
|
+
contextEditHelper?: string;
|
|
23
|
+
contextEditHelperGui?: string;
|
|
24
|
+
mcpServers?: Record<string, any>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Project-level settings stored in .grok/settings.json
|
|
28
|
+
* These are project-specific settings
|
|
29
|
+
*/
|
|
30
|
+
export interface ProjectSettings {
|
|
31
|
+
model?: string;
|
|
32
|
+
mcpServers?: Record<string, any>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Unified settings manager that handles both user-level and project-level settings
|
|
36
|
+
*/
|
|
37
|
+
export declare class SettingsManager {
|
|
38
|
+
private static instance;
|
|
39
|
+
private userSettingsPath;
|
|
40
|
+
private projectSettingsPath;
|
|
41
|
+
private constructor();
|
|
42
|
+
/**
|
|
43
|
+
* Get singleton instance
|
|
44
|
+
*/
|
|
45
|
+
static getInstance(): SettingsManager;
|
|
46
|
+
/**
|
|
47
|
+
* Ensure directory exists for a given file path
|
|
48
|
+
*/
|
|
49
|
+
private ensureDirectoryExists;
|
|
50
|
+
/**
|
|
51
|
+
* Load user settings from ~/.grok/user-settings.json
|
|
52
|
+
*/
|
|
53
|
+
loadUserSettings(): UserSettings;
|
|
54
|
+
/**
|
|
55
|
+
* Save user settings to ~/.grok/user-settings.json
|
|
56
|
+
*/
|
|
57
|
+
saveUserSettings(settings: Partial<UserSettings>): void;
|
|
58
|
+
/**
|
|
59
|
+
* Update a specific user setting
|
|
60
|
+
*/
|
|
61
|
+
updateUserSetting<K extends keyof UserSettings>(key: K, value: UserSettings[K]): void;
|
|
62
|
+
/**
|
|
63
|
+
* Get a specific user setting
|
|
64
|
+
*/
|
|
65
|
+
getUserSetting<K extends keyof UserSettings>(key: K): UserSettings[K];
|
|
66
|
+
/**
|
|
67
|
+
* Load project settings from .grok/settings.json
|
|
68
|
+
*/
|
|
69
|
+
loadProjectSettings(): ProjectSettings;
|
|
70
|
+
/**
|
|
71
|
+
* Save project settings to .grok/settings.json
|
|
72
|
+
* Note: This is a no-op - project settings are not used in ZDS agent workflow
|
|
73
|
+
*/
|
|
74
|
+
saveProjectSettings(settings: Partial<ProjectSettings>): void;
|
|
75
|
+
/**
|
|
76
|
+
* Update a specific project setting
|
|
77
|
+
*/
|
|
78
|
+
updateProjectSetting<K extends keyof ProjectSettings>(key: K, value: ProjectSettings[K]): void;
|
|
79
|
+
/**
|
|
80
|
+
* Get a specific project setting
|
|
81
|
+
*/
|
|
82
|
+
getProjectSetting<K extends keyof ProjectSettings>(key: K): ProjectSettings[K];
|
|
83
|
+
/**
|
|
84
|
+
* Get the current model with proper fallback logic:
|
|
85
|
+
* 1. Project-specific model setting
|
|
86
|
+
* 2. User's default model
|
|
87
|
+
* 3. System default
|
|
88
|
+
*/
|
|
89
|
+
getCurrentModel(): string;
|
|
90
|
+
/**
|
|
91
|
+
* Set the current model for the project
|
|
92
|
+
*/
|
|
93
|
+
setCurrentModel(model: string): void;
|
|
94
|
+
/**
|
|
95
|
+
* Get available models list from user settings
|
|
96
|
+
*/
|
|
97
|
+
getAvailableModels(): string[];
|
|
98
|
+
/**
|
|
99
|
+
* Get API key from user settings or environment
|
|
100
|
+
*/
|
|
101
|
+
getApiKey(): string | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* Get startup hook command from user settings
|
|
104
|
+
*/
|
|
105
|
+
getStartupHook(): string | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Get instance hook command from user settings
|
|
108
|
+
*/
|
|
109
|
+
getInstanceHook(): string | undefined;
|
|
110
|
+
/**
|
|
111
|
+
* Get task approval hook command from user settings
|
|
112
|
+
* Used for validating all task operations (start/transition/stop)
|
|
113
|
+
*/
|
|
114
|
+
getTaskApprovalHook(): string | undefined;
|
|
115
|
+
/**
|
|
116
|
+
* Get tool approval hook command from user settings
|
|
117
|
+
*/
|
|
118
|
+
getToolApprovalHook(): string | undefined;
|
|
119
|
+
/**
|
|
120
|
+
* Get persona hook command from user settings
|
|
121
|
+
*/
|
|
122
|
+
getPersonaHook(): string | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* Check if persona hook is mandatory
|
|
125
|
+
*/
|
|
126
|
+
isPersonaHookMandatory(): boolean;
|
|
127
|
+
/**
|
|
128
|
+
* Get mood hook command from user settings
|
|
129
|
+
*/
|
|
130
|
+
getMoodHook(): string | undefined;
|
|
131
|
+
/**
|
|
132
|
+
* Check if mood hook is mandatory
|
|
133
|
+
*/
|
|
134
|
+
isMoodHookMandatory(): boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Detect if we're running in a GUI environment or text-only (SSH/terminal)
|
|
137
|
+
* Returns true if GUI is available, false for text-only
|
|
138
|
+
*/
|
|
139
|
+
isGuiAvailable(): boolean;
|
|
140
|
+
/**
|
|
141
|
+
* Get context view helper command from user settings
|
|
142
|
+
* Auto-detects GUI vs text-only environment
|
|
143
|
+
*/
|
|
144
|
+
getContextViewHelper(): string;
|
|
145
|
+
/**
|
|
146
|
+
* Get context edit helper command from user settings
|
|
147
|
+
* Auto-detects GUI vs text-only environment
|
|
148
|
+
*/
|
|
149
|
+
getContextEditHelper(): string;
|
|
150
|
+
/**
|
|
151
|
+
* Get base URL from user settings or environment
|
|
152
|
+
*/
|
|
153
|
+
getBaseURL(): string;
|
|
154
|
+
/**
|
|
155
|
+
* Get temperature from user settings
|
|
156
|
+
* Defaults to 0.7 if not set
|
|
157
|
+
*/
|
|
158
|
+
getTemperature(): number;
|
|
159
|
+
/**
|
|
160
|
+
* Get max tokens from user settings or environment
|
|
161
|
+
* Priority: user settings > ZDS_AI_AGENT_MAX_TOKENS env var > undefined
|
|
162
|
+
* Returns undefined if not set (allows API to use its default)
|
|
163
|
+
*/
|
|
164
|
+
getMaxTokens(): number | undefined;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Convenience function to get the singleton instance
|
|
168
|
+
*/
|
|
169
|
+
export declare function getSettingsManager(): SettingsManager;
|