@rsconcept/rstool 0.3.0 → 0.5.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 (42) hide show
  1. package/README.md +4 -2
  2. package/dist/index-uhkmwruf.d.ts +46 -0
  3. package/dist/index.d.ts +5 -4
  4. package/dist/index.js +2 -2
  5. package/dist/mappers/model-adapter.d.ts +1 -1
  6. package/dist/mappers/schema-adapter.d.ts +1 -1
  7. package/dist/models/index.d.ts +5 -4
  8. package/dist/models/index.js +2 -2
  9. package/dist/models/rstool-agent.d.ts +1 -1
  10. package/dist/models/rstool-agent.js +1 -92
  11. package/dist/models/session.d.ts +1 -1
  12. package/dist/models/tool-contract.d.ts +1 -1
  13. package/dist/models/tool-contract.js +1 -1
  14. package/dist/models/tool-contract.js.map +1 -1
  15. package/dist/rstool-agent-BZi5jO1y.js +158 -0
  16. package/dist/rstool-agent-BZi5jO1y.js.map +1 -0
  17. package/dist/{rstool-agent-DkeH5Qml.d.ts → rstool-agent-pRaPnZay.d.ts} +6 -4
  18. package/dist/session/session-store.d.ts +2 -1
  19. package/dist/session/session-store.js +3 -0
  20. package/dist/session/session-store.js.map +1 -1
  21. package/dist/{session-BHGCCLfQ.d.ts → session-BPgsE80c.d.ts} +12 -1
  22. package/dist/{tool-contract-CsGqg_0P.d.ts → tool-contract-n1ghUOrK.d.ts} +5 -3
  23. package/dist/wrapper/stdio-wrapper.js +13 -1
  24. package/dist/wrapper/stdio-wrapper.js.map +1 -1
  25. package/docs/CONCEPTUAL-SCHEMA.md +66 -28
  26. package/docs/CONSTITUENTA.md +11 -9
  27. package/docs/PORTAL-API.md +1 -0
  28. package/docs/TYPIFICATION.md +3 -9
  29. package/package.json +1 -1
  30. package/skills/rstool-helper/EXAMPLES.md +59 -0
  31. package/skills/rstool-helper/GUIDE.md +5 -30
  32. package/skills/rstool-helper/REFERENCE.md +42 -11
  33. package/src/index.ts +6 -0
  34. package/src/models/index.ts +8 -0
  35. package/src/models/portal-json.ts +45 -0
  36. package/src/models/rstool-agent.test.ts +98 -0
  37. package/src/models/rstool-agent.ts +72 -4
  38. package/src/models/session.ts +11 -0
  39. package/src/models/tool-contract.ts +3 -1
  40. package/src/session/session-store.ts +3 -0
  41. package/src/wrapper/stdio-wrapper.ts +14 -0
  42. package/dist/models/rstool-agent.js.map +0 -1
@@ -126,6 +126,104 @@ describe('RSToolAgent', () => {
126
126
  });
127
127
  });
128
128
 
