trucontext 0.8.5 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.js +74 -13
- package/package.json +1 -1
- package/src/commands/curiosity.js +4 -4
- package/src/commands/entities.js +9 -9
- package/src/commands/graph.js +101 -0
- package/src/commands/ingest.js +2 -2
- package/src/commands/init.js +2 -2
- package/src/commands/keys.js +63 -0
- package/src/commands/mind.js +66 -0
- package/src/commands/query.js +2 -2
- package/src/commands/recall.js +2 -2
- package/src/commands/recipes.js +36 -5
- package/src/commands/relationship-types.js +41 -4
- package/src/commands/roots.js +7 -7
- package/src/commands/settings.js +50 -0
package/bin/cli.js
CHANGED
|
@@ -12,15 +12,18 @@ import { initCommand } from '../src/commands/init.js';
|
|
|
12
12
|
import { ingestCommand } from '../src/commands/ingest.js';
|
|
13
13
|
import { queryCommand } from '../src/commands/query.js';
|
|
14
14
|
import { recallCommand } from '../src/commands/recall.js';
|
|
15
|
-
import { contextsListCommand, contextsCreateCommand, contextsDeleteCommand } from '../src/commands/contexts.js';
|
|
16
15
|
import { schemaShowCommand, schemaGenerateCommand, schemaSetAuthorshipCommand } from '../src/commands/schema.js';
|
|
17
16
|
import { entitiesListCommand, entitiesGetCommand, entitiesCreateCommand, entitiesUpdateCommand, entitiesDeleteCommand, entitiesEdgesCommand } from '../src/commands/entities.js';
|
|
18
|
-
import { recipesListCommand, recipesGetCommand, recipesCreateCommand, recipesDeleteCommand } from '../src/commands/recipes.js';
|
|
19
|
-
import { relationshipTypesListCommand } from '../src/commands/relationship-types.js';
|
|
17
|
+
import { recipesListCommand, recipesGetCommand, recipesCreateCommand, recipesUpdateCommand, recipesDeleteCommand } from '../src/commands/recipes.js';
|
|
18
|
+
import { relationshipTypesListCommand, relationshipTypesCreateCommand, relationshipTypesDeleteCommand } from '../src/commands/relationship-types.js';
|
|
20
19
|
import { docsListCommand, docsShowCommand } from '../src/commands/docs.js';
|
|
21
20
|
import { registerRootsCommand } from '../src/commands/roots.js';
|
|
22
21
|
import { registerCuriosityCommand } from '../src/commands/curiosity.js';
|
|
23
22
|
import { usageCommand, usageHistoryCommand, plansCommand } from '../src/commands/billing.js';
|
|
23
|
+
import { keysListCommand, keysCreateCommand, keysRevokeCommand } from '../src/commands/keys.js';
|
|
24
|
+
import { graphOverviewCommand, graphSearchCommand, graphNodeCommand, graphNeighborsCommand } from '../src/commands/graph.js';
|
|
25
|
+
import { mindPresenceCommand, mindThoughtsCommand } from '../src/commands/mind.js';
|
|
26
|
+
import { settingsShowCommand, settingsUpdateCommand } from '../src/commands/settings.js';
|
|
24
27
|
|
|
25
28
|
program
|
|
26
29
|
.name('trucontext')
|
|
@@ -83,15 +86,6 @@ program.command('recall <query>')
|
|
|
83
86
|
.option('-d, --depth <n>', 'Graph expansion depth', '2')
|
|
84
87
|
.action(recallCommand);
|
|
85
88
|
|
|
86
|
-
// Contexts (deprecated — use entities with contexts array)
|
|
87
|
-
const contexts = program.command('contexts').description('Manage contexts (deprecated — use entities)').action(function() { this.help(); });
|
|
88
|
-
contexts.command('list').description('List contexts').action(contextsListCommand);
|
|
89
|
-
contexts.command('create <name>')
|
|
90
|
-
.description('Create a context')
|
|
91
|
-
.option('--metadata <json>', 'JSON metadata object')
|
|
92
|
-
.action(contextsCreateCommand);
|
|
93
|
-
contexts.command('delete <id>').description('Delete a context').action(contextsDeleteCommand);
|
|
94
|
-
|
|
95
89
|
// Entities
|
|
96
90
|
const entities = program.command('entities').description('Manage entities').action(function() { this.help(); });
|
|
97
91
|
entities.command('list')
|
|
@@ -152,15 +146,31 @@ recipes.command('create')
|
|
|
152
146
|
.option('--decay-profile <text>', 'Decay profile description')
|
|
153
147
|
.option('--confidence-bias <text>', 'Confidence bias description')
|
|
154
148
|
.action(recipesCreateCommand);
|
|
149
|
+
recipes.command('update <recipeId>')
|
|
150
|
+
.description('Update a custom recipe')
|
|
151
|
+
.option('--name <name>', 'New name')
|
|
152
|
+
.option('--file <path>', 'JSON file with updated interpretation')
|
|
153
|
+
.option('--purpose <text>', 'Update purpose text')
|
|
154
|
+
.action(recipesUpdateCommand);
|
|
155
155
|
recipes.command('delete <recipeId>')
|
|
156
156
|
.description('Delete a recipe')
|
|
157
157
|
.action(recipesDeleteCommand);
|
|
158
158
|
|
|
159
159
|
// Relationship Types
|
|
160
|
-
program.command('relationship-types')
|
|
160
|
+
const relTypes = program.command('relationship-types').description('Manage relationship types').action(relationshipTypesListCommand);
|
|
161
|
+
relTypes.command('list')
|
|
161
162
|
.description('List relationship types')
|
|
162
163
|
.option('--category <cat>', 'Filter by category')
|
|
163
164
|
.action(relationshipTypesListCommand);
|
|
165
|
+
relTypes.command('create')
|
|
166
|
+
.description('Create a custom relationship type')
|
|
167
|
+
.requiredOption('--type <type>', 'Relationship type (UPPER_SNAKE_CASE)')
|
|
168
|
+
.requiredOption('--description <text>', 'Description of the relationship')
|
|
169
|
+
.option('--category <cat>', 'Category (default: Custom)')
|
|
170
|
+
.action(relationshipTypesCreateCommand);
|
|
171
|
+
relTypes.command('delete <type>')
|
|
172
|
+
.description('Delete a custom relationship type')
|
|
173
|
+
.action(relationshipTypesDeleteCommand);
|
|
164
174
|
|
|
165
175
|
// Schema
|
|
166
176
|
const schema = program.command('schema').description('Manage app schema').action(function() { this.help(); });
|
|
@@ -196,6 +206,57 @@ billing.command('plans')
|
|
|
196
206
|
.description('View available plans')
|
|
197
207
|
.action(plansCommand);
|
|
198
208
|
|
|
209
|
+
// API Keys
|
|
210
|
+
const keys = program.command('keys').description('Manage API keys').action(keysListCommand);
|
|
211
|
+
keys.command('list').description('List API keys').action(keysListCommand);
|
|
212
|
+
keys.command('create')
|
|
213
|
+
.description('Create a new API key')
|
|
214
|
+
.requiredOption('--name <name>', 'Key name')
|
|
215
|
+
.action(keysCreateCommand);
|
|
216
|
+
keys.command('revoke <keyId>')
|
|
217
|
+
.description('Revoke an API key')
|
|
218
|
+
.action(keysRevokeCommand);
|
|
219
|
+
|
|
220
|
+
// Graph Explorer
|
|
221
|
+
const graph = program.command('graph').description('Explore the knowledge graph').action(function() { this.help(); });
|
|
222
|
+
graph.command('overview')
|
|
223
|
+
.description('Graph overview (node/edge counts)')
|
|
224
|
+
.option('-l, --limit <n>', 'Max nodes to return', '100')
|
|
225
|
+
.action(graphOverviewCommand);
|
|
226
|
+
graph.command('search <query>')
|
|
227
|
+
.description('Search graph by keyword')
|
|
228
|
+
.option('--type <type>', 'Filter by node type')
|
|
229
|
+
.option('-l, --limit <n>', 'Max results', '50')
|
|
230
|
+
.action(graphSearchCommand);
|
|
231
|
+
graph.command('node <nodeId>')
|
|
232
|
+
.description('Get detailed node info')
|
|
233
|
+
.action(graphNodeCommand);
|
|
234
|
+
graph.command('neighbors <nodeId>')
|
|
235
|
+
.description('Get node neighbors')
|
|
236
|
+
.option('-l, --limit <n>', 'Max neighbors', '20')
|
|
237
|
+
.action(graphNeighborsCommand);
|
|
238
|
+
|
|
239
|
+
// Mind
|
|
240
|
+
const mind = program.command('mind').description('View mind state and thoughts').action(function() { this.help(); });
|
|
241
|
+
mind.command('presence')
|
|
242
|
+
.description('View consciousness state')
|
|
243
|
+
.action(mindPresenceCommand);
|
|
244
|
+
mind.command('thoughts')
|
|
245
|
+
.description('View dream diary')
|
|
246
|
+
.option('-l, --limit <n>', 'Max entries', '20')
|
|
247
|
+
.option('-m, --mode <mode>', 'Filter by dream type')
|
|
248
|
+
.action(mindThoughtsCommand);
|
|
249
|
+
|
|
250
|
+
// Settings
|
|
251
|
+
const settings = program.command('settings').description('Manage app settings').action(settingsShowCommand);
|
|
252
|
+
settings.command('show').description('Show current settings').action(settingsShowCommand);
|
|
253
|
+
settings.command('update')
|
|
254
|
+
.description('Update settings')
|
|
255
|
+
.option('--json <json>', 'JSON object with settings to update')
|
|
256
|
+
.option('--key <key>', 'Setting key')
|
|
257
|
+
.option('--value <value>', 'Setting value')
|
|
258
|
+
.action(settingsUpdateCommand);
|
|
259
|
+
|
|
199
260
|
// Root nodes + Curiosity (registered as subcommand groups)
|
|
200
261
|
registerRootsCommand(program);
|
|
201
262
|
registerCuriosityCommand(program);
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// Curiosity analysis is always scoped to a root node's ego network.
|
|
5
5
|
|
|
6
6
|
import chalk from 'chalk';
|
|
7
|
-
import {
|
|
7
|
+
import { dataPlane } from '../client.js';
|
|
8
8
|
import { getConfig, getActiveApp } from '../config.js';
|
|
9
9
|
|
|
10
10
|
export function registerCuriosityCommand(program) {
|
|
@@ -30,7 +30,7 @@ export function registerCuriosityCommand(program) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
try {
|
|
33
|
-
const res = await
|
|
33
|
+
const res = await dataPlane('GET', `/v1/curiosity?root_id=${rootId}&status=${opts.status}&limit=${opts.limit}`);
|
|
34
34
|
const packets = res.data?.packets || [];
|
|
35
35
|
|
|
36
36
|
if (packets.length === 0) {
|
|
@@ -69,7 +69,7 @@ export function registerCuriosityCommand(program) {
|
|
|
69
69
|
|
|
70
70
|
try {
|
|
71
71
|
console.log(chalk.dim(`Triggering curiosity analysis for root: ${rootId}...`));
|
|
72
|
-
await
|
|
72
|
+
await dataPlane('POST', `/v1/curiosity`, {
|
|
73
73
|
root_id: rootId,
|
|
74
74
|
});
|
|
75
75
|
console.log(chalk.green(`Curiosity analysis started for root: ${rootId}`));
|
|
@@ -87,7 +87,7 @@ export function registerCuriosityCommand(program) {
|
|
|
87
87
|
.action(async (packetId) => {
|
|
88
88
|
const appId = getActiveApp();
|
|
89
89
|
try {
|
|
90
|
-
await
|
|
90
|
+
await dataPlane('PUT', `/v1/curiosity/${packetId}/dismiss`);
|
|
91
91
|
console.log(chalk.green(`Dismissed: ${packetId}`));
|
|
92
92
|
} catch (err) {
|
|
93
93
|
console.error(chalk.red('Failed:'), err.response?.data?.error || err.message);
|
package/src/commands/entities.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {
|
|
2
|
+
import { dataPlane } from '../client.js';
|
|
3
3
|
import { getActiveApp } from '../config.js';
|
|
4
4
|
|
|
5
5
|
// Fields stored on the node but not user-declared properties
|
|
@@ -46,9 +46,9 @@ export async function entitiesListCommand(options) {
|
|
|
46
46
|
if (options.scope) params.set('scope', options.scope);
|
|
47
47
|
if (options.limit) params.set('limit', options.limit);
|
|
48
48
|
const qs = params.toString();
|
|
49
|
-
const path = `/
|
|
49
|
+
const path = `/v1/entities${qs ? `?${qs}` : ''}`;
|
|
50
50
|
|
|
51
|
-
const res = await
|
|
51
|
+
const res = await dataPlane('GET', path);
|
|
52
52
|
const entities = Array.isArray(res.data) ? res.data : [];
|
|
53
53
|
|
|
54
54
|
if (entities.length === 0) {
|
|
@@ -69,13 +69,13 @@ export async function entitiesListCommand(options) {
|
|
|
69
69
|
export async function entitiesGetCommand(entityId) {
|
|
70
70
|
try {
|
|
71
71
|
const appId = getActiveApp();
|
|
72
|
-
const res = await
|
|
72
|
+
const res = await dataPlane('GET', `/v1/entities/${entityId}`);
|
|
73
73
|
const e = res.data;
|
|
74
74
|
displayEntity(e);
|
|
75
75
|
|
|
76
76
|
// Show edges if available
|
|
77
77
|
try {
|
|
78
|
-
const edgeRes = await
|
|
78
|
+
const edgeRes = await dataPlane('GET', `/v1/entities/${entityId}/edges`);
|
|
79
79
|
const edges = edgeRes.data;
|
|
80
80
|
if (edges.length > 0) {
|
|
81
81
|
console.log(chalk.dim(`\n Edges (${edges.length}):`));
|
|
@@ -137,7 +137,7 @@ export async function entitiesCreateCommand(options) {
|
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
const res = await
|
|
140
|
+
const res = await dataPlane('POST', `/v1/entities`, body);
|
|
141
141
|
const e = res.data;
|
|
142
142
|
console.log(chalk.green(`Created: ${chalk.bold(e.entityId || options.id)}`));
|
|
143
143
|
} catch (err) {
|
|
@@ -178,7 +178,7 @@ export async function entitiesUpdateCommand(entityId, options) {
|
|
|
178
178
|
});
|
|
179
179
|
}
|
|
180
180
|
|
|
181
|
-
await
|
|
181
|
+
await dataPlane('PUT', `/v1/entities/${entityId}`, body);
|
|
182
182
|
console.log(chalk.green(`Updated: ${entityId}`));
|
|
183
183
|
} catch (err) {
|
|
184
184
|
console.error(chalk.red(`Failed: ${err.message}`));
|
|
@@ -189,7 +189,7 @@ export async function entitiesUpdateCommand(entityId, options) {
|
|
|
189
189
|
export async function entitiesDeleteCommand(entityId) {
|
|
190
190
|
try {
|
|
191
191
|
const appId = getActiveApp();
|
|
192
|
-
await
|
|
192
|
+
await dataPlane('DELETE', `/v1/entities/${entityId}`);
|
|
193
193
|
console.log(chalk.green(`Deleted: ${entityId}`));
|
|
194
194
|
} catch (err) {
|
|
195
195
|
console.error(chalk.red(`Failed: ${err.message}`));
|
|
@@ -200,7 +200,7 @@ export async function entitiesDeleteCommand(entityId) {
|
|
|
200
200
|
export async function entitiesEdgesCommand(entityId) {
|
|
201
201
|
try {
|
|
202
202
|
const appId = getActiveApp();
|
|
203
|
-
const res = await
|
|
203
|
+
const res = await dataPlane('GET', `/v1/entities/${entityId}/edges`);
|
|
204
204
|
const edges = Array.isArray(res.data) ? res.data : [];
|
|
205
205
|
|
|
206
206
|
if (edges.length === 0) {
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { dataPlane } from '../client.js';
|
|
3
|
+
|
|
4
|
+
export async function graphOverviewCommand(options) {
|
|
5
|
+
try {
|
|
6
|
+
const res = await dataPlane('GET', `/v1/graph/overview?limit=${options.limit || 100}`);
|
|
7
|
+
const data = res.data;
|
|
8
|
+
|
|
9
|
+
console.log(chalk.bold('Graph Overview'));
|
|
10
|
+
if (data.stats) {
|
|
11
|
+
const s = data.stats;
|
|
12
|
+
console.log(` Nodes: ${s.nodeCount || 0}`);
|
|
13
|
+
console.log(` Edges: ${s.edgeCount || 0}`);
|
|
14
|
+
if (s.typeCounts) {
|
|
15
|
+
console.log(' By type:');
|
|
16
|
+
for (const [type, count] of Object.entries(s.typeCounts)) {
|
|
17
|
+
console.log(` ${type}: ${count}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (data.nodes && data.nodes.length > 0) {
|
|
22
|
+
console.log(`\n ${data.nodes.length} nodes returned`);
|
|
23
|
+
}
|
|
24
|
+
} catch (err) {
|
|
25
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function graphSearchCommand(query, options) {
|
|
31
|
+
try {
|
|
32
|
+
const params = [`q=${encodeURIComponent(query)}`];
|
|
33
|
+
if (options.type) params.push(`type=${options.type}`);
|
|
34
|
+
if (options.limit) params.push(`limit=${options.limit}`);
|
|
35
|
+
const res = await dataPlane('GET', `/v1/graph/search?${params.join('&')}`);
|
|
36
|
+
const nodes = res.data?.nodes || res.data || [];
|
|
37
|
+
|
|
38
|
+
if (nodes.length === 0) {
|
|
39
|
+
console.log('No matches found.');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
for (const node of nodes) {
|
|
44
|
+
const label = node.label || node.displayName || node.name || node.entityId || node.id;
|
|
45
|
+
const type = node.type || (node.labels || []).filter(l => l !== 'Entity')[0] || '?';
|
|
46
|
+
console.log(`${chalk.bold(label)} [${type}]`);
|
|
47
|
+
if (node.snippet) console.log(` ${chalk.dim(node.snippet.slice(0, 120))}`);
|
|
48
|
+
}
|
|
49
|
+
console.log(`\n${nodes.length} result${nodes.length !== 1 ? 's' : ''}`);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function graphNodeCommand(nodeId) {
|
|
57
|
+
try {
|
|
58
|
+
const res = await dataPlane('GET', `/v1/graph/node/${encodeURIComponent(nodeId)}`);
|
|
59
|
+
const node = res.data;
|
|
60
|
+
if (!node) {
|
|
61
|
+
console.log('Node not found.');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
console.log(chalk.bold(node.label || node.displayName || node.name || nodeId));
|
|
65
|
+
console.log(` Type: ${node.type || (node.labels || []).join(', ')}`);
|
|
66
|
+
if (node.properties) {
|
|
67
|
+
for (const [k, v] of Object.entries(node.properties)) {
|
|
68
|
+
console.log(` ${k}: ${v}`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (node.edges) {
|
|
72
|
+
console.log(` Edges: ${node.edges.length}`);
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export async function graphNeighborsCommand(nodeId, options) {
|
|
81
|
+
try {
|
|
82
|
+
const res = await dataPlane('GET', `/v1/graph/neighbors/${encodeURIComponent(nodeId)}?limit=${options.limit || 20}`);
|
|
83
|
+
const neighbors = res.data?.neighbors || res.data || [];
|
|
84
|
+
|
|
85
|
+
if (neighbors.length === 0) {
|
|
86
|
+
console.log('No neighbors found.');
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
for (const n of neighbors) {
|
|
91
|
+
const label = n.label || n.displayName || n.name || n.entityId || n.id;
|
|
92
|
+
const type = n.type || '?';
|
|
93
|
+
const rel = n.relationship || n.edgeType || '';
|
|
94
|
+
console.log(` ${rel ? `[${rel}]` : ''} ${chalk.bold(label)} (${type})`);
|
|
95
|
+
}
|
|
96
|
+
console.log(`\n${neighbors.length} neighbor${neighbors.length !== 1 ? 's' : ''}`);
|
|
97
|
+
} catch (err) {
|
|
98
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
}
|
package/src/commands/ingest.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { readFileSync, existsSync } from 'fs';
|
|
3
3
|
import { basename } from 'path';
|
|
4
|
-
import {
|
|
4
|
+
import { dataPlane } from '../client.js';
|
|
5
5
|
import { getActiveApp } from '../config.js';
|
|
6
6
|
|
|
7
7
|
export async function ingestCommand(source, options) {
|
|
@@ -52,7 +52,7 @@ export async function ingestCommand(source, options) {
|
|
|
52
52
|
};
|
|
53
53
|
});
|
|
54
54
|
|
|
55
|
-
const res = await
|
|
55
|
+
const res = await dataPlane('POST', `/v1/ingest`, body);
|
|
56
56
|
const data = res.data;
|
|
57
57
|
console.log(chalk.green('Accepted'));
|
|
58
58
|
console.log(chalk.dim(`Content ID: ${data.contentId}`));
|
package/src/commands/init.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import input from '@inquirer/input';
|
|
3
3
|
import select from '@inquirer/select';
|
|
4
|
-
import { controlPlane } from '../client.js';
|
|
4
|
+
import { controlPlane, dataPlane } from '../client.js';
|
|
5
5
|
import { setActiveApp } from '../config.js';
|
|
6
6
|
|
|
7
7
|
export async function initCommand(name, options) {
|
|
@@ -105,7 +105,7 @@ export async function initCommand(name, options) {
|
|
|
105
105
|
const rootName = await input({ message: 'Display name (e.g., Dustin Henderson):' });
|
|
106
106
|
|
|
107
107
|
try {
|
|
108
|
-
await
|
|
108
|
+
await dataPlane('POST', `/v1/roots`, {
|
|
109
109
|
entityId: rootId,
|
|
110
110
|
type: rootType,
|
|
111
111
|
recipe_id: rootRecipe,
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { controlPlane } from '../client.js';
|
|
3
|
+
import { getActiveApp } from '../config.js';
|
|
4
|
+
|
|
5
|
+
export async function keysListCommand() {
|
|
6
|
+
try {
|
|
7
|
+
const appId = getActiveApp();
|
|
8
|
+
const res = await controlPlane('GET', `/apps/${appId}/keys`);
|
|
9
|
+
const keys = Array.isArray(res.data) ? res.data : [];
|
|
10
|
+
|
|
11
|
+
if (keys.length === 0) {
|
|
12
|
+
console.log('No API keys. Create one with: trucontext keys create --name "My Key"');
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
for (const key of keys) {
|
|
17
|
+
const status = key.status === 'active'
|
|
18
|
+
? chalk.green('Active')
|
|
19
|
+
: chalk.red(key.status || 'Unknown');
|
|
20
|
+
console.log(`${chalk.bold(key.name || key.keyId)} ${status}`);
|
|
21
|
+
console.log(` ID: ${key.keyId}`);
|
|
22
|
+
if (key.createdAt) console.log(` Created: ${key.createdAt}`);
|
|
23
|
+
if (key.lastUsed) console.log(` Last used: ${key.lastUsed}`);
|
|
24
|
+
console.log('');
|
|
25
|
+
}
|
|
26
|
+
console.log(`${keys.length} key${keys.length !== 1 ? 's' : ''}`);
|
|
27
|
+
} catch (err) {
|
|
28
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function keysCreateCommand(options) {
|
|
34
|
+
try {
|
|
35
|
+
const appId = getActiveApp();
|
|
36
|
+
if (!options.name) {
|
|
37
|
+
console.error(chalk.red('--name is required'));
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
const res = await controlPlane('POST', `/apps/${appId}/keys`, { name: options.name });
|
|
41
|
+
const key = res.data;
|
|
42
|
+
|
|
43
|
+
console.log(chalk.green('API Key Created'));
|
|
44
|
+
console.log(` Name: ${key.name || options.name}`);
|
|
45
|
+
console.log(` Key: ${chalk.bold(key.plainKey || key.key)}`);
|
|
46
|
+
console.log('');
|
|
47
|
+
console.log(chalk.yellow('Save this key now — you will not see it again.'));
|
|
48
|
+
} catch (err) {
|
|
49
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function keysRevokeCommand(keyId) {
|
|
55
|
+
try {
|
|
56
|
+
const appId = getActiveApp();
|
|
57
|
+
await controlPlane('DELETE', `/apps/${appId}/keys/${keyId}`);
|
|
58
|
+
console.log(chalk.green(`Revoked: ${keyId}`));
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { dataPlane } from '../client.js';
|
|
3
|
+
|
|
4
|
+
export async function mindPresenceCommand() {
|
|
5
|
+
try {
|
|
6
|
+
const res = await dataPlane('GET', '/v1/mind/presence');
|
|
7
|
+
const p = res.data;
|
|
8
|
+
|
|
9
|
+
console.log(chalk.bold('Mind Presence'));
|
|
10
|
+
if (p.status) console.log(` Status: ${p.status}`);
|
|
11
|
+
if (p.lastCycle) console.log(` Last cycle: ${p.lastCycle}`);
|
|
12
|
+
if (p.cycleNumber != null) console.log(` Cycle: ${p.cycleNumber}`);
|
|
13
|
+
if (p.events != null) console.log(` Events: ${p.events}`);
|
|
14
|
+
if (p.insights != null) console.log(` Insights: ${p.insights}`);
|
|
15
|
+
if (p.patterns != null) console.log(` Patterns: ${p.patterns}`);
|
|
16
|
+
if (p.confirmed != null) console.log(` Confirmed: ${p.confirmed}`);
|
|
17
|
+
if (p.rejected != null) console.log(` Rejected: ${p.rejected}`);
|
|
18
|
+
if (p.thought) {
|
|
19
|
+
console.log(`\n ${chalk.italic(p.thought.slice(0, 200))}`);
|
|
20
|
+
}
|
|
21
|
+
} catch (err) {
|
|
22
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function mindThoughtsCommand(options) {
|
|
28
|
+
try {
|
|
29
|
+
const params = [];
|
|
30
|
+
if (options.limit) params.push(`limit=${options.limit}`);
|
|
31
|
+
if (options.mode) params.push(`mode=${options.mode}`);
|
|
32
|
+
const qs = params.length > 0 ? `?${params.join('&')}` : '';
|
|
33
|
+
const res = await dataPlane('GET', `/v1/mind/thoughts${qs}`);
|
|
34
|
+
const thoughts = res.data?.thoughts || res.data || [];
|
|
35
|
+
|
|
36
|
+
if (thoughts.length === 0) {
|
|
37
|
+
console.log('No thoughts recorded yet.');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
for (const t of thoughts) {
|
|
42
|
+
const mode = t.mode || t.dream_type || '?';
|
|
43
|
+
const cycle = t.cycle_number != null ? `cycle ${t.cycle_number}` : '';
|
|
44
|
+
const ts = t.created_at || t.createdAt || '';
|
|
45
|
+
const ago = ts ? timeSince(ts) : '';
|
|
46
|
+
console.log(` ${chalk.cyan(`[${mode}]`)} ${cycle} ${chalk.dim(ago)}`);
|
|
47
|
+
if (t.diary || t.thought) {
|
|
48
|
+
console.log(` ${(t.diary || t.thought).slice(0, 200)}`);
|
|
49
|
+
}
|
|
50
|
+
console.log('');
|
|
51
|
+
}
|
|
52
|
+
console.log(`${thoughts.length} thought${thoughts.length !== 1 ? 's' : ''}`);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function timeSince(dateStr) {
|
|
60
|
+
const diff = Date.now() - new Date(dateStr).getTime();
|
|
61
|
+
const mins = Math.floor(diff / 60000);
|
|
62
|
+
if (mins < 60) return `${mins}m ago`;
|
|
63
|
+
const hours = Math.floor(mins / 60);
|
|
64
|
+
if (hours < 24) return `${hours}h ago`;
|
|
65
|
+
return `${Math.floor(hours / 24)}d ago`;
|
|
66
|
+
}
|
package/src/commands/query.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {
|
|
2
|
+
import { dataPlane } from '../client.js';
|
|
3
3
|
import { getConfig, getActiveApp } from '../config.js';
|
|
4
4
|
|
|
5
5
|
export async function queryCommand(question, options) {
|
|
@@ -27,7 +27,7 @@ export async function queryCommand(question, options) {
|
|
|
27
27
|
|
|
28
28
|
if (options.context) body.context_id = options.context;
|
|
29
29
|
|
|
30
|
-
const res = await
|
|
30
|
+
const res = await dataPlane('POST', `/v1/query`, body);
|
|
31
31
|
const data = res.data;
|
|
32
32
|
|
|
33
33
|
// Print answer
|
package/src/commands/recall.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {
|
|
2
|
+
import { dataPlane } from '../client.js';
|
|
3
3
|
import { getConfig, getActiveApp } from '../config.js';
|
|
4
4
|
|
|
5
5
|
export async function recallCommand(query, options) {
|
|
@@ -22,7 +22,7 @@ export async function recallCommand(query, options) {
|
|
|
22
22
|
|
|
23
23
|
if (options.context) body.context_id = options.context;
|
|
24
24
|
|
|
25
|
-
const res = await
|
|
25
|
+
const res = await dataPlane('POST', `/v1/recall`, body);
|
|
26
26
|
const data = res.data;
|
|
27
27
|
|
|
28
28
|
// Print synthesis
|
package/src/commands/recipes.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFileSync } from 'fs';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import {
|
|
3
|
+
import { dataPlane } from '../client.js';
|
|
4
4
|
import { getActiveApp } from '../config.js';
|
|
5
5
|
|
|
6
6
|
function requireApp() {
|
|
@@ -15,7 +15,7 @@ function requireApp() {
|
|
|
15
15
|
export async function recipesListCommand() {
|
|
16
16
|
try {
|
|
17
17
|
const appId = requireApp();
|
|
18
|
-
const res = await
|
|
18
|
+
const res = await dataPlane('GET', `/v1/recipes`);
|
|
19
19
|
const recipes = res.data;
|
|
20
20
|
|
|
21
21
|
if (recipes.length === 0) {
|
|
@@ -36,7 +36,7 @@ export async function recipesListCommand() {
|
|
|
36
36
|
export async function recipesGetCommand(recipeId) {
|
|
37
37
|
try {
|
|
38
38
|
const appId = requireApp();
|
|
39
|
-
const res = await
|
|
39
|
+
const res = await dataPlane('GET', `/v1/recipes/${recipeId}`);
|
|
40
40
|
const r = res.data;
|
|
41
41
|
|
|
42
42
|
console.log(chalk.bold(r.recipeId || recipeId));
|
|
@@ -138,7 +138,7 @@ export async function recipesCreateCommand(options) {
|
|
|
138
138
|
if (options.confidenceBias) body.interpretation.confidence_bias = options.confidenceBias;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
const res = await
|
|
141
|
+
const res = await dataPlane('POST', `/v1/recipes`, body);
|
|
142
142
|
const r = res.data;
|
|
143
143
|
console.log(chalk.green(`Created: ${chalk.bold(r.recipeId || options.id)}`));
|
|
144
144
|
} catch (err) {
|
|
@@ -147,10 +147,41 @@ export async function recipesCreateCommand(options) {
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
export async function recipesUpdateCommand(recipeId, options) {
|
|
151
|
+
try {
|
|
152
|
+
const appId = requireApp();
|
|
153
|
+
const body = {};
|
|
154
|
+
|
|
155
|
+
if (options.name) body.name = options.name;
|
|
156
|
+
|
|
157
|
+
if (options.file) {
|
|
158
|
+
const fs = await import('fs');
|
|
159
|
+
const content = fs.readFileSync(options.file, 'utf8');
|
|
160
|
+
body.interpretation = JSON.parse(content);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (options.purpose) {
|
|
164
|
+
body.interpretation = body.interpretation || {};
|
|
165
|
+
body.interpretation.purpose = options.purpose;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (Object.keys(body).length === 0) {
|
|
169
|
+
console.error(chalk.red('Nothing to update. Provide --name, --file, or --purpose'));
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const res = await dataPlane('PUT', `/v1/recipes/${recipeId}`, body);
|
|
174
|
+
console.log(chalk.green(`Updated: ${recipeId}`));
|
|
175
|
+
} catch (err) {
|
|
176
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
150
181
|
export async function recipesDeleteCommand(recipeId) {
|
|
151
182
|
try {
|
|
152
183
|
const appId = requireApp();
|
|
153
|
-
await
|
|
184
|
+
await dataPlane('DELETE', `/v1/recipes/${recipeId}`);
|
|
154
185
|
console.log(chalk.green(`Deleted: ${recipeId}`));
|
|
155
186
|
} catch (err) {
|
|
156
187
|
console.error(chalk.red(`Failed: ${err.message}`));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
import {
|
|
2
|
+
import { dataPlane } from '../client.js';
|
|
3
3
|
import { getActiveApp } from '../config.js';
|
|
4
4
|
|
|
5
5
|
export async function relationshipTypesListCommand(options) {
|
|
@@ -13,10 +13,10 @@ export async function relationshipTypesListCommand(options) {
|
|
|
13
13
|
const params = new URLSearchParams();
|
|
14
14
|
if (options.category) params.set('category', options.category);
|
|
15
15
|
const qs = params.toString();
|
|
16
|
-
const path = `/
|
|
16
|
+
const path = `/v1/relationship-types${qs ? `?${qs}` : ''}`;
|
|
17
17
|
|
|
18
|
-
const res = await
|
|
19
|
-
const types = res.data;
|
|
18
|
+
const res = await dataPlane('GET', path);
|
|
19
|
+
const types = res.data.types;
|
|
20
20
|
|
|
21
21
|
if (Array.isArray(types) && types.length === 0) {
|
|
22
22
|
console.log(chalk.yellow('No relationship types found.'));
|
|
@@ -54,3 +54,40 @@ export async function relationshipTypesListCommand(options) {
|
|
|
54
54
|
process.exit(1);
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
+
|
|
58
|
+
export async function relationshipTypesCreateCommand(options) {
|
|
59
|
+
try {
|
|
60
|
+
const appId = getActiveApp();
|
|
61
|
+
if (!options.type) {
|
|
62
|
+
console.error(chalk.red('--type is required'));
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
if (!options.description) {
|
|
66
|
+
console.error(chalk.red('--description is required'));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const body = {
|
|
71
|
+
type: options.type,
|
|
72
|
+
description: options.description,
|
|
73
|
+
category: options.category || 'Custom',
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const res = await dataPlane('POST', '/v1/relationship-types', body);
|
|
77
|
+
console.log(chalk.green(`Created: ${chalk.bold(res.data.type)}`));
|
|
78
|
+
} catch (err) {
|
|
79
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
80
|
+
process.exit(1);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export async function relationshipTypesDeleteCommand(type) {
|
|
85
|
+
try {
|
|
86
|
+
const appId = getActiveApp();
|
|
87
|
+
await dataPlane('DELETE', `/v1/relationship-types/${encodeURIComponent(type)}`);
|
|
88
|
+
console.log(chalk.green(`Deleted: ${type}`));
|
|
89
|
+
} catch (err) {
|
|
90
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
91
|
+
process.exit(1);
|
|
92
|
+
}
|
|
93
|
+
}
|
package/src/commands/roots.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// carry recipes, and control which dreams run. Queries require a root_id.
|
|
5
5
|
|
|
6
6
|
import chalk from 'chalk';
|
|
7
|
-
import {
|
|
7
|
+
import { dataPlane } from '../client.js';
|
|
8
8
|
import { getConfig, saveConfig, getActiveApp } from '../config.js';
|
|
9
9
|
|
|
10
10
|
export function registerRootsCommand(program) {
|
|
@@ -55,7 +55,7 @@ export function registerRootsCommand(program) {
|
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
const appId = getActiveApp();
|
|
58
|
-
const res = await
|
|
58
|
+
const res = await dataPlane('POST', `/v1/roots`, body);
|
|
59
59
|
const r = res.data;
|
|
60
60
|
console.log(chalk.green(`Root node created: ${r.entityId}`));
|
|
61
61
|
console.log(` Type: ${r.type}`);
|
|
@@ -75,7 +75,7 @@ export function registerRootsCommand(program) {
|
|
|
75
75
|
.action(async () => {
|
|
76
76
|
try {
|
|
77
77
|
const appId = getActiveApp();
|
|
78
|
-
const res = await
|
|
78
|
+
const res = await dataPlane('GET', `/v1/roots`);
|
|
79
79
|
const rootNodes = Array.isArray(res.data) ? res.data : [];
|
|
80
80
|
if (rootNodes.length === 0) {
|
|
81
81
|
console.log('No root nodes. Create one with: trucontext roots create');
|
|
@@ -102,7 +102,7 @@ export function registerRootsCommand(program) {
|
|
|
102
102
|
.action(async (rootId) => {
|
|
103
103
|
try {
|
|
104
104
|
const appId = getActiveApp();
|
|
105
|
-
const res = await
|
|
105
|
+
const res = await dataPlane('GET', `/v1/roots/${rootId}`);
|
|
106
106
|
const r = res.data;
|
|
107
107
|
console.log(chalk.bold(`Root: ${r.entityId}`));
|
|
108
108
|
console.log(` Type: ${r.type}`);
|
|
@@ -148,7 +148,7 @@ export function registerRootsCommand(program) {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
const appId = getActiveApp();
|
|
151
|
-
await
|
|
151
|
+
await dataPlane('PUT', `/v1/roots/${rootId}`, body);
|
|
152
152
|
console.log(chalk.green(`Updated: ${rootId}`));
|
|
153
153
|
} catch (err) {
|
|
154
154
|
console.error(chalk.red('Failed:'), err.response?.data?.error || err.message);
|
|
@@ -163,7 +163,7 @@ export function registerRootsCommand(program) {
|
|
|
163
163
|
.action(async (rootId) => {
|
|
164
164
|
try {
|
|
165
165
|
const appId = getActiveApp();
|
|
166
|
-
await
|
|
166
|
+
await dataPlane('DELETE', `/v1/roots/${rootId}`);
|
|
167
167
|
console.log(chalk.green(`Demoted: ${rootId} (no longer a root node)`));
|
|
168
168
|
|
|
169
169
|
const config = getConfig();
|
|
@@ -184,7 +184,7 @@ export function registerRootsCommand(program) {
|
|
|
184
184
|
.action(async (rootId) => {
|
|
185
185
|
try {
|
|
186
186
|
const appId = getActiveApp();
|
|
187
|
-
await
|
|
187
|
+
await dataPlane('GET', `/v1/roots/${rootId}`);
|
|
188
188
|
const config = getConfig();
|
|
189
189
|
config.activeRoot = rootId;
|
|
190
190
|
saveConfig(config);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { controlPlane } from '../client.js';
|
|
3
|
+
import { getActiveApp } from '../config.js';
|
|
4
|
+
|
|
5
|
+
export async function settingsShowCommand() {
|
|
6
|
+
try {
|
|
7
|
+
const appId = getActiveApp();
|
|
8
|
+
const res = await controlPlane('GET', `/apps/${appId}/settings`);
|
|
9
|
+
const settings = res.data;
|
|
10
|
+
|
|
11
|
+
console.log(chalk.bold('App Settings'));
|
|
12
|
+
if (typeof settings === 'object') {
|
|
13
|
+
for (const [k, v] of Object.entries(settings)) {
|
|
14
|
+
const val = typeof v === 'object' ? JSON.stringify(v) : v;
|
|
15
|
+
console.log(` ${k}: ${val}`);
|
|
16
|
+
}
|
|
17
|
+
} else {
|
|
18
|
+
console.log(' No settings configured.');
|
|
19
|
+
}
|
|
20
|
+
} catch (err) {
|
|
21
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function settingsUpdateCommand(options) {
|
|
27
|
+
try {
|
|
28
|
+
const appId = getActiveApp();
|
|
29
|
+
let updates;
|
|
30
|
+
if (options.json) {
|
|
31
|
+
try {
|
|
32
|
+
updates = JSON.parse(options.json);
|
|
33
|
+
} catch {
|
|
34
|
+
console.error(chalk.red('Invalid JSON'));
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
} else if (options.key && options.value !== undefined) {
|
|
38
|
+
updates = { [options.key]: options.value };
|
|
39
|
+
} else {
|
|
40
|
+
console.error(chalk.red('Provide --json or --key + --value'));
|
|
41
|
+
process.exit(1);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const res = await controlPlane('PUT', `/apps/${appId}/settings`, updates);
|
|
45
|
+
console.log(chalk.green('Settings updated'));
|
|
46
|
+
} catch (err) {
|
|
47
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
}
|