deepclause-sdk 0.0.72 → 0.0.74

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.
@@ -17,12 +17,13 @@
17
17
 
18
18
  :- module(deepclause_mi, [
19
19
  parse_dml/5,
20
- create_engine/5,
20
+ create_engine/6,
21
21
  step_engine/4,
22
22
  destroy_engine/1,
23
23
  post_agent_result/4,
24
24
  post_exec_result/3,
25
25
  post_sample_token_result/3,
26
+ post_llm_result/3,
26
27
  provide_input/2,
27
28
  mi/3,
28
29
  % Tool engine predicates for isolated tool execution
@@ -48,6 +49,7 @@
48
49
  :- dynamic session_agent_result/2. % session_agent_result(SessionId, Result)
49
50
  :- dynamic session_exec_result/2. % session_exec_result(SessionId, Result)
50
51
  :- dynamic session_sample_token_result/2. % session_sample_token_result(SessionId, Result)
52
+ :- dynamic session_llm_result/2. % session_llm_result(SessionId, Result)
51
53
  :- dynamic session_trace_log/2. % session_trace_log(SessionId, TraceLog) - accumulated trace entries
52
54
  :- dynamic session_trace_enabled/2. % session_trace_enabled(SessionId, true/false)
53
55
  :- dynamic session_pending_signal/2. % session_pending_signal(SessionId, Signal) - fallback for engine_fetch
@@ -462,10 +464,10 @@ process_directive(_, _).
462
464
  %% Engine Management
463
465
  %% ============================================================
464
466
 
465
- %% create_engine(+SessionId, +MemoryId, +Args, +Params, -Engine)
467
+ %% create_engine(+SessionId, +MemoryId, +Args, +Params, +InitialMemory, -Engine)
466
468
  %% Args is a list of positional arguments for agent_main
467
469
  %% Params is a dict of named parameters (already asserted as param/2 facts)
468
- create_engine(SessionId, _MemoryId, Args, Params, Engine) :-
470
+ create_engine(SessionId, _MemoryId, Args, Params, InitialMemory, Engine) :-
469
471
  assertz(session_params(SessionId, Params)),
470
472
  determine_agent_goal(SessionId, Args, Goal),
471
473
  % Check if tracing is enabled and store in session state
@@ -474,8 +476,8 @@ create_engine(SessionId, _MemoryId, Args, Params, Engine) :-
474
476
  assertz(session_trace_log(SessionId, [])),
475
477
  % Check for gas limit in params
476
478
  (get_dict(gas_limit, Params, GasLimit) -> true ; GasLimit = -1),
477
- % Create initial state with empty memory, params, context stack, trace depth and gas
478
- InitialState = state{memory: [], params: Params, context_stack: [], depth: 0, gas_remaining: GasLimit},
479
+ % Create initial state with provided memory, params, context stack, trace depth and gas
480
+ InitialState = state{memory: InitialMemory, params: Params, context_stack: [], depth: 0, gas_remaining: GasLimit},
479
481
  % Create the engine - pass SessionId and initial state to mi/3
480
482
  engine_create(_,
481
483
  deepclause_mi:mi(Goal, InitialState, SessionId),
@@ -565,6 +567,8 @@ process_engine_result(request_exec(Tool, Args), request_exec, '',
565
567
  payload{toolName: Tool, args: Args}) :- !.
566
568
  process_engine_result(request_sample_token(Prompt, Allowed), request_sample_token, '',
567
569
  payload{prompt: Prompt, allowedTokens: Allowed}) :- !.
570
+ process_engine_result(request_llm(Messages), request_llm, '',
571
+ payload{messages: Messages}) :- !.
568
572
  %% Tool result from inline tool execution
569
573
  process_engine_result(tool_result(Result), tool_result, '',
570
574
  payload{result: Result}) :- !.
@@ -587,6 +591,7 @@ destroy_engine(SessionId) :-
587
591
  retractall(session_agent_result(SessionId, _)),
588
592
  retractall(session_exec_result(SessionId, _)),
589
593
  retractall(session_sample_token_result(SessionId, _)),
594
+ retractall(session_llm_result(SessionId, _)),
590
595
  retractall(session_trace_log(SessionId, _)),
591
596
  retractall(session_trace_enabled(SessionId, _)),
592
597
  ( current_module(SessionId)
@@ -633,6 +638,12 @@ post_sample_token_result(SessionId, Status, TokenOrError) :-
633
638
  assertz(session_sample_token_result(SessionId, result{status: Status, token: TokenOrError})),
634
639
  post_signal_to_engine(SessionId, sample_token_done).
635
640
 
641
+ %% post_llm_result(+SessionId, +Status, +TextOrError)
642
+ post_llm_result(SessionId, Status, TextOrError) :-
643
+ retractall(session_llm_result(SessionId, _)),
644
+ assertz(session_llm_result(SessionId, result{status: Status, text: TextOrError})),
645
+ post_signal_to_engine(SessionId, llm_done).
646
+
636
647
  %% provide_input(+SessionId, +Input)
637
648
  provide_input(SessionId, Input) :-
638
649
  assertz(session_pending_input(SessionId, Input)),
@@ -821,6 +832,11 @@ handle_signal(SessionId, exec_done, StateIn, StateOut) :-
821
832
  !,
822
833
  handle_agent_signals(SessionId, StateIn, StateOut).
823
834
 
835
+ handle_signal(SessionId, llm_done, StateIn, StateOut) :-
836
+ % Stale signal - ignore and continue waiting
837
+ !,
838
+ handle_agent_signals(SessionId, StateIn, StateOut).
839
+
824
840
  handle_signal(SessionId, _Unknown, StateIn, StateOut) :-
825
841
  % Unknown signal - ignore and continue waiting
826
842
  !,
@@ -963,6 +979,8 @@ process_tool_engine_result(request_exec(Tool, Args), request_exec, '',
963
979
  payload{toolName: Tool, args: Args}) :- !.
964
980
  process_tool_engine_result(request_sample_token(Prompt, Allowed), request_sample_token, '',
965
981
  payload{prompt: Prompt, allowedTokens: Allowed}) :- !.
982
+ process_tool_engine_result(request_llm(Messages), request_llm, '',
983
+ payload{messages: Messages}) :- !.
966
984
  process_tool_engine_result(request_agent_loop(Desc, Vars, Tools, Memory, ToolScope), request_agent_loop, '',
967
985
  payload{taskDescription: Desc, outputVars: Vars, userTools: Tools, memory: Memory, toolScope: ToolScope}) :- !.
968
986
  %% Legacy 4-arg format (no tool scope)
@@ -1229,6 +1247,45 @@ wait_sample_token_signal(SessionId) :-
1229
1247
  ; wait_sample_token_signal(SessionId)
1230
1248
  ).
1231
1249
 
1250
+ mi_call(llm(Messages, Reply), StateIn, StateOut) :-
1251
+ !,
1252
+ consume_gas(StateIn, State1),
1253
+ mi_call_llm(Messages, Reply, State1, StateOut).
1254
+
1255
+ mi_call_llm(Messages, Reply, StateIn, StateOut) :-
1256
+ get_session_id(SessionId),
1257
+ get_depth(StateIn, Depth),
1258
+ add_trace_entry(SessionId, llm_call, llm, [Messages], Depth),
1259
+ engine_yield(request_llm(Messages)),
1260
+ wait_llm_signal(SessionId),
1261
+ ( session_llm_result(SessionId, Result)
1262
+ -> retract(session_llm_result(SessionId, _)),
1263
+ ( Result.status == success
1264
+ -> Reply = Result.text,
1265
+ add_trace_with_result(SessionId, exit, llm, [Messages], Reply, Depth),
1266
+ StateOut = StateIn
1267
+ ; ( get_dict(text, Result, ErrorMsg), ErrorMsg \= ""
1268
+ -> format(atom(WarnMsg), 'Warning: llm/2 failed: ~w', [ErrorMsg])
1269
+ ; format(atom(WarnMsg), 'Warning: llm/2 failed (status=~w)', [Result.status])
1270
+ ),
1271
+ add_trace_entry(SessionId, fail, llm, [Messages], Depth),
1272
+ engine_yield(output(WarnMsg)),
1273
+ fail
1274
+ )
1275
+ ; add_trace_entry(SessionId, fail, llm, [Messages], Depth),
1276
+ engine_yield(output('Warning: llm/2 failed (no result returned)')),
1277
+ fail
1278
+ ).
1279
+
1280
+ wait_llm_signal(SessionId) :-
1281
+ get_next_signal(SessionId, Signal),
1282
+ ( Signal == llm_done
1283
+ -> true
1284
+ ; Signal = error_signal(_)
1285
+ -> true
1286
+ ; wait_llm_signal(SessionId)
1287
+ ).
1288
+
1232
1289
  %% mi_call_task_n(+Desc, +Vars, +VarNames, +StateIn, -StateOut)
1233
1290
  mi_call_task_n(Desc, Vars, VarNames, StateIn, StateOut) :-
1234
1291
  !, % Cut to make this predicate deterministic - no backtracking once started
@@ -1364,6 +1421,11 @@ mi_call(user(Text), StateIn, StateOut) :-
1364
1421
  interpolate_desc(Text, Params, InterpText),
1365
1422
  add_memory(StateIn, user, InterpText, StateOut).
1366
1423
 
1424
+ %% mi_call(get_memory(Messages), +StateIn, -StateOut)
1425
+ mi_call(get_memory(Messages), StateIn, StateIn) :-
1426
+ !,
1427
+ get_memory(StateIn, Messages).
1428
+
1367
1429
  %% ============================================================
1368
1430
  %% Output Predicates
1369
1431
  %% ============================================================
@@ -2027,10 +2089,12 @@ is_mi_special_predicate(prompt(_,_)).
2027
2089
  is_mi_special_predicate(prompt(_,_,_)).
2028
2090
  is_mi_special_predicate(prompt(_,_,_,_)).
2029
2091
  is_mi_special_predicate(prompt_named(_,_,_)). %% Transformed form of prompt/N
2092
+ is_mi_special_predicate(llm(_,_)).
2030
2093
  %% Tool scoping predicates
2031
2094
  is_mi_special_predicate(with_tools(_,_)).
2032
2095
  is_mi_special_predicate(without_tools(_,_)).
2033
2096
  %% Context stack management
2097
+ is_mi_special_predicate(get_memory(_)).
2034
2098
  is_mi_special_predicate(push_context).
2035
2099
  is_mi_special_predicate(push_context(_)).
2036
2100
  is_mi_special_predicate(pop_context).
package/dist/runner.d.ts CHANGED
@@ -25,10 +25,7 @@ export interface InternalRunOptions {
25
25
  toolPolicy: ToolPolicy | null;
26
26
  onInputRequired: (prompt: string) => Promise<string>;
27
27
  signal?: AbortSignal;
28
- initialMessages?: Array<{
29
- role: 'user' | 'assistant';
30
- content: string;
31
- }>;
28
+ initialMessages?: MemoryMessage[];
32
29
  compaction?: CompactionOptions;
33
30
  }
34
31
  /**
@@ -45,7 +42,6 @@ export declare class DMLRunner {
45
42
  private engine;
46
43
  private sessionId;
47
44
  private currentMemory;
48
- private initialMessagesApplied;
49
45
  constructor(swipl: SWIPLModule, options: RunnerOptions);
50
46
  /**
51
47
  * Get the current conversation memory
@@ -92,6 +88,10 @@ export declare class DMLRunner {
92
88
  * Handle one-token sampling request (sample_token/2-3)
93
89
  */
94
90
  private handleSampleToken;
91
+ /**
92
+ * Handle direct one-shot LLM request (llm/2)
93
+ */
94
+ private handleLlm;
95
95
  /**
96
96
  * Handle exec request (exec() predicate)
97
97
  */
@@ -132,6 +132,7 @@ export declare class DMLRunner {
132
132
  /**
133
133
  * Extract memory from payload (now passed via state threading)
134
134
  */
135
+ private extractMessagesFromValue;
135
136
  private extractMemoryFromPayload;
136
137
  private serializeMemoryMessages;
137
138
  /**
@@ -146,6 +147,10 @@ export declare class DMLRunner {
146
147
  * Post one-token sampling result back to Prolog
147
148
  */
148
149
  private postSampleTokenResult;
150
+ /**
151
+ * Post direct llm/2 result back to Prolog
152
+ */
153
+ private postLlmResult;
149
154
  /**
150
155
  * Post tool engine agent loop result back to Prolog
151
156
  */
@@ -1 +1 @@
1
- {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"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"}
package/dist/runner.js CHANGED
@@ -8,7 +8,7 @@ import { runAgentLoop } from './agent.js';
8
8
  import { executeCompactor, getCompactionBindings, resolveCompactionOptions, } from './compaction.js';
9
9
  import { buildToolCompletionEvent, buildToolFailureEvent, buildToolStartEvent, } from './system/runtime/shell-tool-events.js';
10
10
  import { checkToolPolicy } from './tools.js';
11
- import { sampleSingleToken } from './prolog/bridge.js';
11
+ import { generateLlmReply, sampleSingleToken } from './prolog/bridge.js';
12
12
  /**
13
13
  * Convert swipl-wasm value to plain JavaScript value
14
14
  * Handles PrologString, PrologAtom, PrologList, etc.
@@ -142,7 +142,6 @@ export class DMLRunner {
142
142
  engine = null;
143
143
  sessionId = '';
144
144
  currentMemory = [];
145
- initialMessagesApplied = false;
146
145
  constructor(swipl, options) {
147
146
  this.swipl = swipl;
148
147
  this.options = options;
@@ -172,8 +171,11 @@ export class DMLRunner {
172
171
  return;
173
172
  }
174
173
  }
175
- // Memory is now managed internally by the MI via state threading
176
- // No external initialization needed
174
+ // Seed the MI state so top-level DML can inspect initial messages via get_memory/1.
175
+ this.currentMemory = (options.initialMessages ?? []).map((message) => ({
176
+ role: message.role,
177
+ content: message.content,
178
+ }));
177
179
  // Build args and params
178
180
  const args = this.buildArgs(options);
179
181
  const params = this.buildParams(options);
@@ -235,6 +237,9 @@ export class DMLRunner {
235
237
  case 'request_sample_token':
236
238
  yield* this.handleSampleToken(step.payload, options);
237
239
  break;
240
+ case 'request_llm':
241
+ yield* this.handleLlm(step.payload, options);
242
+ break;
238
243
  case 'wait_input':
239
244
  // Request user input
240
245
  yield { type: 'input_required', prompt: step.prompt };
@@ -366,7 +371,8 @@ export class DMLRunner {
366
371
  */
367
372
  createEngine(memoryId, args, params) {
368
373
  try {
369
- const result = this.query(`deepclause_mi:create_engine('${this.sessionId}', '${memoryId}', ${args}, ${params}, Engine)`);
374
+ const initialMemory = this.serializeMemoryMessages(this.currentMemory);
375
+ const result = this.query(`deepclause_mi:create_engine('${this.sessionId}', '${memoryId}', ${args}, ${params}, [${initialMemory}], Engine)`);
370
376
  if (result && result.Engine) {
371
377
  this.engine = result.Engine;
372
378
  return {};
@@ -436,18 +442,7 @@ export class DMLRunner {
436
442
  }
437
443
  };
438
444
  // Extract memory from payload (now passed via state threading)
439
- const memory = this.extractMemoryFromPayload(rawPayload);
440
- // Prepend initial conversation messages (from RunOptions.initialMessages)
441
- // Only on the FIRST task() call — after that, persistent messages already include them.
442
- const initialMsgs = (!this.initialMessagesApplied && options.initialMessages?.length)
443
- ? options.initialMessages
444
- : undefined;
445
- const fullMemory = initialMsgs
446
- ? [...initialMsgs, ...memory]
447
- : memory;
448
- if (initialMsgs)
449
- this.initialMessagesApplied = true;
450
- const preparedMemory = fullMemory;
445
+ const preparedMemory = this.extractMemoryFromPayload(rawPayload);
451
446
  // Store current memory for getMemory() access
452
447
  this.currentMemory = preparedMemory;
453
448
  const emitToolEvent = (event) => {
@@ -658,6 +653,33 @@ export class DMLRunner {
658
653
  yield { type: 'log', content: `sample_token failed: ${message}` };
659
654
  }
660
655
  }
656
+ /**
657
+ * Handle direct one-shot LLM request (llm/2)
658
+ */
659
+ async *handleLlm(payload, options) {
660
+ const data = payload;
661
+ const messages = this.extractMessagesFromValue(data.messages);
662
+ try {
663
+ const text = await generateLlmReply({
664
+ messages,
665
+ modelOptions: {
666
+ provider: this.options.provider,
667
+ model: this.options.model,
668
+ temperature: this.options.temperature,
669
+ maxOutputTokens: this.options.maxTokens,
670
+ baseUrl: this.options.baseUrl,
671
+ providerOptions: this.options.providerOptions,
672
+ },
673
+ signal: options.signal,
674
+ });
675
+ this.postLlmResult({ success: true, text });
676
+ }
677
+ catch (error) {
678
+ const message = error instanceof Error ? error.message : String(error);
679
+ this.postLlmResult({ success: false, error: message });
680
+ yield { type: 'log', content: `llm/2 failed: ${message}` };
681
+ }
682
+ }
661
683
  /**
662
684
  * Handle exec request (exec() predicate)
663
685
  */
@@ -1024,6 +1046,32 @@ export class DMLRunner {
1024
1046
  }
1025
1047
  break;
1026
1048
  }
1049
+ case 'request_llm': {
1050
+ const messages = this.extractMessagesFromValue(payload?.messages);
1051
+ try {
1052
+ const text = await generateLlmReply({
1053
+ messages,
1054
+ modelOptions: {
1055
+ provider: this.options.provider,
1056
+ model: this.options.model,
1057
+ temperature: this.options.temperature,
1058
+ maxOutputTokens: this.options.maxTokens,
1059
+ baseUrl: this.options.baseUrl,
1060
+ providerOptions: this.options.providerOptions,
1061
+ },
1062
+ signal: runContext.signal,
1063
+ });
1064
+ this.postLlmResult({ success: true, text });
1065
+ }
1066
+ catch (error) {
1067
+ const message = error instanceof Error ? error.message : String(error);
1068
+ this.postLlmResult({ success: false, error: message });
1069
+ if (process.env.DEBUG_RUNNER) {
1070
+ console.log('[RUNNER] llm/2 request failed:', message);
1071
+ }
1072
+ }
1073
+ break;
1074
+ }
1027
1075
  case 'request_agent_loop': {
1028
1076
  // Tool is calling task() or prompt() - run nested agent loop
1029
1077
  const taskDescription = String(payload?.taskDescription ?? '');
@@ -1227,6 +1275,7 @@ export class DMLRunner {
1227
1275
  const result = await executeCompactor({
1228
1276
  binding,
1229
1277
  messages,
1278
+ emitEvent: params.emitEvent,
1230
1279
  execute: (request) => this.runBoundCompactor({
1231
1280
  request,
1232
1281
  executionContext: params.executionContext,
@@ -1261,6 +1310,7 @@ export class DMLRunner {
1261
1310
  workspacePath: params.executionContext.workspacePath,
1262
1311
  gasLimit: binding.compactor.gasLimit,
1263
1312
  params: compactorParams,
1313
+ initialMessages: params.request.messages,
1264
1314
  tools,
1265
1315
  toolPolicy: binding.compactor.toolPolicy ?? (binding.compactor.inheritTools ? params.toolPolicy : null) ?? null,
1266
1316
  onInputRequired: async (prompt) => {
@@ -1305,22 +1355,25 @@ export class DMLRunner {
1305
1355
  /**
1306
1356
  * Extract memory from payload (now passed via state threading)
1307
1357
  */
1308
- extractMemoryFromPayload(rawPayload) {
1309
- const rawMemory = toJsValue(rawPayload.memory);
1310
- if (!Array.isArray(rawMemory)) {
1358
+ extractMessagesFromValue(rawMessages) {
1359
+ const normalized = toJsValue(rawMessages);
1360
+ if (!Array.isArray(normalized)) {
1311
1361
  return [];
1312
1362
  }
1313
- return rawMemory.map((m) => {
1314
- const msg = toJsValue(m);
1363
+ return normalized.map((messageValue) => {
1364
+ const msg = toJsValue(messageValue);
1315
1365
  const role = String(toJsValue(msg.role) ?? 'user');
1316
1366
  const content = String(toJsValue(msg.content) ?? '');
1317
- // Validate role
1318
1367
  if (role !== 'system' && role !== 'user' && role !== 'assistant') {
1319
1368
  return { role: 'user', content };
1320
1369
  }
1321
1370
  return { role: role, content };
1322
1371
  });
1323
1372
  }
1373
+ extractMemoryFromPayload(rawPayload) {
1374
+ const rawMemory = toJsValue(rawPayload.memory);
1375
+ return this.extractMessagesFromValue(rawMemory);
1376
+ }
1324
1377
  serializeMemoryMessages(messages) {
1325
1378
  return messages
1326
1379
  .map((message) => `message{role: ${message.role}, content: ${this.toPrologTerm(message.content)}}`)
@@ -1365,6 +1418,19 @@ export class DMLRunner {
1365
1418
  this.query(`deepclause_mi:post_sample_token_result('${this.sessionId}', failure, ${error})`);
1366
1419
  }
1367
1420
  }
1421
+ /**
1422
+ * Post direct llm/2 result back to Prolog
1423
+ */
1424
+ postLlmResult(result) {
1425
+ if (result.success) {
1426
+ const text = this.toPrologTerm(result.text ?? '');
1427
+ this.query(`deepclause_mi:post_llm_result('${this.sessionId}', success, ${text})`);
1428
+ }
1429
+ else {
1430
+ const error = this.toPrologTerm(result.error ?? 'Unknown error');
1431
+ this.query(`deepclause_mi:post_llm_result('${this.sessionId}', failure, ${error})`);
1432
+ }
1433
+ }
1368
1434
  /**
1369
1435
  * Post tool engine agent loop result back to Prolog
1370
1436
  */