lyzr-cortex-cli 0.1.2
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 +233 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +753 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
# Lyzr Cortex CLI
|
|
2
|
+
|
|
3
|
+
Command-line tool for Cortex platform developers. Push documents, query the knowledge graph, share with users, and manage tool projects.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g lyzr-cortex-cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Set environment variables (or pass `--api-url`, `--api-key`, `--tool-id` to each command):
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
export CORTEX_API_URL=https://your-cortex-server.com
|
|
17
|
+
export CORTEX_API_KEY=your-api-key
|
|
18
|
+
export CORTEX_TOOL_ID=your-tool-id
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## API Commands
|
|
24
|
+
|
|
25
|
+
These commands map directly to the Python (`lyzr-cortex-sdk`) and TypeScript (`lyzr-cortex-sdk`) SDK methods.
|
|
26
|
+
|
|
27
|
+
| CLI Command | Python SDK | TypeScript SDK | HTTP Endpoint |
|
|
28
|
+
|-------------|-----------|---------------|---------------|
|
|
29
|
+
| `cortex push` | `client.push()` | `client.push()` | `POST /api/tools/documents` |
|
|
30
|
+
| `cortex query` | `client.query()` | `client.query()` | `POST /api/tools/query` |
|
|
31
|
+
| `cortex whoami` | `client.get_user_context()` | `client.getUserContext()` | `GET /api/tools/context/{email}` |
|
|
32
|
+
| `cortex share` | `client.share_document()` | `client.shareDocument()` | `POST /api/tools/share-document-for-user` |
|
|
33
|
+
| `cortex users` | `client.get_org_users()` | `client.getOrgUsers()` | `GET /api/tools/org-users-for-tool` |
|
|
34
|
+
|
|
35
|
+
### `cortex push`
|
|
36
|
+
|
|
37
|
+
Push a document to the Cortex Knowledge Graph.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Push a transcript file
|
|
41
|
+
cortex push transcript_123 --type meeting_transcript --file ./transcript.txt --name "Product Sync"
|
|
42
|
+
|
|
43
|
+
# Push with personal scope
|
|
44
|
+
cortex push doc_456 --type note --file ./note.md --scope personal
|
|
45
|
+
|
|
46
|
+
# Push with team scope
|
|
47
|
+
cortex push doc_789 --type report --file ./report.txt --scope team --teams "team_eng,team_product"
|
|
48
|
+
|
|
49
|
+
# Push with metadata
|
|
50
|
+
cortex push doc_abc --type doc --file ./doc.txt --metadata '{"author":"alice@co.com"}'
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Options:
|
|
54
|
+
- `<id>` - Unique document ID (required)
|
|
55
|
+
- `-t, --type <type>` - Document type (required)
|
|
56
|
+
- `-f, --file <path>` - File with document content (required)
|
|
57
|
+
- `-n, --name <name>` - Display name
|
|
58
|
+
- `-u, --url <url>` - External URL
|
|
59
|
+
- `-s, --scope <scope>` - Access scope: `global`, `team`, or `personal` (default: `global`)
|
|
60
|
+
- `--teams <ids>` - Comma-separated team IDs (for team scope)
|
|
61
|
+
- `--metadata <json>` - JSON metadata object
|
|
62
|
+
|
|
63
|
+
### `cortex query`
|
|
64
|
+
|
|
65
|
+
Query the Cortex Knowledge Graph.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
# Simple query
|
|
69
|
+
cortex query "What decisions were made about Q1?"
|
|
70
|
+
|
|
71
|
+
# Filter by document type
|
|
72
|
+
cortex query "Latest meeting notes" --filters '{"type":["meeting_transcript"]}'
|
|
73
|
+
|
|
74
|
+
# Limit to recent documents
|
|
75
|
+
cortex query "Action items this week" --time-range 7
|
|
76
|
+
|
|
77
|
+
# Get raw JSON output
|
|
78
|
+
cortex query "Project status" --json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Options:
|
|
82
|
+
- `<question>` - Natural language query (required)
|
|
83
|
+
- `--filters <json>` - JSON filter object
|
|
84
|
+
- `--time-range <days>` - Limit to recent N days
|
|
85
|
+
- `--max-results <n>` - Maximum results (default: 10)
|
|
86
|
+
- `--user-email <email>` - User email for access-scoped queries
|
|
87
|
+
- `--json` - Output raw JSON
|
|
88
|
+
|
|
89
|
+
### `cortex whoami`
|
|
90
|
+
|
|
91
|
+
Get user context (teams, permissions, org info).
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
cortex whoami alice@company.com
|
|
95
|
+
cortex whoami alice@company.com --json
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Options:
|
|
99
|
+
- `<email>` - User email address (required)
|
|
100
|
+
- `--json` - Output raw JSON
|
|
101
|
+
|
|
102
|
+
### `cortex share`
|
|
103
|
+
|
|
104
|
+
Share a document with another user. The document appears in the recipient's "Shared with Me" at `/personal/shared`.
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
cortex share transcript_123 --from alice@co.com --to bob@co.com --name "Product Sync"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Options:
|
|
111
|
+
- `<document-id>` - External ID of the document (required)
|
|
112
|
+
- `--from <email>` - Sharer's email (required)
|
|
113
|
+
- `--to <email>` - Recipient's email (required)
|
|
114
|
+
- `-n, --name <name>` - Document display name
|
|
115
|
+
- `-c, --content <text>` - Document content
|
|
116
|
+
- `-u, --url <url>` - External URL
|
|
117
|
+
- `--metadata <json>` - JSON metadata object
|
|
118
|
+
|
|
119
|
+
### `cortex users`
|
|
120
|
+
|
|
121
|
+
List organization users.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
cortex users
|
|
125
|
+
cortex users --exclude alice@co.com
|
|
126
|
+
cortex users --json
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Options:
|
|
130
|
+
- `--exclude <email>` - Exclude an email from results
|
|
131
|
+
- `--json` - Output raw JSON
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Project Management Commands
|
|
136
|
+
|
|
137
|
+
### `cortex init`
|
|
138
|
+
|
|
139
|
+
Initialize a new Cortex tool project.
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
cortex init
|
|
143
|
+
cortex init --name my-tool --description "My awesome tool"
|
|
144
|
+
cortex init -y # Use defaults without prompts
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Creates:
|
|
148
|
+
- `cortex.yaml` - Tool manifest
|
|
149
|
+
- `.env.example` - Environment variables template
|
|
150
|
+
- Basic directory structure
|
|
151
|
+
|
|
152
|
+
### `cortex validate`
|
|
153
|
+
|
|
154
|
+
Validate your `cortex.yaml` manifest.
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
cortex validate
|
|
158
|
+
cortex validate --file path/to/cortex.yaml
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### `cortex dev`
|
|
162
|
+
|
|
163
|
+
Start local development environment.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
cortex dev
|
|
167
|
+
cortex dev --port 8080
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### `cortex deploy`
|
|
171
|
+
|
|
172
|
+
Deploy your tool to Cortex platform.
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
cortex deploy
|
|
176
|
+
cortex deploy --api-url https://api.cortex.ai --api-key your-key
|
|
177
|
+
cortex deploy --dry-run
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### `cortex status`
|
|
181
|
+
|
|
182
|
+
Check tool registration and health status.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
cortex status
|
|
186
|
+
cortex status --api-url https://api.cortex.ai --api-key your-key
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## Access Scopes
|
|
192
|
+
|
|
193
|
+
| Scope | Who Can See | Cortex UI Location |
|
|
194
|
+
|-------|-------------|-------------------|
|
|
195
|
+
| `global` | Everyone in organization | Organization knowledge base |
|
|
196
|
+
| `team` | Specified team members | Team knowledge base |
|
|
197
|
+
| `personal` | Only the creator | `/personal/transcripts` |
|
|
198
|
+
| Shared via `cortex share` | Recipient | `/personal/shared` |
|
|
199
|
+
|
|
200
|
+
## Manifest Format (cortex.yaml)
|
|
201
|
+
|
|
202
|
+
```yaml
|
|
203
|
+
name: my-tool
|
|
204
|
+
display_name: My Tool
|
|
205
|
+
description: A tool that does awesome things
|
|
206
|
+
version: 1.0.0
|
|
207
|
+
|
|
208
|
+
documents:
|
|
209
|
+
- my_document_type
|
|
210
|
+
|
|
211
|
+
icon: puzzle
|
|
212
|
+
ui:
|
|
213
|
+
embed_path: /
|
|
214
|
+
menu:
|
|
215
|
+
label: My Tool
|
|
216
|
+
position: tools
|
|
217
|
+
|
|
218
|
+
build:
|
|
219
|
+
backend:
|
|
220
|
+
dockerfile: backend/Dockerfile
|
|
221
|
+
port: 8000
|
|
222
|
+
health_check: /health
|
|
223
|
+
frontend:
|
|
224
|
+
dockerfile: frontend/Dockerfile
|
|
225
|
+
port: 3000
|
|
226
|
+
|
|
227
|
+
secrets:
|
|
228
|
+
- MY_API_KEY
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## License
|
|
232
|
+
|
|
233
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,753 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __defProp = Object.defineProperty;
|
|
5
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
8
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
18
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
19
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
20
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
21
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
22
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
23
|
+
mod
|
|
24
|
+
));
|
|
25
|
+
|
|
26
|
+
// src/index.ts
|
|
27
|
+
var import_commander = require("commander");
|
|
28
|
+
var import_chalk12 = __toESM(require("chalk"));
|
|
29
|
+
|
|
30
|
+
// src/commands/init.ts
|
|
31
|
+
var fs2 = __toESM(require("fs"));
|
|
32
|
+
var path2 = __toESM(require("path"));
|
|
33
|
+
var import_chalk = __toESM(require("chalk"));
|
|
34
|
+
var import_inquirer = __toESM(require("inquirer"));
|
|
35
|
+
var import_ora = __toESM(require("ora"));
|
|
36
|
+
|
|
37
|
+
// src/utils/manifest.ts
|
|
38
|
+
var fs = __toESM(require("fs"));
|
|
39
|
+
var path = __toESM(require("path"));
|
|
40
|
+
var yaml = __toESM(require("js-yaml"));
|
|
41
|
+
function loadManifest(filePath = "cortex.yaml") {
|
|
42
|
+
const fullPath = path.resolve(process.cwd(), filePath);
|
|
43
|
+
if (!fs.existsSync(fullPath)) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const content = fs.readFileSync(fullPath, "utf-8");
|
|
48
|
+
const manifest = yaml.load(content);
|
|
49
|
+
return manifest;
|
|
50
|
+
} catch (error) {
|
|
51
|
+
throw new Error(`Failed to parse ${filePath}: ${error}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function validateManifest(manifest) {
|
|
55
|
+
const errors = [];
|
|
56
|
+
if (!manifest.name) {
|
|
57
|
+
errors.push({ field: "name", message: "Tool name is required" });
|
|
58
|
+
} else if (!/^[a-z0-9-]+$/.test(manifest.name)) {
|
|
59
|
+
errors.push({
|
|
60
|
+
field: "name",
|
|
61
|
+
message: "Tool name must be lowercase alphanumeric with hyphens only"
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (!manifest.display_name) {
|
|
65
|
+
errors.push({ field: "display_name", message: "Display name is required" });
|
|
66
|
+
}
|
|
67
|
+
if (!manifest.version) {
|
|
68
|
+
errors.push({ field: "version", message: "Version is required" });
|
|
69
|
+
} else if (!/^\d+\.\d+\.\d+$/.test(manifest.version)) {
|
|
70
|
+
errors.push({
|
|
71
|
+
field: "version",
|
|
72
|
+
message: "Version must be semver format (e.g., 1.0.0)"
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (!manifest.documents || !Array.isArray(manifest.documents)) {
|
|
76
|
+
errors.push({
|
|
77
|
+
field: "documents",
|
|
78
|
+
message: "Documents array is required (list of document types this tool produces)"
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
if (manifest.build) {
|
|
82
|
+
if (manifest.build.backend) {
|
|
83
|
+
if (manifest.build.backend.port && typeof manifest.build.backend.port !== "number") {
|
|
84
|
+
errors.push({ field: "build.backend.port", message: "Port must be a number" });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (manifest.build.frontend) {
|
|
88
|
+
if (manifest.build.frontend.port && typeof manifest.build.frontend.port !== "number") {
|
|
89
|
+
errors.push({ field: "build.frontend.port", message: "Port must be a number" });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return errors;
|
|
94
|
+
}
|
|
95
|
+
function createDefaultManifest(name, displayName, description) {
|
|
96
|
+
return {
|
|
97
|
+
name,
|
|
98
|
+
display_name: displayName,
|
|
99
|
+
description: description || `${displayName} tool for Cortex platform`,
|
|
100
|
+
version: "1.0.0",
|
|
101
|
+
documents: ["document"],
|
|
102
|
+
icon: "puzzle",
|
|
103
|
+
ui: {
|
|
104
|
+
embed_path: "/",
|
|
105
|
+
menu: {
|
|
106
|
+
label: displayName,
|
|
107
|
+
position: "tools"
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
build: {
|
|
111
|
+
backend: {
|
|
112
|
+
dockerfile: "backend/Dockerfile",
|
|
113
|
+
port: 8e3,
|
|
114
|
+
health_check: "/health"
|
|
115
|
+
},
|
|
116
|
+
frontend: {
|
|
117
|
+
dockerfile: "frontend/Dockerfile",
|
|
118
|
+
port: 3e3
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
secrets: []
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function writeManifest(manifest, filePath = "cortex.yaml") {
|
|
125
|
+
const fullPath = path.resolve(process.cwd(), filePath);
|
|
126
|
+
const content = yaml.dump(manifest, {
|
|
127
|
+
indent: 2,
|
|
128
|
+
lineWidth: 100,
|
|
129
|
+
noRefs: true
|
|
130
|
+
});
|
|
131
|
+
fs.writeFileSync(fullPath, content, "utf-8");
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/commands/init.ts
|
|
135
|
+
async function initCommand(options) {
|
|
136
|
+
console.log(import_chalk.default.cyan("\n Cortex Tool Initializer\n"));
|
|
137
|
+
if (loadManifest()) {
|
|
138
|
+
console.log(import_chalk.default.yellow(" cortex.yaml already exists in this directory."));
|
|
139
|
+
const { overwrite } = await import_inquirer.default.prompt([
|
|
140
|
+
{
|
|
141
|
+
type: "confirm",
|
|
142
|
+
name: "overwrite",
|
|
143
|
+
message: "Overwrite existing cortex.yaml?",
|
|
144
|
+
default: false
|
|
145
|
+
}
|
|
146
|
+
]);
|
|
147
|
+
if (!overwrite) {
|
|
148
|
+
console.log(import_chalk.default.gray(" Initialization cancelled."));
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
let name;
|
|
153
|
+
let displayName;
|
|
154
|
+
let description;
|
|
155
|
+
let documentTypes;
|
|
156
|
+
if (options.yes) {
|
|
157
|
+
const dirName = path2.basename(process.cwd());
|
|
158
|
+
name = options.name || dirName.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
159
|
+
displayName = name.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
160
|
+
description = options.description || `${displayName} tool for Cortex`;
|
|
161
|
+
documentTypes = ["document"];
|
|
162
|
+
} else {
|
|
163
|
+
const answers = await import_inquirer.default.prompt([
|
|
164
|
+
{
|
|
165
|
+
type: "input",
|
|
166
|
+
name: "name",
|
|
167
|
+
message: "Tool name (lowercase, hyphens only):",
|
|
168
|
+
default: options.name || path2.basename(process.cwd()).toLowerCase().replace(/[^a-z0-9-]/g, "-"),
|
|
169
|
+
validate: (input) => /^[a-z0-9-]+$/.test(input) || "Name must be lowercase alphanumeric with hyphens"
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
type: "input",
|
|
173
|
+
name: "displayName",
|
|
174
|
+
message: "Display name:",
|
|
175
|
+
default: (answers2) => answers2.name.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ")
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
type: "input",
|
|
179
|
+
name: "description",
|
|
180
|
+
message: "Description:",
|
|
181
|
+
default: options.description
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
type: "input",
|
|
185
|
+
name: "documentTypes",
|
|
186
|
+
message: "Document types (comma-separated):",
|
|
187
|
+
default: "document"
|
|
188
|
+
}
|
|
189
|
+
]);
|
|
190
|
+
name = answers.name;
|
|
191
|
+
displayName = answers.displayName;
|
|
192
|
+
description = answers.description;
|
|
193
|
+
documentTypes = answers.documentTypes.split(",").map((t) => t.trim());
|
|
194
|
+
}
|
|
195
|
+
const spinner = (0, import_ora.default)("Creating cortex.yaml...").start();
|
|
196
|
+
try {
|
|
197
|
+
const manifest = createDefaultManifest(name, displayName, description);
|
|
198
|
+
manifest.documents = documentTypes;
|
|
199
|
+
writeManifest(manifest);
|
|
200
|
+
spinner.succeed("Created cortex.yaml");
|
|
201
|
+
const dirs = ["backend", "frontend"];
|
|
202
|
+
for (const dir of dirs) {
|
|
203
|
+
if (!fs2.existsSync(dir)) {
|
|
204
|
+
fs2.mkdirSync(dir, { recursive: true });
|
|
205
|
+
console.log(import_chalk.default.gray(` Created ${dir}/`));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
const envExample = `# Cortex Integration
|
|
209
|
+
CORTEX_ENABLED=false
|
|
210
|
+
CORTEX_API_URL=
|
|
211
|
+
CORTEX_API_KEY=
|
|
212
|
+
CORTEX_TOOL_ID=${name}
|
|
213
|
+
CORTEX_JWT_PUBLIC_KEY=
|
|
214
|
+
`;
|
|
215
|
+
if (!fs2.existsSync(".env.example")) {
|
|
216
|
+
fs2.writeFileSync(".env.example", envExample, "utf-8");
|
|
217
|
+
console.log(import_chalk.default.gray(" Created .env.example"));
|
|
218
|
+
}
|
|
219
|
+
console.log(import_chalk.default.green("\n Tool initialized successfully!\n"));
|
|
220
|
+
console.log(import_chalk.default.gray(" Next steps:"));
|
|
221
|
+
console.log(import_chalk.default.gray(" 1. Edit cortex.yaml with your tool configuration"));
|
|
222
|
+
console.log(import_chalk.default.gray(" 2. Implement your backend and frontend"));
|
|
223
|
+
console.log(import_chalk.default.gray(" 3. Run `cortex validate` to check your manifest"));
|
|
224
|
+
console.log(import_chalk.default.gray(" 4. Run `cortex dev` to start local development\n"));
|
|
225
|
+
} catch (error) {
|
|
226
|
+
spinner.fail("Failed to create cortex.yaml");
|
|
227
|
+
console.error(import_chalk.default.red(` Error: ${error}`));
|
|
228
|
+
process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// src/commands/validate.ts
|
|
233
|
+
var import_chalk2 = __toESM(require("chalk"));
|
|
234
|
+
async function validateCommand(options) {
|
|
235
|
+
const filePath = options.file || "cortex.yaml";
|
|
236
|
+
console.log(import_chalk2.default.cyan(`
|
|
237
|
+
Validating ${filePath}...
|
|
238
|
+
`));
|
|
239
|
+
const manifest = loadManifest(filePath);
|
|
240
|
+
if (!manifest) {
|
|
241
|
+
console.log(import_chalk2.default.red(` Error: ${filePath} not found.`));
|
|
242
|
+
console.log(import_chalk2.default.gray(" Run `cortex init` to create a manifest.\n"));
|
|
243
|
+
process.exit(1);
|
|
244
|
+
}
|
|
245
|
+
const errors = validateManifest(manifest);
|
|
246
|
+
if (errors.length === 0) {
|
|
247
|
+
console.log(import_chalk2.default.green(" \u2713 Manifest is valid!\n"));
|
|
248
|
+
console.log(import_chalk2.default.gray(" Summary:"));
|
|
249
|
+
console.log(import_chalk2.default.gray(` Name: ${manifest.name}`));
|
|
250
|
+
console.log(import_chalk2.default.gray(` Display Name: ${manifest.display_name}`));
|
|
251
|
+
console.log(import_chalk2.default.gray(` Version: ${manifest.version}`));
|
|
252
|
+
console.log(import_chalk2.default.gray(` Documents: ${manifest.documents.join(", ")}`));
|
|
253
|
+
if (manifest.build?.backend) {
|
|
254
|
+
console.log(import_chalk2.default.gray(` Backend Port: ${manifest.build.backend.port}`));
|
|
255
|
+
}
|
|
256
|
+
if (manifest.build?.frontend) {
|
|
257
|
+
console.log(import_chalk2.default.gray(` Frontend Port: ${manifest.build.frontend.port}`));
|
|
258
|
+
}
|
|
259
|
+
console.log("");
|
|
260
|
+
process.exit(0);
|
|
261
|
+
} else {
|
|
262
|
+
console.log(import_chalk2.default.red(` \u2717 Found ${errors.length} error(s):
|
|
263
|
+
`));
|
|
264
|
+
for (const error of errors) {
|
|
265
|
+
console.log(import_chalk2.default.red(` \u2022 ${error.field}: ${error.message}`));
|
|
266
|
+
}
|
|
267
|
+
console.log("");
|
|
268
|
+
process.exit(1);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// src/commands/dev.ts
|
|
273
|
+
var import_chalk3 = __toESM(require("chalk"));
|
|
274
|
+
var import_ora2 = __toESM(require("ora"));
|
|
275
|
+
async function devCommand(options) {
|
|
276
|
+
console.log(import_chalk3.default.cyan("\n Cortex Development Server\n"));
|
|
277
|
+
const manifest = loadManifest();
|
|
278
|
+
if (!manifest) {
|
|
279
|
+
console.log(import_chalk3.default.red(" Error: cortex.yaml not found."));
|
|
280
|
+
console.log(import_chalk3.default.gray(" Run `cortex init` first.\n"));
|
|
281
|
+
process.exit(1);
|
|
282
|
+
}
|
|
283
|
+
const errors = validateManifest(manifest);
|
|
284
|
+
if (errors.length > 0) {
|
|
285
|
+
console.log(import_chalk3.default.red(" Error: Invalid manifest. Run `cortex validate` for details.\n"));
|
|
286
|
+
process.exit(1);
|
|
287
|
+
}
|
|
288
|
+
const port = options.port || String(manifest.build?.backend?.port || 8e3);
|
|
289
|
+
console.log(import_chalk3.default.gray(` Tool: ${manifest.display_name}`));
|
|
290
|
+
console.log(import_chalk3.default.gray(` Version: ${manifest.version}`));
|
|
291
|
+
console.log("");
|
|
292
|
+
const spinner = (0, import_ora2.default)("Starting development environment...").start();
|
|
293
|
+
setTimeout(() => {
|
|
294
|
+
spinner.succeed("Development environment ready");
|
|
295
|
+
console.log(import_chalk3.default.green("\n Local development server started!\n"));
|
|
296
|
+
console.log(import_chalk3.default.gray(" Environment variables set:"));
|
|
297
|
+
console.log(import_chalk3.default.gray(` CORTEX_ENABLED=true`));
|
|
298
|
+
console.log(import_chalk3.default.gray(` CORTEX_API_URL=http://localhost:${port}/api/tools`));
|
|
299
|
+
console.log(import_chalk3.default.gray(` CORTEX_API_KEY=dev-key-${manifest.name}`));
|
|
300
|
+
console.log(import_chalk3.default.gray(` CORTEX_TOOL_ID=${manifest.name}`));
|
|
301
|
+
console.log("");
|
|
302
|
+
console.log(import_chalk3.default.gray(" To start your tool:"));
|
|
303
|
+
console.log(import_chalk3.default.gray(" 1. Set the environment variables above in your .env"));
|
|
304
|
+
console.log(import_chalk3.default.gray(" 2. Start your backend and frontend services"));
|
|
305
|
+
console.log(import_chalk3.default.gray(" 3. Your tool will connect to the local Cortex gateway"));
|
|
306
|
+
console.log("");
|
|
307
|
+
console.log(import_chalk3.default.cyan(" Press Ctrl+C to stop\n"));
|
|
308
|
+
}, 1e3);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// src/commands/deploy.ts
|
|
312
|
+
var import_chalk4 = __toESM(require("chalk"));
|
|
313
|
+
var import_ora3 = __toESM(require("ora"));
|
|
314
|
+
var import_inquirer2 = __toESM(require("inquirer"));
|
|
315
|
+
async function deployCommand(options) {
|
|
316
|
+
console.log(import_chalk4.default.cyan("\n Cortex Tool Deployment\n"));
|
|
317
|
+
const manifest = loadManifest();
|
|
318
|
+
if (!manifest) {
|
|
319
|
+
console.log(import_chalk4.default.red(" Error: cortex.yaml not found."));
|
|
320
|
+
console.log(import_chalk4.default.gray(" Run `cortex init` first.\n"));
|
|
321
|
+
process.exit(1);
|
|
322
|
+
}
|
|
323
|
+
const errors = validateManifest(manifest);
|
|
324
|
+
if (errors.length > 0) {
|
|
325
|
+
console.log(import_chalk4.default.red(" Error: Invalid manifest. Run `cortex validate` for details.\n"));
|
|
326
|
+
process.exit(1);
|
|
327
|
+
}
|
|
328
|
+
let apiUrl = options.apiUrl || process.env.CORTEX_API_URL;
|
|
329
|
+
let apiKey = options.apiKey || process.env.CORTEX_API_KEY;
|
|
330
|
+
if (!apiUrl || !apiKey) {
|
|
331
|
+
console.log(import_chalk4.default.yellow(" Cortex API credentials not provided.\n"));
|
|
332
|
+
const answers = await import_inquirer2.default.prompt([
|
|
333
|
+
{
|
|
334
|
+
type: "input",
|
|
335
|
+
name: "apiUrl",
|
|
336
|
+
message: "Cortex API URL:",
|
|
337
|
+
default: apiUrl || "https://api.cortex.ai",
|
|
338
|
+
when: !apiUrl
|
|
339
|
+
},
|
|
340
|
+
{
|
|
341
|
+
type: "password",
|
|
342
|
+
name: "apiKey",
|
|
343
|
+
message: "Cortex API Key:",
|
|
344
|
+
when: !apiKey
|
|
345
|
+
}
|
|
346
|
+
]);
|
|
347
|
+
apiUrl = apiUrl || answers.apiUrl;
|
|
348
|
+
apiKey = apiKey || answers.apiKey;
|
|
349
|
+
}
|
|
350
|
+
if (!apiUrl || !apiKey) {
|
|
351
|
+
console.log(import_chalk4.default.red(" Error: API URL and API Key are required.\n"));
|
|
352
|
+
process.exit(1);
|
|
353
|
+
}
|
|
354
|
+
console.log(import_chalk4.default.gray(` Tool: ${manifest.display_name} (${manifest.name})`));
|
|
355
|
+
console.log(import_chalk4.default.gray(` Version: ${manifest.version}`));
|
|
356
|
+
console.log(import_chalk4.default.gray(` Documents: ${manifest.documents.join(", ")}`));
|
|
357
|
+
console.log(import_chalk4.default.gray(` Target: ${apiUrl}`));
|
|
358
|
+
console.log("");
|
|
359
|
+
if (options.dryRun) {
|
|
360
|
+
console.log(import_chalk4.default.yellow(" Dry run mode - no changes will be made.\n"));
|
|
361
|
+
console.log(import_chalk4.default.gray(" Would deploy:"));
|
|
362
|
+
console.log(import_chalk4.default.gray(` \u2022 Register tool: ${manifest.name}`));
|
|
363
|
+
console.log(import_chalk4.default.gray(` \u2022 Document types: ${manifest.documents.join(", ")}`));
|
|
364
|
+
if (manifest.build?.backend) {
|
|
365
|
+
console.log(import_chalk4.default.gray(` \u2022 Backend: ${manifest.build.backend.dockerfile}`));
|
|
366
|
+
}
|
|
367
|
+
if (manifest.build?.frontend) {
|
|
368
|
+
console.log(import_chalk4.default.gray(` \u2022 Frontend: ${manifest.build.frontend.dockerfile}`));
|
|
369
|
+
}
|
|
370
|
+
console.log("");
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const { confirm } = await import_inquirer2.default.prompt([
|
|
374
|
+
{
|
|
375
|
+
type: "confirm",
|
|
376
|
+
name: "confirm",
|
|
377
|
+
message: "Deploy to Cortex platform?",
|
|
378
|
+
default: true
|
|
379
|
+
}
|
|
380
|
+
]);
|
|
381
|
+
if (!confirm) {
|
|
382
|
+
console.log(import_chalk4.default.gray(" Deployment cancelled.\n"));
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
385
|
+
const spinner = (0, import_ora3.default)("Deploying to Cortex...").start();
|
|
386
|
+
try {
|
|
387
|
+
await new Promise((resolve2) => setTimeout(resolve2, 2e3));
|
|
388
|
+
spinner.succeed("Deployment complete!");
|
|
389
|
+
console.log(import_chalk4.default.green("\n Tool deployed successfully!\n"));
|
|
390
|
+
console.log(import_chalk4.default.gray(" Your tool is now available in Cortex."));
|
|
391
|
+
console.log(import_chalk4.default.gray(` Tool URL: ${apiUrl}/tools/${manifest.name}`));
|
|
392
|
+
console.log("");
|
|
393
|
+
} catch (error) {
|
|
394
|
+
spinner.fail("Deployment failed");
|
|
395
|
+
console.error(import_chalk4.default.red(` Error: ${error}`));
|
|
396
|
+
process.exit(1);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// src/commands/status.ts
|
|
401
|
+
var import_chalk5 = __toESM(require("chalk"));
|
|
402
|
+
var import_ora4 = __toESM(require("ora"));
|
|
403
|
+
async function statusCommand(options) {
|
|
404
|
+
console.log(import_chalk5.default.cyan("\n Cortex Tool Status\n"));
|
|
405
|
+
const manifest = loadManifest();
|
|
406
|
+
if (!manifest) {
|
|
407
|
+
console.log(import_chalk5.default.yellow(" No cortex.yaml found - showing general status.\n"));
|
|
408
|
+
} else {
|
|
409
|
+
console.log(import_chalk5.default.gray(` Tool: ${manifest.display_name} (${manifest.name})`));
|
|
410
|
+
console.log(import_chalk5.default.gray(` Version: ${manifest.version}`));
|
|
411
|
+
console.log("");
|
|
412
|
+
}
|
|
413
|
+
const apiUrl = options.apiUrl || process.env.CORTEX_API_URL;
|
|
414
|
+
const apiKey = options.apiKey || process.env.CORTEX_API_KEY;
|
|
415
|
+
if (!apiUrl || !apiKey) {
|
|
416
|
+
console.log(import_chalk5.default.gray(" Local Status:"));
|
|
417
|
+
console.log(import_chalk5.default.gray(" cortex.yaml: " + (manifest ? import_chalk5.default.green("\u2713 Found") : import_chalk5.default.red("\u2717 Not found"))));
|
|
418
|
+
if (manifest) {
|
|
419
|
+
const hasBackend = manifest.build?.backend?.dockerfile && require("fs").existsSync(manifest.build.backend.dockerfile.split("/")[0]);
|
|
420
|
+
const hasFrontend = manifest.build?.frontend?.dockerfile && require("fs").existsSync(manifest.build.frontend.dockerfile.split("/")[0]);
|
|
421
|
+
console.log(
|
|
422
|
+
import_chalk5.default.gray(" Backend: " + (hasBackend ? import_chalk5.default.green("\u2713 Found") : import_chalk5.default.yellow("\u25CB Not found")))
|
|
423
|
+
);
|
|
424
|
+
console.log(
|
|
425
|
+
import_chalk5.default.gray(" Frontend: " + (hasFrontend ? import_chalk5.default.green("\u2713 Found") : import_chalk5.default.yellow("\u25CB Not found")))
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
console.log("");
|
|
429
|
+
console.log(import_chalk5.default.gray(" To check remote status, provide --api-url and --api-key"));
|
|
430
|
+
console.log(import_chalk5.default.gray(" or set CORTEX_API_URL and CORTEX_API_KEY environment variables.\n"));
|
|
431
|
+
return;
|
|
432
|
+
}
|
|
433
|
+
const spinner = (0, import_ora4.default)("Checking status...").start();
|
|
434
|
+
try {
|
|
435
|
+
await new Promise((resolve2) => setTimeout(resolve2, 1e3));
|
|
436
|
+
spinner.stop();
|
|
437
|
+
console.log(import_chalk5.default.gray(" Remote Status:"));
|
|
438
|
+
console.log(import_chalk5.default.gray(` API: ${apiUrl}`));
|
|
439
|
+
if (manifest) {
|
|
440
|
+
console.log(import_chalk5.default.gray(` Registration: ${import_chalk5.default.green("\u2713 Registered")}`));
|
|
441
|
+
console.log(import_chalk5.default.gray(` Status: ${import_chalk5.default.green("Active")}`));
|
|
442
|
+
console.log(import_chalk5.default.gray(` Last Deployed: 2024-01-15 10:30:00`));
|
|
443
|
+
console.log(import_chalk5.default.gray(` Documents Pushed: 1,234`));
|
|
444
|
+
console.log(import_chalk5.default.gray(` Queries Served: 5,678`));
|
|
445
|
+
} else {
|
|
446
|
+
console.log(import_chalk5.default.gray(` Connection: ${import_chalk5.default.green("\u2713 Connected")}`));
|
|
447
|
+
}
|
|
448
|
+
console.log("");
|
|
449
|
+
} catch (error) {
|
|
450
|
+
spinner.fail("Failed to check status");
|
|
451
|
+
console.error(import_chalk5.default.red(` Error: ${error}`));
|
|
452
|
+
console.log("");
|
|
453
|
+
process.exit(1);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// src/commands/push.ts
|
|
458
|
+
var import_chalk7 = __toESM(require("chalk"));
|
|
459
|
+
var import_ora5 = __toESM(require("ora"));
|
|
460
|
+
var fs3 = __toESM(require("fs"));
|
|
461
|
+
|
|
462
|
+
// src/utils/api.ts
|
|
463
|
+
var import_chalk6 = __toESM(require("chalk"));
|
|
464
|
+
function resolveConfig(options) {
|
|
465
|
+
const apiUrl = options.apiUrl || process.env.CORTEX_API_URL;
|
|
466
|
+
const apiKey = options.apiKey || process.env.CORTEX_API_KEY;
|
|
467
|
+
const toolId = options.toolId || process.env.CORTEX_TOOL_ID || "";
|
|
468
|
+
if (!apiUrl || !apiKey) {
|
|
469
|
+
console.log(import_chalk6.default.red("\n Error: Missing API credentials.\n"));
|
|
470
|
+
console.log(import_chalk6.default.gray(" Provide --api-url and --api-key options, or set environment variables:"));
|
|
471
|
+
console.log(import_chalk6.default.gray(" CORTEX_API_URL=https://your-cortex-server.com"));
|
|
472
|
+
console.log(import_chalk6.default.gray(" CORTEX_API_KEY=your-api-key"));
|
|
473
|
+
console.log(import_chalk6.default.gray(" CORTEX_TOOL_ID=your-tool-id\n"));
|
|
474
|
+
return null;
|
|
475
|
+
}
|
|
476
|
+
return { apiUrl: apiUrl.replace(/\/$/, ""), apiKey, toolId };
|
|
477
|
+
}
|
|
478
|
+
async function apiRequest(config, method, path3, body) {
|
|
479
|
+
const url = `${config.apiUrl}${path3}`;
|
|
480
|
+
const headers = {
|
|
481
|
+
"Content-Type": "application/json",
|
|
482
|
+
"X-API-Key": config.apiKey
|
|
483
|
+
};
|
|
484
|
+
if (config.toolId) {
|
|
485
|
+
headers["X-Cortex-Tool-ID"] = config.toolId;
|
|
486
|
+
}
|
|
487
|
+
const response = await fetch(url, {
|
|
488
|
+
method,
|
|
489
|
+
headers,
|
|
490
|
+
body: body ? JSON.stringify(body) : void 0
|
|
491
|
+
});
|
|
492
|
+
if (!response.ok) {
|
|
493
|
+
const errorText = await response.text();
|
|
494
|
+
throw new Error(`API error (${response.status}): ${errorText}`);
|
|
495
|
+
}
|
|
496
|
+
const text = await response.text();
|
|
497
|
+
return text ? JSON.parse(text) : {};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// src/commands/push.ts
|
|
501
|
+
async function pushCommand(id, options) {
|
|
502
|
+
const config = resolveConfig(options);
|
|
503
|
+
if (!config) process.exit(1);
|
|
504
|
+
let content;
|
|
505
|
+
if (options.file) {
|
|
506
|
+
if (!fs3.existsSync(options.file)) {
|
|
507
|
+
console.log(import_chalk7.default.red(`
|
|
508
|
+
Error: File not found: ${options.file}
|
|
509
|
+
`));
|
|
510
|
+
process.exit(1);
|
|
511
|
+
}
|
|
512
|
+
content = fs3.readFileSync(options.file, "utf-8");
|
|
513
|
+
} else {
|
|
514
|
+
console.log(import_chalk7.default.red("\n Error: --file <path> is required to provide document content.\n"));
|
|
515
|
+
process.exit(1);
|
|
516
|
+
}
|
|
517
|
+
let metadata;
|
|
518
|
+
if (options.metadata) {
|
|
519
|
+
try {
|
|
520
|
+
metadata = JSON.parse(options.metadata);
|
|
521
|
+
} catch {
|
|
522
|
+
console.log(import_chalk7.default.red("\n Error: --metadata must be valid JSON.\n"));
|
|
523
|
+
process.exit(1);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
const teamIds = options.teams ? options.teams.split(",").map((t) => t.trim()) : void 0;
|
|
527
|
+
const spinner = (0, import_ora5.default)("Pushing document to Cortex...").start();
|
|
528
|
+
try {
|
|
529
|
+
const result = await apiRequest(
|
|
530
|
+
config,
|
|
531
|
+
"POST",
|
|
532
|
+
"/api/tools/documents",
|
|
533
|
+
{
|
|
534
|
+
external_id: id,
|
|
535
|
+
document_type: options.type,
|
|
536
|
+
content,
|
|
537
|
+
name: options.name || id,
|
|
538
|
+
external_url: options.url,
|
|
539
|
+
access_scope: options.scope || "global",
|
|
540
|
+
scope_team_ids: teamIds,
|
|
541
|
+
metadata
|
|
542
|
+
}
|
|
543
|
+
);
|
|
544
|
+
spinner.succeed("Document pushed successfully");
|
|
545
|
+
console.log(import_chalk7.default.gray(`
|
|
546
|
+
ID: ${result.id || id}`));
|
|
547
|
+
console.log(import_chalk7.default.gray(` Status: ${result.status || "ok"}`));
|
|
548
|
+
console.log(import_chalk7.default.gray(` Type: ${options.type}`));
|
|
549
|
+
console.log(import_chalk7.default.gray(` Scope: ${options.scope || "global"}
|
|
550
|
+
`));
|
|
551
|
+
} catch (error) {
|
|
552
|
+
spinner.fail("Failed to push document");
|
|
553
|
+
console.error(import_chalk7.default.red(` ${error}
|
|
554
|
+
`));
|
|
555
|
+
process.exit(1);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// src/commands/query.ts
|
|
560
|
+
var import_chalk8 = __toESM(require("chalk"));
|
|
561
|
+
var import_ora6 = __toESM(require("ora"));
|
|
562
|
+
async function queryCommand(question, options) {
|
|
563
|
+
const config = resolveConfig(options);
|
|
564
|
+
if (!config) process.exit(1);
|
|
565
|
+
let filters;
|
|
566
|
+
if (options.filters) {
|
|
567
|
+
try {
|
|
568
|
+
filters = JSON.parse(options.filters);
|
|
569
|
+
} catch {
|
|
570
|
+
console.log(import_chalk8.default.red("\n Error: --filters must be valid JSON.\n"));
|
|
571
|
+
process.exit(1);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
const spinner = (0, import_ora6.default)("Querying Cortex...").start();
|
|
575
|
+
try {
|
|
576
|
+
const result = await apiRequest(config, "POST", "/api/tools/query", {
|
|
577
|
+
query: question,
|
|
578
|
+
filters,
|
|
579
|
+
time_range_days: options.timeRange ? parseInt(options.timeRange, 10) : void 0,
|
|
580
|
+
max_results: options.maxResults ? parseInt(options.maxResults, 10) : 10,
|
|
581
|
+
user_email: options.userEmail
|
|
582
|
+
});
|
|
583
|
+
spinner.stop();
|
|
584
|
+
if (options.json) {
|
|
585
|
+
console.log(JSON.stringify(result, null, 2));
|
|
586
|
+
return;
|
|
587
|
+
}
|
|
588
|
+
console.log(import_chalk8.default.cyan("\n Answer:\n"));
|
|
589
|
+
console.log(` ${result.answer}
|
|
590
|
+
`);
|
|
591
|
+
if (result.sources && result.sources.length > 0) {
|
|
592
|
+
console.log(import_chalk8.default.gray(` Sources (${result.sources.length}):`));
|
|
593
|
+
for (const source of result.sources) {
|
|
594
|
+
console.log(import_chalk8.default.gray(` \u2022 [${source.type}] ${source.name}`));
|
|
595
|
+
if (source.excerpt) {
|
|
596
|
+
console.log(import_chalk8.default.gray(` ${source.excerpt.substring(0, 120)}...`));
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
console.log("");
|
|
601
|
+
} catch (error) {
|
|
602
|
+
spinner.fail("Query failed");
|
|
603
|
+
console.error(import_chalk8.default.red(` ${error}
|
|
604
|
+
`));
|
|
605
|
+
process.exit(1);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// src/commands/whoami.ts
|
|
610
|
+
var import_chalk9 = __toESM(require("chalk"));
|
|
611
|
+
var import_ora7 = __toESM(require("ora"));
|
|
612
|
+
async function whoamiCommand(email, options) {
|
|
613
|
+
const config = resolveConfig(options);
|
|
614
|
+
if (!config) process.exit(1);
|
|
615
|
+
const spinner = (0, import_ora7.default)(`Looking up ${email}...`).start();
|
|
616
|
+
try {
|
|
617
|
+
const user = await apiRequest(config, "GET", `/api/tools/context/${encodeURIComponent(email)}`);
|
|
618
|
+
spinner.stop();
|
|
619
|
+
if (options.json) {
|
|
620
|
+
console.log(JSON.stringify(user, null, 2));
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
console.log(import_chalk9.default.cyan("\n User Context:\n"));
|
|
624
|
+
console.log(import_chalk9.default.gray(` Email: ${user.email}`));
|
|
625
|
+
if (user.full_name) console.log(import_chalk9.default.gray(` Name: ${user.full_name}`));
|
|
626
|
+
if (user.org_name) console.log(import_chalk9.default.gray(` Org: ${user.org_name}`));
|
|
627
|
+
if (user.role) console.log(import_chalk9.default.gray(` Role: ${user.role}`));
|
|
628
|
+
if (user.teams && user.teams.length > 0) {
|
|
629
|
+
console.log(import_chalk9.default.gray(` Teams:`));
|
|
630
|
+
for (const team of user.teams) {
|
|
631
|
+
console.log(import_chalk9.default.gray(` \u2022 ${team.name} (${team.id})`));
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
if (user.permissions && user.permissions.length > 0) {
|
|
635
|
+
console.log(import_chalk9.default.gray(` Permissions: ${user.permissions.join(", ")}`));
|
|
636
|
+
}
|
|
637
|
+
console.log("");
|
|
638
|
+
} catch (error) {
|
|
639
|
+
spinner.fail("Failed to get user context");
|
|
640
|
+
if (String(error).includes("404")) {
|
|
641
|
+
console.log(import_chalk9.default.yellow(` User ${email} not found in Cortex.
|
|
642
|
+
`));
|
|
643
|
+
} else {
|
|
644
|
+
console.error(import_chalk9.default.red(` ${error}
|
|
645
|
+
`));
|
|
646
|
+
}
|
|
647
|
+
process.exit(1);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
// src/commands/share.ts
|
|
652
|
+
var import_chalk10 = __toESM(require("chalk"));
|
|
653
|
+
var import_ora8 = __toESM(require("ora"));
|
|
654
|
+
async function shareCommand(documentId, options) {
|
|
655
|
+
const config = resolveConfig(options);
|
|
656
|
+
if (!config) process.exit(1);
|
|
657
|
+
if (!options.from || !options.to) {
|
|
658
|
+
console.log(import_chalk10.default.red("\n Error: --from and --to email addresses are required.\n"));
|
|
659
|
+
console.log(import_chalk10.default.gray(" Usage: cortex share <document-id> --from alice@co.com --to bob@co.com\n"));
|
|
660
|
+
process.exit(1);
|
|
661
|
+
}
|
|
662
|
+
let metadata;
|
|
663
|
+
if (options.metadata) {
|
|
664
|
+
try {
|
|
665
|
+
metadata = JSON.parse(options.metadata);
|
|
666
|
+
} catch {
|
|
667
|
+
console.log(import_chalk10.default.red("\n Error: --metadata must be valid JSON.\n"));
|
|
668
|
+
process.exit(1);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
const spinner = (0, import_ora8.default)(`Sharing document with ${options.to}...`).start();
|
|
672
|
+
try {
|
|
673
|
+
const result = await apiRequest(
|
|
674
|
+
config,
|
|
675
|
+
"POST",
|
|
676
|
+
"/api/tools/share-document-for-user",
|
|
677
|
+
{
|
|
678
|
+
document_external_id: documentId,
|
|
679
|
+
shared_by_email: options.from,
|
|
680
|
+
shared_with_email: options.to,
|
|
681
|
+
document_name: options.name,
|
|
682
|
+
content: options.content,
|
|
683
|
+
external_url: options.url,
|
|
684
|
+
metadata
|
|
685
|
+
}
|
|
686
|
+
);
|
|
687
|
+
spinner.succeed("Document shared successfully");
|
|
688
|
+
console.log(import_chalk10.default.gray(`
|
|
689
|
+
Document: ${documentId}`));
|
|
690
|
+
console.log(import_chalk10.default.gray(` From: ${options.from}`));
|
|
691
|
+
console.log(import_chalk10.default.gray(` To: ${options.to}`));
|
|
692
|
+
if (result.id) console.log(import_chalk10.default.gray(` Share ID: ${result.id}`));
|
|
693
|
+
console.log("");
|
|
694
|
+
} catch (error) {
|
|
695
|
+
spinner.fail("Failed to share document");
|
|
696
|
+
console.error(import_chalk10.default.red(` ${error}
|
|
697
|
+
`));
|
|
698
|
+
process.exit(1);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/commands/users.ts
|
|
703
|
+
var import_chalk11 = __toESM(require("chalk"));
|
|
704
|
+
var import_ora9 = __toESM(require("ora"));
|
|
705
|
+
async function usersCommand(options) {
|
|
706
|
+
const config = resolveConfig(options);
|
|
707
|
+
if (!config) process.exit(1);
|
|
708
|
+
const spinner = (0, import_ora9.default)("Fetching organization users...").start();
|
|
709
|
+
try {
|
|
710
|
+
const params = options.exclude ? `?exclude_email=${encodeURIComponent(options.exclude)}` : "";
|
|
711
|
+
const users = await apiRequest(config, "GET", `/api/tools/org-users-for-tool${params}`);
|
|
712
|
+
spinner.stop();
|
|
713
|
+
if (options.json) {
|
|
714
|
+
console.log(JSON.stringify(users, null, 2));
|
|
715
|
+
return;
|
|
716
|
+
}
|
|
717
|
+
console.log(import_chalk11.default.cyan(`
|
|
718
|
+
Organization Users (${users.length}):
|
|
719
|
+
`));
|
|
720
|
+
if (users.length === 0) {
|
|
721
|
+
console.log(import_chalk11.default.gray(" No users found.\n"));
|
|
722
|
+
return;
|
|
723
|
+
}
|
|
724
|
+
for (const user of users) {
|
|
725
|
+
console.log(import_chalk11.default.gray(` \u2022 ${user.full_name || "Unknown"} <${user.email}>`));
|
|
726
|
+
}
|
|
727
|
+
console.log("");
|
|
728
|
+
} catch (error) {
|
|
729
|
+
spinner.fail("Failed to fetch users");
|
|
730
|
+
console.error(import_chalk11.default.red(` ${error}
|
|
731
|
+
`));
|
|
732
|
+
process.exit(1);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
// src/index.ts
|
|
737
|
+
var program = new import_commander.Command();
|
|
738
|
+
program.name("cortex").description("CLI tool for Cortex platform developers").version("0.1.2");
|
|
739
|
+
program.command("init").description("Initialize a new Cortex tool project").option("-n, --name <name>", "Tool name").option("-d, --description <desc>", "Tool description").option("-y, --yes", "Skip prompts and use defaults").action(initCommand);
|
|
740
|
+
program.command("validate").description("Validate cortex.yaml manifest").option("-f, --file <path>", "Path to manifest file", "cortex.yaml").action(validateCommand);
|
|
741
|
+
program.command("dev").description("Start local development environment").option("-p, --port <port>", "API port", "8000").option("--no-browser", "Do not open browser").action(devCommand);
|
|
742
|
+
program.command("deploy").description("Deploy tool to Cortex platform").option("--api-url <url>", "Cortex API URL").option("--api-key <key>", "Cortex API key").option("--dry-run", "Show what would be deployed without deploying").action(deployCommand);
|
|
743
|
+
program.command("status").description("Check tool registration status").option("--api-url <url>", "Cortex API URL").option("--api-key <key>", "Cortex API key").action(statusCommand);
|
|
744
|
+
program.command("push <id>").description("Push a document to Cortex Knowledge Graph").requiredOption("-t, --type <type>", "Document type (e.g., meeting_transcript)").requiredOption("-f, --file <path>", "File containing document content").option("-n, --name <name>", "Display name for the document").option("-u, --url <url>", "External URL for the document").option("-s, --scope <scope>", "Access scope: global, team, or personal", "global").option("--teams <ids>", "Comma-separated team IDs (for team scope)").option("--metadata <json>", "JSON metadata object").option("--api-url <url>", "Cortex API URL").option("--api-key <key>", "Cortex API key").option("--tool-id <id>", "Cortex Tool ID").action(pushCommand);
|
|
745
|
+
program.command("query <question>").description("Query the Cortex Knowledge Graph").option("--filters <json>", `JSON filter object (e.g., '{"type":["meeting_transcript"]}')`).option("--time-range <days>", "Limit to recent N days").option("--max-results <n>", "Maximum results", "10").option("--user-email <email>", "User email for access-scoped queries").option("--json", "Output raw JSON").option("--api-url <url>", "Cortex API URL").option("--api-key <key>", "Cortex API key").option("--tool-id <id>", "Cortex Tool ID").action(queryCommand);
|
|
746
|
+
program.command("whoami <email>").description("Get user context from Cortex").option("--json", "Output raw JSON").option("--api-url <url>", "Cortex API URL").option("--api-key <key>", "Cortex API key").option("--tool-id <id>", "Cortex Tool ID").action(whoamiCommand);
|
|
747
|
+
program.command("share <document-id>").description("Share a document with another user").requiredOption("--from <email>", "Sharer email address").requiredOption("--to <email>", "Recipient email address").option("-n, --name <name>", "Document display name").option("-c, --content <text>", "Document content").option("-u, --url <url>", "External URL").option("--metadata <json>", "JSON metadata object").option("--api-url <url>", "Cortex API URL").option("--api-key <key>", "Cortex API key").option("--tool-id <id>", "Cortex Tool ID").action(shareCommand);
|
|
748
|
+
program.command("users").description("List organization users").option("--exclude <email>", "Exclude email from results").option("--json", "Output raw JSON").option("--api-url <url>", "Cortex API URL").option("--api-key <key>", "Cortex API key").option("--tool-id <id>", "Cortex Tool ID").action(usersCommand);
|
|
749
|
+
program.parse();
|
|
750
|
+
if (!process.argv.slice(2).length) {
|
|
751
|
+
console.log(import_chalk12.default.cyan("\n Cortex CLI - Build tools for Cortex platform\n"));
|
|
752
|
+
program.help();
|
|
753
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "lyzr-cortex-cli",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "CLI tool for Cortex platform developers - push, query, share documents and manage tools",
|
|
5
|
+
"author": "Cortex Lyzr AI",
|
|
6
|
+
"email": "krish@lyzr.ai",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"bin": {
|
|
9
|
+
"cortex": "./dist/index.js"
|
|
10
|
+
},
|
|
11
|
+
"main": "dist/index.js",
|
|
12
|
+
"types": "dist/index.d.ts",
|
|
13
|
+
"files": [
|
|
14
|
+
"dist"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup src/index.ts --format cjs --dts --clean",
|
|
18
|
+
"dev": "tsup src/index.ts --format cjs --dts --watch",
|
|
19
|
+
"start": "node dist/index.js",
|
|
20
|
+
"typecheck": "tsc --noEmit",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"chalk": "^4.1.2",
|
|
25
|
+
"commander": "^11.1.0",
|
|
26
|
+
"inquirer": "^8.2.6",
|
|
27
|
+
"js-yaml": "^4.1.0",
|
|
28
|
+
"ora": "^5.4.1"
|
|
29
|
+
},
|
|
30
|
+
"devDependencies": {
|
|
31
|
+
"@types/inquirer": "^9.0.7",
|
|
32
|
+
"@types/js-yaml": "^4.0.9",
|
|
33
|
+
"@types/node": "^20.10.0",
|
|
34
|
+
"tsup": "^8.0.0",
|
|
35
|
+
"typescript": "^5.3.0"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=16.0.0"
|
|
39
|
+
},
|
|
40
|
+
"keywords": [
|
|
41
|
+
"cortex",
|
|
42
|
+
"cli",
|
|
43
|
+
"tools",
|
|
44
|
+
"sdk",
|
|
45
|
+
"knowledge-graph",
|
|
46
|
+
"rag",
|
|
47
|
+
"lyzr"
|
|
48
|
+
],
|
|
49
|
+
"homepage": "https://cortex.lyzr.app/docs",
|
|
50
|
+
"repository": {
|
|
51
|
+
"type": "git"
|
|
52
|
+
},
|
|
53
|
+
"bugs": {
|
|
54
|
+
}
|
|
55
|
+
}
|