deepclause-sdk 0.0.89 → 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.
- package/README.md +417 -948
- package/dist/agent.d.ts +18 -2
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +74 -21
- package/dist/agent.js.map +1 -1
- package/dist/cli/config.d.ts +323 -176
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +146 -188
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/index.d.ts +3 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +61 -425
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/login.d.ts +29 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/login.js +184 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/readline.d.ts +6 -0
- package/dist/cli/readline.d.ts.map +1 -0
- package/dist/cli/readline.js +15 -0
- package/dist/cli/readline.js.map +1 -0
- package/dist/cli/repl-bin.d.ts +9 -0
- package/dist/cli/repl-bin.d.ts.map +1 -0
- package/dist/cli/repl-bin.js +16 -0
- package/dist/cli/repl-bin.js.map +1 -0
- package/dist/cli/repl.d.ts +191 -0
- package/dist/cli/repl.d.ts.map +1 -0
- package/dist/cli/repl.js +1232 -0
- package/dist/cli/repl.js.map +1 -0
- package/dist/cli/run.d.ts +17 -18
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +196 -183
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/set-backend.d.ts +53 -0
- package/dist/cli/set-backend.d.ts.map +1 -0
- package/dist/cli/set-backend.js +259 -0
- package/dist/cli/set-backend.js.map +1 -0
- package/dist/cli/visualize.d.ts +38 -0
- package/dist/cli/visualize.d.ts.map +1 -0
- package/dist/cli/visualize.js +125 -0
- package/dist/cli/visualize.js.map +1 -0
- package/dist/compiler.d.ts +5 -52
- package/dist/compiler.d.ts.map +1 -1
- package/dist/compiler.js +4 -768
- package/dist/compiler.js.map +1 -1
- package/dist/index.d.ts +27 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -2
- package/dist/index.js.map +1 -1
- package/dist/prolog/bridge.d.ts +3 -1
- package/dist/prolog/bridge.d.ts.map +1 -1
- package/dist/prolog/bridge.js +8 -1
- package/dist/prolog/bridge.js.map +1 -1
- package/dist/prolog-src/deepclause_analysis.pl +10 -2
- package/dist/prolog-src/deepclause_mi.pl +2245 -41
- package/dist/repl/agent.d.ts +72 -0
- package/dist/repl/agent.d.ts.map +1 -0
- package/dist/repl/agent.js +366 -0
- package/dist/repl/agent.js.map +1 -0
- package/dist/repl/auth.d.ts +45 -0
- package/dist/repl/auth.d.ts.map +1 -0
- package/dist/repl/auth.js +116 -0
- package/dist/repl/auth.js.map +1 -0
- package/dist/repl/backend.d.ts +290 -0
- package/dist/repl/backend.d.ts.map +1 -0
- package/dist/repl/backend.js +370 -0
- package/dist/repl/backend.js.map +1 -0
- package/dist/repl/compaction.d.ts +122 -0
- package/dist/repl/compaction.d.ts.map +1 -0
- package/dist/repl/compaction.js +318 -0
- package/dist/repl/compaction.js.map +1 -0
- package/dist/repl/export.d.ts +30 -0
- package/dist/repl/export.d.ts.map +1 -0
- package/dist/repl/export.js +23 -0
- package/dist/repl/export.js.map +1 -0
- package/dist/repl/frames.d.ts +21 -0
- package/dist/repl/frames.d.ts.map +1 -0
- package/dist/repl/frames.js +79 -0
- package/dist/repl/frames.js.map +1 -0
- package/dist/repl/harness-tools.d.ts +74 -0
- package/dist/repl/harness-tools.d.ts.map +1 -0
- package/dist/repl/harness-tools.js +121 -0
- package/dist/repl/harness-tools.js.map +1 -0
- package/dist/repl/highlight.d.ts +30 -0
- package/dist/repl/highlight.d.ts.map +1 -0
- package/dist/repl/highlight.js +285 -0
- package/dist/repl/highlight.js.map +1 -0
- package/dist/repl/history.d.ts +234 -0
- package/dist/repl/history.d.ts.map +1 -0
- package/dist/repl/history.js +661 -0
- package/dist/repl/history.js.map +1 -0
- package/dist/repl/index.d.ts +120 -0
- package/dist/repl/index.d.ts.map +1 -0
- package/dist/repl/index.js +107 -0
- package/dist/repl/index.js.map +1 -0
- package/dist/repl/judge.d.ts +51 -0
- package/dist/repl/judge.d.ts.map +1 -0
- package/dist/repl/judge.js +58 -0
- package/dist/repl/judge.js.map +1 -0
- package/dist/repl/markdown.d.ts +25 -0
- package/dist/repl/markdown.d.ts.map +1 -0
- package/dist/repl/markdown.js +103 -0
- package/dist/repl/markdown.js.map +1 -0
- package/dist/repl/picker.d.ts +34 -0
- package/dist/repl/picker.d.ts.map +1 -0
- package/dist/repl/picker.js +81 -0
- package/dist/repl/picker.js.map +1 -0
- package/dist/repl/project-context.d.ts +16 -0
- package/dist/repl/project-context.d.ts.map +1 -0
- package/dist/repl/project-context.js +23 -0
- package/dist/repl/project-context.js.map +1 -0
- package/dist/repl/render.d.ts +160 -0
- package/dist/repl/render.d.ts.map +1 -0
- package/dist/repl/render.js +715 -0
- package/dist/repl/render.js.map +1 -0
- package/dist/repl/session.d.ts +356 -0
- package/dist/repl/session.d.ts.map +1 -0
- package/dist/repl/session.js +1275 -0
- package/dist/repl/session.js.map +1 -0
- package/dist/repl/status.d.ts +100 -0
- package/dist/repl/status.d.ts.map +1 -0
- package/dist/repl/status.js +218 -0
- package/dist/repl/status.js.map +1 -0
- package/dist/repl/tools.d.ts +53 -0
- package/dist/repl/tools.d.ts.map +1 -0
- package/dist/repl/tools.js +307 -0
- package/dist/repl/tools.js.map +1 -0
- package/dist/repl/toolset.d.ts +32 -0
- package/dist/repl/toolset.d.ts.map +1 -0
- package/dist/repl/toolset.js +82 -0
- package/dist/repl/toolset.js.map +1 -0
- package/dist/repl/tui/editor.d.ts +17 -0
- package/dist/repl/tui/editor.d.ts.map +1 -0
- package/dist/repl/tui/editor.js +39 -0
- package/dist/repl/tui/editor.js.map +1 -0
- package/dist/repl/tui/status-bar.d.ts +26 -0
- package/dist/repl/tui/status-bar.d.ts.map +1 -0
- package/dist/repl/tui/status-bar.js +47 -0
- package/dist/repl/tui/status-bar.js.map +1 -0
- package/dist/repl/tui/theme.d.ts +30 -0
- package/dist/repl/tui/theme.d.ts.map +1 -0
- package/dist/repl/tui/theme.js +81 -0
- package/dist/repl/tui/theme.js.map +1 -0
- package/dist/repl/tui/transcript.d.ts +39 -0
- package/dist/repl/tui/transcript.d.ts.map +1 -0
- package/dist/repl/tui/transcript.js +123 -0
- package/dist/repl/tui/transcript.js.map +1 -0
- package/dist/runner.d.ts +132 -13
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +434 -277
- package/dist/runner.js.map +1 -1
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +0 -32
- package/dist/sdk.js.map +1 -1
- package/dist/system/assets/docs/AGENT_PROMPT.md +1373 -0
- package/dist/system/assets/docs/DML_AUTHORING.md +195 -0
- package/dist/system/assets/docs/DML_REFERENCE.md +312 -72
- package/dist/system/assets/docs/HARNESS_EXAMPLES.md +172 -0
- package/dist/system/assets/docs/HARNESS_PATTERNS.md +562 -0
- package/dist/system/assets/docs/META_PROMPT.md +68 -0
- package/dist/system/assets/docs/PROLOG_SNIPPETS.md +117 -0
- package/dist/system/assets/index.d.ts +9 -17
- package/dist/system/assets/index.d.ts.map +1 -1
- package/dist/system/assets/index.js +26 -85
- package/dist/system/assets/index.js.map +1 -1
- package/dist/system/runtime/agentvm-manager.d.ts +9 -2
- package/dist/system/runtime/agentvm-manager.d.ts.map +1 -1
- package/dist/system/runtime/agentvm-manager.js +70 -44
- package/dist/system/runtime/agentvm-manager.js.map +1 -1
- package/dist/system/runtime/media.d.ts +23 -0
- package/dist/system/runtime/media.d.ts.map +1 -0
- package/dist/system/runtime/media.js +55 -0
- package/dist/system/runtime/media.js.map +1 -0
- package/dist/system/runtime/shell-limits.d.ts +21 -0
- package/dist/system/runtime/shell-limits.d.ts.map +1 -0
- package/dist/system/runtime/shell-limits.js +39 -0
- package/dist/system/runtime/shell-limits.js.map +1 -0
- package/dist/system/runtime/shell-manager.d.ts +8 -3
- package/dist/system/runtime/shell-manager.d.ts.map +1 -1
- package/dist/system/runtime/shell-manager.js +56 -39
- package/dist/system/runtime/shell-manager.js.map +1 -1
- package/dist/system/runtime/shell-tool-events.js +5 -0
- package/dist/system/runtime/shell-tool-events.js.map +1 -1
- package/dist/system/runtime/token-usage.d.ts +2 -0
- package/dist/system/runtime/token-usage.d.ts.map +1 -1
- package/dist/system/runtime/token-usage.js +7 -0
- package/dist/system/runtime/token-usage.js.map +1 -1
- package/dist/tools.d.ts +3 -21
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +14 -168
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +80 -118
- package/dist/types.d.ts.map +1 -1
- package/dist/validate.d.ts +19 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +338 -0
- package/dist/validate.js.map +1 -0
- package/dist/visualize/index.d.ts +52 -0
- package/dist/visualize/index.d.ts.map +1 -0
- package/dist/visualize/index.js +189 -0
- package/dist/visualize/index.js.map +1 -0
- package/package.json +17 -15
- package/src/prolog-src/deepclause_analysis.pl +10 -2
- package/src/prolog-src/deepclause_mi.pl +2245 -41
- package/dist/cli/commands.d.ts +0 -42
- package/dist/cli/commands.d.ts.map +0 -1
- package/dist/cli/commands.js +0 -246
- package/dist/cli/commands.js.map +0 -1
- package/dist/cli/compile.d.ts +0 -99
- package/dist/cli/compile.d.ts.map +0 -1
- package/dist/cli/compile.js +0 -363
- package/dist/cli/compile.js.map +0 -1
- package/dist/cli/default-skills.d.ts +0 -10
- package/dist/cli/default-skills.d.ts.map +0 -1
- package/dist/cli/default-skills.js +0 -206
- package/dist/cli/default-skills.js.map +0 -1
- package/dist/cli/interactive.d.ts +0 -2
- package/dist/cli/interactive.d.ts.map +0 -1
- package/dist/cli/interactive.js +0 -20
- package/dist/cli/interactive.js.map +0 -1
- package/dist/cli/mcp.d.ts +0 -56
- package/dist/cli/mcp.d.ts.map +0 -1
- package/dist/cli/mcp.js +0 -138
- package/dist/cli/mcp.js.map +0 -1
- package/dist/cli/prompt.d.ts +0 -2
- package/dist/cli/prompt.d.ts.map +0 -1
- package/dist/cli/prompt.js +0 -2
- package/dist/cli/prompt.js.map +0 -1
- package/dist/cli/search.d.ts +0 -19
- package/dist/cli/search.d.ts.map +0 -1
- package/dist/cli/search.js +0 -189
- package/dist/cli/search.js.map +0 -1
- package/dist/cli/tool-args.d.ts +0 -2
- package/dist/cli/tool-args.d.ts.map +0 -1
- package/dist/cli/tool-args.js +0 -39
- package/dist/cli/tool-args.js.map +0 -1
- package/dist/cli/tools.d.ts +0 -36
- package/dist/cli/tools.d.ts.map +0 -1
- package/dist/cli/tools.js +0 -229
- package/dist/cli/tools.js.map +0 -1
- package/dist/cli/tui/index.d.ts +0 -22
- package/dist/cli/tui/index.d.ts.map +0 -1
- package/dist/cli/tui/index.js +0 -29
- package/dist/cli/tui/index.js.map +0 -1
- package/dist/cli/tui.d.ts +0 -167
- package/dist/cli/tui.d.ts.map +0 -1
- package/dist/cli/tui.js +0 -5228
- package/dist/cli/tui.js.map +0 -1
- package/dist/compiler_prompt.d.ts +0 -20
- package/dist/compiler_prompt.d.ts.map +0 -1
- package/dist/compiler_prompt.js +0 -870
- package/dist/compiler_prompt.js.map +0 -1
- package/dist/deepclause-cli.skill +0 -0
- package/dist/prolog-src/deepclause_mi.pl.bak +0 -570
- package/dist/system/assets/docs/CONDUCTOR_PROMPT.md +0 -105
- package/dist/system/assets/docs/DML_COMPILER_PROMPT.md +0 -700
- package/dist/system/assets/docs/TUI.md +0 -150
- package/dist/system/assets/recipes/deepclause-coding-workflow/SKILL.md +0 -100
- package/dist/system/assets/skills/conductor.dml +0 -76
- package/dist/system/assets/skills/deep-planner.dml +0 -412
- package/dist/system/assets/skills/plan.dml +0 -429
- package/dist/system/assets/skills/security-planner.dml +0 -337
- package/dist/system/assets/skills/skill-creator.dml +0 -187
- package/dist/system/runtime/catalog-recipes.d.ts +0 -24
- package/dist/system/runtime/catalog-recipes.d.ts.map +0 -1
- package/dist/system/runtime/catalog-recipes.js +0 -273
- package/dist/system/runtime/catalog-recipes.js.map +0 -1
- package/dist/system/runtime/catalog-skills.d.ts +0 -50
- package/dist/system/runtime/catalog-skills.d.ts.map +0 -1
- package/dist/system/runtime/catalog-skills.js +0 -152
- package/dist/system/runtime/catalog-skills.js.map +0 -1
- package/dist/system/runtime/conductor.d.ts +0 -105
- package/dist/system/runtime/conductor.d.ts.map +0 -1
- package/dist/system/runtime/conductor.js +0 -732
- package/dist/system/runtime/conductor.js.map +0 -1
- package/dist/system/runtime/console-capture.d.ts +0 -9
- package/dist/system/runtime/console-capture.d.ts.map +0 -1
- package/dist/system/runtime/console-capture.js +0 -67
- package/dist/system/runtime/console-capture.js.map +0 -1
- package/dist/system/runtime/dml-executor.d.ts +0 -52
- package/dist/system/runtime/dml-executor.d.ts.map +0 -1
- package/dist/system/runtime/dml-executor.js +0 -203
- package/dist/system/runtime/dml-executor.js.map +0 -1
- package/dist/system/runtime/runtime-tools.d.ts +0 -31
- package/dist/system/runtime/runtime-tools.d.ts.map +0 -1
- package/dist/system/runtime/runtime-tools.js +0 -312
- package/dist/system/runtime/runtime-tools.js.map +0 -1
- package/dist/system/runtime/skill-creator.d.ts +0 -38
- package/dist/system/runtime/skill-creator.d.ts.map +0 -1
- package/dist/system/runtime/skill-creator.js +0 -763
- package/dist/system/runtime/skill-creator.js.map +0 -1
- package/src/prolog-src/deepclause_mi.pl.bak +0 -570
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
- [system/1, user/1](#memory-predicates)
|
|
15
15
|
- [output/1, yield/1, log/1](#output-predicates)
|
|
16
16
|
- [answer/1](#answer1)
|
|
17
|
-
- [param/3](#param3)
|
|
18
17
|
- [Control Flow](#control-flow)
|
|
19
18
|
- [String Interpolation](#string-interpolation)
|
|
20
19
|
- [Backtracking](#backtracking)
|
|
@@ -58,7 +57,7 @@ agent_main :-
|
|
|
58
57
|
```
|
|
59
58
|
|
|
60
59
|
### agent_main/1
|
|
61
|
-
Receives the first
|
|
60
|
+
Receives the first argument:
|
|
62
61
|
```prolog
|
|
63
62
|
agent_main(Name) :-
|
|
64
63
|
format(string(Msg), "Hello, ~w!", [Name]),
|
|
@@ -66,7 +65,7 @@ agent_main(Name) :-
|
|
|
66
65
|
```
|
|
67
66
|
|
|
68
67
|
### agent_main/2
|
|
69
|
-
Receives first two
|
|
68
|
+
Receives the first two arguments:
|
|
70
69
|
```prolog
|
|
71
70
|
agent_main(Name, Task) :-
|
|
72
71
|
system("You are a helpful assistant."),
|
|
@@ -142,6 +141,23 @@ agent_main :-
|
|
|
142
141
|
|
|
143
142
|
Bind up to three variables.
|
|
144
143
|
|
|
144
|
+
> **Note — `task/N` is load-time sugar.** `task/1,2,3,4` and `prompt/2,3,4` are
|
|
145
|
+
> rewritten by the DML loader into `task_named/3` / `prompt_named/3` with typed
|
|
146
|
+
> output variables. The rewrite runs whenever code is loaded (`deepclause run`,
|
|
147
|
+
> the REPL `-l` and commit paths, `consult`, and the REPL `assert`/`assert_many`
|
|
148
|
+
> tools). The untransformed form has no runtime handler,
|
|
149
|
+
> so code that somehow reaches the runtime without the rewrite raises
|
|
150
|
+
> `domain_error(unrewritten_task_form, Goal)` instead of failing silently.
|
|
151
|
+
> `task/1`/`prompt/1` are handled directly and are unaffected.
|
|
152
|
+
|
|
153
|
+
> **Internal note.** At load time `task/N`/`prompt/N` are rewritten to
|
|
154
|
+
> `task_named/3`/`prompt_named/3` (which carry the output-variable names) and
|
|
155
|
+
> `{Var}` descriptions are hoisted into a `format/3`. That is why a description
|
|
156
|
+
> like `task("Answer: {Question}", Answer)` sometimes *appears* as
|
|
157
|
+
> `format(string(C), "Answer: ~w", [Question]), task_named(C, [Answer], ...)`.
|
|
158
|
+
> `listing` and `export` reverse this, so you always read/write `task/N` and
|
|
159
|
+
> `prompt/N` — never author `task_named/3` yourself.
|
|
160
|
+
|
|
145
161
|
### Type-Safe Output Variables
|
|
146
162
|
|
|
147
163
|
You can wrap output variables with type specifiers to enforce strict validation on the LLM's output. The runtime will ensure the value matches the specified type.
|
|
@@ -200,38 +216,66 @@ Or positional if the tool supports it:
|
|
|
200
216
|
exec(get_time, CurrentTime)
|
|
201
217
|
```
|
|
202
218
|
|
|
219
|
+
The `bash` tool accepts an optional wall-clock `timeoutMs` and always returns the
|
|
220
|
+
wall-clock duration as `timeMs`:
|
|
221
|
+
|
|
222
|
+
```prolog
|
|
223
|
+
exec(bash(command: "sleep 30", timeoutMs: 5000), R),
|
|
224
|
+
get_dict(timeMs, R, Took),
|
|
225
|
+
( get_dict(exitCode, R, 124)
|
|
226
|
+
-> format(string(Msg), "timed out after ~w ms", [Took])
|
|
227
|
+
; format(string(Msg), "finished in ~w ms", [Took])
|
|
228
|
+
).
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
A command is also killed when it produces no output for `DC_HOST_SHELL_IDLE_TIMEOUT_MS`
|
|
232
|
+
(default 180 000 ms); `DC_HOST_SHELL_TIMEOUT_MS` sets a default wall-clock cap
|
|
233
|
+
(0 = disabled). Exit code `124` means a timeout.
|
|
234
|
+
|
|
203
235
|
---
|
|
204
236
|
|
|
205
237
|
### Tool Definitions
|
|
206
238
|
|
|
207
|
-
|
|
239
|
+
`tool/2` is an **annotation**, not an implementation. It exposes an existing
|
|
240
|
+
harness predicate to the nested agent that runs inside `task/N`. Define the
|
|
241
|
+
predicate normally, then add a `tool/2` clause that delegates to it:
|
|
208
242
|
|
|
209
243
|
```prolog
|
|
210
|
-
%
|
|
211
|
-
|
|
212
|
-
|
|
244
|
+
% 1. The capability: a normal predicate, callable from `execute` and `/goal`.
|
|
245
|
+
count_words(File, Count) :-
|
|
246
|
+
script_file(count_words, Script),
|
|
247
|
+
format(atom(Cmd), "python3 '~w' '~w'", [Script, File]),
|
|
248
|
+
exec(bash(command: Cmd), Result),
|
|
249
|
+
get_dict(stdout, Result, Count).
|
|
213
250
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
answer("Done").
|
|
251
|
+
% 2. The annotation: exposes it to the nested agent. Thin body only.
|
|
252
|
+
tool(count_words(File, Count), "Count words in a workspace file.") :-
|
|
253
|
+
count_words(File, Count).
|
|
218
254
|
```
|
|
219
255
|
|
|
220
|
-
|
|
256
|
+
A predicate defined *only* inside a `tool/2` clause is invisible to
|
|
257
|
+
`execute` / `/goal` — the loader asserts it as `tool(Head)`, never as `Head`. Split
|
|
258
|
+
the two so one implementation is reachable from both surfaces:
|
|
259
|
+
|
|
221
260
|
```prolog
|
|
222
|
-
|
|
261
|
+
/goal count_words("report.txt", C). % authoring agent
|
|
262
|
+
task("Count the words in report.txt.", N). % nested agent calls the tool
|
|
223
263
|
```
|
|
224
264
|
|
|
225
|
-
The last argument is
|
|
226
|
-
|
|
265
|
+
The tool head's **last argument is the output**; the description is shown to the
|
|
266
|
+
nested agent. Keep the `tool/2` body a single delegation — put no logic in it.
|
|
267
|
+
|
|
268
|
+
Logic lives in the predicate, not the annotation:
|
|
227
269
|
|
|
228
|
-
You can add Prolog logic in tool implementations:
|
|
229
270
|
```prolog
|
|
230
|
-
|
|
271
|
+
safe_divide(A, B, Result) :-
|
|
231
272
|
( B =:= 0
|
|
232
273
|
-> Result = error("Division by zero")
|
|
233
|
-
;
|
|
274
|
+
; Result is A / B
|
|
234
275
|
).
|
|
276
|
+
|
|
277
|
+
tool(safe_divide(A, B, Result), "Safely divide two numbers.") :-
|
|
278
|
+
safe_divide(A, B, Result).
|
|
235
279
|
```
|
|
236
280
|
|
|
237
281
|
#### Using `task()` Inside Tools
|
|
@@ -239,20 +283,22 @@ tool(safe_divide(A, B, Result), "Safely divide two numbers") :-
|
|
|
239
283
|
Tools can use `task()` and `prompt()` internally to combine Prolog logic with LLM reasoning:
|
|
240
284
|
|
|
241
285
|
```prolog
|
|
242
|
-
% A
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
tool(explain_calculation(A, B, Explanation)) :-
|
|
286
|
+
% A predicate that computes then explains.
|
|
287
|
+
explain_calculation(A, B, Explanation) :-
|
|
246
288
|
Sum is A + B, % Prolog computation
|
|
247
289
|
format(string(Desc), "Explain ~w + ~w = ~w to a child", [A, B, Sum]),
|
|
248
290
|
task(Desc, Explanation). % LLM explanation
|
|
249
291
|
|
|
250
|
-
|
|
251
|
-
|
|
292
|
+
tool(explain_calculation(A, B, Explanation), "Calculate and explain the result.") :-
|
|
293
|
+
explain_calculation(A, B, Explanation).
|
|
252
294
|
|
|
253
|
-
|
|
295
|
+
% A predicate that uses the LLM for formatting.
|
|
296
|
+
format_data(Data, FormattedOutput) :-
|
|
254
297
|
format(string(Desc), "Format this data nicely: ~w", [Data]),
|
|
255
298
|
task(Desc, FormattedOutput).
|
|
299
|
+
|
|
300
|
+
tool(format_data(Data, FormattedOutput), "Format data nicely using LLM.") :-
|
|
301
|
+
format_data(Data, FormattedOutput).
|
|
256
302
|
```
|
|
257
303
|
|
|
258
304
|
**Memory Isolation:** When `task()` or `prompt()` runs inside a tool, the nested agent starts with **fresh memory**. It does NOT inherit the parent's accumulated memory from `system()`, `user()`, or previous `task()` calls. If you need context in a nested task, pass it explicitly as a tool argument or add it with `system()` inside the tool body.
|
|
@@ -260,12 +306,16 @@ tool(format_data(Data, FormattedOutput)) :-
|
|
|
260
306
|
**Tool Access:** The nested agent has access to all DML tools **except** the tool that is currently executing (automatic call stack exclusion to prevent infinite recursion). You can further control tool access using `with_tools/2` and `without_tools/2`.
|
|
261
307
|
|
|
262
308
|
```prolog
|
|
263
|
-
% Example:
|
|
264
|
-
|
|
265
|
-
system(
|
|
266
|
-
|
|
267
|
-
|
|
309
|
+
% Example: passing context explicitly.
|
|
310
|
+
smart_grep(BuildContext, Pattern, Summary) :-
|
|
311
|
+
system(BuildContext), % add context to the nested task's memory
|
|
312
|
+
format(atom(Cmd), "grep -rn '~w' .", [Pattern]),
|
|
313
|
+
exec(bash(command: Cmd), Results),
|
|
314
|
+
format(string(Desc), "Summarize these matches: ~w", [Results]),
|
|
268
315
|
task(Desc, Summary).
|
|
316
|
+
|
|
317
|
+
tool(smart_grep(BuildContext, Pattern, Summary), "Grep with context.") :-
|
|
318
|
+
smart_grep(BuildContext, Pattern, Summary).
|
|
269
319
|
```
|
|
270
320
|
|
|
271
321
|
---
|
|
@@ -309,7 +359,7 @@ agent_main :-
|
|
|
309
359
|
system("You are a safe assistant."),
|
|
310
360
|
|
|
311
361
|
% Run task with only safe tools
|
|
312
|
-
with_tools([
|
|
362
|
+
with_tools([search, fetch_page], (
|
|
313
363
|
task("Analyze the files in the workspace.", Analysis)
|
|
314
364
|
)),
|
|
315
365
|
|
|
@@ -351,6 +401,68 @@ agent_main :-
|
|
|
351
401
|
|
|
352
402
|
---
|
|
353
403
|
|
|
404
|
+
### Media Predicates
|
|
405
|
+
|
|
406
|
+
Images are **workspace files**; DML carries only a reference. See
|
|
407
|
+
`docs/DML_MEDIA.md`.
|
|
408
|
+
|
|
409
|
+
#### `read_media(+Path, -Media)`
|
|
410
|
+
|
|
411
|
+
Bind `Media = media(Path, Mime)` for a workspace-relative image (PNG, JPEG, GIF,
|
|
412
|
+
WebP). The bytes are not read into Prolog.
|
|
413
|
+
|
|
414
|
+
#### `attach_media(+Media)`
|
|
415
|
+
|
|
416
|
+
Append the image to conversation memory (reference only), so the next `task/N`
|
|
417
|
+
call sends it to the model as an image block:
|
|
418
|
+
|
|
419
|
+
```prolog
|
|
420
|
+
agent_main :-
|
|
421
|
+
read_media("photos/fox.png", Img),
|
|
422
|
+
attach_media(Img),
|
|
423
|
+
task("Describe the image in one sentence.", Description),
|
|
424
|
+
answer(Description).
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Memory stores `media{path, mime}` — never the image bytes. Judgments
|
|
428
|
+
(`choose`/`rate`/`verify`/`probability`) stay text-only.
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
432
|
+
### File I/O and paths — prefer the shell
|
|
433
|
+
|
|
434
|
+
**Prefer `exec(bash(...))` for file operations.**
|
|
435
|
+
Reading, writing, copying, or converting files is usually clearer and more
|
|
436
|
+
robust as a shell command; reach for the DML predicates below only when the
|
|
437
|
+
content must be bound and reasoned over inside Prolog. Pulling a file into DML
|
|
438
|
+
just to hand it back to the shell is a smell (`DML_AUTHORING.md` §2).
|
|
439
|
+
|
|
440
|
+
If you do use them: every path in DML is **workspace-relative** and confined to
|
|
441
|
+
the workspace. The
|
|
442
|
+
engine mounts the workspace at `/workspace`, but you must not write
|
|
443
|
+
`/workspace/...` in DML — passing an absolute path is rejected, as is `..`. File
|
|
444
|
+
predicates all take a relative path:
|
|
445
|
+
|
|
446
|
+
```prolog
|
|
447
|
+
read_file("images/a.png", Bytes),
|
|
448
|
+
write_file("out/report.txt", Text),
|
|
449
|
+
make_directory_path("out/nested"), % create a directory (and parents)
|
|
450
|
+
append_file("out/log.txt", Line),
|
|
451
|
+
delete_file("out/report.txt"),
|
|
452
|
+
directory_files("images", Names), % bare entry names: ["a.png", ...]
|
|
453
|
+
exists_file("images/a.png"),
|
|
454
|
+
size_file("images/a.png", Size),
|
|
455
|
+
time_file("images/a.png", Modified).
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
`write_file/2` does **not** create parent directories — call
|
|
459
|
+
`make_directory_path/1` first. `directory_files/2` returns bare entry names (no
|
|
460
|
+
directory), so build a path with `atom_concat('images/', Name, Path)` when you
|
|
461
|
+
need one. `bash` runs with a wider view of the sandbox than DML has; convert
|
|
462
|
+
anything from the shell to a workspace-relative path before handing it to DML.
|
|
463
|
+
|
|
464
|
+
---
|
|
465
|
+
|
|
354
466
|
### Output Predicates
|
|
355
467
|
|
|
356
468
|
#### `output(+Text)`
|
|
@@ -397,25 +509,6 @@ agent_main :-
|
|
|
397
509
|
|
|
398
510
|
---
|
|
399
511
|
|
|
400
|
-
### `param(+Key, +Description, -Value)`
|
|
401
|
-
|
|
402
|
-
Access parameters passed from the caller:
|
|
403
|
-
|
|
404
|
-
```prolog
|
|
405
|
-
agent_main :-
|
|
406
|
-
param(name, "User's name", Name),
|
|
407
|
-
param(age, "User's age", Age),
|
|
408
|
-
format(string(Msg), "Hello ~w, you are ~w years old!", [Name, Age]),
|
|
409
|
-
answer(Msg).
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
Called from TypeScript:
|
|
413
|
-
```typescript
|
|
414
|
-
dc.runDML(code, { params: { name: 'Alice', age: 30 } });
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
---
|
|
418
|
-
|
|
419
512
|
## Control Flow
|
|
420
513
|
|
|
421
514
|
DML supports standard Prolog control flow:
|
|
@@ -460,14 +553,13 @@ throw(Error)
|
|
|
460
553
|
|
|
461
554
|
## String Interpolation
|
|
462
555
|
|
|
463
|
-
Text arguments support `{variable}` interpolation with
|
|
556
|
+
Text arguments support `{variable}` interpolation with bound variables:
|
|
464
557
|
|
|
465
558
|
```prolog
|
|
466
|
-
agent_main :-
|
|
467
|
-
param(topic, "Research topic", Topic),
|
|
559
|
+
agent_main(Topic) :-
|
|
468
560
|
system("You are a research assistant."),
|
|
469
|
-
task("Research the topic: {
|
|
470
|
-
answer("Research on {
|
|
561
|
+
task("Research the topic: {Topic}"), % Topic is interpolated
|
|
562
|
+
answer("Research on {Topic} complete!").
|
|
471
563
|
```
|
|
472
564
|
|
|
473
565
|
---
|
|
@@ -524,7 +616,12 @@ agent_main :-
|
|
|
524
616
|
|
|
525
617
|
## Full Prolog Support
|
|
526
618
|
|
|
527
|
-
DML is built on SWI-Prolog, so you have access to the full Prolog language
|
|
619
|
+
DML is built on SWI-Prolog, so you have access to the full Prolog language — and
|
|
620
|
+
to the constraint libraries (`clpfd`, `clpq`, `clpr`). Many questions are best
|
|
621
|
+
answered by a plain Prolog or CLP goal run with `execute`, with no model call at
|
|
622
|
+
all: arithmetic, counting, ordering, membership, `findall/3`, `aggregate_all/3`,
|
|
623
|
+
list/set operations, and constraint or optimisation problems. Reach for `task/N`
|
|
624
|
+
only when the step genuinely needs language understanding.
|
|
528
625
|
|
|
529
626
|
### Lists
|
|
530
627
|
```prolog
|
|
@@ -568,6 +665,44 @@ agent_main :-
|
|
|
568
665
|
answer(Msg).
|
|
569
666
|
```
|
|
570
667
|
|
|
668
|
+
### Bounding a goal (inference limit)
|
|
669
|
+
|
|
670
|
+
The interpreter has **no wall-clock timeout for a single builtin call** — the
|
|
671
|
+
session `gas` budget counts meta-interpreter steps, and a runaway `findall/3`,
|
|
672
|
+
`aggregate_all/3`, or `label/1` runs inside one step. Wrap such a call in
|
|
673
|
+
`call_with_inference_limit/3` (core SWI-Prolog; available in this runtime, which
|
|
674
|
+
has no threads) to bound it by inference count:
|
|
675
|
+
|
|
676
|
+
```prolog
|
|
677
|
+
bounded_findall(Goal, Xs) :-
|
|
678
|
+
call_with_inference_limit(findall(X, call(Goal, X), Xs), 1000000, Result),
|
|
679
|
+
( Result == inference_limit_exceeded
|
|
680
|
+
-> throw(error(inference_limit_exceeded, context(bounded_findall/2, Goal)))
|
|
681
|
+
; true
|
|
682
|
+
).
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
`Result` is `inference_limit_exceeded` when the limit is hit (otherwise the
|
|
686
|
+
normal call result). Use it for `findall/3`, `aggregate_all/3`, and CLP
|
|
687
|
+
`label/1` over a large or under-specified domain:
|
|
688
|
+
|
|
689
|
+
```prolog
|
|
690
|
+
sudoku_solve(Puzzle, Solution) :-
|
|
691
|
+
...
|
|
692
|
+
call_with_inference_limit(label(Solution), 500000, Result),
|
|
693
|
+
( Result == inference_limit_exceeded
|
|
694
|
+
-> throw(error(inference_limit_exceeded, context(sudoku_solve/2, label)))
|
|
695
|
+
; true
|
|
696
|
+
).
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
System libraries imported with `:- use_module(library(...)).` (e.g. `clpfd`) are
|
|
700
|
+
also visible inside meta-calls, so `label/1`, `all_distinct/1`, and `ins/2` work
|
|
701
|
+
unqualified through the wrapper. If a library predicate is somehow not found
|
|
702
|
+
inside a wrapper (`existence_error`), qualify it: `clpfd:label(Xs)`.
|
|
703
|
+
|
|
704
|
+
For shell commands, pass `exec(bash(command: Cmd, timeoutMs: N), R)` instead.
|
|
705
|
+
|
|
571
706
|
### Assert/Retract (within session)
|
|
572
707
|
```prolog
|
|
573
708
|
agent_main :-
|
|
@@ -577,24 +712,97 @@ agent_main :-
|
|
|
577
712
|
answer(Msg).
|
|
578
713
|
```
|
|
579
714
|
|
|
580
|
-
### Constraint Logic Programming (CLP)
|
|
715
|
+
### Constraint Logic Programming (CLP) — advanced, use sparingly
|
|
716
|
+
|
|
717
|
+
Use CLP only for a **genuine constraint problem** (scheduling, assignment,
|
|
718
|
+
puzzles, exact search). It is the wrong tool for ordinary arithmetic and
|
|
719
|
+
transformations — prefer a `task/N`/`prompt/N` step when the numbers or the
|
|
720
|
+
operation are open-ended (`DML_AUTHORING.md` §0). CLP also regresses easily: an
|
|
721
|
+
under-specified model, or one that is simply **unsatisfiable**, can search
|
|
722
|
+
essentially forever, so a buggy skill hangs the turn instead of failing fast.
|
|
723
|
+
If you use it:
|
|
581
724
|
|
|
582
|
-
|
|
725
|
+
- **Bound every domain first.** For one variable use `X in 0..100`; for a list use
|
|
726
|
+
`[X,Y,Z] ins 0..100`. (`X ins 0..100` on a bare variable is an
|
|
727
|
+
`instantiation_error` — use `in` for a single variable.)
|
|
728
|
+
- `all_distinct/1` / `all_different/1` over the list constrains it pairwise.
|
|
729
|
+
- Call `label/1` (or `labeling/2` with options such as `ff`) only when you need
|
|
730
|
+
concrete values; wrap it in `once/1` when a single witness is enough.
|
|
731
|
+
- To bound a search that can run away, wrap it in `call_with_inference_limit/3`
|
|
732
|
+
(see *Bounding a goal* above):
|
|
733
|
+
`call_with_inference_limit(label(Xs), 500000, R)` — `R == inference_limit_exceeded`
|
|
734
|
+
when it gave up. This works for CLP(FD) predicates in this runtime.
|
|
735
|
+
- Keep the model small; a big model is a sign the step belongs in a `task/N`.
|
|
583
736
|
|
|
584
|
-
- **CLP(FD)**:
|
|
585
|
-
- **CLP(Q)**:
|
|
586
|
-
- **CLP(R)**:
|
|
737
|
+
- **CLP(FD)**: finite domains (integers). `:- use_module(library(clpfd)).`
|
|
738
|
+
- **CLP(Q)**: rationals. `:- use_module(library(clpq)).`
|
|
739
|
+
- **CLP(R)**: reals. `:- use_module(library(clpr)).`
|
|
587
740
|
|
|
588
741
|
```prolog
|
|
589
742
|
:- use_module(library(clpfd)).
|
|
590
743
|
|
|
591
|
-
|
|
592
|
-
|
|
744
|
+
% Small, fully bounded search; one witness.
|
|
745
|
+
solve_sum_product(Total, X, Y) :-
|
|
746
|
+
[X, Y] ins 0..100, % bound the domains; never leave them open
|
|
593
747
|
X + Y #= Total,
|
|
594
748
|
X * Y #= 2400,
|
|
595
|
-
label([X,Y])
|
|
596
|
-
|
|
597
|
-
|
|
749
|
+
once(label([X, Y])).
|
|
750
|
+
|
|
751
|
+
% A search bounded by inference count instead of by the domain.
|
|
752
|
+
bounded_label(Xs, Result) :-
|
|
753
|
+
call_with_inference_limit(label(Xs), 500000, Result).
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
#### Optimisation (LP / MIP)
|
|
757
|
+
|
|
758
|
+
The CLP family here is **CLP(FD)** (integers), **CLP(Q)** (exact rationals) and
|
|
759
|
+
**CLP(R)** (reals) — there is no `clpfq`. `library(simplex)` loads but returns
|
|
760
|
+
unreliable answers in this runtime (its minimum/maximum come back wrong); do not
|
|
761
|
+
build on it.
|
|
762
|
+
|
|
763
|
+
**Continuous LP** — `clpr` (reals) / `clpq` (rationals), same interface. `{...}`
|
|
764
|
+
posts the constraints; `maximize/1` / `minimize/1` find the optimum:
|
|
765
|
+
|
|
766
|
+
```prolog
|
|
767
|
+
:- use_module(library(clpr)).
|
|
768
|
+
|
|
769
|
+
lp(X, Y) :-
|
|
770
|
+
{X >= 0, Y >= 0, X =< 10, Y =< 10, X + 2*Y =< 14},
|
|
771
|
+
maximize(X + Y). % X = 10.0, Y = 2.0
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
> **Caveat:** `maximize/1` / `minimize/1` bind the variables only when the optimum
|
|
775
|
+
> is a *unique vertex*. If the optimum is a face (a family of optima), they succeed
|
|
776
|
+
> and bind nothing. Use `sup/2` / `inf/2` to get the optimum **value** reliably —
|
|
777
|
+
> `{X >= 0, Y >= 0, X + Y =< 10, 2*X + Y =< 15}, sup(X + Y, S)` → `S = 10.0`.
|
|
778
|
+
> (`inf/3` / `sup/3` do not exist in this build.)
|
|
779
|
+
|
|
780
|
+
**Integer optimum** — negate the objective and use `bb_inf/5`; the 4th argument
|
|
781
|
+
comes back as the integer vertex:
|
|
782
|
+
|
|
783
|
+
```prolog
|
|
784
|
+
:- use_module(library(clpr)).
|
|
785
|
+
|
|
786
|
+
mip(Inf, Vertex) :-
|
|
787
|
+
{X >= 0, Y >= 0, X + Y =< 4, X + 3*Y =< 6},
|
|
788
|
+
bb_inf([X, Y], -(3*X + 2*Y), Inf, Vertex, 0.001).
|
|
789
|
+
% Inf = -12.0, Vertex = [4,0] (negate the objective to maximise)
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
**Exact integer optimum** — CLP(FD) with a `max(Expr)` label option. Prefer this
|
|
793
|
+
when the problem is genuinely integer: it is exact, bounded, and well-tested.
|
|
794
|
+
Bound every domain first and keep `label`/`labeling` inside
|
|
795
|
+
`call_with_inference_limit/3`:
|
|
796
|
+
|
|
797
|
+
```prolog
|
|
798
|
+
:- use_module(library(clpfd)).
|
|
799
|
+
|
|
800
|
+
exact_max(X, Y) :-
|
|
801
|
+
[X, Y] ins 0..10,
|
|
802
|
+
X + Y #=< 4,
|
|
803
|
+
X + 3*Y #=< 6,
|
|
804
|
+
call_with_inference_limit(labeling([max(3*X + 2*Y), down], [X, Y]), 500000, _).
|
|
805
|
+
% X = 4, Y = 0
|
|
598
806
|
```
|
|
599
807
|
|
|
600
808
|
### Dictionaries (SWI-Prolog)
|
|
@@ -619,10 +827,8 @@ step(N, Desc) :-
|
|
|
619
827
|
format(string(Msg), "Step ~w: ~w", [N, Desc]),
|
|
620
828
|
output(Msg).
|
|
621
829
|
|
|
622
|
-
% Main entry point
|
|
623
|
-
agent_main :-
|
|
624
|
-
param(topic, "Research topic", Topic),
|
|
625
|
-
|
|
830
|
+
% Main entry point; the topic is an argument.
|
|
831
|
+
agent_main(Topic) :-
|
|
626
832
|
% Set up the assistant
|
|
627
833
|
system("You are a thorough research assistant."),
|
|
628
834
|
system("Provide detailed, accurate information."),
|
|
@@ -649,7 +855,7 @@ agent_main :-
|
|
|
649
855
|
Run with:
|
|
650
856
|
```typescript
|
|
651
857
|
for await (const event of dc.runDML(code, {
|
|
652
|
-
|
|
858
|
+
args: ['quantum computing']
|
|
653
859
|
})) {
|
|
654
860
|
console.log(event.type, event.content);
|
|
655
861
|
}
|
|
@@ -718,6 +924,11 @@ with_judgment(jev, choose("state", "Which team?", [billing, orders], Team)).
|
|
|
718
924
|
require_judgment(calibrated, verify("state", "Is this urgent?", Truth)).
|
|
719
925
|
```
|
|
720
926
|
|
|
927
|
+
> **In the DML REPL**, an `llm` backend is always registered (it reuses the
|
|
928
|
+
> active model), and `jev` is registered when `judgment.jev.enabled` is set in
|
|
929
|
+
> `.deepclause/config.json` and its API key is available. `with_judgment(jev,
|
|
930
|
+
> ...)` fails if `jev` is not registered.
|
|
931
|
+
|
|
721
932
|
`require_judgment/2` fails the wrapped goal before it runs when the active
|
|
722
933
|
backend does not provide the capability, so a skill that depends on calibrated
|
|
723
934
|
probabilities cannot silently run on an uncalibrated backend. Available
|
|
@@ -734,4 +945,33 @@ backtracking reuses an answer instead of re-querying the model.
|
|
|
734
945
|
- Values are constrained to the options/levels you supply. A `choose` answer is
|
|
735
946
|
always one of your option atoms.
|
|
736
947
|
- Prefer one `judge/2` batch over several one-off calls when you need more than
|
|
737
|
-
one or two judgments.
|
|
948
|
+
one or two judgments.
|
|
949
|
+
## The DML REPL (`deepclause repl`)
|
|
950
|
+
|
|
951
|
+
DML skills can also be grown interactively in a persistent **living module**.
|
|
952
|
+
|
|
953
|
+
- `/goal <dml>` runs a goal and enumerates its solutions (the legacy dotted
|
|
954
|
+
`goal: <dml>.` form still works).
|
|
955
|
+
- Plain English builds the module: the **authoring agent** inspects and edits it
|
|
956
|
+
through tools (`listing`, `begin_turn`, `define`/`assert`/`assert_many`,
|
|
957
|
+
`retract`/`delete`, `execute`, `end_turn`/`rollback`). Edits are transactions:
|
|
958
|
+
`begin_turn` is required before any edit, `end_turn` commits a version.
|
|
959
|
+
Nothing is auto-run; the agent uses `execute` to test during a turn.
|
|
960
|
+
- There is **no implicit `agent_main` requirement** in the REPL. Run any
|
|
961
|
+
predicate with `/goal <name>(…)`. Define `agent_main` in the module when it
|
|
962
|
+
should also run with `deepclause run` / `/dc-run`.
|
|
963
|
+
- `freeze.` makes the module read-only; `export <file>.` serializes it.
|
|
964
|
+
`export harness.zip` bundles the module with its linked script files;
|
|
965
|
+
`export harness.dml` inlines them into one portable file.
|
|
966
|
+
- `input/2` / `exec(ask_user(...))` (module) ask the human. They never block in
|
|
967
|
+
non-interactive runs (`-g`, piped stdin, CI).
|
|
968
|
+
|
|
969
|
+
**Self-containment.** The harness is the `.dml` **plus the files it links**.
|
|
970
|
+
Materialize each program with a DML goal (`make_directory_path(...)`,
|
|
971
|
+
`write_file(...)`), link it with `script_file(Name, Path)`, and run it with
|
|
972
|
+
`exec(bash(...))`. The
|
|
973
|
+
exporter bundles the linked files, so they travel with the harness. Pass
|
|
974
|
+
untrusted data through files or stdin, never interpolated into the shell
|
|
975
|
+
command.
|
|
976
|
+
|
|
977
|
+
See [`docs/REPL.md`](../../../../docs/REPL.md) for the full guide.
|