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 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trucontext",
3
- "version": "0.9.0",
3
+ "version": "0.9.2",
4
4
  "description": "TruContext CLI — contextual memory for AI applications",
5
5
  "type": "module",
6
6
  "bin": {
@@ -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
+ }
@@ -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();
@@ -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}`));