graphlin 0.1.2 → 0.2.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/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/README.md +12 -3
- package/docs/decision-service.md +393 -0
- package/docs/extension-authoring.md +553 -0
- package/docs/model-api.md +293 -0
- package/docs/usage.md +465 -0
- package/docs/visualizer-views.md +199 -0
- package/node_modules/@vscode/tree-sitter-wasm/LICENSE +21 -0
- package/node_modules/@vscode/tree-sitter-wasm/README.md +36 -0
- package/node_modules/@vscode/tree-sitter-wasm/SECURITY.md +41 -0
- package/node_modules/@vscode/tree-sitter-wasm/cgmanifest.json +16 -0
- package/node_modules/@vscode/tree-sitter-wasm/package.json +42 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-bash.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-c-sharp.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-cpp.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-css.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-go.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ini.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-java.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-javascript.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-php.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-powershell.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-python.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-regex.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ruby.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-rust.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-tsx.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.js +4075 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm +0 -0
- package/node_modules/@vscode/tree-sitter-wasm/wasm/web-tree-sitter.d.ts +1027 -0
- package/package.json +74 -9
- package/plugin.json +4 -2
- package/runtime/core/evidence.mjs +43 -9
- package/runtime/core/graph.mjs +11 -6
- package/runtime/core/privacy.mjs +1 -0
- package/runtime/daemon/auth.mjs +7 -3
- package/runtime/daemon/diagnostics.mjs +1 -1
- package/runtime/daemon/extension-api.mjs +203 -0
- package/runtime/daemon/lineage.mjs +70 -0
- package/runtime/daemon/manager.mjs +9 -6
- package/runtime/daemon/model-api.mjs +728 -0
- package/runtime/daemon/model-persistence.mjs +220 -0
- package/runtime/daemon/server.mjs +70 -12
- package/runtime/daemon/settings.mjs +11 -3
- package/runtime/decisions/broker.mjs +349 -0
- package/runtime/decisions/contracts.mjs +179 -0
- package/runtime/decisions/evaluation.mjs +305 -0
- package/runtime/decisions/faults.mjs +32 -0
- package/runtime/decisions/index.mjs +818 -0
- package/runtime/decisions/profiles.mjs +93 -0
- package/runtime/decisions/questions.mjs +268 -0
- package/runtime/discovery/index.mjs +2 -0
- package/runtime/discovery/inventory.mjs +160 -0
- package/runtime/discovery/parser.mjs +40 -0
- package/runtime/discovery/structure.mjs +232 -0
- package/runtime/extensions/contracts.mjs +59 -0
- package/runtime/extensions/frame.mjs +64 -0
- package/runtime/extensions/index.mjs +9 -0
- package/runtime/extensions/manifest.mjs +95 -0
- package/runtime/extensions/packages.mjs +222 -0
- package/runtime/extensions/profiles.mjs +36 -0
- package/runtime/extensions/projection.mjs +130 -0
- package/runtime/extensions/registry.mjs +285 -0
- package/runtime/extensions/scene.mjs +105 -0
- package/runtime/extensions/sdk.d.ts +205 -0
- package/runtime/extensions/sdk.mjs +88 -0
- package/runtime/jev/index.mjs +13 -777
- package/runtime/jev/provider.mjs +101 -0
- package/runtime/jev/questions.mjs +16 -258
- package/runtime/jev/wire.mjs +17 -25
- package/runtime/model/changes.mjs +42 -0
- package/runtime/model/history.mjs +124 -0
- package/runtime/model/index.mjs +2 -0
- package/runtime/model/project-model.mjs +889 -0
- package/runtime/model/records.mjs +239 -0
- package/runtime/pipeline.mjs +127 -48
- package/runtime/platform.mjs +254 -0
- package/runtime/visualizers/blocks.mjs +5 -0
- package/runtime/visualizers/c4.mjs +52 -0
- package/runtime/visualizers/changes.mjs +24 -0
- package/runtime/visualizers/code.mjs +5 -0
- package/runtime/visualizers/index.mjs +23 -0
- package/runtime/visualizers/structure.mjs +120 -0
- package/runtime/visualizers/timeline.mjs +66 -0
- package/runtime/web/app.js +369 -86
- package/runtime/web/extension-frame.js +128 -0
- package/runtime/web/index.html +123 -80
- package/runtime/web/model-client.js +162 -0
- package/runtime/web/platform.js +337 -0
- package/runtime/web/scene.js +111 -0
- package/runtime/web/style.css +152 -142
- package/schemas/graph.schema.json +4 -1
- package/scripts/arguments.mjs +5 -1
- package/scripts/build-packages.mjs +6 -2
- package/scripts/control.mjs +1 -1
- package/scripts/daemon.mjs +2 -1
- package/scripts/extensions.mjs +44 -0
- package/scripts/graphlin.mjs +23 -3
- package/scripts/onboarding.mjs +10 -3
- package/scripts/validate-packages.mjs +54 -8
package/scripts/graphlin.mjs
CHANGED
|
@@ -4,11 +4,12 @@ import { parseArguments } from './arguments.mjs';
|
|
|
4
4
|
import { initOnboarding, uninstallOnboarding, needsOnboarding, openViewer, agentInstructions } from './onboarding.mjs';
|
|
5
5
|
import { readSettings } from '../runtime/daemon/settings.mjs';
|
|
6
6
|
import { projectPaths } from '../runtime/daemon/paths.mjs';
|
|
7
|
+
import { runExtensions } from './extensions.mjs';
|
|
7
8
|
|
|
8
9
|
const HELP = `Graphlin — local architecture and activity viewer (Node.js 22.14+, macOS/Linux).
|
|
9
10
|
graphlin Guided setup if needed, then foreground start
|
|
10
|
-
init [--host claude|codex|both] [--allow-source|--no-source] [--replace-key]
|
|
11
|
-
start --project PATH [--allow-source|--no-source] [--persist-evidence] [--no-display-evidence] [--background] [--no-open]
|
|
11
|
+
init [--host claude|codex|both] [--allow-source|--local-source|--no-source] [--replace-key]
|
|
12
|
+
start --project PATH [--allow-source|--local-source|--no-source] [--persist-evidence] [--no-display-evidence] [--background] [--no-open]
|
|
12
13
|
open --project PATH Open/reopen the viewer; start detached if needed
|
|
13
14
|
uninstall [--host claude|codex|both]
|
|
14
15
|
stop --project PATH
|
|
@@ -17,10 +18,16 @@ const HELP = `Graphlin — local architecture and activity viewer (Node.js 22.14
|
|
|
17
18
|
demo [--data-dir PATH] [--background]
|
|
18
19
|
export --project PATH
|
|
19
20
|
logs --project PATH [--file PATH]
|
|
21
|
+
extensions list List installed visualizers and approvals
|
|
22
|
+
extensions add PACKAGE@VERSION Install without running package scripts
|
|
23
|
+
extensions dev ./DIRECTORY Install a local development snapshot
|
|
24
|
+
extensions update PACKAGE@VERSION Replace an installed visualizer
|
|
25
|
+
extensions remove ID
|
|
26
|
+
extensions doctor
|
|
20
27
|
All commands accept --project PATH and --data-dir PATH (or GRAPHLIN_DATA_DIR).
|
|
21
28
|
init installs for your user account using the host CLIs; it saves project consent
|
|
22
29
|
and offers a masked key prompt only in a terminal. Non-interactive init requires
|
|
23
|
-
--host and
|
|
30
|
+
--host and one source mode; remote source also needs a saved/environment key.
|
|
24
31
|
init --replace-key replaces a saved key at the masked prompt; it requires a terminal.
|
|
25
32
|
uninstall removes only Graphlin host plugins for all projects, retaining keys,
|
|
26
33
|
history, packages and marketplace registrations; it resets current project consent.
|
|
@@ -31,6 +38,10 @@ Omitted policy flags reuse current/saved consent. Without consent: metadata only
|
|
|
31
38
|
--no-source explicitly opts out; --allow-source permits sanitized source/public
|
|
32
39
|
intent to TypeSafe using TYPESAFE_API_KEY or the privately saved key. Approved evidence
|
|
33
40
|
is displayed by default; excerpts are persisted only with --persist-evidence.
|
|
41
|
+
--local-source parses supported source on this machine, without remote decisions.
|
|
42
|
+
Metadata mode inventories paths without opening source files. Visualizers require
|
|
43
|
+
project approval in the viewer before receiving data; custom renderers run in a
|
|
44
|
+
sandboxed frame. Install or mount does not run decision profiles.
|
|
34
45
|
Credentials, environment files, excluded paths, binary and oversized files are
|
|
35
46
|
filtered locally. Replay history is bounded to 7 days; an expired stopped-daemon
|
|
36
47
|
snapshot is deleted on the next startup. Current snapshots are private and bounded.
|
|
@@ -47,6 +58,15 @@ artifact identity, including files since deleted.
|
|
|
47
58
|
try {
|
|
48
59
|
const args = process.argv.slice(2);
|
|
49
60
|
if (args.includes('--help') || args[0] === 'help') process.stdout.write(HELP);
|
|
61
|
+
else if (args[0] === 'extensions') {
|
|
62
|
+
const globalArgs = [], extensionArgs = [];
|
|
63
|
+
for (let index = 1; index < args.length; index++) {
|
|
64
|
+
if (['--project', '--data-dir'].includes(args[index])) globalArgs.push(args[index], args[++index]);
|
|
65
|
+
else extensionArgs.push(args[index]);
|
|
66
|
+
}
|
|
67
|
+
const { projectRoot, dataDir } = parseArguments(['status', ...globalArgs]);
|
|
68
|
+
await runExtensions(extensionArgs, { projectRoot, dataDir });
|
|
69
|
+
}
|
|
50
70
|
else {
|
|
51
71
|
const options = parseArguments(args);
|
|
52
72
|
const print = result => process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
|
package/scripts/onboarding.mjs
CHANGED
|
@@ -313,13 +313,19 @@ export async function initOnboarding(options, dependencies = {}) {
|
|
|
313
313
|
write(`Project: ${JSON.stringify(paths.projectRoot)}\n`);
|
|
314
314
|
if (upgrading) write('Updating every recorded Graphlin host to keep the installed version consistent.\n');
|
|
315
315
|
let allowSource = options.allowSource ?? (resuming ? saved.policy?.allowSource : undefined);
|
|
316
|
+
let localSource = options.localSource === true ||
|
|
317
|
+
(resuming && options.allowSource === undefined && saved.policy?.localSource === true);
|
|
316
318
|
if (allowSource === undefined) {
|
|
317
|
-
write('Source mode sends locally filtered source excerpts
|
|
318
|
-
|
|
319
|
+
write('Source mode sends locally filtered source excerpts and public messages to the decision provider (Jev by default). Local mode parses code on this machine without sending it. Metadata mode reads no source content. Local and metadata need no key.\n');
|
|
320
|
+
const mode = await choose('For this project, choose source, local, or metadata: ', ['source', 'local', 'metadata'], prompt);
|
|
321
|
+
allowSource = mode === 'source';
|
|
322
|
+
localSource = mode === 'local';
|
|
319
323
|
}
|
|
320
324
|
const policy = { ...defaults, ...saved.policy, allowSource,
|
|
321
325
|
persistEvidence: options.persistEvidence ?? saved.policy?.persistEvidence ?? false,
|
|
322
326
|
displayEvidence: options.displayEvidence ?? saved.policy?.displayEvidence ?? true };
|
|
327
|
+
if (localSource && !allowSource) policy.localSource = true;
|
|
328
|
+
else delete policy.localSource;
|
|
323
329
|
// Explicit setup plus source consent authorizes saving the supplied key so
|
|
324
330
|
// later launches do not depend on this terminal's environment.
|
|
325
331
|
let apiKey = allowSource && env.TYPESAFE_API_KEY ? env.TYPESAFE_API_KEY : undefined;
|
|
@@ -399,7 +405,8 @@ export async function uninstallOnboarding(options, dependencies = {}) {
|
|
|
399
405
|
await record();
|
|
400
406
|
write(`Graphlin removed from ${host}.\n`);
|
|
401
407
|
}
|
|
402
|
-
await saveSettings(paths, { policy: { ...defaults, ...saved.policy, allowSource: false,
|
|
408
|
+
await saveSettings(paths, { policy: { ...defaults, ...saved.policy, allowSource: false,
|
|
409
|
+
...(saved.policy?.localSource ? { localSource: false } : {}), persistEvidence: false } });
|
|
403
410
|
write('Source and evidence-persistence consent reset for this project. A running viewer keeps its current policy until stopped; use graphlin stop.\n');
|
|
404
411
|
return { removed, ...(cancelledPending.length ? { cancelledPending } : {}), retainedData: true };
|
|
405
412
|
}
|
|
@@ -4,6 +4,51 @@ import path from 'node:path';
|
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
5
|
import assert from 'node:assert/strict';
|
|
6
6
|
|
|
7
|
+
const PARSER_NAME = '@vscode/tree-sitter-wasm';
|
|
8
|
+
const PARSER_VERSION = '0.3.1';
|
|
9
|
+
// The complete published 0.3.1 package, not a pruned grammar subset. Keep this
|
|
10
|
+
// explicit: arbitrary new files under node_modules must never enter a release.
|
|
11
|
+
const PARSER_FILES = [
|
|
12
|
+
'LICENSE', 'README.md', 'SECURITY.md', 'cgmanifest.json', 'package.json',
|
|
13
|
+
'wasm/tree-sitter.js', 'wasm/tree-sitter.wasm', 'wasm/web-tree-sitter.d.ts',
|
|
14
|
+
...['bash', 'c-sharp', 'cpp', 'css', 'go', 'ini', 'java', 'javascript', 'php',
|
|
15
|
+
'powershell', 'python', 'regex', 'ruby', 'rust', 'tsx', 'typescript']
|
|
16
|
+
.map(language => `wasm/tree-sitter-${language}.wasm`),
|
|
17
|
+
];
|
|
18
|
+
const SDK_EXPORTS = {
|
|
19
|
+
'./extensions/sdk': {
|
|
20
|
+
types: './runtime/extensions/sdk.d.ts',
|
|
21
|
+
import: './runtime/extensions/sdk.mjs',
|
|
22
|
+
default: './runtime/extensions/sdk.mjs',
|
|
23
|
+
},
|
|
24
|
+
'./extensions/scene': './runtime/extensions/scene.mjs',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
async function assertRegularFile(root, file) {
|
|
28
|
+
let current = root;
|
|
29
|
+
for (const component of file.split('/')) {
|
|
30
|
+
current = path.join(current, component);
|
|
31
|
+
assert.equal((await lstat(current)).isSymbolicLink(), false, 'package_symlink_rejected');
|
|
32
|
+
}
|
|
33
|
+
assert.ok((await lstat(current)).isFile(), 'package_file_must_be_regular');
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function bundledPackageFiles(root, metadata) {
|
|
37
|
+
metadata ??= JSON.parse(await readFile(path.join(root, 'package.json'), 'utf8'));
|
|
38
|
+
assert.deepEqual(metadata.bundledDependencies, [PARSER_NAME], 'parser_bundle_required');
|
|
39
|
+
assert.equal(metadata.dependencies?.[PARSER_NAME], PARSER_VERSION, 'parser_dependency_must_be_pinned');
|
|
40
|
+
const base = `node_modules/${PARSER_NAME}`;
|
|
41
|
+
await assertRegularFile(root, `${base}/package.json`);
|
|
42
|
+
const parser = JSON.parse(await readFile(path.join(root, base, 'package.json'), 'utf8'));
|
|
43
|
+
assert.equal(parser.name, PARSER_NAME, 'unexpected_parser_package');
|
|
44
|
+
assert.equal(parser.version, PARSER_VERSION, 'unexpected_parser_version');
|
|
45
|
+
assert.equal(parser.license, 'MIT', 'unexpected_parser_license');
|
|
46
|
+
assert.deepEqual(Object.keys(parser.dependencies ?? {}), [], 'unexpected_parser_dependencies');
|
|
47
|
+
const files = PARSER_FILES.map(file => `${base}/${file}`);
|
|
48
|
+
for (const file of files) await assertRegularFile(root, file);
|
|
49
|
+
return files;
|
|
50
|
+
}
|
|
51
|
+
|
|
7
52
|
// Dependency-free checks for this package's deliberately small manifest profile.
|
|
8
53
|
// This is not a replacement for a host's schema validation or activation/trust.
|
|
9
54
|
export async function publicPackageFiles(root) {
|
|
@@ -22,21 +67,22 @@ export async function publicPackageFiles(root) {
|
|
|
22
67
|
assert.ok(typeof file === 'string' && file.length > 0 && !file.includes('\\') &&
|
|
23
68
|
!path.posix.isAbsolute(file) && !/[*?[\]{}!\u0000-\u001f]/.test(file) &&
|
|
24
69
|
file.split('/').every(part => part && part !== '.' && part !== '..'), 'invalid_package_file');
|
|
25
|
-
assert.ok(/^(?:package\.json|LICENSE|README\.md|plugin\.json|mcp\.json|\.mcp\.json|\.claude-plugin\/plugin\.json|\.codex-plugin\/plugin\.json|adapters\/(?:README\.md|(?:claude|codex|kiro)\/(?:hooks|profile)\.json)|skills\/graphlin\/SKILL\.md|runtime\/(?:[a-z0-9-]+\/)*[a-z0-9-]+\.(?:mjs|js|css|html)|schemas\/[a-z0-9-]+\.schema\.json|scripts\/(?:arguments|build-packages|collector|control|daemon|graphlin|onboarding|validate-packages)\.mjs|scripts\/collect\.sh)$/.test(file),
|
|
70
|
+
assert.ok(/^(?:package\.json|LICENSE|README\.md|plugin\.json|mcp\.json|\.mcp\.json|\.claude-plugin\/plugin\.json|\.codex-plugin\/plugin\.json|adapters\/(?:README\.md|(?:claude|codex|kiro)\/(?:hooks|profile)\.json)|skills\/graphlin\/SKILL\.md|runtime\/(?:[a-z0-9-]+\/)*[a-z0-9-]+\.(?:mjs|js|css|html|d\.ts)|docs\/(?:decision-service|extension-authoring|model-api|visualizer-views|usage)\.md|schemas\/[a-z0-9-]+\.schema\.json|scripts\/(?:arguments|build-packages|collector|control|daemon|extensions|graphlin|onboarding|validate-packages)\.mjs|scripts\/collect\.sh)$/.test(file),
|
|
26
71
|
'unexpected_public_package_file');
|
|
27
|
-
|
|
28
|
-
for (const component of file.split('/')) {
|
|
29
|
-
current = path.join(current, component);
|
|
30
|
-
assert.equal((await lstat(current)).isSymbolicLink(), false, 'package_symlink_rejected');
|
|
31
|
-
}
|
|
32
|
-
assert.ok((await lstat(current)).isFile(), 'package_file_must_be_regular');
|
|
72
|
+
await assertRegularFile(root, file);
|
|
33
73
|
}
|
|
34
|
-
return files;
|
|
74
|
+
return [...files, ...await bundledPackageFiles(root, metadata)];
|
|
35
75
|
}
|
|
36
76
|
|
|
37
77
|
export async function validatePackage(root) {
|
|
38
78
|
const json = async name => JSON.parse(await readFile(path.join(root, name), 'utf8'));
|
|
39
79
|
const metadata = await json('package.json');
|
|
80
|
+
await bundledPackageFiles(root, metadata);
|
|
81
|
+
assert.deepEqual(metadata.exports, SDK_EXPORTS, 'invalid_sdk_exports');
|
|
82
|
+
for (const file of ['runtime/extensions/sdk.mjs', 'runtime/extensions/sdk.d.ts', 'runtime/extensions/scene.mjs']) {
|
|
83
|
+
assert.ok(metadata.files.includes(`./${file}`), 'sdk_export_must_be_packaged');
|
|
84
|
+
await assertRegularFile(root, file);
|
|
85
|
+
}
|
|
40
86
|
const manifest = await json('plugin.json'), portable = await json('mcp.json');
|
|
41
87
|
assert.equal(manifest.$schema, 'https://agent-plugins.org/schemas/1.0.0/plugin.schema.json');
|
|
42
88
|
assert.equal(manifest.name, 'graphlin');
|