@rho-workspace/rho 0.5.4 → 0.5.5

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/dist/browser-access.js +3 -2
  2. package/dist/capabilities.d.ts +2 -2
  3. package/dist/capabilities.js +6 -1
  4. package/dist/cli.js +186 -173
  5. package/dist/contract.generated.d.ts +329 -4
  6. package/dist/contract.generated.js +1 -1
  7. package/dist/contracts/owners.generated.js +360 -6
  8. package/dist/discovery.d.ts +1 -0
  9. package/dist/discovery.js +3 -3
  10. package/dist/extension-contract.d.ts +99 -0
  11. package/dist/extension-contract.js +52 -0
  12. package/dist/extension-directory.d.ts +9 -0
  13. package/dist/extension-directory.js +11 -0
  14. package/dist/extension-worker.d.ts +1 -0
  15. package/dist/extension-worker.js +36 -0
  16. package/dist/extensions.d.ts +157 -0
  17. package/dist/extensions.js +349 -0
  18. package/dist/plugin-cli.d.ts +1 -0
  19. package/dist/plugin-cli.js +139 -0
  20. package/dist/plugin-inventory.json +18 -0
  21. package/dist/plugins.d.ts +3 -3
  22. package/dist/project-work.d.ts +3 -1
  23. package/dist/project-work.js +15 -2
  24. package/dist/protocol.d.ts +7 -0
  25. package/dist/protocol.js +4 -2
  26. package/dist/server.d.ts +4 -1
  27. package/dist/server.js +55 -8
  28. package/dist/web/.vite/manifest.json +61 -61
  29. package/dist/web/assets/{canvas-BXhC8RDZ.js → canvas-D8rDdfDz.js} +1 -1
  30. package/dist/web/assets/choices-b0XhrGQV.js +1 -0
  31. package/dist/web/assets/{console-Dbdo-5oO.js → console-BSjLGe0T.js} +1 -1
  32. package/dist/web/assets/{dist-B2V0VDO0.js → dist-Buk0lwzI.js} +2 -2
  33. package/dist/web/assets/dist-Cw8hRIlT.js +1 -0
  34. package/dist/web/assets/dist-Tzoe_zm-.js +3 -0
  35. package/dist/web/assets/{dist-D25Vn17i.js → dist-foH9IKc6.js} +1 -1
  36. package/dist/web/assets/explore-in-BVUy3ZW_.js +1 -0
  37. package/dist/web/assets/graph-1OdIJ9l7.js +2 -0
  38. package/dist/web/assets/index-CsC3sTRq.css +1 -0
  39. package/dist/web/assets/{index-BHQIaDsx.js → index-CxmItXqa.js} +85 -85
  40. package/dist/web/assets/{notes-meaning-DdPbtNzJ.js → notes-meaning-pVbbQUGP.js} +1 -1
  41. package/dist/web/assets/overview-B9UtVJ32.js +6 -0
  42. package/dist/web/assets/preview-CksD_5KS.js +1 -0
  43. package/dist/web/assets/{review-CmWou4Iv.js → review-CMxQlQ-C.js} +1 -1
  44. package/dist/web/assets/{skills-Dy7n3L9d.js → skills-BFNSyrnD.js} +1 -1
  45. package/dist/web/assets/{skills-work-Cj0W6b-I.js → skills-work-BGPSnF_I.js} +1 -1
  46. package/dist/web/assets/{studio-process-QOY_n2_8.js → studio-process-CsRoTHOh.js} +2 -2
  47. package/dist/web/assets/{timeline-events-DmX1BCh3.js → timeline-events-BbuuFWHV.js} +1 -1
  48. package/dist/web/assets/{work-turns-Co0C71rJ.js → work-turns-BvJlIMmA.js} +1 -1
  49. package/dist/web/assets/workspace-CWlkjLNx.js +5 -0
  50. package/dist/web/composition.json +67 -67
  51. package/dist/web/index.html +3 -3
  52. package/dist/web/renderer.json +1 -1
  53. package/dist/web-assets.d.ts +2 -1
  54. package/dist/web-assets.js +3 -2
  55. package/dist/work-contract.js +2 -2
  56. package/docs/HEADLESS.md +1 -1
  57. package/docs/PLUGIN-AUTHORING.md +4 -0
  58. package/docs/THIRD-PARTY-PLUGINS.md +190 -0
  59. package/node_modules/@rho-workspace/plugin-agent/README.md +39 -0
  60. package/node_modules/@rho-workspace/plugin-agent/dist/activity-normalize.d.ts +1 -0
  61. package/node_modules/@rho-workspace/plugin-agent/dist/activity-normalize.js +2 -2
  62. package/node_modules/@rho-workspace/plugin-agent/dist/dsh-session.d.ts +6 -0
  63. package/node_modules/@rho-workspace/plugin-agent/dist/dsh-session.js +174 -0
  64. package/node_modules/@rho-workspace/plugin-agent/dist/external-session-contract.d.ts +82 -0
  65. package/node_modules/@rho-workspace/plugin-agent/dist/external-session-contract.js +15 -0
  66. package/node_modules/@rho-workspace/plugin-agent/dist/external-session.d.ts +73 -0
  67. package/node_modules/@rho-workspace/plugin-agent/dist/external-session.js +190 -0
  68. package/node_modules/@rho-workspace/plugin-agent/dist/index.d.ts +373 -0
  69. package/node_modules/@rho-workspace/plugin-agent/dist/index.js +1 -0
  70. package/node_modules/@rho-workspace/plugin-agent/dist/operations.d.ts +33 -0
  71. package/node_modules/@rho-workspace/plugin-agent/dist/operations.js +3 -0
  72. package/node_modules/@rho-workspace/plugin-agent/dist/presentation.d.ts +14 -0
  73. package/node_modules/@rho-workspace/plugin-agent/dist/presentation.js +2 -0
  74. package/node_modules/@rho-workspace/plugin-agent/dist/ui-external-session.d.ts +15 -0
  75. package/node_modules/@rho-workspace/plugin-agent/dist/ui-external-session.js +37 -0
  76. package/node_modules/@rho-workspace/plugin-agent/package.json +5 -1
  77. package/package.json +5 -3
  78. package/protocol/index.json +58 -4
  79. package/protocol/operations/agent.sessions.list.json +100 -0
  80. package/protocol/operations/agent.sessions.read.json +266 -0
  81. package/protocol/operations/extension.call.json +132 -0
  82. package/protocol/operations/extension.content.json +78 -0
  83. package/protocol/operations/extension.describe.json +195 -0
  84. package/protocol/operations/extension.install.json +198 -0
  85. package/protocol/operations/extension.list.json +123 -0
  86. package/protocol/operations/extension.manage.json +55 -0
  87. package/protocol/operations/extension.read.json +112 -0
  88. package/protocol/operations/project.work.read.json +3 -2
  89. package/protocol/operations/session.grant.json +9 -0
  90. package/scripts/third-party-acceptance.mjs +77 -0
  91. package/vendor/composition.json +85 -85
  92. package/vendor/rho-workspace-plugin-agent-0.4.29.tgz +0 -0
  93. package/dist/web/assets/choices-DU9kHlyQ.js +0 -1
  94. package/dist/web/assets/dist-BV3hWfn_.js +0 -3
  95. package/dist/web/assets/dist-CLNF2g-E.js +0 -1
  96. package/dist/web/assets/explore-in-8Q5ftt-E.js +0 -1
  97. package/dist/web/assets/graph-hS2kvHTI.js +0 -2
  98. package/dist/web/assets/index-Cj1_iqyK.css +0 -1
  99. package/dist/web/assets/overview-BV6ZO5TO.js +0 -6
  100. package/dist/web/assets/preview-n5lOOdjN.js +0 -1
  101. package/dist/web/assets/workspace-BKFefRfJ.js +0 -5
  102. package/vendor/rho-workspace-plugin-agent-0.4.28.tgz +0 -0
