@zergai/ztc 0.2.2-dev.35680553693 → 0.2.3-dev.35760740177

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 CHANGED
@@ -1038,3 +1038,20 @@ the ZTC 0.1.x releases.
1038
1038
  ---
1039
1039
 
1040
1040
  Part of the [Zerg](https://github.com/idanbeck/zerg) autonomous AI framework.
1041
+
1042
+ ## Updating the npm CLI
1043
+
1044
+ Run `ztc update` or `ztc --update` to install a newer npm
1045
+ release. `ztc update --check` prints JSON without installing. The
1046
+ installed channel is preserved (`dev`, `next`, or `latest`); select a channel
1047
+ explicitly with `update --channel dev|next|latest`. Updates never downgrade.
1048
+
1049
+ Startup checks only notify on stderr when it is a terminal, never prompt or
1050
+ install, and are cached for one hour. CI, redirected stderr, and help/version
1051
+ requests skip checks. Set `ZERGAI_NO_UPDATE_CHECK=1` to disable startup checks.
1052
+ Self-installation requires the matching macOS/Linux global npm prefix; local,
1053
+ linked, npx, or other package-manager installs must use their original manager.
1054
+ Existing releases need one ordinary npm upgrade before these commands exist.
1055
+
1056
+ See [shared updater policy](https://github.com/Epoch-ML/zerg/blob/development/docs/npm-cli-updates.md)
1057
+ for installation safety, channel switching, and packaging details.
@@ -12130,7 +12130,7 @@ var invokeSkillTool = makeInvokeSkillTool(resolveAmbientSkills);
12130
12130
  // src/zlm.ts
12131
12131
  var ZLM_EMBED_API_VERSION = "zerglang.ztc-embed/1";
12132
12132
  var ZLM_STDIO_PROTOCOL = "zerglang.ztc-host/1";
12133
- var ZLM_ZTC_VERSION = true ? "0.2.2-dev.35680553693" : "development";
12133
+ var ZLM_ZTC_VERSION = true ? "0.2.3-dev.35760740177" : "development";
12134
12134
  var ZLM_MAX_HOST_TOOLS = 64;
12135
12135
  var ZLM_MAX_SYSTEM_PROMPT_BYTES = 128 * 1024;
12136
12136
  var ZLM_HOST_APPROVAL_CAPABILITIES = Object.freeze([
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+ const { execFile, spawn } = require('node:child_process');
3
+ const { promisify } = require('node:util');
4
+
5
+ // Kept separate so OS process contracts can be exercised independently from the
6
+ // version/cache policy. This is copied alongside the updater in each artifact.
7
+ module.exports = async function runNpm(args, options) {
8
+ if (args[0] === 'prefix') return promisify(execFile)('npm', args, { ...options, encoding: 'utf8', timeout: 5000, maxBuffer: 16384 });
9
+ await new Promise((done, fail) => {
10
+ const child = spawn('npm', args, { ...options, stdio: ['ignore', 'inherit', 'inherit'], shell: false });
11
+ // npm shares the foreground group; a terminal has already signalled it.
12
+ const relay = ![process.stdin, process.stdout, process.stderr].some(stream => stream.isTTY);
13
+ const interrupt = () => { if (relay) child.kill('SIGINT'); };
14
+ const terminate = () => { if (relay) child.kill('SIGTERM'); };
15
+ process.on('SIGINT', interrupt); process.on('SIGTERM', terminate);
16
+ const cleanup = () => { process.off('SIGINT', interrupt); process.off('SIGTERM', terminate); };
17
+ child.on('error', error => { cleanup(); fail(error); });
18
+ child.on('exit', (code, signal) => { cleanup(); if (code === 0) done(); else fail(new Error(`npm exited ${signal || code}`)); });
19
+ });
20
+ return { stdout: '' };
21
+ };
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+ const { spawn } = require('node:child_process');
4
+ const { join } = require('node:path');
5
+ const { handleUpdate } = require('./update.cjs');
6
+
7
+ async function main() {
8
+ const root = join(__dirname, '..');
9
+ const args = process.argv.slice(2);
10
+ const result = await handleUpdate({ root, args });
11
+ if (result !== null) { process.exitCode = result; return; }
12
+ if (args.length === 1 && ['--help', '-h', 'help'].includes(args[0])) {
13
+ process.stdout.write('Updates: update | --update [--check] [--channel dev|next|latest]\n');
14
+ }
15
+ const metadata = require('../package.json');
16
+ // ZTC's old TUI updaters must not install silently behind this launch policy.
17
+ const env = { ...process.env };
18
+ if (['@zergai/ztc', 'zerg-ztc'].includes(metadata.name)) {
19
+ env.ZTC_NO_AUTO_UPDATE = '1'; env.ZTC_DISABLE_UPDATE = '1';
20
+ }
21
+ const child = spawn(process.execPath, [join(root, metadata.zergCli.entry), ...args], { stdio: 'inherit', env });
22
+ // Attached terminals signal the foreground group, including the child. Relay
23
+ // only for non-TTY supervisors; keep the group intact for terminal resize.
24
+ const relay = ![process.stdin, process.stdout, process.stderr].some(stream => stream.isTTY);
25
+ const interrupt = () => { if (relay) child.kill('SIGINT'); };
26
+ const terminate = () => { if (relay) child.kill('SIGTERM'); };
27
+ process.on('SIGINT', interrupt); process.on('SIGTERM', terminate);
28
+ const cleanup = () => { process.off('SIGINT', interrupt); process.off('SIGTERM', terminate); };
29
+ child.on('error', error => { cleanup(); console.error(`Unable to launch ${metadata.name}: ${error.message}`); process.exitCode = 1; });
30
+ child.on('exit', (code, signal) => {
31
+ cleanup();
32
+ if (signal) process.kill(process.pid, signal);
33
+ else process.exitCode = code ?? 1;
34
+ });
35
+ }
36
+ main().catch(error => { console.error(error.message); process.exitCode = 1; });
@@ -0,0 +1,161 @@
1
+ 'use strict';
2
+
3
+ // Copied into each npm CLI at pack time. No repo paths or runtime dependencies.
4
+ const runNpm = require('./npm-process.cjs');
5
+ const { readFile, realpath, lstat, mkdir, mkdtemp, writeFile, rename, rm } = require('node:fs/promises');
6
+ const { homedir } = require('node:os');
7
+ const { join, resolve, isAbsolute } = require('node:path');
8
+ const registry = 'https://registry.npmjs.org';
9
+ const cacheLifetime = 60 * 60 * 1000;
10
+
11
+ function parseVersion(version) {
12
+ const match = typeof version === 'string' && version.length <= 256 && /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/.exec(version);
13
+ if (!match || match.slice(1, 4).some(n => !Number.isSafeInteger(Number(n))) || (match[4] || '').split('.').some(n => /^0\d+$/.test(n))) {
14
+ throw new Error('Invalid semantic version');
15
+ }
16
+ return { core: match.slice(1, 4).map(Number), pre: match[4] ? match[4].split('.') : [] };
17
+ }
18
+
19
+ function compareVersions(left, right) {
20
+ const a = parseVersion(left), b = parseVersion(right);
21
+ for (let i = 0; i < 3; i++) if (a.core[i] !== b.core[i]) return a.core[i] > b.core[i] ? 1 : -1;
22
+ if (!a.pre.length && b.pre.length) return 1;
23
+ if (a.pre.length && !b.pre.length) return -1;
24
+ for (let i = 0; i < Math.max(a.pre.length, b.pre.length); i++) {
25
+ if (a.pre[i] === b.pre[i]) continue;
26
+ if (a.pre[i] === undefined) return -1;
27
+ if (b.pre[i] === undefined) return 1;
28
+ const an = /^\d+$/.test(a.pre[i]), bn = /^\d+$/.test(b.pre[i]);
29
+ if (an !== bn) return an ? -1 : 1;
30
+ return (an ? BigInt(a.pre[i]) > BigInt(b.pre[i]) : a.pre[i] > b.pre[i]) ? 1 : -1;
31
+ }
32
+ return 0;
33
+ }
34
+
35
+ function releaseChannel(version) {
36
+ const { pre } = parseVersion(version);
37
+ return pre[0] === 'dev' ? 'dev' : pre.length ? 'next' : 'latest';
38
+ }
39
+
40
+ function identity(metadata) {
41
+ if (!/^@zergai\/[a-z0-9][a-z0-9-]*$/.test(metadata.name) && !['zerg-ztc', 'zerg-cyberdeck'].includes(metadata.name)) {
42
+ throw new Error('Unsupported CLI package identity');
43
+ }
44
+ parseVersion(metadata.version);
45
+ }
46
+
47
+ async function checkUpdate(metadata, { fetch = globalThis.fetch, channel = releaseChannel(metadata.version), timeoutMs = 5000 } = {}) {
48
+ identity(metadata);
49
+ if (!['dev', 'next', 'latest'].includes(channel)) throw new Error('Invalid update channel');
50
+ const response = await fetch(`${registry}/${encodeURIComponent(metadata.name)}/${channel}`, {
51
+ headers: { Accept: 'application/json' }, redirect: 'error', signal: AbortSignal.timeout(timeoutMs),
52
+ });
53
+ if (!response.ok) throw new Error(`npm registry check failed (${response.status})`);
54
+ const reader = response.body.getReader();
55
+ const chunks = []; let size = 0;
56
+ try {
57
+ while (true) {
58
+ const { done, value } = await reader.read();
59
+ if (done) break;
60
+ size += value.byteLength;
61
+ if (size > 1024 * 1024) throw new Error('npm registry response too large');
62
+ chunks.push(Buffer.from(value));
63
+ }
64
+ } finally { await reader.cancel(); }
65
+ const data = JSON.parse(Buffer.concat(chunks).toString('utf8'));
66
+ if (data.name !== metadata.name) throw new Error('npm registry package identity mismatch');
67
+ if (releaseChannel(data.version) !== channel) throw new Error('npm registry version does not match the requested channel');
68
+ return { name: metadata.name, current: metadata.version, latest: data.version, channel, hasUpdate: compareVersions(data.version, metadata.version) > 0 };
69
+ }
70
+
71
+ function updateOptions(args) {
72
+ const options = { check: false };
73
+ for (let i = 1; i < args.length; i++) {
74
+ const arg = args[i];
75
+ if (arg === '--check' && !options.check) options.check = true;
76
+ else if (arg === '--channel' && !options.channel && ['dev', 'next', 'latest'].includes(args[i + 1])) options.channel = args[++i];
77
+ else if (['--help', '-h'].includes(arg) && args.length === 2) options.help = true;
78
+ else throw new Error('Usage: update [--check] [--channel dev|next|latest]');
79
+ }
80
+ return options;
81
+ }
82
+
83
+ async function install(root, metadata, info, npm, env) {
84
+ const { stdout } = await npm(['prefix', '--global'], { env });
85
+ const prefix = stdout.trim();
86
+ if (!isAbsolute(prefix)) throw new Error('Cannot identify the global npm installation');
87
+ const expected = join(prefix, 'lib/node_modules', metadata.name);
88
+ // Compare real paths AND reject npm link. Never turn npx/local/checkouts into a
89
+ // global install or update a different Node-version manager's global prefix.
90
+ const matches = await (async () => !(await lstat(expected)).isSymbolicLink() && await realpath(root) === await realpath(expected))().catch(() => false);
91
+ if (!matches) {
92
+ throw new Error('Not this global npm installation. Update using the package manager/prefix that installed this CLI.');
93
+ }
94
+ await npm(['install', '--global', '--prefix', prefix, `--registry=${registry}`, `--@zergai:registry=${registry}`, '--no-audit', '--no-fund', `${metadata.name}@${info.latest}`], { cwd: prefix, env });
95
+ const installed = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
96
+ if (installed.name !== metadata.name || installed.version !== info.latest) throw new Error('npm did not install the requested package version');
97
+ }
98
+
99
+ async function startupCheck(metadata, env, fetch) {
100
+ const channel = releaseChannel(metadata.version);
101
+ const directory = join(env.XDG_CACHE_HOME || join(homedir(), '.cache'), 'zergai-cli-updates');
102
+ const path = join(directory, `${encodeURIComponent(metadata.name)}-${channel}.json`);
103
+ try {
104
+ const cached = JSON.parse(await readFile(path, 'utf8'));
105
+ const age = Date.now() - cached.checkedAt;
106
+ if (Number.isFinite(age) && age >= 0 && age < cacheLifetime && cached.current === metadata.version) {
107
+ if (cached.latest === null) return null;
108
+ if (releaseChannel(cached.latest) === channel) return { latest: cached.latest, hasUpdate: compareVersions(cached.latest, metadata.version) > 0 };
109
+ }
110
+ } catch { /* Missing, stale, or malformed cache: do a bounded public check. */ }
111
+ let info = null;
112
+ try { info = await checkUpdate(metadata, { fetch, timeoutMs: 800 }); }
113
+ catch { /* A registry outage must not prevent use of a CLI. */ }
114
+ let staging;
115
+ try {
116
+ await mkdir(directory, { recursive: true, mode: 0o700 });
117
+ staging = await mkdtemp(join(directory, '.check-'));
118
+ const source = join(staging, 'record');
119
+ await writeFile(source, JSON.stringify({ current: metadata.version, latest: info?.latest ?? null, checkedAt: Date.now() }), { flag: 'wx', mode: 0o600 });
120
+ await rename(source, path);
121
+ } catch { /* Read-only home/cache is supported. */ }
122
+ finally { if (staging) await rm(staging, { recursive: true, force: true }).catch(() => {}); }
123
+ return info;
124
+ }
125
+
126
+ async function handleUpdate({ root, args, env = process.env, stdout = process.stdout, stderr = process.stderr, fetch = globalThis.fetch, npm = runNpm }) {
127
+ const explicit = ['update', '--update'].includes(args[0]);
128
+ if (!explicit && (env.CI || env.ZERGAI_NO_UPDATE_CHECK === '1' || !stderr.isTTY || args.some(arg => ['help', '--help', '-h', 'version', '--version', '-V'].includes(arg)))) return null;
129
+ let options;
130
+ try { options = explicit ? updateOptions(args) : {}; }
131
+ catch (error) { stderr.write(`${error.message}\n`); return 2; }
132
+ if (options.help) {
133
+ stdout.write('Check npm and update this globally installed CLI\nUsage: update | --update [--check] [--channel dev|next|latest]\n--check prints JSON without installing. Channels are preserved by default.\nStartup only notifies; set ZERGAI_NO_UPDATE_CHECK=1 to disable checks.\n');
134
+ return 0;
135
+ }
136
+ try {
137
+ const metadata = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'));
138
+ identity(metadata);
139
+ if (!explicit) {
140
+ const info = await startupCheck(metadata, env, fetch);
141
+ if (info?.hasUpdate) stderr.write(`Update available for ${metadata.name}: ${metadata.version} → ${info.latest}. Run ${Object.keys(metadata.bin || {})[0] || metadata.name} update.\n`);
142
+ return null;
143
+ }
144
+ // Explicit checks/install always consult the registry; cache is advisory only.
145
+ const info = await checkUpdate(metadata, { fetch, ...options });
146
+ if (options.check) stdout.write(`${JSON.stringify(info)}\n`);
147
+ else if (!info.hasUpdate) stderr.write(`No newer ${info.channel} release of ${metadata.name} (installed ${metadata.version}).\n`);
148
+ else {
149
+ stderr.write(`Updating ${metadata.name}: ${metadata.version} → ${info.latest} (${info.channel})…\n`);
150
+ await install(resolve(root), metadata, info, npm, env);
151
+ stderr.write(`Updated ${metadata.name} to ${info.latest}. The next launch uses the new version.\n`);
152
+ }
153
+ return 0;
154
+ } catch (error) {
155
+ if (!explicit) return null;
156
+ stderr.write(`Update failed: ${error.message}\n`);
157
+ return 1;
158
+ }
159
+ }
160
+
161
+ module.exports = { compareVersions, releaseChannel, checkUpdate, handleUpdate };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zergai/ztc",
3
- "version": "0.2.2-dev.35680553693",
3
+ "version": "0.2.3-dev.35760740177",
4
4
  "description": "Zerg Terminal Client - CLI agent for continual AI systems",
5
5
  "license": "SEE LICENSE IN LICENSE.md",
6
6
  "repository": {
@@ -38,9 +38,12 @@
38
38
  "falkordblite"
39
39
  ]
40
40
  },
41
+ "zergCli": {
42
+ "entry": "dist/cli_main.js"
43
+ },
41
44
  "bin": {
42
- "ztc": "dist/cli_main.js",
43
- "zerg": "dist/cli_main.js"
45
+ "ztc": "npm-cli/run.cjs",
46
+ "zerg": "npm-cli/run.cjs"
44
47
  },
45
48
  "exports": {
46
49
  ".": {
@@ -129,7 +132,7 @@
129
132
  "package:prepare": "./scripts/prepare-package.sh",
130
133
  "pack:dry": "npm pack --dry-run --cache ${NPM_CONFIG_CACHE:-/tmp/ztc-npm-cache}",
131
134
  "pack:tarball": "npm pack --cache ${NPM_CONFIG_CACHE:-/tmp/ztc-npm-cache}",
132
- "prepack": "npm run package:prepare",
135
+ "prepack": "npm run package:prepare && node ../scripts/npm/prepare-cli.mjs",
133
136
  "predev": "npm run clean",
134
137
  "dev": "npm run build:rust && tsx src/cli_main.ts",
135
138
  "dev:ink": "tsx src/cli.tsx",
@@ -161,6 +164,7 @@
161
164
  "release:preflight-governance": "node scripts/preflight-release-governance.mjs"
162
165
  },
163
166
  "files": [
167
+ "npm-cli/*.cjs",
164
168
  "LICENSE.md",
165
169
  "COMMERCIAL-LICENSING.md",
166
170
  "NOTICE",
@@ -185,7 +189,6 @@
185
189
  "!packages/sim-swarm/dist/**/*.map"
186
190
  ],
187
191
  "bundleDependencies": [
188
- "@ztc/sim-graph",
189
192
  "@ztc/sim-swarm",
190
193
  "exceljs",
191
194
  "pptxgenjs"
@@ -235,7 +238,7 @@
235
238
  "zergRelease": {
236
239
  "branch": "development",
237
240
  "channel": "dev",
238
- "sourceCommit": "47d9d5f588404db372a9901019d94ffb7f99c365",
241
+ "sourceCommit": "4b068dffbc8a4dd0debe7e14c61674e5d4670ff4",
239
242
  "sourceVersion": "0.2.0-canary.1"
240
243
  },
241
244
  "publishConfig": {
@@ -1 +0,0 @@
1
- export * from './sim_graph.js';
@@ -1 +0,0 @@
1
- export * from './sim_graph.js';
@@ -1,351 +0,0 @@
1
- /**
2
- * SimGraph — FalkorDB Graph Backbone for Simulation
3
- *
4
- * Property graph storing entities, temporal facts, relationships,
5
- * feed posts, and events. Replaces flat in-memory stores with
6
- * structured, queryable graph data.
7
- *
8
- * Inspired by MiroFish/Graphiti's temporal knowledge graph but
9
- * implemented natively in TypeScript with FalkorDBLite (embedded,
10
- * no Docker, no Python).
11
- */
12
- /**
13
- * Scalar + nested shape accepted by FalkorDB parameter binding. Mirrors
14
- * the internal `QueryParam` type from the `falkordb` package (which is
15
- * not exported) so consumers of `rawQuery` get the same strictness.
16
- */
17
- export type QueryParamValue = null | string | number | boolean | QueryParams | QueryParamValue[];
18
- export interface QueryParams {
19
- [key: string]: QueryParamValue;
20
- }
21
- export interface GraphFact {
22
- id: string;
23
- content: string;
24
- category: string;
25
- sourceTick: number;
26
- validFrom: number;
27
- invalidAt: number | null;
28
- }
29
- export interface GraphRelationship {
30
- agentIdA: string;
31
- agentIdB: string;
32
- nameA: string;
33
- nameB: string;
34
- sentiment: number;
35
- trust: number;
36
- interactionCount: number;
37
- lastNote: string | null;
38
- }
39
- export interface GraphFeedPost {
40
- id: string;
41
- content: string;
42
- authorId: string;
43
- authorName: string;
44
- authorRole: string;
45
- source: string;
46
- createdAt: number;
47
- replyTo: string | null;
48
- reactionCount: number;
49
- topicTags: string[];
50
- }
51
- export interface GraphContext {
52
- facts: GraphFact[];
53
- agents: Array<{
54
- id: string;
55
- name: string;
56
- role: string;
57
- }>;
58
- relationships: GraphRelationship[];
59
- }
60
- export interface WorldView {
61
- ownFacts: GraphFact[];
62
- peerFacts: Array<{
63
- peerName: string;
64
- peerRole: string;
65
- facts: GraphFact[];
66
- }>;
67
- topicFacts: GraphFact[];
68
- }
69
- export interface SimulationGraphFact {
70
- id: string;
71
- subjectId: string;
72
- predicate: string;
73
- objectId: string;
74
- content: string;
75
- validFrom: number;
76
- invalidAt: number | null;
77
- sourceEventId: string;
78
- data: Record<string, unknown>;
79
- }
80
- export interface SimulationGraphFactInput {
81
- id: string;
82
- subjectId: string;
83
- predicate: string;
84
- objectId?: string;
85
- content: string;
86
- validFrom: number;
87
- invalidAt?: number | null;
88
- sourceEventId?: string;
89
- supersedesIds?: string[];
90
- data?: Record<string, unknown>;
91
- }
92
- export interface SimulationGraphEdge {
93
- sourceId: string;
94
- targetId: string;
95
- type: string;
96
- tick: number;
97
- data: Record<string, unknown>;
98
- }
99
- export interface SimulationFactGraph {
100
- schemaVersion: 1;
101
- facts: SimulationGraphFact[];
102
- edges: SimulationGraphEdge[];
103
- }
104
- export interface RecordSimulationFactInput {
105
- graph?: SimulationFactGraph;
106
- fact: SimulationGraphFactInput;
107
- }
108
- export interface ProjectActiveFactsInput {
109
- graph: SimulationFactGraph;
110
- atTick: number;
111
- subjectIds?: string[];
112
- predicates?: string[];
113
- }
114
- export interface SimulationNeighborhoodInput {
115
- graph: SimulationFactGraph;
116
- startIds: string[];
117
- maxDepth?: number;
118
- edgeTypes?: string[];
119
- }
120
- export interface SimulationNeighborhood {
121
- schemaVersion: 1;
122
- factIds: string[];
123
- facts: SimulationGraphFact[];
124
- edges: SimulationGraphEdge[];
125
- depthByFactId: Record<string, number>;
126
- }
127
- export type SimulationFocusGraphDirection = 'in' | 'out' | 'both';
128
- export interface SimulationFocusGraphNode {
129
- id: string;
130
- kind?: string;
131
- label?: string;
132
- data?: Record<string, unknown>;
133
- }
134
- export interface SimulationFocusGraphEdge {
135
- sourceId: string;
136
- targetId: string;
137
- type: string;
138
- createdAt?: string;
139
- data: Record<string, unknown>;
140
- }
141
- export interface SimulationFocusRelationSpec {
142
- name: string;
143
- edgeTypes: string[];
144
- direction?: SimulationFocusGraphDirection;
145
- limit?: number;
146
- }
147
- export interface SimulationFocusLineageSpec {
148
- edgeTypes: string[];
149
- direction?: Exclude<SimulationFocusGraphDirection, 'both'>;
150
- includeFocus?: boolean;
151
- maxDepth?: number;
152
- }
153
- export interface BuildSimulationFocusGraphContextInput {
154
- nodes?: SimulationFocusGraphNode[];
155
- edges?: SimulationFocusGraphEdge[];
156
- focusIds?: string[];
157
- relations?: SimulationFocusRelationSpec[];
158
- lineage?: SimulationFocusLineageSpec;
159
- maxFocusIds?: number;
160
- }
161
- export interface SimulationFocusLineage {
162
- focusId: string;
163
- nodeIds: string[];
164
- edgeTypes: string[];
165
- edges: SimulationFocusGraphEdge[];
166
- }
167
- export interface SimulationFocusRelationGroup {
168
- name: string;
169
- focusId: string;
170
- nodeIds: string[];
171
- edges: SimulationFocusGraphEdge[];
172
- }
173
- export interface SimulationFocusGraphContext {
174
- version: 1;
175
- focusIds: string[];
176
- lineages: SimulationFocusLineage[];
177
- relationGroups: SimulationFocusRelationGroup[];
178
- }
179
- export interface SimulationSteeringEvent {
180
- id: string;
181
- eventType?: string;
182
- acceptedSignalKinds?: string[];
183
- subjectId?: string;
184
- verdict?: string;
185
- selectionStatus?: string;
186
- createdAt?: string;
187
- data?: Record<string, unknown>;
188
- }
189
- export interface SimulationSteeringSignal {
190
- kind?: string;
191
- subjectId?: string;
192
- verdict?: string;
193
- selectionStatus?: string;
194
- priority?: number;
195
- data?: Record<string, unknown>;
196
- }
197
- export interface SimulationSteeringTask {
198
- id: string;
199
- taskType?: string;
200
- source?: string;
201
- createdAt?: string;
202
- signals?: SimulationSteeringSignal[];
203
- }
204
- export interface SimulationSteeringOutput {
205
- id: string;
206
- taskId: string;
207
- outputType?: string;
208
- createdAt?: string;
209
- data?: Record<string, unknown>;
210
- }
211
- export interface SimulationSteeringInfluenceEdge {
212
- sourceId: string;
213
- targetId: string;
214
- type: 'steering_influenced_task' | 'steering_influenced_output';
215
- createdAt: string;
216
- data: Record<string, unknown>;
217
- }
218
- export interface BuildSimulationSteeringInfluenceGraphInput {
219
- steeringEvents?: SimulationSteeringEvent[];
220
- tasks?: SimulationSteeringTask[];
221
- outputs?: SimulationSteeringOutput[];
222
- ignoreVerdictKinds?: string[];
223
- }
224
- export interface SimulationSteeringInfluenceGraph {
225
- version: 1;
226
- taskEdges: SimulationSteeringInfluenceEdge[];
227
- outputEdges: SimulationSteeringInfluenceEdge[];
228
- }
229
- export interface SimulationRestartMemoryGraphStats {
230
- nodes: number;
231
- edges: number;
232
- activeFactCount: number;
233
- }
234
- export interface SimulationRestartMemoryPacket<TFact = Record<string, unknown>> {
235
- version: 1;
236
- runId: string;
237
- focusIds: string[];
238
- activeFacts: TFact[];
239
- graphStats: SimulationRestartMemoryGraphStats;
240
- }
241
- export interface BuildSimulationRestartMemoryInput<TFact = Record<string, unknown>> {
242
- runId?: string;
243
- focusIds?: string[];
244
- activeFacts?: TFact[];
245
- graphStats?: Partial<SimulationRestartMemoryGraphStats>;
246
- maxFocusIds?: number;
247
- }
248
- export declare function recordSimulationFact(input: RecordSimulationFactInput): SimulationFactGraph;
249
- export declare function projectActiveFacts(input: ProjectActiveFactsInput): SimulationGraphFact[];
250
- export declare function traverseSimulationNeighborhood(input: SimulationNeighborhoodInput): SimulationNeighborhood;
251
- export declare function buildSimulationFocusGraphContext(input: BuildSimulationFocusGraphContextInput): SimulationFocusGraphContext;
252
- export declare function buildSimulationSteeringInfluenceGraph(input: BuildSimulationSteeringInfluenceGraphInput): SimulationSteeringInfluenceGraph;
253
- export declare function buildSimulationRestartMemory<TFact = Record<string, unknown>>(input: BuildSimulationRestartMemoryInput<TFact>): SimulationRestartMemoryPacket<TFact>;
254
- export declare class SimGraph {
255
- private db;
256
- private graph;
257
- /** Per-instance counter (review #8: avoid module-level mutable state) */
258
- private factCounter;
259
- private constructor();
260
- /**
261
- * Open an embedded FalkorDB instance and select the simulation graph.
262
- * If dataPath is provided, data persists to disk.
263
- */
264
- static open(dataPath?: string): Promise<SimGraph>;
265
- /** Close the graph database and stop the embedded server. */
266
- close(): Promise<void>;
267
- /**
268
- * Escape hatch for domain-specific adapters that want to use labels/
269
- * relationships outside the built-in schema (e.g. cybersim's `:CS*`
270
- * nodes). Returned shape matches FalkorDB's `graph.query` result.
271
- */
272
- rawQuery<T = Record<string, unknown>>(cypher: string, params?: QueryParams): Promise<{
273
- data?: T[];
274
- }>;
275
- /**
276
- * Register a range index on a node label/property pair. Safe to call
277
- * for already-indexed pairs — creation errors are swallowed.
278
- */
279
- ensureNodeIndex(label: string, property: string): Promise<void>;
280
- /** Create indices for common query patterns. */
281
- private initSchema;
282
- addAgent(agent: {
283
- id: string;
284
- name: string;
285
- role: string;
286
- organization: string;
287
- type: 'internal' | 'external';
288
- }): Promise<void>;
289
- addCompany(company: {
290
- id: string;
291
- name: string;
292
- industry: string;
293
- stage: string;
294
- }): Promise<void>;
295
- addCompetitor(companyIdA: string, companyIdB: string): Promise<void>;
296
- addWorksAt(agentId: string, companyId: string): Promise<void>;
297
- /** Add a fact stated by an agent. Returns the fact ID. */
298
- addFact(agentId: string, content: string, category: string, tick: number, aboutEntityId?: string): Promise<string>;
299
- /** Invalidate a fact at the given tick. */
300
- invalidateFact(factId: string, tick: number): Promise<void>;
301
- /**
302
- * Add a fact, checking for contradictions. If the same agent has
303
- * a current fact in the same category about the same entity,
304
- * invalidate the old fact and create a SUPERSEDES edge.
305
- */
306
- addFactWithSupersede(agentId: string, content: string, category: string, tick: number, aboutEntityId?: string): Promise<string>;
307
- /** Get all facts stated by an agent. */
308
- getAgentFacts(agentId: string, currentOnly?: boolean): Promise<GraphFact[]>;
309
- /** Get all facts about an entity. */
310
- getFactsAbout(entityId: string, currentOnly?: boolean): Promise<GraphFact[]>;
311
- /** Get facts matching a keyword in content. */
312
- getFactsByKeyword(keyword: string, currentOnly?: boolean): Promise<GraphFact[]>;
313
- setRelationship(agentIdA: string, agentIdB: string, sentiment: number, trust: number, interactionCount: number, note?: string): Promise<void>;
314
- /** Review #12: Query both directions for KNOWS relationship. */
315
- getRelationship(agentIdA: string, agentIdB: string): Promise<GraphRelationship | null>;
316
- getRelationshipsFor(agentId: string): Promise<GraphRelationship[]>;
317
- addPost(post: {
318
- id: string;
319
- content: string;
320
- authorId: string;
321
- authorName: string;
322
- authorRole: string;
323
- source: string;
324
- tick: number;
325
- replyTo?: string;
326
- topicTags?: string[];
327
- }): Promise<void>;
328
- addReaction(agentId: string, postId: string): Promise<void>;
329
- getRecentPosts(limit?: number, sinceTick?: number): Promise<GraphFeedPost[]>;
330
- addEvent(event: {
331
- id: string;
332
- type: string;
333
- description: string;
334
- tick: number;
335
- participantIds: string[];
336
- }): Promise<void>;
337
- /**
338
- * Get an agent's full world view at a given tick:
339
- * - Facts they've stated (current)
340
- * - Facts their peers have stated (current)
341
- * - Facts about topics they've discussed
342
- */
343
- getAgentWorldView(agentId: string, tick: number): Promise<WorldView>;
344
- /**
345
- * Get context around any entity — all facts, agents, and relationships.
346
- * Review #9: removed unused depth param (queries are always 1-hop).
347
- */
348
- getEntityContext(entityId: string): Promise<GraphContext>;
349
- private parseFactRows;
350
- private parsePostRows;
351
- }