@forthix/forthic 0.7.0 → 0.7.2
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/type_utils.js.map +1 -1
- package/dist/cjs/forthic/interpreter.d.ts +2 -1
- package/dist/cjs/forthic/interpreter.js +10 -0
- package/dist/cjs/forthic/interpreter.js.map +1 -1
- package/dist/cjs/forthic/literals.d.ts +0 -1
- package/dist/cjs/forthic/literals.js +14 -15
- package/dist/cjs/forthic/literals.js.map +1 -1
- package/dist/cjs/forthic/modules/standard/datetime_module.d.ts +0 -1
- package/dist/cjs/forthic/modules/standard/datetime_module.js +19 -20
- package/dist/cjs/forthic/modules/standard/datetime_module.js.map +1 -1
- package/dist/cjs/forthic/utils.d.ts +0 -1
- package/dist/cjs/forthic/utils.js +1 -2
- package/dist/cjs/forthic/utils.js.map +1 -1
- package/dist/cjs/grpc/serializer.js +3 -4
- package/dist/cjs/grpc/serializer.js.map +1 -1
- package/dist/cjs/grpc/server.test.d.ts +1 -0
- package/dist/cjs/grpc/server.test.js +156 -0
- package/dist/cjs/grpc/server.test.js.map +1 -0
- package/dist/cjs/grpc/temporal_utils.d.ts +36 -0
- package/dist/cjs/grpc/temporal_utils.js +80 -0
- package/dist/cjs/grpc/temporal_utils.js.map +1 -0
- package/dist/cjs/test-setup.d.ts +1 -0
- package/dist/cjs/test-setup.js +4 -0
- package/dist/cjs/test-setup.js.map +1 -0
- package/dist/cjs/websocket/action_cable_client.d.ts +106 -0
- package/dist/cjs/websocket/action_cable_client.js +269 -0
- package/dist/cjs/websocket/action_cable_client.js.map +1 -0
- package/dist/cjs/websocket/client.d.ts +103 -0
- package/dist/cjs/websocket/client.js +266 -0
- package/dist/cjs/websocket/client.js.map +1 -0
- package/dist/cjs/websocket/remote_module.d.ts +68 -0
- package/dist/cjs/websocket/remote_module.js +107 -0
- package/dist/cjs/websocket/remote_module.js.map +1 -0
- package/dist/cjs/websocket/remote_word.d.ts +53 -0
- package/dist/cjs/websocket/remote_word.js +93 -0
- package/dist/cjs/websocket/remote_word.js.map +1 -0
- package/dist/cjs/websocket/runtime_manager.d.ts +69 -0
- package/dist/cjs/websocket/runtime_manager.js +112 -0
- package/dist/cjs/websocket/runtime_manager.js.map +1 -0
- package/dist/cjs/websocket/serializer.js +3 -4
- package/dist/cjs/websocket/serializer.js.map +1 -1
- package/dist/esm/common/type_utils.js.map +1 -1
- package/dist/esm/forthic/interpreter.d.ts +2 -1
- package/dist/esm/forthic/interpreter.js +11 -1
- package/dist/esm/forthic/interpreter.js.map +1 -1
- package/dist/esm/forthic/literals.d.ts +0 -1
- package/dist/esm/forthic/literals.js +0 -1
- package/dist/esm/forthic/literals.js.map +1 -1
- package/dist/esm/forthic/modules/standard/datetime_module.d.ts +0 -1
- package/dist/esm/forthic/modules/standard/datetime_module.js +0 -1
- package/dist/esm/forthic/modules/standard/datetime_module.js.map +1 -1
- package/dist/esm/forthic/utils.d.ts +0 -1
- package/dist/esm/forthic/utils.js +0 -1
- package/dist/esm/forthic/utils.js.map +1 -1
- package/dist/esm/grpc/serializer.js +0 -1
- package/dist/esm/grpc/serializer.js.map +1 -1
- package/dist/esm/grpc/server.test.d.ts +1 -0
- package/dist/esm/grpc/server.test.js +121 -0
- package/dist/esm/grpc/server.test.js.map +1 -0
- package/dist/esm/grpc/temporal_utils.d.ts +36 -0
- package/dist/esm/grpc/temporal_utils.js +72 -0
- package/dist/esm/grpc/temporal_utils.js.map +1 -0
- package/dist/esm/test-setup.d.ts +1 -0
- package/dist/esm/test-setup.js +2 -0
- package/dist/esm/test-setup.js.map +1 -0
- package/dist/esm/websocket/action_cable_client.d.ts +106 -0
- package/dist/esm/websocket/action_cable_client.js +265 -0
- package/dist/esm/websocket/action_cable_client.js.map +1 -0
- package/dist/esm/websocket/client.d.ts +103 -0
- package/dist/esm/websocket/client.js +262 -0
- package/dist/esm/websocket/client.js.map +1 -0
- package/dist/esm/websocket/remote_module.d.ts +68 -0
- package/dist/esm/websocket/remote_module.js +103 -0
- package/dist/esm/websocket/remote_module.js.map +1 -0
- package/dist/esm/websocket/remote_word.d.ts +53 -0
- package/dist/esm/websocket/remote_word.js +89 -0
- package/dist/esm/websocket/remote_word.js.map +1 -0
- package/dist/esm/websocket/runtime_manager.d.ts +69 -0
- package/dist/esm/websocket/runtime_manager.js +108 -0
- package/dist/esm/websocket/runtime_manager.js.map +1 -0
- package/dist/esm/websocket/serializer.js +0 -1
- package/dist/esm/websocket/serializer.js.map +1 -1
- package/package.json +3 -2
- package/dist/cjs/forthic/decorators/schemaUtils.d.ts +0 -70
- package/dist/cjs/forthic/decorators/schemaUtils.js +0 -77
- package/dist/cjs/forthic/decorators/schemaUtils.js.map +0 -1
- package/dist/cjs/forthic/decorators/stackEffect.d.ts +0 -63
- package/dist/cjs/forthic/decorators/stackEffect.js +0 -179
- package/dist/cjs/forthic/decorators/stackEffect.js.map +0 -1
- package/dist/esm/forthic/decorators/schemaUtils.d.ts +0 -70
- package/dist/esm/forthic/decorators/schemaUtils.js +0 -72
- package/dist/esm/forthic/decorators/schemaUtils.js.map +0 -1
- package/dist/esm/forthic/decorators/stackEffect.d.ts +0 -63
- package/dist/esm/forthic/decorators/stackEffect.js +0 -174
- package/dist/esm/forthic/decorators/stackEffect.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"action_cable_client.js","sourceRoot":"","sources":["../../../src/websocket/action_cable_client.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,mDAA+E;AAC/E,2CAAiD;AAoIjD;;;;GAIG;AACH,MAAa,iBAAiB;IACpB,EAAE,CAAa;IACf,MAAM,CAAoC;IAC1C,eAAe,GAAgC,IAAI,GAAG,EAAE,CAAC;IACzD,SAAS,GAAW,CAAC,CAAC;IACtB,SAAS,GAAY,KAAK,CAAC;IAC3B,iBAAiB,CAAiB;IAE1C,YAAY,MAA+B;QACzC,IAAI,CAAC,MAAM,GAAG;YACZ,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,KAAK;YAClC,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,IAAI;YACnC,cAAc,EAAE,MAAM,CAAC,cAAc,IAAI,IAAI;YAC7C,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,uBAAuB;SACnD,CAAC;QAEF,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED;;OAEG;IACK,OAAO;QACb,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,iBAAiB,CAAC;QAChC,CAAC;QAED,IAAI,CAAC,iBAAiB,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACvD,IAAI,CAAC;gBACH,IAAI,CAAC,EAAE,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAEzC,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,GAAG,EAAE;oBACpB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;oBAEtB,mCAAmC;oBACnC,MAAM,gBAAgB,GAAG;wBACvB,OAAO,EAAE,WAAW;wBACpB,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;4BACzB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;4BAC5B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;yBAC/B,CAAC;qBACH,CAAC;oBACF,IAAI,CAAC,EAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC;oBAEhD,OAAO,EAAE,CAAC;gBACZ,CAAC,CAAC;gBAEF,IAAI,CAAC,EAAE,CAAC,SAAS,GAAG,CAAC,KAAmB,EAAE,EAAE;oBAC1C,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;gBAC5B,CAAC,CAAC;gBAEF,IAAI,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,KAAY,EAAE,EAAE;oBACjC,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;oBACzC,MAAM,CAAC,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC,CAAC;gBAClD,CAAC,CAAC;gBAEF,IAAI,CAAC,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE;oBACrB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;oBACvB,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAC;oBAEnC,8BAA8B;oBAC9B,KAAK,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,EAAE,CAAC;wBAC3D,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;oBAC3D,CAAC;oBACD,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;oBAE7B,+BAA+B;oBAC/B,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;wBAC1B,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;oBAC/D,CAAC;gBACH,CAAC,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAC;YAChB,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;IAED;;OAEG;IACK,aAAa,CAAC,KAAmB;QACvC,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAEpC,sCAAsC;YACtC,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,sBAAsB,EAAE,CAAC;gBAC5F,OAAO;YACT,CAAC;YAED,uDAAuD;YACvD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;YAErC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;gBAChB,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,OAAO,CAAC,CAAC;gBACtD,OAAO;YACT,CAAC;YAED,oCAAoC;YACpC,IAAI,OAAO,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;gBAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;gBACrD,IAAI,OAAO,EAAE,UAAU,EAAE,CAAC;oBACxB,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACvC,CAAC;gBACD,OAAO;YACT,CAAC;YAED,yBAAyB;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACrD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,wCAAwC,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;gBACnE,OAAO;YACT,CAAC;YAED,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;gBAClB,OAAO,CAAC,MAAM,CAAC,IAAI,8BAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC;YACxD,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAClC,CAAC;YAED,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC1C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED;;OAEG;IACK,aAAa;QACnB,OAAO,OAAO,EAAE,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;IACjD,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,WAAW,CAAI,OAAoB;QAC/C,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAE7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YAE1D,qCAAqC;YACrC,MAAM,kBAAkB,GAAG;gBACzB,OAAO,EAAE,SAAS;gBAClB,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;oBACzB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;iBAC7B,CAAC;gBACF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;aAC9B,CAAC;YAEF,IAAI,CAAC,EAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,oBAAoB,CAChC,OAAoB,EACpB,UAA+C;QAE/C,MAAM,IAAI,CAAC,eAAe,EAAE,CAAC;QAE7B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;YAEtE,qCAAqC;YACrC,MAAM,kBAAkB,GAAG;gBACzB,OAAO,EAAE,SAAS;gBAClB,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC;oBACzB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;iBAC7B,CAAC;gBACF,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;aAC9B,CAAC;YAEF,IAAI,CAAC,EAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,eAAe;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QACvB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,IAAY,EAAE,KAAY;QAC1C,MAAM,OAAO,GAAuB;YAClC,IAAI,EAAE,cAAc;YACpB,EAAE,EAAE,IAAI,CAAC,aAAa,EAAE;YACxB,MAAM,EAAE;gBACN,IAAI;gBACJ,KAAK,EAAE,IAAA,8BAAc,EAAC,KAAK,CAAC;aAC7B;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAA0B,OAAO,CAAC,CAAC;QACxE,OAAO,IAAA,gCAAgB,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,eAAe,CAAC,KAAe,EAAE,KAAY;QACjD,MAAM,OAAO,GAA2B;YACtC,IAAI,EAAE,kBAAkB;YACxB,EAAE,EAAE,IAAI,CAAC,aAAa,EAAE;YACxB,MAAM,EAAE;gBACN,KAAK;gBACL,KAAK,EAAE,IAAA,8BAAc,EAAC,KAAK,CAAC;aAC7B;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAA0B,OAAO,CAAC,CAAC;QACxE,OAAO,IAAA,gCAAgB,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,MAAM,OAAO,GAAuB;YAClC,IAAI,EAAE,cAAc;YACpB,EAAE,EAAE,IAAI,CAAC,aAAa,EAAE;SACzB,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,WAAW,CAA+B,OAAO,CAAC,CAAC;QAC7E,OAAO,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;IAC9B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,aAAa,CAAC,UAAkB;QACpC,MAAM,OAAO,GAAyB;YACpC,IAAI,EAAE,iBAAiB;YACvB,EAAE,EAAE,IAAI,CAAC,aAAa,EAAE;YACxB,MAAM,EAAE;gBACN,WAAW,EAAE,UAAU;aACxB;SACF,CAAC;QAEF,OAAO,MAAM,IAAI,CAAC,WAAW,CAAa,OAAO,CAAC,CAAC;IACrD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CACpB,IAAY,EACZ,KAAY,EACZ,UAA+C;QAE/C,MAAM,OAAO,GAA4B;YACvC,IAAI,EAAE,mBAAmB;YACzB,EAAE,EAAE,IAAI,CAAC,aAAa,EAAE;YACxB,MAAM,EAAE;gBACN,IAAI;gBACJ,KAAK,EAAE,IAAA,8BAAc,EAAC,KAAK,CAAC;aAC7B;SACF,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAA0B,OAAO,EAAE,UAAU,CAAC,CAAC;QAC7F,OAAO,IAAA,gCAAgB,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,yBAAyB;YACxD,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,EAAE,GAAG,SAAS,CAAC;YACpB,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACzB,CAAC;IACH,CAAC;IAED;;OAEG;IACH,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;CACF;AA1SD,8CA0SC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket Client for Forthic
|
|
3
|
+
* Browser-compatible client that mirrors GrpcClient API
|
|
4
|
+
* Connects to Rails ActionCable server and executes remote words
|
|
5
|
+
*/
|
|
6
|
+
import { StackValue } from './serializer.js';
|
|
7
|
+
export interface ModuleSummary {
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
word_count: number;
|
|
11
|
+
}
|
|
12
|
+
export interface WordInfo {
|
|
13
|
+
name: string;
|
|
14
|
+
stack_effect: string;
|
|
15
|
+
description: string;
|
|
16
|
+
}
|
|
17
|
+
export interface ModuleInfo {
|
|
18
|
+
module_name: string;
|
|
19
|
+
words: WordInfo[];
|
|
20
|
+
}
|
|
21
|
+
export interface ProgressUpdate {
|
|
22
|
+
step: number;
|
|
23
|
+
total_steps: number;
|
|
24
|
+
current_word: string;
|
|
25
|
+
message?: string;
|
|
26
|
+
partial_stack?: StackValue[];
|
|
27
|
+
}
|
|
28
|
+
export interface WebSocketClientConfig {
|
|
29
|
+
url: string;
|
|
30
|
+
timezone?: string;
|
|
31
|
+
reconnect?: boolean;
|
|
32
|
+
reconnectDelay?: number;
|
|
33
|
+
channel?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* WebSocket client for executing words in remote Forthic runtimes
|
|
37
|
+
* Mirrors the GrpcClient API for compatibility
|
|
38
|
+
*/
|
|
39
|
+
export declare class WebSocketClient {
|
|
40
|
+
private ws?;
|
|
41
|
+
private config;
|
|
42
|
+
private pendingRequests;
|
|
43
|
+
private messageId;
|
|
44
|
+
private connected;
|
|
45
|
+
private connectionPromise?;
|
|
46
|
+
constructor(config: WebSocketClientConfig);
|
|
47
|
+
/**
|
|
48
|
+
* Connect to the WebSocket server
|
|
49
|
+
*/
|
|
50
|
+
private connect;
|
|
51
|
+
/**
|
|
52
|
+
* Handle incoming WebSocket messages
|
|
53
|
+
*/
|
|
54
|
+
private handleMessage;
|
|
55
|
+
/**
|
|
56
|
+
* Generate next message ID
|
|
57
|
+
*/
|
|
58
|
+
private nextMessageId;
|
|
59
|
+
/**
|
|
60
|
+
* Send a request and wait for response
|
|
61
|
+
*/
|
|
62
|
+
private sendRequest;
|
|
63
|
+
/**
|
|
64
|
+
* Send a streaming request with progress callbacks
|
|
65
|
+
*/
|
|
66
|
+
private sendStreamingRequest;
|
|
67
|
+
/**
|
|
68
|
+
* Ensure WebSocket is connected
|
|
69
|
+
*/
|
|
70
|
+
private ensureConnected;
|
|
71
|
+
/**
|
|
72
|
+
* Execute a word in the remote runtime
|
|
73
|
+
* Mirrors GrpcClient.executeWord
|
|
74
|
+
*/
|
|
75
|
+
executeWord(word: string, stack: any[]): Promise<any[]>;
|
|
76
|
+
/**
|
|
77
|
+
* Execute a sequence of words (batched execution)
|
|
78
|
+
* Mirrors GrpcClient.executeSequence
|
|
79
|
+
*/
|
|
80
|
+
executeSequence(words: string[], stack: any[]): Promise<any[]>;
|
|
81
|
+
/**
|
|
82
|
+
* List available runtime-specific modules
|
|
83
|
+
* Mirrors GrpcClient.listModules
|
|
84
|
+
*/
|
|
85
|
+
listModules(): Promise<ModuleSummary[]>;
|
|
86
|
+
/**
|
|
87
|
+
* Get detailed information about a specific module
|
|
88
|
+
* Mirrors GrpcClient.getModuleInfo
|
|
89
|
+
*/
|
|
90
|
+
getModuleInfo(moduleName: string): Promise<ModuleInfo>;
|
|
91
|
+
/**
|
|
92
|
+
* Execute code with streaming progress updates (NEW capability)
|
|
93
|
+
*/
|
|
94
|
+
streamingExecute(code: string, stack: any[], onProgress?: (progress: ProgressUpdate) => void): Promise<any[]>;
|
|
95
|
+
/**
|
|
96
|
+
* Close the WebSocket connection
|
|
97
|
+
*/
|
|
98
|
+
close(): void;
|
|
99
|
+
/**
|
|
100
|
+
* Check if the client is connected
|
|
101
|
+
*/
|
|
102
|
+
isConnected(): boolean;
|
|
103
|
+
}
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WebSocket Client for Forthic
|
|
4
|
+
* Browser-compatible client that mirrors GrpcClient API
|
|
5
|
+
* Connects to Rails ActionCable server and executes remote words
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.WebSocketClient = void 0;
|
|
9
|
+
const serializer_js_1 = require("./serializer.js");
|
|
10
|
+
const errors_js_1 = require("./errors.js");
|
|
11
|
+
/**
|
|
12
|
+
* WebSocket client for executing words in remote Forthic runtimes
|
|
13
|
+
* Mirrors the GrpcClient API for compatibility
|
|
14
|
+
*/
|
|
15
|
+
class WebSocketClient {
|
|
16
|
+
ws;
|
|
17
|
+
config;
|
|
18
|
+
pendingRequests = new Map();
|
|
19
|
+
messageId = 0;
|
|
20
|
+
connected = false;
|
|
21
|
+
connectionPromise;
|
|
22
|
+
constructor(config) {
|
|
23
|
+
this.config = {
|
|
24
|
+
url: config.url,
|
|
25
|
+
timezone: config.timezone || 'UTC',
|
|
26
|
+
reconnect: config.reconnect ?? true,
|
|
27
|
+
reconnectDelay: config.reconnectDelay || 3000,
|
|
28
|
+
channel: config.channel || 'ForthicRuntimeChannel',
|
|
29
|
+
};
|
|
30
|
+
this.connect();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Connect to the WebSocket server
|
|
34
|
+
*/
|
|
35
|
+
connect() {
|
|
36
|
+
if (this.connectionPromise) {
|
|
37
|
+
return this.connectionPromise;
|
|
38
|
+
}
|
|
39
|
+
this.connectionPromise = new Promise((resolve, reject) => {
|
|
40
|
+
try {
|
|
41
|
+
this.ws = new WebSocket(this.config.url);
|
|
42
|
+
this.ws.onopen = () => {
|
|
43
|
+
this.connected = true;
|
|
44
|
+
// Subscribe to ActionCable channel
|
|
45
|
+
const subscribeMessage = {
|
|
46
|
+
command: 'subscribe',
|
|
47
|
+
identifier: JSON.stringify({
|
|
48
|
+
channel: this.config.channel,
|
|
49
|
+
timezone: this.config.timezone,
|
|
50
|
+
}),
|
|
51
|
+
};
|
|
52
|
+
this.ws.send(JSON.stringify(subscribeMessage));
|
|
53
|
+
resolve();
|
|
54
|
+
};
|
|
55
|
+
this.ws.onmessage = (event) => {
|
|
56
|
+
this.handleMessage(event);
|
|
57
|
+
};
|
|
58
|
+
this.ws.onerror = (error) => {
|
|
59
|
+
console.error('WebSocket error:', error);
|
|
60
|
+
reject(new Error('WebSocket connection error'));
|
|
61
|
+
};
|
|
62
|
+
this.ws.onclose = () => {
|
|
63
|
+
this.connected = false;
|
|
64
|
+
this.connectionPromise = undefined;
|
|
65
|
+
// Reject all pending requests
|
|
66
|
+
for (const [id, pending] of this.pendingRequests.entries()) {
|
|
67
|
+
pending.reject(new Error('WebSocket connection closed'));
|
|
68
|
+
}
|
|
69
|
+
this.pendingRequests.clear();
|
|
70
|
+
// Attempt reconnect if enabled
|
|
71
|
+
if (this.config.reconnect) {
|
|
72
|
+
setTimeout(() => this.connect(), this.config.reconnectDelay);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
reject(error);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return this.connectionPromise;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Handle incoming WebSocket messages
|
|
84
|
+
*/
|
|
85
|
+
handleMessage(event) {
|
|
86
|
+
try {
|
|
87
|
+
const data = JSON.parse(event.data);
|
|
88
|
+
// Handle ActionCable control messages
|
|
89
|
+
if (data.type === 'welcome' || data.type === 'ping' || data.type === 'confirm_subscription') {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
// Extract the actual message from ActionCable envelope
|
|
93
|
+
const message = data.message || data;
|
|
94
|
+
if (!message.id) {
|
|
95
|
+
console.warn('Received message without ID:', message);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Handle streaming progress updates
|
|
99
|
+
if (message.type === 'streaming_progress') {
|
|
100
|
+
const pending = this.pendingRequests.get(message.id);
|
|
101
|
+
if (pending?.onProgress) {
|
|
102
|
+
pending.onProgress(message.progress);
|
|
103
|
+
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Handle final responses
|
|
107
|
+
const pending = this.pendingRequests.get(message.id);
|
|
108
|
+
if (!pending) {
|
|
109
|
+
console.warn('Received response for unknown request:', message.id);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
if (message.error) {
|
|
113
|
+
pending.reject(new errors_js_1.RemoteRuntimeError(message.error));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
pending.resolve(message.result);
|
|
117
|
+
}
|
|
118
|
+
this.pendingRequests.delete(message.id);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
console.error('Error handling WebSocket message:', error);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Generate next message ID
|
|
126
|
+
*/
|
|
127
|
+
nextMessageId() {
|
|
128
|
+
return `msg-${++this.messageId}-${Date.now()}`;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Send a request and wait for response
|
|
132
|
+
*/
|
|
133
|
+
async sendRequest(message) {
|
|
134
|
+
await this.ensureConnected();
|
|
135
|
+
return new Promise((resolve, reject) => {
|
|
136
|
+
this.pendingRequests.set(message.id, { resolve, reject });
|
|
137
|
+
// Wrap message in ActionCable format
|
|
138
|
+
const actionCableMessage = {
|
|
139
|
+
command: 'message',
|
|
140
|
+
identifier: JSON.stringify({
|
|
141
|
+
channel: this.config.channel,
|
|
142
|
+
}),
|
|
143
|
+
data: JSON.stringify(message),
|
|
144
|
+
};
|
|
145
|
+
this.ws.send(JSON.stringify(actionCableMessage));
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Send a streaming request with progress callbacks
|
|
150
|
+
*/
|
|
151
|
+
async sendStreamingRequest(message, onProgress) {
|
|
152
|
+
await this.ensureConnected();
|
|
153
|
+
return new Promise((resolve, reject) => {
|
|
154
|
+
this.pendingRequests.set(message.id, { resolve, reject, onProgress });
|
|
155
|
+
// Wrap message in ActionCable format
|
|
156
|
+
const actionCableMessage = {
|
|
157
|
+
command: 'message',
|
|
158
|
+
identifier: JSON.stringify({
|
|
159
|
+
channel: this.config.channel,
|
|
160
|
+
}),
|
|
161
|
+
data: JSON.stringify(message),
|
|
162
|
+
};
|
|
163
|
+
this.ws.send(JSON.stringify(actionCableMessage));
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Ensure WebSocket is connected
|
|
168
|
+
*/
|
|
169
|
+
async ensureConnected() {
|
|
170
|
+
if (!this.connected) {
|
|
171
|
+
await this.connect();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Execute a word in the remote runtime
|
|
176
|
+
* Mirrors GrpcClient.executeWord
|
|
177
|
+
*/
|
|
178
|
+
async executeWord(word, stack) {
|
|
179
|
+
const message = {
|
|
180
|
+
type: 'execute_word',
|
|
181
|
+
id: this.nextMessageId(),
|
|
182
|
+
params: {
|
|
183
|
+
word,
|
|
184
|
+
stack: (0, serializer_js_1.serializeStack)(stack),
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
const result = await this.sendRequest(message);
|
|
188
|
+
return (0, serializer_js_1.deserializeStack)(result.stack);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Execute a sequence of words (batched execution)
|
|
192
|
+
* Mirrors GrpcClient.executeSequence
|
|
193
|
+
*/
|
|
194
|
+
async executeSequence(words, stack) {
|
|
195
|
+
const message = {
|
|
196
|
+
type: 'execute_sequence',
|
|
197
|
+
id: this.nextMessageId(),
|
|
198
|
+
params: {
|
|
199
|
+
words,
|
|
200
|
+
stack: (0, serializer_js_1.serializeStack)(stack),
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
const result = await this.sendRequest(message);
|
|
204
|
+
return (0, serializer_js_1.deserializeStack)(result.stack);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* List available runtime-specific modules
|
|
208
|
+
* Mirrors GrpcClient.listModules
|
|
209
|
+
*/
|
|
210
|
+
async listModules() {
|
|
211
|
+
const message = {
|
|
212
|
+
type: 'list_modules',
|
|
213
|
+
id: this.nextMessageId(),
|
|
214
|
+
};
|
|
215
|
+
const result = await this.sendRequest(message);
|
|
216
|
+
return result.modules || [];
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Get detailed information about a specific module
|
|
220
|
+
* Mirrors GrpcClient.getModuleInfo
|
|
221
|
+
*/
|
|
222
|
+
async getModuleInfo(moduleName) {
|
|
223
|
+
const message = {
|
|
224
|
+
type: 'get_module_info',
|
|
225
|
+
id: this.nextMessageId(),
|
|
226
|
+
params: {
|
|
227
|
+
module_name: moduleName,
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
return await this.sendRequest(message);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Execute code with streaming progress updates (NEW capability)
|
|
234
|
+
*/
|
|
235
|
+
async streamingExecute(code, stack, onProgress) {
|
|
236
|
+
const message = {
|
|
237
|
+
type: 'streaming_execute',
|
|
238
|
+
id: this.nextMessageId(),
|
|
239
|
+
params: {
|
|
240
|
+
code,
|
|
241
|
+
stack: (0, serializer_js_1.serializeStack)(stack),
|
|
242
|
+
},
|
|
243
|
+
};
|
|
244
|
+
const result = await this.sendStreamingRequest(message, onProgress);
|
|
245
|
+
return (0, serializer_js_1.deserializeStack)(result.stack);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Close the WebSocket connection
|
|
249
|
+
*/
|
|
250
|
+
close() {
|
|
251
|
+
if (this.ws) {
|
|
252
|
+
this.config.reconnect = false; // Disable auto-reconnect
|
|
253
|
+
this.ws.close();
|
|
254
|
+
this.ws = undefined;
|
|
255
|
+
this.connected = false;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Check if the client is connected
|
|
260
|
+
*/
|
|
261
|
+
isConnected() {
|
|
262
|
+
return this.connected;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
exports.WebSocketClient = WebSocketClient;
|
|
266
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/websocket/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocketRemoteModule - Module that wraps runtime-specific words from a remote runtime
|
|
3
|
+
* Mirrors RemoteModule from gRPC implementation
|
|
4
|
+
*/
|
|
5
|
+
import { Module } from '../forthic/module.js';
|
|
6
|
+
import { Interpreter } from '../forthic/interpreter.js';
|
|
7
|
+
import { ActionCableClient, type ModuleInfo } from './action_cable_client.js';
|
|
8
|
+
/**
|
|
9
|
+
* WebSocketRemoteModule - Module containing proxy words that execute in a remote runtime
|
|
10
|
+
*
|
|
11
|
+
* This module discovers words from a remote runtime (e.g., pandas module in Ruby)
|
|
12
|
+
* and creates WebSocketRemoteWord proxies for each discovered word. When used in TypeScript
|
|
13
|
+
* Forthic code, these words execute in the remote runtime via ActionCable.
|
|
14
|
+
*
|
|
15
|
+
* Example usage:
|
|
16
|
+
* ```typescript
|
|
17
|
+
* const client = new ActionCableClient({ url: 'ws://localhost:3000/cable' });
|
|
18
|
+
* const pandasModule = new WebSocketRemoteModule('pandas', client, 'rails');
|
|
19
|
+
* await pandasModule.initialize();
|
|
20
|
+
* interp.register_module(pandasModule);
|
|
21
|
+
* interp.use_modules(['pandas']);
|
|
22
|
+
*
|
|
23
|
+
* // Now pandas words execute in Rails runtime
|
|
24
|
+
* await interp.run(`
|
|
25
|
+
* [ [[.name "Alice"] [.age 30]] REC]
|
|
26
|
+
* DF-FROM-RECORDS # Executes in Rails!
|
|
27
|
+
* `);
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare class WebSocketRemoteModule extends Module {
|
|
31
|
+
private client;
|
|
32
|
+
private runtimeName;
|
|
33
|
+
private initialized;
|
|
34
|
+
private moduleInfo;
|
|
35
|
+
/**
|
|
36
|
+
* @param moduleName - Name of the module in the remote runtime (e.g., "pandas")
|
|
37
|
+
* @param client - ActionCable client connected to the remote runtime
|
|
38
|
+
* @param runtimeName - Name of the runtime (e.g., "rails") for debugging
|
|
39
|
+
*/
|
|
40
|
+
constructor(moduleName: string, client: ActionCableClient, runtimeName?: string);
|
|
41
|
+
/**
|
|
42
|
+
* Initialize the module by discovering words from the remote runtime
|
|
43
|
+
*
|
|
44
|
+
* This must be called before the module is registered with an interpreter.
|
|
45
|
+
* It fetches the module metadata and creates WebSocketRemoteWord proxies for each word.
|
|
46
|
+
*/
|
|
47
|
+
initialize(): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* Override set_interp to ensure module is initialized
|
|
50
|
+
*/
|
|
51
|
+
set_interp(interp: Interpreter): void;
|
|
52
|
+
/**
|
|
53
|
+
* Get the module metadata from the remote runtime
|
|
54
|
+
*/
|
|
55
|
+
getModuleInfo(): ModuleInfo | null;
|
|
56
|
+
/**
|
|
57
|
+
* Get runtime name for debugging
|
|
58
|
+
*/
|
|
59
|
+
getRuntimeName(): string;
|
|
60
|
+
/**
|
|
61
|
+
* Check if module is initialized
|
|
62
|
+
*/
|
|
63
|
+
isInitialized(): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Get count of discovered words
|
|
66
|
+
*/
|
|
67
|
+
getWordCount(): number;
|
|
68
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.WebSocketRemoteModule = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* WebSocketRemoteModule - Module that wraps runtime-specific words from a remote runtime
|
|
6
|
+
* Mirrors RemoteModule from gRPC implementation
|
|
7
|
+
*/
|
|
8
|
+
const module_js_1 = require("../forthic/module.js");
|
|
9
|
+
const remote_word_js_1 = require("./remote_word.js");
|
|
10
|
+
/**
|
|
11
|
+
* WebSocketRemoteModule - Module containing proxy words that execute in a remote runtime
|
|
12
|
+
*
|
|
13
|
+
* This module discovers words from a remote runtime (e.g., pandas module in Ruby)
|
|
14
|
+
* and creates WebSocketRemoteWord proxies for each discovered word. When used in TypeScript
|
|
15
|
+
* Forthic code, these words execute in the remote runtime via ActionCable.
|
|
16
|
+
*
|
|
17
|
+
* Example usage:
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const client = new ActionCableClient({ url: 'ws://localhost:3000/cable' });
|
|
20
|
+
* const pandasModule = new WebSocketRemoteModule('pandas', client, 'rails');
|
|
21
|
+
* await pandasModule.initialize();
|
|
22
|
+
* interp.register_module(pandasModule);
|
|
23
|
+
* interp.use_modules(['pandas']);
|
|
24
|
+
*
|
|
25
|
+
* // Now pandas words execute in Rails runtime
|
|
26
|
+
* await interp.run(`
|
|
27
|
+
* [ [[.name "Alice"] [.age 30]] REC]
|
|
28
|
+
* DF-FROM-RECORDS # Executes in Rails!
|
|
29
|
+
* `);
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
class WebSocketRemoteModule extends module_js_1.Module {
|
|
33
|
+
client;
|
|
34
|
+
runtimeName;
|
|
35
|
+
initialized = false;
|
|
36
|
+
moduleInfo = null;
|
|
37
|
+
/**
|
|
38
|
+
* @param moduleName - Name of the module in the remote runtime (e.g., "pandas")
|
|
39
|
+
* @param client - ActionCable client connected to the remote runtime
|
|
40
|
+
* @param runtimeName - Name of the runtime (e.g., "rails") for debugging
|
|
41
|
+
*/
|
|
42
|
+
constructor(moduleName, client, runtimeName = 'remote') {
|
|
43
|
+
super(moduleName);
|
|
44
|
+
this.client = client;
|
|
45
|
+
this.runtimeName = runtimeName;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Initialize the module by discovering words from the remote runtime
|
|
49
|
+
*
|
|
50
|
+
* This must be called before the module is registered with an interpreter.
|
|
51
|
+
* It fetches the module metadata and creates WebSocketRemoteWord proxies for each word.
|
|
52
|
+
*/
|
|
53
|
+
async initialize() {
|
|
54
|
+
if (this.initialized) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
// Discover module info from remote runtime
|
|
59
|
+
this.moduleInfo = await this.client.getModuleInfo(this.name);
|
|
60
|
+
// Create WebSocketRemoteWord for each discovered word
|
|
61
|
+
for (const wordInfo of this.moduleInfo.words) {
|
|
62
|
+
const remoteWord = new remote_word_js_1.WebSocketRemoteWord(wordInfo.name, this.client, this.runtimeName, this.name, wordInfo.stack_effect, wordInfo.description);
|
|
63
|
+
// Add as exportable word (visible when module is imported)
|
|
64
|
+
this.add_exportable_word(remoteWord);
|
|
65
|
+
}
|
|
66
|
+
this.initialized = true;
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
throw new Error(`Failed to initialize remote module '${this.name}' from ${this.runtimeName} runtime: ${error.message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Override set_interp to ensure module is initialized
|
|
74
|
+
*/
|
|
75
|
+
set_interp(interp) {
|
|
76
|
+
if (!this.initialized) {
|
|
77
|
+
throw new Error(`WebSocketRemoteModule '${this.name}' must be initialized before being registered with an interpreter. Call await module.initialize() first.`);
|
|
78
|
+
}
|
|
79
|
+
super.set_interp(interp);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Get the module metadata from the remote runtime
|
|
83
|
+
*/
|
|
84
|
+
getModuleInfo() {
|
|
85
|
+
return this.moduleInfo;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get runtime name for debugging
|
|
89
|
+
*/
|
|
90
|
+
getRuntimeName() {
|
|
91
|
+
return this.runtimeName;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Check if module is initialized
|
|
95
|
+
*/
|
|
96
|
+
isInitialized() {
|
|
97
|
+
return this.initialized;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Get count of discovered words
|
|
101
|
+
*/
|
|
102
|
+
getWordCount() {
|
|
103
|
+
return this.moduleInfo?.words?.length || 0;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.WebSocketRemoteModule = WebSocketRemoteModule;
|
|
107
|
+
//# sourceMappingURL=remote_module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remote_module.js","sourceRoot":"","sources":["../../../src/websocket/remote_module.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,oDAA8C;AAG9C,qDAAuD;AAEvD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAa,qBAAsB,SAAQ,kBAAM;IACvC,MAAM,CAAoB;IAC1B,WAAW,CAAS;IACpB,WAAW,GAAY,KAAK,CAAC;IAC7B,UAAU,GAAsB,IAAI,CAAC;IAE7C;;;;OAIG;IACH,YAAY,UAAkB,EAAE,MAAyB,EAAE,cAAsB,QAAQ;QACvF,KAAK,CAAC,UAAU,CAAC,CAAC;QAClB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QAED,IAAI,CAAC;YACH,2CAA2C;YAC3C,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAE7D,sDAAsD;YACtD,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;gBAC7C,MAAM,UAAU,GAAG,IAAI,oCAAmB,CACxC,QAAQ,CAAC,IAAI,EACb,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,WAAW,EAChB,IAAI,CAAC,IAAI,EACT,QAAQ,CAAC,YAAY,EACrB,QAAQ,CAAC,WAAW,CACrB,CAAC;gBAEF,2DAA2D;gBAC3D,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;YACvC,CAAC;YAED,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,uCAAuC,IAAI,CAAC,IAAI,UAAU,IAAI,CAAC,WAAW,aAAc,KAAe,CAAC,OAAO,EAAE,CAClH,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,UAAU,CAAC,MAAmB;QAC5B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,0BAA0B,IAAI,CAAC,IAAI,0GAA0G,CAC9I,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,aAAa;QACX,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC,CAAC;IAC7C,CAAC;CACF;AA9FD,sDA8FC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocketRemoteWord - Word that executes in a remote runtime via ActionCable
|
|
3
|
+
* Mirrors RemoteWord from gRPC implementation
|
|
4
|
+
*/
|
|
5
|
+
import { Word, RuntimeInfo } from '../forthic/module.js';
|
|
6
|
+
import { Interpreter } from '../forthic/interpreter.js';
|
|
7
|
+
import { ActionCableClient } from './action_cable_client.js';
|
|
8
|
+
/**
|
|
9
|
+
* WebSocketRemoteWord - Proxy word that delegates execution to a remote runtime
|
|
10
|
+
*
|
|
11
|
+
* When executed:
|
|
12
|
+
* 1. Captures current interpreter stack
|
|
13
|
+
* 2. Sends word name + stack to remote runtime via ActionCable
|
|
14
|
+
* 3. Replaces local stack with result stack from remote execution
|
|
15
|
+
*
|
|
16
|
+
* This allows seamless integration of remote runtime words
|
|
17
|
+
* into the local TypeScript interpreter.
|
|
18
|
+
*/
|
|
19
|
+
export declare class WebSocketRemoteWord extends Word {
|
|
20
|
+
private client;
|
|
21
|
+
private runtimeName;
|
|
22
|
+
private moduleName;
|
|
23
|
+
stackEffect: string;
|
|
24
|
+
description: string;
|
|
25
|
+
/**
|
|
26
|
+
* @param name - Word name (e.g., "DF_FROM_RECORDS")
|
|
27
|
+
* @param client - ActionCable client connected to remote runtime
|
|
28
|
+
* @param runtimeName - Name of remote runtime (e.g., "rails", "ruby")
|
|
29
|
+
* @param moduleName - Module name (e.g., "pandas")
|
|
30
|
+
* @param stackEffect - Stack notation (e.g., "( records:array -- df:DataFrame )")
|
|
31
|
+
* @param description - Human-readable description
|
|
32
|
+
*/
|
|
33
|
+
constructor(name: string, client: ActionCableClient, runtimeName: string, moduleName: string, stackEffect?: string, description?: string);
|
|
34
|
+
/**
|
|
35
|
+
* Execute word in remote runtime
|
|
36
|
+
*
|
|
37
|
+
* Captures entire stack, sends to remote runtime, and replaces stack with result.
|
|
38
|
+
*/
|
|
39
|
+
execute(interp: Interpreter): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Get runtime name for debugging/introspection
|
|
42
|
+
*/
|
|
43
|
+
getRuntimeName(): string;
|
|
44
|
+
/**
|
|
45
|
+
* Get module name for debugging/introspection
|
|
46
|
+
*/
|
|
47
|
+
getModuleName(): string;
|
|
48
|
+
/**
|
|
49
|
+
* Get runtime execution information
|
|
50
|
+
* RemoteWords are runtime-specific and can only execute in their designated runtime
|
|
51
|
+
*/
|
|
52
|
+
getRuntimeInfo(): RuntimeInfo;
|
|
53
|
+
}
|