deepclause-sdk 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +446 -0
  2. package/dist/agent.d.ts +44 -0
  3. package/dist/agent.d.ts.map +1 -0
  4. package/dist/agent.js +518 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/cli/commands.d.ts +37 -0
  7. package/dist/cli/commands.d.ts.map +1 -0
  8. package/dist/cli/commands.js +105 -0
  9. package/dist/cli/commands.js.map +1 -0
  10. package/dist/cli/compile.d.ts +88 -0
  11. package/dist/cli/compile.d.ts.map +1 -0
  12. package/dist/cli/compile.js +362 -0
  13. package/dist/cli/compile.js.map +1 -0
  14. package/dist/cli/config.d.ts +265 -0
  15. package/dist/cli/config.d.ts.map +1 -0
  16. package/dist/cli/config.js +272 -0
  17. package/dist/cli/config.js.map +1 -0
  18. package/dist/cli/index.d.ts +8 -0
  19. package/dist/cli/index.d.ts.map +1 -0
  20. package/dist/cli/index.js +287 -0
  21. package/dist/cli/index.js.map +1 -0
  22. package/dist/cli/mcp.d.ts +56 -0
  23. package/dist/cli/mcp.d.ts.map +1 -0
  24. package/dist/cli/mcp.js +138 -0
  25. package/dist/cli/mcp.js.map +1 -0
  26. package/dist/cli/prompt.d.ts +20 -0
  27. package/dist/cli/prompt.d.ts.map +1 -0
  28. package/dist/cli/prompt.js +669 -0
  29. package/dist/cli/prompt.js.map +1 -0
  30. package/dist/cli/run.d.ts +33 -0
  31. package/dist/cli/run.d.ts.map +1 -0
  32. package/dist/cli/run.js +429 -0
  33. package/dist/cli/run.js.map +1 -0
  34. package/dist/cli/search.d.ts +25 -0
  35. package/dist/cli/search.d.ts.map +1 -0
  36. package/dist/cli/search.js +125 -0
  37. package/dist/cli/search.js.map +1 -0
  38. package/dist/cli/tools.d.ts +36 -0
  39. package/dist/cli/tools.d.ts.map +1 -0
  40. package/dist/cli/tools.js +204 -0
  41. package/dist/cli/tools.js.map +1 -0
  42. package/dist/cli/tui/index.d.ts +22 -0
  43. package/dist/cli/tui/index.d.ts.map +1 -0
  44. package/dist/cli/tui/index.js +29 -0
  45. package/dist/cli/tui/index.js.map +1 -0
  46. package/dist/index.d.ts +9 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +8 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/prolog/bridge.d.ts +21 -0
  51. package/dist/prolog/bridge.d.ts.map +1 -0
  52. package/dist/prolog/bridge.js +226 -0
  53. package/dist/prolog/bridge.js.map +1 -0
  54. package/dist/prolog/loader.d.ts +40 -0
  55. package/dist/prolog/loader.d.ts.map +1 -0
  56. package/dist/prolog/loader.js +133 -0
  57. package/dist/prolog/loader.js.map +1 -0
  58. package/dist/prolog-src/deepclause_memory.pl +45 -0
  59. package/dist/prolog-src/deepclause_mi.pl +1978 -0
  60. package/dist/prolog-src/deepclause_mi.pl.bak +570 -0
  61. package/dist/prolog-src/deepclause_strings.pl +89 -0
  62. package/dist/runner.d.ts +143 -0
  63. package/dist/runner.d.ts.map +1 -0
  64. package/dist/runner.js +1095 -0
  65. package/dist/runner.js.map +1 -0
  66. package/dist/sdk.d.ts +9 -0
  67. package/dist/sdk.d.ts.map +1 -0
  68. package/dist/sdk.js +131 -0
  69. package/dist/sdk.js.map +1 -0
  70. package/dist/tools.d.ts +22 -0
  71. package/dist/tools.d.ts.map +1 -0
  72. package/dist/tools.js +138 -0
  73. package/dist/tools.js.map +1 -0
  74. package/dist/types.d.ts +186 -0
  75. package/dist/types.d.ts.map +1 -0
  76. package/dist/types.js +5 -0
  77. package/dist/types.js.map +1 -0
  78. package/package.json +79 -0
  79. package/src/prolog-src/deepclause_memory.pl +45 -0
  80. package/src/prolog-src/deepclause_mi.pl +1978 -0
  81. package/src/prolog-src/deepclause_mi.pl.bak +570 -0
  82. package/src/prolog-src/deepclause_strings.pl +89 -0
  83. package/vendor/swipl-wasm/LICENSE.txt +41 -0
  84. package/vendor/swipl-wasm/dist/bin/index.js +25 -0
  85. package/vendor/swipl-wasm/dist/common.d.ts +88 -0
  86. package/vendor/swipl-wasm/dist/generateImage.d.ts +6 -0
  87. package/vendor/swipl-wasm/dist/generateImage.js +76 -0
  88. package/vendor/swipl-wasm/dist/index.d.ts +2 -0
  89. package/vendor/swipl-wasm/dist/index.js +1 -0
  90. package/vendor/swipl-wasm/dist/loadImage.d.ts +2 -0
  91. package/vendor/swipl-wasm/dist/loadImage.js +10 -0
  92. package/vendor/swipl-wasm/dist/loadImageDefault.d.ts +2 -0
  93. package/vendor/swipl-wasm/dist/loadImageDefault.js +11 -0
  94. package/vendor/swipl-wasm/dist/strToBuffer.d.ts +8 -0
  95. package/vendor/swipl-wasm/dist/strToBuffer.js +41 -0
  96. package/vendor/swipl-wasm/dist/swipl/swipl-bundle-no-data.d.ts +2 -0
  97. package/vendor/swipl-wasm/dist/swipl/swipl-bundle-no-data.js +2 -0
  98. package/vendor/swipl-wasm/dist/swipl/swipl-bundle.d.ts +2 -0
  99. package/vendor/swipl-wasm/dist/swipl/swipl-bundle.js +2 -0
  100. package/vendor/swipl-wasm/dist/swipl/swipl-web.d.ts +2 -0
  101. package/vendor/swipl-wasm/dist/swipl/swipl-web.data +0 -0
  102. package/vendor/swipl-wasm/dist/swipl/swipl-web.js +2 -0
  103. package/vendor/swipl-wasm/dist/swipl/swipl-web.wasm +0 -0
  104. package/vendor/swipl-wasm/dist/swipl/swipl-win.js +1 -0
  105. package/vendor/swipl-wasm/dist/swipl/swipl-win.wasm +0 -0
  106. package/vendor/swipl-wasm/dist/swipl/swipl.d.ts +2 -0
  107. package/vendor/swipl-wasm/dist/swipl/swipl.js +1 -0
  108. package/vendor/swipl-wasm/dist/swipl/swipl.wasm +0 -0
  109. package/vendor/swipl-wasm/dist/swipl-node.d.ts +2 -0
  110. package/vendor/swipl-wasm/dist/swipl-node.js +17 -0
  111. package/vendor/swipl-wasm/package.json +129 -0
