lptp-mcp-server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +91 -0
  3. package/build/backends/gprolog.d.ts +32 -0
  4. package/build/backends/gprolog.d.ts.map +1 -0
  5. package/build/backends/gprolog.js +113 -0
  6. package/build/backends/gprolog.js.map +1 -0
  7. package/build/backends/registry.d.ts +15 -0
  8. package/build/backends/registry.d.ts.map +1 -0
  9. package/build/backends/registry.js +61 -0
  10. package/build/backends/registry.js.map +1 -0
  11. package/build/backends/scryer.d.ts +33 -0
  12. package/build/backends/scryer.d.ts.map +1 -0
  13. package/build/backends/scryer.js +71 -0
  14. package/build/backends/scryer.js.map +1 -0
  15. package/build/backends/swipl.d.ts +24 -0
  16. package/build/backends/swipl.d.ts.map +1 -0
  17. package/build/backends/swipl.js +73 -0
  18. package/build/backends/swipl.js.map +1 -0
  19. package/build/backends/types.d.ts +27 -0
  20. package/build/backends/types.d.ts.map +1 -0
  21. package/build/backends/types.js +3 -0
  22. package/build/backends/types.js.map +1 -0
  23. package/build/index.d.ts +3 -0
  24. package/build/index.d.ts.map +1 -0
  25. package/build/index.js +355 -0
  26. package/build/index.js.map +1 -0
  27. package/build/lptpExecutor.d.ts +19 -0
  28. package/build/lptpExecutor.d.ts.map +1 -0
  29. package/build/lptpExecutor.js +520 -0
  30. package/build/lptpExecutor.js.map +1 -0
  31. package/jest.config.js +11 -0
  32. package/mcp-config-example.json +12 -0
  33. package/package.json +41 -0
  34. package/src/__tests__/mcp_lptp_server.test.ts +97 -0
  35. package/src/backends/gprolog.ts +87 -0
  36. package/src/backends/registry.ts +70 -0
  37. package/src/backends/scryer.ts +83 -0
  38. package/src/backends/swipl.ts +88 -0
  39. package/src/backends/types.ts +36 -0
  40. package/src/index.ts +369 -0
  41. package/src/lptpExecutor.ts +551 -0
  42. package/tsconfig.json +26 -0
