@crewx/cli 0.8.0 → 0.8.1-rc.1
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/bin/crewx +2 -2
- package/dist/commands/agent.js +23 -23
- package/dist/commands/init.js +19 -19
- package/dist/commands/task-db.js +7 -7
- package/dist/main.js +59 -59
- package/package.json +5 -5
- package/dist/examples/deny-secrets-plugin.d.ts +0 -22
- package/dist/examples/deny-secrets-plugin.js +0 -40
- package/dist/plugins/examples/echo-hook.d.ts +0 -24
- package/dist/plugins/examples/echo-hook.js +0 -60
- package/dist/plugins/examples/verify-echo-hook.d.ts +0 -8
- package/dist/plugins/examples/verify-echo-hook.js +0 -47
- package/dist/plugins/sqlite-tracing.d.ts +0 -13
- package/dist/plugins/sqlite-tracing.js +0 -20
package/bin/crewx
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
require('../dist/main.js');
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
require('../dist/main.js');
|
package/dist/commands/agent.js
CHANGED
|
@@ -219,28 +219,28 @@ function loadAgentSkills() {
|
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
function printAgentHelp() {
|
|
222
|
-
console.log(`
|
|
223
|
-
CrewX Agent Management
|
|
224
|
-
|
|
225
|
-
Usage:
|
|
226
|
-
crewx agent # List configured agents (default)
|
|
227
|
-
crewx agent ls # List configured agents
|
|
228
|
-
crewx agent list # Alias for ls
|
|
229
|
-
crewx agent prompt <id> # Inspect rendered agent prompt
|
|
230
|
-
|
|
231
|
-
Filter Options (for agent ls):
|
|
232
|
-
--role <value> Filter by agent role (comma-separated for multiple: PM,Dev)
|
|
233
|
-
--team <value> Filter by agent team (comma-separated for multiple)
|
|
234
|
-
--provider <value> Filter by provider (comma-separated, partial match: claude)
|
|
235
|
-
|
|
236
|
-
Examples:
|
|
237
|
-
crewx agent
|
|
238
|
-
crewx agent ls
|
|
239
|
-
crewx agent ls --role=PM
|
|
240
|
-
crewx agent ls --team="CrewX Core 개발팀"
|
|
241
|
-
crewx agent ls --provider=claude
|
|
242
|
-
crewx agent ls --role=PM --provider=claude
|
|
243
|
-
crewx agent ls --role=PM,general
|
|
244
|
-
CREWX_CONFIG=./crewx.yaml crewx agent list
|
|
222
|
+
console.log(`
|
|
223
|
+
CrewX Agent Management
|
|
224
|
+
|
|
225
|
+
Usage:
|
|
226
|
+
crewx agent # List configured agents (default)
|
|
227
|
+
crewx agent ls # List configured agents
|
|
228
|
+
crewx agent list # Alias for ls
|
|
229
|
+
crewx agent prompt <id> # Inspect rendered agent prompt
|
|
230
|
+
|
|
231
|
+
Filter Options (for agent ls):
|
|
232
|
+
--role <value> Filter by agent role (comma-separated for multiple: PM,Dev)
|
|
233
|
+
--team <value> Filter by agent team (comma-separated for multiple)
|
|
234
|
+
--provider <value> Filter by provider (comma-separated, partial match: claude)
|
|
235
|
+
|
|
236
|
+
Examples:
|
|
237
|
+
crewx agent
|
|
238
|
+
crewx agent ls
|
|
239
|
+
crewx agent ls --role=PM
|
|
240
|
+
crewx agent ls --team="CrewX Core 개발팀"
|
|
241
|
+
crewx agent ls --provider=claude
|
|
242
|
+
crewx agent ls --role=PM --provider=claude
|
|
243
|
+
crewx agent ls --role=PM,general
|
|
244
|
+
CREWX_CONFIG=./crewx.yaml crewx agent list
|
|
245
245
|
`.trim());
|
|
246
246
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -56,27 +56,27 @@ function escapeYamlBlock(text) {
|
|
|
56
56
|
}
|
|
57
57
|
function generateDefaultYaml(agents) {
|
|
58
58
|
const agentBlocks = agents
|
|
59
|
-
.map((a) => ` - id: "${a.id}"
|
|
60
|
-
name: "${a.name}"
|
|
61
|
-
role: "${a.role}"
|
|
62
|
-
team: "${a.team}"
|
|
63
|
-
provider: "${a.provider}"
|
|
64
|
-
default_model: "${a.default_model}"
|
|
65
|
-
working_directory: "${a.working_directory}"
|
|
66
|
-
description: "${a.description}"
|
|
67
|
-
system_prompt: |
|
|
59
|
+
.map((a) => ` - id: "${a.id}"
|
|
60
|
+
name: "${a.name}"
|
|
61
|
+
role: "${a.role}"
|
|
62
|
+
team: "${a.team}"
|
|
63
|
+
provider: "${a.provider}"
|
|
64
|
+
default_model: "${a.default_model}"
|
|
65
|
+
working_directory: "${a.working_directory}"
|
|
66
|
+
description: "${a.description}"
|
|
67
|
+
system_prompt: |
|
|
68
68
|
${escapeYamlBlock(a.system_prompt)}`)
|
|
69
69
|
.join('\n\n');
|
|
70
|
-
return `# CrewX Agents Configuration
|
|
71
|
-
# Generated by 'crewx init'
|
|
72
|
-
|
|
73
|
-
agents:
|
|
74
|
-
${agentBlocks}
|
|
75
|
-
|
|
76
|
-
# Usage examples:
|
|
77
|
-
# crewx query "@planner analyze this codebase"
|
|
78
|
-
# crewx execute "@developer implement the feature described above"
|
|
79
|
-
# crewx agent ls
|
|
70
|
+
return `# CrewX Agents Configuration
|
|
71
|
+
# Generated by 'crewx init'
|
|
72
|
+
|
|
73
|
+
agents:
|
|
74
|
+
${agentBlocks}
|
|
75
|
+
|
|
76
|
+
# Usage examples:
|
|
77
|
+
# crewx query "@planner analyze this codebase"
|
|
78
|
+
# crewx execute "@developer implement the feature described above"
|
|
79
|
+
# crewx agent ls
|
|
80
80
|
`;
|
|
81
81
|
}
|
|
82
82
|
/**
|
package/dist/commands/task-db.js
CHANGED
|
@@ -33,8 +33,8 @@ function getRunningTasks(dbRoot) {
|
|
|
33
33
|
if (!db)
|
|
34
34
|
return [];
|
|
35
35
|
try {
|
|
36
|
-
return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
|
|
37
|
-
result, error, duration_ms
|
|
36
|
+
return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
|
|
37
|
+
result, error, duration_ms
|
|
38
38
|
FROM tasks WHERE status = 'running' ORDER BY started_at DESC`).all();
|
|
39
39
|
}
|
|
40
40
|
finally {
|
|
@@ -47,8 +47,8 @@ function getAllTasks(dbRoot) {
|
|
|
47
47
|
if (!db)
|
|
48
48
|
return [];
|
|
49
49
|
try {
|
|
50
|
-
return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
|
|
51
|
-
result, error, duration_ms
|
|
50
|
+
return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
|
|
51
|
+
result, error, duration_ms
|
|
52
52
|
FROM tasks ORDER BY started_at DESC`).all();
|
|
53
53
|
}
|
|
54
54
|
finally {
|
|
@@ -61,8 +61,8 @@ function getTask(id, dbRoot) {
|
|
|
61
61
|
if (!db)
|
|
62
62
|
return undefined;
|
|
63
63
|
try {
|
|
64
|
-
return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
|
|
65
|
-
result, error, duration_ms
|
|
64
|
+
return db.prepare(`SELECT id, agent_id, prompt, mode, status, pid, started_at, completed_at,
|
|
65
|
+
result, error, duration_ms
|
|
66
66
|
FROM tasks WHERE id = ?`).get(id);
|
|
67
67
|
}
|
|
68
68
|
finally {
|
|
@@ -97,7 +97,7 @@ function killTask(id, dbRoot) {
|
|
|
97
97
|
// ESRCH = process already gone — still clean up the record
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
-
db.prepare(`UPDATE tasks SET status='failed', error='killed by user',
|
|
100
|
+
db.prepare(`UPDATE tasks SET status='failed', error='killed by user',
|
|
101
101
|
completed_at=?, pid=NULL WHERE id=?`).run(new Date().toISOString(), id);
|
|
102
102
|
return { ok: true, message: `Killed task ${id}${task.pid ? ` (PID: ${task.pid})` : ''}` };
|
|
103
103
|
}
|
package/dist/main.js
CHANGED
|
@@ -234,65 +234,65 @@ async function runSkill(skillArgs) {
|
|
|
234
234
|
});
|
|
235
235
|
}
|
|
236
236
|
function printHelp() {
|
|
237
|
-
console.log(`
|
|
238
|
-
CrewX CLI v${version_1.CLI_VERSION}
|
|
239
|
-
|
|
240
|
-
Usage:
|
|
241
|
-
crewx <command> [options]
|
|
242
|
-
|
|
243
|
-
Query / Execute:
|
|
244
|
-
q|query [@agent] <message> Query an agent (read-only)
|
|
245
|
-
x|execute [@agent] <task> Execute a task with an agent (write-capable)
|
|
246
|
-
|
|
247
|
-
@agent is optional — defaults to @crewx when omitted.
|
|
248
|
-
|
|
249
|
-
Common flags:
|
|
250
|
-
--thread <name> Conversation thread
|
|
251
|
-
--provider <cli/xxx> Provider override
|
|
252
|
-
--metadata <json> Extra metadata (JSON object, double-quoted). Propagated to events/hooks/tracing.
|
|
253
|
-
Invalid JSON aborts with exit code 2.
|
|
254
|
-
e.g. --metadata='{"workflow_id":"wf-1"}'
|
|
255
|
-
--verbose Debug output mode (default: raw response only)
|
|
256
|
-
--config/-c <path> Config file path (default: CREWX_CONFIG or crewx.yaml)
|
|
257
|
-
--output-format <fmt> Output format (json|text|stream-json)
|
|
258
|
-
--effort <level> Model effort (high|medium|low)
|
|
259
|
-
|
|
260
|
-
Agent Management:
|
|
261
|
-
agent ls [options] List configured agents
|
|
262
|
-
--role <value> Filter by role (comma-separated for OR match)
|
|
263
|
-
--team <value> Filter by team (comma-separated for OR match)
|
|
264
|
-
--provider <value> Filter by provider (comma-separated for OR match)
|
|
265
|
-
agent prompt <@id> Show rendered system prompt for an agent
|
|
266
|
-
|
|
267
|
-
Task Management:
|
|
268
|
-
ps List running tasks
|
|
269
|
-
kill <task-id> Kill a running task
|
|
270
|
-
kill --all Kill all running tasks
|
|
271
|
-
result [task-id] Get task result (or list recent tasks)
|
|
272
|
-
|
|
273
|
-
Logs & Diagnostics:
|
|
274
|
-
log [ls|<task-id>] View task logs
|
|
275
|
-
doctor [--config <path>] Run system diagnosis
|
|
276
|
-
init [--force] [--config <p>] Initialize crewx.yaml
|
|
277
|
-
|
|
278
|
-
Built-in Tools:
|
|
279
|
-
memory <args> Memory tool
|
|
280
|
-
search <args> Search tool
|
|
281
|
-
doc <args> Doc tool
|
|
282
|
-
wbs <args> WBS tool
|
|
283
|
-
cron <args> Cron tool
|
|
284
|
-
workflow <args> Workflow tool
|
|
285
|
-
skill <args> Skill tool
|
|
286
|
-
|
|
287
|
-
Hook Platform:
|
|
288
|
-
hook install [--yes] Install PreToolUse hook in .claude/settings.json
|
|
289
|
-
hook uninstall Remove crewx hook from .claude/settings.json
|
|
290
|
-
hook status Show hook installation status and plugins
|
|
291
|
-
hook-dispatch Internal: IPC router called by Claude (stdin→stdout)
|
|
292
|
-
|
|
293
|
-
Global Options:
|
|
294
|
-
--help, -h Show this help
|
|
295
|
-
--version, -v Show version
|
|
237
|
+
console.log(`
|
|
238
|
+
CrewX CLI v${version_1.CLI_VERSION}
|
|
239
|
+
|
|
240
|
+
Usage:
|
|
241
|
+
crewx <command> [options]
|
|
242
|
+
|
|
243
|
+
Query / Execute:
|
|
244
|
+
q|query [@agent] <message> Query an agent (read-only)
|
|
245
|
+
x|execute [@agent] <task> Execute a task with an agent (write-capable)
|
|
246
|
+
|
|
247
|
+
@agent is optional — defaults to @crewx when omitted.
|
|
248
|
+
|
|
249
|
+
Common flags:
|
|
250
|
+
--thread <name> Conversation thread
|
|
251
|
+
--provider <cli/xxx> Provider override
|
|
252
|
+
--metadata <json> Extra metadata (JSON object, double-quoted). Propagated to events/hooks/tracing.
|
|
253
|
+
Invalid JSON aborts with exit code 2.
|
|
254
|
+
e.g. --metadata='{"workflow_id":"wf-1"}'
|
|
255
|
+
--verbose Debug output mode (default: raw response only)
|
|
256
|
+
--config/-c <path> Config file path (default: CREWX_CONFIG or crewx.yaml)
|
|
257
|
+
--output-format <fmt> Output format (json|text|stream-json)
|
|
258
|
+
--effort <level> Model effort (high|medium|low)
|
|
259
|
+
|
|
260
|
+
Agent Management:
|
|
261
|
+
agent ls [options] List configured agents
|
|
262
|
+
--role <value> Filter by role (comma-separated for OR match)
|
|
263
|
+
--team <value> Filter by team (comma-separated for OR match)
|
|
264
|
+
--provider <value> Filter by provider (comma-separated for OR match)
|
|
265
|
+
agent prompt <@id> Show rendered system prompt for an agent
|
|
266
|
+
|
|
267
|
+
Task Management:
|
|
268
|
+
ps List running tasks
|
|
269
|
+
kill <task-id> Kill a running task
|
|
270
|
+
kill --all Kill all running tasks
|
|
271
|
+
result [task-id] Get task result (or list recent tasks)
|
|
272
|
+
|
|
273
|
+
Logs & Diagnostics:
|
|
274
|
+
log [ls|<task-id>] View task logs
|
|
275
|
+
doctor [--config <path>] Run system diagnosis
|
|
276
|
+
init [--force] [--config <p>] Initialize crewx.yaml
|
|
277
|
+
|
|
278
|
+
Built-in Tools:
|
|
279
|
+
memory <args> Memory tool
|
|
280
|
+
search <args> Search tool
|
|
281
|
+
doc <args> Doc tool
|
|
282
|
+
wbs <args> WBS tool
|
|
283
|
+
cron <args> Cron tool
|
|
284
|
+
workflow <args> Workflow tool
|
|
285
|
+
skill <args> Skill tool
|
|
286
|
+
|
|
287
|
+
Hook Platform:
|
|
288
|
+
hook install [--yes] Install PreToolUse hook in .claude/settings.json
|
|
289
|
+
hook uninstall Remove crewx hook from .claude/settings.json
|
|
290
|
+
hook status Show hook installation status and plugins
|
|
291
|
+
hook-dispatch Internal: IPC router called by Claude (stdin→stdout)
|
|
292
|
+
|
|
293
|
+
Global Options:
|
|
294
|
+
--help, -h Show this help
|
|
295
|
+
--version, -v Show version
|
|
296
296
|
`.trim());
|
|
297
297
|
}
|
|
298
298
|
main().catch((err) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewx/cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1-rc.1",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=20.19.0"
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@crewx/adapter-slack": "0.1.3",
|
|
29
29
|
"better-sqlite3": "*",
|
|
30
|
-
"@crewx/
|
|
31
|
-
"@crewx/doc": "0.1.7",
|
|
30
|
+
"@crewx/memory": "0.1.9",
|
|
32
31
|
"@crewx/wbs": "0.1.8",
|
|
33
|
-
"@crewx/
|
|
32
|
+
"@crewx/sdk": "0.8.1-rc.1",
|
|
34
33
|
"@crewx/cron": "0.1.7",
|
|
35
|
-
"@crewx/
|
|
34
|
+
"@crewx/doc": "0.1.7",
|
|
35
|
+
"@crewx/search": "0.1.8",
|
|
36
36
|
"@crewx/workflow": "0.3.7",
|
|
37
37
|
"@crewx/skill": "0.1.6",
|
|
38
38
|
"@crewx/shared": "0.0.4"
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DenyIfTouchesSecretsPlugin — Phase 0 demo HookPlugin.
|
|
3
|
-
*
|
|
4
|
-
* Denies Bash tool calls whose command string contains ".env".
|
|
5
|
-
* Pure string matching — trivially bypassable (see README).
|
|
6
|
-
*
|
|
7
|
-
* SECURITY NOTE:
|
|
8
|
-
* Do NOT include tool.input content in deny reasons.
|
|
9
|
-
* Use static messages only to prevent prompt injection.
|
|
10
|
-
* ✅ return ctx.deny('Secrets-related command');
|
|
11
|
-
* ❌ return ctx.deny(`Blocked: ${cmd}`);
|
|
12
|
-
*/
|
|
13
|
-
import { HookPlugin } from '@crewx/sdk/hooks';
|
|
14
|
-
import type { HookContext, HookResult } from '@crewx/sdk/hooks';
|
|
15
|
-
export declare class DenyIfTouchesSecretsPlugin extends HookPlugin {
|
|
16
|
-
readonly name = "deny-secrets";
|
|
17
|
-
readonly version = "0.1.0";
|
|
18
|
-
readonly capabilities: {
|
|
19
|
-
required: readonly ["deny"];
|
|
20
|
-
};
|
|
21
|
-
run(ctx: HookContext): Promise<HookResult>;
|
|
22
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* DenyIfTouchesSecretsPlugin — Phase 0 demo HookPlugin.
|
|
4
|
-
*
|
|
5
|
-
* Denies Bash tool calls whose command string contains ".env".
|
|
6
|
-
* Pure string matching — trivially bypassable (see README).
|
|
7
|
-
*
|
|
8
|
-
* SECURITY NOTE:
|
|
9
|
-
* Do NOT include tool.input content in deny reasons.
|
|
10
|
-
* Use static messages only to prevent prompt injection.
|
|
11
|
-
* ✅ return ctx.deny('Secrets-related command');
|
|
12
|
-
* ❌ return ctx.deny(`Blocked: ${cmd}`);
|
|
13
|
-
*/
|
|
14
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.DenyIfTouchesSecretsPlugin = void 0;
|
|
16
|
-
const hooks_1 = require("@crewx/sdk/hooks");
|
|
17
|
-
const SECRET_PATTERNS = ['.env', 'credentials.json', 'service-account-key.json'];
|
|
18
|
-
const SHELL_TOOL_NAMES = new Set(['Bash', 'shell', 'local_shell']);
|
|
19
|
-
class DenyIfTouchesSecretsPlugin extends hooks_1.HookPlugin {
|
|
20
|
-
name = 'deny-secrets';
|
|
21
|
-
version = '0.1.0';
|
|
22
|
-
capabilities = { required: ['deny'] };
|
|
23
|
-
async run(ctx) {
|
|
24
|
-
if (!SHELL_TOOL_NAMES.has(ctx.tool.rawName) && ctx.tool.name !== 'shell') {
|
|
25
|
-
return ctx.pass();
|
|
26
|
-
}
|
|
27
|
-
const input = ctx.tool.input;
|
|
28
|
-
const command = input?.command;
|
|
29
|
-
if (typeof command !== 'string') {
|
|
30
|
-
return ctx.pass();
|
|
31
|
-
}
|
|
32
|
-
for (const pattern of SECRET_PATTERNS) {
|
|
33
|
-
if (command.includes(pattern)) {
|
|
34
|
-
return ctx.deny('Secrets-related command');
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return ctx.pass();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
exports.DenyIfTouchesSecretsPlugin = DenyIfTouchesSecretsPlugin;
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* EchoObserverPlugin — Tool observer that echoes events to a JSONL log.
|
|
3
|
-
*
|
|
4
|
-
* Observes tool:before / tool:after events from the Crewx event bus
|
|
5
|
-
* and appends them as JSONL to ~/.crewx/logs/echo-hook.log.
|
|
6
|
-
* Pure observer — no flow control (deny/inject/modify not applicable).
|
|
7
|
-
*/
|
|
8
|
-
import { ToolObserverPlugin } from '@crewx/sdk/hooks';
|
|
9
|
-
import type { ObserverContext, ObserverResult } from '@crewx/sdk/hooks';
|
|
10
|
-
export declare class EchoHookPlugin extends ToolObserverPlugin {
|
|
11
|
-
readonly name = "echo-hook";
|
|
12
|
-
readonly version = "0.0.1";
|
|
13
|
-
readonly on: {
|
|
14
|
-
beforeTool: true;
|
|
15
|
-
afterTool: true;
|
|
16
|
-
beforePrompt: true;
|
|
17
|
-
sessionStart: true;
|
|
18
|
-
};
|
|
19
|
-
private readonly logPath;
|
|
20
|
-
constructor(logDir?: string);
|
|
21
|
-
run(ctx: ObserverContext): Promise<ObserverResult>;
|
|
22
|
-
private ensureLogDir;
|
|
23
|
-
private echo;
|
|
24
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* EchoObserverPlugin — Tool observer that echoes events to a JSONL log.
|
|
4
|
-
*
|
|
5
|
-
* Observes tool:before / tool:after events from the Crewx event bus
|
|
6
|
-
* and appends them as JSONL to ~/.crewx/logs/echo-hook.log.
|
|
7
|
-
* Pure observer — no flow control (deny/inject/modify not applicable).
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
exports.EchoHookPlugin = void 0;
|
|
11
|
-
const fs_1 = require("fs");
|
|
12
|
-
const path_1 = require("path");
|
|
13
|
-
const os_1 = require("os");
|
|
14
|
-
const hooks_1 = require("@crewx/sdk/hooks");
|
|
15
|
-
class EchoHookPlugin extends hooks_1.ToolObserverPlugin {
|
|
16
|
-
name = 'echo-hook';
|
|
17
|
-
version = '0.0.1';
|
|
18
|
-
on = {
|
|
19
|
-
beforeTool: true,
|
|
20
|
-
afterTool: true,
|
|
21
|
-
beforePrompt: true,
|
|
22
|
-
sessionStart: true,
|
|
23
|
-
};
|
|
24
|
-
logPath;
|
|
25
|
-
constructor(logDir) {
|
|
26
|
-
super();
|
|
27
|
-
this.logPath = (0, path_1.join)(logDir ?? (0, os_1.homedir)(), '.crewx', 'logs', 'echo-hook.log');
|
|
28
|
-
this.ensureLogDir();
|
|
29
|
-
}
|
|
30
|
-
async run(ctx) {
|
|
31
|
-
this.echo(ctx);
|
|
32
|
-
return ctx.pass();
|
|
33
|
-
}
|
|
34
|
-
ensureLogDir() {
|
|
35
|
-
const dir = (0, path_1.dirname)(this.logPath);
|
|
36
|
-
if (!(0, fs_1.existsSync)(dir)) {
|
|
37
|
-
(0, fs_1.mkdirSync)(dir, { recursive: true, mode: 0o700 });
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
echo(ctx) {
|
|
41
|
-
try {
|
|
42
|
-
const line = JSON.stringify({
|
|
43
|
-
timestamp: new Date().toISOString(),
|
|
44
|
-
event: ctx.event,
|
|
45
|
-
traceId: ctx.traceId,
|
|
46
|
-
agent: ctx.agent,
|
|
47
|
-
provider: ctx.provider,
|
|
48
|
-
thread: ctx.thread,
|
|
49
|
-
tool: ctx.tool,
|
|
50
|
-
cwd: ctx.cwd,
|
|
51
|
-
sessionId: ctx.sessionId,
|
|
52
|
-
});
|
|
53
|
-
(0, fs_1.appendFileSync)(this.logPath, line + '\n', { encoding: 'utf8', mode: 0o600 });
|
|
54
|
-
}
|
|
55
|
-
catch {
|
|
56
|
-
// Non-fatal
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
exports.EchoHookPlugin = EchoHookPlugin;
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env npx tsx
|
|
2
|
-
"use strict";
|
|
3
|
-
/**
|
|
4
|
-
* Phase 0 e2e verification — EchoHookPlugin logs Claude Code tool calls.
|
|
5
|
-
*
|
|
6
|
-
* Run: npx tsx packages/cli/src/plugins/examples/verify-echo-hook.ts
|
|
7
|
-
* Prereq: claude CLI installed, crewx.yaml with @claude agent
|
|
8
|
-
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
const sdk_1 = require("@crewx/sdk");
|
|
11
|
-
const echo_hook_1 = require("./echo-hook");
|
|
12
|
-
const fs_1 = require("fs");
|
|
13
|
-
const path_1 = require("path");
|
|
14
|
-
const os_1 = require("os");
|
|
15
|
-
const LOG_PATH = (0, path_1.join)((0, os_1.homedir)(), '.crewx', 'logs', 'echo-hook.log');
|
|
16
|
-
async function main() {
|
|
17
|
-
if ((0, fs_1.existsSync)(LOG_PATH))
|
|
18
|
-
(0, fs_1.unlinkSync)(LOG_PATH);
|
|
19
|
-
const crewx = await sdk_1.Crewx.loadYaml('crewx.yaml');
|
|
20
|
-
await crewx.use(new echo_hook_1.EchoHookPlugin());
|
|
21
|
-
console.log('[verify] querying @claude with "ls"...');
|
|
22
|
-
await crewx.query('@claude', 'Run ls in the current directory. Use the Bash tool.');
|
|
23
|
-
await crewx.close();
|
|
24
|
-
if (!(0, fs_1.existsSync)(LOG_PATH)) {
|
|
25
|
-
console.error('[FAIL] echo-hook.log not created');
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
const lines = (0, fs_1.readFileSync)(LOG_PATH, 'utf8').trim().split('\n');
|
|
29
|
-
const entries = lines.map((l) => JSON.parse(l));
|
|
30
|
-
const hasBeforeTool = entries.some((e) => e.event === 'beforeTool');
|
|
31
|
-
const hasTraceId = entries.every((e) => e.traceId?.startsWith('tsk_'));
|
|
32
|
-
const hasToolName = entries
|
|
33
|
-
.filter((e) => e.event === 'beforeTool')
|
|
34
|
-
.every((e) => typeof e.tool?.rawName === 'string' && e.tool.rawName.length > 0);
|
|
35
|
-
console.log(`[verify] entries: ${entries.length}`);
|
|
36
|
-
console.log(`[verify] beforeTool: ${hasBeforeTool}`);
|
|
37
|
-
console.log(`[verify] traceId: ${hasTraceId}`);
|
|
38
|
-
console.log(`[verify] toolName: ${hasToolName}`);
|
|
39
|
-
if (hasBeforeTool && hasTraceId && hasToolName) {
|
|
40
|
-
console.log('[PASS] Phase 0 e2e verification passed');
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
console.error('[FAIL] Some checks failed');
|
|
44
|
-
process.exit(1);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
main().catch((err) => { console.error(err); process.exit(1); });
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI convenience wrapper for SqliteTracingPlugin.
|
|
3
|
-
* Accepts a dbRoot string or an options object so existing CLI tests can pass
|
|
4
|
-
* a temp directory path directly.
|
|
5
|
-
*/
|
|
6
|
-
import { SqliteTracingPlugin as SdkPlugin } from '@crewx/sdk/plugins';
|
|
7
|
-
export type { SqliteTracingPluginOptions } from '@crewx/sdk/plugins';
|
|
8
|
-
export declare class SqliteTracingPlugin extends SdkPlugin {
|
|
9
|
-
constructor(dbRootOrOpts?: string | {
|
|
10
|
-
dbRoot?: string;
|
|
11
|
-
version?: string;
|
|
12
|
-
});
|
|
13
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SqliteTracingPlugin = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* CLI convenience wrapper for SqliteTracingPlugin.
|
|
6
|
-
* Accepts a dbRoot string or an options object so existing CLI tests can pass
|
|
7
|
-
* a temp directory path directly.
|
|
8
|
-
*/
|
|
9
|
-
const plugins_1 = require("@crewx/sdk/plugins");
|
|
10
|
-
class SqliteTracingPlugin extends plugins_1.SqliteTracingPlugin {
|
|
11
|
-
constructor(dbRootOrOpts) {
|
|
12
|
-
if (typeof dbRootOrOpts === 'string') {
|
|
13
|
-
super({ dbRoot: dbRootOrOpts });
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
super(dbRootOrOpts);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
exports.SqliteTracingPlugin = SqliteTracingPlugin;
|