129
+ it('stores and exports session metadata', () => {
130
+ const tool = new RSToolAgent();
131
+ const session = tool.createSession({
132
+ alias: 'KIN',
133
+ title: 'Kinship',
134
+ comment: 'Example schema'
135
+ });
136
+
137
+ expect(tool.getFormState(session.sessionId)).toMatchObject({
138
+ alias: 'KIN',
139
+ title: 'Kinship',
140
+ comment: 'Example schema'
141
+ });
142
+
143
+ const exported = JSON.parse(tool.exportPortalSchema(session.sessionId)) as {
144
+ title: string;
145
+ alias: string;
146
+ description: string;
147
+ };
148
+ expect(exported).toMatchObject({
149
+ title: 'Kinship',
150
+ alias: 'KIN',
151
+ description: 'Example schema'
152
+ });
153
+ });
154
+
155
+ it('exports schema data for Portal JSON import', () => {
156
+ const tool = new RSToolAgent();
157
+ const session = tool.createSession();
158
+ tool.addOrUpdateConstituenta(session.sessionId, {
159
+ draft: {
160
+ id: 15,
161
+ alias: 'D2',
162
+ cstType: CstType.TERM,
163
+ definitionFormal: '1',
164
+ term: 'natural number',
165
+ definitionText: 'A positive integer',
166
+ convention: 'Standard arithmetic'
167
+ }
168
+ });
169
+
170
+ const exported = JSON.parse(tool.exportPortalSchema(session.sessionId)) as {
171
+ contract_version: string;
172
+ title: string;
173
+ alias: string;
174
+ description: string;
175
+ items: Array<Record<string, unknown>>;
176
+ attribution: unknown[];
177
+ };
178
+
179
+ expect(exported.contract_version).toBe('1.0.0');
180
+ expect(exported.title).toBe('Conceptual schema');
181
+ expect(exported.alias).toBe('SCHEMA');
182
+ expect(exported.description).toBe('');
183
+
184
+ expect(exported.items[0]).toMatchObject({
185
+ id: 15,
186
+ alias: 'D2',
187
+ cst_type: CstType.TERM,
188
+ definition_formal: '1',
189
+ definition_raw: 'A positive integer',
190
+ term_raw: 'natural number',
191
+ convention: 'Standard arithmetic',
192
+ crucial: false
193
+ });
194
+ expect(exported.attribution).toEqual([]);
195
+ });
196
+
197
+ it('exports model data for Portal JSON import', async () => {
198
+ const tool = new RSToolAgent();
199
+ const session = tool.createSession();
200
+ buildSampleForm(tool, session.sessionId);
201
+ await tool.setConstituentaValue(session.sessionId, {
202
+ target: 1,
203
+ value: { 1: 'Alice' }
204
+ });
205
+
206
+ const exported = JSON.parse(tool.exportPortalModel(session.sessionId)) as {
207
+ contract_version: string;
208
+ title: string;
209
+ alias: string;
210
+ description: string;
211
+ items: Array<Record<string, unknown>>;
212
+ };
213
+
214
+ expect(exported.contract_version).toBe('1.0.0');
215
+ expect(exported.title).toBe('Conceptual model');
216
+ expect(exported.alias).toBe('MODEL');
217
+
218
+ expect(exported.items).toEqual([
219
+ {
220
+ id: 1,
221
+ type: 'basic',
222
+ value: { 1: 'Alice' }
223
+ }
224
+ ]);
225
+ });
226
+
129
227
  it('defaults missing text fields to empty strings', () => {
130
228
  const tool = new RSToolAgent();
131
229
  const session = tool.createSession();
@@ -19,9 +19,41 @@ import {
19
19
  type SetConstituentaValueInput,
20
20
  type SetConstituentaValuesInput
21
21
  } from './model-value';
22
+ import {
23
+ PORTAL_JSON_CONTRACT_VERSION,
24
+ type PortalModelImportData,
25
+ type PortalSchemaImportData
26
+ } from './portal-json';
22
27
  import { type SessionHandle, type SessionRevision, type SessionState } from './session';
23
28
  import { CONTRACT_VERSION, type RSToolAgentContract } from './tool-contract';
24
29
 
30
+ function normalizeImportedState(state: SessionState): SessionState {
31
+ return {
32
+ ...state,
33
+ alias: state.alias ?? '',
34
+ title: state.title ?? '',
35
+ comment: state.comment ?? '',
36
+ model: state.model ?? { items: [] }
37
+ };
38
+ }
39
+
40
+ function portalImportMetadata(
41
+ session: SessionState,
42
+ kind: 'schema' | 'model'
43
+ ): Pick<PortalSchemaImportData, 'title' | 'alias' | 'description'> {
44
+ const defaults =
45
+ kind === 'schema'
46
+ ? { title: 'Conceptual schema', alias: 'SCHEMA' }
47
+ : { title: 'Conceptual model', alias: 'MODEL' };
48
+ const title = session.title.trim();
49
+ const alias = session.alias.trim();
50
+ return {
51
+ title: title.length > 0 ? title : defaults.title,
52
+ alias: alias.length > 0 ? alias : defaults.alias,
53
+ description: session.comment.trim()
54
+ };
55
+ }
56
+
25
57
  export class RSToolAgent implements RSToolAgentContract {
26
58
  public readonly contractVersion = CONTRACT_VERSION;
27
59
  private readonly sessions = new SessionStore();
@@ -87,14 +119,50 @@ export class RSToolAgent implements RSToolAgentContract {
87
119
  );
88
120
  }
89
121
 
122
+ public exportPortalSchema(sessionId: string): string {
123
+ const envelope = this.sessions.get(sessionId);
124
+ const payload: PortalSchemaImportData = {
125
+ contract_version: PORTAL_JSON_CONTRACT_VERSION,
126
+ ...portalImportMetadata(envelope.state, 'schema'),
127
+ items: envelope.state.items.map(item => ({
128
+ id: item.id,
129
+ alias: item.alias,
130
+ convention: item.convention,
131
+ crucial: false,
132
+ cst_type: item.cstType,
133
+ definition_formal: item.definitionFormal,
134
+ typification_manual: '',
135
+ value_is_property: false,
136
+ definition_raw: item.definitionText,
137
+ definition_resolved: item.definitionText,
138
+ term_raw: item.term,
139
+ term_resolved: item.term,
140
+ term_forms: []
141
+ })),
142
+ attribution: []
143
+ };
144
+ return JSON.stringify(payload, null, 2);
145
+ }
146
+
147
+ public exportPortalModel(sessionId: string): string {
148
+ const envelope = this.sessions.get(sessionId);
149
+ const payload: PortalModelImportData = {
150
+ contract_version: PORTAL_JSON_CONTRACT_VERSION,
151
+ ...portalImportMetadata(envelope.state, 'model'),
152
+ items: envelope.state.model.items.map(item => ({
153
+ id: item.id,
154
+ type: item.type,
155
+ value: item.value
156
+ }))
157
+ };
158
+ return JSON.stringify(payload, null, 2);
159
+ }
160
+
90
161
  public importSession(payload: string): SessionHandle {
91
162
  const parsed = JSON.parse(payload) as {
92
163
  state: SessionState;
93
164
  };
94
- if (!parsed.state.model) {
95
- parsed.state.model = { items: [] };
96
- }
97
- return this.sessions.create(parsed.state, this.contractVersion);
165
+ return this.sessions.create(normalizeImportedState(parsed.state), this.contractVersion);
98
166
  }
99
167
 
100
168
  public async setConstituentaValue(
@@ -14,9 +14,20 @@ export interface SessionRevision {
14
14
 
15
15
  export interface SessionState {
16
16
  sessionId: string;
17
+ /** Library item alias for the conceptual schema or model. */
18
+ alias: string;
19
+ /** Human-readable title. */
20
+ title: string;
21
+ /** Developer comment (Portal JSON `description` on export). */
22
+ comment: string;
23
+ /** Date of creation. */
17
24
  createdAt: string;
25
+ /** Date of last update. */
18
26
  updatedAt: string;
27
+ /** List of revisions. */
19
28
  revisions: SessionRevision[];
29
+ /** List of constituents in the session. */
20
30
  items: ConstituentaState[];
31
+ /** Model state. */
21
32
  model: SessionModelState;
22
33
  }
@@ -25,7 +25,7 @@ import {
25
25
  type SessionState
26
26
  } from './session';
27
27
 
28
- export const CONTRACT_VERSION = '1.2.0';
28
+ export const CONTRACT_VERSION = '1.4.0';
29
29
 
30
30
  export interface RSToolAgentContract {
31
31
  readonly contractVersion: string;
@@ -36,6 +36,8 @@ export interface RSToolAgentContract {
36
36
  listDiagnostics(sessionId: string, filters?: ListDiagnosticsFilters): DiagnosticRecord[];
37
37
  commitStep(sessionId: string, message?: string): SessionRevision;
38
38
  exportSession(sessionId: string): string;
39
+ exportPortalSchema(sessionId: string): string;
40
+ exportPortalModel(sessionId: string): string;
39
41
  importSession(payload: string): SessionHandle;
40
42
  setConstituentaValue(sessionId: string, input: SetConstituentaValueInput): Promise<SessionModelState>;
41
43
  setConstituentaValues(sessionId: string, input: SetConstituentaValuesInput): Promise<SessionModelState>;
@@ -21,6 +21,9 @@ export class SessionStore {
21
21
  const sessionId = initial?.sessionId ?? randomUUID();
22
22
  const state: SessionState = {
23
23
  sessionId,
24
+ alias: initial?.alias ?? '',
25
+ title: initial?.title ?? '',
26
+ comment: initial?.comment ?? '',
24
27
  createdAt: initial?.createdAt ?? now,
25
28
  updatedAt: now,
26
29
  revisions: initial?.revisions ?? [],
@@ -30,6 +30,8 @@ const METHODS = [
30
30
  'listDiagnostics',
31
31
  'commitStep',
32
32
  'exportSession',
33
+ 'exportPortalSchema',
34
+ 'exportPortalModel',
33
35
  'importSession',
34
36
  'setConstituentaValue',
35
37
  'setConstituentaValues',
@@ -116,6 +118,18 @@ async function handleRequest(request: StdioRequest): Promise<StdioResponse> {
116
118
  ok: true,
117
119
  result: tool.exportSession(requiredString(params, 'sessionId'))
118
120
  };
121
+ case 'exportPortalSchema':
122
+ return {
123
+ id: request.id,
124
+ ok: true,
125
+ result: tool.exportPortalSchema(requiredString(params, 'sessionId'))
126
+ };
127
+ case 'exportPortalModel':
128
+ return {
129
+ id: request.id,
130
+ ok: true,
131
+ result: tool.exportPortalModel(requiredString(params, 'sessionId'))
132
+ };
119
133
  case 'importSession':
120
134
  return {
121
135
  id: request.id,
@@ -1 +0,0 @@
1
- {"version":3,"file":"rstool-agent.js","names":[],"sources":["../../src/models/rstool-agent.ts"],"sourcesContent":["import { ModelAdapter } from '../mappers/model-adapter';\nimport { SchemaAdapter } from '../mappers/schema-adapter';\nimport { SessionStore } from '../session/session-store';\nimport { type AnalysisResult, type AnalyzeExpressionInput } from './analysis';\nimport {\n type AddOrUpdateConstituentaInput,\n type AddOrUpdateConstituentaResult\n} from './constituenta';\nimport { type ListDiagnosticsFilters } from './diagnostic';\nimport {\n type EvaluateConstituentaInput,\n type EvaluateExpressionInput,\n type EvaluationResult\n} from './evaluation';\nimport {\n type ClearConstituentaValuesInput,\n type RecalculateModelResult,\n type SessionModelState,\n type SetConstituentaValueInput,\n type SetConstituentaValuesInput\n} from './model-value';\nimport { type SessionHandle, type SessionRevision, type SessionState } from './session';\nimport { CONTRACT_VERSION, type RSToolAgentContract } from './tool-contract';\n\nexport class RSToolAgent implements RSToolAgentContract {\n public readonly contractVersion = CONTRACT_VERSION;\n private readonly sessions = new SessionStore();\n private readonly adapter = new SchemaAdapter();\n private readonly evaluation = new ModelAdapter();\n\n public createSession(initial?: Partial<SessionState>): SessionHandle {\n return this.sessions.create(initial, this.contractVersion);\n }\n\n public addOrUpdateConstituenta(\n sessionId: string,\n input: AddOrUpdateConstituentaInput\n ): AddOrUpdateConstituentaResult {\n const envelope = this.sessions.get(sessionId);\n const { result, diagnostics } = this.adapter.analyzeAgainstSession(envelope.state, input.draft);\n const state = this.adapter.mergeStateWithDraft(envelope.state, input.draft, result);\n this.sessions.appendDiagnostics(sessionId, diagnostics);\n return {\n state,\n diagnostics\n };\n }\n\n public analyzeExpression(sessionId: string, input: AnalyzeExpressionInput): AnalysisResult {\n const envelope = this.sessions.get(sessionId);\n const { result, diagnostics } = this.adapter.analyzeAgainstSession(envelope.state, {\n id: -1,\n alias: '_analysis',\n cstType: input.cstType,\n definitionFormal: input.expression\n });\n this.sessions.appendDiagnostics(\n sessionId,\n diagnostics.map(item => ({ ...item, constituentId: undefined }))\n );\n return result;\n }\n\n public getFormState(sessionId: string): SessionState {\n const envelope = this.sessions.get(sessionId);\n return structuredClone(envelope.state);\n }\n\n public listDiagnostics(sessionId: string, filters?: ListDiagnosticsFilters) {\n return this.sessions.listDiagnostics(sessionId, filters);\n }\n\n public commitStep(sessionId: string, message?: string): SessionRevision {\n return this.sessions.addRevision(sessionId, message);\n }\n\n public exportSession(sessionId: string): string {\n const envelope = this.sessions.get(sessionId);\n return JSON.stringify(\n {\n contractVersion: this.contractVersion,\n state: envelope.state,\n diagnostics: envelope.diagnostics\n },\n null,\n 2\n );\n }\n\n public importSession(payload: string): SessionHandle {\n const parsed = JSON.parse(payload) as {\n state: SessionState;\n };\n if (!parsed.state.model) {\n parsed.state.model = { items: [] };\n }\n return this.sessions.create(parsed.state, this.contractVersion);\n }\n\n public async setConstituentaValue(\n sessionId: string,\n input: SetConstituentaValueInput\n ): Promise<SessionModelState> {\n const envelope = this.sessions.get(sessionId);\n return this.evaluation.setConstituentaValue(envelope.state, input);\n }\n\n public async setConstituentaValues(\n sessionId: string,\n input: SetConstituentaValuesInput\n ): Promise<SessionModelState> {\n const envelope = this.sessions.get(sessionId);\n return this.evaluation.setConstituentaValues(envelope.state, input);\n }\n\n public async clearConstituentaValues(\n sessionId: string,\n input: ClearConstituentaValuesInput\n ): Promise<SessionModelState> {\n const envelope = this.sessions.get(sessionId);\n return this.evaluation.clearConstituentaValues(envelope.state, input.items);\n }\n\n public getModelState(sessionId: string): SessionModelState {\n const envelope = this.sessions.get(sessionId);\n return structuredClone(envelope.state.model);\n }\n\n public evaluateExpression(sessionId: string, input: EvaluateExpressionInput): EvaluationResult {\n const envelope = this.sessions.get(sessionId);\n return this.evaluation.evaluateExpression(envelope.state, input.expression, input.cstType);\n }\n\n public evaluateConstituenta(sessionId: string, input: EvaluateConstituentaInput): EvaluationResult {\n const envelope = this.sessions.get(sessionId);\n return this.evaluation.evaluateConstituenta(envelope.state, input.constituentId);\n }\n\n public recalculateModel(sessionId: string): RecalculateModelResult {\n const envelope = this.sessions.get(sessionId);\n return this.evaluation.recalculateModel(envelope.state);\n }\n}\n"],"mappings":";;;;;AAwBA,IAAa,cAAb,MAAwD;CACtD,kBAAkC;CAClC,WAA4B,IAAI,aAAa;CAC7C,UAA2B,IAAI,cAAc;CAC7C,aAA8B,IAAI,aAAa;CAE/C,cAAqB,SAAgD;EACnE,OAAO,KAAK,SAAS,OAAO,SAAS,KAAK,eAAe;CAC3D;CAEA,wBACE,WACA,OAC+B;EAC/B,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,MAAM,EAAE,QAAQ,gBAAgB,KAAK,QAAQ,sBAAsB,SAAS,OAAO,MAAM,KAAK;EAC9F,MAAM,QAAQ,KAAK,QAAQ,oBAAoB,SAAS,OAAO,MAAM,OAAO,MAAM;EAClF,KAAK,SAAS,kBAAkB,WAAW,WAAW;EACtD,OAAO;GACL;GACA;EACF;CACF;CAEA,kBAAyB,WAAmB,OAA+C;EACzF,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,MAAM,EAAE,QAAQ,gBAAgB,KAAK,QAAQ,sBAAsB,SAAS,OAAO;GACjF,IAAI;GACJ,OAAO;GACP,SAAS,MAAM;GACf,kBAAkB,MAAM;EAC1B,CAAC;EACD,KAAK,SAAS,kBACZ,WACA,YAAY,KAAI,UAAS;GAAE,GAAG;GAAM,eAAe;EAAU,EAAE,CACjE;EACA,OAAO;CACT;CAEA,aAAoB,WAAiC;EACnD,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,OAAO,gBAAgB,SAAS,KAAK;CACvC;CAEA,gBAAuB,WAAmB,SAAkC;EAC1E,OAAO,KAAK,SAAS,gBAAgB,WAAW,OAAO;CACzD;CAEA,WAAkB,WAAmB,SAAmC;EACtE,OAAO,KAAK,SAAS,YAAY,WAAW,OAAO;CACrD;CAEA,cAAqB,WAA2B;EAC9C,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,OAAO,KAAK,UACV;GACE,iBAAiB,KAAK;GACtB,OAAO,SAAS;GAChB,aAAa,SAAS;EACxB,GACA,MACA,CACF;CACF;CAEA,cAAqB,SAAgC;EACnD,MAAM,SAAS,KAAK,MAAM,OAAO;EAGjC,IAAI,CAAC,OAAO,MAAM,OAChB,OAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,EAAE;EAEnC,OAAO,KAAK,SAAS,OAAO,OAAO,OAAO,KAAK,eAAe;CAChE;CAEA,MAAa,qBACX,WACA,OAC4B;EAC5B,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,OAAO,KAAK,WAAW,qBAAqB,SAAS,OAAO,KAAK;CACnE;CAEA,MAAa,sBACX,WACA,OAC4B;EAC5B,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,OAAO,KAAK,WAAW,sBAAsB,SAAS,OAAO,KAAK;CACpE;CAEA,MAAa,wBACX,WACA,OAC4B;EAC5B,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,OAAO,KAAK,WAAW,wBAAwB,SAAS,OAAO,MAAM,KAAK;CAC5E;CAEA,cAAqB,WAAsC;EACzD,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,OAAO,gBAAgB,SAAS,MAAM,KAAK;CAC7C;CAEA,mBAA0B,WAAmB,OAAkD;EAC7F,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,OAAO,KAAK,WAAW,mBAAmB,SAAS,OAAO,MAAM,YAAY,MAAM,OAAO;CAC3F;CAEA,qBAA4B,WAAmB,OAAoD;EACjG,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,OAAO,KAAK,WAAW,qBAAqB,SAAS,OAAO,MAAM,aAAa;CACjF;CAEA,iBAAwB,WAA2C;EACjE,MAAM,WAAW,KAAK,SAAS,IAAI,SAAS;EAC5C,OAAO,KAAK,WAAW,iBAAiB,SAAS,KAAK;CACxD;AACF"}