@crewx/cli 0.9.0-rc.4 → 0.9.0-rc.41

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.
@@ -0,0 +1,45 @@
1
+ /**
2
+ * CLI-layer policy: inject CrewX home as an extra writable root for Codex
3
+ * `workspace-write` sandbox invocations.
4
+ *
5
+ * Why this lives in packages/cli (not packages/sdk):
6
+ * CrewX home (`~/.crewx` by default) is a product-specific path. The SDK's
7
+ * `additionalArgsProvider` extension point (WI-20260703-001) exists precisely
8
+ * so that product layers like this CLI can inject such paths without the SDK
9
+ * knowing about them.
10
+ *
11
+ * Why `-c sandbox_workspace_write.writable_roots=[...]` instead of `--add-dir`:
12
+ * Verified against codex-cli 0.139.0 (`codex exec --help` / `codex exec resume --help`):
13
+ * - `codex exec` supports `--add-dir <DIR>`.
14
+ * - `codex exec resume` does NOT support `--add-dir` (only `-c/--config`).
15
+ * Using the `-c` config-override form works identically for both `exec` and
16
+ * `exec resume`, avoiding a resume-incompatible flag.
17
+ */
18
+ import type { AdditionalArgsProvider } from '@crewx/sdk';
19
+ /**
20
+ * Resolve CrewX home directory.
21
+ * Priority: `CREWX_HOME` env var → `~/.crewx`.
22
+ */
23
+ export declare function resolveCrewxHome(): string;
24
+ /**
25
+ * Escape a string for embedding inside a TOML basic string (`"..."`).
26
+ * Sufficient for filesystem paths: handles backslash (Windows paths),
27
+ * double-quote, and control characters that could otherwise break TOML
28
+ * parsing of the `-c key="value"` override.
29
+ */
30
+ export declare function escapeTomlBasicString(value: string): string;
31
+ /**
32
+ * Build the `-c sandbox_workspace_write.writable_roots=["<path>"]` arg pair.
33
+ * Works for both `codex exec` and `codex exec resume` (config-override form).
34
+ */
35
+ export declare function buildCodexWritableRootArgs(crewxHome: string): string[];
36
+ /**
37
+ * Create an `AdditionalArgsProvider` (SDK extension point, WI-20260703-001)
38
+ * that injects CrewX home as a Codex writable root for `workspace-write`
39
+ * equivalent modes (`agent`, `auto`, `undefined`).
40
+ *
41
+ * No-ops for:
42
+ * - Non-codex providers.
43
+ * - Modes in {@link NO_INJECT_MODES} (read-only/plan/agent-full-access/yolo/danger-full-access).
44
+ */
45
+ export declare function createCodexWritableRootsProvider(crewxHome?: string): AdditionalArgsProvider;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ /**
3
+ * CLI-layer policy: inject CrewX home as an extra writable root for Codex
4
+ * `workspace-write` sandbox invocations.
5
+ *
6
+ * Why this lives in packages/cli (not packages/sdk):
7
+ * CrewX home (`~/.crewx` by default) is a product-specific path. The SDK's
8
+ * `additionalArgsProvider` extension point (WI-20260703-001) exists precisely
9
+ * so that product layers like this CLI can inject such paths without the SDK
10
+ * knowing about them.
11
+ *
12
+ * Why `-c sandbox_workspace_write.writable_roots=[...]` instead of `--add-dir`:
13
+ * Verified against codex-cli 0.139.0 (`codex exec --help` / `codex exec resume --help`):
14
+ * - `codex exec` supports `--add-dir <DIR>`.
15
+ * - `codex exec resume` does NOT support `--add-dir` (only `-c/--config`).
16
+ * Using the `-c` config-override form works identically for both `exec` and
17
+ * `exec resume`, avoiding a resume-incompatible flag.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.resolveCrewxHome = resolveCrewxHome;
21
+ exports.escapeTomlBasicString = escapeTomlBasicString;
22
+ exports.buildCodexWritableRootArgs = buildCodexWritableRootArgs;
23
+ exports.createCodexWritableRootsProvider = createCodexWritableRootsProvider;
24
+ const os_1 = require("os");
25
+ const path_1 = require("path");
26
+ /**
27
+ * crewx.yaml / query-option `mode` values for which Codex is NOT running in
28
+ * (or being pushed into) a `workspace-write`-equivalent sandbox. Injecting an
29
+ * extra writable root is meaningless (read-only/plan) or redundant
30
+ * (full-access variants already allow writes everywhere) in these modes.
31
+ */
32
+ const NO_INJECT_MODES = new Set([
33
+ 'read-only',
34
+ 'plan',
35
+ 'agent-full-access',
36
+ 'yolo',
37
+ 'danger-full-access',
38
+ ]);
39
+ /**
40
+ * Resolve CrewX home directory.
41
+ * Priority: `CREWX_HOME` env var → `~/.crewx`.
42
+ */
43
+ function resolveCrewxHome() {
44
+ return process.env.CREWX_HOME ?? (0, path_1.join)((0, os_1.homedir)(), '.crewx');
45
+ }
46
+ /**
47
+ * Escape a string for embedding inside a TOML basic string (`"..."`).
48
+ * Sufficient for filesystem paths: handles backslash (Windows paths),
49
+ * double-quote, and control characters that could otherwise break TOML
50
+ * parsing of the `-c key="value"` override.
51
+ */
52
+ function escapeTomlBasicString(value) {
53
+ return value
54
+ .replace(/\\/g, '\\\\')
55
+ .replace(/"/g, '\\"')
56
+ .replace(/\n/g, '\\n')
57
+ .replace(/\r/g, '\\r')
58
+ .replace(/\t/g, '\\t');
59
+ }
60
+ /**
61
+ * Build the `-c sandbox_workspace_write.writable_roots=["<path>"]` arg pair.
62
+ * Works for both `codex exec` and `codex exec resume` (config-override form).
63
+ */
64
+ function buildCodexWritableRootArgs(crewxHome) {
65
+ const escaped = escapeTomlBasicString(crewxHome);
66
+ return ['-c', `sandbox_workspace_write.writable_roots=["${escaped}"]`];
67
+ }
68
+ function isCodexProvider(ctx) {
69
+ return ctx.providerId === 'codex' || ctx.providerStr === 'cli/codex';
70
+ }
71
+ /**
72
+ * Create an `AdditionalArgsProvider` (SDK extension point, WI-20260703-001)
73
+ * that injects CrewX home as a Codex writable root for `workspace-write`
74
+ * equivalent modes (`agent`, `auto`, `undefined`).
75
+ *
76
+ * No-ops for:
77
+ * - Non-codex providers.
78
+ * - Modes in {@link NO_INJECT_MODES} (read-only/plan/agent-full-access/yolo/danger-full-access).
79
+ */
80
+ function createCodexWritableRootsProvider(crewxHome = resolveCrewxHome()) {
81
+ return (ctx) => {
82
+ if (!isCodexProvider(ctx))
83
+ return [];
84
+ if (ctx.mode !== undefined && NO_INJECT_MODES.has(ctx.mode))
85
+ return [];
86
+ return buildCodexWritableRootArgs(crewxHome);
87
+ };
88
+ }
@@ -9,6 +9,7 @@ const plugins_1 = require("@crewx/sdk/plugins");
9
9
  const repository_1 = require("@crewx/sdk/repository");
10
10
  const register_builtin_tools_1 = require("../register-builtin-tools");
11
11
  const version_1 = require("../utils/version");
12
+ const codex_writable_roots_1 = require("./codex-writable-roots");
12
13
  /**
13
14
  * Build a Crewx instance with CLI-standard plugins (FileLogger + SqliteTracing)
14
15
  * and built-in tools registered. Use this from any CLI command that needs a
@@ -52,6 +53,7 @@ async function createCliCrewx(configPath = process.env.CREWX_CONFIG ?? 'crewx.ya
52
53
  }
53
54
  const crewx = await sdk_1.Crewx.loadYaml(yamlPath, {
54
55
  remoteFactory: createCliCrewx,
56
+ additionalArgsProvider: (0, codex_writable_roots_1.createCodexWritableRootsProvider)(),
55
57
  });
56
58
  (0, register_builtin_tools_1.registerBuiltinToolsIfNeeded)(crewx);
57
59
  await crewx.use(new plugins_1.ConversationPlugin());
package/dist/builtin.js CHANGED
@@ -55,6 +55,7 @@ const BUILTIN_MAP = {
55
55
  dreaming: () => Promise.resolve().then(() => __importStar(require('@crewx/dreaming/cli'))),
56
56
  wi: () => Promise.resolve().then(() => __importStar(require('@crewx/wi/cli'))),
57
57
  chromex: () => Promise.resolve().then(() => __importStar(require('@crewx/chromex/cli'))),
58
+ notify: () => Promise.resolve().then(() => __importStar(require('@crewx/notify/cli'))),
58
59
  };
59
60
  exports.BUILTIN_COMMANDS = new Set(Object.keys(BUILTIN_MAP));
60
61
  // Load skill-tracer for observability (graceful degradation if unavailable)
@@ -5,6 +5,7 @@
5
5
  * Flags:
6
6
  * --thread <name> Conversation thread name
7
7
  * --provider <cli/xxx> Provider override
8
+ * --model <name> Model override (e.g. claude-sonnet-5)
8
9
  * --metadata <json> Extra metadata JSON (double-quoted object). Propagated to events/hooks/tracing.
9
10
  * e.g. --metadata='{"workflow_id":"wf-1"}'
10
11
  * --verbose Debug output mode (default: raw agent response only)
@@ -12,6 +13,9 @@
12
13
  * --output-format <fmt> Output format (json|text|stream-json)
13
14
  * --effort <level> Model effort (high|medium|low)
14
15
  * -f/--prompt-file <path> Read task body from file (bypasses cmd.exe argv truncation)
16
+ * --detach Re-spawn as a detached runner; print task-id and exit 0 immediately.
17
+ * Ignored when CREWX_TRACE_ID is already set (recursive-spawn guard) or
18
+ * on win32 (unsupported — exits with an error).
15
19
  *
16
20
  * Stdin support:
17
21
  * Pipe or redirect content into crewx x to supply the task body via stdin.
@@ -6,6 +6,7 @@
6
6
  * Flags:
7
7
  * --thread <name> Conversation thread name
8
8
  * --provider <cli/xxx> Provider override
9
+ * --model <name> Model override (e.g. claude-sonnet-5)
9
10
  * --metadata <json> Extra metadata JSON (double-quoted object). Propagated to events/hooks/tracing.
10
11
  * e.g. --metadata='{"workflow_id":"wf-1"}'
11
12
  * --verbose Debug output mode (default: raw agent response only)
@@ -13,6 +14,9 @@
13
14
  * --output-format <fmt> Output format (json|text|stream-json)
14
15
  * --effort <level> Model effort (high|medium|low)
15
16
  * -f/--prompt-file <path> Read task body from file (bypasses cmd.exe argv truncation)
17
+ * --detach Re-spawn as a detached runner; print task-id and exit 0 immediately.
18
+ * Ignored when CREWX_TRACE_ID is already set (recursive-spawn guard) or
19
+ * on win32 (unsupported — exits with an error).
16
20
  *
17
21
  * Stdin support:
18
22
  * Pipe or redirect content into crewx x to supply the task body via stdin.
@@ -21,12 +25,72 @@
21
25
  */
22
26
  Object.defineProperty(exports, "__esModule", { value: true });
23
27
  exports.handleExecute = handleExecute;
28
+ const child_process_1 = require("child_process");
29
+ const fs_1 = require("fs");
30
+ const path_1 = require("path");
31
+ const os_1 = require("os");
24
32
  const sdk_1 = require("@crewx/sdk");
25
33
  const parse_agent_message_1 = require("./parse-agent-message");
26
34
  const parse_common_flags_1 = require("./parse-common-flags");
27
35
  const resolve_prompt_1 = require("./resolve-prompt");
28
36
  const crewx_cli_1 = require("../bootstrap/crewx-cli");
29
37
  const inherited_trace_1 = require("../utils/inherited-trace");
38
+ const write_output_1 = require("./write-output");
39
+ /**
40
+ * Split `--detach` out of argv, respecting the `--` literal-args sentinel
41
+ * (a `--detach` appearing after `--` is message text, not the flag).
42
+ */
43
+ function extractDetachFlag(args) {
44
+ const rest = [];
45
+ let detach = false;
46
+ let escapeMode = false;
47
+ for (const arg of args) {
48
+ if (!escapeMode && arg === '--') {
49
+ escapeMode = true;
50
+ rest.push(arg);
51
+ continue;
52
+ }
53
+ if (!escapeMode && arg === '--detach') {
54
+ detach = true;
55
+ continue;
56
+ }
57
+ rest.push(arg);
58
+ }
59
+ return { detach, rest };
60
+ }
61
+ /**
62
+ * Double-detach: re-spawn this same CLI entry (minus --detach) as a detached
63
+ * process so it survives the parent's exit. The task-id is pre-generated here
64
+ * and injected as CREWX_TRACE_ID so the runner's own task row is created under
65
+ * this id (see handleExecute's `selfTaskId` derivation below) — it doubles as
66
+ * both this task's row id and the root of any further delegation it spawns.
67
+ *
68
+ * stdout contract (script-parseable): task-id only, on the first line.
69
+ * Everything else goes to stderr.
70
+ */
71
+ function runDetached(filteredArgs) {
72
+ const taskId = (0, sdk_1.generateId)('tsk');
73
+ const logDir = (0, path_1.join)((0, os_1.homedir)(), '.crewx', 'logs');
74
+ if (!(0, fs_1.existsSync)(logDir))
75
+ (0, fs_1.mkdirSync)(logDir, { recursive: true });
76
+ const logPath = (0, path_1.join)(logDir, `${taskId}.log`);
77
+ const logFd = (0, fs_1.openSync)(logPath, 'a');
78
+ const entry = process.argv[1];
79
+ const child = (0, child_process_1.spawn)(process.execPath, [entry, 'x', ...filteredArgs], {
80
+ detached: true,
81
+ stdio: ['ignore', logFd, logFd],
82
+ env: { ...process.env, CREWX_TRACE_ID: taskId },
83
+ });
84
+ (0, fs_1.closeSync)(logFd);
85
+ child.on('error', (err) => {
86
+ process.stderr.write(`Failed to spawn detached runner: ${err.message}\n`);
87
+ });
88
+ child.unref();
89
+ console.log(taskId);
90
+ process.stderr.write(`Detached task ${taskId} started (log: ${logPath}).\n`);
91
+ process.stderr.write(`Use \`crewx result ${taskId} --wait=N\` to wait for completion.\n`);
92
+ process.exit(0);
93
+ }
30
94
  /**
31
95
  * Handle `crewx execute <agentRef> <message>` command.
32
96
  *
@@ -34,7 +98,26 @@ const inherited_trace_1 = require("../utils/inherited-trace");
34
98
  * --verbose: debug info written to stderr, response to stdout.
35
99
  */
36
100
  async function handleExecute(args) {
37
- const { thread, provider, metadata, verbose, config, outputFormat, effort, promptFile, vars, rest } = (0, parse_common_flags_1.parseCommonFlags)(args);
101
+ const { detach, rest: detachFilteredArgs } = extractDetachFlag(args);
102
+ if (detach) {
103
+ // Recursive-spawn guard: a CREWX_TRACE_ID already present means this
104
+ // process is itself running inside a traced context (either the
105
+ // respawned runner, or a delegated sub-call) — never chain a second
106
+ // detach off of it. Silently fall through to normal (synchronous) execution.
107
+ if (process.env['CREWX_TRACE_ID']) {
108
+ process.stderr.write('Note: --detach ignored (already running inside a traced context; CREWX_TRACE_ID is set).\n');
109
+ }
110
+ else if (process.platform === 'win32') {
111
+ console.error('Error: --detach is not supported on win32.');
112
+ process.exit(1);
113
+ return;
114
+ }
115
+ else {
116
+ runDetached(detachFilteredArgs);
117
+ return;
118
+ }
119
+ }
120
+ const { thread, provider, model, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest } = (0, parse_common_flags_1.parseCommonFlags)(detachFilteredArgs);
38
121
  const { agentRef: parsedAgentRef, message } = (0, parse_agent_message_1.parseAgentMessage)(rest);
39
122
  // No @mention → default to @crewx agent (matches cli-bak behaviour)
40
123
  const agentRef = parsedAgentRef || '@crewx';
@@ -55,6 +138,7 @@ async function handleExecute(args) {
55
138
  console.error('Options:');
56
139
  console.error(' --thread <name> Conversation thread name');
57
140
  console.error(' --provider <cli/xxx> Provider override');
141
+ console.error(' --model <name> Model override (e.g. claude-sonnet-5)');
58
142
  console.error(' --metadata <json> Extra metadata (JSON object, double-quoted).');
59
143
  console.error(' Propagated to events/hooks/tracing.');
60
144
  console.error(' Invalid JSON aborts with exit code 2.');
@@ -62,9 +146,11 @@ async function handleExecute(args) {
62
146
  console.error(' --verbose Debug output mode');
63
147
  console.error(' --config/-c <path> Config file path');
64
148
  console.error(' --output-format <fmt> Output format (json|text|stream-json)');
149
+ console.error(' --out/-o <path> Save result to file (stdout suppressed)');
65
150
  console.error(' --effort <level> Model effort (high|medium|low)');
66
151
  console.error(' -f/--prompt-file <path> Read task body from file');
67
152
  console.error(' --var key=value Template variable (repeatable)');
153
+ console.error(' --overdrive Activate overdrive (boost) profile for this request');
68
154
  process.exit(1);
69
155
  }
70
156
  const configPath = config ?? process.env.CREWX_CONFIG ?? 'crewx.yaml';
@@ -79,10 +165,14 @@ async function handleExecute(args) {
79
165
  process.stderr.write(`🔗 Thread: ${thread}\n`);
80
166
  if (provider)
81
167
  process.stderr.write(`🔌 Provider: ${provider}\n`);
168
+ if (model)
169
+ process.stderr.write(`🧠 Model: ${model}\n`);
82
170
  if (outputFormat)
83
171
  process.stderr.write(`📄 Output-format: ${outputFormat}\n`);
84
172
  if (effort)
85
173
  process.stderr.write(`⚡ Effort: ${effort}\n`);
174
+ if (overdrive)
175
+ process.stderr.write(`🚀 Overdrive: ON\n`);
86
176
  process.stderr.write('─'.repeat(60) + '\n');
87
177
  }
88
178
  let parsedMetadata = {};
@@ -94,19 +184,32 @@ async function handleExecute(args) {
94
184
  process.stderr.write(`Error: ${msg}\n`);
95
185
  process.exit(2);
96
186
  }
187
+ const inheritedTrace = (0, inherited_trace_1.readInheritedTrace)();
188
+ // A trace with a rootTraceId but no parentTaskId means the id was pre-assigned
189
+ // to *this* task itself (the detach runner's parent injects only CREWX_TRACE_ID,
190
+ // never CREWX_PARENT_TASK_ID — see execute.ts's runDetached), not inherited from
191
+ // an ancestor task in a delegation chain (which always carries both). It doubles
192
+ // as this task's own row id so `crewx result <task-id>` can find it.
193
+ const selfTaskId = inheritedTrace && !inheritedTrace.parentTaskId
194
+ ? (inheritedTrace.rootTraceId || undefined)
195
+ : undefined;
97
196
  let exitCode = 0;
98
197
  try {
99
198
  const result = await crewx.execute(agentRef, finalMessage, {
100
199
  provider,
200
+ model,
101
201
  effort: effort || undefined,
202
+ overdrive: overdrive || undefined,
102
203
  threadId: thread,
204
+ taskId: selfTaskId,
103
205
  metadata: Object.keys(parsedMetadata).length > 0 ? parsedMetadata : undefined,
104
206
  vars: Object.keys(vars).length > 0 ? vars : undefined,
105
- trace: (0, inherited_trace_1.readInheritedTrace)(),
207
+ trace: inheritedTrace,
106
208
  });
107
209
  if (!result.ok) {
108
210
  const errMsg = result.error?.message ?? 'Execute failed';
109
211
  console.error(errMsg);
212
+ (0, write_output_1.appendError)(out, errMsg);
110
213
  exitCode = 1;
111
214
  }
112
215
  else {
@@ -119,7 +222,7 @@ async function handleExecute(args) {
119
222
  process.stderr.write('\n📄 Response:\n');
120
223
  process.stderr.write('─'.repeat(40) + '\n');
121
224
  }
122
- console.log(result.data);
225
+ (0, write_output_1.writeResult)(out, result.data);
123
226
  if (verbose) {
124
227
  process.stderr.write('\n✅ Execute completed successfully\n');
125
228
  }
@@ -128,6 +231,7 @@ async function handleExecute(args) {
128
231
  catch (err) {
129
232
  const errMsg = err instanceof Error ? err.message : String(err);
130
233
  console.error(`Error: ${errMsg}`);
234
+ (0, write_output_1.appendError)(out, `Error: ${errMsg}`);
131
235
  exitCode = 1;
132
236
  }
133
237
  finally {
@@ -84,6 +84,11 @@ const CREWX_MARKER = '# CrewX runtime';
84
84
  const CREWX_GITIGNORE = `# CrewX runtime
85
85
  .crewx/
86
86
 
87
+ # Secrets (workspace .env — see docs/manual)
88
+ .env
89
+ .env.*
90
+ !.env.example
91
+
87
92
  # Memory runtime state (regenerable from entries/)
88
93
  memory/*/.dirty-summary
89
94
  memory/*/graph.json
@@ -2,8 +2,8 @@
2
2
  * Common flag parser for query/execute commands.
3
3
  *
4
4
  * Supports both `--flag=value` and `--flag value` forms.
5
- * Handles: --thread, --provider, --metadata, --verbose, --config/-c,
6
- * --output-format, --effort, --prompt-file/-f.
5
+ * Handles: --thread, --provider, --model, --metadata, --verbose, --config/-c,
6
+ * --output-format, --effort, --prompt-file/-f, --overdrive.
7
7
  *
8
8
  * Strict mode: unknown --xxx tokens after known flags are consumed throw an
9
9
  * error instead of silently leaking into the message prompt.
@@ -14,6 +14,8 @@ export interface CommonFlags {
14
14
  thread?: string;
15
15
  /** Provider override (e.g., cli/claude). */
16
16
  provider?: string;
17
+ /** Model override (e.g., claude-sonnet-5). */
18
+ model?: string;
17
19
  /** Raw metadata JSON string. */
18
20
  metadata?: string;
19
21
  /** Enable verbose/debug output mode. */
@@ -26,6 +28,10 @@ export interface CommonFlags {
26
28
  effort?: string;
27
29
  /** Path to a file whose content is used as the prompt body (-f/--prompt-file). */
28
30
  promptFile?: string;
31
+ /** Whether overdrive (boost) is active for this request. */
32
+ overdrive: boolean;
33
+ /** Output file path for saving result (--out/-o). */
34
+ out?: string;
29
35
  /** Template variables from --var key=value flags. */
30
36
  vars: Record<string, string>;
31
37
  /** Remaining non-flag positional arguments. */
@@ -3,8 +3,8 @@
3
3
  * Common flag parser for query/execute commands.
4
4
  *
5
5
  * Supports both `--flag=value` and `--flag value` forms.
6
- * Handles: --thread, --provider, --metadata, --verbose, --config/-c,
7
- * --output-format, --effort, --prompt-file/-f.
6
+ * Handles: --thread, --provider, --model, --metadata, --verbose, --config/-c,
7
+ * --output-format, --effort, --prompt-file/-f, --overdrive.
8
8
  *
9
9
  * Strict mode: unknown --xxx tokens after known flags are consumed throw an
10
10
  * error instead of silently leaking into the message prompt.
@@ -63,22 +63,27 @@ exports.UnknownOptionError = UnknownOptionError;
63
63
  function parseCommonFlags(args) {
64
64
  const thread = parseFlag(args, '--thread');
65
65
  const provider = parseFlag(args, '--provider');
66
+ const model = parseFlag(args, '--model');
66
67
  const metadata = parseFlag(args, '--metadata');
67
68
  const config = parseFlag(args, '--config', '-c');
68
69
  const outputFormat = parseFlag(args, '--output-format');
69
70
  const effort = parseFlag(args, '--effort');
70
71
  const promptFile = parseFlag(args, '--prompt-file', '-f');
72
+ const out = parseFlag(args, '--out', '-o');
71
73
  const verbose = hasFlag(args, '--verbose');
74
+ const overdrive = hasFlag(args, '--overdrive');
72
75
  // Collect consumed positions for known flags
73
76
  const consumed = new Set();
74
77
  const flagPairs = [
75
78
  { names: ['--thread'] },
76
79
  { names: ['--provider'] },
80
+ { names: ['--model'] },
77
81
  { names: ['--metadata'] },
78
82
  { names: ['--config', '-c'] },
79
83
  { names: ['--output-format'] },
80
84
  { names: ['--effort'] },
81
85
  { names: ['--prompt-file', '-f'] },
86
+ { names: ['--out', '-o'] },
82
87
  ];
83
88
  // Parse --var key=value flags (multiple allowed; last value wins on duplicate keys)
84
89
  const vars = {};
@@ -88,6 +93,10 @@ function parseCommonFlags(args) {
88
93
  consumed.add(i);
89
94
  continue;
90
95
  }
96
+ if (arg === '--overdrive') {
97
+ consumed.add(i);
98
+ continue;
99
+ }
91
100
  // --var=key=value or --var key=value
92
101
  if (arg.startsWith('--var=') || arg === '--var') {
93
102
  let kv;
@@ -148,7 +157,7 @@ function parseCommonFlags(args) {
148
157
  }
149
158
  rest.push(token);
150
159
  }
151
- return { thread, provider, metadata, verbose, config, outputFormat, effort, promptFile, vars, rest };
160
+ return { thread, provider, model, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest };
152
161
  }
153
162
  /**
154
163
  * Parse metadata JSON string from --metadata flag.
@@ -21,14 +21,54 @@ function formatElapsed(ms) {
21
21
  const h = Math.floor(m / 60);
22
22
  return `${h}h ${m % 60}m`;
23
23
  }
24
+ /**
25
+ * Antigravity-family providers (coding_agent_command starting with 'agy',
26
+ * path-included forms like '/usr/local/bin/agy' also count) don't emit
27
+ * parseable logs, so they get a distinct 'n/a' instead of '—'.
28
+ */
29
+ function isAgyCommand(codingAgentCommand) {
30
+ const cmd = (codingAgentCommand ?? '').trim();
31
+ if (!cmd)
32
+ return false;
33
+ const firstToken = cmd.split(/\s+/)[0] ?? '';
34
+ const base = firstToken.split('/').pop() ?? firstToken;
35
+ return base.startsWith('agy');
36
+ }
37
+ function getLastActive(task) {
38
+ try {
39
+ const entries = task.logs ? JSON.parse(task.logs) : [];
40
+ if (Array.isArray(entries) && entries.length > 0) {
41
+ const lastEntry = entries[entries.length - 1];
42
+ const ts = lastEntry?.timestamp;
43
+ const parsedMs = ts ? new Date(ts).getTime() : NaN;
44
+ if (ts && !Number.isNaN(parsedMs)) {
45
+ const diffMs = Math.max(0, Date.now() - parsedMs);
46
+ return {
47
+ display: `${formatElapsed(diffMs)} ago`,
48
+ isoTimestamp: ts,
49
+ logCapable: true,
50
+ };
51
+ }
52
+ }
53
+ }
54
+ catch {
55
+ // fall through to antigravity/dash fallback below
56
+ }
57
+ if (isAgyCommand(task.coding_agent_command)) {
58
+ return { display: 'n/a', isoTimestamp: null, logCapable: false };
59
+ }
60
+ return { display: '—', isoTimestamp: null, logCapable: true };
61
+ }
24
62
  function taskToRow(task) {
25
63
  const elapsed = formatElapsed(Date.now() - new Date(task.started_at).getTime());
64
+ const lastActive = getLastActive(task);
26
65
  return [
27
66
  task.id,
28
67
  task.agent_id ?? '—',
29
68
  task.pid !== null && task.pid !== undefined ? String(task.pid) : '—',
30
69
  elapsed,
31
70
  task.mode ?? '—',
71
+ lastActive.display,
32
72
  ];
33
73
  }
34
74
  function renderTable(headers, rows) {
@@ -43,16 +83,25 @@ function renderTable(headers, rows) {
43
83
  }
44
84
  async function handlePs(args) {
45
85
  const repo = new repository_1.TaskRepository();
86
+ repo.reapRunningWorkflowTasks();
46
87
  const tasks = repo.getRunningTasks();
47
88
  if (tasks.length === 0) {
48
89
  console.log('No running tasks.');
49
90
  return;
50
91
  }
51
92
  if (args.includes('--json')) {
52
- console.log(JSON.stringify(tasks, null, 2));
93
+ const withLastActive = tasks.map((task) => {
94
+ const lastActive = getLastActive(task);
95
+ return {
96
+ ...task,
97
+ last_active_at: lastActive.isoTimestamp,
98
+ log_capable: lastActive.logCapable,
99
+ };
100
+ });
101
+ console.log(JSON.stringify(withLastActive, null, 2));
53
102
  return;
54
103
  }
55
- const headers = ['TASK ID', 'AGENT', 'PID', 'ELAPSED', 'MODE'];
104
+ const headers = ['TASK ID', 'AGENT', 'PID', 'ELAPSED', 'MODE', 'LAST ACTIVE'];
56
105
  const rows = tasks.map(taskToRow);
57
106
  renderTable(headers, rows);
58
107
  console.log(`\n ${tasks.length} running task(s)`);
@@ -5,6 +5,7 @@
5
5
  * Flags:
6
6
  * --thread <name> Conversation thread name
7
7
  * --provider <cli/xxx> Provider override
8
+ * --model <name> Model override (e.g. claude-sonnet-5)
8
9
  * --metadata <json> Extra metadata JSON (double-quoted object). Propagated to events/hooks/tracing.
9
10
  * e.g. --metadata='{"workflow_id":"wf-1"}'
10
11
  * --verbose Debug output mode (default: raw agent response only)
@@ -6,6 +6,7 @@
6
6
  * Flags:
7
7
  * --thread <name> Conversation thread name
8
8
  * --provider <cli/xxx> Provider override
9
+ * --model <name> Model override (e.g. claude-sonnet-5)
9
10
  * --metadata <json> Extra metadata JSON (double-quoted object). Propagated to events/hooks/tracing.
10
11
  * e.g. --metadata='{"workflow_id":"wf-1"}'
11
12
  * --verbose Debug output mode (default: raw agent response only)
@@ -27,6 +28,7 @@ const parse_common_flags_1 = require("./parse-common-flags");
27
28
  const resolve_prompt_1 = require("./resolve-prompt");
28
29
  const crewx_cli_1 = require("../bootstrap/crewx-cli");
29
30
  const inherited_trace_1 = require("../utils/inherited-trace");
31
+ const write_output_1 = require("./write-output");
30
32
  /**
31
33
  * Handle `crewx query <agentRef> <message>` command.
32
34
  *
@@ -34,7 +36,7 @@ const inherited_trace_1 = require("../utils/inherited-trace");
34
36
  * --verbose: debug info written to stderr, response to stdout.
35
37
  */
36
38
  async function handleQuery(args) {
37
- const { thread, provider, metadata, verbose, config, outputFormat, effort, promptFile, vars, rest } = (0, parse_common_flags_1.parseCommonFlags)(args);
39
+ const { thread, provider, model, metadata, verbose, config, outputFormat, effort, promptFile, overdrive, vars, out, rest } = (0, parse_common_flags_1.parseCommonFlags)(args);
38
40
  const { agentRef: parsedAgentRef, message } = (0, parse_agent_message_1.parseAgentMessage)(rest);
39
41
  // No @mention → default to @crewx agent (matches cli-bak behaviour)
40
42
  const agentRef = parsedAgentRef || '@crewx';
@@ -55,6 +57,7 @@ async function handleQuery(args) {
55
57
  console.error('Options:');
56
58
  console.error(' --thread <name> Conversation thread name');
57
59
  console.error(' --provider <cli/xxx> Provider override');
60
+ console.error(' --model <name> Model override (e.g. claude-sonnet-5)');
58
61
  console.error(' --metadata <json> Extra metadata (JSON object, double-quoted).');
59
62
  console.error(' Propagated to events/hooks/tracing.');
60
63
  console.error(' Invalid JSON aborts with exit code 2.');
@@ -62,9 +65,11 @@ async function handleQuery(args) {
62
65
  console.error(' --verbose Debug output mode');
63
66
  console.error(' --config/-c <path> Config file path');
64
67
  console.error(' --output-format <fmt> Output format (json|text|stream-json)');
68
+ console.error(' --out/-o <path> Save result to file (stdout suppressed)');
65
69
  console.error(' --effort <level> Model effort (high|medium|low)');
66
70
  console.error(' -f/--prompt-file <path> Read prompt body from file');
67
71
  console.error(' --var key=value Template variable (repeatable)');
72
+ console.error(' --overdrive Activate overdrive (boost) profile for this request');
68
73
  process.exit(1);
69
74
  }
70
75
  const configPath = config ?? process.env.CREWX_CONFIG ?? 'crewx.yaml';
@@ -79,10 +84,14 @@ async function handleQuery(args) {
79
84
  process.stderr.write(`🔗 Thread: ${thread}\n`);
80
85
  if (provider)
81
86
  process.stderr.write(`🔌 Provider: ${provider}\n`);
87
+ if (model)
88
+ process.stderr.write(`🧠 Model: ${model}\n`);
82
89
  if (outputFormat)
83
90
  process.stderr.write(`📄 Output-format: ${outputFormat}\n`);
84
91
  if (effort)
85
92
  process.stderr.write(`⚡ Effort: ${effort}\n`);
93
+ if (overdrive)
94
+ process.stderr.write(`🚀 Overdrive: ON\n`);
86
95
  process.stderr.write('─'.repeat(60) + '\n');
87
96
  }
88
97
  let parsedMetadata = {};
@@ -98,7 +107,9 @@ async function handleQuery(args) {
98
107
  try {
99
108
  const result = await crewx.query(agentRef, finalMessage, {
100
109
  provider,
110
+ model,
101
111
  effort: effort || undefined,
112
+ overdrive: overdrive || undefined,
102
113
  threadId: thread,
103
114
  metadata: Object.keys(parsedMetadata).length > 0 ? parsedMetadata : undefined,
104
115
  vars: Object.keys(vars).length > 0 ? vars : undefined,
@@ -107,6 +118,7 @@ async function handleQuery(args) {
107
118
  if (!result.ok) {
108
119
  const errMsg = result.error?.message ?? 'Query failed';
109
120
  console.error(errMsg);
121
+ (0, write_output_1.appendError)(out, errMsg);
110
122
  exitCode = 1;
111
123
  }
112
124
  else {
@@ -119,7 +131,7 @@ async function handleQuery(args) {
119
131
  process.stderr.write('\n📄 Response:\n');
120
132
  process.stderr.write('─'.repeat(40) + '\n');
121
133
  }
122
- console.log(result.data);
134
+ (0, write_output_1.writeResult)(out, result.data);
123
135
  if (verbose) {
124
136
  process.stderr.write('\n✅ Query completed successfully\n');
125
137
  }
@@ -128,6 +140,7 @@ async function handleQuery(args) {
128
140
  catch (err) {
129
141
  const errMsg = err instanceof Error ? err.message : String(err);
130
142
  console.error(`Error: ${errMsg}`);
143
+ (0, write_output_1.appendError)(out, `Error: ${errMsg}`);
131
144
  exitCode = 1;
132
145
  }
133
146
  finally {
@@ -23,7 +23,7 @@ exports.KNOWN_COMMANDS = new Set([
23
23
  /** Built-in tool commands routed via handleBuiltin(). */
24
24
  exports.BUILTIN_COMMAND_NAMES = new Set([
25
25
  'memory', 'search', 'doc', 'wbs', 'cron', 'workflow', 'skill', 'dreaming',
26
- 'wi', 'chromex',
26
+ 'wi', 'chromex', 'notify',
27
27
  ]);
28
28
  /** Commands not yet migrated from cli-bak — show a migration message. */
29
29
  exports.NOT_YET_MIGRATED = new Set([
@@ -43,18 +43,23 @@ function buildRetryPrefix(originalTaskId) {
43
43
  * the string when present and non-empty, otherwise `undefined` so the
44
44
  * agent's configured provider default is used.
45
45
  */
46
- function extractProvider(metadata) {
46
+ function parseTaskMetadata(metadata) {
47
47
  if (!metadata)
48
- return undefined;
48
+ return {};
49
49
  try {
50
50
  const parsed = JSON.parse(metadata);
51
- const provider = parsed.provider;
52
- return typeof provider === 'string' && provider.length > 0 ? provider : undefined;
51
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
52
+ ? parsed
53
+ : {};
53
54
  }
54
55
  catch {
55
- return undefined;
56
+ return {};
56
57
  }
57
58
  }
59
+ function extractProvider(metadata) {
60
+ const provider = metadata.provider;
61
+ return typeof provider === 'string' && provider.length > 0 ? provider : undefined;
62
+ }
58
63
  async function handleRestart(args) {
59
64
  const verbose = args.includes('--verbose');
60
65
  const taskId = args.find((a) => !a.startsWith('--'));
@@ -96,7 +101,10 @@ async function handleRestart(args) {
96
101
  // provider: recovered from metadata.provider (SDK-persisted). Falls back to
97
102
  // the agent's configured provider when absent. This preserves a
98
103
  // `crewx x --provider ...` choice across restart.
99
- const provider = extractProvider(original.metadata);
104
+ const originalMetadata = parseTaskMetadata(original.metadata);
105
+ const provider = extractProvider(originalMetadata);
106
+ const originalWasOverdrive = originalMetadata.overdrive === true;
107
+ const originalOverdriveMode = originalMetadata.overdriveState === 'latch' ? 'latch' : 'count';
100
108
  (0, sdk_1.setAuditVerbose)(verbose);
101
109
  if (verbose) {
102
110
  process.stderr.write(`🔁 Restart: ${taskId} → ${newTaskId}\n`);
@@ -111,10 +119,16 @@ async function handleRestart(args) {
111
119
  threadId: original.thread_id ?? undefined,
112
120
  model,
113
121
  provider,
122
+ ...(originalWasOverdrive ? { overdrive: { mode: originalOverdriveMode } } : {}),
114
123
  metadata: {
115
124
  restartedFromTaskId: taskId,
116
125
  // Back-compat / search convenience: mirror the Web UI metadata key.
117
126
  retriedFromTaskId: taskId,
127
+ ...(originalWasOverdrive ? {
128
+ overdrive: true,
129
+ overdriveState: originalOverdriveMode,
130
+ overdriveMode: mode,
131
+ } : {}),
118
132
  },
119
133
  trace: (0, inherited_trace_1.readInheritedTrace)(),
120
134
  };
@@ -3,8 +3,12 @@
3
3
  * Retrieves the result of a completed task by its ID.
4
4
  *
5
5
  * Usage:
6
- * crewx result <task-id> Print raw result
7
- * crewx result <task-id> --json Print full task record as JSON
8
- * crewx result List recent tasks (latest 10)
6
+ * crewx result <task-id> Print raw result
7
+ * crewx result <task-id> --json Print full task record as JSON
8
+ * crewx result <task-id> --wait=N Poll (1s interval) up to N seconds for
9
+ * the task to leave 'running'. Exit 124 on
10
+ * timeout. --wait=0 behaves like no --wait
11
+ * (single immediate check).
12
+ * crewx result List recent tasks (latest 10)
9
13
  */
10
14
  export declare function handleResult(args: string[]): Promise<void>;
@@ -4,13 +4,18 @@
4
4
  * Retrieves the result of a completed task by its ID.
5
5
  *
6
6
  * Usage:
7
- * crewx result <task-id> Print raw result
8
- * crewx result <task-id> --json Print full task record as JSON
9
- * crewx result List recent tasks (latest 10)
7
+ * crewx result <task-id> Print raw result
8
+ * crewx result <task-id> --json Print full task record as JSON
9
+ * crewx result <task-id> --wait=N Poll (1s interval) up to N seconds for
10
+ * the task to leave 'running'. Exit 124 on
11
+ * timeout. --wait=0 behaves like no --wait
12
+ * (single immediate check).
13
+ * crewx result List recent tasks (latest 10)
10
14
  */
11
15
  Object.defineProperty(exports, "__esModule", { value: true });
12
16
  exports.handleResult = handleResult;
13
17
  const repository_1 = require("@crewx/sdk/repository");
18
+ const POLL_INTERVAL_MS = 1000;
14
19
  function statusIcon(status) {
15
20
  switch (status) {
16
21
  case 'running': return '⏳';
@@ -19,8 +24,20 @@ function statusIcon(status) {
19
24
  default: return '❓';
20
25
  }
21
26
  }
27
+ function sleep(ms) {
28
+ return new Promise((resolve) => setTimeout(resolve, ms));
29
+ }
30
+ /** Parses `--wait=N` (seconds). Returns undefined when the flag is absent. */
31
+ function parseWaitSeconds(args) {
32
+ const arg = args.find(a => a.startsWith('--wait='));
33
+ if (arg === undefined)
34
+ return undefined;
35
+ const n = Number(arg.slice('--wait='.length));
36
+ return Number.isFinite(n) && n >= 0 ? n : 0;
37
+ }
22
38
  async function handleResult(args) {
23
39
  const jsonMode = args.includes('--json');
40
+ const waitSeconds = parseWaitSeconds(args);
24
41
  const taskId = args.find(a => !a.startsWith('--'));
25
42
  const repo = new repository_1.TaskRepository();
26
43
  if (!taskId) {
@@ -45,12 +62,29 @@ async function handleResult(args) {
45
62
  console.log('Tip: Run `crewx result <task-id>` to see full output.');
46
63
  return;
47
64
  }
48
- const task = repo.getTask(taskId);
65
+ let task = repo.getTask(taskId);
49
66
  if (!task) {
50
67
  console.error(`Error: Task not found: ${taskId}`);
51
68
  process.exit(1);
52
69
  return;
53
70
  }
71
+ if (waitSeconds !== undefined && waitSeconds > 0 && task.status === 'running') {
72
+ const deadline = Date.now() + waitSeconds * 1000;
73
+ while (task && task.status === 'running') {
74
+ if (Date.now() >= deadline) {
75
+ console.error(`Task ${taskId} did not complete within --wait=${waitSeconds}s (status: running).`);
76
+ process.exit(124);
77
+ return;
78
+ }
79
+ await sleep(Math.min(POLL_INTERVAL_MS, Math.max(0, deadline - Date.now())));
80
+ task = repo.getTask(taskId);
81
+ if (!task) {
82
+ console.error(`Error: Task not found: ${taskId}`);
83
+ process.exit(1);
84
+ return;
85
+ }
86
+ }
87
+ }
54
88
  if (jsonMode) {
55
89
  console.log(JSON.stringify(task, null, 2));
56
90
  return;
@@ -0,0 +1,3 @@
1
+ export declare function writeResult(out: string | undefined, data: string): void;
2
+ /** On failure: if out is specified, append to file (avoid empty file). stderr is kept by the caller. */
3
+ export declare function appendError(out: string | undefined, message: string): void;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeResult = writeResult;
4
+ exports.appendError = appendError;
5
+ /**
6
+ * EPIPE-safe result output.
7
+ * - out specified: write success result to file (sync, no stream EPIPE)
8
+ * - out not specified: fall back to existing stdout (console.log)
9
+ */
10
+ const fs_1 = require("fs");
11
+ function writeResult(out, data) {
12
+ if (out) {
13
+ (0, fs_1.writeFileSync)(out, data, 'utf8');
14
+ }
15
+ else {
16
+ console.log(data);
17
+ }
18
+ }
19
+ /** On failure: if out is specified, append to file (avoid empty file). stderr is kept by the caller. */
20
+ function appendError(out, message) {
21
+ if (out) {
22
+ (0, fs_1.appendFileSync)(out, message.endsWith('\n') ? message : message + '\n', 'utf8');
23
+ }
24
+ }
package/dist/main.d.ts CHANGED
@@ -5,7 +5,8 @@
5
5
  *
6
6
  * Boot sequence:
7
7
  * 1. Inject CREWX_CLI / CREWX_WORKSPACE env defaults (must be first)
8
- * 2. Parse command
9
- * 3. Dispatch to handler
8
+ * 2. Load workspace .env (does not override existing process.env values)
9
+ * 3. Parse command
10
+ * 4. Dispatch to handler
10
11
  */
11
12
  export {};
package/dist/main.js CHANGED
@@ -6,8 +6,9 @@
6
6
  *
7
7
  * Boot sequence:
8
8
  * 1. Inject CREWX_CLI / CREWX_WORKSPACE env defaults (must be first)
9
- * 2. Parse command
10
- * 3. Dispatch to handler
9
+ * 2. Load workspace .env (does not override existing process.env values)
10
+ * 3. Parse command
11
+ * 4. Dispatch to handler
11
12
  */
12
13
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
13
14
  if (k2 === undefined) k2 = k;
@@ -46,8 +47,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
46
47
  // ─── P0-1: Env Bootstrap ─────────────────────────────────────────────────────
47
48
  // Must run before any other code that might use process.env.CREWX_CLI.
48
49
  const env_defaults_1 = require("./utils/env-defaults");
50
+ const sdk_1 = require("@crewx/sdk");
51
+ const dotenv = __importStar(require("dotenv"));
52
+ const path_1 = require("path");
49
53
  process.env.CREWX_CLI ??= (0, env_defaults_1.resolveCrewxCli)();
50
54
  process.env.CREWX_WORKSPACE ??= (0, env_defaults_1.resolveCrewxWorkspace)();
55
+ // Load the workspace .env (WI-20260725-010): keeps CLI (crewx q/x) in parity with
56
+ // the server's ConfigModule, which already reads cwd/.env. override:false so a
57
+ // value already present in the shell/environment always wins over the file.
58
+ // quiet:true suppresses dotenv's injected-keys log and tip banner on stdout.
59
+ dotenv.config({ path: (0, path_1.join)(process.env.CREWX_WORKSPACE, '.env'), override: false, quiet: true });
60
+ // ─── Pricing remote override (WI-20260701-002) ───────────────────────────────
61
+ // Best-effort, non-blocking: fetch remote model registry so new models get
62
+ // accurate pricing without a CLI republish. Falls back to bundled table on
63
+ // failure / offline. Browser entry does not call this automatically.
64
+ void (0, sdk_1.initPricingRemote)();
51
65
  // ─── Command Imports ──────────────────────────────────────────────────────────
52
66
  const query_1 = require("./commands/query");
53
67
  const execute_1 = require("./commands/execute");
@@ -256,12 +270,19 @@ Query / Execute:
256
270
  --verbose Debug output mode (default: raw response only)
257
271
  --config/-c <path> Config file path (default: CREWX_CONFIG or crewx.yaml)
258
272
  --output-format <fmt> Output format (json|text|stream-json)
273
+ --out/-o <path> Save result to file (stdout suppressed)
259
274
  --effort <level> Model effort (high|medium|low)
260
275
  -f/--prompt-file <path> Read task body from file (bypasses argv length limits)
261
276
  --var key=value Template variable (repeatable). Accessible as {{key}} in agent prompt.
262
277
  -- End of flags; remaining tokens treated as message text
263
278
  e.g. crewx q "@agent label" -- --flag-in-message
264
279
 
280
+ x/execute only:
281
+ --detach Re-spawn as a detached background runner; print task-id
282
+ and exit 0 immediately. Ignored if CREWX_TRACE_ID is
283
+ already set (recursive-spawn guard). Unsupported on win32.
284
+ e.g. crewx x "@agent label" --detach
285
+
265
286
  Agent Management:
266
287
  agent ls [options] List configured agents
267
288
  --role <value> Filter by role (comma-separated for OR match)
@@ -274,6 +295,8 @@ Task Management:
274
295
  kill <task-id> Kill a running task
275
296
  kill --all Kill all running tasks
276
297
  result [task-id] Get task result (or list recent tasks)
298
+ --wait=N Poll (1s interval) up to N seconds for the task to
299
+ finish. Exit 124 on timeout. --wait=0 = single check.
277
300
  restart <task-id> Restart a failed task as a new task
278
301
 
279
302
  Logs & Diagnostics:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewx/cli",
3
- "version": "0.9.0-rc.4",
3
+ "version": "0.9.0-rc.41",
4
4
  "license": "UNLICENSED",
5
5
  "engines": {
6
6
  "node": ">=20.19.0"
@@ -23,18 +23,20 @@
23
23
  "dependencies": {
24
24
  "@crewx/adapter-slack": "0.1.4",
25
25
  "better-sqlite3": "*",
26
+ "dotenv": "17.2.3",
26
27
  "isomorphic-git": "1.37.1",
27
- "@crewx/memory": "0.1.23",
28
- "@crewx/sdk": "0.9.0-rc.4",
29
- "@crewx/search": "0.1.10",
30
- "@crewx/cron": "0.1.10",
31
- "@crewx/workflow": "0.3.22",
32
- "@crewx/doc": "0.1.9",
28
+ "@crewx/sdk": "0.9.0-rc.41",
29
+ "@crewx/search": "0.1.10-rc.36",
30
+ "@crewx/memory": "0.1.23-rc.57",
31
+ "@crewx/doc": "0.1.9-rc.33",
32
+ "@crewx/wbs": "0.1.10-rc.66",
33
+ "@crewx/cron": "0.1.10-rc.75",
34
+ "@crewx/workflow": "0.3.22-rc.87",
33
35
  "@crewx/skill": "0.1.20",
34
- "@crewx/wbs": "0.1.10",
35
- "@crewx/chromex": "0.1.0",
36
- "@crewx/wi": "0.1.10",
37
- "@crewx/shared": "0.0.6"
36
+ "@crewx/chromex": "0.1.0-rc.73",
37
+ "@crewx/shared": "0.0.6",
38
+ "@crewx/wi": "0.1.10-rc.61",
39
+ "@crewx/notify": "0.1.0-rc.11"
38
40
  },
39
41
  "devDependencies": {
40
42
  "@types/better-sqlite3": "*",