@forthix/forthic 0.10.0 → 0.11.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/dist/cjs/common/runtime_client.d.ts +30 -0
- package/dist/cjs/common/runtime_client.js +10 -0
- package/dist/cjs/common/runtime_client.js.map +1 -0
- package/dist/cjs/common/type_utils.d.ts +7 -1
- package/dist/cjs/common/type_utils.js +13 -2
- package/dist/cjs/common/type_utils.js.map +1 -1
- package/dist/cjs/forthic/interpreter.js +4 -3
- package/dist/cjs/forthic/interpreter.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/classic/classic_module.d.ts +56 -0
- package/dist/cjs/forthic/modules/standard/classic/classic_module.js +616 -0
- package/dist/cjs/forthic/modules/standard/classic/classic_module.js.map +1 -0
- package/dist/cjs/grpc/config_loader.d.ts +3 -0
- package/dist/cjs/grpc/config_loader.js +5 -0
- package/dist/cjs/grpc/config_loader.js.map +1 -1
- package/dist/cjs/grpc/remote_module.d.ts +3 -3
- package/dist/cjs/grpc/remote_module.js +1 -1
- package/dist/cjs/grpc/remote_module.js.map +1 -1
- package/dist/cjs/grpc/remote_word.d.ts +3 -3
- package/dist/cjs/grpc/remote_word.js +1 -1
- package/dist/cjs/grpc/remote_word.js.map +1 -1
- package/dist/cjs/grpc/runtime_manager.d.ts +5 -4
- package/dist/cjs/grpc/runtime_manager.js +2 -2
- package/dist/cjs/grpc/runtime_manager.js.map +1 -1
- package/dist/cjs/grpc/serializer.d.ts +2 -2
- package/dist/cjs/grpc/serializer.js +11 -10
- package/dist/cjs/grpc/serializer.js.map +1 -1
- package/dist/cjs/jsonrpc/browser-stub.d.ts +8 -0
- package/dist/cjs/jsonrpc/browser-stub.js +18 -0
- package/dist/cjs/jsonrpc/browser-stub.js.map +1 -0
- package/dist/cjs/jsonrpc/client.d.ts +31 -0
- package/dist/cjs/jsonrpc/client.js +98 -0
- package/dist/cjs/jsonrpc/client.js.map +1 -0
- package/dist/cjs/jsonrpc/errors.d.ts +18 -0
- package/dist/cjs/jsonrpc/errors.js +23 -0
- package/dist/cjs/jsonrpc/errors.js.map +1 -0
- package/dist/cjs/jsonrpc/index.d.ts +16 -0
- package/dist/cjs/jsonrpc/index.js +26 -0
- package/dist/cjs/jsonrpc/index.js.map +1 -0
- package/dist/cjs/jsonrpc/serializer.d.ts +8 -0
- package/dist/cjs/jsonrpc/serializer.js +14 -0
- package/dist/cjs/jsonrpc/serializer.js.map +1 -0
- package/dist/cjs/jsonrpc/server.d.ts +15 -0
- package/dist/cjs/jsonrpc/server.js +386 -0
- package/dist/cjs/jsonrpc/server.js.map +1 -0
- package/dist/cjs/websocket/serializer.d.ts +4 -4
- package/dist/cjs/websocket/serializer.js +15 -14
- package/dist/cjs/websocket/serializer.js.map +1 -1
- package/dist/esm/common/runtime_client.d.ts +30 -0
- package/dist/esm/common/runtime_client.js +9 -0
- package/dist/esm/common/runtime_client.js.map +1 -0
- package/dist/esm/common/type_utils.d.ts +7 -1
- package/dist/esm/common/type_utils.js +12 -2
- package/dist/esm/common/type_utils.js.map +1 -1
- package/dist/esm/forthic/interpreter.js +4 -3
- package/dist/esm/forthic/interpreter.js.map +1 -1
- package/dist/esm/forthic/modules/standard/classic/classic_module.d.ts +56 -0
- package/dist/esm/forthic/modules/standard/classic/classic_module.js +500 -0
- package/dist/esm/forthic/modules/standard/classic/classic_module.js.map +1 -0
- package/dist/esm/grpc/config_loader.d.ts +3 -0
- package/dist/esm/grpc/config_loader.js +5 -0
- package/dist/esm/grpc/config_loader.js.map +1 -1
- package/dist/esm/grpc/remote_module.d.ts +3 -3
- package/dist/esm/grpc/remote_module.js +1 -1
- package/dist/esm/grpc/remote_module.js.map +1 -1
- package/dist/esm/grpc/remote_word.d.ts +3 -3
- package/dist/esm/grpc/remote_word.js +1 -1
- package/dist/esm/grpc/remote_word.js.map +1 -1
- package/dist/esm/grpc/runtime_manager.d.ts +5 -4
- package/dist/esm/grpc/runtime_manager.js +2 -2
- package/dist/esm/grpc/runtime_manager.js.map +1 -1
- package/dist/esm/grpc/serializer.d.ts +2 -2
- package/dist/esm/grpc/serializer.js +12 -11
- package/dist/esm/grpc/serializer.js.map +1 -1
- package/dist/esm/jsonrpc/browser-stub.d.ts +8 -0
- package/dist/esm/jsonrpc/browser-stub.js +12 -0
- package/dist/esm/jsonrpc/browser-stub.js.map +1 -0
- package/dist/esm/jsonrpc/client.d.ts +31 -0
- package/dist/esm/jsonrpc/client.js +94 -0
- package/dist/esm/jsonrpc/client.js.map +1 -0
- package/dist/esm/jsonrpc/errors.d.ts +18 -0
- package/dist/esm/jsonrpc/errors.js +18 -0
- package/dist/esm/jsonrpc/errors.js.map +1 -0
- package/dist/esm/jsonrpc/index.d.ts +16 -0
- package/dist/esm/jsonrpc/index.js +16 -0
- package/dist/esm/jsonrpc/index.js.map +1 -0
- package/dist/esm/jsonrpc/serializer.d.ts +8 -0
- package/dist/esm/jsonrpc/serializer.js +9 -0
- package/dist/esm/jsonrpc/serializer.js.map +1 -0
- package/dist/esm/jsonrpc/server.d.ts +15 -0
- package/dist/esm/jsonrpc/server.js +349 -0
- package/dist/esm/jsonrpc/server.js.map +1 -0
- package/dist/esm/websocket/serializer.d.ts +4 -4
- package/dist/esm/websocket/serializer.js +16 -15
- package/dist/esm/websocket/serializer.js.map +1 -1
- package/package.json +15 -2
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.serve = serve;
|
|
37
|
+
exports.main = main;
|
|
38
|
+
/**
|
|
39
|
+
* TypeScript JSON-RPC 2.0 Server for Forthic
|
|
40
|
+
*
|
|
41
|
+
* Mirrors the four methods of the gRPC server:
|
|
42
|
+
* executeWord, executeSequence, listModules, getModuleInfo
|
|
43
|
+
*
|
|
44
|
+
* Transport: HTTP POST /rpc with JSON-RPC 2.0 envelopes.
|
|
45
|
+
* Uses Node's built-in `http` module — zero new dependencies.
|
|
46
|
+
*
|
|
47
|
+
* `executeSequence` is a single JSON-RPC call with an array of words; it is
|
|
48
|
+
* NOT a JSON-RPC batch. Batch envelopes are rejected with code -32600.
|
|
49
|
+
*/
|
|
50
|
+
const http = __importStar(require("http"));
|
|
51
|
+
const interpreter_js_1 = require("../forthic/interpreter.js");
|
|
52
|
+
const serializer_js_1 = require("../grpc/serializer.js");
|
|
53
|
+
const fs_module_js_1 = require("../forthic/modules/typescript/fs_module.js");
|
|
54
|
+
const errors_js_1 = require("./errors.js");
|
|
55
|
+
class ForthicJsonRpcServicer {
|
|
56
|
+
runtimeModules;
|
|
57
|
+
constructor() {
|
|
58
|
+
this.runtimeModules = {
|
|
59
|
+
fs: new fs_module_js_1.FsModule(),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async executeWord(params) {
|
|
63
|
+
const wordName = params?.word_name;
|
|
64
|
+
if (typeof wordName !== 'string') {
|
|
65
|
+
throw makeInvalidParams('executeWord requires string "word_name"');
|
|
66
|
+
}
|
|
67
|
+
const stackParam = params?.stack;
|
|
68
|
+
if (!Array.isArray(stackParam)) {
|
|
69
|
+
throw makeInvalidParams('executeWord requires array "stack"');
|
|
70
|
+
}
|
|
71
|
+
const stack = stackParam.map((sv) => (0, serializer_js_1.deserializeValue)(sv));
|
|
72
|
+
const resultStack = await this._executeWithStack(wordName, stack);
|
|
73
|
+
return { result_stack: resultStack.map((v) => (0, serializer_js_1.serializeValue)(v)) };
|
|
74
|
+
}
|
|
75
|
+
async executeSequence(params) {
|
|
76
|
+
const wordNames = params?.word_names;
|
|
77
|
+
if (!Array.isArray(wordNames) || !wordNames.every((w) => typeof w === 'string')) {
|
|
78
|
+
throw makeInvalidParams('executeSequence requires string[] "word_names"');
|
|
79
|
+
}
|
|
80
|
+
const stackParam = params?.stack;
|
|
81
|
+
if (!Array.isArray(stackParam)) {
|
|
82
|
+
throw makeInvalidParams('executeSequence requires array "stack"');
|
|
83
|
+
}
|
|
84
|
+
const stack = stackParam.map((sv) => (0, serializer_js_1.deserializeValue)(sv));
|
|
85
|
+
const resultStack = await this._executeSequenceWithStack(wordNames, stack);
|
|
86
|
+
return { result_stack: resultStack.map((v) => (0, serializer_js_1.serializeValue)(v)) };
|
|
87
|
+
}
|
|
88
|
+
async listModules(_params) {
|
|
89
|
+
const modules = [];
|
|
90
|
+
for (const [name, mod] of Object.entries(this.runtimeModules)) {
|
|
91
|
+
modules.push({
|
|
92
|
+
name,
|
|
93
|
+
description: `TypeScript-specific ${name} module`,
|
|
94
|
+
word_count: this._getModuleWordCount(mod),
|
|
95
|
+
runtime_specific: true,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
return { modules };
|
|
99
|
+
}
|
|
100
|
+
async getModuleInfo(params) {
|
|
101
|
+
const moduleName = params?.module_name;
|
|
102
|
+
if (typeof moduleName !== 'string') {
|
|
103
|
+
throw makeInvalidParams('getModuleInfo requires string "module_name"');
|
|
104
|
+
}
|
|
105
|
+
if (!(moduleName in this.runtimeModules)) {
|
|
106
|
+
throw new JsonRpcMethodError(errors_js_1.JsonRpcErrorCode.ModuleNotFound, `Module '${moduleName}' not found`);
|
|
107
|
+
}
|
|
108
|
+
const mod = this.runtimeModules[moduleName];
|
|
109
|
+
const words = [];
|
|
110
|
+
if (typeof mod.getWordDocs === 'function') {
|
|
111
|
+
for (const doc of mod.getWordDocs()) {
|
|
112
|
+
words.push({
|
|
113
|
+
name: doc.name,
|
|
114
|
+
stack_effect: doc.stackEffect,
|
|
115
|
+
description: doc.description,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
const exportedWords = mod.exportable || {};
|
|
121
|
+
for (const [name, _word] of Object.entries(exportedWords)) {
|
|
122
|
+
words.push({
|
|
123
|
+
name,
|
|
124
|
+
stack_effect: '( -- )',
|
|
125
|
+
description: `${name} word from ${moduleName} module`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
name: moduleName,
|
|
131
|
+
description: `TypeScript-specific ${moduleName} module`,
|
|
132
|
+
words,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
buildRuntimeError(exception, wordName = null, context = {}) {
|
|
136
|
+
const stackTrace = exception?.stack ? String(exception.stack).split('\n') : [];
|
|
137
|
+
const errorType = exception?.constructor?.name || 'Error';
|
|
138
|
+
const errorContext = {};
|
|
139
|
+
if (wordName)
|
|
140
|
+
errorContext['word_name'] = wordName;
|
|
141
|
+
Object.assign(errorContext, context);
|
|
142
|
+
const errorInfo = {
|
|
143
|
+
message: exception?.message ?? String(exception),
|
|
144
|
+
runtime: 'typescript',
|
|
145
|
+
stack_trace: stackTrace,
|
|
146
|
+
error_type: errorType,
|
|
147
|
+
context: errorContext,
|
|
148
|
+
};
|
|
149
|
+
if (stackTrace.length > 0) {
|
|
150
|
+
const m = stackTrace[0].match(/\((.*):(\d+):\d+\)/);
|
|
151
|
+
if (m)
|
|
152
|
+
errorInfo.word_location = `${m[1]}:${m[2]}`;
|
|
153
|
+
}
|
|
154
|
+
return errorInfo;
|
|
155
|
+
}
|
|
156
|
+
getRegisteredModuleNames() {
|
|
157
|
+
return Object.keys(this.runtimeModules);
|
|
158
|
+
}
|
|
159
|
+
async _executeWithStack(wordName, stack) {
|
|
160
|
+
const interp = new interpreter_js_1.StandardInterpreter();
|
|
161
|
+
for (const [_n, m] of Object.entries(this.runtimeModules)) {
|
|
162
|
+
interp.register_module(m);
|
|
163
|
+
}
|
|
164
|
+
if (Object.keys(this.runtimeModules).length > 0) {
|
|
165
|
+
interp.use_modules(Object.keys(this.runtimeModules));
|
|
166
|
+
}
|
|
167
|
+
for (const item of stack)
|
|
168
|
+
interp.stack_push(item);
|
|
169
|
+
await interp.run(wordName);
|
|
170
|
+
return interp.get_stack().get_items();
|
|
171
|
+
}
|
|
172
|
+
async _executeSequenceWithStack(wordNames, stack) {
|
|
173
|
+
const interp = new interpreter_js_1.StandardInterpreter();
|
|
174
|
+
for (const [_n, m] of Object.entries(this.runtimeModules)) {
|
|
175
|
+
interp.register_module(m);
|
|
176
|
+
}
|
|
177
|
+
if (Object.keys(this.runtimeModules).length > 0) {
|
|
178
|
+
interp.use_modules(Object.keys(this.runtimeModules));
|
|
179
|
+
}
|
|
180
|
+
for (const item of stack)
|
|
181
|
+
interp.stack_push(item);
|
|
182
|
+
for (const wordName of wordNames) {
|
|
183
|
+
await interp.run(wordName);
|
|
184
|
+
}
|
|
185
|
+
return interp.get_stack().get_items();
|
|
186
|
+
}
|
|
187
|
+
_getModuleWordCount(mod) {
|
|
188
|
+
if (typeof mod.getWordDocs === 'function')
|
|
189
|
+
return mod.getWordDocs().length;
|
|
190
|
+
if (mod.exportable)
|
|
191
|
+
return Object.keys(mod.exportable).length;
|
|
192
|
+
return 0;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
class JsonRpcMethodError extends Error {
|
|
196
|
+
code;
|
|
197
|
+
data;
|
|
198
|
+
constructor(code, message, data) {
|
|
199
|
+
super(message);
|
|
200
|
+
this.code = code;
|
|
201
|
+
this.data = data;
|
|
202
|
+
this.name = 'JsonRpcMethodError';
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function makeInvalidParams(message) {
|
|
206
|
+
return new JsonRpcMethodError(errors_js_1.JsonRpcErrorCode.InvalidParams, message);
|
|
207
|
+
}
|
|
208
|
+
async function readBody(req) {
|
|
209
|
+
return new Promise((resolve, reject) => {
|
|
210
|
+
const chunks = [];
|
|
211
|
+
req.on('data', (c) => chunks.push(c));
|
|
212
|
+
req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
|
|
213
|
+
req.on('error', reject);
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function writeJsonRpc(res, status, payload) {
|
|
217
|
+
const body = JSON.stringify(payload);
|
|
218
|
+
res.writeHead(status, {
|
|
219
|
+
'Content-Type': 'application/json',
|
|
220
|
+
'Content-Length': Buffer.byteLength(body),
|
|
221
|
+
});
|
|
222
|
+
res.end(body);
|
|
223
|
+
}
|
|
224
|
+
async function dispatch(servicer, request) {
|
|
225
|
+
const id = request.id ?? null;
|
|
226
|
+
const method = request.method;
|
|
227
|
+
const params = request.params ?? {};
|
|
228
|
+
try {
|
|
229
|
+
let result;
|
|
230
|
+
switch (method) {
|
|
231
|
+
case 'executeWord':
|
|
232
|
+
try {
|
|
233
|
+
result = await servicer.executeWord(params);
|
|
234
|
+
}
|
|
235
|
+
catch (err) {
|
|
236
|
+
if (err instanceof JsonRpcMethodError)
|
|
237
|
+
throw err;
|
|
238
|
+
// Treat as Forthic runtime error with rich data
|
|
239
|
+
const data = servicer.buildRuntimeError(err, params?.word_name ?? null);
|
|
240
|
+
throw new JsonRpcMethodError(errors_js_1.JsonRpcErrorCode.RuntimeError, data.message, data);
|
|
241
|
+
}
|
|
242
|
+
break;
|
|
243
|
+
case 'executeSequence':
|
|
244
|
+
try {
|
|
245
|
+
result = await servicer.executeSequence(params);
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
if (err instanceof JsonRpcMethodError)
|
|
249
|
+
throw err;
|
|
250
|
+
const seqContext = Array.isArray(params?.word_names)
|
|
251
|
+
? { word_sequence: params.word_names.join(', ') }
|
|
252
|
+
: {};
|
|
253
|
+
const data = servicer.buildRuntimeError(err, null, seqContext);
|
|
254
|
+
throw new JsonRpcMethodError(errors_js_1.JsonRpcErrorCode.RuntimeError, data.message, data);
|
|
255
|
+
}
|
|
256
|
+
break;
|
|
257
|
+
case 'listModules':
|
|
258
|
+
result = await servicer.listModules(params);
|
|
259
|
+
break;
|
|
260
|
+
case 'getModuleInfo':
|
|
261
|
+
result = await servicer.getModuleInfo(params);
|
|
262
|
+
break;
|
|
263
|
+
default:
|
|
264
|
+
throw new JsonRpcMethodError(errors_js_1.JsonRpcErrorCode.MethodNotFound, `Method not found: ${method}`);
|
|
265
|
+
}
|
|
266
|
+
return { jsonrpc: '2.0', id, result };
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
if (err instanceof JsonRpcMethodError) {
|
|
270
|
+
const error = { code: err.code, message: err.message };
|
|
271
|
+
if (err.data !== undefined)
|
|
272
|
+
error.data = err.data;
|
|
273
|
+
return { jsonrpc: '2.0', id, error };
|
|
274
|
+
}
|
|
275
|
+
return {
|
|
276
|
+
jsonrpc: '2.0',
|
|
277
|
+
id,
|
|
278
|
+
error: {
|
|
279
|
+
code: errors_js_1.JsonRpcErrorCode.InternalError,
|
|
280
|
+
message: err?.message ?? String(err),
|
|
281
|
+
},
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
async function serve(port = 8765) {
|
|
286
|
+
const servicer = new ForthicJsonRpcServicer();
|
|
287
|
+
const server = http.createServer(async (req, res) => {
|
|
288
|
+
if (req.method !== 'POST') {
|
|
289
|
+
res.writeHead(405, { 'Content-Type': 'text/plain', Allow: 'POST' });
|
|
290
|
+
res.end('Method Not Allowed');
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
if (req.url !== '/rpc' && req.url !== '/') {
|
|
294
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
295
|
+
res.end('Not Found');
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
const ctype = (req.headers['content-type'] || '').toString().toLowerCase();
|
|
299
|
+
if (!ctype.includes('application/json')) {
|
|
300
|
+
res.writeHead(415, { 'Content-Type': 'text/plain' });
|
|
301
|
+
res.end('Unsupported Media Type');
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
let raw;
|
|
305
|
+
try {
|
|
306
|
+
raw = await readBody(req);
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
writeJsonRpc(res, 200, {
|
|
310
|
+
jsonrpc: '2.0',
|
|
311
|
+
id: null,
|
|
312
|
+
error: { code: errors_js_1.JsonRpcErrorCode.ParseError, message: 'Failed to read request body' },
|
|
313
|
+
});
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
316
|
+
let parsed;
|
|
317
|
+
try {
|
|
318
|
+
parsed = JSON.parse(raw);
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
writeJsonRpc(res, 200, {
|
|
322
|
+
jsonrpc: '2.0',
|
|
323
|
+
id: null,
|
|
324
|
+
error: { code: errors_js_1.JsonRpcErrorCode.ParseError, message: `Parse error: ${err.message}` },
|
|
325
|
+
});
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
if (Array.isArray(parsed)) {
|
|
329
|
+
writeJsonRpc(res, 200, {
|
|
330
|
+
jsonrpc: '2.0',
|
|
331
|
+
id: null,
|
|
332
|
+
error: {
|
|
333
|
+
code: errors_js_1.JsonRpcErrorCode.InvalidRequest,
|
|
334
|
+
message: 'Batch requests are not supported',
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
if (!parsed ||
|
|
340
|
+
parsed.jsonrpc !== '2.0' ||
|
|
341
|
+
typeof parsed.method !== 'string' ||
|
|
342
|
+
!('id' in parsed)) {
|
|
343
|
+
writeJsonRpc(res, 200, {
|
|
344
|
+
jsonrpc: '2.0',
|
|
345
|
+
id: parsed?.id ?? null,
|
|
346
|
+
error: {
|
|
347
|
+
code: errors_js_1.JsonRpcErrorCode.InvalidRequest,
|
|
348
|
+
message: 'Invalid JSON-RPC 2.0 request',
|
|
349
|
+
},
|
|
350
|
+
});
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
const response = await dispatch(servicer, parsed);
|
|
354
|
+
writeJsonRpc(res, 200, response);
|
|
355
|
+
});
|
|
356
|
+
return new Promise((resolve, reject) => {
|
|
357
|
+
server.once('error', reject);
|
|
358
|
+
server.listen(port, '0.0.0.0', () => {
|
|
359
|
+
const loaded = servicer.getRegisteredModuleNames();
|
|
360
|
+
if (loaded.length > 0) {
|
|
361
|
+
console.log(` - Available runtime modules: ${loaded.join(', ')}`);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
console.log(' - No runtime-specific modules loaded');
|
|
365
|
+
}
|
|
366
|
+
resolve(server);
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
async function main() {
|
|
371
|
+
const args = process.argv.slice(2);
|
|
372
|
+
let port = 8765;
|
|
373
|
+
const portIndex = args.indexOf('--port');
|
|
374
|
+
if (portIndex !== -1 && args[portIndex + 1]) {
|
|
375
|
+
port = parseInt(args[portIndex + 1], 10);
|
|
376
|
+
}
|
|
377
|
+
await serve(port);
|
|
378
|
+
console.log(`Forthic JSON-RPC server listening on port ${port}`);
|
|
379
|
+
}
|
|
380
|
+
if (require.main === module) {
|
|
381
|
+
main().catch((error) => {
|
|
382
|
+
console.error('Fatal error:', error);
|
|
383
|
+
process.exit(1);
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/jsonrpc/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,16 +12,16 @@ export interface StackValue {
|
|
|
12
12
|
* Serialize a JavaScript value to a JSON StackValue
|
|
13
13
|
* Uses shared type detection and maps to JSON format
|
|
14
14
|
*/
|
|
15
|
-
export declare function serializeValue(value: any): StackValue;
|
|
15
|
+
export declare function serializeValue(value: any, path?: string): StackValue;
|
|
16
16
|
/**
|
|
17
17
|
* Deserialize a JSON StackValue to a JavaScript value
|
|
18
18
|
*/
|
|
19
|
-
export declare function deserializeValue(stackValue: StackValue): any;
|
|
19
|
+
export declare function deserializeValue(stackValue: StackValue, path?: string): any;
|
|
20
20
|
/**
|
|
21
21
|
* Serialize an array of values (stack)
|
|
22
22
|
*/
|
|
23
|
-
export declare function serializeStack(stack: any[]): StackValue[];
|
|
23
|
+
export declare function serializeStack(stack: any[], pathPrefix?: string): StackValue[];
|
|
24
24
|
/**
|
|
25
25
|
* Deserialize an array of StackValues (stack)
|
|
26
26
|
*/
|
|
27
|
-
export declare function deserializeStack(stackValues: StackValue[]): any[];
|
|
27
|
+
export declare function deserializeStack(stackValues: StackValue[], pathPrefix?: string): any[];
|
|
@@ -15,8 +15,8 @@ const type_utils_js_1 = require("../common/type_utils.js");
|
|
|
15
15
|
* Serialize a JavaScript value to a JSON StackValue
|
|
16
16
|
* Uses shared type detection and maps to JSON format
|
|
17
17
|
*/
|
|
18
|
-
function serializeValue(value) {
|
|
19
|
-
const type = (0, type_utils_js_1.getForthicType)(value);
|
|
18
|
+
function serializeValue(value, path = '') {
|
|
19
|
+
const type = (0, type_utils_js_1.getForthicType)(value, path);
|
|
20
20
|
switch (type) {
|
|
21
21
|
case 'null':
|
|
22
22
|
return { type: 'null', value: null };
|
|
@@ -31,17 +31,18 @@ function serializeValue(value) {
|
|
|
31
31
|
case 'array':
|
|
32
32
|
return {
|
|
33
33
|
type: 'array',
|
|
34
|
-
value: value.map((item) => serializeValue(item)),
|
|
34
|
+
value: value.map((item, i) => serializeValue(item, `${path}[${i}]`)),
|
|
35
35
|
};
|
|
36
|
-
case 'record':
|
|
36
|
+
case 'record': {
|
|
37
37
|
const fields = {};
|
|
38
38
|
for (const [key, val] of Object.entries(value)) {
|
|
39
|
-
fields[key] = serializeValue(val);
|
|
39
|
+
fields[key] = serializeValue(val, `${path}${(0, type_utils_js_1.pathSegmentForKey)(key)}`);
|
|
40
40
|
}
|
|
41
41
|
return {
|
|
42
42
|
type: 'record',
|
|
43
43
|
value: fields,
|
|
44
44
|
};
|
|
45
|
+
}
|
|
45
46
|
case 'instant':
|
|
46
47
|
return {
|
|
47
48
|
type: 'instant',
|
|
@@ -58,13 +59,13 @@ function serializeValue(value) {
|
|
|
58
59
|
value: value.toString(),
|
|
59
60
|
};
|
|
60
61
|
default:
|
|
61
|
-
throw new Error(`Unsupported Forthic type: ${type}`);
|
|
62
|
+
throw new Error(`Unsupported Forthic type: ${type}${path ? ` at path: ${path}` : ''}`);
|
|
62
63
|
}
|
|
63
64
|
}
|
|
64
65
|
/**
|
|
65
66
|
* Deserialize a JSON StackValue to a JavaScript value
|
|
66
67
|
*/
|
|
67
|
-
function deserializeValue(stackValue) {
|
|
68
|
+
function deserializeValue(stackValue, path = '') {
|
|
68
69
|
switch (stackValue.type) {
|
|
69
70
|
case 'int':
|
|
70
71
|
case 'float':
|
|
@@ -74,10 +75,10 @@ function deserializeValue(stackValue) {
|
|
|
74
75
|
case 'null':
|
|
75
76
|
return null;
|
|
76
77
|
case 'array':
|
|
77
|
-
return stackValue.value.map((v) => deserializeValue(v));
|
|
78
|
+
return stackValue.value.map((v, i) => deserializeValue(v, `${path}[${i}]`));
|
|
78
79
|
case 'record':
|
|
79
80
|
return Object.entries(stackValue.value).reduce((acc, [k, v]) => {
|
|
80
|
-
acc[k] = deserializeValue(v);
|
|
81
|
+
acc[k] = deserializeValue(v, `${path}${(0, type_utils_js_1.pathSegmentForKey)(k)}`);
|
|
81
82
|
return acc;
|
|
82
83
|
}, {});
|
|
83
84
|
case 'instant':
|
|
@@ -87,19 +88,19 @@ function deserializeValue(stackValue) {
|
|
|
87
88
|
case 'zoned_datetime':
|
|
88
89
|
return Temporal.ZonedDateTime.from(stackValue.value);
|
|
89
90
|
default:
|
|
90
|
-
throw new Error(`Unknown stack value type: ${stackValue.type}`);
|
|
91
|
+
throw new Error(`Unknown stack value type: ${stackValue.type}${path ? ` at path: ${path}` : ''}`);
|
|
91
92
|
}
|
|
92
93
|
}
|
|
93
94
|
/**
|
|
94
95
|
* Serialize an array of values (stack)
|
|
95
96
|
*/
|
|
96
|
-
function serializeStack(stack) {
|
|
97
|
-
return stack.map((value) => serializeValue(value));
|
|
97
|
+
function serializeStack(stack, pathPrefix = '') {
|
|
98
|
+
return stack.map((value, i) => serializeValue(value, `${pathPrefix}[${i}]`));
|
|
98
99
|
}
|
|
99
100
|
/**
|
|
100
101
|
* Deserialize an array of StackValues (stack)
|
|
101
102
|
*/
|
|
102
|
-
function deserializeStack(stackValues) {
|
|
103
|
-
return stackValues.map((value) => deserializeValue(value));
|
|
103
|
+
function deserializeStack(stackValues, pathPrefix = '') {
|
|
104
|
+
return stackValues.map((value, i) => deserializeValue(value, `${pathPrefix}[${i}]`));
|
|
104
105
|
}
|
|
105
106
|
//# sourceMappingURL=serializer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serializer.js","sourceRoot":"","sources":["../../../src/websocket/serializer.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAcH,
|
|
1
|
+
{"version":3,"file":"serializer.js","sourceRoot":"","sources":["../../../src/websocket/serializer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuntimeClient - Transport-agnostic interface for remote Forthic runtime clients.
|
|
3
|
+
*
|
|
4
|
+
* Implemented by both GrpcClient (src/grpc/client.ts) and JsonRpcClient
|
|
5
|
+
* (src/jsonrpc/client.ts) so RemoteModule, RemoteWord, and RuntimeManager
|
|
6
|
+
* work the same way regardless of underlying transport.
|
|
7
|
+
*/
|
|
8
|
+
export interface ModuleSummary {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
word_count: number;
|
|
12
|
+
runtime_specific: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface WordInfo {
|
|
15
|
+
name: string;
|
|
16
|
+
stack_effect: string;
|
|
17
|
+
description: string;
|
|
18
|
+
}
|
|
19
|
+
export interface GetModuleInfoResponse {
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
words: WordInfo[];
|
|
23
|
+
}
|
|
24
|
+
export interface RuntimeClient {
|
|
25
|
+
executeWord(wordName: string, stack: any[]): Promise<any[]>;
|
|
26
|
+
executeSequence(wordNames: string[], stack: any[]): Promise<any[]>;
|
|
27
|
+
listModules(): Promise<ModuleSummary[]>;
|
|
28
|
+
getModuleInfo(moduleName: string): Promise<GetModuleInfoResponse>;
|
|
29
|
+
close(): void;
|
|
30
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuntimeClient - Transport-agnostic interface for remote Forthic runtime clients.
|
|
3
|
+
*
|
|
4
|
+
* Implemented by both GrpcClient (src/grpc/client.ts) and JsonRpcClient
|
|
5
|
+
* (src/jsonrpc/client.ts) so RemoteModule, RemoteWord, and RuntimeManager
|
|
6
|
+
* work the same way regardless of underlying transport.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=runtime_client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime_client.js","sourceRoot":"","sources":["../../../src/common/runtime_client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -16,7 +16,13 @@ export type ForthicType = 'null' | 'boolean' | 'integer' | 'float' | 'string' |
|
|
|
16
16
|
* - Check boolean BEFORE number (to avoid typeof confusion)
|
|
17
17
|
* - Check array BEFORE object (arrays are objects)
|
|
18
18
|
*/
|
|
19
|
-
export declare function getForthicType(value: any): ForthicType;
|
|
19
|
+
export declare function getForthicType(value: any, path?: string): ForthicType;
|
|
20
|
+
/**
|
|
21
|
+
* Format a record key as a path segment.
|
|
22
|
+
* Valid JS identifiers become `.key`; everything else becomes `["key"]` (JSON-escaped)
|
|
23
|
+
* so the path is unambiguous and copy-pasteable.
|
|
24
|
+
*/
|
|
25
|
+
export declare function pathSegmentForKey(key: string): string;
|
|
20
26
|
/**
|
|
21
27
|
* Check if a value is a temporal type
|
|
22
28
|
*/
|
|
@@ -13,7 +13,7 @@ import { isPlainDate, isInstant, isZonedDateTime } from './temporal_utils.js';
|
|
|
13
13
|
* - Check boolean BEFORE number (to avoid typeof confusion)
|
|
14
14
|
* - Check array BEFORE object (arrays are objects)
|
|
15
15
|
*/
|
|
16
|
-
export function getForthicType(value) {
|
|
16
|
+
export function getForthicType(value, path = '') {
|
|
17
17
|
// Handle null/undefined
|
|
18
18
|
if (value === null || value === undefined) {
|
|
19
19
|
return 'null';
|
|
@@ -48,7 +48,17 @@ export function getForthicType(value) {
|
|
|
48
48
|
if (typeof value === 'object') {
|
|
49
49
|
return 'record';
|
|
50
50
|
}
|
|
51
|
-
throw new Error(`Unsupported value type: ${typeof value}`);
|
|
51
|
+
throw new Error(`Unsupported value type: ${typeof value}${path ? ` at path: ${path}` : ''}`);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Format a record key as a path segment.
|
|
55
|
+
* Valid JS identifiers become `.key`; everything else becomes `["key"]` (JSON-escaped)
|
|
56
|
+
* so the path is unambiguous and copy-pasteable.
|
|
57
|
+
*/
|
|
58
|
+
export function pathSegmentForKey(key) {
|
|
59
|
+
return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)
|
|
60
|
+
? `.${key}`
|
|
61
|
+
: `[${JSON.stringify(key)}]`;
|
|
52
62
|
}
|
|
53
63
|
/**
|
|
54
64
|
* Check if a value is a temporal type
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type_utils.js","sourceRoot":"","sources":["../../../src/common/type_utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAiB9E;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,KAAU;
|
|
1
|
+
{"version":3,"file":"type_utils.js","sourceRoot":"","sources":["../../../src/common/type_utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAiB9E;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,KAAU,EAAE,OAAe,EAAE;IAC1D,wBAAwB;IACxB,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,6DAA6D;IAC7D,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,IAAI,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,uCAAuC;IACvC,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,+CAA+C;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;IACvD,CAAC;IAED,gBAAgB;IAChB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,qCAAqC;IACrC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,uBAAuB;IACvB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,OAAO,4BAA4B,CAAC,IAAI,CAAC,GAAG,CAAC;QAC3C,CAAC,CAAC,IAAI,GAAG,EAAE;QACX,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC;AACjC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAU;IACvC,OAAO,SAAS,CAAC,KAAK,CAAC,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAU;IACpC,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,QAAQ,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAU;IACpC,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,IAAI,KAAK,OAAO,IAAI,IAAI,KAAK,QAAQ,CAAC;AAC/C,CAAC"}
|
|
@@ -12,6 +12,7 @@ import { BooleanModule } from "./modules/standard/boolean_module.js";
|
|
|
12
12
|
import { JsonModule } from "./modules/standard/json_module.js";
|
|
13
13
|
import { DateTimeModule } from "./modules/standard/datetime_module.js";
|
|
14
14
|
import { serializeValue, deserializeValue, serializeStack, deserializeStack } from "../websocket/serializer.js";
|
|
15
|
+
import { pathSegmentForKey } from "../common/type_utils.js";
|
|
15
16
|
/**
|
|
16
17
|
* StartModuleWord - Handles module creation and switching
|
|
17
18
|
*
|
|
@@ -894,13 +895,13 @@ export function dup_interpreter(interp) {
|
|
|
894
895
|
*/
|
|
895
896
|
export function export_state(interp) {
|
|
896
897
|
const internal = interp;
|
|
897
|
-
// Serialize the stack
|
|
898
|
-
const stack = serializeStack(internal.stack.get_items());
|
|
898
|
+
// Serialize the stack (annotate path so errors point at the offending stack entry)
|
|
899
|
+
const stack = serializeStack(internal.stack.get_items(), 'stack:');
|
|
899
900
|
// Serialize variables
|
|
900
901
|
const variables = {};
|
|
901
902
|
const appModule = internal.app_module;
|
|
902
903
|
for (const [name, variable] of Object.entries(appModule.variables)) {
|
|
903
|
-
variables[name] = serializeValue(variable.get_value());
|
|
904
|
+
variables[name] = serializeValue(variable.get_value(), `var:${pathSegmentForKey(name)}`);
|
|
904
905
|
}
|
|
905
906
|
// Collect source text from user-defined words
|
|
906
907
|
const word_definitions = [];
|