trucontext 0.9.0 → 0.9.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/bin/cli.js +31 -1
- package/package.json +1 -1
- package/src/commands/agents.js +75 -0
- package/src/commands/entities.js +58 -0
- package/src/commands/settings.js +2 -2
package/bin/cli.js
CHANGED
|
@@ -13,7 +13,7 @@ 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
15
|
import { schemaShowCommand, schemaGenerateCommand, schemaSetAuthorshipCommand } from '../src/commands/schema.js';
|
|
16
|
-
import { entitiesListCommand, entitiesGetCommand, entitiesCreateCommand, entitiesUpdateCommand, entitiesDeleteCommand, entitiesEdgesCommand } from '../src/commands/entities.js';
|
|
16
|
+
import { entitiesListCommand, entitiesGetCommand, entitiesCreateCommand, entitiesUpdateCommand, entitiesDeleteCommand, entitiesEdgesCommand, edgesCreateCommand, edgesDeleteCommand } from '../src/commands/entities.js';
|
|
17
17
|
import { recipesListCommand, recipesGetCommand, recipesCreateCommand, recipesUpdateCommand, recipesDeleteCommand } from '../src/commands/recipes.js';
|
|
18
18
|
import { relationshipTypesListCommand, relationshipTypesCreateCommand, relationshipTypesDeleteCommand } from '../src/commands/relationship-types.js';
|
|
19
19
|
import { docsListCommand, docsShowCommand } from '../src/commands/docs.js';
|
|
@@ -24,6 +24,7 @@ import { keysListCommand, keysCreateCommand, keysRevokeCommand } from '../src/co
|
|
|
24
24
|
import { graphOverviewCommand, graphSearchCommand, graphNodeCommand, graphNeighborsCommand } from '../src/commands/graph.js';
|
|
25
25
|
import { mindPresenceCommand, mindThoughtsCommand } from '../src/commands/mind.js';
|
|
26
26
|
import { settingsShowCommand, settingsUpdateCommand } from '../src/commands/settings.js';
|
|
27
|
+
import { provisionCommand } from '../src/commands/agents.js';
|
|
27
28
|
|
|
28
29
|
program
|
|
29
30
|
.name('trucontext')
|
|
@@ -128,6 +129,19 @@ entities.command('delete <entityId>')
|
|
|
128
129
|
entities.command('edges <entityId>')
|
|
129
130
|
.description('List edges for an entity')
|
|
130
131
|
.action(entitiesEdgesCommand);
|
|
132
|
+
entities.command('edges-create')
|
|
133
|
+
.description('Create an edge between two entities')
|
|
134
|
+
.requiredOption('--type <type>', 'Edge type (UPPER_SNAKE_CASE)')
|
|
135
|
+
.requiredOption('--from <entityId>', 'Source entity ID')
|
|
136
|
+
.requiredOption('--to <entityId>', 'Target entity ID')
|
|
137
|
+
.option('--properties <json>', 'Edge properties as JSON')
|
|
138
|
+
.action(edgesCreateCommand);
|
|
139
|
+
entities.command('edges-delete')
|
|
140
|
+
.description('Delete an edge between two entities')
|
|
141
|
+
.requiredOption('--type <type>', 'Edge type')
|
|
142
|
+
.requiredOption('--from <entityId>', 'Source entity ID')
|
|
143
|
+
.requiredOption('--to <entityId>', 'Target entity ID')
|
|
144
|
+
.action(edgesDeleteCommand);
|
|
131
145
|
|
|
132
146
|
// Recipes
|
|
133
147
|
const recipes = program.command('recipes').description('Manage recipes').action(function() { this.help(); });
|
|
@@ -261,4 +275,20 @@ settings.command('update')
|
|
|
261
275
|
registerRootsCommand(program);
|
|
262
276
|
registerCuriosityCommand(program);
|
|
263
277
|
|
|
278
|
+
// Agent provision
|
|
279
|
+
const agents = program.command('agents').description('Agent provisioning');
|
|
280
|
+
agents.command('provision')
|
|
281
|
+
.description('Provision an agent (create or update root node, ingest content, generate memory briefing)')
|
|
282
|
+
.requiredOption('--agent-id <id>', 'Agent identifier')
|
|
283
|
+
.requiredOption('--name <name>', 'Agent display name')
|
|
284
|
+
.requiredOption('--role <role>', 'Agent role description')
|
|
285
|
+
.option('--user-root <root>', 'User root node ID')
|
|
286
|
+
.requiredOption('--soul <fileOrText>', 'Path to SOUL.md or inline text')
|
|
287
|
+
.option('--agents <fileOrText>', 'Path to AGENTS.md or inline text')
|
|
288
|
+
.option('--identity <fileOrText>', 'Path to IDENTITY.md or inline text')
|
|
289
|
+
.option('--memory <files...>', 'Path(s) to memory files')
|
|
290
|
+
.option('--recipe <recipeId>', 'Recipe hint (skip inference)')
|
|
291
|
+
.option('--dry-run', 'Preview what would happen without doing it')
|
|
292
|
+
.action(provisionCommand);
|
|
293
|
+
|
|
264
294
|
program.parse();
|
package/package.json
CHANGED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// commands/agents.js — Agent Provision CLI
|
|
2
|
+
//
|
|
3
|
+
// trucontext agents provision --agent-id <id> --name <name> --role <role> \
|
|
4
|
+
// --user-root <root> --soul <file> [--agents <file>] [--identity <file>] \
|
|
5
|
+
// [--memory <file>...] [--recipe <recipeId>] [--dry-run]
|
|
6
|
+
|
|
7
|
+
import { readFileSync, existsSync } from 'fs';
|
|
8
|
+
import { dataPlane } from '../client.js';
|
|
9
|
+
import { getConfig } from '../config.js';
|
|
10
|
+
|
|
11
|
+
export async function provisionCommand(options) {
|
|
12
|
+
const config = getConfig();
|
|
13
|
+
if (!config.activeApp) {
|
|
14
|
+
console.error('No active app. Run: trucontext use <app>');
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { agentId, name, role, userRoot, soul, agents, identity, memory, recipe, dryRun } = options;
|
|
19
|
+
|
|
20
|
+
// Read file contents
|
|
21
|
+
const soulText = readFileOrText(soul);
|
|
22
|
+
if (!soulText) {
|
|
23
|
+
console.error('--soul is required (file path or inline text)');
|
|
24
|
+
process.exit(1);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const content = {
|
|
28
|
+
soul: soulText,
|
|
29
|
+
agents: agents ? readFileOrText(agents) : undefined,
|
|
30
|
+
identity: identity ? readFileOrText(identity) : undefined,
|
|
31
|
+
memory: (memory || []).map(m => readFileOrText(m)).filter(Boolean),
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const body = {
|
|
35
|
+
agent: { id: agentId, name, role },
|
|
36
|
+
user: { root_node: userRoot || config.activeRoot || 'dustin' },
|
|
37
|
+
content,
|
|
38
|
+
hints: recipe ? { recipe } : {},
|
|
39
|
+
options: { dry_run: dryRun || false },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const res = await dataPlane('POST', '/v1/agents/provision', body);
|
|
44
|
+
const data = res.data;
|
|
45
|
+
|
|
46
|
+
if (dryRun) {
|
|
47
|
+
console.log(`Dry run — would ${data.status === 'would_create' ? 'create' : 'update'}`);
|
|
48
|
+
console.log(` Agent root: ${data.agent_root}`);
|
|
49
|
+
console.log(` User root: ${data.user_root}`);
|
|
50
|
+
console.log(` Changes: ${Object.entries(data.changes || {}).filter(([,v]) => v).map(([k]) => k).join(', ') || 'none'}`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
console.log(`${data.status === 'created' ? 'Provisioned' : 'Updated'}: ${data.agent_root}`);
|
|
55
|
+
console.log(` Recipe: ${data.recipe_id}`);
|
|
56
|
+
console.log(` Recipe inference: ${data.recipe_inference}`);
|
|
57
|
+
console.log(` Content ingested: soul=${data.content_ingested?.soul}, agents=${data.content_ingested?.agents}, identity=${data.content_ingested?.identity}, memory=${data.content_ingested?.memory_files}`);
|
|
58
|
+
|
|
59
|
+
if (data.prompt_fragment) {
|
|
60
|
+
console.log(`\n--- Prompt Fragment (${data.prompt_fragment.length} chars) ---`);
|
|
61
|
+
console.log(data.prompt_fragment);
|
|
62
|
+
}
|
|
63
|
+
} catch (err) {
|
|
64
|
+
console.error('Failed:', err.message);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function readFileOrText(input) {
|
|
70
|
+
if (!input) return null;
|
|
71
|
+
if (existsSync(input)) {
|
|
72
|
+
return readFileSync(input, 'utf8');
|
|
73
|
+
}
|
|
74
|
+
return input;
|
|
75
|
+
}
|
package/src/commands/entities.js
CHANGED
|
@@ -197,6 +197,64 @@ export async function entitiesDeleteCommand(entityId) {
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
+
export async function edgesCreateCommand(options) {
|
|
201
|
+
try {
|
|
202
|
+
const body = {
|
|
203
|
+
type: options.type,
|
|
204
|
+
from: {},
|
|
205
|
+
to: {},
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
// From reference
|
|
209
|
+
if (options.from) body.from.entityId = options.from;
|
|
210
|
+
if (options.fromType && options.fromKey) {
|
|
211
|
+
body.from = { nodeType: options.fromType, key: JSON.parse(options.fromKey) };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// To reference
|
|
215
|
+
if (options.to) body.to.entityId = options.to;
|
|
216
|
+
if (options.toType && options.toKey) {
|
|
217
|
+
body.to = { nodeType: options.toType, key: JSON.parse(options.toKey) };
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Properties
|
|
221
|
+
if (options.properties) {
|
|
222
|
+
try {
|
|
223
|
+
body.properties = JSON.parse(options.properties);
|
|
224
|
+
} catch {
|
|
225
|
+
console.error(chalk.red('Invalid properties JSON'));
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const res = await dataPlane('POST', '/v1/entities/edges', body);
|
|
231
|
+
const edge = res.data;
|
|
232
|
+
console.log(chalk.green(`Edge created: ${edge.source || options.from} -[${chalk.cyan(options.type)}]-> ${edge.target || options.to}`));
|
|
233
|
+
} catch (err) {
|
|
234
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export async function edgesDeleteCommand(options) {
|
|
240
|
+
try {
|
|
241
|
+
const body = {
|
|
242
|
+
type: options.type,
|
|
243
|
+
from: {},
|
|
244
|
+
to: {},
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
if (options.from) body.from.entityId = options.from;
|
|
248
|
+
if (options.to) body.to.entityId = options.to;
|
|
249
|
+
|
|
250
|
+
await dataPlane('DELETE', '/v1/entities/edges', body);
|
|
251
|
+
console.log(chalk.green(`Edge deleted: ${options.from} -[${options.type}]-> ${options.to}`));
|
|
252
|
+
} catch (err) {
|
|
253
|
+
console.error(chalk.red(`Failed: ${err.message}`));
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
200
258
|
export async function entitiesEdgesCommand(entityId) {
|
|
201
259
|
try {
|
|
202
260
|
const appId = getActiveApp();
|
package/src/commands/settings.js
CHANGED
|
@@ -5,7 +5,7 @@ import { getActiveApp } from '../config.js';
|
|
|
5
5
|
export async function settingsShowCommand() {
|
|
6
6
|
try {
|
|
7
7
|
const appId = getActiveApp();
|
|
8
|
-
const res = await controlPlane('GET', `/apps/${appId}/settings`);
|
|
8
|
+
const res = await controlPlane('GET', `/apps/${appId}/intelligence/debug-settings`);
|
|
9
9
|
const settings = res.data;
|
|
10
10
|
|
|
11
11
|
console.log(chalk.bold('App Settings'));
|
|
@@ -41,7 +41,7 @@ export async function settingsUpdateCommand(options) {
|
|
|
41
41
|
process.exit(1);
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
const res = await controlPlane('PUT', `/apps/${appId}/settings`, updates);
|
|
44
|
+
const res = await controlPlane('PUT', `/apps/${appId}/intelligence/debug-settings`, updates);
|
|
45
45
|
console.log(chalk.green('Settings updated'));
|
|
46
46
|
} catch (err) {
|
|
47
47
|
console.error(chalk.red(`Failed: ${err.message}`));
|