@@ -0,0 +1,123 @@
1
+ {
2
+ "method": "extension.list",
3
+ "inputSchema": {
4
+ "type": "object",
5
+ "properties": {
6
+ "projectId": {
7
+ "type": "string",
8
+ "minLength": 1,
9
+ "maxLength": 1024
10
+ }
11
+ },
12
+ "required": [],
13
+ "additionalProperties": false
14
+ },
15
+ "outputSchema": {
16
+ "type": "object",
17
+ "properties": {
18
+ "plugins": {
19
+ "type": "array",
20
+ "items": {
21
+ "type": "object",
22
+ "properties": {
23
+ "id": {
24
+ "type": "string",
25
+ "pattern": "^[a-z0-9][a-z0-9._-]{0,95}$"
26
+ },
27
+ "name": {
28
+ "type": "string"
29
+ },
30
+ "version": {
31
+ "type": "string"
32
+ },
33
+ "title": {
34
+ "type": "string"
35
+ },
36
+ "description": {
37
+ "type": "string"
38
+ },
39
+ "digest": {
40
+ "type": "string",
41
+ "pattern": "^[a-f0-9]{64}$"
42
+ },
43
+ "source": {
44
+ "type": "string"
45
+ },
46
+ "sourceCommit": {
47
+ "type": "string"
48
+ },
49
+ "enabled": {
50
+ "type": "boolean"
51
+ },
52
+ "installedAt": {
53
+ "type": "string"
54
+ }
55
+ },
56
+ "required": [
57
+ "id",
58
+ "name",
59
+ "version",
60
+ "title",
61
+ "description",
62
+ "digest",
63
+ "source",
64
+ "enabled",
65
+ "installedAt"
66
+ ],
67
+ "additionalProperties": false
68
+ }
69
+ },
70
+ "directory": {
71
+ "type": "array",
72
+ "items": {
73
+ "type": "object",
74
+ "properties": {
75
+ "id": {
76
+ "type": "string",
77
+ "pattern": "^[a-z0-9][a-z0-9._-]{0,95}$"
78
+ },
79
+ "title": {
80
+ "type": "string"
81
+ },
82
+ "version": {
83
+ "type": "string"
84
+ },
85
+ "description": {
86
+ "type": "string"
87
+ },
88
+ "source": {
89
+ "type": "string"
90
+ },
91
+ "repository": {
92
+ "type": "string"
93
+ },
94
+ "needs": {
95
+ "type": "string"
96
+ }
97
+ },
98
+ "required": [
99
+ "id",
100
+ "title",
101
+ "version",
102
+ "description",
103
+ "source",
104
+ "repository",
105
+ "needs"
106
+ ],
107
+ "additionalProperties": false
108
+ }
109
+ },
110
+ "limits": {
111
+ "type": "object",
112
+ "additionalProperties": true
113
+ }
114
+ },
115
+ "required": [
116
+ "plugins",
117
+ "directory",
118
+ "limits"
119
+ ],
120
+ "additionalProperties": false
121
+ },
122
+ "description": "List independently installed third-party packages and their enabled state, source and immutable digest. Reads start no plugin or runtime. Use extension.describe to discover operation schemas and Skills."
123
+ }
@@ -0,0 +1,55 @@
1
+ {
2
+ "method": "extension.manage",
3
+ "inputSchema": {
4
+ "type": "object",
5
+ "properties": {
6
+ "pluginId": {
7
+ "type": "string",
8
+ "pattern": "^[a-z0-9][a-z0-9._-]{0,95}$"
9
+ },
10
+ "expectedDigest": {
11
+ "type": "string",
12
+ "pattern": "^[a-f0-9]{64}$"
13
+ },
14
+ "action": {
15
+ "enum": [
16
+ "enable",
17
+ "disable",
18
+ "remove"
19
+ ]
20
+ }
21
+ },
22
+ "required": [
23
+ "pluginId",
24
+ "expectedDigest",
25
+ "action"
26
+ ],
27
+ "additionalProperties": false
28
+ },
29
+ "outputSchema": {
30
+ "type": "object",
31
+ "properties": {
32
+ "pluginId": {
33
+ "type": "string",
34
+ "pattern": "^[a-z0-9][a-z0-9._-]{0,95}$"
35
+ },
36
+ "action": {
37
+ "enum": [
38
+ "enable",
39
+ "disable",
40
+ "remove"
41
+ ]
42
+ },
43
+ "retained": {
44
+ "type": "string"
45
+ }
46
+ },
47
+ "required": [
48
+ "pluginId",
49
+ "action",
50
+ "retained"
51
+ ],
52
+ "additionalProperties": false
53
+ },
54
+ "description": "Local person/operator: enable, disable or remove an installed third-party package at the expected digest. Existing native tasks, R sessions, project files and retained receipts are preserved."
55
+ }
@@ -0,0 +1,112 @@
1
+ {
2
+ "method": "extension.read",
3
+ "inputSchema": {
4
+ "type": "object",
5
+ "properties": {
6
+ "projectId": {
7
+ "type": "string",
8
+ "minLength": 1,
9
+ "maxLength": 1024
10
+ },
11
+ "invocationId": {
12
+ "type": "string",
13
+ "pattern": "^[a-f0-9]{64}$"
14
+ }
15
+ },
16
+ "required": [
17
+ "projectId",
18
+ "invocationId"
19
+ ],
20
+ "additionalProperties": false
21
+ },
22
+ "outputSchema": {
23
+ "type": "object",
24
+ "properties": {
25
+ "invocationId": {
26
+ "type": "string",
27
+ "pattern": "^[a-f0-9]{64}$"
28
+ },
29
+ "caller": {
30
+ "type": "string"
31
+ },
32
+ "projectId": {
33
+ "type": "string"
34
+ },
35
+ "pluginId": {
36
+ "type": "string",
37
+ "pattern": "^[a-z0-9][a-z0-9._-]{0,95}$"
38
+ },
39
+ "packageDigest": {
40
+ "type": "string",
41
+ "pattern": "^[a-f0-9]{64}$"
42
+ },
43
+ "operation": {
44
+ "type": "string",
45
+ "pattern": "^[a-z0-9][a-z0-9._-]{0,95}$"
46
+ },
47
+ "requestDigest": {
48
+ "type": "string",
49
+ "pattern": "^[a-f0-9]{64}$"
50
+ },
51
+ "state": {
52
+ "enum": [
53
+ "pending",
54
+ "completed",
55
+ "unknown"
56
+ ]
57
+ },
58
+ "startedAt": {
59
+ "type": "string"
60
+ },
61
+ "endedAt": {
62
+ "type": "string"
63
+ },
64
+ "value": {},
65
+ "error": {
66
+ "type": "string"
67
+ },
68
+ "delegations": {
69
+ "type": "array",
70
+ "items": {
71
+ "type": "object",
72
+ "properties": {
73
+ "method": {
74
+ "type": "string"
75
+ },
76
+ "request": {},
77
+ "state": {
78
+ "enum": [
79
+ "pending",
80
+ "completed",
81
+ "unknown"
82
+ ]
83
+ },
84
+ "value": {},
85
+ "error": {
86
+ "type": "string"
87
+ }
88
+ },
89
+ "required": [
90
+ "method",
91
+ "request",
92
+ "state"
93
+ ],
94
+ "additionalProperties": false
95
+ }
96
+ }
97
+ },
98
+ "required": [
99
+ "invocationId",
100
+ "caller",
101
+ "projectId",
102
+ "pluginId",
103
+ "packageDigest",
104
+ "operation",
105
+ "requestDigest",
106
+ "state",
107
+ "startedAt"
108
+ ],
109
+ "additionalProperties": false
110
+ },
111
+ "description": "Observe an original plugin invocation, including pending or unknown outcomes. Never reruns code. Only its original caller can read it."
112
+ }
@@ -68,7 +68,8 @@
68
68
  "acp",
