@rsconcept/rstool 1.0.0 → 1.0.1

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 +22 -4
  2. package/dist/{agent-workflow-D-PSIb-m.d.ts → agent-workflow-Gk0Vfnv1.d.ts} +3 -9
  3. package/dist/index.d.ts +3 -3
  4. package/dist/index.js +1 -2
  5. package/dist/models/agent-workflow.d.ts +2 -2
  6. package/dist/models/index.d.ts +3 -3
  7. package/dist/models/index.js +1 -1
  8. package/dist/models/rstool-agent.d.ts +1 -1
  9. package/dist/models/rstool-agent.js +1 -1
  10. package/dist/models/tool-contract.d.ts +1 -1
  11. package/dist/{rstool-agent-kijHA9ML.js → models-Bw6Uum8i.js} +243 -34
  12. package/dist/models-Bw6Uum8i.js.map +1 -0
  13. package/dist/{rstool-agent-_8bplZnb.d.ts → rstool-agent-D2cQze_b.d.ts} +3 -3
  14. package/dist/session/session-store.js +1 -1
  15. package/dist/{tool-contract-5_Q44DGE.d.ts → tool-contract-0uRGhEfW.d.ts} +2 -2
  16. package/dist/wrapper/stdio-wrapper.js +16 -14
  17. package/dist/wrapper/stdio-wrapper.js.map +1 -1
  18. package/examples/build-chocolate-nim-rsform.ts +2 -56
  19. package/examples/kinship/build-rsmodel.ts +5 -3
  20. package/examples/sample/build-rsform.ts +7 -9
  21. package/examples/sample/rsform-session.json +31 -31
  22. package/package.json +3 -1
  23. package/src/mappers/portal-adapter.ts +14 -8
  24. package/src/models/agent-workflow.ts +1 -13
  25. package/src/models/import-detect.test.ts +66 -0
  26. package/src/models/import-detect.ts +6 -3
  27. package/src/models/portal-json.test.ts +38 -0
  28. package/src/models/portal-json.ts +11 -2
  29. package/src/models/rstool-agent.test.ts +402 -3
  30. package/src/models/rstool-agent.ts +60 -17
  31. package/src/session/batch-apply.test.ts +103 -8
  32. package/src/session/batch-apply.ts +35 -0
  33. package/src/session/persistence.test.ts +63 -0
  34. package/src/session/persistence.ts +14 -1
  35. package/src/session/session-store.ts +10 -3
  36. package/src/wrapper/client.test.ts +58 -0
  37. package/src/wrapper/stdio-handler.test.ts +101 -0
  38. package/src/wrapper/stdio-handler.ts +195 -0
  39. package/src/wrapper/stdio-wrapper.ts +2 -195
  40. package/dist/rstool-agent-kijHA9ML.js.map +0 -1
  41. package/dist/session-store-C3jyOSqI.js +0 -142
  42. package/dist/session-store-C3jyOSqI.js.map +0 -1
@@ -2,9 +2,9 @@ import { n as AnalyzeExpressionInput, t as AnalysisResult } from "./analysis-LLn
2
2
  import { n as ListDiagnosticsFilters, t as DiagnosticRecord } from "./diagnostic-D9yl_mEL.js";
3
3
  import { i as SessionModelState, r as RecalculateModelResult, s as SetModelValuesInput } from "./model-value-BbonPzMz.js";
4
4
  import { n as SessionRevision, r as SessionState, t as SessionHandle } from "./session-ChexW8i7.js";
5
- import { a as SessionStateDetail, n as ApplySchemaPatchInput, o as SessionStateResult, r as ApplySchemaPatchResult } from "./agent-workflow-D-PSIb-m.js";
5
+ import { a as SessionStateResult, i as SessionStateDetail, n as ApplySchemaPatchInput, r as ApplySchemaPatchResult } from "./agent-workflow-Gk0Vfnv1.js";
6
6
  import { i as EvaluationResult, r as EvaluateInput } from "./evaluation-Cns8BFm4.js";
7
- import { a as ExportPortalInput, n as RSToolAgentContract, o as ExportPortalResult, r as RSToolAgentOptions, s as ImportDataKind } from "./tool-contract-5_Q44DGE.js";
7
+ import { a as ExportPortalInput, n as RSToolAgentContract, o as ExportPortalResult, r as RSToolAgentOptions, s as ImportDataKind } from "./tool-contract-0uRGhEfW.js";
8
8
 
9
9
  //#region src/models/rstool-agent.d.ts
