@crewx/cli 0.8.2-rc.2 → 0.8.2-rc.4

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/README.md ADDED
@@ -0,0 +1,33 @@
1
+ # CrewX CLI
2
+
3
+ > Build AI agent teams from your terminal.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/@crewx/cli.svg)](https://www.npmjs.com/package/@crewx/cli)
6
+ [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install -g @crewx/cli
12
+ ```
13
+
14
+ ## Quick Start
15
+
16
+ ```bash
17
+ crewx q "@assistant hello"
18
+ crewx x "@coder implement feature X"
19
+ crewx agent list
20
+ ```
21
+
22
+ Run `crewx --help` for the full list.
23
+
24
+ ## What is CrewX?
25
+
26
+ CrewX lets you define AI agents in a single `crewx.yaml` and call them from the terminal.
27
+
28
+ This repository contains the **CrewX CLI** — a thin wrapper over the [`@crewx/sdk`](https://www.npmjs.com/package/@crewx/sdk) runtime (distributed via npm).
29
+
30
+ ## License
31
+
32
+ CLI source: [Apache-2.0](LICENSE).
33
+ `@crewx/sdk` runtime: proprietary on npm.
package/dist/main.js CHANGED
@@ -58,6 +58,7 @@ const result_1 = require("./commands/result");
58
58
  const log_1 = require("./commands/log");
59
59
  const doctor_1 = require("./commands/doctor");
60
60
  const init_1 = require("./commands/init");
61
+ const workspace_repository_1 = require("./repository/workspace.repository");
61
62
  const builtin_1 = require("./builtin");
62
63
  const slack_1 = require("./commands/slack");
63
64
  const install_1 = require("./commands/hook/install");
@@ -145,6 +146,7 @@ async function main() {
145
146
  const force = initArgs.includes('--force') || initArgs.includes('-f');
146
147
  try {
147
148
  const r = await (0, init_1.handleInit)({ path: process.cwd(), force });
149
+ new workspace_repository_1.WorkspaceRepository().registerWorkspace(process.cwd());
148
150
  if (r.skippedReason === 'yaml-exists') {
149
151
  console.log('✓ crewx.yaml already exists (use --force to overwrite)');
150
152
  }
@@ -0,0 +1,26 @@
1
+ import BetterSqlite3 from 'better-sqlite3';
2
+ export interface WorkspaceRepositoryOptions {
3
+ /** Root directory under which `.crewx/crewx.db` lives. Defaults to `os.homedir()`. */
4
+ dbRoot?: string;
5
+ }
6
+ export declare class WorkspaceRepository {
7
+ private readonly dbPath;
8
+ constructor(opts?: WorkspaceRepositoryOptions);
9
+ /**
10
+ * Register a CLI workspace in the global CrewX DB.
11
+ *
12
+ * This is intentionally CLI-owned, not SDK-owned: workspace registration is
13
+ * CrewX application metadata, while the SDK only needs pure workspace helpers.
14
+ * Registration is best-effort so `crewx init` remains usable even if tracing
15
+ * DB setup fails.
16
+ */
17
+ registerWorkspace(workspacePath: string): void;
18
+ ensureSchema(db: InstanceType<typeof BetterSqlite3>): void;
19
+ resolveSlug(db: InstanceType<typeof BetterSqlite3>, workspaceId: string, workspacePath: string): string;
20
+ ensureRow(db: InstanceType<typeof BetterSqlite3>, opts: {
21
+ id: string;
22
+ slug: string;
23
+ name: string;
24
+ workspacePath: string;
25
+ }): void;
26
+ }
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.WorkspaceRepository = void 0;
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ const os_1 = require("os");
10
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
11
+ const sdk_1 = require("@crewx/sdk");
12
+ class WorkspaceRepository {
13
+ dbPath;
14
+ constructor(opts = {}) {
15
+ this.dbPath = (0, path_1.join)(opts.dbRoot ?? (0, os_1.homedir)(), '.crewx', 'crewx.db');
16
+ }
17
+ /**
18
+ * Register a CLI workspace in the global CrewX DB.
19
+ *
20
+ * This is intentionally CLI-owned, not SDK-owned: workspace registration is
21
+ * CrewX application metadata, while the SDK only needs pure workspace helpers.
22
+ * Registration is best-effort so `crewx init` remains usable even if tracing
23
+ * DB setup fails.
24
+ */
25
+ registerWorkspace(workspacePath) {
26
+ const normalizedPath = (0, sdk_1.normalizeWorkspacePath)(workspacePath);
27
+ try {
28
+ const dbDir = (0, path_1.dirname)(this.dbPath);
29
+ if (!(0, fs_1.existsSync)(dbDir)) {
30
+ (0, fs_1.mkdirSync)(dbDir, { recursive: true });
31
+ }
32
+ const db = new better_sqlite3_1.default(this.dbPath);
33
+ try {
34
+ this.ensureSchema(db);
35
+ const id = (0, sdk_1.hashWorkspaceId)(normalizedPath);
36
+ const name = (0, path_1.basename)(normalizedPath);
37
+ const slug = this.resolveSlug(db, id, normalizedPath);
38
+ this.ensureRow(db, { id, slug, name, workspacePath: normalizedPath });
39
+ }
40
+ finally {
41
+ db.close();
42
+ }
43
+ }
44
+ catch {
45
+ // Non-fatal: workspace registration must never crash `crewx init`.
46
+ }
47
+ }
48
+ ensureSchema(db) {
49
+ db.exec(`
50
+ CREATE TABLE IF NOT EXISTS workspaces (
51
+ id TEXT PRIMARY KEY,
52
+ slug TEXT NOT NULL UNIQUE,
53
+ name TEXT NOT NULL,
54
+ workspace_path TEXT,
55
+ is_active INTEGER NOT NULL DEFAULT 1,
56
+ created_at TEXT NOT NULL,
57
+ updated_at TEXT NOT NULL
58
+ )
59
+ `);
60
+ db.exec(`
61
+ CREATE TABLE IF NOT EXISTS threads (
62
+ id TEXT PRIMARY KEY,
63
+ workspace_id TEXT,
64
+ platform TEXT NOT NULL DEFAULT 'cli',
65
+ title TEXT,
66
+ first_message TEXT,
67
+ last_message TEXT,
68
+ message_count INTEGER NOT NULL DEFAULT 0,
69
+ created_at TEXT NOT NULL,
70
+ updated_at TEXT NOT NULL,
71
+ metadata TEXT,
72
+ FOREIGN KEY (workspace_id) REFERENCES workspaces(id) ON DELETE SET NULL
73
+ )
74
+ `);
75
+ }
76
+ resolveSlug(db, workspaceId, workspacePath) {
77
+ const basenameSlug = (0, path_1.basename)(workspacePath);
78
+ const parentSlug = `${(0, path_1.basename)((0, path_1.dirname)(workspacePath))}/${basenameSlug}`;
79
+ const candidates = [basenameSlug, parentSlug];
80
+ try {
81
+ const slugExistsForOtherWorkspace = (slug) => !!db
82
+ .prepare('SELECT id FROM workspaces WHERE slug = ? AND id != ?')
83
+ .get(slug, workspaceId);
84
+ for (const slug of candidates) {
85
+ if (!slugExistsForOtherWorkspace(slug))
86
+ return slug;
87
+ }
88
+ for (let suffix = 2; suffix < 1000; suffix += 1) {
89
+ const slug = `${parentSlug}-${suffix}`;
90
+ if (!slugExistsForOtherWorkspace(slug))
91
+ return slug;
92
+ }
93
+ }
94
+ catch {
95
+ // workspaces table may not yet exist during early migration.
96
+ }
97
+ return basenameSlug;
98
+ }
99
+ ensureRow(db, opts) {
100
+ const { id, slug, name, workspacePath } = opts;
101
+ const now = new Date().toISOString();
102
+ db.prepare(`
103
+ INSERT OR IGNORE INTO workspaces (id, slug, name, workspace_path, is_active, created_at, updated_at)
104
+ VALUES (?, ?, ?, ?, 1, ?, ?)
105
+ `).run(id, slug, name, workspacePath, now, now);
106
+ db.prepare(`
107
+ UPDATE workspaces SET workspace_path = ?, updated_at = ? WHERE id = ? AND workspace_path IS NULL
108
+ `).run(workspacePath, now, id);
109
+ }
110
+ }
111
+ exports.WorkspaceRepository = WorkspaceRepository;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewx/cli",
3
- "version": "0.8.2-rc.2",
3
+ "version": "0.8.2-rc.4",
4
4
  "license": "UNLICENSED",
5
5
  "engines": {
6
6
  "node": ">=20.19.0"
@@ -27,15 +27,15 @@
27
27
  "dependencies": {
28
28
  "@crewx/adapter-slack": "^0.1.4",
29
29
  "better-sqlite3": "*",
30
- "@crewx/sdk": "0.8.2-rc.2",
30
+ "@crewx/doc": "0.1.7",
31
31
  "@crewx/search": "0.1.8",
32
+ "@crewx/sdk": "0.8.2-rc.4",
33
+ "@crewx/skill": "0.1.7",
34
+ "@crewx/workflow": "0.3.10",
32
35
  "@crewx/memory": "0.1.9",
33
- "@crewx/doc": "0.1.7",
36
+ "@crewx/shared": "0.0.4",
34
37
  "@crewx/wbs": "0.1.8",
35
- "@crewx/cron": "0.1.7",
36
- "@crewx/workflow": "0.3.8",
37
- "@crewx/skill": "0.1.7",
38
- "@crewx/shared": "0.0.4"
38
+ "@crewx/cron": "0.1.7"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/better-sqlite3": "*",