graphlin 0.1.3 → 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.
Files changed (102) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/README.md +12 -3
  4. package/docs/decision-service.md +393 -0
  5. package/docs/extension-authoring.md +553 -0
  6. package/docs/model-api.md +293 -0
  7. package/docs/usage.md +465 -0
  8. package/docs/visualizer-views.md +199 -0
  9. package/node_modules/@vscode/tree-sitter-wasm/LICENSE +21 -0
  10. package/node_modules/@vscode/tree-sitter-wasm/README.md +36 -0
  11. package/node_modules/@vscode/tree-sitter-wasm/SECURITY.md +41 -0
  12. package/node_modules/@vscode/tree-sitter-wasm/cgmanifest.json +16 -0
  13. package/node_modules/@vscode/tree-sitter-wasm/package.json +42 -0
  14. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-bash.wasm +0 -0
  15. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-c-sharp.wasm +0 -0
  16. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-cpp.wasm +0 -0
  17. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-css.wasm +0 -0
  18. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-go.wasm +0 -0
  19. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ini.wasm +0 -0
  20. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-java.wasm +0 -0
  21. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-javascript.wasm +0 -0
  22. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-php.wasm +0 -0
  23. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-powershell.wasm +0 -0
  24. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-python.wasm +0 -0
  25. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-regex.wasm +0 -0
  26. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-ruby.wasm +0 -0
  27. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-rust.wasm +0 -0
  28. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-tsx.wasm +0 -0
  29. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter-typescript.wasm +0 -0
  30. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.js +4075 -0
  31. package/node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm +0 -0
  32. package/node_modules/@vscode/tree-sitter-wasm/wasm/web-tree-sitter.d.ts +1027 -0
  33. package/package.json +74 -9
  34. package/plugin.json +4 -2
  35. package/runtime/core/evidence.mjs +43 -9
  36. package/runtime/core/graph.mjs +11 -6
  37. package/runtime/core/privacy.mjs +1 -0
  38. package/runtime/daemon/auth.mjs +7 -3
  39. package/runtime/daemon/diagnostics.mjs +1 -1
  40. package/runtime/daemon/extension-api.mjs +203 -0
  41. package/runtime/daemon/lineage.mjs +70 -0
  42. package/runtime/daemon/manager.mjs +9 -6
  43. package/runtime/daemon/model-api.mjs +728 -0
  44. package/runtime/daemon/model-persistence.mjs +220 -0
  45. package/runtime/daemon/server.mjs +70 -12
  46. package/runtime/daemon/settings.mjs +11 -3
  47. package/runtime/decisions/broker.mjs +349 -0
  48. package/runtime/decisions/contracts.mjs +179 -0
  49. package/runtime/decisions/evaluation.mjs +305 -0
  50. package/runtime/decisions/faults.mjs +32 -0
  51. package/runtime/decisions/index.mjs +818 -0
  52. package/runtime/decisions/profiles.mjs +93 -0
  53. package/runtime/decisions/questions.mjs +268 -0
  54. package/runtime/discovery/index.mjs +2 -0
  55. package/runtime/discovery/inventory.mjs +160 -0
  56. package/runtime/discovery/parser.mjs +40 -0
  57. package/runtime/discovery/structure.mjs +232 -0
  58. package/runtime/extensions/contracts.mjs +59 -0
  59. package/runtime/extensions/frame.mjs +64 -0
  60. package/runtime/extensions/index.mjs +9 -0
  61. package/runtime/extensions/manifest.mjs +95 -0
  62. package/runtime/extensions/packages.mjs +222 -0
  63. package/runtime/extensions/profiles.mjs +36 -0
  64. package/runtime/extensions/projection.mjs +130 -0
  65. package/runtime/extensions/registry.mjs +285 -0
  66. package/runtime/extensions/scene.mjs +105 -0
  67. package/runtime/extensions/sdk.d.ts +205 -0
  68. package/runtime/extensions/sdk.mjs +88 -0
  69. package/runtime/jev/index.mjs +13 -777
  70. package/runtime/jev/provider.mjs +101 -0
  71. package/runtime/jev/questions.mjs +16 -258
  72. package/runtime/jev/wire.mjs +17 -25
  73. package/runtime/model/changes.mjs +42 -0
  74. package/runtime/model/history.mjs +124 -0
  75. package/runtime/model/index.mjs +2 -0
  76. package/runtime/model/project-model.mjs +889 -0
  77. package/runtime/model/records.mjs +239 -0
  78. package/runtime/pipeline.mjs +127 -48
  79. package/runtime/platform.mjs +254 -0
  80. package/runtime/visualizers/blocks.mjs +5 -0
  81. package/runtime/visualizers/c4.mjs +52 -0
  82. package/runtime/visualizers/changes.mjs +24 -0
  83. package/runtime/visualizers/code.mjs +5 -0
  84. package/runtime/visualizers/index.mjs +23 -0
  85. package/runtime/visualizers/structure.mjs +120 -0
  86. package/runtime/visualizers/timeline.mjs +66 -0
  87. package/runtime/web/app.js +225 -63
  88. package/runtime/web/extension-frame.js +128 -0
  89. package/runtime/web/index.html +36 -1
  90. package/runtime/web/model-client.js +162 -0
  91. package/runtime/web/platform.js +337 -0
  92. package/runtime/web/scene.js +111 -0
  93. package/runtime/web/style.css +49 -0
  94. package/schemas/graph.schema.json +4 -1
  95. package/scripts/arguments.mjs +5 -1
  96. package/scripts/build-packages.mjs +6 -2
  97. package/scripts/control.mjs +1 -1
  98. package/scripts/daemon.mjs +2 -1
  99. package/scripts/extensions.mjs +44 -0
  100. package/scripts/graphlin.mjs +23 -3
  101. package/scripts/onboarding.mjs +10 -3
  102. package/scripts/validate-packages.mjs +54 -8
