@rsconcept/rstool 0.10.2 → 1.0.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/README.md +41 -31
- package/dist/agent-workflow-D-PSIb-m.d.ts +70 -0
- package/dist/analysis-LLnPhmGa.d.ts +23 -0
- package/dist/{common-DxLg3eXX.d.ts → common-DHJalS-Q.d.ts} +6 -1
- package/dist/constituenta-DnGR6bnM.d.ts +54 -0
- package/dist/diagnostic-D9yl_mEL.d.ts +19 -0
- package/dist/evaluation-Cns8BFm4.d.ts +31 -0
- package/dist/index.d.ts +11 -11
- package/dist/index.js +1 -1
- package/dist/mappers/model-adapter.d.ts +3 -3
- package/dist/mappers/schema-adapter.d.ts +4 -4
- package/dist/mappers/types.d.ts +6 -2
- package/dist/mappers/types.js +2 -0
- package/dist/mappers/types.js.map +1 -1
- package/dist/{model-value-SFAVj0dw.d.ts → model-value-BbonPzMz.d.ts} +14 -3
- package/dist/models/agent-workflow.d.ts +2 -0
- package/dist/models/agent-workflow.js +1 -0
- package/dist/models/analysis.d.ts +1 -1
- package/dist/models/common.d.ts +1 -1
- package/dist/models/constituenta.d.ts +2 -2
- package/dist/models/diagnostic.d.ts +1 -1
- package/dist/models/evaluation.d.ts +2 -2
- package/dist/models/index.d.ts +11 -11
- package/dist/models/index.js +2 -2
- package/dist/models/model-value.d.ts +2 -2
- package/dist/models/rstool-agent.d.ts +1 -1
- package/dist/models/rstool-agent.js +1 -1
- package/dist/models/session.d.ts +1 -1
- package/dist/models/tool-contract.d.ts +2 -2
- package/dist/models/tool-contract.js +2 -1
- package/dist/models/tool-contract.js.map +1 -1
- package/dist/rstool-agent-_8bplZnb.d.ts +71 -0
- package/dist/rstool-agent-kijHA9ML.js +476 -0
- package/dist/rstool-agent-kijHA9ML.js.map +1 -0
- package/dist/session/session-store.d.ts +18 -5
- package/dist/session/session-store.js +1 -64
- package/dist/{session-BPgsE80c.d.ts → session-ChexW8i7.d.ts} +11 -8
- package/dist/session-store-C3jyOSqI.js +142 -0
- package/dist/session-store-C3jyOSqI.js.map +1 -0
- package/dist/tool-contract-5_Q44DGE.d.ts +164 -0
- package/dist/wrapper/client.d.ts +23 -0
- package/dist/wrapper/client.js +17 -0
- package/dist/wrapper/client.js.map +1 -1
- package/dist/wrapper/stdio-wrapper.js +62 -52
- package/dist/wrapper/stdio-wrapper.js.map +1 -1
- package/docs/CONSTITUENTA.md +2 -2
- package/docs/DIAGNOSTICS.md +20 -18
- package/docs/MODEL-TESTING.md +3 -3
- package/docs/PORTAL-API.md +24 -18
- package/examples/README.md +1 -1
- package/examples/agent-client.ts +11 -41
- package/examples/build-chocolate-nim-rsform.ts +23 -18
- package/examples/chocolate-nim/build-rsform.ts +23 -18
- package/examples/chocolate-nim/build-rsmodel.ts +10 -12
- package/examples/chocolate-nim/rsform-session.json +290 -290
- package/examples/chocolate-nim/rsmodel-session.json +291 -291
- package/examples/expression-bank/bank-constituents.ts +304 -53
- package/examples/expression-bank/build-rsform.ts +19 -16
- package/examples/expression-bank/rsform-session.json +1551 -1551
- package/examples/kinship/build-rsform.ts +23 -18
- package/examples/kinship/build-rsmodel.ts +13 -15
- package/examples/kinship/rsform-session.json +219 -219
- package/examples/kinship/rsmodel-session.json +221 -221
- package/examples/kinship/session.ts +19 -21
- package/examples/movd/build-rsform.ts +23 -18
- package/examples/movd/build-rsmodel.ts +18 -20
- package/examples/movd/rsform-session.json +262 -262
- package/examples/movd/rsmodel-session.json +264 -264
- package/examples/sample/build-rsform.ts +19 -50
- package/examples/sample/build-rsmodel.ts +25 -44
- package/examples/sample/rsform-session.json +36 -33
- package/examples/sample/rsmodel-session.json +36 -33
- package/examples/template-apply/build-rsform.ts +27 -24
- package/examples/template-apply/rsform-session.json +48 -48
- package/package.json +3 -3
- package/skills/rstool-helper/EXAMPLES.md +44 -116
- package/skills/rstool-helper/GUIDE.md +40 -25
- package/skills/rstool-helper/REFERENCE.md +40 -177
- package/src/index.ts +24 -17
- package/src/mappers/portal-adapter.ts +43 -0
- package/src/mappers/types.ts +4 -0
- package/src/models/agent-workflow.ts +78 -0
- package/src/models/analysis.ts +7 -0
- package/src/models/common.ts +7 -0
- package/src/models/constituenta.ts +24 -6
- package/src/models/diagnostic.ts +4 -0
- package/src/models/evaluation.ts +11 -0
- package/src/models/import-detect.ts +39 -0
- package/src/models/import-export.ts +24 -0
- package/src/models/index.ts +22 -14
- package/src/models/model-value.ts +12 -0
- package/src/models/portal-json.ts +44 -0
- package/src/models/rstool-agent.test.ts +300 -147
- package/src/models/rstool-agent.ts +350 -93
- package/src/models/session.ts +8 -5
- package/src/models/tool-contract.ts +81 -42
- package/src/session/batch-apply.test.ts +28 -0
- package/src/session/batch-apply.ts +47 -0
- package/src/session/persistence.ts +56 -0
- package/src/session/session-store.ts +67 -4
- package/src/wrapper/client.ts +23 -0
- package/src/wrapper/stdio-wrapper.ts +59 -49
- package/dist/analysis-JiwOYDKx.d.ts +0 -16
- package/dist/constituenta-Dnd6iToB.d.ts +0 -36
- package/dist/diagnostic-BMYvciz8.d.ts +0 -15
- package/dist/evaluation-CCVYH0wA.d.ts +0 -21
- package/dist/index-uhkmwruf.d.ts +0 -46
- package/dist/rstool-agent-BZi5jO1y.js +0 -158
- package/dist/rstool-agent-BZi5jO1y.js.map +0 -1
- package/dist/rstool-agent-pRaPnZay.d.ts +0 -35
- package/dist/session/session-store.js.map +0 -1
- package/dist/tool-contract-n1ghUOrK.d.ts +0 -32
|
@@ -1,17 +1,21 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
1
4
|
import { describe, expect, it } from 'vitest';
|
|
2
5
|
|
|
3
6
|
import { CstType, EvalStatus, RSErrorCode, RSToolAgent } from './index';
|
|
4
7
|
|
|
5
8
|
function buildSampleForm(tool: RSToolAgent, sessionId: string) {
|
|
6
|
-
tool.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
tool.applySchemaPatch(
|
|
10
|
+
{
|
|
11
|
+
items: [{ alias: 'X1' }, { alias: 'D1', definitionFormal: '1+2' }, { alias: 'A1', definitionFormal: '1=1' }]
|
|
12
|
+
},
|
|
13
|
+
sessionId
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function fullState(tool: RSToolAgent, sessionId?: string) {
|
|
18
|
+
return tool.getSessionState('full', sessionId) as import('./session').SessionState;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
describe('RSToolAgent', () => {
|
|
@@ -26,10 +30,7 @@ describe('RSToolAgent', () => {
|
|
|
26
30
|
it('analyzes a valid expression', () => {
|
|
27
31
|
const tool = new RSToolAgent();
|
|
28
32
|
const session = tool.createSession();
|
|
29
|
-
const analysis = tool.analyzeExpression(session.sessionId
|
|
30
|
-
expression: '1+2',
|
|
31
|
-
cstType: CstType.TERM
|
|
32
|
-
});
|
|
33
|
+
const analysis = tool.analyzeExpression({ expression: '1+2', cstType: CstType.TERM }, session.sessionId);
|
|
33
34
|
expect(analysis.success).toBe(true);
|
|
34
35
|
expect(analysis.diagnostics.length).toBe(0);
|
|
35
36
|
});
|
|
@@ -37,10 +38,7 @@ describe('RSToolAgent', () => {
|
|
|
37
38
|
it('returns syntax diagnostics for invalid expression', () => {
|
|
38
39
|
const tool = new RSToolAgent();
|
|
39
40
|
const session = tool.createSession();
|
|
40
|
-
const analysis = tool.analyzeExpression(session.sessionId
|
|
41
|
-
expression: '(',
|
|
42
|
-
cstType: CstType.TERM
|
|
43
|
-
});
|
|
41
|
+
const analysis = tool.analyzeExpression({ expression: '(', cstType: CstType.TERM }, session.sessionId);
|
|
44
42
|
expect(analysis.success).toBe(false);
|
|
45
43
|
expect(analysis.diagnostics.length).toBeGreaterThan(0);
|
|
46
44
|
});
|
|
@@ -48,68 +46,64 @@ describe('RSToolAgent', () => {
|
|
|
48
46
|
it('rejects formal definition for constants', () => {
|
|
49
47
|
const tool = new RSToolAgent();
|
|
50
48
|
const session = tool.createSession();
|
|
51
|
-
const result = tool.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
expect(result.state.analysis.success).toBe(false);
|
|
60
|
-
expect(result.diagnostics[0]?.error.code).toBe(RSErrorCode.definitionNotAllowed);
|
|
49
|
+
const result = tool.applySchemaPatch(
|
|
50
|
+
{
|
|
51
|
+
items: [{ alias: 'C1', cstType: CstType.CONSTANT, definitionFormal: 'X1' }]
|
|
52
|
+
},
|
|
53
|
+
session.sessionId
|
|
54
|
+
);
|
|
55
|
+
expect(result.success).toBe(false);
|
|
56
|
+
expect(result.failed[0]?.diagnostics[0]?.error.code).toBe(RSErrorCode.definitionNotAllowed);
|
|
61
57
|
});
|
|
62
58
|
|
|
63
59
|
it('rejects formal definition for basic sets', () => {
|
|
64
60
|
const tool = new RSToolAgent();
|
|
65
61
|
const session = tool.createSession();
|
|
66
|
-
const result = tool.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
expect(result.state.analysis.success).toBe(false);
|
|
75
|
-
expect(result.diagnostics[0]?.error.code).toBe(RSErrorCode.definitionNotAllowed);
|
|
62
|
+
const result = tool.applySchemaPatch(
|
|
63
|
+
{
|
|
64
|
+
items: [{ alias: 'X1', cstType: CstType.BASE, definitionFormal: 'Z' }]
|
|
65
|
+
},
|
|
66
|
+
session.sessionId
|
|
67
|
+
);
|
|
68
|
+
expect(result.success).toBe(false);
|
|
69
|
+
expect(result.failed[0]?.diagnostics[0]?.error.code).toBe(RSErrorCode.definitionNotAllowed);
|
|
76
70
|
});
|
|
77
71
|
|
|
78
72
|
it('returns known analysis for empty base definition', () => {
|
|
79
73
|
const tool = new RSToolAgent();
|
|
80
74
|
const session = tool.createSession();
|
|
81
|
-
const result = tool.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
expect(
|
|
90
|
-
expect(
|
|
91
|
-
expect(result.state.analysis.valueClass).toBe('value');
|
|
75
|
+
const result = tool.applySchemaPatch(
|
|
76
|
+
{
|
|
77
|
+
items: [{ alias: 'X1', cstType: CstType.BASE, definitionFormal: '' }]
|
|
78
|
+
},
|
|
79
|
+
session.sessionId
|
|
80
|
+
);
|
|
81
|
+
expect(result.success).toBe(true);
|
|
82
|
+
const state = fullState(tool, session.sessionId);
|
|
83
|
+
expect(state.items[0]?.analysis.type).not.toBeNull();
|
|
84
|
+
expect(state.items[0]?.analysis.valueClass).toBe('value');
|
|
92
85
|
});
|
|
93
86
|
|
|
94
87
|
it('persists term, definitionText, and convention in session state', () => {
|
|
95
88
|
const tool = new RSToolAgent();
|
|
96
89
|
const session = tool.createSession();
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
90
|
+
tool.applySchemaPatch(
|
|
91
|
+
{
|
|
92
|
+
items: [
|
|
93
|
+
{
|
|
94
|
+
alias: 'D2',
|
|
95
|
+
cstType: CstType.TERM,
|
|
96
|
+
definitionFormal: '1',
|
|
97
|
+
term: 'natural number',
|
|
98
|
+
definitionText: 'A positive integer',
|
|
99
|
+
convention: 'Standard arithmetic'
|
|
100
|
+
}
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
session.sessionId
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
const form = fullState(tool, session.sessionId);
|
|
113
107
|
expect(form.items[0]).toMatchObject({
|
|
114
108
|
term: 'natural number',
|
|
115
109
|
definitionText: 'A positive integer',
|
|
@@ -117,8 +111,8 @@ describe('RSToolAgent', () => {
|
|
|
117
111
|
});
|
|
118
112
|
|
|
119
113
|
const exported = tool.exportSession(session.sessionId);
|
|
120
|
-
const imported = tool.
|
|
121
|
-
const restored = tool
|
|
114
|
+
const imported = tool.importData(exported, 'session');
|
|
115
|
+
const restored = fullState(tool, imported.sessionId);
|
|
122
116
|
expect(restored.items[0]).toMatchObject({
|
|
123
117
|
term: 'natural number',
|
|
124
118
|
definitionText: 'A positive integer',
|
|
@@ -134,13 +128,13 @@ describe('RSToolAgent', () => {
|
|
|
134
128
|
comment: 'Example schema'
|
|
135
129
|
});
|
|
136
130
|
|
|
137
|
-
expect(tool
|
|
131
|
+
expect(fullState(tool, session.sessionId)).toMatchObject({
|
|
138
132
|
alias: 'KIN',
|
|
139
133
|
title: 'Kinship',
|
|
140
134
|
comment: 'Example schema'
|
|
141
135
|
});
|
|
142
136
|
|
|
143
|
-
const exported = JSON.parse(tool.
|
|
137
|
+
const exported = JSON.parse(tool.exportPortal({ kind: 'schema' }, session.sessionId) as string) as {
|
|
144
138
|
title: string;
|
|
145
139
|
alias: string;
|
|
146
140
|
description: string;
|
|
@@ -155,19 +149,23 @@ describe('RSToolAgent', () => {
|
|
|
155
149
|
it('exports schema data for Portal JSON import', () => {
|
|
156
150
|
const tool = new RSToolAgent();
|
|
157
151
|
const session = tool.createSession();
|
|
158
|
-
tool.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
152
|
+
tool.applySchemaPatch(
|
|
153
|
+
{
|
|
154
|
+
items: [
|
|
155
|
+
{
|
|
156
|
+
alias: 'D2',
|
|
157
|
+
cstType: CstType.TERM,
|
|
158
|
+
definitionFormal: '1',
|
|
159
|
+
term: 'natural number',
|
|
160
|
+
definitionText: 'A positive integer',
|
|
161
|
+
convention: 'Standard arithmetic'
|
|
162
|
+
}
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
session.sessionId
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
const exported = JSON.parse(tool.exportPortal({ kind: 'schema' }, session.sessionId) as string) as {
|
|
171
169
|
contract_version: string;
|
|
172
170
|
title: string;
|
|
173
171
|
alias: string;
|
|
@@ -182,7 +180,6 @@ describe('RSToolAgent', () => {
|
|
|
182
180
|
expect(exported.description).toBe('');
|
|
183
181
|
|
|
184
182
|
expect(exported.items[0]).toMatchObject({
|
|
185
|
-
id: 15,
|
|
186
183
|
alias: 'D2',
|
|
187
184
|
cst_type: CstType.TERM,
|
|
188
185
|
definition_formal: '1',
|
|
@@ -198,12 +195,9 @@ describe('RSToolAgent', () => {
|
|
|
198
195
|
const tool = new RSToolAgent();
|
|
199
196
|
const session = tool.createSession();
|
|
200
197
|
buildSampleForm(tool, session.sessionId);
|
|
201
|
-
await tool.
|
|
202
|
-
target: 1,
|
|
203
|
-
value: { 1: 'Alice' }
|
|
204
|
-
});
|
|
198
|
+
await tool.setModelValues({ set: [{ target: 1, value: { 1: 'Alice' } }] }, session.sessionId);
|
|
205
199
|
|
|
206
|
-
const exported = JSON.parse(tool.
|
|
200
|
+
const exported = JSON.parse(tool.exportPortal({ kind: 'model' }, session.sessionId) as string) as {
|
|
207
201
|
contract_version: string;
|
|
208
202
|
title: string;
|
|
209
203
|
alias: string;
|
|
@@ -227,33 +221,31 @@ describe('RSToolAgent', () => {
|
|
|
227
221
|
it('defaults missing text fields to empty strings', () => {
|
|
228
222
|
const tool = new RSToolAgent();
|
|
229
223
|
const session = tool.createSession();
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
expect(
|
|
239
|
-
expect(
|
|
240
|
-
expect(result.state.convention).toBe('');
|
|
224
|
+
tool.applySchemaPatch(
|
|
225
|
+
{
|
|
226
|
+
items: [{ alias: 'D3', cstType: CstType.TERM, definitionFormal: '2' }]
|
|
227
|
+
},
|
|
228
|
+
session.sessionId
|
|
229
|
+
);
|
|
230
|
+
const state = fullState(tool, session.sessionId);
|
|
231
|
+
expect(state.items[0]?.term).toBe('');
|
|
232
|
+
expect(state.items[0]?.definitionText).toBe('');
|
|
233
|
+
expect(state.items[0]?.convention).toBe('');
|
|
241
234
|
});
|
|
242
235
|
|
|
243
236
|
it('returns known analysis for empty constant definition', () => {
|
|
244
237
|
const tool = new RSToolAgent();
|
|
245
238
|
const session = tool.createSession();
|
|
246
|
-
const result = tool.
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
expect(
|
|
255
|
-
expect(
|
|
256
|
-
expect(result.state.analysis.valueClass).toBe('value');
|
|
239
|
+
const result = tool.applySchemaPatch(
|
|
240
|
+
{
|
|
241
|
+
items: [{ alias: 'C1', cstType: CstType.CONSTANT, definitionFormal: '' }]
|
|
242
|
+
},
|
|
243
|
+
session.sessionId
|
|
244
|
+
);
|
|
245
|
+
expect(result.success).toBe(true);
|
|
246
|
+
const state = fullState(tool, session.sessionId);
|
|
247
|
+
expect(state.items[0]?.analysis.type).not.toBeNull();
|
|
248
|
+
expect(state.items[0]?.analysis.valueClass).toBe('value');
|
|
257
249
|
});
|
|
258
250
|
});
|
|
259
251
|
|
|
@@ -270,10 +262,10 @@ describe('RSToolAgent modeling and evaluation', () => {
|
|
|
270
262
|
const session = tool.createSession();
|
|
271
263
|
buildSampleForm(tool, session.sessionId);
|
|
272
264
|
|
|
273
|
-
const model = await tool.
|
|
274
|
-
target: 1,
|
|
275
|
-
|
|
276
|
-
|
|
265
|
+
const model = await tool.setModelValues(
|
|
266
|
+
{ set: [{ target: 1, value: { 0: 'zero', 1: 'one' } }] },
|
|
267
|
+
session.sessionId
|
|
268
|
+
);
|
|
277
269
|
expect(model.items).toHaveLength(1);
|
|
278
270
|
expect(model.items[0]).toMatchObject({
|
|
279
271
|
id: 1,
|
|
@@ -287,12 +279,9 @@ describe('RSToolAgent modeling and evaluation', () => {
|
|
|
287
279
|
const session = tool.createSession();
|
|
288
280
|
buildSampleForm(tool, session.sessionId);
|
|
289
281
|
|
|
290
|
-
await expect(
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
value: 3
|
|
294
|
-
})
|
|
295
|
-
).rejects.toThrow(/inferrable/);
|
|
282
|
+
await expect(tool.setModelValues({ set: [{ target: 2, value: 3 }] }, session.sessionId)).rejects.toThrow(
|
|
283
|
+
/inferrable/
|
|
284
|
+
);
|
|
296
285
|
});
|
|
297
286
|
|
|
298
287
|
it('evaluates expression against session context', () => {
|
|
@@ -300,10 +289,7 @@ describe('RSToolAgent modeling and evaluation', () => {
|
|
|
300
289
|
const session = tool.createSession();
|
|
301
290
|
buildSampleForm(tool, session.sessionId);
|
|
302
291
|
|
|
303
|
-
const result = tool.
|
|
304
|
-
expression: '1+2',
|
|
305
|
-
cstType: CstType.TERM
|
|
306
|
-
});
|
|
292
|
+
const result = tool.evaluate({ expression: '1+2', cstType: CstType.TERM }, session.sessionId);
|
|
307
293
|
expect(result.success).toBe(true);
|
|
308
294
|
expect(result.value).toBe(3);
|
|
309
295
|
expect(result.status).toBe(EvalStatus.HAS_DATA);
|
|
@@ -315,7 +301,7 @@ describe('RSToolAgent modeling and evaluation', () => {
|
|
|
315
301
|
const session = tool.createSession();
|
|
316
302
|
buildSampleForm(tool, session.sessionId);
|
|
317
303
|
|
|
318
|
-
const result = tool.
|
|
304
|
+
const result = tool.evaluate({ constituentId: 2 }, session.sessionId);
|
|
319
305
|
expect(result.success).toBe(true);
|
|
320
306
|
expect(result.value).toBe(3);
|
|
321
307
|
expect(result.status).toBe(EvalStatus.HAS_DATA);
|
|
@@ -326,7 +312,7 @@ describe('RSToolAgent modeling and evaluation', () => {
|
|
|
326
312
|
const session = tool.createSession();
|
|
327
313
|
buildSampleForm(tool, session.sessionId);
|
|
328
314
|
|
|
329
|
-
const result = tool.
|
|
315
|
+
const result = tool.evaluate({ constituentId: 3 }, session.sessionId);
|
|
330
316
|
expect(result.success).toBe(true);
|
|
331
317
|
expect(result.value).toBe(1);
|
|
332
318
|
});
|
|
@@ -349,31 +335,31 @@ describe('RSToolAgent modeling and evaluation', () => {
|
|
|
349
335
|
const tool = new RSToolAgent();
|
|
350
336
|
const session = tool.createSession();
|
|
351
337
|
buildSampleForm(tool, session.sessionId);
|
|
352
|
-
await tool.
|
|
353
|
-
target: 1,
|
|
354
|
-
value: { 0: 'a' }
|
|
355
|
-
});
|
|
338
|
+
await tool.setModelValues({ set: [{ target: 1, value: { 0: 'a' } }] }, session.sessionId);
|
|
356
339
|
|
|
357
|
-
const model = await tool.
|
|
340
|
+
const model = await tool.setModelValues({ clear: [1] }, session.sessionId);
|
|
358
341
|
expect(model.items).toHaveLength(0);
|
|
359
342
|
});
|
|
360
343
|
|
|
361
344
|
it('batch sets model values', async () => {
|
|
362
345
|
const tool = new RSToolAgent();
|
|
363
346
|
const session = tool.createSession();
|
|
364
|
-
tool.
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
347
|
+
tool.applySchemaPatch(
|
|
348
|
+
{
|
|
349
|
+
items: [{ alias: 'X1' }, { alias: 'C1', cstType: CstType.CONSTANT, definitionFormal: '' }]
|
|
350
|
+
},
|
|
351
|
+
session.sessionId
|
|
352
|
+
);
|
|
370
353
|
|
|
371
|
-
const model = await tool.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
354
|
+
const model = await tool.setModelValues(
|
|
355
|
+
{
|
|
356
|
+
set: [
|
|
357
|
+
{ target: 1, value: { 0: 'a', 1: 'b' } },
|
|
358
|
+
{ target: 2, value: { 0: 'c' } }
|
|
359
|
+
]
|
|
360
|
+
},
|
|
361
|
+
session.sessionId
|
|
362
|
+
);
|
|
377
363
|
expect(model.items).toHaveLength(2);
|
|
378
364
|
});
|
|
379
365
|
|
|
@@ -381,18 +367,185 @@ describe('RSToolAgent modeling and evaluation', () => {
|
|
|
381
367
|
const tool = new RSToolAgent();
|
|
382
368
|
const session = tool.createSession();
|
|
383
369
|
buildSampleForm(tool, session.sessionId);
|
|
384
|
-
await tool.
|
|
385
|
-
target: 1,
|
|
386
|
-
value: { 0: 'zero' }
|
|
387
|
-
});
|
|
370
|
+
await tool.setModelValues({ set: [{ target: 1, value: { 0: 'zero' } }] }, session.sessionId);
|
|
388
371
|
|
|
389
372
|
const exported = tool.exportSession(session.sessionId);
|
|
390
373
|
expect(exported).toContain('"model"');
|
|
391
374
|
|
|
392
375
|
const newTool = new RSToolAgent();
|
|
393
|
-
const imported = newTool.
|
|
376
|
+
const imported = newTool.importData(exported, 'session');
|
|
394
377
|
const model = newTool.getModelState(imported.sessionId);
|
|
395
378
|
expect(model.items).toHaveLength(1);
|
|
396
379
|
expect(model.items[0]?.value).toEqual({ 0: 'zero' });
|
|
397
380
|
});
|
|
398
381
|
});
|
|
382
|
+
|
|
383
|
+
describe('RSToolAgent agent ergonomics', () => {
|
|
384
|
+
it('tracks current session and allows omitting sessionId', () => {
|
|
385
|
+
const tool = new RSToolAgent();
|
|
386
|
+
const session = tool.createSession({ title: 'Active' });
|
|
387
|
+
expect(tool.getCurrentSession()?.sessionId).toBe(session.sessionId);
|
|
388
|
+
expect(fullState(tool).title).toBe('Active');
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
it('auto-creates a session when sessionId is omitted', () => {
|
|
392
|
+
const tool = new RSToolAgent();
|
|
393
|
+
const result = tool.applySchemaPatch({
|
|
394
|
+
items: [{ alias: 'X1' }]
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
expect(result.success).toBe(true);
|
|
398
|
+
expect(tool.getCurrentSession()).not.toBeNull();
|
|
399
|
+
expect(fullState(tool).items).toHaveLength(1);
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
it('applies agent schema patches with inferred ids and cstType', () => {
|
|
403
|
+
const tool = new RSToolAgent();
|
|
404
|
+
|
|
405
|
+
const result = tool.applySchemaPatch({
|
|
406
|
+
initial: { title: 'Agent patch' },
|
|
407
|
+
commitMessage: 'initial schema',
|
|
408
|
+
items: [
|
|
409
|
+
{ alias: 'D1', definitionFormal: 'Pr1(S1)' },
|
|
410
|
+
{ alias: 'X1' },
|
|
411
|
+
{ alias: 'S1', definitionFormal: 'ℬ(X1×X1)' }
|
|
412
|
+
]
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
expect(result.success).toBe(true);
|
|
416
|
+
expect(result.summary.title).toBe('Agent patch');
|
|
417
|
+
expect(result.summary.itemCount).toBe(3);
|
|
418
|
+
expect(result.revision?.message).toBe('initial schema');
|
|
419
|
+
expect(fullState(tool).items.map(item => item.alias)).toEqual(['X1', 'S1', 'D1']);
|
|
420
|
+
expect(fullState(tool).items.map(item => item.cstType)).toEqual([CstType.BASE, CstType.STRUCTURED, CstType.TERM]);
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
it('exports Portal payloads as structured objects', () => {
|
|
424
|
+
const tool = new RSToolAgent();
|
|
425
|
+
tool.applySchemaPatch({
|
|
426
|
+
items: [{ alias: 'D1', definitionFormal: '1+2' }]
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
const schema = tool.exportPortal({ kind: 'schema', format: 'object' });
|
|
430
|
+
expect(schema).toMatchObject({ items: [{ alias: 'D1', cst_type: CstType.TERM }] });
|
|
431
|
+
expect(JSON.parse(tool.exportPortal({ kind: 'schema' }) as string).items[0]).toMatchObject(
|
|
432
|
+
(schema as { items: unknown[] }).items[0] as object
|
|
433
|
+
);
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
it('replaces active diagnostics per constituent on upsert', () => {
|
|
437
|
+
const tool = new RSToolAgent();
|
|
438
|
+
const session = tool.createSession();
|
|
439
|
+
tool.applySchemaPatch(
|
|
440
|
+
{ mode: 'best_effort', items: [{ alias: 'X1', cstType: CstType.BASE, definitionFormal: 'Z' }] },
|
|
441
|
+
session.sessionId
|
|
442
|
+
);
|
|
443
|
+
expect(tool.listDiagnostics(undefined, session.sessionId)).toHaveLength(1);
|
|
444
|
+
|
|
445
|
+
tool.applySchemaPatch({ items: [{ alias: 'X1', cstType: CstType.BASE, definitionFormal: '' }] }, session.sessionId);
|
|
446
|
+
expect(tool.listDiagnostics(undefined, session.sessionId)).toHaveLength(0);
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
it('does not record analyzeExpression diagnostics by default', () => {
|
|
450
|
+
const tool = new RSToolAgent();
|
|
451
|
+
const session = tool.createSession();
|
|
452
|
+
tool.analyzeExpression({ expression: '(', cstType: CstType.TERM }, session.sessionId);
|
|
453
|
+
expect(tool.listDiagnostics(undefined, session.sessionId)).toHaveLength(0);
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
it('records analyzeExpression diagnostics when requested', () => {
|
|
457
|
+
const tool = new RSToolAgent();
|
|
458
|
+
const session = tool.createSession();
|
|
459
|
+
tool.analyzeExpression({ expression: '(', cstType: CstType.TERM, recordDiagnostics: true }, session.sessionId);
|
|
460
|
+
expect(tool.listDiagnostics(undefined, session.sessionId).length).toBeGreaterThan(0);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
it('applySchemaPatch rolls back in atomic mode', () => {
|
|
464
|
+
const tool = new RSToolAgent();
|
|
465
|
+
const session = tool.createSession();
|
|
466
|
+
tool.applySchemaPatch({ items: [{ alias: 'X1' }] }, session.sessionId);
|
|
467
|
+
|
|
468
|
+
const result = tool.applySchemaPatch(
|
|
469
|
+
{
|
|
470
|
+
mode: 'atomic',
|
|
471
|
+
items: [
|
|
472
|
+
{ alias: 'D1', definitionFormal: '1+2' },
|
|
473
|
+
{ alias: 'D2', definitionFormal: 'Pr1(MISSING)' }
|
|
474
|
+
]
|
|
475
|
+
},
|
|
476
|
+
session.sessionId
|
|
477
|
+
);
|
|
478
|
+
|
|
479
|
+
expect(result.success).toBe(false);
|
|
480
|
+
expect(result.applied).toHaveLength(0);
|
|
481
|
+
expect(fullState(tool, session.sessionId).items).toHaveLength(1);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
it('applySchemaPatch applies valid drafts in best_effort mode', () => {
|
|
485
|
+
const tool = new RSToolAgent();
|
|
486
|
+
const session = tool.createSession();
|
|
487
|
+
tool.applySchemaPatch(
|
|
488
|
+
{
|
|
489
|
+
items: [{ alias: 'X1' }, { alias: 'S1', definitionFormal: 'ℬ(X1×X1)' }]
|
|
490
|
+
},
|
|
491
|
+
session.sessionId
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
const result = tool.applySchemaPatch(
|
|
495
|
+
{
|
|
496
|
+
mode: 'best_effort',
|
|
497
|
+
items: [
|
|
498
|
+
{ alias: 'D1', definitionFormal: 'Pr1(S1)' },
|
|
499
|
+
{ alias: 'D2', definitionFormal: 'Pr1(MISSING)' }
|
|
500
|
+
]
|
|
501
|
+
},
|
|
502
|
+
session.sessionId
|
|
503
|
+
);
|
|
504
|
+
|
|
505
|
+
expect(result.applied).toHaveLength(1);
|
|
506
|
+
expect(result.failed).toHaveLength(1);
|
|
507
|
+
expect(fullState(tool, session.sessionId).items.map(item => item.alias)).toContain('D1');
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
it('imports portal details JSON', () => {
|
|
511
|
+
const tool = new RSToolAgent();
|
|
512
|
+
const payload = {
|
|
513
|
+
title: 'Kinship',
|
|
514
|
+
alias: 'KIN',
|
|
515
|
+
description: 'Example',
|
|
516
|
+
items: [
|
|
517
|
+
{ id: 1, alias: 'X1', cst_type: CstType.BASE, definition_formal: '' },
|
|
518
|
+
{ id: 2, alias: 'D1', cst_type: CstType.TERM, definition_formal: '1+2' }
|
|
519
|
+
]
|
|
520
|
+
};
|
|
521
|
+
const session = tool.importData(payload, 'portal-details');
|
|
522
|
+
const state = fullState(tool, session.sessionId);
|
|
523
|
+
expect(state.title).toBe('Kinship');
|
|
524
|
+
expect(state.items).toHaveLength(2);
|
|
525
|
+
expect(state.items.map(item => item.alias).sort()).toEqual(['D1', 'X1']);
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
it('auto-detects portal details import kind', () => {
|
|
529
|
+
const tool = new RSToolAgent();
|
|
530
|
+
const session = tool.importData({
|
|
531
|
+
title: 'Auto',
|
|
532
|
+
items: [{ id: 1, alias: 'X1', cst_type: CstType.BASE, definition_formal: '' }]
|
|
533
|
+
});
|
|
534
|
+
expect(fullState(tool, session.sessionId).title).toBe('Auto');
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
it('persists sessions across agent restarts', () => {
|
|
538
|
+
const dir = mkdtempSync(join(tmpdir(), 'rstool-test-sessions-'));
|
|
539
|
+
try {
|
|
540
|
+
const tool = new RSToolAgent({ persistenceDir: dir });
|
|
541
|
+
const session = tool.createSession({ title: 'Persisted' });
|
|
542
|
+
tool.applySchemaPatch({ items: [{ alias: 'X1' }] }, session.sessionId);
|
|
543
|
+
|
|
544
|
+
const restored = new RSToolAgent({ persistenceDir: dir });
|
|
545
|
+
expect(restored.getCurrentSession()?.sessionId).toBe(session.sessionId);
|
|
546
|
+
expect(fullState(restored, session.sessionId).items).toHaveLength(1);
|
|
547
|
+
} finally {
|
|
548
|
+
rmSync(dir, { recursive: true, force: true });
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
});
|