package/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Thierry Marianne
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Note: This package provides a Model Context Protocol (MCP) server interface
26
+ to LPTP (Logic Program Theorem Prover), originally developed by Robert F.
27
+ Staerk (1996). The LPTP Prolog source code (src/lptp.pl) is distributed
28
+ under its own license terms. This MIT license applies only to the MCP server
29
+ TypeScript code in this package.
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # lptp-mcp-server
2
+
3
+ An [MCP (Model Context Protocol)](https://modelcontextprotocol.io/) server that exposes [LPTP (Logic Program Theorem Prover)](https://www.sciencedirect.com/science/article/pii/S0743106698100060 "Stärk, R.F. (1998). The theoretical foundations of LPTP. Journal of Logic Programming, 36(3):241-269.") operations as tools — proof verification, tactic application, definition querying, and ground representation compilation. Any MCP-compatible client (Claude Code, Claude Desktop, etc.) can connect and use these tools to interactively construct and verify formal proofs of Prolog programs.
4
+
5
+ ## Prerequisites
6
+
7
+ - **Node.js** >= 18
8
+ - **LPTP source checkout** — the directory containing `src/lptp.pl` and the `lib/` hierarchy
9
+ - **At least one Prolog backend** on PATH:
10
+ - [SWI-Prolog](https://www.swi-prolog.org/) (`swipl`) — recommended, best resource-limit support
11
+ - [Scryer Prolog](https://www.scryer.pl/) (`scryer-prolog`) — ISO-compliant alternative
12
+ - GNU Prolog (`bin/lptp-gnu-prolog`) — pre-compiled binary with LPTP baked in
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install lptp-mcp-server
18
+ ```
19
+
20
+ Or install from a local checkout:
21
+
22
+ ```bash
23
+ cd etc/lptp-mcp-server
24
+ npm install
25
+ npm run build
26
+ ```
27
+
28
+ ## Configuration
29
+
30
+ ### Claude Code
31
+
32
+ Add to your `.mcp.json` (project or global):
33
+
34
+ ```json
35
+ {
36
+ "mcpServers": {
37
+ "lptp-server": {
38
+ "type": "stdio",
39
+ "command": "npx",
40
+ "args": ["lptp-mcp-server"],
41
+ "env": {
42
+ "LPTP_ROOT_DIR": "/path/to/your/lptp/checkout"
43
+ }
44
+ }
45
+ }
46
+ }
47
+ ```
48
+
49
+ ### Environment Variables
50
+
51
+ | Variable | Required | Description |
52
+ |----------|----------|-------------|
53
+ | `LPTP_ROOT_DIR` | Yes* | Path to the LPTP checkout root (directory containing `src/lptp.pl`). *If the server is installed inside the LPTP tree, it can auto-detect. |
54
+ | `LPTP_PROLOG_BACKEND` | No | Force a specific backend: `swipl`, `scryer`, or `gprolog`. Default: auto-detect in that order. |
55
+
56
+ ## Available Tools
57
+
58
+ | Tool | Description |
59
+ |------|-------------|
60
+ | `get_lptp_grammar` | Returns LPTP grammar summary for LLM reasoning |
61
+ | `verify_lemma` | Validates LPTP proof code (lemma/3, theorem/3) |
62
+ | `check_proof` | Runs `check/1` on a `.pr` proof file on disk |
63
+ | `apply_tactic` | Applies a tactic to a formula, returns derivation tree |
64
+ | `tactic_auto` | Automatic proof with configurable depth and resource limits |
65
+ | `tactic_case` | Case splitting on disjunctions |
66
+ | `tactic_comp` | Completion formula (fixed-point semantics) |
67
+ | `tactic_elim` | Predicate definition elimination |
68
+ | `tactic_ex` | Existential quantifier instantiation |
69
+ | `tactic_fact` | Apply a known fact (lemma, theorem, corollary) |
70
+ | `tactic_ind` | Structural induction |
71
+ | `tactic_indqf` | Quantifier-free induction |
72
+ | `tactic_tot` | Totality (termination) case splitting |
73
+ | `tactic_unfold` | Unfold an abbreviation or definition |
74
+ | `tactic_debug` | Show available formulas and assumptions in context |
75
+ | `print_definition` | Print completion definition (IND(P) axioms) of a predicate |
76
+ | `list_facts` | List known theorems/lemmas/corollaries about a predicate |
77
+ | `compile_gr` | Compile `.pl` to LPTP ground representation (`.gr`) |
78
+
79
+ ## Prolog Backend Selection
80
+
81
+ The server auto-detects backends in this order:
82
+
83
+ 1. **SWI-Prolog** (`swipl`) — full resource limits (time, inference, depth)
84
+ 2. **Scryer Prolog** (`scryer-prolog`) — inference limits only, Node.js timeout for time
85
+ 3. **GNU Prolog** (`bin/lptp-gnu-prolog`) — Node.js timeout only
86
+
87
+ Override with `LPTP_PROLOG_BACKEND=swipl` (or `scryer`, `gprolog`).
88
+
89
+ ## License
90
+
91
+ MIT — see [LICENSE](./LICENSE). The LPTP Prolog source (`src/lptp.pl`) has its own license (R.F. Staerk, 1996).
@@ -0,0 +1,32 @@
1
+ import type { PrologBackend, ResourceLimits } from './types';
2
+ /**
3
+ * GNU Prolog backend.
4
+ *
5
+ * CLI pattern (from Makefile line 839):
6
+ * cat ./src/allg.pl | ./bin/lptp-gnu-prolog
7
+ *
8
+ * Key differences from SWI-Prolog:
9
+ * - Uses a pre-compiled binary (bin/lptp-gnu-prolog) with LPTP baked in
10
+ * - No consult needed — LPTP is compiled into the binary
11
+ * - Input is piped via stdin: echo "goal." | bin/lptp-gnu-prolog
12
+ * - No Prolog-level resource limits — Node.js timeout only
13
+ * - PREVENT_PRE_COMPILATION=true avoids .gr compilation on startup
14
+ */
15
+ export declare class GprologBackend implements PrologBackend {
16
+ readonly id: "gprolog";
17
+ readonly displayName = "GNU Prolog";
18
+ private getBinaryPath;
19
+ isAvailable(): boolean;
20
+ /**
21
+ * GNU Prolog has no Prolog-level resource limits.
22
+ * Returns the goal unchanged, wrapped in once/1 for determinism.
23
+ */
24
+ wrapWithLimits(goal: string, _limits?: ResourceLimits): string;
25
+ buildExecCommand(_lptpSrc: string, tmpFile: string, _limits?: ResourceLimits): string;
26
+ buildCheckCommand(_lptpSrc: string, checkPath: string, _limits?: ResourceLimits): string;
27
+ buildCompileGrCommand(_lptpSrc: string, tmpFile: string, _limits?: ResourceLimits): string;
28
+ suppressWarningsGoal(): string;
29
+ nodeTimeout(limits?: ResourceLimits, defaultMs?: number): number;
30
+ execEnv(): Record<string, string>;
31
+ }
32
+ //# sourceMappingURL=gprolog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gprolog.d.ts","sourceRoot":"","sources":["../../src/backends/gprolog.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAE7D;;;;;;;;;;;;GAYG;AACH,qBAAa,cAAe,YAAW,aAAa;IAChD,QAAQ,CAAC,EAAE,EAAG,SAAS,CAAU;IACjC,QAAQ,CAAC,WAAW,gBAAgB;IAEpC,OAAO,CAAC,aAAa;IAkBrB,WAAW,IAAI,OAAO;IAStB;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM;IAI9D,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM;IAMrF,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM;IAKxF,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM;IAK1F,oBAAoB,IAAI,MAAM;IAI9B,WAAW,CAAC,MAAM,GAAE,cAAmB,EAAE,SAAS,GAAE,MAAe,GAAG,MAAM;IAQ5E,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAGpC"}
@@ -0,0 +1,113 @@
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.GprologBackend = void 0;
37
+ const path = __importStar(require("path"));
38
+ /**
39
+ * GNU Prolog backend.
40
+ *
41
+ * CLI pattern (from Makefile line 839):
42
+ * cat ./src/allg.pl | ./bin/lptp-gnu-prolog
43
+ *
44
+ * Key differences from SWI-Prolog:
45
+ * - Uses a pre-compiled binary (bin/lptp-gnu-prolog) with LPTP baked in
46
+ * - No consult needed — LPTP is compiled into the binary
47
+ * - Input is piped via stdin: echo "goal." | bin/lptp-gnu-prolog
48
+ * - No Prolog-level resource limits — Node.js timeout only
49
+ * - PREVENT_PRE_COMPILATION=true avoids .gr compilation on startup
50
+ */
51
+ class GprologBackend {
52
+ id = 'gprolog';
53
+ displayName = 'GNU Prolog';
54
+ getBinaryPath() {
55
+ const root = process.env['LPTP_ROOT_DIR'];
56
+ if (root)
57
+ return path.join(root, 'bin', 'lptp-gnu-prolog');
58
+ // Walk up from __dirname to find bin/lptp-gnu-prolog
59
+ let dir = __dirname;
60
+ for (let i = 0; i < 8; i++) {
61
+ const candidate = path.join(dir, 'bin', 'lptp-gnu-prolog');
62
+ if (require('fs').existsSync(candidate))
63
+ return candidate;
64
+ dir = path.dirname(dir);
65
+ }
66
+ throw new Error('GNU Prolog binary (bin/lptp-gnu-prolog) not found. ' +
67
+ 'Set LPTP_ROOT_DIR to your LPTP checkout root, or build the binary with: cd src && make gprolog');
68
+ }
69
+ isAvailable() {
70
+ try {
71
+ this.getBinaryPath();
72
+ return require('fs').existsSync(this.getBinaryPath());
73
+ }
74
+ catch {
75
+ return false;
76
+ }
77
+ }
78
+ /**
79
+ * GNU Prolog has no Prolog-level resource limits.
80
+ * Returns the goal unchanged, wrapped in once/1 for determinism.
81
+ */
82
+ wrapWithLimits(goal, _limits) {
83
+ return `once(${goal})`;
84
+ }
85
+ buildExecCommand(_lptpSrc, tmpFile, _limits) {
86
+ const binary = this.getBinaryPath();
87
+ // LPTP is compiled into the binary — no consult needed
88
+ return `echo "exec('${tmpFile}')." | ${binary}`;
89
+ }
90
+ buildCheckCommand(_lptpSrc, checkPath, _limits) {
91
+ const binary = this.getBinaryPath();
92
+ return `echo "check('${checkPath}')." | ${binary}`;
93
+ }
94
+ buildCompileGrCommand(_lptpSrc, tmpFile, _limits) {
95
+ const binary = this.getBinaryPath();
96
+ return `echo "exec('${tmpFile}')." | ${binary}`;
97
+ }
98
+ suppressWarningsGoal() {
99
+ return '';
100
+ }
101
+ nodeTimeout(limits = {}, defaultMs = 30_000) {
102
+ // Node.js timeout is the only guard for GNU Prolog.
103
+ if (limits.timeLimitS != null) {
104
+ return limits.timeLimitS * 1000 + 5000;
105
+ }
106
+ return defaultMs;
107
+ }
108
+ execEnv() {
109
+ return { PREVENT_PRE_COMPILATION: 'true' };
110
+ }
111
+ }
112
+ exports.GprologBackend = GprologBackend;
113
+ //# sourceMappingURL=gprolog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gprolog.js","sourceRoot":"","sources":["../../src/backends/gprolog.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAA6B;AAG7B;;;;;;;;;;;;GAYG;AACH,MAAa,cAAc;IACd,EAAE,GAAG,SAAkB,CAAC;IACxB,WAAW,GAAG,YAAY,CAAC;IAE5B,aAAa;QACjB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC1C,IAAI,IAAI;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;QAE3D,qDAAqD;QACrD,IAAI,GAAG,GAAG,SAAS,CAAC;QACpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YACzB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAC;YAC3D,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC;gBAAE,OAAO,SAAS,CAAC;YAC1D,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC5B,CAAC;QAED,MAAM,IAAI,KAAK,CACX,qDAAqD;YACrD,gGAAgG,CACnG,CAAC;IACN,CAAC;IAED,WAAW;QACP,IAAI,CAAC;YACD,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,cAAc,CAAC,IAAY,EAAE,OAAwB;QACjD,OAAO,QAAQ,IAAI,GAAG,CAAC;IAC3B,CAAC;IAED,gBAAgB,CAAC,QAAgB,EAAE,OAAe,EAAE,OAAwB;QACxE,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,uDAAuD;QACvD,OAAO,eAAe,OAAO,UAAU,MAAM,EAAE,CAAC;IACpD,CAAC;IAED,iBAAiB,CAAC,QAAgB,EAAE,SAAiB,EAAE,OAAwB;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,OAAO,gBAAgB,SAAS,UAAU,MAAM,EAAE,CAAC;IACvD,CAAC;IAED,qBAAqB,CAAC,QAAgB,EAAE,OAAe,EAAE,OAAwB;QAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;QACpC,OAAO,eAAe,OAAO,UAAU,MAAM,EAAE,CAAC;IACpD,CAAC;IAED,oBAAoB;QAChB,OAAO,EAAE,CAAC;IACd,CAAC;IAED,WAAW,CAAC,SAAyB,EAAE,EAAE,YAAoB,MAAM;QAC/D,oDAAoD;QACpD,IAAI,MAAM,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;YAC5B,OAAO,MAAM,CAAC,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;QAC3C,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO;QACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAC/C,CAAC;CACJ;AAtED,wCAsEC"}
@@ -0,0 +1,15 @@
1
+ import type { PrologBackend } from './types';
2
+ /**
3
+ * Returns the active Prolog backend.
4
+ *
5
+ * Selection logic:
6
+ * 1. If LPTP_PROLOG_BACKEND env var is set, use that backend (throw if unavailable).
7
+ * 2. Otherwise auto-detect in order: swipl -> scryer -> gprolog (first available wins).
8
+ * 3. If none found, throw a descriptive error.
9
+ *
10
+ * Result is cached for the lifetime of the server process.
11
+ */
12
+ export declare function getBackend(): PrologBackend;
13
+ /** Reset cached backend — useful for tests. */
14
+ export declare function resetBackendCache(): void;
15
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/backends/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,aAAa,EAAE,MAAM,SAAS,CAAC;AAexD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,IAAI,aAAa,CAuC1C;AAED,+CAA+C;AAC/C,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getBackend = getBackend;
4
+ exports.resetBackendCache = resetBackendCache;
5
+ const swipl_1 = require("./swipl");
6
+ const scryer_1 = require("./scryer");
7
+ const gprolog_1 = require("./gprolog");
8
+ let cachedBackend = null;
9
+ function instantiate(id) {
10
+ switch (id) {
11
+ case 'swipl': return new swipl_1.SwiplBackend();
12
+ case 'scryer': return new scryer_1.ScryerBackend();
13
+ case 'gprolog': return new gprolog_1.GprologBackend();
14
+ }
15
+ }
16
+ /**
17
+ * Returns the active Prolog backend.
18
+ *
19
+ * Selection logic:
20
+ * 1. If LPTP_PROLOG_BACKEND env var is set, use that backend (throw if unavailable).
21
+ * 2. Otherwise auto-detect in order: swipl -> scryer -> gprolog (first available wins).
22
+ * 3. If none found, throw a descriptive error.
23
+ *
24
+ * Result is cached for the lifetime of the server process.
25
+ */
26
+ function getBackend() {
27
+ if (cachedBackend)
28
+ return cachedBackend;
29
+ const envChoice = process.env['LPTP_PROLOG_BACKEND'];
30
+ if (envChoice) {
31
+ const validIds = ['swipl', 'scryer', 'gprolog'];
32
+ if (!validIds.includes(envChoice)) {
33
+ throw new Error(`LPTP_PROLOG_BACKEND="${envChoice}" is not valid. ` +
34
+ `Choose one of: ${validIds.join(', ')}`);
35
+ }
36
+ const backend = instantiate(envChoice);
37
+ if (!backend.isAvailable()) {
38
+ throw new Error(`LPTP_PROLOG_BACKEND="${envChoice}" requested but ` +
39
+ `${backend.displayName} is not available on this system.`);
40
+ }
41
+ cachedBackend = backend;
42
+ return cachedBackend;
43
+ }
44
+ // Auto-detect: try each backend in preference order
45
+ const probeOrder = ['swipl', 'scryer', 'gprolog'];
46
+ for (const id of probeOrder) {
47
+ const backend = instantiate(id);
48
+ if (backend.isAvailable()) {
49
+ cachedBackend = backend;
50
+ return cachedBackend;
51
+ }
52
+ }
53
+ throw new Error('No Prolog backend found. Install SWI-Prolog (swipl), ' +
54
+ 'Scryer Prolog (scryer-prolog), or build GNU Prolog binary ' +
55
+ '(cd src && make gprolog). Or set LPTP_PROLOG_BACKEND explicitly.');
56
+ }
57
+ /** Reset cached backend — useful for tests. */
58
+ function resetBackendCache() {
59
+ cachedBackend = null;
60
+ }
61
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/backends/registry.ts"],"names":[],"mappings":";;AAyBA,gCAuCC;AAGD,8CAEC;AApED,mCAAuC;AACvC,qCAAyC;AACzC,uCAA2C;AAE3C,IAAI,aAAa,GAAyB,IAAI,CAAC;AAE/C,SAAS,WAAW,CAAC,EAAa;IAC9B,QAAQ,EAAE,EAAE,CAAC;QACT,KAAK,OAAO,CAAC,CAAE,OAAO,IAAI,oBAAY,EAAE,CAAC;QACzC,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,sBAAa,EAAE,CAAC;QAC1C,KAAK,SAAS,CAAC,CAAC,OAAO,IAAI,wBAAc,EAAE,CAAC;IAChD,CAAC;AACL,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,UAAU;IACtB,IAAI,aAAa;QAAE,OAAO,aAAa,CAAC;IAExC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAA0B,CAAC;IAE9E,IAAI,SAAS,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAgB,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC7D,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CACX,wBAAwB,SAAS,kBAAkB;gBACnD,kBAAkB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC1C,CAAC;QACN,CAAC;QACD,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACX,wBAAwB,SAAS,kBAAkB;gBACnD,GAAG,OAAO,CAAC,WAAW,mCAAmC,CAC5D,CAAC;QACN,CAAC;QACD,aAAa,GAAG,OAAO,CAAC;QACxB,OAAO,aAAa,CAAC;IACzB,CAAC;IAED,oDAAoD;IACpD,MAAM,UAAU,GAAgB,CAAC,OAAO,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAC/D,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;QAChC,IAAI,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,aAAa,GAAG,OAAO,CAAC;YACxB,OAAO,aAAa,CAAC;QACzB,CAAC;IACL,CAAC;IAED,MAAM,IAAI,KAAK,CACX,uDAAuD;QACvD,4DAA4D;QAC5D,kEAAkE,CACrE,CAAC;AACN,CAAC;AAED,+CAA+C;AAC/C,SAAgB,iBAAiB;IAC7B,aAAa,GAAG,IAAI,CAAC;AACzB,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { PrologBackend, ResourceLimits } from './types';
2
+ /**
3
+ * Scryer Prolog backend.
4
+ *
5
+ * CLI pattern (from Makefile line 819):
6
+ * scryer-prolog -g "consult('./src/lptp.pl'),exec('file')." -g "halt."
7
+ *
8
+ * Key differences from SWI-Prolog:
9
+ * - Goals passed to -g need a trailing period
10
+ * - Supports call_with_inference_limit/3 from iso_ext module
11
+ * - No call_with_time_limit or call_with_depth_limit — Node.js timeout covers those
12
+ * - Quiet mode via QUIET_MODE=true environment variable
13
+ * - No message_hook suppression needed
14
+ */
15
+ export declare class ScryerBackend implements PrologBackend {
16
+ readonly id: "scryer";
17
+ readonly displayName = "Scryer Prolog";
18
+ isAvailable(): boolean;
19
+ /**
20
+ * Wraps a Prolog goal with Scryer-specific resource limits.
21
+ * Only inference limit is supported at the Prolog level via
22
+ * call_with_inference_limit/3 (iso_ext module).
23
+ * Time and depth limits fall back to Node.js timeout.
24
+ */
25
+ wrapWithLimits(goal: string, limits?: ResourceLimits): string;
26
+ buildExecCommand(lptpSrc: string, tmpFile: string, limits?: ResourceLimits): string;
27
+ buildCheckCommand(lptpSrc: string, checkPath: string, limits?: ResourceLimits): string;
28
+ buildCompileGrCommand(lptpSrc: string, tmpFile: string, limits?: ResourceLimits): string;
29
+ suppressWarningsGoal(): string;
30
+ nodeTimeout(limits?: ResourceLimits, defaultMs?: number): number;
31
+ execEnv(): Record<string, string>;
32
+ }
33
+ //# sourceMappingURL=scryer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scryer.d.ts","sourceRoot":"","sources":["../../src/backends/scryer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAI7D;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAc,YAAW,aAAa;IAC/C,QAAQ,CAAC,EAAE,EAAG,QAAQ,CAAU;IAChC,QAAQ,CAAC,WAAW,mBAAmB;IAEvC,WAAW,IAAI,OAAO;IAKtB;;;;;OAKG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,cAAmB,GAAG,MAAM;IASjE,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM;IAQnF,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM;IAQtF,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM;IAQxF,oBAAoB,IAAI,MAAM;IAI9B,WAAW,CAAC,MAAM,GAAE,cAAmB,EAAE,SAAS,GAAE,MAAe,GAAG,MAAM;IAS5E,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAGpC"}
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ScryerBackend = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const DEFAULT_INFERENCE_LIMIT = 1_000_000;
6
+ /**
7
+ * Scryer Prolog backend.
8
+ *
9
+ * CLI pattern (from Makefile line 819):
10
+ * scryer-prolog -g "consult('./src/lptp.pl'),exec('file')." -g "halt."
11
+ *
12
+ * Key differences from SWI-Prolog:
13
+ * - Goals passed to -g need a trailing period
14
+ * - Supports call_with_inference_limit/3 from iso_ext module
15
+ * - No call_with_time_limit or call_with_depth_limit — Node.js timeout covers those
16
+ * - Quiet mode via QUIET_MODE=true environment variable
17
+ * - No message_hook suppression needed
18
+ */
19
+ class ScryerBackend {
20
+ id = 'scryer';
21
+ displayName = 'Scryer Prolog';
22
+ isAvailable() {
23
+ try {
24
+ (0, child_process_1.execSync)('which scryer-prolog', { stdio: 'ignore' });
25
+ return true;
26
+ }
27
+ catch {
28
+ return false;
29
+ }
30
+ }
31
+ /**
32
+ * Wraps a Prolog goal with Scryer-specific resource limits.
33
+ * Only inference limit is supported at the Prolog level via
34
+ * call_with_inference_limit/3 (iso_ext module).
35
+ * Time and depth limits fall back to Node.js timeout.
36
+ */
37
+ wrapWithLimits(goal, limits = {}) {
38
+ let wrapped = `once(${goal})`;
39
+ const infLim = limits.inferenceLimit ?? DEFAULT_INFERENCE_LIMIT;
40
+ wrapped = `call_with_inference_limit((${wrapped}), ${infLim}, _InfRes)`;
41
+ return wrapped;
42
+ }
43
+ buildExecCommand(lptpSrc, tmpFile, limits) {
44
+ const wrappedGoal = this.wrapWithLimits(`(consult('${lptpSrc}'), exec('${tmpFile}'))`, limits);
45
+ return `scryer-prolog -g "${wrappedGoal}." -g "halt."`;
46
+ }
47
+ buildCheckCommand(lptpSrc, checkPath, limits) {
48
+ const wrappedGoal = this.wrapWithLimits(`(consult('${lptpSrc}'), check('${checkPath}'))`, limits ?? { inferenceLimit: 10_000_000 });
49
+ return `scryer-prolog -g "${wrappedGoal}." -g "halt."`;
50
+ }
51
+ buildCompileGrCommand(lptpSrc, tmpFile, limits) {
52
+ const wrappedGoal = this.wrapWithLimits(`(consult('${lptpSrc}'), exec('${tmpFile}'))`, limits);
53
+ return `scryer-prolog -g "${wrappedGoal}." -g "halt."`;
54
+ }
55
+ suppressWarningsGoal() {
56
+ return '';
57
+ }
58
+ nodeTimeout(limits = {}, defaultMs = 30_000) {
59
+ // Scryer has no Prolog-level time limit, so Node.js timeout is the primary guard.
60
+ // Use the timeLimitS hint if provided, otherwise fall back to defaultMs.
61
+ if (limits.timeLimitS != null) {
62
+ return limits.timeLimitS * 1000 + 5000;
63
+ }
64
+ return defaultMs;
65
+ }
66
+ execEnv() {
67
+ return { QUIET_MODE: 'true' };
68
+ }
69
+ }
70
+ exports.ScryerBackend = ScryerBackend;
71
+ //# sourceMappingURL=scryer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scryer.js","sourceRoot":"","sources":["../../src/backends/scryer.ts"],"names":[],"mappings":";;;AAAA,iDAAyC;AAGzC,MAAM,uBAAuB,GAAG,SAAS,CAAC;AAE1C;;;;;;;;;;;;GAYG;AACH,MAAa,aAAa;IACb,EAAE,GAAG,QAAiB,CAAC;IACvB,WAAW,GAAG,eAAe,CAAC;IAEvC,WAAW;QACP,IAAI,CAAC;YAAC,IAAA,wBAAQ,EAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QAC1E,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,IAAY,EAAE,SAAyB,EAAE;QACpD,IAAI,OAAO,GAAG,QAAQ,IAAI,GAAG,CAAC;QAE9B,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,IAAI,uBAAuB,CAAC;QAChE,OAAO,GAAG,8BAA8B,OAAO,MAAM,MAAM,YAAY,CAAC;QAExE,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,gBAAgB,CAAC,OAAe,EAAE,OAAe,EAAE,MAAuB;QACtE,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CACnC,aAAa,OAAO,aAAa,OAAO,KAAK,EAC7C,MAAM,CACT,CAAC;QACF,OAAO,qBAAqB,WAAW,eAAe,CAAC;IAC3D,CAAC;IAED,iBAAiB,CAAC,OAAe,EAAE,SAAiB,EAAE,MAAuB;QACzE,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CACnC,aAAa,OAAO,cAAc,SAAS,KAAK,EAChD,MAAM,IAAI,EAAE,cAAc,EAAE,UAAU,EAAE,CAC3C,CAAC;QACF,OAAO,qBAAqB,WAAW,eAAe,CAAC;IAC3D,CAAC;IAED,qBAAqB,CAAC,OAAe,EAAE,OAAe,EAAE,MAAuB;QAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CACnC,aAAa,OAAO,aAAa,OAAO,KAAK,EAC7C,MAAM,CACT,CAAC;QACF,OAAO,qBAAqB,WAAW,eAAe,CAAC;IAC3D,CAAC;IAED,oBAAoB;QAChB,OAAO,EAAE,CAAC;IACd,CAAC;IAED,WAAW,CAAC,SAAyB,EAAE,EAAE,YAAoB,MAAM;QAC/D,kFAAkF;QAClF,yEAAyE;QACzE,IAAI,MAAM,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;YAC5B,OAAO,MAAM,CAAC,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;QAC3C,CAAC;QACD,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,OAAO;QACH,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAClC,CAAC;CACJ;AAhED,sCAgEC"}
@@ -0,0 +1,24 @@
1
+ import type { PrologBackend, ResourceLimits } from './types';
2
+ export declare class SwiplBackend implements PrologBackend {
3
+ readonly id: "swipl";
4
+ readonly displayName = "SWI-Prolog";
5
+ isAvailable(): boolean;
6
+ /**
7
+ * Wraps a SWI-Prolog goal with resource limits:
8
+ * once/1 — deterministic, no backtracking
9
+ * call_with_time_limit/2 — wall-clock timeout (throws time_limit_exceeded)
10
+ * call_with_inference_limit/3 — inference bound (binds Result)
11
+ * call_with_depth_limit/3 — depth bound (binds Result)
12
+ *
13
+ * If any limit is exceeded the process writes a diagnostic and halts with
14
+ * a non-zero exit code so the Node.js side captures it as an error.
15
+ */
16
+ wrapWithLimits(goal: string, limits?: ResourceLimits): string;
17
+ buildExecCommand(lptpSrc: string, tmpFile: string, limits?: ResourceLimits): string;
18
+ buildCheckCommand(lptpSrc: string, checkPath: string, limits?: ResourceLimits): string;
19
+ buildCompileGrCommand(lptpSrc: string, tmpFile: string, limits?: ResourceLimits): string;
20
+ suppressWarningsGoal(): string;
21
+ nodeTimeout(limits?: ResourceLimits, defaultMs?: number): number;
22
+ execEnv(): Record<string, string>;
23
+ }
24
+ //# sourceMappingURL=swipl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swipl.d.ts","sourceRoot":"","sources":["../../src/backends/swipl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK7D,qBAAa,YAAa,YAAW,aAAa;IAC9C,QAAQ,CAAC,EAAE,EAAG,OAAO,CAAU;IAC/B,QAAQ,CAAC,WAAW,gBAAgB;IAEpC,WAAW,IAAI,OAAO;IAKtB;;;;;;;;;OASG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,cAAmB,GAAG,MAAM;IAyBjE,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM;IAQnF,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM;IAStF,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM;IAQxF,oBAAoB,IAAI,MAAM;IAI9B,WAAW,CAAC,MAAM,GAAE,cAAmB,EAAE,SAAS,GAAE,MAAe,GAAG,MAAM;IAK5E,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAGpC"}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SwiplBackend = void 0;
4
+ const child_process_1 = require("child_process");
5
+ const DEFAULT_PROLOG_TIME_LIMIT_S = 25;
6
+ const DEFAULT_INFERENCE_LIMIT = 1_000_000;
7
+ class SwiplBackend {
8
+ id = 'swipl';
9
+ displayName = 'SWI-Prolog';
10
+ isAvailable() {
11
+ try {
12
+ (0, child_process_1.execSync)('which swipl', { stdio: 'ignore' });
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ /**
20
+ * Wraps a SWI-Prolog goal with resource limits:
21
+ * once/1 — deterministic, no backtracking
22
+ * call_with_time_limit/2 — wall-clock timeout (throws time_limit_exceeded)
23
+ * call_with_inference_limit/3 — inference bound (binds Result)
24
+ * call_with_depth_limit/3 — depth bound (binds Result)
25
+ *
26
+ * If any limit is exceeded the process writes a diagnostic and halts with
27
+ * a non-zero exit code so the Node.js side captures it as an error.
28
+ */
29
+ wrapWithLimits(goal, limits = {}) {
30
+ const timeS = limits.timeLimitS ?? DEFAULT_PROLOG_TIME_LIMIT_S;
31
+ const infLim = limits.inferenceLimit ?? DEFAULT_INFERENCE_LIMIT;
32
+ // Build from inside out:
33
+ // innermost: once(Goal)
34
+ // then: call_with_inference_limit(…, InfLim, InfRes)
35
+ // then: call_with_time_limit(TimeS, …)
36
+ // outermost: catch(…, time_limit_exceeded, diagnostic)
37
+ let wrapped = `once(${goal})`;
38
+ // Inference limit guard
39
+ wrapped = `call_with_inference_limit((${wrapped}), ${infLim}, _InfRes)`;
40
+ // Optional depth limit
41
+ if (limits.depthLimit != null) {
42
+ wrapped = `call_with_depth_limit((${wrapped}), ${limits.depthLimit}, _DepthRes)`;
43
+ }
44
+ // Time limit guard (outermost catch)
45
+ wrapped = `catch(call_with_time_limit(${timeS}, (${wrapped})), time_limit_exceeded, (write('TIME_LIMIT_EXCEEDED'), nl, halt(2)))`;
46
+ return wrapped;
47
+ }
48
+ buildExecCommand(lptpSrc, tmpFile, limits) {
49
+ const wrappedGoal = this.wrapWithLimits(`(consult('${lptpSrc}'), exec('${tmpFile}'))`, limits);
50
+ return `swipl -q -g "${wrappedGoal}, halt" -t "halt(1)"`;
51
+ }
52
+ buildCheckCommand(lptpSrc, checkPath, limits) {
53
+ const suppressWarnings = this.suppressWarningsGoal();
54
+ const wrappedGoal = this.wrapWithLimits(`(${suppressWarnings}, consult('${lptpSrc}'), check('${checkPath}'))`, limits ?? { timeLimitS: 110, inferenceLimit: 10_000_000 });
55
+ return `swipl -q -g "${wrappedGoal}, halt" -t "halt(1)"`;
56
+ }
57
+ buildCompileGrCommand(lptpSrc, tmpFile, limits) {
58
+ const wrappedGoal = this.wrapWithLimits(`(consult('${lptpSrc}'), exec('${tmpFile}'))`, limits);
59
+ return `swipl -q -g "${wrappedGoal}, halt" -t "halt(1)"`;
60
+ }
61
+ suppressWarningsGoal() {
62
+ return `asserta((user:message_hook(_,warning,_) :- !))`;
63
+ }
64
+ nodeTimeout(limits = {}, defaultMs = 30_000) {
65
+ const timeS = limits.timeLimitS ?? DEFAULT_PROLOG_TIME_LIMIT_S;
66
+ return timeS * 1000 + 5000;
67
+ }
68
+ execEnv() {
69
+ return {};
70
+ }
71
+ }
72
+ exports.SwiplBackend = SwiplBackend;
73
+ //# sourceMappingURL=swipl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swipl.js","sourceRoot":"","sources":["../../src/backends/swipl.ts"],"names":[],"mappings":";;;AAAA,iDAAyC;AAGzC,MAAM,2BAA2B,GAAG,EAAE,CAAC;AACvC,MAAM,uBAAuB,GAAO,SAAS,CAAC;AAE9C,MAAa,YAAY;IACZ,EAAE,GAAG,OAAgB,CAAC;IACtB,WAAW,GAAG,YAAY,CAAC;IAEpC,WAAW;QACP,IAAI,CAAC;YAAC,IAAA,wBAAQ,EAAC,aAAa,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;YAAC,OAAO,IAAI,CAAC;QAAC,CAAC;QAClE,MAAM,CAAC;YAAC,OAAO,KAAK,CAAC;QAAC,CAAC;IAC3B,CAAC;IAED;;;;;;;;;OASG;IACH,cAAc,CAAC,IAAY,EAAE,SAAyB,EAAE;QACpD,MAAM,KAAK,GAAI,MAAM,CAAC,UAAU,IAAI,2BAA2B,CAAC;QAChE,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,IAAI,uBAAuB,CAAC;QAEhE,yBAAyB;QACzB,0BAA0B;QAC1B,uDAAuD;QACvD,yCAAyC;QACzC,yDAAyD;QACzD,IAAI,OAAO,GAAG,QAAQ,IAAI,GAAG,CAAC;QAE9B,wBAAwB;QACxB,OAAO,GAAG,8BAA8B,OAAO,MAAM,MAAM,YAAY,CAAC;QAExE,uBAAuB;QACvB,IAAI,MAAM,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;YAC5B,OAAO,GAAG,0BAA0B,OAAO,MAAM,MAAM,CAAC,UAAU,cAAc,CAAC;QACrF,CAAC;QAED,qCAAqC;QACrC,OAAO,GAAG,8BAA8B,KAAK,MAAM,OAAO,uEAAuE,CAAC;QAElI,OAAO,OAAO,CAAC;IACnB,CAAC;IAED,gBAAgB,CAAC,OAAe,EAAE,OAAe,EAAE,MAAuB;QACtE,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CACnC,aAAa,OAAO,aAAa,OAAO,KAAK,EAC7C,MAAM,CACT,CAAC;QACF,OAAO,gBAAgB,WAAW,sBAAsB,CAAC;IAC7D,CAAC;IAED,iBAAiB,CAAC,OAAe,EAAE,SAAiB,EAAE,MAAuB;QACzE,MAAM,gBAAgB,GAAG,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACrD,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CACnC,IAAI,gBAAgB,cAAc,OAAO,cAAc,SAAS,KAAK,EACrE,MAAM,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,CAC5D,CAAC;QACF,OAAO,gBAAgB,WAAW,sBAAsB,CAAC;IAC7D,CAAC;IAED,qBAAqB,CAAC,OAAe,EAAE,OAAe,EAAE,MAAuB;QAC3E,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CACnC,aAAa,OAAO,aAAa,OAAO,KAAK,EAC7C,MAAM,CACT,CAAC;QACF,OAAO,gBAAgB,WAAW,sBAAsB,CAAC;IAC7D,CAAC;IAED,oBAAoB;QAChB,OAAO,gDAAgD,CAAC;IAC5D,CAAC;IAED,WAAW,CAAC,SAAyB,EAAE,EAAE,YAAoB,MAAM;QAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,IAAI,2BAA2B,CAAC;QAC/D,OAAO,KAAK,GAAG,IAAI,GAAG,IAAI,CAAC;IAC/B,CAAC;IAED,OAAO;QACH,OAAO,EAAE,CAAC;IACd,CAAC;CACJ;AAjFD,oCAiFC"}
@@ -0,0 +1,27 @@
1
+ export type BackendId = 'swipl' | 'scryer' | 'gprolog';
2
+ export interface ResourceLimits {
3
+ timeLimitS?: number;
4
+ inferenceLimit?: number;
5
+ depthLimit?: number;
6
+ }
7
+ export interface PrologBackend {
8
+ readonly id: BackendId;
9
+ readonly displayName: string;
10
+ /** Returns true when the backend's binary / compiled artifact is on PATH or at expected location. */
11
+ isAvailable(): boolean;
12
+ /** Build shell command that runs `exec(TmpFile)` through LPTP. */
13
+ buildExecCommand(lptpSrc: string, tmpFile: string, limits?: ResourceLimits): string;
14
+ /** Build shell command that runs `check(CheckPath)` through LPTP. */
15
+ buildCheckCommand(lptpSrc: string, checkPath: string, limits?: ResourceLimits): string;
16
+ /** Build shell command that compiles a .gr file through LPTP. */
17
+ buildCompileGrCommand(lptpSrc: string, tmpFile: string, limits?: ResourceLimits): string;
18
+ /** Wrap a Prolog goal with backend-specific resource limits. */
19
+ wrapWithLimits(goal: string, limits?: ResourceLimits): string;
20
+ /** Return a Prolog goal that suppresses backend-specific warnings, or '' if N/A. */
21
+ suppressWarningsGoal(): string;
22
+ /** Compute Node.js exec timeout (ms) from limits. */
23
+ nodeTimeout(limits?: ResourceLimits, defaultMs?: number): number;
24
+ /** Extra environment variables for child_process.exec. */
25
+ execEnv(): Record<string, string>;
26
+ }
27
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/backends/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEvD,MAAM,WAAW,cAAc;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC1B,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAE7B,qGAAqG;IACrG,WAAW,IAAI,OAAO,CAAC;IAEvB,kEAAkE;IAClE,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;IAEpF,qEAAqE;IACrE,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;IAEvF,iEAAiE;IACjE,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;IAEzF,gEAAgE;IAChE,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC;IAE9D,oFAAoF;IACpF,oBAAoB,IAAI,MAAM,CAAC;IAE/B,qDAAqD;IACrD,WAAW,CAAC,MAAM,CAAC,EAAE,cAAc,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAEjE,0DAA0D;IAC1D,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/backends/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}