@@ -0,0 +1,570 @@
1
+ /**
2
+ * deepclause_mi.pl - Meta-interpreter for DeepClause SDK
3
+ *
4
+ * The simplified meta-interpreter that handles:
5
+ * - task/1 and task/N predicates (agent loops)
6
+ * - exec/2 predicate (external tool calls)
7
+ * - Memory predicates (system, user, push_context, pop_context)
8
+ * - Output predicates (answer, yield, log)
9
+ * - Parameter handling
10
+ *
11
+ * Key design decisions:
12
+ * - No @-predicates - all LLM interaction via task()
13
+ * - Cooperative execution via engine yields
14
+ * - Backtrackable memory via push_context/pop_context
15
+ */
16
+
17
+ :- module(deepclause_mi, [
18
+ parse_dml/4,
19
+ create_engine/4,
20
+ step_engine/4,
21
+ destroy_engine/1,
22
+ post_agent_result/3,
23
+ post_exec_result/3,
24
+ provide_input/2,
25
+ mi/4
26
+ ]).
27
+
28
+ :- use_module(deepclause_memory).
29
+ :- use_module(deepclause_strings).
30
+
31
+ %% Dynamic predicates for session state
32
+ :- dynamic session_engine/2. % session_engine(SessionId, Engine)
33
+ :- dynamic session_memory/2. % session_memory(SessionId, MemoryId)
34
+ :- dynamic session_params/2. % session_params(SessionId, ParamsDict)
35
+ :- dynamic session_user_tools/2. % session_user_tools(SessionId, ToolName)
36
+ :- dynamic session_user_tool_schema/3. % session_user_tool_schema(SessionId, ToolName, Schema)
37
+ :- dynamic session_pending_input/2. % session_pending_input(SessionId, Input)
38
+ :- dynamic session_agent_result/2. % session_agent_result(SessionId, Result)
39
+ :- dynamic session_exec_result/2. % session_exec_result(SessionId, Result)
40
+
41
+ %% ============================================================
42
+ %% DML Parsing
43
+ %% ============================================================
44
+
45
+ %% parse_dml(+FilePath, +SessionId, +MemoryId, -Error)
46
+ %% Parse a DML file and load its clauses into the session module
47
+ parse_dml(FilePath, SessionId, MemoryId, Error) :-
48
+ catch(
49
+ (
50
+ read_file_to_string(FilePath, Code, []),
51
+ parse_dml_string(Code, SessionId, MemoryId),
52
+ Error = none
53
+ ),
54
+ ParseError,
55
+ format(atom(Error), '~w', [ParseError])
56
+ ).
57
+
58
+ %% parse_dml_string(+Code, +SessionId, +MemoryId)
59
+ %% Parse DML code from a string
60
+ parse_dml_string(Code, SessionId, MemoryId) :-
61
+ open_string(Code, Stream),
62
+ parse_clauses(Stream, SessionId, MemoryId),
63
+ close(Stream).
64
+
65
+ %% parse_clauses(+Stream, +SessionId, +MemoryId)
66
+ %% Read and process all clauses from a stream
67
+ parse_clauses(Stream, SessionId, MemoryId) :-
68
+ read_term(Stream, Term, [module(SessionId)]),
69
+ ( Term == end_of_file
70
+ -> true
71
+ ; process_clause(Term, SessionId, MemoryId),
72
+ parse_clauses(Stream, SessionId, MemoryId)
73
+ ).
74
+
75
+ %% process_clause(+Term, +SessionId, +MemoryId)
76
+ %% Process a single clause and add to session
77
+ process_clause((:- Directive), SessionId, _MemoryId) :-
78
+ !,
79
+ process_directive(Directive, SessionId).
80
+
81
+ %% Handle tool/2 with description: tool(Head, Description) :- Body
82
+ process_clause((tool(ToolHead, Description) :- Body), SessionId, _MemoryId) :-
83
+ !,
84
+ extract_tool_schema(ToolHead, Description, ToolName, Schema),
85
+ assertz(session_user_tools(SessionId, ToolName)),
86
+ assertz(session_user_tool_schema(SessionId, ToolName, Schema)),
87
+ % Store the source code for the tool description
88
+ format(string(SourceCode), "tool(~w, ~q) :-~n ~w.", [ToolHead, Description, Body]),
89
+ assertz(SessionId:tool_source(ToolName, SourceCode)),
90
+ % Assert the tool implementation (use just ToolHead for execution)
91
+ assertz(SessionId:(tool(ToolHead) :- Body)).
92
+
93
+ %% Handle tool/1 without description: tool(Head) :- Body
94
+ process_clause((tool(ToolHead) :- Body), SessionId, _MemoryId) :-
95
+ !,
96
+ extract_tool_schema(ToolHead, none, ToolName, Schema),
97
+ assertz(session_user_tools(SessionId, ToolName)),
98
+ assertz(session_user_tool_schema(SessionId, ToolName, Schema)),
99
+ % Store the source code for the tool description
100
+ format(string(SourceCode), "tool(~w) :-~n ~w.", [ToolHead, Body]),
101
+ assertz(SessionId:tool_source(ToolName, SourceCode)),
102
+ % Assert the tool implementation
103
+ assertz(SessionId:(tool(ToolHead) :- Body)).
104
+
105
+ process_clause((Head :- Body), SessionId, _MemoryId) :-
106
+ !,
107
+ % Regular clause - assert it
108
+ assertz(SessionId:(Head :- Body)).
109
+
110
+ process_clause(Fact, SessionId, _MemoryId) :-
111
+ % Simple fact
112
+ assertz(SessionId:Fact).
113
+
114
+ %% ============================================================
115
+ %% Tool Schema Extraction
116
+ %% ============================================================
117
+
118
+ %% extract_tool_schema(+ToolHead, +Description, -ToolName, -Schema)
119
+ %% Parse tool head to extract schema information
120
+ %% Schema = schema{name, description, inputs, outputs}
121
+ %% Each param = param{name, type, direction}
122
+ extract_tool_schema(ToolHead, Description, ToolName, Schema) :-
123
+ ToolHead =.. [ToolName|Args],
124
+ length(Args, Arity),
125
+ extract_params(Args, 1, Arity, Inputs, Outputs),
126
+ (Description == none -> Desc = "" ; Desc = Description),
127
+ Schema = schema{
128
+ name: ToolName,
129
+ description: Desc,
130
+ inputs: Inputs,
131
+ outputs: Outputs
132
+ }.
133
+
134
+ %% extract_params(+Args, +Index, +Arity, -Inputs, -Outputs)
135
+ %% Extract input and output parameters from argument list
136
+ %% Uses positional inference: first N-1 args are inputs, last arg is output
137
+ %% Parameter names are generic: arg1, arg2, etc.
138
+ extract_params([], _, _, [], []) :- !.
139
+ extract_params([_Arg|Rest], Index, Arity, Inputs, Outputs) :-
140
+ format(atom(Name), 'arg~w', [Index]),
141
+ Type = string, % Default type
142
+ NextIndex is Index + 1,
143
+ extract_params(Rest, NextIndex, Arity, RestInputs, RestOutputs),
144
+ Param = param{name: Name, type: Type},
145
+ % Last arg is output, all others are inputs
146
+ ( Index == Arity
147
+ -> Inputs = RestInputs, Outputs = [Param|RestOutputs]
148
+ ; Inputs = [Param|RestInputs], Outputs = RestOutputs
149
+ ).
150
+
151
+ %% process_directive(+Directive, +SessionId)
152
+ %% Handle directives like :- param(...)
153
+ process_directive(param(Key, Desc), SessionId) :-
154
+ !,
155
+ assertz(SessionId:param_decl(Key, Desc)).
156
+ process_directive(param(Key, Desc, Default), SessionId) :-
157
+ !,
158
+ assertz(SessionId:param_decl(Key, Desc, Default)).
159
+ process_directive(_, _).
160
+
161
+ %% ============================================================
162
+ %% Engine Management
163
+ %% ============================================================
164
+
165
+ %% create_engine(+SessionId, +MemoryId, +Params, -Engine)
166
+ %% Create a cooperative execution engine for agent_main
167
+ create_engine(SessionId, MemoryId, Params, Engine) :-
168
+ assertz(session_memory(SessionId, MemoryId)),
169
+ assertz(session_params(SessionId, Params)),
170
+ % Determine goal based on what agent_main arity is defined
171
+ determine_agent_goal(SessionId, Params, Goal),
172
+ % Create the engine - pass SessionId to mi/4
173
+ engine_create(_,
174
+ deepclause_mi:mi(Goal, MemoryId, Params, SessionId),
175
+ Engine),
176
+ assertz(session_engine(SessionId, Engine)).
177
+
178
+ %% determine_agent_goal(+SessionId, +Params, -Goal)
179
+ %% Determine the correct agent_main goal to call based on arity
180
+ determine_agent_goal(SessionId, _Params, SessionId:agent_main) :-
181
+ current_predicate(SessionId:agent_main/0), !.
182
+ determine_agent_goal(SessionId, Params, Goal) :-
183
+ current_predicate(SessionId:agent_main/1), !,
184
+ % Get first parameter value from dict
185
+ dict_pairs(Params, _, Pairs),
186
+ ( Pairs = [_-V1|_]
187
+ -> Goal = SessionId:agent_main(V1)
188
+ ; Goal = SessionId:agent_main(_)
189
+ ).
190
+ determine_agent_goal(SessionId, Params, Goal) :-
191
+ current_predicate(SessionId:agent_main/2), !,
192
+ dict_pairs(Params, _, Pairs),
193
+ ( Pairs = [_-V1, _-V2|_]
194
+ -> Goal = SessionId:agent_main(V1, V2)
195
+ ; Pairs = [_-V1|_]
196
+ -> Goal = SessionId:agent_main(V1, _)
197
+ ; Goal = SessionId:agent_main(_, _)
198
+ ).
199
+ determine_agent_goal(SessionId, _Params, SessionId:agent_main).
200
+
201
+ %% step_engine(+SessionId, -Status, -Content, -Payload)
202
+ %% Execute one step of the engine and return the result
203
+ step_engine(SessionId, Status, Content, Payload) :-
204
+ session_engine(SessionId, Engine),
205
+ ( engine_next(Engine, Result)
206
+ -> process_engine_result(Result, Status, Content, Payload)
207
+ ; Status = finished,
208
+ Content = '',
209
+ Payload = none
210
+ ).
211
+
212
+ %% process_engine_result(+Result, -Status, -Content, -Payload)
213
+ process_engine_result(output(Text), output, Text, none) :- !.
214
+ process_engine_result(log(Text), log, Text, none) :- !.
215
+ process_engine_result(answer(Text), answer, Text, none) :- !.
216
+ process_engine_result(request_agent_loop(Desc, Vars, Tools), request_agent_loop, '',
217
+ payload{taskDescription: Desc, outputVars: Vars, userTools: Tools}) :- !.
218
+ process_engine_result(request_exec(Tool, Args), request_exec, '',
219
+ payload{toolName: Tool, args: Args}) :- !.
220
+ process_engine_result(wait_input(Prompt), wait_input, Prompt, none) :- !.
221
+ process_engine_result(error(Msg), error, Msg, none) :- !.
222
+ process_engine_result(Other, error, Msg, none) :-
223
+ format(atom(Msg), 'Unknown engine result: ~w', [Other]).
224
+
225
+ %% destroy_engine(+SessionId)
226
+ %% Clean up engine and session state
227
+ destroy_engine(SessionId) :-
228
+ ( session_engine(SessionId, Engine)
229
+ -> catch(engine_destroy(Engine), _, true)
230
+ ; true
231
+ ),
232
+ retractall(session_engine(SessionId, _)),
233
+ retractall(session_memory(SessionId, _)),
234
+ retractall(session_params(SessionId, _)),
235
+ retractall(session_user_tools(SessionId, _)),
236
+ retractall(session_user_tool_schema(SessionId, _, _)),
237
+ retractall(session_pending_input(SessionId, _)),
238
+ retractall(session_agent_result(SessionId, _)),
239
+ retractall(session_exec_result(SessionId, _)),
240
+ % Clean up session module (if it exists)
241
+ ( current_module(SessionId)
242
+ -> catch(
243
+ ( findall(Head,
244
+ (current_predicate(SessionId:Name/Arity),
245
+ functor(Head, Name, Arity),
246
+ clause(SessionId:Head, _)),
247
+ Heads),
248
+ forall(member(H, Heads), retractall(SessionId:H))
249
+ ),
250
+ _,
251
+ true
252
+ )
253
+ ; true
254
+ ).
255
+
256
+ %% ============================================================
257
+ %% Result Posting (from JavaScript)
258
+ %% ============================================================
259
+
260
+ %% post_agent_result(+SessionId, +Success, +Variables)
261
+ %% Post the result of an agent loop back to the waiting engine
262
+ post_agent_result(SessionId, Success, Variables) :-
263
+ assertz(session_agent_result(SessionId, result{success: Success, variables: Variables})),
264
+ session_engine(SessionId, Engine),
265
+ engine_post(Engine, agent_done).
266
+
267
+ %% post_exec_result(+SessionId, +Status, +Result)
268
+ %% Post the result of an exec call back to the waiting engine
269
+ post_exec_result(SessionId, Status, Result) :-
270
+ assertz(session_exec_result(SessionId, result{status: Status, result: Result})),
271
+ session_engine(SessionId, Engine),
272
+ engine_post(Engine, exec_done).
273
+
274
+ %% provide_input(+SessionId, +Input)
275
+ %% Provide user input to a waiting engine
276
+ provide_input(SessionId, Input) :-
277
+ assertz(session_pending_input(SessionId, Input)),
278
+ session_engine(SessionId, Engine),
279
+ engine_post(Engine, input_provided).
280
+
281
+ %% ============================================================
282
+ %% Meta-Interpreter Core
283
+ %% ============================================================
284
+
285
+ %% mi(+Goal, +MemoryId, +Params, +SessionId)
286
+ %% Main meta-interpreter entry point
287
+ mi(Goal, MemoryId, Params, SessionId) :-
288
+ % Store session ID for use by get_session_id/1
289
+ nb_setval(current_session_id, SessionId),
290
+ catch(
291
+ mi_call(Goal, MemoryId, Params),
292
+ Error,
293
+ ( format(atom(ErrMsg), 'Runtime error: ~w', [Error]),
294
+ engine_yield(error(ErrMsg)),
295
+ fail
296
+ )
297
+ ).
298
+
299
+ %% ============================================================
300
+ %% Task Handling
301
+ %% ============================================================
302
+
303
+ %% collect_user_tools(+SessionId, -ToolSchemas)
304
+ %% Collect all user tool schemas for the session
305
+ collect_user_tools(SessionId, ToolSchemas) :-
306
+ findall(
307
+ tool_info{name: Name, schema: Schema, source: Source},
308
+ (
309
+ session_user_tool_schema(SessionId, Name, Schema),
310
+ (SessionId:tool_source(Name, Source) -> true ; Source = "")
311
+ ),
312
+ ToolSchemas
313
+ ).
314
+
315
+ %% mi_call(task(Desc), +MemoryId, +Params)
316
+ %% Handle task/1 - simple task without output variables
317
+ mi_call(task(Desc), MemoryId, Params) :-
318
+ !,
319
+ interpolate_desc(Desc, Params, InterpDesc),
320
+ get_session_id(SessionId),
321
+ collect_user_tools(SessionId, UserTools),
322
+ % Yield request to JavaScript with tool schemas
323
+ engine_yield(request_agent_loop(InterpDesc, [], UserTools)),
324
+ % Wait for result
325
+ engine_fetch(_Signal),
326
+ % Get and process result
327
+ session_agent_result(SessionId, Result),
328
+ retract(session_agent_result(SessionId, _)),
329
+ Result.success == true.
330
+
331
+ %% mi_call(task(Desc, Var1), +MemoryId, +Params)
332
+ %% Handle task/2 - task with one output variable
333
+ mi_call(task(Desc, Var1), MemoryId, Params) :-
334
+ !,
335
+ mi_call_task_n(Desc, [Var1], ['Var1'], MemoryId, Params).
336
+
337
+ %% mi_call(task(Desc, Var1, Var2), +MemoryId, +Params)
338
+ %% Handle task/3 - task with two output variables
339
+ mi_call(task(Desc, Var1, Var2), MemoryId, Params) :-
340
+ !,
341
+ mi_call_task_n(Desc, [Var1, Var2], ['Var1', 'Var2'], MemoryId, Params).
342
+
343
+ %% mi_call(task(Desc, Var1, Var2, Var3), +MemoryId, +Params)
344
+ %% Handle task/4 - task with three output variables
345
+ mi_call(task(Desc, Var1, Var2, Var3), MemoryId, Params) :-
346
+ !,
347
+ mi_call_task_n(Desc, [Var1, Var2, Var3], ['Var1', 'Var2', 'Var3'], MemoryId, Params).
348
+
349
+ %% mi_call_task_n(+Desc, +Vars, +VarNames, +MemoryId, +Params)
350
+ %% Generic handler for task/N with N-1 output variables
351
+ mi_call_task_n(Desc, Vars, VarNames, _MemoryId, Params) :-
352
+ interpolate_desc(Desc, Params, InterpDesc),
353
+ get_session_id(SessionId),
354
+ collect_user_tools(SessionId, UserTools),
355
+ % Yield request to JavaScript with tool schemas
356
+ engine_yield(request_agent_loop(InterpDesc, VarNames, UserTools)),
357
+ % Wait for result
358
+ engine_fetch(_Signal),
359
+ % Get and process result
360
+ session_agent_result(SessionId, Result),
361
+ retract(session_agent_result(SessionId, _)),
362
+ Result.success == true,
363
+ % Bind output variables
364
+ bind_task_variables(Result.variables, VarNames, Vars).
365
+
366
+ %% bind_task_variables(+VarsDict, +Names, -Values)
367
+ bind_task_variables(_, [], []) :- !.
368
+ bind_task_variables(VarsDict, [Name|Names], [Value|Values]) :-
369
+ ( get_dict(Name, VarsDict, Value)
370
+ -> true
371
+ ; true % Leave unbound if not present
372
+ ),
373
+ bind_task_variables(VarsDict, Names, Values).
374
+
375
+ %% ============================================================
376
+ %% Exec Handling
377
+ %% ============================================================
378
+
379
+ %% mi_call(exec(ToolCall, Output), +MemoryId, +Params)
380
+ %% Handle exec/2 - external tool execution
381
+ mi_call(exec(ToolCall, Output), _MemoryId, _Params) :-
382
+ !,
383
+ ToolCall =.. [ToolName|Args],
384
+ get_session_id(SessionId),
385
+ % Yield request to JavaScript
386
+ engine_yield(request_exec(ToolName, Args)),
387
+ % Wait for result
388
+ engine_fetch(_Signal),
389
+ % Get and process result
390
+ session_exec_result(SessionId, Result),
391
+ retract(session_exec_result(SessionId, _)),
392
+ ( Result.status == success
393
+ -> Output = Result.result
394
+ ; fail
395
+ ).
396
+
397
+ %% ============================================================
398
+ %% Memory Predicates
399
+ %% ============================================================
400
+
401
+ %% mi_call(system(Text), +MemoryId, +Params)
402
+ mi_call(system(Text), MemoryId, Params) :-
403
+ !,
404
+ interpolate_desc(Text, Params, InterpText),
405
+ deepclause_memory:push_memory(MemoryId, message{role: system, content: InterpText}).
406
+
407
+ %% mi_call(user(Text), +MemoryId, +Params)
408
+ mi_call(user(Text), MemoryId, Params) :-
409
+ !,
410
+ interpolate_desc(Text, Params, InterpText),
411
+ deepclause_memory:push_memory(MemoryId, message{role: user, content: InterpText}).
412
+
413
+ %% mi_call(push_context, +MemoryId, +Params)
414
+ mi_call(push_context, MemoryId, _Params) :-
415
+ !,
416
+ deepclause_memory:push_context(MemoryId).
417
+
418
+ %% mi_call(pop_context, +MemoryId, +Params)
419
+ mi_call(pop_context, MemoryId, _Params) :-
420
+ !,
421
+ deepclause_memory:pop_context(MemoryId).
422
+
423
+ %% ============================================================
424
+ %% Output Predicates
425
+ %% ============================================================
426
+
427
+ %% mi_call(answer(Text), +MemoryId, +Params)
428
+ mi_call(answer(Text), _MemoryId, Params) :-
429
+ !,
430
+ interpolate_desc(Text, Params, InterpText),
431
+ engine_yield(answer(InterpText)).
432
+
433
+ %% mi_call(yield(Text), +MemoryId, +Params)
434
+ mi_call(yield(Text), _MemoryId, Params) :-
435
+ !,
436
+ interpolate_desc(Text, Params, InterpText),
437
+ engine_yield(output(InterpText)).
438
+
439
+ %% mi_call(log(Text), +MemoryId, +Params)
440
+ mi_call(log(Text), _MemoryId, Params) :-
441
+ !,
442
+ interpolate_desc(Text, Params, InterpText),
443
+ engine_yield(log(InterpText)).
444
+
445
+ %% ============================================================
446
+ %% Parameter Handling
447
+ %% ============================================================
448
+
449
+ %% mi_call(param(Key, Desc, Value), +MemoryId, +Params)
450
+ mi_call(param(Key, _Desc, Value), _MemoryId, Params) :-
451
+ !,
452
+ ( atom(Key)
453
+ -> KeyAtom = Key
454
+ ; atom_string(KeyAtom, Key)
455
+ ),
456
+ get_dict(KeyAtom, Params, Value).
457
+
458
+ %% ============================================================
459
+ %% Control Flow
460
+ %% ============================================================
461
+
462
+ %% mi_call((A, B), +MemoryId, +Params)
463
+ mi_call((A, B), MemoryId, Params) :-
464
+ !,
465
+ mi_call(A, MemoryId, Params),
466
+ mi_call(B, MemoryId, Params).
467
+
468
+ %% mi_call((A ; B), +MemoryId, +Params)
469
+ mi_call((A ; B), MemoryId, Params) :-
470
+ !,
471
+ ( mi_call(A, MemoryId, Params)
472
+ ; mi_call(B, MemoryId, Params)
473
+ ).
474
+
475
+ %% mi_call((Cond -> Then ; Else), +MemoryId, +Params)
476
+ mi_call((Cond -> Then ; Else), MemoryId, Params) :-
477
+ !,
478
+ ( mi_call(Cond, MemoryId, Params)
479
+ -> mi_call(Then, MemoryId, Params)
480
+ ; mi_call(Else, MemoryId, Params)
481
+ ).
482
+
483
+ %% mi_call((Cond -> Then), +MemoryId, +Params)
484
+ mi_call((Cond -> Then), MemoryId, Params) :-
485
+ !,
486
+ ( mi_call(Cond, MemoryId, Params)
487
+ -> mi_call(Then, MemoryId, Params)
488
+ ).
489
+
490
+ %% mi_call(\+(Goal), +MemoryId, +Params)
491
+ mi_call(\+(Goal), MemoryId, Params) :-
492
+ !,
493
+ \+ mi_call(Goal, MemoryId, Params).
494
+
495
+ %% mi_call(!, +MemoryId, +Params)
496
+ mi_call(!, _MemoryId, _Params) :-
497
+ !.
498
+
499
+ %% mi_call(true, +MemoryId, +Params)
500
+ mi_call(true, _MemoryId, _Params) :-
501
+ !.
502
+
503
+ %% mi_call(fail, +MemoryId, +Params)
504
+ mi_call(fail, _MemoryId, _Params) :-
505
+ !,
506
+ fail.
507
+
508
+ %% mi_call(false, +MemoryId, +Params)
509
+ mi_call(false, _MemoryId, _Params) :-
510
+ !,
511
+ fail.
512
+
513
+ %% ============================================================
514
+ %% Module-Qualified Goals
515
+ %% ============================================================
516
+
517
+ %% mi_call(Module:Goal, +MemoryId, +Params)
518
+ mi_call(Module:Goal, MemoryId, Params) :-
519
+ !,
520
+ ( % Check if it's a user-defined predicate that needs meta-interpretation
521
+ callable(Module:Goal), clause(Module:Goal, Body),
522
+ Body \== true
523
+ -> mi_call(Body, MemoryId, Params)
524
+ ; % Try direct call
525
+ call(Module:Goal)
526
+ ).
527
+
528
+ %% ============================================================
529
+ %% Built-in and User-Defined Predicates
530
+ %% ============================================================
531
+
532
+ %% mi_call(Goal, +MemoryId, +Params)
533
+ %% Default handler - try built-in first, then user-defined
534
+ mi_call(Goal, MemoryId, Params) :-
535
+ % Guard: Goal must be callable (not a variable)
536
+ ( var(Goal)
537
+ -> throw(error(instantiation_error, mi_call/3))
538
+ ; true
539
+ ),
540
+ % Try as built-in
541
+ ( predicate_property(Goal, built_in)
542
+ -> call(Goal)
543
+ ; % Try as user-defined with meta-interpretation
544
+ get_session_id(SessionId),
545
+ callable(Goal),
546
+ catch(clause(SessionId:Goal, Body), _, fail)
547
+ -> mi_call(Body, MemoryId, Params)
548
+ ; % Final fallback - direct call
549
+ call(Goal)
550
+ ).
551
+
552
+ %% ============================================================
553
+ %% Helper Predicates
554
+ %% ============================================================
555
+
556
+ %% interpolate_desc(+Template, +Params, -Result)
557
+ %% Expand {Variable} patterns using params
558
+ interpolate_desc(Template, Params, Result) :-
559
+ ( is_dict(Params)
560
+ -> dict_pairs(Params, _, Pairs),
561
+ maplist([K-V, K=V]>>true, Pairs, Bindings),
562
+ deepclause_strings:interpolate_string(Template, Bindings, Result)
563
+ ; Result = Template
564
+ ).
565
+
566
+ %% get_session_id(-SessionId)
567
+ %% Extract session ID from current execution context
568
+ get_session_id(SessionId) :-
569
+ nb_current(current_session_id, SessionId), !.
570
+ get_session_id(default_session).
@@ -0,0 +1,89 @@
1
+ /**
2
+ * deepclause_strings.pl - String interpolation for DeepClause SDK
3
+ *
4
+ * Provides:
5
+ * - interpolate_string/3: Replace {Variable} patterns with values
6
+ */
7
+
8
+ :- module(deepclause_strings, [
9
+ interpolate_string/3,
10
+ dml_string_expand/3
11
+ ]).
12
+
13
+ %% interpolate_string(+Template, +Bindings, -Result)
14
+ %% Replace {VariableName} patterns in Template with values from Bindings
15
+ %% Bindings is a list of Name=Value pairs
16
+ interpolate_string(Template, Bindings, Result) :-
17
+ ( string(Template)
18
+ -> atom_string(TemplateAtom, Template)
19
+ ; TemplateAtom = Template
20
+ ),
21
+ interpolate_atom(TemplateAtom, Bindings, ResultAtom),
22
+ atom_string(ResultAtom, Result).
23
+
24
+ %% interpolate_atom(+Template, +Bindings, -Result)
25
+ interpolate_atom(Template, Bindings, Result) :-
26
+ atom_codes(Template, Codes),
27
+ interpolate_codes(Codes, Bindings, ResultCodes),
28
+ atom_codes(Result, ResultCodes).
29
+
30
+ %% interpolate_codes(+Codes, +Bindings, -ResultCodes)
31
+ %% Process character codes, replacing {var} patterns
32
+ interpolate_codes([], _, []) :- !.
33
+
34
+ % Found opening brace - extract variable name
35
+ interpolate_codes([0'{|Rest], Bindings, Result) :-
36
+ !,
37
+ extract_var_name(Rest, VarNameCodes, AfterVar),
38
+ atom_codes(VarName, VarNameCodes),
39
+ ( find_binding(VarName, Bindings, Value)
40
+ -> format(atom(ValueAtom), '~w', [Value]),
41
+ atom_codes(ValueAtom, ValueCodes),
42
+ interpolate_codes(AfterVar, Bindings, RestResult),
43
+ append(ValueCodes, RestResult, Result)
44
+ ; % Variable not found - keep as is
45
+ interpolate_codes(AfterVar, Bindings, RestResult),
46
+ append([0'{|VarNameCodes], [0'}|RestResult], Result)
47
+ ).
48
+
49
+ % Regular character - keep it
50
+ interpolate_codes([C|Rest], Bindings, [C|Result]) :-
51
+ interpolate_codes(Rest, Bindings, Result).
52
+
53
+ %% extract_var_name(+Codes, -VarNameCodes, -RemainingCodes)
54
+ %% Extract characters until closing brace
55
+ extract_var_name([0'}|Rest], [], Rest) :- !.
56
+ extract_var_name([C|Rest], [C|VarRest], Final) :-
57
+ C \= 0'},
58
+ extract_var_name(Rest, VarRest, Final).
59
+ extract_var_name([], [], []). % Handle unclosed brace gracefully
60
+
61
+ %% find_binding(+VarName, +Bindings, -Value)
62
+ %% Look up a variable in the bindings list
63
+ find_binding(VarName, Bindings, Value) :-
64
+ ( member(VarName=Value, Bindings)
65
+ -> true
66
+ ; % Also try with atom version
67
+ atom_string(VarNameAtom, VarName),
68
+ member(VarNameAtom=Value, Bindings)
69
+ ; % Try dict-style binding
70
+ is_dict(Bindings),
71
+ get_dict(VarName, Bindings, Value)
72
+ ).
73
+
74
+ %% dml_string_expand(+Term, +Bindings, -Expanded)
75
+ %% Expand strings within a term
76
+ dml_string_expand(Term, Bindings, Expanded) :-
77
+ ( string(Term)
78
+ -> interpolate_string(Term, Bindings, Expanded)
79
+ ; atom(Term)
80
+ -> interpolate_string(Term, Bindings, ExpandedStr),
81
+ atom_string(Expanded, ExpandedStr)
82
+ ; is_list(Term)
83
+ -> maplist({Bindings}/[T, E]>>dml_string_expand(T, Bindings, E), Term, Expanded)
84
+ ; compound(Term)
85
+ -> Term =.. [Functor|Args],
86
+ maplist({Bindings}/[A, EA]>>dml_string_expand(A, Bindings, EA), Args, ExpandedArgs),
87
+ Expanded =.. [Functor|ExpandedArgs]
88
+ ; Expanded = Term
89
+ ).
@@ -0,0 +1,41 @@
1
+ # SWI-Prolog copyright status
2
+
3
+ SWI-Prolog is covered by the Simplified BSD license:
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright
13
+ notice, this list of conditions and the following disclaimer in
14
+ the documentation and/or other materials provided with the
15
+ distribution.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20
+ FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
+ COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23
+ BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ ## Possible additional license requirements
31
+
32
+ Note that SWI-Prolog may be linked with libraries covered by more
33
+ restrictive license and therefore the above conditions may not suffice
34
+ for a particular version of SWI-Prolog or a program loaded into
35
+ SWI-Prolog. Run the following predicate to find which components with
36
+ additional requirements are loaded into a particular version.
37
+
38
+ ```
39
+ ?- license.
40
+ ```
41
+