@aaronsb/kg-cli 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -0
- package/dist/api/client.d.ts +867 -0
- package/dist/api/client.d.ts.map +1 -0
- package/dist/api/client.js +1362 -0
- package/dist/api/client.js.map +1 -0
- package/dist/cli/admin/backup.d.ts +9 -0
- package/dist/cli/admin/backup.d.ts.map +1 -0
- package/dist/cli/admin/backup.js +363 -0
- package/dist/cli/admin/backup.js.map +1 -0
- package/dist/cli/admin/index.d.ts +7 -0
- package/dist/cli/admin/index.d.ts.map +1 -0
- package/dist/cli/admin/index.js +52 -0
- package/dist/cli/admin/index.js.map +1 -0
- package/dist/cli/admin/scheduler.d.ts +7 -0
- package/dist/cli/admin/scheduler.d.ts.map +1 -0
- package/dist/cli/admin/scheduler.js +125 -0
- package/dist/cli/admin/scheduler.js.map +1 -0
- package/dist/cli/admin/status.d.ts +7 -0
- package/dist/cli/admin/status.d.ts.map +1 -0
- package/dist/cli/admin/status.js +134 -0
- package/dist/cli/admin/status.js.map +1 -0
- package/dist/cli/admin/utils.d.ts +34 -0
- package/dist/cli/admin/utils.d.ts.map +1 -0
- package/dist/cli/admin/utils.js +441 -0
- package/dist/cli/admin/utils.js.map +1 -0
- package/dist/cli/ai-config/embedding.d.ts +11 -0
- package/dist/cli/ai-config/embedding.d.ts.map +1 -0
- package/dist/cli/ai-config/embedding.js +598 -0
- package/dist/cli/ai-config/embedding.js.map +1 -0
- package/dist/cli/ai-config/extraction.d.ts +11 -0
- package/dist/cli/ai-config/extraction.d.ts.map +1 -0
- package/dist/cli/ai-config/extraction.js +206 -0
- package/dist/cli/ai-config/extraction.js.map +1 -0
- package/dist/cli/ai-config/index.d.ts +21 -0
- package/dist/cli/ai-config/index.d.ts.map +1 -0
- package/dist/cli/ai-config/index.js +27 -0
- package/dist/cli/ai-config/index.js.map +1 -0
- package/dist/cli/ai-config/keys.d.ts +11 -0
- package/dist/cli/ai-config/keys.d.ts.map +1 -0
- package/dist/cli/ai-config/keys.js +182 -0
- package/dist/cli/ai-config/keys.js.map +1 -0
- package/dist/cli/ai-config/utils.d.ts +13 -0
- package/dist/cli/ai-config/utils.d.ts.map +1 -0
- package/dist/cli/ai-config/utils.js +84 -0
- package/dist/cli/ai-config/utils.js.map +1 -0
- package/dist/cli/artifact.d.ts +8 -0
- package/dist/cli/artifact.d.ts.map +1 -0
- package/dist/cli/artifact.js +296 -0
- package/dist/cli/artifact.js.map +1 -0
- package/dist/cli/auth-admin.d.ts +11 -0
- package/dist/cli/auth-admin.d.ts.map +1 -0
- package/dist/cli/auth-admin.js +415 -0
- package/dist/cli/auth-admin.js.map +1 -0
- package/dist/cli/colors.d.ts +105 -0
- package/dist/cli/colors.d.ts.map +1 -0
- package/dist/cli/colors.js +164 -0
- package/dist/cli/colors.js.map +1 -0
- package/dist/cli/commands.d.ts +6 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +164 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/config.d.ts +6 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +694 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/curve-viz.d.ts +89 -0
- package/dist/cli/curve-viz.d.ts.map +1 -0
- package/dist/cli/curve-viz.js +228 -0
- package/dist/cli/curve-viz.js.map +1 -0
- package/dist/cli/database.d.ts +6 -0
- package/dist/cli/database.d.ts.map +1 -0
- package/dist/cli/database.js +324 -0
- package/dist/cli/database.js.map +1 -0
- package/dist/cli/document.d.ts +6 -0
- package/dist/cli/document.d.ts.map +1 -0
- package/dist/cli/document.js +458 -0
- package/dist/cli/document.js.map +1 -0
- package/dist/cli/group.d.ts +8 -0
- package/dist/cli/group.d.ts.map +1 -0
- package/dist/cli/group.js +174 -0
- package/dist/cli/group.js.map +1 -0
- package/dist/cli/health.d.ts +6 -0
- package/dist/cli/health.d.ts.map +1 -0
- package/dist/cli/health.js +34 -0
- package/dist/cli/health.js.map +1 -0
- package/dist/cli/help-formatter.d.ts +16 -0
- package/dist/cli/help-formatter.d.ts.map +1 -0
- package/dist/cli/help-formatter.js +248 -0
- package/dist/cli/help-formatter.js.map +1 -0
- package/dist/cli/help.d.ts +9 -0
- package/dist/cli/help.d.ts.map +1 -0
- package/dist/cli/help.js +227 -0
- package/dist/cli/help.js.map +1 -0
- package/dist/cli/ingest.d.ts +6 -0
- package/dist/cli/ingest.d.ts.map +1 -0
- package/dist/cli/ingest.js +722 -0
- package/dist/cli/ingest.js.map +1 -0
- package/dist/cli/jobs.d.ts +6 -0
- package/dist/cli/jobs.d.ts.map +1 -0
- package/dist/cli/jobs.js +663 -0
- package/dist/cli/jobs.js.map +1 -0
- package/dist/cli/login.d.ts +21 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/login.js +221 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/logout.d.ts +16 -0
- package/dist/cli/logout.d.ts.map +1 -0
- package/dist/cli/logout.js +141 -0
- package/dist/cli/logout.js.map +1 -0
- package/dist/cli/mcp-config.d.ts +10 -0
- package/dist/cli/mcp-config.d.ts.map +1 -0
- package/dist/cli/mcp-config.js +358 -0
- package/dist/cli/mcp-config.js.map +1 -0
- package/dist/cli/oauth.d.ts +15 -0
- package/dist/cli/oauth.d.ts.map +1 -0
- package/dist/cli/oauth.js +296 -0
- package/dist/cli/oauth.js.map +1 -0
- package/dist/cli/ontology.d.ts +6 -0
- package/dist/cli/ontology.d.ts.map +1 -0
- package/dist/cli/ontology.js +231 -0
- package/dist/cli/ontology.js.map +1 -0
- package/dist/cli/polarity.d.ts +6 -0
- package/dist/cli/polarity.d.ts.map +1 -0
- package/dist/cli/polarity.js +295 -0
- package/dist/cli/polarity.js.map +1 -0
- package/dist/cli/projection.d.ts +8 -0
- package/dist/cli/projection.d.ts.map +1 -0
- package/dist/cli/projection.js +297 -0
- package/dist/cli/projection.js.map +1 -0
- package/dist/cli/query-def.d.ts +8 -0
- package/dist/cli/query-def.d.ts.map +1 -0
- package/dist/cli/query-def.js +163 -0
- package/dist/cli/query-def.js.map +1 -0
- package/dist/cli/rbac.d.ts +12 -0
- package/dist/cli/rbac.d.ts.map +1 -0
- package/dist/cli/rbac.js +615 -0
- package/dist/cli/rbac.js.map +1 -0
- package/dist/cli/search.d.ts +6 -0
- package/dist/cli/search.d.ts.map +1 -0
- package/dist/cli/search.js +829 -0
- package/dist/cli/search.js.map +1 -0
- package/dist/cli/source.d.ts +6 -0
- package/dist/cli/source.d.ts.map +1 -0
- package/dist/cli/source.js +202 -0
- package/dist/cli/source.js.map +1 -0
- package/dist/cli/verb-router.d.ts +25 -0
- package/dist/cli/verb-router.d.ts.map +1 -0
- package/dist/cli/verb-router.js +415 -0
- package/dist/cli/verb-router.js.map +1 -0
- package/dist/cli/vocabulary/config.d.ts +7 -0
- package/dist/cli/vocabulary/config.d.ts.map +1 -0
- package/dist/cli/vocabulary/config.js +201 -0
- package/dist/cli/vocabulary/config.js.map +1 -0
- package/dist/cli/vocabulary/consolidate.d.ts +8 -0
- package/dist/cli/vocabulary/consolidate.d.ts.map +1 -0
- package/dist/cli/vocabulary/consolidate.js +192 -0
- package/dist/cli/vocabulary/consolidate.js.map +1 -0
- package/dist/cli/vocabulary/embeddings.d.ts +9 -0
- package/dist/cli/vocabulary/embeddings.d.ts.map +1 -0
- package/dist/cli/vocabulary/embeddings.js +205 -0
- package/dist/cli/vocabulary/embeddings.js.map +1 -0
- package/dist/cli/vocabulary/epistemic.d.ts +7 -0
- package/dist/cli/vocabulary/epistemic.d.ts.map +1 -0
- package/dist/cli/vocabulary/epistemic.js +315 -0
- package/dist/cli/vocabulary/epistemic.js.map +1 -0
- package/dist/cli/vocabulary/index.d.ts +7 -0
- package/dist/cli/vocabulary/index.d.ts.map +1 -0
- package/dist/cli/vocabulary/index.js +45 -0
- package/dist/cli/vocabulary/index.js.map +1 -0
- package/dist/cli/vocabulary/profiles.d.ts +7 -0
- package/dist/cli/vocabulary/profiles.d.ts.map +1 -0
- package/dist/cli/vocabulary/profiles.js +171 -0
- package/dist/cli/vocabulary/profiles.js.map +1 -0
- package/dist/cli/vocabulary/similarity.d.ts +9 -0
- package/dist/cli/vocabulary/similarity.d.ts.map +1 -0
- package/dist/cli/vocabulary/similarity.js +199 -0
- package/dist/cli/vocabulary/similarity.js.map +1 -0
- package/dist/cli/vocabulary/status.d.ts +8 -0
- package/dist/cli/vocabulary/status.d.ts.map +1 -0
- package/dist/cli/vocabulary/status.js +280 -0
- package/dist/cli/vocabulary/status.js.map +1 -0
- package/dist/cli/vocabulary/sync.d.ts +7 -0
- package/dist/cli/vocabulary/sync.d.ts.map +1 -0
- package/dist/cli/vocabulary/sync.js +111 -0
- package/dist/cli/vocabulary/sync.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/auth/auth-client.d.ts +247 -0
- package/dist/lib/auth/auth-client.d.ts.map +1 -0
- package/dist/lib/auth/auth-client.js +305 -0
- package/dist/lib/auth/auth-client.js.map +1 -0
- package/dist/lib/auth/challenge.d.ts +39 -0
- package/dist/lib/auth/challenge.d.ts.map +1 -0
- package/dist/lib/auth/challenge.js +125 -0
- package/dist/lib/auth/challenge.js.map +1 -0
- package/dist/lib/auth/client-credentials-flow.d.ts +58 -0
- package/dist/lib/auth/client-credentials-flow.d.ts.map +1 -0
- package/dist/lib/auth/client-credentials-flow.js +118 -0
- package/dist/lib/auth/client-credentials-flow.js.map +1 -0
- package/dist/lib/auth/device-flow.d.ts +75 -0
- package/dist/lib/auth/device-flow.d.ts.map +1 -0
- package/dist/lib/auth/device-flow.js +177 -0
- package/dist/lib/auth/device-flow.js.map +1 -0
- package/dist/lib/auth/index.d.ts +14 -0
- package/dist/lib/auth/index.d.ts.map +1 -0
- package/dist/lib/auth/index.js +34 -0
- package/dist/lib/auth/index.js.map +1 -0
- package/dist/lib/auth/oauth-types.d.ts +69 -0
- package/dist/lib/auth/oauth-types.d.ts.map +1 -0
- package/dist/lib/auth/oauth-types.js +10 -0
- package/dist/lib/auth/oauth-types.js.map +1 -0
- package/dist/lib/auth/oauth-utils.d.ts +51 -0
- package/dist/lib/auth/oauth-utils.d.ts.map +1 -0
- package/dist/lib/auth/oauth-utils.js +110 -0
- package/dist/lib/auth/oauth-utils.js.map +1 -0
- package/dist/lib/auth/token-manager.d.ts +87 -0
- package/dist/lib/auth/token-manager.d.ts.map +1 -0
- package/dist/lib/auth/token-manager.js +139 -0
- package/dist/lib/auth/token-manager.js.map +1 -0
- package/dist/lib/auth/token-refresh.d.ts +63 -0
- package/dist/lib/auth/token-refresh.d.ts.map +1 -0
- package/dist/lib/auth/token-refresh.js +141 -0
- package/dist/lib/auth/token-refresh.js.map +1 -0
- package/dist/lib/config.d.ts +286 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +537 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/job-stream.d.ts +53 -0
- package/dist/lib/job-stream.d.ts.map +1 -0
- package/dist/lib/job-stream.js +153 -0
- package/dist/lib/job-stream.js.map +1 -0
- package/dist/lib/mcp-allowlist.d.ts +101 -0
- package/dist/lib/mcp-allowlist.d.ts.map +1 -0
- package/dist/lib/mcp-allowlist.js +340 -0
- package/dist/lib/mcp-allowlist.js.map +1 -0
- package/dist/lib/table-example.d.ts +7 -0
- package/dist/lib/table-example.d.ts.map +1 -0
- package/dist/lib/table-example.js +105 -0
- package/dist/lib/table-example.js.map +1 -0
- package/dist/lib/table.d.ts +95 -0
- package/dist/lib/table.d.ts.map +1 -0
- package/dist/lib/table.js +263 -0
- package/dist/lib/table.js.map +1 -0
- package/dist/lib/terminal-images.d.ts +66 -0
- package/dist/lib/terminal-images.d.ts.map +1 -0
- package/dist/lib/terminal-images.js +268 -0
- package/dist/lib/terminal-images.js.map +1 -0
- package/dist/mcp/formatters.d.ts +100 -0
- package/dist/mcp/formatters.d.ts.map +1 -0
- package/dist/mcp/formatters.js +1411 -0
- package/dist/mcp/formatters.js.map +1 -0
- package/dist/mcp-server.d.ts +9 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +1810 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/types/index.d.ts +742 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/version.d.ts +10 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +13 -0
- package/dist/version.js.map +1 -0
- package/package.json +84 -0
package/dist/cli/jobs.js
ADDED
|
@@ -0,0 +1,663 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Job management commands
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
39
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
40
|
+
};
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.jobsCommand = void 0;
|
|
43
|
+
const commander_1 = require("commander");
|
|
44
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
45
|
+
const client_1 = require("../api/client");
|
|
46
|
+
const colors = __importStar(require("./colors"));
|
|
47
|
+
const table_1 = require("../lib/table");
|
|
48
|
+
const help_formatter_1 = require("./help-formatter");
|
|
49
|
+
exports.jobsCommand = (0, help_formatter_1.setCommandHelp)(new commander_1.Command('job'), 'Manage and monitor ingestion jobs', 'Manage and monitor ingestion jobs through their lifecycle (pending → approval → processing → completed/failed)')
|
|
50
|
+
.alias('jobs') // Plural alias for backwards compatibility
|
|
51
|
+
.showHelpAfterError('(add --help for additional information)')
|
|
52
|
+
.showSuggestionAfterError();
|
|
53
|
+
// Get job status
|
|
54
|
+
exports.jobsCommand
|
|
55
|
+
.command('status <job-id>')
|
|
56
|
+
.description('Get detailed status information for a job (progress, costs, errors) - use --watch to poll until completion')
|
|
57
|
+
.showHelpAfterError()
|
|
58
|
+
.option('-w, --watch', 'Watch job until completion (polls every few seconds)', false)
|
|
59
|
+
.action(async (jobId, options) => {
|
|
60
|
+
try {
|
|
61
|
+
const client = (0, client_1.createClientFromEnv)();
|
|
62
|
+
if (options.watch) {
|
|
63
|
+
// Poll until completion
|
|
64
|
+
console.log(chalk_1.default.blue(`Watching job ${jobId}...`));
|
|
65
|
+
console.log(chalk_1.default.gray('Press Ctrl+C to stop\n'));
|
|
66
|
+
const finalJob = await client.pollJob(jobId, (job) => {
|
|
67
|
+
// Clear line and rewrite
|
|
68
|
+
process.stdout.write('\r\x1b[K'); // Clear line
|
|
69
|
+
if (job.status === 'queued') {
|
|
70
|
+
process.stdout.write(chalk_1.default.yellow(`Status: ${job.status}`));
|
|
71
|
+
}
|
|
72
|
+
else if (job.status === 'processing' && job.progress) {
|
|
73
|
+
const p = job.progress;
|
|
74
|
+
if (p.percent !== undefined) {
|
|
75
|
+
const conceptsTotal = (p.concepts_created || 0) + (p.concepts_linked || 0);
|
|
76
|
+
const hitRate = conceptsTotal > 0 ? Math.round((p.concepts_linked || 0) / conceptsTotal * 100) : 0;
|
|
77
|
+
process.stdout.write(chalk_1.default.blue(`Processing: ${p.percent}% `) +
|
|
78
|
+
chalk_1.default.gray(`(${p.chunks_processed}/${p.chunks_total} chunks) `) +
|
|
79
|
+
chalk_1.default.gray(`| Concepts: ${conceptsTotal} (${hitRate}% reused) `) +
|
|
80
|
+
chalk_1.default.gray(`| Rels: ${p.relationships_created || 0}`));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
process.stdout.write(chalk_1.default.blue(`Processing: ${p.stage}`));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
console.log(); // New line after polling
|
|
88
|
+
printJobStatus(finalJob);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Single fetch
|
|
92
|
+
const job = await client.getJob(jobId);
|
|
93
|
+
printJobStatus(job);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
console.error(chalk_1.default.red('\n✗ Failed to get job status'));
|
|
98
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
// Helper function to display jobs list using Table utility
|
|
103
|
+
async function displayJobsList(status, clientId, limit = 20, fullId = false, offset = 0) {
|
|
104
|
+
const client = (0, client_1.createClientFromEnv)();
|
|
105
|
+
const jobs = await client.listJobs(status, clientId, limit, offset);
|
|
106
|
+
if (jobs.length === 0) {
|
|
107
|
+
console.log(colors.status.dim('\nNo jobs found\n'));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Create table with dynamic configuration
|
|
111
|
+
const table = new table_1.Table({
|
|
112
|
+
columns: [
|
|
113
|
+
{
|
|
114
|
+
header: 'Job ID',
|
|
115
|
+
field: 'job_id',
|
|
116
|
+
type: 'job_id',
|
|
117
|
+
width: fullId ? 38 : 16, // Fixed width - job IDs are consistent length
|
|
118
|
+
truncate: false
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
header: 'Source',
|
|
122
|
+
field: (job) => job.source_path || job.filename || '-',
|
|
123
|
+
type: 'text',
|
|
124
|
+
width: 'flex',
|
|
125
|
+
priority: 10, // Highest priority - gets most space
|
|
126
|
+
customFormat: (source, job) => {
|
|
127
|
+
if (!source || source === '-')
|
|
128
|
+
return colors.status.dim('-');
|
|
129
|
+
return source;
|
|
130
|
+
},
|
|
131
|
+
truncate: true
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
header: 'User',
|
|
135
|
+
field: 'username',
|
|
136
|
+
type: 'user',
|
|
137
|
+
width: 'auto', // Fit to content
|
|
138
|
+
maxWidth: 12,
|
|
139
|
+
customFormat: (username) => username || 'unknown',
|
|
140
|
+
truncate: true
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
header: 'Status',
|
|
144
|
+
field: 'status',
|
|
145
|
+
type: 'text', // Use custom formatting instead of status type
|
|
146
|
+
width: 8, // Fixed width for compact status
|
|
147
|
+
customFormat: (status) => {
|
|
148
|
+
// Compact status - just icons for terminal states
|
|
149
|
+
switch (status) {
|
|
150
|
+
case 'completed': return colors.status.success('✓ done');
|
|
151
|
+
case 'failed': return colors.status.error('✗ fail');
|
|
152
|
+
case 'running': return colors.status.info('⚙ run');
|
|
153
|
+
case 'processing': return colors.status.info('⚙ run');
|
|
154
|
+
case 'approved': return colors.status.success('✓ ok');
|
|
155
|
+
case 'awaiting_approval': return colors.status.warning('⏸ wait');
|
|
156
|
+
case 'pending': return colors.status.dim('○ pend');
|
|
157
|
+
case 'queued': return colors.status.info('⋯ queue');
|
|
158
|
+
case 'cancelled': return colors.status.dim('⊗ stop');
|
|
159
|
+
default: return colors.status.dim(status);
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
truncate: false
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
header: 'Ontology',
|
|
166
|
+
field: 'ontology',
|
|
167
|
+
type: 'heading',
|
|
168
|
+
width: 'flex',
|
|
169
|
+
priority: 3, // Lower priority than Source
|
|
170
|
+
customFormat: (name) => name || '-',
|
|
171
|
+
truncate: true
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
header: 'Created',
|
|
175
|
+
field: 'created_at',
|
|
176
|
+
type: 'timestamp',
|
|
177
|
+
width: 16 // Timestamp is consistent width
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
header: '', // No header for progress icon
|
|
181
|
+
field: (job) => job.progress?.percent,
|
|
182
|
+
type: 'progress',
|
|
183
|
+
width: 1, // Just the icon
|
|
184
|
+
customFormat: (percent, job) => {
|
|
185
|
+
// Just icons, no text
|
|
186
|
+
if (job.status === 'completed')
|
|
187
|
+
return '✓';
|
|
188
|
+
if (job.status === 'failed')
|
|
189
|
+
return '✗';
|
|
190
|
+
if (job.status === 'cancelled')
|
|
191
|
+
return '⊗';
|
|
192
|
+
return percent !== undefined && percent < 100 ? '⋯' : ' ';
|
|
193
|
+
},
|
|
194
|
+
truncate: false
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
spacing: 1, // Tighter spacing between columns
|
|
198
|
+
showHeader: true,
|
|
199
|
+
showSeparator: true
|
|
200
|
+
});
|
|
201
|
+
// Render table
|
|
202
|
+
table.print(jobs);
|
|
203
|
+
// Helpful tip
|
|
204
|
+
if (!fullId && jobs.length > 0) {
|
|
205
|
+
console.log(colors.status.dim('Tip: Use --full-id to show complete job IDs\n'));
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// List command with subcommands
|
|
209
|
+
const listCommand = new commander_1.Command('list')
|
|
210
|
+
.description('List recent jobs with optional filtering by status or user - includes subcommands for common filters')
|
|
211
|
+
.option('-s, --status <status>', 'Filter by status (pending|awaiting_approval|approved|queued|processing|completed|failed|cancelled)')
|
|
212
|
+
.option('-c, --client <user-id>', 'Filter by user ID (view specific user\'s jobs)')
|
|
213
|
+
.option('-l, --limit <n>', 'Maximum jobs to return (max: 500, default: 100)', '100')
|
|
214
|
+
.option('-o, --offset <n>', 'Number of jobs to skip for pagination (default: 0)', '0')
|
|
215
|
+
.option('--full-id', 'Show full job IDs without truncation', false)
|
|
216
|
+
.showHelpAfterError()
|
|
217
|
+
.action(async (options) => {
|
|
218
|
+
try {
|
|
219
|
+
const limit = parseInt(options.limit);
|
|
220
|
+
const offset = parseInt(options.offset);
|
|
221
|
+
await displayJobsList(options.status, options.client, limit, options.fullId, offset);
|
|
222
|
+
}
|
|
223
|
+
catch (error) {
|
|
224
|
+
console.error(chalk_1.default.red('✗ Failed to list jobs'));
|
|
225
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
// List subcommands for common filters
|
|
230
|
+
listCommand
|
|
231
|
+
.command('pending')
|
|
232
|
+
.description('List jobs awaiting approval')
|
|
233
|
+
.option('-c, --client <user-id>', 'Filter by user ID')
|
|
234
|
+
.option('-l, --limit <n>', 'Maximum jobs to return', '20')
|
|
235
|
+
.option('--full-id', 'Show full job IDs (no truncation)', false)
|
|
236
|
+
.action(async (options) => {
|
|
237
|
+
try {
|
|
238
|
+
console.log(chalk_1.default.blue('Jobs awaiting approval:\n'));
|
|
239
|
+
await displayJobsList('awaiting_approval', options.client, parseInt(options.limit), options.fullId);
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
console.error(chalk_1.default.red('✗ Failed to list jobs'));
|
|
243
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
244
|
+
process.exit(1);
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
listCommand
|
|
248
|
+
.command('approved')
|
|
249
|
+
.description('List approved jobs (queued or processing)')
|
|
250
|
+
.option('-c, --client <user-id>', 'Filter by user ID')
|
|
251
|
+
.option('-l, --limit <n>', 'Maximum jobs to return', '20')
|
|
252
|
+
.option('--full-id', 'Show full job IDs (no truncation)', false)
|
|
253
|
+
.action(async (options) => {
|
|
254
|
+
try {
|
|
255
|
+
console.log(chalk_1.default.blue('Approved jobs:\n'));
|
|
256
|
+
await displayJobsList('approved', options.client, parseInt(options.limit), options.fullId);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
console.error(chalk_1.default.red('✗ Failed to list jobs'));
|
|
260
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
261
|
+
process.exit(1);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
listCommand
|
|
265
|
+
.command('done')
|
|
266
|
+
.description('List completed jobs')
|
|
267
|
+
.option('-c, --client <user-id>', 'Filter by user ID')
|
|
268
|
+
.option('-l, --limit <n>', 'Maximum jobs to return', '20')
|
|
269
|
+
.option('--full-id', 'Show full job IDs (no truncation)', false)
|
|
270
|
+
.action(async (options) => {
|
|
271
|
+
try {
|
|
272
|
+
console.log(chalk_1.default.green('Completed jobs:\n'));
|
|
273
|
+
await displayJobsList('completed', options.client, parseInt(options.limit), options.fullId);
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
console.error(chalk_1.default.red('✗ Failed to list jobs'));
|
|
277
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
listCommand
|
|
282
|
+
.command('failed')
|
|
283
|
+
.description('List failed jobs')
|
|
284
|
+
.option('-c, --client <user-id>', 'Filter by user ID')
|
|
285
|
+
.option('-l, --limit <n>', 'Maximum jobs to return', '20')
|
|
286
|
+
.option('--full-id', 'Show full job IDs (no truncation)', false)
|
|
287
|
+
.action(async (options) => {
|
|
288
|
+
try {
|
|
289
|
+
console.log(chalk_1.default.red('Failed jobs:\n'));
|
|
290
|
+
await displayJobsList('failed', options.client, parseInt(options.limit), options.fullId);
|
|
291
|
+
}
|
|
292
|
+
catch (error) {
|
|
293
|
+
console.error(chalk_1.default.red('✗ Failed to list jobs'));
|
|
294
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
listCommand
|
|
299
|
+
.command('cancelled')
|
|
300
|
+
.description('List cancelled jobs')
|
|
301
|
+
.option('-c, --client <user-id>', 'Filter by user ID')
|
|
302
|
+
.option('-l, --limit <n>', 'Maximum jobs to return', '20')
|
|
303
|
+
.option('--full-id', 'Show full job IDs (no truncation)', false)
|
|
304
|
+
.action(async (options) => {
|
|
305
|
+
try {
|
|
306
|
+
console.log(chalk_1.default.yellow('Cancelled jobs:\n'));
|
|
307
|
+
await displayJobsList('cancelled', options.client, parseInt(options.limit), options.fullId);
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
console.error(chalk_1.default.red('✗ Failed to list jobs'));
|
|
311
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
312
|
+
process.exit(1);
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
// Add list command to jobs
|
|
316
|
+
exports.jobsCommand.addCommand(listCommand);
|
|
317
|
+
// Approve job(s) (ADR-014)
|
|
318
|
+
const approveCommand = new commander_1.Command('approve')
|
|
319
|
+
.description('Approve jobs for processing (ADR-014 approval workflow) - single job, batch pending, or filter by status')
|
|
320
|
+
.showHelpAfterError();
|
|
321
|
+
// Approve single job
|
|
322
|
+
approveCommand
|
|
323
|
+
.command('job <job-id>')
|
|
324
|
+
.description('Approve a specific job by ID after reviewing cost estimates')
|
|
325
|
+
.action(async (jobId) => {
|
|
326
|
+
try {
|
|
327
|
+
const client = (0, client_1.createClientFromEnv)();
|
|
328
|
+
console.log(chalk_1.default.blue(`Approving job ${jobId}...`));
|
|
329
|
+
const result = await client.approveJob(jobId);
|
|
330
|
+
console.log(chalk_1.default.green('✓ Job approved'));
|
|
331
|
+
console.log(chalk_1.default.gray(` Status: ${result.status}`));
|
|
332
|
+
console.log(chalk_1.default.gray(`\nMonitor: ${chalk_1.default.cyan(`kg jobs status ${jobId} --watch`)}`));
|
|
333
|
+
}
|
|
334
|
+
catch (error) {
|
|
335
|
+
console.error(chalk_1.default.red('✗ Failed to approve job'));
|
|
336
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
337
|
+
process.exit(1);
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
// Approve all pending jobs
|
|
341
|
+
approveCommand
|
|
342
|
+
.command('pending')
|
|
343
|
+
.description('Approve all jobs awaiting approval (batch operation with confirmation)')
|
|
344
|
+
.option('-c, --client <user-id>', 'Filter by user ID')
|
|
345
|
+
.option('-l, --limit <n>', 'Maximum jobs to approve (default: 100)', '100')
|
|
346
|
+
.action(async (options) => {
|
|
347
|
+
try {
|
|
348
|
+
const client = (0, client_1.createClientFromEnv)();
|
|
349
|
+
console.log(chalk_1.default.blue('Finding jobs awaiting approval...\n'));
|
|
350
|
+
const jobs = await client.listJobs('awaiting_approval', options.client, parseInt(options.limit));
|
|
351
|
+
if (jobs.length === 0) {
|
|
352
|
+
console.log(chalk_1.default.gray('No pending jobs found'));
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
console.log(chalk_1.default.blue(`Found ${jobs.length} pending job(s):\n`));
|
|
356
|
+
let approved = 0;
|
|
357
|
+
let failed = 0;
|
|
358
|
+
for (const job of jobs) {
|
|
359
|
+
try {
|
|
360
|
+
await client.approveJob(job.job_id);
|
|
361
|
+
console.log(chalk_1.default.green(`✓ Approved: ${job.job_id.substring(0, 12)}... (${job.ontology || 'unknown'})`));
|
|
362
|
+
approved++;
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
console.log(chalk_1.default.red(`✗ Failed: ${job.job_id.substring(0, 12)}... - ${error.message}`));
|
|
366
|
+
failed++;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
console.log(chalk_1.default.blue(`\nSummary: ${approved} approved, ${failed} failed`));
|
|
370
|
+
console.log(chalk_1.default.gray(`\nMonitor jobs: ${chalk_1.default.cyan('kg jobs list')}`));
|
|
371
|
+
}
|
|
372
|
+
catch (error) {
|
|
373
|
+
console.error(chalk_1.default.red('✗ Failed to approve pending jobs'));
|
|
374
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
375
|
+
process.exit(1);
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
// Legacy: approve with ID or filter
|
|
379
|
+
approveCommand
|
|
380
|
+
.command('filter <status>')
|
|
381
|
+
.description('Approve all jobs matching status filter')
|
|
382
|
+
.option('-c, --client <user-id>', 'Filter by user ID')
|
|
383
|
+
.action(async (statusFilter, options) => {
|
|
384
|
+
try {
|
|
385
|
+
const client = (0, client_1.createClientFromEnv)();
|
|
386
|
+
const statusMap = {
|
|
387
|
+
'pending': 'awaiting_approval',
|
|
388
|
+
'awaiting': 'awaiting_approval',
|
|
389
|
+
};
|
|
390
|
+
const status = statusMap[statusFilter] || statusFilter;
|
|
391
|
+
console.log(chalk_1.default.blue(`Finding jobs with status: ${status}...\n`));
|
|
392
|
+
const jobs = await client.listJobs(status, options.client, 100);
|
|
393
|
+
if (jobs.length === 0) {
|
|
394
|
+
console.log(chalk_1.default.gray('No jobs found matching filter'));
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
console.log(chalk_1.default.blue(`Found ${jobs.length} job(s). Approving...\n`));
|
|
398
|
+
let approved = 0;
|
|
399
|
+
let failed = 0;
|
|
400
|
+
for (const job of jobs) {
|
|
401
|
+
try {
|
|
402
|
+
await client.approveJob(job.job_id);
|
|
403
|
+
console.log(chalk_1.default.green(`✓ Approved: ${job.job_id.substring(0, 12)}... (${job.ontology || 'unknown'})`));
|
|
404
|
+
approved++;
|
|
405
|
+
}
|
|
406
|
+
catch (error) {
|
|
407
|
+
console.log(chalk_1.default.red(`✗ Failed: ${job.job_id.substring(0, 12)}... - ${error.message}`));
|
|
408
|
+
failed++;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
console.log(chalk_1.default.blue(`\nSummary: ${approved} approved, ${failed} failed`));
|
|
412
|
+
}
|
|
413
|
+
catch (error) {
|
|
414
|
+
console.error(chalk_1.default.red('✗ Failed to approve jobs'));
|
|
415
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
416
|
+
process.exit(1);
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
exports.jobsCommand.addCommand(approveCommand);
|
|
420
|
+
// Cancel job(s)
|
|
421
|
+
exports.jobsCommand
|
|
422
|
+
.command('cancel <job-id-or-filter>')
|
|
423
|
+
.description('Cancel a specific job by ID or batch cancel using filters (all, pending, running, queued, approved)')
|
|
424
|
+
.showHelpAfterError()
|
|
425
|
+
.option('-c, --client <user-id>', 'Filter by user ID for batch operations')
|
|
426
|
+
.option('-l, --limit <n>', 'Maximum jobs to cancel for safety (default: 100)', '100')
|
|
427
|
+
.action(async (jobIdOrFilter, options) => {
|
|
428
|
+
try {
|
|
429
|
+
const client = (0, client_1.createClientFromEnv)();
|
|
430
|
+
const limit = parseInt(options.limit);
|
|
431
|
+
// Check if it's a job ID or a status filter
|
|
432
|
+
if (jobIdOrFilter.startsWith('job_')) {
|
|
433
|
+
// Single job cancellation
|
|
434
|
+
console.log(chalk_1.default.blue(`Cancelling job ${jobIdOrFilter}...`));
|
|
435
|
+
const result = await client.cancelJob(jobIdOrFilter);
|
|
436
|
+
if (result.cancelled) {
|
|
437
|
+
console.log(chalk_1.default.green('✓ Job cancelled'));
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
440
|
+
console.log(chalk_1.default.yellow('⚠ Job could not be cancelled'));
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
else {
|
|
444
|
+
// Batch cancellation by status filter
|
|
445
|
+
const statusMap = {
|
|
446
|
+
'all': undefined, // No filter = all jobs
|
|
447
|
+
'pending': 'awaiting_approval',
|
|
448
|
+
'awaiting': 'awaiting_approval',
|
|
449
|
+
'approved': 'approved',
|
|
450
|
+
'queued': 'queued',
|
|
451
|
+
'running': 'processing',
|
|
452
|
+
'processing': 'processing',
|
|
453
|
+
};
|
|
454
|
+
const filter = jobIdOrFilter.toLowerCase();
|
|
455
|
+
// Check if it's a known filter
|
|
456
|
+
if (!(filter in statusMap)) {
|
|
457
|
+
console.error(chalk_1.default.red(`✗ Unknown filter: "${jobIdOrFilter}"`));
|
|
458
|
+
console.error(chalk_1.default.gray('\nSupported filters:'));
|
|
459
|
+
console.error(chalk_1.default.gray(' all - All cancellable jobs'));
|
|
460
|
+
console.error(chalk_1.default.gray(' pending - Jobs awaiting approval'));
|
|
461
|
+
console.error(chalk_1.default.gray(' approved - Approved jobs (not yet started)'));
|
|
462
|
+
console.error(chalk_1.default.gray(' queued - Queued jobs'));
|
|
463
|
+
console.error(chalk_1.default.gray(' running - Currently processing jobs'));
|
|
464
|
+
process.exit(1);
|
|
465
|
+
}
|
|
466
|
+
const status = statusMap[filter];
|
|
467
|
+
const filterDisplay = status || 'all cancellable jobs';
|
|
468
|
+
console.log(chalk_1.default.blue(`Finding ${filterDisplay}...`));
|
|
469
|
+
const jobs = await client.listJobs(status, options.client, limit);
|
|
470
|
+
if (jobs.length === 0) {
|
|
471
|
+
console.log(chalk_1.default.gray(`No jobs found matching filter: ${jobIdOrFilter}`));
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
// Filter to only cancellable statuses (not completed, failed, or already cancelled)
|
|
475
|
+
const cancellableStatuses = ['awaiting_approval', 'approved', 'queued', 'processing'];
|
|
476
|
+
const cancellableJobs = jobs.filter(j => cancellableStatuses.includes(j.status));
|
|
477
|
+
if (cancellableJobs.length === 0) {
|
|
478
|
+
console.log(chalk_1.default.yellow(`Found ${jobs.length} job(s), but none are cancellable`));
|
|
479
|
+
console.log(chalk_1.default.gray('Only jobs in these states can be cancelled: awaiting_approval, approved, queued, processing'));
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
if (cancellableJobs.length < jobs.length) {
|
|
483
|
+
console.log(chalk_1.default.yellow(`Found ${jobs.length} job(s), ${cancellableJobs.length} are cancellable\n`));
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
console.log(chalk_1.default.blue(`Found ${cancellableJobs.length} job(s). Cancelling...\n`));
|
|
487
|
+
}
|
|
488
|
+
let cancelled = 0;
|
|
489
|
+
let failed = 0;
|
|
490
|
+
for (const job of cancellableJobs) {
|
|
491
|
+
try {
|
|
492
|
+
await client.cancelJob(job.job_id);
|
|
493
|
+
console.log(chalk_1.default.yellow(`✓ Cancelled: ${job.job_id.substring(0, 12)}... (${job.status}) - ${job.ontology || 'N/A'}`));
|
|
494
|
+
cancelled++;
|
|
495
|
+
}
|
|
496
|
+
catch (error) {
|
|
497
|
+
const errorMsg = error.response?.data?.detail || error.message || 'Unknown error';
|
|
498
|
+
console.log(chalk_1.default.red(`✗ Failed: ${job.job_id.substring(0, 12)}... - ${errorMsg}`));
|
|
499
|
+
failed++;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
console.log(chalk_1.default.blue(`\nSummary: ${cancelled} cancelled, ${failed} failed`));
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
catch (error) {
|
|
506
|
+
console.error(chalk_1.default.red('✗ Failed to cancel job(s)'));
|
|
507
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
508
|
+
process.exit(1);
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
// Clear all jobs
|
|
512
|
+
exports.jobsCommand
|
|
513
|
+
.command('clear')
|
|
514
|
+
.description('Clear ALL jobs from database - DESTRUCTIVE operation requiring --confirm flag (use for dev/testing cleanup)')
|
|
515
|
+
.option('--confirm', 'Confirm deletion (REQUIRED for safety)', false)
|
|
516
|
+
.showHelpAfterError()
|
|
517
|
+
.action(async (options) => {
|
|
518
|
+
try {
|
|
519
|
+
if (!options.confirm) {
|
|
520
|
+
console.error(chalk_1.default.red('✗ Confirmation required'));
|
|
521
|
+
console.error(chalk_1.default.yellow('\n⚠️ This will DELETE ALL jobs from the database!'));
|
|
522
|
+
console.error(chalk_1.default.gray('\nTo confirm, run: ') + chalk_1.default.cyan('kg jobs clear --confirm'));
|
|
523
|
+
process.exit(1);
|
|
524
|
+
}
|
|
525
|
+
const client = (0, client_1.createClientFromEnv)();
|
|
526
|
+
console.log(chalk_1.default.yellow('\n⚠️ Clearing ALL jobs from database...'));
|
|
527
|
+
const result = await client.clearAllJobs(true);
|
|
528
|
+
console.log(chalk_1.default.green(`\n✓ ${result.message}`));
|
|
529
|
+
console.log(chalk_1.default.gray(` Jobs deleted: ${result.jobs_deleted}\n`));
|
|
530
|
+
}
|
|
531
|
+
catch (error) {
|
|
532
|
+
console.error(chalk_1.default.red('✗ Failed to clear jobs'));
|
|
533
|
+
console.error(chalk_1.default.red(error.response?.data?.detail || error.message));
|
|
534
|
+
process.exit(1);
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
/**
|
|
538
|
+
* Print detailed job status
|
|
539
|
+
*/
|
|
540
|
+
function printJobStatus(job) {
|
|
541
|
+
console.log(chalk_1.default.blue('\nJob Status:'));
|
|
542
|
+
console.log(chalk_1.default.gray(` ID: ${job.job_id}`));
|
|
543
|
+
console.log(chalk_1.default.gray(` Type: ${job.job_type}`));
|
|
544
|
+
// Format job status with icons
|
|
545
|
+
let statusDisplay = job.status;
|
|
546
|
+
switch (job.status) {
|
|
547
|
+
case 'completed':
|
|
548
|
+
statusDisplay = colors.status.success('✓ completed');
|
|
549
|
+
break;
|
|
550
|
+
case 'failed':
|
|
551
|
+
statusDisplay = colors.status.error('✗ failed');
|
|
552
|
+
break;
|
|
553
|
+
case 'processing':
|
|
554
|
+
statusDisplay = colors.status.info('⚙ processing');
|
|
555
|
+
break;
|
|
556
|
+
case 'approved':
|
|
557
|
+
statusDisplay = colors.status.success('✓ approved');
|
|
558
|
+
break;
|
|
559
|
+
case 'awaiting_approval':
|
|
560
|
+
statusDisplay = colors.status.warning('⏸ awaiting approval');
|
|
561
|
+
break;
|
|
562
|
+
case 'pending':
|
|
563
|
+
statusDisplay = colors.status.dim('○ pending');
|
|
564
|
+
break;
|
|
565
|
+
case 'queued':
|
|
566
|
+
statusDisplay = colors.status.info('⋯ queued');
|
|
567
|
+
break;
|
|
568
|
+
case 'cancelled':
|
|
569
|
+
statusDisplay = colors.status.dim('⊗ cancelled');
|
|
570
|
+
break;
|
|
571
|
+
default:
|
|
572
|
+
statusDisplay = colors.status.dim(job.status);
|
|
573
|
+
}
|
|
574
|
+
console.log(` Status: ${statusDisplay}`);
|
|
575
|
+
if (job.ontology) {
|
|
576
|
+
console.log(chalk_1.default.gray(` Ontology: ${job.ontology}`));
|
|
577
|
+
}
|
|
578
|
+
console.log(chalk_1.default.gray(` Created: ${new Date(job.created_at).toLocaleString()}`));
|
|
579
|
+
if (job.started_at) {
|
|
580
|
+
console.log(chalk_1.default.gray(` Started: ${new Date(job.started_at).toLocaleString()}`));
|
|
581
|
+
}
|
|
582
|
+
if (job.completed_at) {
|
|
583
|
+
console.log(chalk_1.default.gray(` Completed: ${new Date(job.completed_at).toLocaleString()}`));
|
|
584
|
+
const duration = (new Date(job.completed_at).getTime() - new Date(job.created_at).getTime()) / 1000;
|
|
585
|
+
console.log(chalk_1.default.gray(` Duration: ${duration.toFixed(1)}s`));
|
|
586
|
+
}
|
|
587
|
+
// ADR-014: Show analysis when available
|
|
588
|
+
if (job.analysis) {
|
|
589
|
+
console.log(chalk_1.default.blue('\nPre-Ingestion Analysis:'));
|
|
590
|
+
const a = job.analysis;
|
|
591
|
+
if (a.file_stats) {
|
|
592
|
+
console.log(chalk_1.default.gray(` File: ${a.file_stats.filename} (${a.file_stats.size_human})`));
|
|
593
|
+
console.log(chalk_1.default.gray(` Words: ${a.file_stats.word_count.toLocaleString()}`));
|
|
594
|
+
console.log(chalk_1.default.gray(` Estimated chunks: ~${a.file_stats.estimated_chunks}`));
|
|
595
|
+
}
|
|
596
|
+
if (a.cost_estimate) {
|
|
597
|
+
console.log(chalk_1.default.blue('\n💰 Cost Estimate:'));
|
|
598
|
+
const ce = a.cost_estimate;
|
|
599
|
+
console.log(chalk_1.default.gray(` Extraction (${ce.extraction.model}):`));
|
|
600
|
+
console.log(chalk_1.default.gray(` Tokens: ${ce.extraction.tokens_low.toLocaleString()}-${ce.extraction.tokens_high.toLocaleString()}`));
|
|
601
|
+
console.log(chalk_1.default.gray(` Cost: $${ce.extraction.cost_low.toFixed(2)}-$${ce.extraction.cost_high.toFixed(2)}`));
|
|
602
|
+
console.log(chalk_1.default.gray(` Embeddings (${ce.embeddings.model}):`));
|
|
603
|
+
console.log(chalk_1.default.gray(` Concepts: ${ce.embeddings.concepts_low}-${ce.embeddings.concepts_high}`));
|
|
604
|
+
console.log(chalk_1.default.gray(` Cost: $${ce.embeddings.cost_low.toFixed(2)}-$${ce.embeddings.cost_high.toFixed(2)}`));
|
|
605
|
+
console.log(chalk_1.default.bold(` Total: $${ce.total.cost_low.toFixed(2)}-$${ce.total.cost_high.toFixed(2)}`));
|
|
606
|
+
}
|
|
607
|
+
if (a.warnings && a.warnings.length > 0) {
|
|
608
|
+
console.log(chalk_1.default.yellow('\n⚠️ Warnings:'));
|
|
609
|
+
a.warnings.forEach((w) => console.log(chalk_1.default.yellow(` • ${w}`)));
|
|
610
|
+
}
|
|
611
|
+
if (job.status === 'awaiting_approval') {
|
|
612
|
+
console.log(chalk_1.default.blue('\n📌 Next Steps:'));
|
|
613
|
+
console.log(chalk_1.default.gray(` Approve: kg jobs approve ${job.job_id}`));
|
|
614
|
+
console.log(chalk_1.default.gray(` Cancel: kg jobs cancel ${job.job_id}`));
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
if (job.progress) {
|
|
618
|
+
console.log(chalk_1.default.blue('\nProgress:'));
|
|
619
|
+
const p = job.progress;
|
|
620
|
+
if (p.percent !== undefined) {
|
|
621
|
+
console.log(chalk_1.default.gray(` ${p.percent}% complete`));
|
|
622
|
+
}
|
|
623
|
+
if (p.chunks_total) {
|
|
624
|
+
console.log(chalk_1.default.gray(` Chunks: ${p.chunks_processed}/${p.chunks_total}`));
|
|
625
|
+
}
|
|
626
|
+
// Concept statistics
|
|
627
|
+
const conceptsNew = p.concepts_created || 0;
|
|
628
|
+
const conceptsLinked = p.concepts_linked || 0;
|
|
629
|
+
const conceptsTotal = conceptsNew + conceptsLinked;
|
|
630
|
+
if (conceptsTotal > 0) {
|
|
631
|
+
const hitRate = Math.round((conceptsLinked / conceptsTotal) * 100);
|
|
632
|
+
console.log(chalk_1.default.gray(` Concepts: ${conceptsTotal} total (${conceptsNew} new, ${conceptsLinked} reused)`));
|
|
633
|
+
console.log(chalk_1.default.gray(` Hit rate: ${hitRate}% (existing concepts reused)`));
|
|
634
|
+
}
|
|
635
|
+
if (p.instances_created) {
|
|
636
|
+
console.log(chalk_1.default.gray(` Instances: ${p.instances_created}`));
|
|
637
|
+
}
|
|
638
|
+
if (p.relationships_created) {
|
|
639
|
+
console.log(chalk_1.default.gray(` Relationships: ${p.relationships_created}`));
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
if (job.result) {
|
|
643
|
+
console.log(chalk_1.default.blue('\nResults:'));
|
|
644
|
+
const r = job.result;
|
|
645
|
+
if (r.stats) {
|
|
646
|
+
console.log(chalk_1.default.gray(` Chunks processed: ${r.stats.chunks_processed}`));
|
|
647
|
+
console.log(chalk_1.default.gray(` Concepts created: ${r.stats.concepts_created}`));
|
|
648
|
+
console.log(chalk_1.default.gray(` Sources created: ${r.stats.sources_created}`));
|
|
649
|
+
console.log(chalk_1.default.gray(` Relationships: ${r.stats.relationships_created}`));
|
|
650
|
+
}
|
|
651
|
+
if (r.cost) {
|
|
652
|
+
console.log(chalk_1.default.blue('\nCost:'));
|
|
653
|
+
console.log(chalk_1.default.gray(` Extraction: ${r.cost.extraction}`));
|
|
654
|
+
console.log(chalk_1.default.gray(` Embeddings: ${r.cost.embeddings}`));
|
|
655
|
+
console.log(chalk_1.default.gray(` Total: ${r.cost.total}`));
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
if (job.error) {
|
|
659
|
+
console.log(chalk_1.default.red('\nError:'));
|
|
660
|
+
console.log(chalk_1.default.red(` ${job.error}`));
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
//# sourceMappingURL=jobs.js.map
|