10
10
  /**
@@ -68,4 +68,4 @@ declare class RSToolAgent implements RSToolAgentContract {
68
68
  }
69
69
  //#endregion
70
70
  export { RSToolAgent as t };
71
- //# sourceMappingURL=rstool-agent-_8bplZnb.d.ts.map
71
+ //# sourceMappingURL=rstool-agent-D2cQze_b.d.ts.map
@@ -1,2 +1,2 @@
1
- import { t as SessionStore } from "../session-store-C3jyOSqI.js";
1
+ import { n as SessionStore } from "../models-Bw6Uum8i.js";
2
2
  export { SessionStore };
@@ -4,7 +4,7 @@ import { n as ListDiagnosticsFilters, t as DiagnosticRecord } from "./diagnostic
4
4
  import { o as ConstituentaDraft } from "./constituenta-DnGR6bnM.js";
5
5
  import { i as SessionModelState, r as RecalculateModelResult, s as SetModelValuesInput } from "./model-value-BbonPzMz.js";
6
6
  import { n as SessionRevision, r as SessionState, t as SessionHandle } from "./session-ChexW8i7.js";
7
- import { a as SessionStateDetail, n as ApplySchemaPatchInput, o as SessionStateResult, r as ApplySchemaPatchResult } from "./agent-workflow-D-PSIb-m.js";
7
+ import { a as SessionStateResult, i as SessionStateDetail, n as ApplySchemaPatchInput, r as ApplySchemaPatchResult } from "./agent-workflow-Gk0Vfnv1.js";
8
8
  import { i as EvaluationResult, r as EvaluateInput } from "./evaluation-Cns8BFm4.js";
9
9
 
10
10
  //#region src/models/portal-json.d.ts
@@ -161,4 +161,4 @@ interface RSToolAgentContract {
161
161
  }
162
162
  //#endregion
163
163
  export { ExportPortalInput as a, PortalExportKind as c, PortalModelImportData as d, PortalRsformDetails as f, portalItemToDraft as g, PortalTermForm as h, ExportFormat as i, PORTAL_JSON_CONTRACT_VERSION as l, PortalSchemaImportData as m, RSToolAgentContract as n, ExportPortalResult as o, PortalSchemaConstituenta as p, RSToolAgentOptions as r, ImportDataKind as s, CONTRACT_VERSION as t, PortalImportMetadata as u };
164
- //# sourceMappingURL=tool-contract-5_Q44DGE.d.ts.map
164
+ //# sourceMappingURL=tool-contract-0uRGhEfW.d.ts.map
@@ -1,10 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { t as RSToolAgent } from "../rstool-agent-kijHA9ML.js";
2
+ import { t as RSToolAgent } from "../models-Bw6Uum8i.js";
3
3
  import readline from "node:readline";
4
- //#region src/wrapper/stdio-wrapper.ts
5
- const persistenceDir = process.env.RSTOOL_PERSISTENCE_DIR;
6
- const tool = new RSToolAgent(persistenceDir ? { persistenceDir } : {});
7
- const METHODS = [
4
+ //#region src/wrapper/stdio-handler.ts
5
+ const STDIO_METHODS = [
8
6
  "ensureSession",
9
7
  "createSession",
10
8
  "getCurrentSession",
@@ -22,12 +20,6 @@ const METHODS = [
22
20
  "evaluate",
23
21
  "recalculateModel"
24
22
  ];
25
- function writeResponse(response) {
26
- if (!process.stdout.writable || process.stdout.destroyed || process.stdout.writableEnded) return;
27
- try {
28
- process.stdout.write(`${JSON.stringify(response)}\n`);
29
- } catch {}
30
- }
31
23
  function asObject(value) {
32
24
  if (!value || typeof value !== "object" || Array.isArray(value)) return {};
33
25
  return value;
@@ -45,7 +37,7 @@ function omitSessionId(input) {
45
37
  const { sessionId: _sessionId, ...rest } = input;
46
38
  return rest;
47
39
  }
48
- async function handleRequest(request) {
40
+ async function handleStdioRequest(tool, request) {
49
41
  try {
50
42
  const params = asObject(request.params);
51
43
  switch (request.method) {
@@ -60,7 +52,7 @@ async function handleRequest(request) {
60
52
  case "methods": return {
61
53
  id: request.id,
62
54
  ok: true,
63
- result: METHODS
55
+ result: STDIO_METHODS
64
56
  };
65
57
  case "ensureSession": return {
66
58
  id: request.id,
@@ -167,6 +159,16 @@ async function handleRequest(request) {
167
159
  };
168
160
  }
169
161
  }
162
+ //#endregion
163
+ //#region src/wrapper/stdio-wrapper.ts
164
+ const persistenceDir = process.env.RSTOOL_PERSISTENCE_DIR;
165
+ const tool = new RSToolAgent(persistenceDir ? { persistenceDir } : {});
166
+ function writeResponse(response) {
167
+ if (!process.stdout.writable || process.stdout.destroyed || process.stdout.writableEnded) return;
168
+ try {
169
+ process.stdout.write(`${JSON.stringify(response)}\n`);
170
+ } catch {}
171
+ }
170
172
  const input = readline.createInterface({
171
173
  input: process.stdin,
172
174
  crlfDelay: Infinity
@@ -185,7 +187,7 @@ input.on("line", (line) => {
185
187
  try {
186
188
  const request = JSON.parse(line);
187
189
  if (!("id" in request) || !("method" in request)) throw new Error("Request must include \"id\" and \"method\"");
188
- handleRequest(request).then(writeResponse);
190
+ handleStdioRequest(tool, request).then(writeResponse);
189
191
  } catch (error) {
190
192
  writeResponse({
191
193
  id: null,
@@ -1 +1 @@
1
- {"version":3,"file":"stdio-wrapper.js","names":[],"sources":["../../src/wrapper/stdio-wrapper.ts"],"sourcesContent":["#!/usr/bin/env node\nimport readline from 'node:readline';\n\nimport { RSToolAgent } from '../models/rstool-agent';\n\ninterface StdioRequest {\n id: string | number;\n method: string;\n params?: unknown;\n}\n\ninterface StdioResponse {\n id: string | number | null;\n ok: boolean;\n result?: unknown;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\nconst persistenceDir = process.env.RSTOOL_PERSISTENCE_DIR;\nconst tool = new RSToolAgent(persistenceDir ? { persistenceDir } : {});\n\nconst METHODS = [\n 'ensureSession',\n 'createSession',\n 'getCurrentSession',\n 'setCurrentSession',\n 'applySchemaPatch',\n 'getSessionState',\n 'listDiagnostics',\n 'analyzeExpression',\n 'commitStep',\n 'exportSession',\n 'exportPortal',\n 'importData',\n 'setModelValues',\n 'getModelState',\n 'evaluate',\n 'recalculateModel'\n] as const;\n\nfunction writeResponse(response: StdioResponse): void {\n if (!process.stdout.writable || process.stdout.destroyed || process.stdout.writableEnded) {\n return;\n }\n try {\n process.stdout.write(`${JSON.stringify(response)}\\n`);\n } catch {\n // The client might have already closed stdout (EPIPE). Safe to ignore.\n }\n}\n\nfunction asObject(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {};\n }\n return value as Record<string, unknown>;\n}\n\nfunction requiredString(input: Record<string, unknown>, key: string): string {\n const value = input[key];\n if (typeof value !== 'string' || value.length === 0) {\n throw new Error(`Missing or invalid \"${key}\"`);\n }\n return value;\n}\n\nfunction optionalSessionId(input: Record<string, unknown>): string | undefined {\n const value = input.sessionId;\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction omitSessionId(input: Record<string, unknown>): Record<string, unknown> {\n const { sessionId: _sessionId, ...rest } = input;\n return rest;\n}\n\nasync function handleRequest(request: StdioRequest): Promise<StdioResponse> {\n try {\n const params = asObject(request.params);\n switch (request.method) {\n case 'ping':\n return { id: request.id, ok: true, result: { pong: true, contractVersion: tool.contractVersion } };\n case 'methods':\n return { id: request.id, ok: true, result: METHODS };\n case 'ensureSession':\n return {\n id: request.id,\n ok: true,\n result: tool.ensureSession(params.initial as never)\n };\n case 'createSession':\n return {\n id: request.id,\n ok: true,\n result: tool.createSession(params.initial as never)\n };\n case 'getCurrentSession':\n return {\n id: request.id,\n ok: true,\n result: tool.getCurrentSession()\n };\n case 'setCurrentSession':\n return {\n id: request.id,\n ok: true,\n result: tool.setCurrentSession(requiredString(params, 'sessionId'))\n };\n case 'applySchemaPatch':\n return {\n id: request.id,\n ok: true,\n result: tool.applySchemaPatch(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'getSessionState':\n return {\n id: request.id,\n ok: true,\n result: tool.getSessionState(\n (params.detail as 'summary' | 'full' | undefined) ?? 'summary',\n optionalSessionId(params)\n )\n };\n case 'listDiagnostics': {\n const constituentId = params.constituentId;\n const filters = typeof constituentId === 'number' ? { constituentId } : (params.filters as never);\n return {\n id: request.id,\n ok: true,\n result: tool.listDiagnostics(filters, optionalSessionId(params))\n };\n }\n case 'analyzeExpression':\n return {\n id: request.id,\n ok: true,\n result: tool.analyzeExpression(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'commitStep':\n return {\n id: request.id,\n ok: true,\n result: tool.commitStep(params.message as string | undefined, optionalSessionId(params))\n };\n case 'exportSession':\n return {\n id: request.id,\n ok: true,\n result: tool.exportSession(optionalSessionId(params))\n };\n case 'exportPortal':\n return {\n id: request.id,\n ok: true,\n result: tool.exportPortal(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'importData':\n return {\n id: request.id,\n ok: true,\n result: tool.importData(params.payload as string | object, params.kind as never)\n };\n case 'setModelValues':\n return {\n id: request.id,\n ok: true,\n result: await tool.setModelValues(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'getModelState':\n return {\n id: request.id,\n ok: true,\n result: tool.getModelState(optionalSessionId(params))\n };\n case 'evaluate':\n return {\n id: request.id,\n ok: true,\n result: tool.evaluate(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'recalculateModel':\n return {\n id: request.id,\n ok: true,\n result: tool.recalculateModel(optionalSessionId(params))\n };\n default:\n return {\n id: request.id ?? null,\n ok: false,\n error: {\n code: 'METHOD_NOT_FOUND',\n message: `Unknown method: ${request.method}`\n }\n };\n }\n } catch (error) {\n return {\n id: request.id ?? null,\n ok: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: error instanceof Error ? error.message : 'Unknown error',\n details: error\n }\n };\n }\n}\n\nconst input = readline.createInterface({\n input: process.stdin,\n crlfDelay: Infinity\n});\n\nwriteResponse({\n id: null,\n ok: true,\n result: {\n ready: true,\n wrapper: 'rstool-stdio',\n contractVersion: tool.contractVersion\n }\n});\n\ninput.on('line', line => {\n if (!line.trim()) {\n return;\n }\n try {\n const request = JSON.parse(line) as StdioRequest;\n if (!('id' in request) || !('method' in request)) {\n throw new Error('Request must include \"id\" and \"method\"');\n }\n void handleRequest(request).then(writeResponse);\n } catch (error) {\n writeResponse({\n id: null,\n ok: false,\n error: {\n code: 'BAD_REQUEST',\n message: error instanceof Error ? error.message : 'Invalid JSON'\n }\n });\n }\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"stdio-wrapper.js","names":[],"sources":["../../src/wrapper/stdio-handler.ts","../../src/wrapper/stdio-wrapper.ts"],"sourcesContent":["import type { RSToolAgent } from '../models/rstool-agent';\n\nexport interface StdioRequest {\n id: string | number;\n method: string;\n params?: unknown;\n}\n\nexport interface StdioResponse {\n id: string | number | null;\n ok: boolean;\n result?: unknown;\n error?: {\n code: string;\n message: string;\n details?: unknown;\n };\n}\n\nexport const STDIO_METHODS = [\n 'ensureSession',\n 'createSession',\n 'getCurrentSession',\n 'setCurrentSession',\n 'applySchemaPatch',\n 'getSessionState',\n 'listDiagnostics',\n 'analyzeExpression',\n 'commitStep',\n 'exportSession',\n 'exportPortal',\n 'importData',\n 'setModelValues',\n 'getModelState',\n 'evaluate',\n 'recalculateModel'\n] as const;\n\nfunction asObject(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return {};\n }\n return value as Record<string, unknown>;\n}\n\nfunction requiredString(input: Record<string, unknown>, key: string): string {\n const value = input[key];\n if (typeof value !== 'string' || value.length === 0) {\n throw new Error(`Missing or invalid \"${key}\"`);\n }\n return value;\n}\n\nfunction optionalSessionId(input: Record<string, unknown>): string | undefined {\n const value = input.sessionId;\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction omitSessionId(input: Record<string, unknown>): Record<string, unknown> {\n const { sessionId: _sessionId, ...rest } = input;\n return rest;\n}\n\nexport async function handleStdioRequest(tool: RSToolAgent, request: StdioRequest): Promise<StdioResponse> {\n try {\n const params = asObject(request.params);\n switch (request.method) {\n case 'ping':\n return { id: request.id, ok: true, result: { pong: true, contractVersion: tool.contractVersion } };\n case 'methods':\n return { id: request.id, ok: true, result: STDIO_METHODS };\n case 'ensureSession':\n return {\n id: request.id,\n ok: true,\n result: tool.ensureSession(params.initial as never)\n };\n case 'createSession':\n return {\n id: request.id,\n ok: true,\n result: tool.createSession(params.initial as never)\n };\n case 'getCurrentSession':\n return {\n id: request.id,\n ok: true,\n result: tool.getCurrentSession()\n };\n case 'setCurrentSession':\n return {\n id: request.id,\n ok: true,\n result: tool.setCurrentSession(requiredString(params, 'sessionId'))\n };\n case 'applySchemaPatch':\n return {\n id: request.id,\n ok: true,\n result: tool.applySchemaPatch(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'getSessionState':\n return {\n id: request.id,\n ok: true,\n result: tool.getSessionState(\n (params.detail as 'summary' | 'full' | undefined) ?? 'summary',\n optionalSessionId(params)\n )\n };\n case 'listDiagnostics': {\n const constituentId = params.constituentId;\n const filters = typeof constituentId === 'number' ? { constituentId } : (params.filters as never);\n return {\n id: request.id,\n ok: true,\n result: tool.listDiagnostics(filters, optionalSessionId(params))\n };\n }\n case 'analyzeExpression':\n return {\n id: request.id,\n ok: true,\n result: tool.analyzeExpression(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'commitStep':\n return {\n id: request.id,\n ok: true,\n result: tool.commitStep(params.message as string | undefined, optionalSessionId(params))\n };\n case 'exportSession':\n return {\n id: request.id,\n ok: true,\n result: tool.exportSession(optionalSessionId(params))\n };\n case 'exportPortal':\n return {\n id: request.id,\n ok: true,\n result: tool.exportPortal(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'importData':\n return {\n id: request.id,\n ok: true,\n result: tool.importData(params.payload as string | object, params.kind as never)\n };\n case 'setModelValues':\n return {\n id: request.id,\n ok: true,\n result: await tool.setModelValues(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'getModelState':\n return {\n id: request.id,\n ok: true,\n result: tool.getModelState(optionalSessionId(params))\n };\n case 'evaluate':\n return {\n id: request.id,\n ok: true,\n result: tool.evaluate(omitSessionId(params) as never, optionalSessionId(params))\n };\n case 'recalculateModel':\n return {\n id: request.id,\n ok: true,\n result: tool.recalculateModel(optionalSessionId(params))\n };\n default:\n return {\n id: request.id ?? null,\n ok: false,\n error: {\n code: 'METHOD_NOT_FOUND',\n message: `Unknown method: ${request.method}`\n }\n };\n }\n } catch (error) {\n return {\n id: request.id ?? null,\n ok: false,\n error: {\n code: 'INTERNAL_ERROR',\n message: error instanceof Error ? error.message : 'Unknown error',\n details: error\n }\n };\n }\n}\n","#!/usr/bin/env node\nimport readline from 'node:readline';\n\nimport { RSToolAgent } from '../models/rstool-agent';\nimport { handleStdioRequest, type StdioRequest, type StdioResponse } from './stdio-handler';\n\nconst persistenceDir = process.env.RSTOOL_PERSISTENCE_DIR;\nconst tool = new RSToolAgent(persistenceDir ? { persistenceDir } : {});\n\nfunction writeResponse(response: StdioResponse): void {\n if (!process.stdout.writable || process.stdout.destroyed || process.stdout.writableEnded) {\n return;\n }\n try {\n process.stdout.write(`${JSON.stringify(response)}\\n`);\n } catch {\n // The client might have already closed stdout (EPIPE). Safe to ignore.\n }\n}\n\nconst input = readline.createInterface({\n input: process.stdin,\n crlfDelay: Infinity\n});\n\nwriteResponse({\n id: null,\n ok: true,\n result: {\n ready: true,\n wrapper: 'rstool-stdio',\n contractVersion: tool.contractVersion\n }\n});\n\ninput.on('line', line => {\n if (!line.trim()) {\n return;\n }\n try {\n const request = JSON.parse(line) as StdioRequest;\n if (!('id' in request) || !('method' in request)) {\n throw new Error('Request must include \"id\" and \"method\"');\n }\n void handleStdioRequest(tool, request).then(writeResponse);\n } catch (error) {\n writeResponse({\n id: null,\n ok: false,\n error: {\n code: 'BAD_REQUEST',\n message: error instanceof Error ? error.message : 'Invalid JSON'\n }\n });\n }\n});\n"],"mappings":"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"}
@@ -3,8 +3,6 @@ import { resolve } from 'node:path';
3
3
 
4
4
  import { CstType, RSToolWrapperClient, type AgentConstituentaPatch } from '../src';
5
5
 
6
- type DraftBatch = { draft: AgentConstituentaPatch };
7
-
8
6
  import { DEFAULT_RSFORM_SESSION_PATH } from './chocolate-nim/constants';
9
7
 
10
8
  /**
@@ -20,248 +18,197 @@ async function run() {
20
18
  await client.waitUntilReady();
21
19
  const session = await client.call<{ sessionId: string; contractVersion: string }>('createSession');
22
20
 
23
- const drafts: DraftBatch[] = [
21
+ const items: AgentConstituentaPatch[] = [
24
22
  {
25
- draft: {
26
23
  id: 1,
27
24
  alias: 'S1',
28
25
  cstType: CstType.STRUCTURED,
29
26
  definitionFormal: 'Z×Z',
30
27
  term: 'шоколадка',
31
28
  convention: 'Первая проекция — ширина, вторая — длина'
32
- }
33
29
  },
34
30
  {
35
- draft: {
36
31
  id: 2,
37
32
  alias: 'D1',
38
33
  cstType: CstType.TERM,
39
34
  definitionFormal: 'pr1(S1)',
40
35
  term: 'ширина шоколадки'
41
- }
42
36
  },
43
37
  {
44
- draft: {
45
38
  id: 3,
46
39
  alias: 'D2',
47
40
  cstType: CstType.TERM,
48
41
  definitionFormal: 'pr2(S1)',
49
42
  term: 'длина шоколадки'
50
- }
51
43
  },
52
44
  {
53
- draft: {
54
45
  id: 4,
55
46
  alias: 'S2',
56
47
  cstType: CstType.STRUCTURED,
57
48
  definitionFormal: 'Z×Z',
58
49
  term: 'отравленная долька',
59
50
  convention: 'Координаты отравленной дольки: первая проекция по ширине, вторая — по длине'
60
- }
61
51
  },
62
52
  {
63
- draft: {
64
53
  id: 5,
65
54
  alias: 'D3',
66
55
  cstType: CstType.TERM,
67
56
  definitionFormal: 'pr1(S2)',
68
57
  term: 'расположение отравленной дольки по ширине'
69
- }
70
58
  },
71
59
  {
72
- draft: {
73
60
  id: 6,
74
61
  alias: 'D4',
75
62
  cstType: CstType.TERM,
76
63
  definitionFormal: 'pr2(S2)',
77
64
  term: 'расположение отравленной дольки по длине'
78
- }
79
65
  },
80
66
  {
81
- draft: {
82
67
  id: 7,
83
68
  alias: 'A1',
84
69
  cstType: CstType.AXIOM,
85
70
  definitionFormal: '(1≤D3)&(D3≤D1)&(1≤D4)&(D4≤D2)',
86
71
  term: 'отравленная долька в шоколадке',
87
72
  definitionText: 'Координаты отравленной дольки лежат в пределах шоколадки'
88
- }
89
73
  },
90
74
  {
91
- draft: {
92
75
  id: 8,
93
76
  alias: 'P1',
94
77
  cstType: CstType.PREDICATE,
95
78
  definitionFormal: '[α∈Z] R{ξ:=α | ξ≥2 | ξ-2}=0',
96
79
  term: 'чётное?',
97
80
  convention: 'Для малых аргументов — прямое вычитание двойки; для больших нужно двоичное представление'
98
- }
99
81
  },
100
82
  {
101
- draft: {
102
83
  id: 9,
103
84
  alias: 'F1',
104
85
  cstType: CstType.FUNCTION,
105
86
  definitionFormal: '[α∈Z, σ∈ℬ(Z×R1)] debool(Pr2(Fi1[{α}](σ)))',
106
87
  term: 'значение элемента последовательности с данным номером',
107
88
  definitionText: 'Значение пары с заданным номером в последовательности пар'
108
- }
109
89
  },
110
90
  {
111
- draft: {
112
91
  id: 10,
113
92
  alias: 'F2',
114
93
  cstType: CstType.FUNCTION,
115
94
  definitionFormal: '[σ∈ℬ(Z)] debool(D{ξ∈σ | ∀α∈σ α≤ξ})',
116
95
  term: 'максимум набора чисел'
117
- }
118
96
  },
119
97
  {
120
- draft: {
121
98
  id: 11,
122
99
  alias: 'F4',
123
100
  cstType: CstType.FUNCTION,
124
101
  definitionFormal: '[σ∈ℬ(Z)] D{ξ∈σ | ∀α∈σ α≤ξ}',
125
102
  term: 'верхние границы набора чисел',
126
103
  definitionText: 'Множество элементов набора, не меньших всех остальных'
127
- }
128
104
  },
129
105
  {
130
- draft: {
131
106
  id: 12,
132
107
  alias: 'F5',
133
108
  cstType: CstType.FUNCTION,
134
109
  definitionFormal: '[α∈Z, β∈Z] debool(I{(α,0) | α<β} ∪ I{(α-β,1) | α≥β})',
135
110
  term: 'деление с остатком на степень двойки',
136
111
  convention: 'Предполагается, что удвоенный делитель больше делимого'
137
- }
138
112
  },
139
113
  {
140
- draft: {
141
114
  id: 13,
142
115
  alias: 'F6',
143
116
  cstType: CstType.FUNCTION,
144
117
  definitionFormal: '[α∈Z, β∈Z] pr1(F5[α, β])',
145
118
  term: 'остаток'
146
- }
147
119
  },
148
120
  {
149
- draft: {
150
121
  id: 14,
151
122
  alias: 'F7',
152
123
  cstType: CstType.FUNCTION,
153
124
  definitionFormal: '[α∈Z, β∈Z] pr2(F5[α, β])',
154
125
  term: 'целая часть'
155
- }
156
126
  },
157
127
  {
158
- draft: {
159
128
  id: 15,
160
129
  alias: 'D5',
161
130
  cstType: CstType.TERM,
162
131
  definitionFormal: '{(0, D3-1), (1, D4-1), (2, D1-D3), (3, D2-D4)}',
163
132
  term: 'шоколадка как кучки Ним',
164
133
  definitionText: 'Четыре кучки камней после разреза по отравленной дольке: слева, сверху, справа и снизу'
165
- }
166
134
  },
167
135
  {
168
- draft: {
169
136
  id: 16,
170
137
  alias: 'D6',
171
138
  cstType: CstType.TERM,
172
139
  definitionFormal: 'card(D5)',
173
140
  term: 'количество кучек'
174
- }
175
141
  },
176
142
  {
177
- draft: {
178
143
  id: 17,
179
144
  alias: 'D7',
180
145
  cstType: CstType.TERM,
181
146
  definitionFormal: 'Pr1(D5)',
182
147
  term: 'номера кучек'
183
- }
184
148
  },
185
149
  {
186
- draft: {
187
150
  id: 18,
188
151
  alias: 'D8',
189
152
  cstType: CstType.TERM,
190
153
  definitionFormal: 'Pr2(D5)',
191
154
  term: 'размеры кучек'
192
- }
193
155
  },
194
156
  {
195
- draft: {
196
157
  id: 19,
197
158
  alias: 'A2',
198
159
  cstType: CstType.AXIOM,
199
160
  definitionFormal: 'card(D5)=card(D7)',
200
161
  term: 'однозначность количества камней в кучках',
201
162
  definitionText: 'У каждой кучки ровно один номер'
202
- }
203
163
  },
204
164
  {
205
- draft: {
206
165
  id: 20,
207
166
  alias: 'A3',
208
167
  cstType: CstType.AXIOM,
209
168
  definitionFormal: '∀α∈D5 (pr1(α)<D6 & pr1(α)≥0)',
210
169
  term: 'последовательная нумерация кучек',
211
170
  definitionText: 'Номера кучек — целые от нуля до количества кучек минус один'
212
- }
213
171
  },
214
172
  {
215
- draft: {
216
173
  id: 21,
217
174
  alias: 'F8',
218
175
  cstType: CstType.FUNCTION,
219
176
  definitionFormal: '[α∈Z] F1[α,D5]',
220
177
  term: 'количество камней в данной кучке'
221
- }
222
178
  },
223
179
  {
224
- draft: {
225
180
  id: 22,
226
181
  alias: 'D9',
227
182
  cstType: CstType.TERM,
228
183
  definitionFormal: 'Pr1(Fi2[{0}](D5))',
229
184
  term: 'пустые кучки',
230
185
  definitionText: 'Номера кучек с нулевым размером'
231
- }
232
186
  },
233
187
  {
234
- draft: {
235
188
  id: 23,
236
189
  alias: 'D10',
237
190
  cstType: CstType.TERM,
238
191
  definitionFormal: 'D7\\D9',
239
192
  term: 'непустые кучки',
240
193
  definitionText: 'Номера кучек с положительным размером'
241
- }
242
194
  },
243
195
  {
244
- draft: {
245
196
  id: 24,
246
197
  alias: 'T1',
247
198
  cstType: CstType.STATEMENT,
248
199
  definitionFormal: 'D8={0}',
249
200
  term: 'игра закончена',
250
201
  definitionText: 'Во всех кучках не осталось камней'
251
- }
252
202
  },
253
203
  {
254
- draft: {
255
204
  id: 25,
256
205
  alias: 'T2',
257
206
  cstType: CstType.STATEMENT,
258
207
  definitionFormal: 'card(D10)=1',
259
208
  term: 'существует выигрышный ход',
260
209
  definitionText: 'Осталась ровно одна непустая кучка'
261
- }
262
210
  },
263
211
  {
264
- draft: {
265
212
  id: 26,
266
213
  alias: 'F10',
267
214
  cstType: CstType.FUNCTION,
@@ -269,7 +216,6 @@ async function run() {
269
216
  term: 'оценка хода Ним',
270
217
  definitionText:
271
218
  'Стоимость хода в дольках шоколадки: для чётного номера кучки — размер, умноженный на длину, иначе — на ширину'
272
- }
273
219
  }
274
220
  ];
275
221
 
@@ -281,7 +227,7 @@ async function run() {
281
227
  }>('applySchemaPatch', {
282
228
  sessionId: session.sessionId,
283
229
  mode: 'atomic',
284
- items: drafts.map(entry => entry.draft)
230
+ items
285
231
  });
286
232
 
287
233
  for (const item of patch.summary.items) {
@@ -10,9 +10,11 @@ import {
10
10
  D3_ID,
11
11
  DEFAULT_RSFORM_SESSION_PATH,
12
12
  DEFAULT_RSMODEL_SESSION_PATH,
13
+ S1_ID,
13
14
  S2_ID,
14
15
  S3_ID,
15
- S4_ID
16
+ S4_ID,
17
+ X1_ID
16
18
  } from './constants';
17
19
 
18
20
  /**
@@ -68,8 +70,8 @@ async function run() {
68
70
  await client.call('setModelValues', {
69
71
  sessionId: imported.sessionId,
70
72
  set: [
71
- { target: 1, value: X1_BINDING },
72
- { target: 2, value: S1_VALUE },
73
+ { target: X1_ID, value: X1_BINDING },
74
+ { target: S1_ID, value: S1_VALUE },
73
75
  { target: S2_ID, value: S2_VALUE },
74
76
  { target: S3_ID, value: S3_VALUE },
75
77
  { target: S4_ID, value: S4_VALUE }
@@ -1,7 +1,7 @@
1
1
  import { writeFile } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
3
 
4
- import { CstType, RSToolWrapperClient, type AgentConstituentaPatch } from '../../src';
4
+ import { CstType, RSToolWrapperClient, type AgentConstituentaPatch, type ApplySchemaPatchResult } from '../../src';
5
5
 
6
6
  async function run() {
7
7
  const client = new RSToolWrapperClient({
@@ -26,16 +26,14 @@ async function run() {
26
26
  { id: 5, alias: 'A1', cstType: CstType.AXIOM, definitionFormal: '1=1' }
27
27
  ];
28
28
 
29
- const result = await client.call<{ diagnostics: unknown[]; summary: { items: { alias: string }[] } }>(
30
- 'applySchemaPatch',
31
- {
32
- sessionId: session.sessionId,
33
- items
34
- }
35
- );
29
+ const result = await client.call<ApplySchemaPatchResult>('applySchemaPatch', {
30
+ sessionId: session.sessionId,
31
+ items
32
+ });
36
33
  for (const item of result.summary.items) {
37
- console.log(`Added ${item.alias}:`, result.diagnostics?.length ?? 0, 'diagnostics');
34
+ console.log(`Added ${item.alias}`);
38
35
  }
36
+ console.log(`Patch diagnostics: ${result.diagnostics.length}`);
39
37
 
40
38
  await client.call('commitStep', {
41
39
  sessionId: session.sessionId,
@@ -1,32 +1,36 @@
1
1
  {
2
2
  "contractVersion": "2.0.0",
3
3
  "state": {
4
- "sessionId": "b86aa3b1-3a18-47e9-b025-4295ab9ba57c",
4
+ "sessionId": "a03eec4c-6519-4088-9d8c-0a9c11611583",
5
5
  "alias": "",
6
6
  "title": "",
7
7
  "comment": "",
8
- "createdAt": "2026-07-01T17:12:43.950Z",
9
- "updatedAt": "2026-07-01T17:12:43.963Z",
8
+ "createdAt": "2026-07-01T21:33:21.321Z",
9
+ "updatedAt": "2026-07-01T21:33:21.332Z",
10
10
  "revisions": [
11
11
  {
12
- "revisionId": "49f6f60f-04d2-435a-8d56-e31de745c581",
13
- "at": "2026-07-01T17:12:43.963Z",
12
+ "revisionId": "4ec113d2-1d28-4bac-bed8-6a593bb6b0e2",
13
+ "at": "2026-07-01T21:33:21.332Z",
14
14
  "message": "Built sample RSForm"
15
15
  }
16
16
  ],
17
17
  "items": [
18
18
  {
19
- "id": 5,
20
- "alias": "A1",
21
- "cstType": "axiom",
22
- "definitionFormal": "1=1",
19
+ "id": 1,
20
+ "alias": "X1",
21
+ "cstType": "basic",
22
+ "definitionFormal": "",
23
23
  "term": "",
24
24
  "definitionText": "",
25
25
  "convention": "",
26
26
  "analysis": {
27
27
  "success": true,
28
28
  "type": {
29
- "typeID": 6
29
+ "typeID": 5,
30
+ "base": {
31
+ "typeID": 3,
32
+ "baseID": "X1"
33
+ }
30
34
  },
31
35
  "valueClass": "value",
32
36
  "diagnostics": []
@@ -56,27 +60,6 @@
56
60
  "diagnostics": []
57
61
  }
58
62
  },
59
- {
60
- "id": 1,
61
- "alias": "X1",
62
- "cstType": "basic",
63
- "definitionFormal": "",
64
- "term": "",
65
- "definitionText": "",
66
- "convention": "",
67
- "analysis": {
68
- "success": true,
69
- "type": {
70
- "typeID": 5,
71
- "base": {
72
- "typeID": 3,
73
- "baseID": "X1"
74
- }
75
- },
76
- "valueClass": "value",
77
- "diagnostics": []
78
- }
79
- },
80
63
  {
81
64
  "id": 3,
82
65
  "alias": "S1",
@@ -127,6 +110,23 @@
127
110
  "valueClass": "value",
128
111
  "diagnostics": []
129
112
  }
113
+ },
114
+ {
115
+ "id": 5,
116
+ "alias": "A1",
117
+ "cstType": "axiom",
118
+ "definitionFormal": "1=1",
119
+ "term": "",
120
+ "definitionText": "",
121
+ "convention": "",
122
+ "analysis": {
123
+ "success": true,
124
+ "type": {
125
+ "typeID": 6
126
+ },
127
+ "valueClass": "value",
128
+ "diagnostics": []
129
+ }
130
130
  }
131
131
  ],
132
132
  "model": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rsconcept/rstool",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Agent-facing library for incremental RSForm construction, RSLang analysis, diagnostics, modeling, and evaluation. Wraps @rsconcept/domain with a deterministic session contract.",
5
5
  "license": "MIT",
6
6
  "author": "IRBorisov",
@@ -54,6 +54,7 @@
54
54
  "build": "tsdown",
55
55
  "typecheck": "tsc -p tsconfig.json --noEmit",
56
56
  "test": "vitest run",
57
+ "test:coverage": "vitest run --coverage",
57
58
  "wrapper": "tsx src/wrapper/stdio-wrapper.ts",
58
59
  "example:client": "tsx examples/agent-client.ts",
59
60
  "example:build-schema": "tsx examples/sample/build-rsform.ts",
@@ -74,6 +75,7 @@
74
75
  },
75
76
  "devDependencies": {
76
77
  "@types/node": "^26.0.1",
78
+ "@vitest/coverage-v8": "^4.1.9",
77
79
  "tsdown": "^0.22.3",
78
80
  "tsx": "^4.22.4",
79
81
  "typescript": "^6.0.3",
@@ -1,8 +1,15 @@
1
1
  import { type ConstituentaDraft } from '../models/constituenta';
2
- import { type PortalRsformDetails, type PortalSchemaImportData, portalItemToDraft } from '../models/portal-json';
2
+ import {
3
+ type PortalImportMetadata,
4
+ type PortalRsformDetails,
5
+ type PortalSchemaImportData,
6
+ portalItemToDraft
7
+ } from '../models/portal-json';
3
8
  import { type SessionState } from '../models/session';
4
9
 
5
- export function portalSchemaToSessionSeed(data: PortalSchemaImportData): Partial<SessionState> {
10
+ type PortalSessionSeedInput = Partial<Pick<PortalImportMetadata, 'alias' | 'title' | 'description'>>;
11
+
12
+ function portalMetadataToSessionSeed(data: PortalSessionSeedInput): Partial<SessionState> {
6
13
  return {
7
14
  alias: data.alias ?? '',
8
15
  title: data.title ?? '',
@@ -11,13 +18,12 @@ export function portalSchemaToSessionSeed(data: PortalSchemaImportData): Partial
11
18
  };
12
19
  }
13
20
 
21
+ export function portalSchemaToSessionSeed(data: PortalSchemaImportData): Partial<SessionState> {
22
+ return portalMetadataToSessionSeed(data);
23
+ }
24
+
14
25
  export function portalDetailsToSessionSeed(data: PortalRsformDetails): Partial<SessionState> {
15
- return {
16
- alias: data.alias ?? '',
17
- title: data.title ?? '',
18
- comment: data.description ?? '',
19
- items: []
20
- };
26
+ return portalMetadataToSessionSeed(data);
21
27
  }
22
28
 
23
29
  export function portalItemsToDrafts(