@@ -0,0 +1,88 @@
1
+ // This entry has no Node imports. Bundle it with the extension's one classic
2
+ // browser entry, or use the graphlin:connect event directly without a build tool.
3
+ export { API_VERSION, MODEL_SCHEMA, SCENE_VERSION, EXTENSION_LIMITS } from './contracts.mjs';
4
+ export { validateScene, SCENE_KINDS, SCENE_SHAPES, EDGE_KINDS } from './scene.mjs';
5
+ export { validateDecisionProfile } from './profiles.mjs';
6
+ import { check, exact, id, integer, jsonBytes, EXTENSION_LIMITS } from './contracts.mjs';
7
+ import { validateScene } from './scene.mjs';
8
+
9
+ const CONTEXT = ['instanceId', 'projectId', 'revision', 'viewEpoch', 'requestId'];
10
+ export function validateMessage(message, { model, context } = {}) {
11
+ const payloadFields = {
12
+ 'graphlin:project': ['model', 'settings', 'selection'], 'graphlin:scene': ['scene'],
13
+ 'graphlin:dispose': [], 'graphlin:error': ['code'], 'graphlin:status': ['status', 'itemCount'],
14
+ 'graphlin:select': ['selection'],
15
+ };
16
+ check(message && Object.hasOwn(payloadFields, message.type) &&
17
+ exact(message, ['type', 'apiVersion', ...CONTEXT], payloadFields[message.type]) &&
18
+ message.apiVersion === 1 && ['instanceId', 'projectId', 'requestId'].every(key => id(message[key])) &&
19
+ integer(message.revision) && integer(message.viewEpoch), 'invalid_extension_message');
20
+ jsonBytes(message, EXTENSION_LIMITS.projectionBytes, 'extension_message_limit');
21
+ if (context) check(['apiVersion', ...CONTEXT].every(key => message[key] === context[key]),
22
+ 'extension_message_context_mismatch');
23
+ if (model) check(model.schemaVersion === 2 && model.projectId === message.projectId &&
24
+ model.revision === message.revision, 'extension_model_context_mismatch');
25
+ if (message.type === 'graphlin:status') {
26
+ check(['ready', 'busy', 'empty', 'error'].includes(message.status) &&
27
+ integer(message.itemCount, EXTENSION_LIMITS.entities), 'invalid_extension_status');
28
+ }
29
+ if (message.type === 'graphlin:error') {
30
+ check(['extension_projection_failed', 'extension_unavailable', 'extension_cancelled'].includes(message.code),
31
+ 'invalid_extension_error');
32
+ }
33
+ if (message.type === 'graphlin:select') {
34
+ check(exact(message.selection, [], ['entityId', 'relationId', 'activityId']) &&
35
+ Object.keys(message.selection).length === 1 && Object.values(message.selection).every(id), 'invalid_extension_selection');
36
+ check(model, 'selection_projection_required');
37
+ const [field, target] = Object.entries(message.selection)[0];
38
+ const collection = { entityId: 'entities', relationId: 'relations', activityId: 'activity' }[field];
39
+ check(Array.isArray(model[collection]) && model[collection].some(value => value.id === target),
40
+ 'unknown_extension_selection');
41
+ }
42
+ return message;
43
+ }
44
+
45
+ /** Minimal asynchronous lifecycle. The host also enforces deadlines, rate and
46
+ * size limits, context matching, current grants, and disposal on navigation.
47
+ */
48
+ export function connectExtension({ project, mount, dispose } = {}) {
49
+ check(project === undefined || typeof project === 'function', 'invalid_extension_projector');
50
+ check(mount === undefined || typeof mount === 'function', 'invalid_extension_mount');
51
+ let port, stopped = false, epoch = -1, request = 0;
52
+ const stop = () => {
53
+ if (stopped) return;
54
+ stopped = true; request++;
55
+ port?.close();
56
+ window.removeEventListener('graphlin:connect', connected);
57
+ dispose?.();
58
+ };
59
+ function connected(event) {
60
+ if (port || stopped) return;
61
+ port = event.detail.port;
62
+ mount?.({ root: document.getElementById('graphlin-extension'), assets: event.detail.assets });
63
+ port.onmessage = async event => {
64
+ let message;
65
+ try { message = validateMessage(event.data); } catch { return; }
66
+ if (message.type === 'graphlin:dispose') { stop(); return; }
67
+ if (message.type !== 'graphlin:project' || message.viewEpoch < epoch || stopped) return;
68
+ epoch = message.viewEpoch;
69
+ const current = ++request;
70
+ const context = Object.fromEntries(CONTEXT.map(key => [key, message[key]]));
71
+ try {
72
+ check(message.model?.schemaVersion === 2 && message.model.projectId === message.projectId &&
73
+ message.model.revision === message.revision, 'extension_model_context_mismatch');
74
+ const output = await project?.(message.model, message.settings ?? {}, message.selection ?? null);
75
+ if (current !== request || stopped || !output) return;
76
+ const scene = validateScene(output, { model: message.model });
77
+ port.postMessage({ type: 'graphlin:scene', apiVersion: 1, ...context, scene });
78
+ } catch {
79
+ if (current === request && !stopped) port.postMessage({
80
+ type: 'graphlin:error', apiVersion: 1, ...context, code: 'extension_projection_failed',
81
+ });
82
+ }
83
+ };
84
+ port.start();
85
+ }
86
+ window.addEventListener('graphlin:connect', connected);
87
+ return stop;
88
+ }