69
69
  "claude-cli",
70
70
  "native-transcript",
71
- "external-acp"
71
+ "external-acp",
72
+ "external-session"
72
73
  ]
73
74
  },
74
75
  "sessionId": {
@@ -573,7 +574,7 @@
573
574
  "resourceRefs"
574
575
  ]
575
576
  },
576
- "maxItems": 80
577
+ "maxItems": 88
577
578
  },
578
579
  "files": {
579
580
  "type": "array",
@@ -27,6 +27,8 @@
27
27
  "agent.activity.capture",
28
28
  "agent.activity.outputs",
29
29
  "agent.activity.read",
30
+ "agent.sessions.list",
31
+ "agent.sessions.read",
30
32
  "annotation.create",
31
33
  "annotation.decide",
32
34
  "annotation.list",
@@ -68,6 +70,13 @@
68
70
  "document.undoOwn",
69
71
  "evidence.export",
70
72
  "evidence.preview",
73
+ "extension.call",
74
+ "extension.content",
75
+ "extension.describe",
76
+ "extension.install",
77
+ "extension.list",
78
+ "extension.manage",
79
+ "extension.read",
71
80
  "feedback.read",
72
81
  "feedback.status",
73
82
  "feedback.submit",
@@ -0,0 +1,77 @@
1
+ #!/usr/bin/env node
2
+ // An opt-in, real scientific episode. R packages must already be available;
3
+ // this script never installs dependencies or touches an existing R session.
4
+ import fs from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import os from 'node:os';
7
+ import assert from 'node:assert/strict';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { RhoService } from '../dist/server.js';
10
+ import { RhoClient } from '../dist/client.js';
11
+
12
+ const repo = fileURLToPath(new URL('../', import.meta.url));
13
+ const source = process.env.RHO_SCLET_PLUGIN ?? path.resolve(repo, '../Rho-plugins/examples/sclet-plugin');
14
+ const root = await fs.mkdtemp(path.join(os.tmpdir(), 'rho-third-party-'));
15
+ await fs.mkdir(path.join(root, 'project'));
16
+ const service = await new RhoService({ root, stateDir: path.join(root, 'state'), rscript: process.env.RHO_RSCRIPT ?? 'Rscript', example: false }).start();
17
+ const client = new RhoClient({ url: service.url, token: service.adminToken });
18
+ const project = await client.call('project.open', { path: 'project' });
19
+ const notes = [];
20
+ let sequence = 0;
21
+ const text = cell => cell.outputs.map(output => output.text ?? '').join('\n') + (cell.error ? '\n' + JSON.stringify(cell.error) : '');
22
+ const json = value => JSON.parse(value.slice(value.indexOf('{'), value.lastIndexOf('}') + 1));
23
+ async function finished(cell) {
24
+ for (let i = 0; i < 600; i++) {
25
+ const current = (await client.call('kernel.read', { projectId: project.id, cellId: cell.cellId })).cells[0];
26
+ if (['done', 'error', 'unknown', 'interrupted'].includes(current.state)) return current;
27
+ await new Promise(resolve => setTimeout(resolve, 500));
28
+ }
29
+ throw new Error('Observation deadline reached; original cell: ' + cell.cellId);
30
+ }
31
+ try {
32
+ const plugin = await client.call('extension.install', { source });
33
+ const invoke = (operation, input = {}, changeId = 'acceptance-' + ++sequence) => client.call('extension.call', { projectId: project.id, pluginId: plugin.id, expectedDigest: plugin.digest, operation, input, changeId });
34
+ assert.deepEqual((await invoke('sessions')).value.sessions, []);
35
+ async function run(operation, input = {}) {
36
+ const receipt = await invoke(operation, input); assert.equal(receipt.state, 'completed', receipt.error);
37
+ const cell = await finished(receipt.value.cell); notes.push({ operation, cellId: cell.cellId, state: cell.state });
38
+ assert.equal(cell.state, 'done', text(cell)); return { receipt, cell, text: text(cell) };
39
+ }
40
+ const library = process.env.RHO_SCLET_LIBRARY;
41
+ const seedCode = `${library ? '.libPaths(c(' + JSON.stringify(library) + ', .libPaths()))\n' : ''}if (!requireNamespace("sclet", quietly=TRUE)) stop("Set RHO_SCLET_LIBRARY to an existing sclet library.")\nset.seed(19)\nsce <- scuttle::mockSCE(ncells=60, ngenes=200)`;
42
+ const seed = await client.call('kernel.run', { projectId: project.id, language: 'r', code: seedCode, purpose: 'Disposable third-party plugin trial', changeId: 'seed', waitMs: 0 });
43
+ const seeded = await finished(seed.cell); assert.equal(seeded.state, 'done', text(seeded));
44
+ const packages = await run('check');
45
+ const before = json((await run('ledger', { object: 'sce', includeArtifacts: true })).text);
46
+ await run('registry', { object: 'sce' }); await run('skill', { name: 'sclet-driver' });
47
+ const plan = { task: 'plugin-acceptance', context_fingerprint: before.fingerprint, actions: [
48
+ { id: 'normalize', action: 'normalize_data' },
49
+ { id: 'hvg', action: 'find_variable_features', params: { nfeatures: 50 }, depends_on: 'normalize' },
50
+ { id: 'scale', action: 'scale_data', depends_on: 'hvg' },
51
+ { id: 'pca', action: 'run_pca', params: { ncomponents: 5 }, depends_on: 'scale' },
52
+ ] };
53
+ const validated = json((await run('validate', { object: 'sce', plan })).text); assert.equal(validated.validation.valid, true);
54
+ const executeBody = { validationId: validated.validationId };
55
+ const execution = await invoke('execute', executeBody, 'execute-once'); assert.equal(execution.state, 'completed', execution.error);
56
+ const executed = await finished(execution.value.cell); assert.equal(executed.state, 'done', text(executed));
57
+ assert.equal(json(text(executed)).status, 'completed');
58
+ assert.equal((await invoke('execute', executeBody, 'execute-once')).value.cell.cellId, executed.cellId);
59
+ await run('record', { object: 'sce', recordId: 'smoke-report', result: {
60
+ task: 'plugin-acceptance', answer: 'A synthetic 200-gene, 60-cell input completed normalization, variable feature selection, scaling and PCA. This verifies software integration; no biological conclusion is claimed.',
61
+ findings: [], evidence: [], warnings: ['Synthetic input, not evidence for a biological hypothesis.'], recommendations: [], proposed_actions: [], success_criteria: [], stop_conditions: [], context: { fingerprint: json(text(executed)).fingerprint }, metadata: { provider: 'integration-test' },
62
+ } });
63
+ const report = await run('report', { object: 'sce', recordId: 'smoke-report' }); assert.match(report.text, /all checks passed/);
64
+ const after = json((await run('ledger', { object: 'sce', includeArtifacts: true })).text);
65
+ assert.equal(after.dataset.reductions, 'PCA'); assert.equal(after.features.hvg.n, 50);
66
+ assert.equal(json((await run('validate', { object: 'sce', plan })).text).validation.valid, false);
67
+ await client.call('extension.manage', { pluginId: plugin.id, expectedDigest: plugin.digest, action: 'disable' });
68
+ await assert.rejects(invoke('ledger', { object: 'sce' }), /disabled/);
69
+ await client.call('extension.manage', { pluginId: plugin.id, expectedDigest: plugin.digest, action: 'remove' });
70
+ assert.equal((await invoke('execute', executeBody, 'execute-once')).value.cell.cellId, executed.cellId);
71
+ const sessions = await client.call('kernel.read', { projectId: project.id, limit: 1 });
72
+ assert.ok(sessions.sessions.some(s => s.sessionId === seed.cell.sessionId && s.state !== 'ended'));
73
+ const output = path.resolve(process.env.RHO_THIRD_PARTY_OUTPUT ?? path.join(repo, 'output/third-party-plugins/acceptance.json'));
74
+ await fs.mkdir(path.dirname(output), { recursive: true });
75
+ await fs.writeFile(output, JSON.stringify({ at: new Date().toISOString(), node: process.version, platform: process.platform, source, digest: plugin.digest, packages: packages.text, notes, execution: json(text(executed)), report: report.text, lifecycle: 'disable/remove retained original cell and live R session', passed: true }, null, 2) + '\n');
76
+ console.log(JSON.stringify({ passed: true, output }));
77
+ } finally { await service.close(); await fs.rm(root, { recursive: true, force: true }); }