deepclause-sdk 0.1.3 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -6
- package/dist/cli/config.d.ts +2 -2
- package/dist/cli/repl.d.ts +36 -0
- package/dist/cli/repl.d.ts.map +1 -1
- package/dist/cli/repl.js +414 -14
- package/dist/cli/repl.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/prolog-src/deepclause_mi.pl +547 -2
- package/dist/repl/backend.d.ts +9 -0
- package/dist/repl/backend.d.ts.map +1 -1
- package/dist/repl/backend.js +44 -0
- package/dist/repl/backend.js.map +1 -1
- package/dist/repl/harness-tools.d.ts +36 -0
- package/dist/repl/harness-tools.d.ts.map +1 -1
- package/dist/repl/harness-tools.js +173 -0
- package/dist/repl/harness-tools.js.map +1 -1
- package/dist/repl/history.d.ts +29 -0
- package/dist/repl/history.d.ts.map +1 -1
- package/dist/repl/history.js +71 -0
- package/dist/repl/history.js.map +1 -1
- package/dist/repl/index.d.ts +6 -0
- package/dist/repl/index.d.ts.map +1 -1
- package/dist/repl/index.js +9 -1
- package/dist/repl/index.js.map +1 -1
- package/dist/repl/picker.d.ts +3 -0
- package/dist/repl/picker.d.ts.map +1 -1
- package/dist/repl/picker.js +132 -0
- package/dist/repl/picker.js.map +1 -1
- package/dist/repl/process-backend.d.ts +31 -0
- package/dist/repl/process-backend.d.ts.map +1 -0
- package/dist/repl/process-backend.js +10 -0
- package/dist/repl/process-backend.js.map +1 -0
- package/dist/repl/process-executor.d.ts +67 -0
- package/dist/repl/process-executor.d.ts.map +1 -0
- package/dist/repl/process-executor.js +371 -0
- package/dist/repl/process-executor.js.map +1 -0
- package/dist/repl/process-worker.d.ts +10 -0
- package/dist/repl/process-worker.d.ts.map +1 -0
- package/dist/repl/process-worker.js +210 -0
- package/dist/repl/process-worker.js.map +1 -0
- package/dist/repl/processes.d.ts +282 -0
- package/dist/repl/processes.d.ts.map +1 -0
- package/dist/repl/processes.js +557 -0
- package/dist/repl/processes.js.map +1 -0
- package/dist/repl/render.d.ts.map +1 -1
- package/dist/repl/render.js +19 -5
- package/dist/repl/render.js.map +1 -1
- package/dist/repl/session.d.ts +142 -3
- package/dist/repl/session.d.ts.map +1 -1
- package/dist/repl/session.js +435 -4
- package/dist/repl/session.js.map +1 -1
- package/dist/repl/tui/autocomplete.d.ts.map +1 -1
- package/dist/repl/tui/autocomplete.js +7 -0
- package/dist/repl/tui/autocomplete.js.map +1 -1
- package/dist/repl/tui/harness-view.d.ts +102 -0
- package/dist/repl/tui/harness-view.d.ts.map +1 -0
- package/dist/repl/tui/harness-view.js +323 -0
- package/dist/repl/tui/harness-view.js.map +1 -0
- package/dist/repl/tui/renderer.d.ts.map +1 -1
- package/dist/repl/tui/renderer.js +6 -1
- package/dist/repl/tui/renderer.js.map +1 -1
- package/dist/repl/tui/services-panel.d.ts +35 -0
- package/dist/repl/tui/services-panel.d.ts.map +1 -0
- package/dist/repl/tui/services-panel.js +108 -0
- package/dist/repl/tui/services-panel.js.map +1 -0
- package/dist/repl/tui/status-bar.d.ts +2 -0
- package/dist/repl/tui/status-bar.d.ts.map +1 -1
- package/dist/repl/tui/status-bar.js +2 -0
- package/dist/repl/tui/status-bar.js.map +1 -1
- package/dist/repl/tui/tool-pane.d.ts.map +1 -1
- package/dist/repl/tui/tool-pane.js +6 -2
- package/dist/repl/tui/tool-pane.js.map +1 -1
- package/dist/repl/worker-host.d.ts +80 -0
- package/dist/repl/worker-host.d.ts.map +1 -0
- package/dist/repl/worker-host.js +305 -0
- package/dist/repl/worker-host.js.map +1 -0
- package/dist/repl/worker-protocol.d.ts +123 -0
- package/dist/repl/worker-protocol.d.ts.map +1 -0
- package/dist/repl/worker-protocol.js +9 -0
- package/dist/repl/worker-protocol.js.map +1 -0
- package/dist/runner.d.ts +24 -0
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +58 -0
- package/dist/runner.js.map +1 -1
- package/dist/system/assets/docs/AGENT_PROMPT.md +247 -0
- package/dist/system/assets/docs/DML_AUTHORING.md +21 -0
- package/dist/system/assets/docs/DML_REFERENCE.md +199 -0
- package/package.json +7 -6
- package/src/prolog-src/deepclause_mi.pl +547 -2
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
repl_memory_term/3,
|
|
94
94
|
repl_get_memory/3,
|
|
95
95
|
repl_set_memory/3,
|
|
96
|
+
repl_note_resumed/2,
|
|
96
97
|
post_agent_result/4,
|
|
97
98
|
post_exec_result/3,
|
|
98
99
|
post_sample_token_result/3,
|
|
@@ -114,6 +115,9 @@
|
|
|
114
115
|
:- discontiguous mi_call/3.
|
|
115
116
|
:- discontiguous transform_task_calls/3.
|
|
116
117
|
:- discontiguous var_to_name/3.
|
|
118
|
+
%% `proc_request_payload/2` sits between the process-primitive clauses of
|
|
119
|
+
%% `process_engine_result/4`, which is intentional.
|
|
120
|
+
:- discontiguous process_engine_result/4.
|
|
117
121
|
|
|
118
122
|
%% Dynamic predicates for session state (engine management only, not memory!)
|
|
119
123
|
:- dynamic session_engine/2. % session_engine(SessionId, Engine) - legacy default engine handle
|
|
@@ -148,6 +152,7 @@
|
|
|
148
152
|
:- dynamic session_trace_log/2. % session_trace_log(SessionId, TraceLog) - accumulated trace entries
|
|
149
153
|
:- dynamic session_trace_enabled/2. % session_trace_enabled(SessionId, true/false)
|
|
150
154
|
:- dynamic session_pending_signal/2. % session_pending_signal(SessionId, Signal) - fallback for engine_fetch
|
|
155
|
+
:- dynamic session_proc_result/3. % session_proc_result(SessionId, Key, Value) - process primitive results
|
|
151
156
|
:- dynamic session_user_input/2. % session_user_input(SessionId, Input) - for ask_user tool
|
|
152
157
|
:- dynamic session_input_cancelled/1. % session_input_cancelled(SessionId) - input/2 should fail (non-interactive)
|
|
153
158
|
|
|
@@ -957,7 +962,11 @@ step_engine_handle(SessionId, Engine, Status, Content, Payload) :-
|
|
|
957
962
|
)
|
|
958
963
|
),
|
|
959
964
|
Error,
|
|
960
|
-
(
|
|
965
|
+
( Error = process_exit(_)
|
|
966
|
+
-> Status = finished,
|
|
967
|
+
Content = '',
|
|
968
|
+
Payload = none
|
|
969
|
+
; format(atom(ErrMsg), 'Engine error: ~w', [Error]),
|
|
961
970
|
Status = error,
|
|
962
971
|
Content = ErrMsg,
|
|
963
972
|
( session_trace_enabled(SessionId, true),
|
|
@@ -1304,6 +1313,13 @@ repl_listing_output(SessionId, Filter) :-
|
|
|
1304
1313
|
)
|
|
1305
1314
|
).
|
|
1306
1315
|
|
|
1316
|
+
%% A filter either names a predicate (`name/arity`), names a prefix, or is `all`.
|
|
1317
|
+
%% Anything else matches **nothing**.
|
|
1318
|
+
%%
|
|
1319
|
+
%% There used to be a final `repl_listing_match(_, _, _)` catch-all, which turned any
|
|
1320
|
+
%% filter it did not understand into "the whole module" — silently. `listing('alpha/1')`
|
|
1321
|
+
%% therefore listed every predicate, so the side view's drill-down showed the module
|
|
1322
|
+
%% instead of the predicate under the cursor.
|
|
1307
1323
|
repl_listing_match(all, _, _) :- !.
|
|
1308
1324
|
repl_listing_match(Name/Arity, Name, Arity) :- !.
|
|
1309
1325
|
repl_listing_match(Filter, Name, _) :-
|
|
@@ -1312,7 +1328,8 @@ repl_listing_match(Filter, Name, _) :-
|
|
|
1312
1328
|
( sub_atom(Name, 0, _, _, Filter)
|
|
1313
1329
|
; sub_atom(Filter, 0, _, _, Name)
|
|
1314
1330
|
).
|
|
1315
|
-
repl_listing_match(_, _, _)
|
|
1331
|
+
repl_listing_match(_, _, _) :-
|
|
1332
|
+
fail.
|
|
1316
1333
|
|
|
1317
1334
|
%% repl_user_predicate(+SessionId, +Name, +Arity)
|
|
1318
1335
|
%% Excludes reserved and internal predicates from listing/export.
|
|
@@ -2308,6 +2325,46 @@ repl_rollback(SessionId, Source, Result) :-
|
|
|
2308
2325
|
format(atom(Result), 'error(~w)', [RollbackError])
|
|
2309
2326
|
).
|
|
2310
2327
|
|
|
2328
|
+
%% repl_harness_view(+SessionId, -Rows)
|
|
2329
|
+
%% One row per predicate of the harness, for the live side view:
|
|
2330
|
+
%% "Name/Arity|ClauseCount|flag,flag"
|
|
2331
|
+
%% Text rather than terms, so the host does not have to decode compound terms through
|
|
2332
|
+
%% the bridge — the view needs identity (to diff) and a little detail, not structure.
|
|
2333
|
+
repl_harness_view(SessionId, Rows) :-
|
|
2334
|
+
repl_user_predicates(SessionId, Preds),
|
|
2335
|
+
findall(Row,
|
|
2336
|
+
( member(Name/Arity, Preds),
|
|
2337
|
+
repl_predicate_clause_count(SessionId, Name, Arity, Clauses),
|
|
2338
|
+
repl_harness_flags(SessionId, Name, Arity, Flags),
|
|
2339
|
+
( Flags == []
|
|
2340
|
+
-> FlagText = ""
|
|
2341
|
+
; atomic_list_concat(Flags, ',', FlagText)
|
|
2342
|
+
),
|
|
2343
|
+
format(atom(Row), "~w/~w|~w|~w", [Name, Arity, Clauses, FlagText])
|
|
2344
|
+
),
|
|
2345
|
+
Rows).
|
|
2346
|
+
|
|
2347
|
+
repl_predicate_clause_count(SessionId, Name, Arity, Count) :-
|
|
2348
|
+
functor(Head, Name, Arity),
|
|
2349
|
+
findall(x, clause(SessionId:Head, _), All),
|
|
2350
|
+
length(All, Count).
|
|
2351
|
+
|
|
2352
|
+
repl_harness_flags(SessionId, Name, Arity, Flags) :-
|
|
2353
|
+
findall(Flag,
|
|
2354
|
+
( member(Flag, [entry, tool, doc, touched]),
|
|
2355
|
+
repl_harness_flag(SessionId, Name, Arity, Flag)
|
|
2356
|
+
),
|
|
2357
|
+
Flags).
|
|
2358
|
+
|
|
2359
|
+
repl_harness_flag(_SessionId, agent_main, _Arity, entry).
|
|
2360
|
+
repl_harness_flag(SessionId, Name, _Arity, tool) :-
|
|
2361
|
+
session_user_tools(SessionId, Name).
|
|
2362
|
+
repl_harness_flag(SessionId, Name, Arity, doc) :-
|
|
2363
|
+
current_predicate(SessionId:doc/2),
|
|
2364
|
+
catch(SessionId:doc(Name/Arity, _), _, fail).
|
|
2365
|
+
repl_harness_flag(SessionId, Name, Arity, touched) :-
|
|
2366
|
+
session_edit_touched(SessionId, Name/Arity).
|
|
2367
|
+
|
|
2311
2368
|
%% repl_user_predicates(+SessionId, -Preds)
|
|
2312
2369
|
%% Sorted Name/Arity list of the harness's own predicates.
|
|
2313
2370
|
repl_user_predicates(SessionId, Preds) :-
|
|
@@ -2414,6 +2471,9 @@ repl_validate_docs(SessionId, Warnings) :-
|
|
|
2414
2471
|
list_to_set(Raw, Warnings).
|
|
2415
2472
|
|
|
2416
2473
|
doc_without_clauses(SessionId, Warning) :-
|
|
2474
|
+
% A harness with no `doc/2` at all would otherwise make this call an
|
|
2475
|
+
% undefined-procedure warning (`Unknown procedure: repl_x:doc/2`).
|
|
2476
|
+
current_predicate(SessionId:doc/2),
|
|
2417
2477
|
SessionId:doc(Name/Arity, _),
|
|
2418
2478
|
( \+ current_predicate(SessionId:Name/Arity)
|
|
2419
2479
|
; functor(Head, Name, Arity),
|
|
@@ -2666,6 +2726,33 @@ repl_set_memory(SessionId, Slot, Messages) :-
|
|
|
2666
2726
|
assertz(session_repl_memory(SessionId, Messages))
|
|
2667
2727
|
).
|
|
2668
2728
|
|
|
2729
|
+
%% repl_note_resumed(+SessionId, +Text)
|
|
2730
|
+
%% Record that the session was restored from a saved snapshot. Added to both
|
|
2731
|
+
%% memory slots so the authoring agent and every task/N see it. Any earlier
|
|
2732
|
+
%% note is replaced, so a session resumed many times carries one line, not a
|
|
2733
|
+
%% growing stack.
|
|
2734
|
+
repl_note_resumed(SessionId, Text) :-
|
|
2735
|
+
atom_string(TextAtom, Text),
|
|
2736
|
+
Note = message{role: system, content: TextAtom},
|
|
2737
|
+
forall(member(Slot, [harness, meta]), (
|
|
2738
|
+
repl_get_memory(SessionId, Slot, Messages),
|
|
2739
|
+
exclude(is_resume_note, Messages, Kept),
|
|
2740
|
+
append(Kept, [Note], Next),
|
|
2741
|
+
repl_set_memory(SessionId, Slot, Next)
|
|
2742
|
+
)).
|
|
2743
|
+
|
|
2744
|
+
%% is_resume_note(+Message)
|
|
2745
|
+
%% True for a prior `repl_note_resumed/2` message, matched by its opening words.
|
|
2746
|
+
%% The content may be an atom (as first written) or a string (after a task/N
|
|
2747
|
+
%% round-trips the memory through the runner), so accept either.
|
|
2748
|
+
is_resume_note(message{role: system, content: Content}) :-
|
|
2749
|
+
( atom(Content)
|
|
2750
|
+
-> sub_atom(Content, 0, _, _, 'This session was reloaded')
|
|
2751
|
+
; string(Content)
|
|
2752
|
+
-> sub_string(Content, 0, _, _, "This session was reloaded")
|
|
2753
|
+
; fail
|
|
2754
|
+
).
|
|
2755
|
+
|
|
2669
2756
|
%% ---- Edit transactions ----
|
|
2670
2757
|
|
|
2671
2758
|
%% repl_snapshot_save(+SessionId)
|
|
@@ -2922,6 +3009,25 @@ process_engine_result(request_agent_loop(Desc, Vars, Tools, Memory), request_age
|
|
|
2922
3009
|
payload{taskDescription: Desc, outputVars: Vars, userTools: Tools, memory: Memory, toolScope: none, reasoningEffort: none, recipeContext: ""}) :- !.
|
|
2923
3010
|
process_engine_result(request_exec(Tool, Args), request_exec, '',
|
|
2924
3011
|
payload{toolName: Tool, args: Args}) :- !.
|
|
3012
|
+
%% Process primitives (spawn/send/receive/...) are yielded to the host, which
|
|
3013
|
+
%% owns identity, mailboxes, links, monitors, and naming.
|
|
3014
|
+
process_engine_result(request_proc(Request), request_proc, '', Payload) :-
|
|
3015
|
+
proc_request_payload(Request, Payload).
|
|
3016
|
+
|
|
3017
|
+
%% proc_request_payload(+Request, -Payload)
|
|
3018
|
+
proc_request_payload(self, payload{op: self}) :- !.
|
|
3019
|
+
proc_request_payload(spawn(Goal), payload{op: spawn, goal: Goal}) :- !.
|
|
3020
|
+
proc_request_payload(spawn(Goal, Options), payload{op: spawn, goal: Goal, options: Options}) :- !.
|
|
3021
|
+
proc_request_payload(send(To, Message), payload{op: send, to: To, message: Message}) :- !.
|
|
3022
|
+
proc_request_payload(receive(Timeout), payload{op: receive, timeout: Timeout}) :- !.
|
|
3023
|
+
proc_request_payload(requeue(Message), payload{op: requeue, message: Message}) :- !.
|
|
3024
|
+
proc_request_payload(wait(Pid), payload{op: wait, pid: Pid}) :- !.
|
|
3025
|
+
proc_request_payload(exit(Reason), payload{op: exit, reason: Reason}) :- !.
|
|
3026
|
+
proc_request_payload(exit(Pid, Reason), payload{op: exit, pid: Pid, reason: Reason}) :- !.
|
|
3027
|
+
proc_request_payload(process_info(Pid), payload{op: process_info, pid: Pid}) :- !.
|
|
3028
|
+
proc_request_payload(register(Name, Pid), payload{op: register, name: Name, pid: Pid}) :- !.
|
|
3029
|
+
proc_request_payload(whereis(Name), payload{op: whereis, name: Name}) :- !.
|
|
3030
|
+
proc_request_payload(sleep(Milliseconds), payload{op: sleep, ms: Milliseconds}) :- !.
|
|
2925
3031
|
process_engine_result(request_sample_token(Prompt, Allowed, ModelSpec), request_sample_token, '',
|
|
2926
3032
|
payload{prompt: Prompt, allowedTokens: Allowed, modelSpec: ModelSpec}) :- !.
|
|
2927
3033
|
process_engine_result(request_sample_token(Prompt, Allowed), request_sample_token, '',
|
|
@@ -3010,6 +3116,13 @@ post_exec_result(SessionId, Status, Result) :-
|
|
|
3010
3116
|
assertz(session_exec_result(SessionId, result{status: Status, result: Result})),
|
|
3011
3117
|
post_signal_to_engine(SessionId, exec_done).
|
|
3012
3118
|
|
|
3119
|
+
%% post_proc_result(+SessionId, +Key, +Value)
|
|
3120
|
+
%% Reply to a process primitive (spawn/send/receive/...). Key names the result.
|
|
3121
|
+
post_proc_result(SessionId, Key, Value) :-
|
|
3122
|
+
retractall(session_proc_result(SessionId, Key, _)),
|
|
3123
|
+
assertz(session_proc_result(SessionId, Key, Value)),
|
|
3124
|
+
post_signal_to_engine(SessionId, proc_done).
|
|
3125
|
+
|
|
3013
3126
|
%% post_sample_token_result(+SessionId, +Status, +TokenOrError)
|
|
3014
3127
|
post_sample_token_result(SessionId, Status, TokenOrError) :-
|
|
3015
3128
|
retractall(session_sample_token_result(SessionId, _)),
|
|
@@ -3459,6 +3572,10 @@ process_tool_engine_result(request_agent_loop(Desc, Vars, Tools, Memory, ToolSco
|
|
|
3459
3572
|
%% Legacy 4-arg format (no tool scope)
|
|
3460
3573
|
process_tool_engine_result(request_agent_loop(Desc, Vars, Tools, Memory), request_agent_loop, '',
|
|
3461
3574
|
payload{taskDescription: Desc, outputVars: Vars, userTools: Tools, memory: Memory, toolScope: none, reasoningEffort: none, recipeContext: ""}) :- !.
|
|
3575
|
+
%% Process primitives (self/send/receive/spawn/...) reached inside a DML tool
|
|
3576
|
+
%% are yielded to the host exactly as in the main engine.
|
|
3577
|
+
process_tool_engine_result(request_proc(Request), request_proc, '', Payload) :-
|
|
3578
|
+
proc_request_payload(Request, Payload).
|
|
3462
3579
|
process_tool_engine_result(output(Text), output, Text, none) :- !.
|
|
3463
3580
|
process_tool_engine_result(log(Text), log, Text, none) :- !.
|
|
3464
3581
|
process_tool_engine_result(Other, error, Msg, none) :-
|
|
@@ -4144,6 +4261,410 @@ mi_call(exec(ToolCall, Output), StateIn, StateOut) :-
|
|
|
4144
4261
|
fail
|
|
4145
4262
|
).
|
|
4146
4263
|
|
|
4264
|
+
%% ============================================================
|
|
4265
|
+
%% Process Primitives (session-scoped subagents)
|
|
4266
|
+
%% ============================================================
|
|
4267
|
+
%% These yield to the TypeScript host, which owns process identity, mailboxes,
|
|
4268
|
+
%% links, monitors, and naming. See docs/DML_REPL_PROCESSES_SPEC.md.
|
|
4269
|
+
%% Goals and messages cross the boundary as canonical term strings, so a
|
|
4270
|
+
%% process never shares a variable with its spawner (invariant A).
|
|
4271
|
+
|
|
4272
|
+
%% mi_call(self(?Pid), +StateIn, -StateOut)
|
|
4273
|
+
mi_call(self(Pid), StateIn, StateIn) :-
|
|
4274
|
+
!,
|
|
4275
|
+
get_session_id(SessionId),
|
|
4276
|
+
engine_yield(request_proc(self)),
|
|
4277
|
+
get_next_signal(SessionId, _),
|
|
4278
|
+
session_proc_result(SessionId, self, Pid),
|
|
4279
|
+
retract(session_proc_result(SessionId, self, _)).
|
|
4280
|
+
|
|
4281
|
+
%% mi_call(spawn(+Goal, -Pid), +StateIn, -StateOut)
|
|
4282
|
+
mi_call(spawn(Goal, Pid), StateIn, StateIn) :-
|
|
4283
|
+
!,
|
|
4284
|
+
get_session_id(SessionId),
|
|
4285
|
+
copy_term(Goal, GoalCopy),
|
|
4286
|
+
term_string(GoalCopy, GoalText),
|
|
4287
|
+
engine_yield(request_proc(spawn(GoalText))),
|
|
4288
|
+
get_next_signal(SessionId, _),
|
|
4289
|
+
session_proc_result(SessionId, spawn, SpawnResult),
|
|
4290
|
+
retract(session_proc_result(SessionId, spawn, _)),
|
|
4291
|
+
( SpawnResult = ok(Pid)
|
|
4292
|
+
-> true
|
|
4293
|
+
; throw(error(process_spawn_failed(SpawnResult), spawn/2))
|
|
4294
|
+
).
|
|
4295
|
+
|
|
4296
|
+
%% mi_call(spawn_opt(+Goal, -Pid, +Options), +StateIn, -StateOut)
|
|
4297
|
+
mi_call(spawn_opt(Goal, Pid, Options), StateIn, StateIn) :-
|
|
4298
|
+
!,
|
|
4299
|
+
get_session_id(SessionId),
|
|
4300
|
+
copy_term(Goal, GoalCopy),
|
|
4301
|
+
term_string(GoalCopy, GoalText),
|
|
4302
|
+
( is_dict(Options) -> term_string(Options, OptionsText) ; OptionsText = "{}" ),
|
|
4303
|
+
engine_yield(request_proc(spawn(GoalText, OptionsText))),
|
|
4304
|
+
get_next_signal(SessionId, _),
|
|
4305
|
+
session_proc_result(SessionId, spawn, SpawnResult),
|
|
4306
|
+
retract(session_proc_result(SessionId, spawn, _)),
|
|
4307
|
+
( SpawnResult = ok(Pid)
|
|
4308
|
+
-> true
|
|
4309
|
+
; throw(error(process_spawn_failed(SpawnResult), spawn_opt/3))
|
|
4310
|
+
).
|
|
4311
|
+
|
|
4312
|
+
%% mi_call(send(+Target, +Message), +StateIn, -StateOut)
|
|
4313
|
+
mi_call(send(To, Message), StateIn, StateIn) :-
|
|
4314
|
+
!,
|
|
4315
|
+
get_session_id(SessionId),
|
|
4316
|
+
term_string(To, ToText),
|
|
4317
|
+
term_string(Message, MessageText),
|
|
4318
|
+
engine_yield(request_proc(send(ToText, MessageText))),
|
|
4319
|
+
get_next_signal(SessionId, _),
|
|
4320
|
+
session_proc_result(SessionId, send, SendResult),
|
|
4321
|
+
retract(session_proc_result(SessionId, send, _)),
|
|
4322
|
+
( SendResult == ok
|
|
4323
|
+
-> true
|
|
4324
|
+
; throw(error(process_send_failed(SendResult), send/2))
|
|
4325
|
+
).
|
|
4326
|
+
|
|
4327
|
+
%% mi_call(receive(?Message), +StateIn, -StateOut)
|
|
4328
|
+
mi_call(receive(Message), StateIn, StateIn) :-
|
|
4329
|
+
!,
|
|
4330
|
+
mi_call(receive(Message, 0), StateIn, StateIn).
|
|
4331
|
+
|
|
4332
|
+
%% mi_call(receive(?Message, +TimeoutMs), +StateIn, -StateOut)
|
|
4333
|
+
%% Fails on timeout, so a caller can branch on it.
|
|
4334
|
+
mi_call(receive(Message, TimeoutMs), StateIn, StateIn) :-
|
|
4335
|
+
!,
|
|
4336
|
+
get_session_id(SessionId),
|
|
4337
|
+
engine_yield(request_proc(receive(TimeoutMs))),
|
|
4338
|
+
get_next_signal(SessionId, _),
|
|
4339
|
+
session_proc_result(SessionId, receive, ReceiveResult),
|
|
4340
|
+
retract(session_proc_result(SessionId, receive, _)),
|
|
4341
|
+
ReceiveResult = ok(Message).
|
|
4342
|
+
|
|
4343
|
+
%% mi_call(receive_match(+Template, ?Message, +TimeoutMs), +StateIn, -StateOut)
|
|
4344
|
+
%% Selective receive: skip messages that do not unify with Template, requeue
|
|
4345
|
+
%% them in order, and fail on timeout. The template unifies in this process.
|
|
4346
|
+
mi_call(receive_match(Template, Message, TimeoutMs), StateIn, StateIn) :-
|
|
4347
|
+
!,
|
|
4348
|
+
get_session_id(SessionId),
|
|
4349
|
+
proc_now_ms(Start),
|
|
4350
|
+
receive_match_loop(Template, Message, TimeoutMs, Start, SessionId, []).
|
|
4351
|
+
|
|
4352
|
+
%% A plain monotonic clock for helpers (now_ms/1 is a mi_call special predicate).
|
|
4353
|
+
proc_now_ms(Milliseconds) :-
|
|
4354
|
+
get_time(Seconds),
|
|
4355
|
+
Milliseconds is round(Seconds * 1000).
|
|
4356
|
+
|
|
4357
|
+
receive_match_loop(Template, Message, TimeoutMs, Start, SessionId, Skipped) :-
|
|
4358
|
+
proc_now_ms(Now),
|
|
4359
|
+
( TimeoutMs > 0
|
|
4360
|
+
-> Left is TimeoutMs - (Now - Start)
|
|
4361
|
+
; Left = 0
|
|
4362
|
+
),
|
|
4363
|
+
( TimeoutMs > 0, Left =< 0
|
|
4364
|
+
-> requeue_skipped(Skipped, SessionId),
|
|
4365
|
+
fail
|
|
4366
|
+
; engine_yield(request_proc(receive(Left))),
|
|
4367
|
+
get_next_signal(SessionId, _),
|
|
4368
|
+
session_proc_result(SessionId, receive, Result),
|
|
4369
|
+
retract(session_proc_result(SessionId, receive, _)),
|
|
4370
|
+
( Result = ok(Term),
|
|
4371
|
+
( copy_term(Template, Copy), Copy = Term
|
|
4372
|
+
-> requeue_skipped(Skipped, SessionId),
|
|
4373
|
+
Template = Term,
|
|
4374
|
+
Message = Term
|
|
4375
|
+
; receive_match_loop(Template, Message, TimeoutMs, Start, SessionId, [Term|Skipped])
|
|
4376
|
+
)
|
|
4377
|
+
; requeue_skipped(Skipped, SessionId),
|
|
4378
|
+
fail
|
|
4379
|
+
)
|
|
4380
|
+
).
|
|
4381
|
+
|
|
4382
|
+
requeue_skipped(Skipped, SessionId) :-
|
|
4383
|
+
requeue_reversed(Skipped, [], Reversed),
|
|
4384
|
+
requeue_all(Reversed, SessionId).
|
|
4385
|
+
|
|
4386
|
+
%% Build the reversed list without library(lists) (deepclause_mi may not have it).
|
|
4387
|
+
requeue_reversed([], Acc, Acc).
|
|
4388
|
+
requeue_reversed([X|Xs], Acc, Out) :- requeue_reversed(Xs, [X|Acc], Out).
|
|
4389
|
+
|
|
4390
|
+
requeue_all([], _).
|
|
4391
|
+
requeue_all([Message|Messages], SessionId) :-
|
|
4392
|
+
term_string(Message, Text),
|
|
4393
|
+
engine_yield(request_proc(requeue(Text))),
|
|
4394
|
+
get_next_signal(SessionId, _),
|
|
4395
|
+
session_proc_result(SessionId, requeue, _),
|
|
4396
|
+
retract(session_proc_result(SessionId, requeue, _)),
|
|
4397
|
+
requeue_all(Messages, SessionId).
|
|
4398
|
+
|
|
4399
|
+
%% mi_call(exit(+Reason), +StateIn, -StateOut)
|
|
4400
|
+
%% Terminate this process. The host marks it killed; the frame is stopped by
|
|
4401
|
+
%% the throw below, which the runner maps to a clean termination.
|
|
4402
|
+
mi_call(exit(Reason), StateIn, StateIn) :-
|
|
4403
|
+
!,
|
|
4404
|
+
get_session_id(SessionId),
|
|
4405
|
+
term_string(Reason, ReasonText),
|
|
4406
|
+
engine_yield(request_proc(exit(ReasonText))),
|
|
4407
|
+
get_next_signal(SessionId, _),
|
|
4408
|
+
session_proc_result(SessionId, exit, _),
|
|
4409
|
+
retract(session_proc_result(SessionId, exit, _)),
|
|
4410
|
+
throw(process_exit(Reason)).
|
|
4411
|
+
|
|
4412
|
+
%% mi_call(exit(+Pid, +Reason), +StateIn, -StateOut)
|
|
4413
|
+
%% Terminate another process. Unlike exit/1 this returns; the target is killed.
|
|
4414
|
+
mi_call(exit(Pid, Reason), StateIn, StateIn) :-
|
|
4415
|
+
!,
|
|
4416
|
+
get_session_id(SessionId),
|
|
4417
|
+
term_string(Pid, PidText),
|
|
4418
|
+
term_string(Reason, ReasonText),
|
|
4419
|
+
engine_yield(request_proc(exit(PidText, ReasonText))),
|
|
4420
|
+
get_next_signal(SessionId, _),
|
|
4421
|
+
session_proc_result(SessionId, exit, ExitResult),
|
|
4422
|
+
retract(session_proc_result(SessionId, exit, _)),
|
|
4423
|
+
( ExitResult == ok
|
|
4424
|
+
-> true
|
|
4425
|
+
; throw(error(process_exit_failed(ExitResult), exit/2))
|
|
4426
|
+
).
|
|
4427
|
+
|
|
4428
|
+
%% mi_call(process_info(+Pid, -Info), +StateIn, -StateOut)
|
|
4429
|
+
mi_call(process_info(Pid, Info), StateIn, StateIn) :-
|
|
4430
|
+
!,
|
|
4431
|
+
get_session_id(SessionId),
|
|
4432
|
+
term_string(Pid, PidText),
|
|
4433
|
+
engine_yield(request_proc(process_info(PidText))),
|
|
4434
|
+
get_next_signal(SessionId, _),
|
|
4435
|
+
session_proc_result(SessionId, process_info, Info),
|
|
4436
|
+
retract(session_proc_result(SessionId, process_info, _)).
|
|
4437
|
+
|
|
4438
|
+
%% mi_call(register(+Name, +Pid), +StateIn, -StateOut)
|
|
4439
|
+
mi_call(register(Name, Pid), StateIn, StateIn) :-
|
|
4440
|
+
!,
|
|
4441
|
+
get_session_id(SessionId),
|
|
4442
|
+
term_string(Name, NameText),
|
|
4443
|
+
term_string(Pid, PidText),
|
|
4444
|
+
engine_yield(request_proc(register(NameText, PidText))),
|
|
4445
|
+
get_next_signal(SessionId, _),
|
|
4446
|
+
session_proc_result(SessionId, register, RegisterResult),
|
|
4447
|
+
retract(session_proc_result(SessionId, register, _)),
|
|
4448
|
+
( RegisterResult == ok
|
|
4449
|
+
-> true
|
|
4450
|
+
; throw(error(process_register_failed(RegisterResult), register/2))
|
|
4451
|
+
).
|
|
4452
|
+
|
|
4453
|
+
%% mi_call(whereis(+Name, ?Pid), +StateIn, -StateOut)
|
|
4454
|
+
mi_call(whereis(Name, Pid), StateIn, StateIn) :-
|
|
4455
|
+
!,
|
|
4456
|
+
get_session_id(SessionId),
|
|
4457
|
+
term_string(Name, NameText),
|
|
4458
|
+
engine_yield(request_proc(whereis(NameText))),
|
|
4459
|
+
get_next_signal(SessionId, _),
|
|
4460
|
+
session_proc_result(SessionId, whereis, WhereResult),
|
|
4461
|
+
retract(session_proc_result(SessionId, whereis, _)),
|
|
4462
|
+
WhereResult = ok(Pid).
|
|
4463
|
+
|
|
4464
|
+
%% mi_call(sleep(+Milliseconds), +StateIn, -StateOut)
|
|
4465
|
+
mi_call(sleep(Milliseconds), StateIn, StateIn) :-
|
|
4466
|
+
!,
|
|
4467
|
+
get_session_id(SessionId),
|
|
4468
|
+
engine_yield(request_proc(sleep(Milliseconds))),
|
|
4469
|
+
get_next_signal(SessionId, _),
|
|
4470
|
+
session_proc_result(SessionId, sleep, _),
|
|
4471
|
+
retract(session_proc_result(SessionId, sleep, _)).
|
|
4472
|
+
|
|
4473
|
+
%% mi_call(make_ref(-Ref), +StateIn, -StateOut)
|
|
4474
|
+
mi_call(make_ref(Ref), StateIn, StateIn) :-
|
|
4475
|
+
!,
|
|
4476
|
+
gensym(ref_, Ref).
|
|
4477
|
+
|
|
4478
|
+
%% mi_call(now_ms(-Milliseconds), +StateIn, -StateOut)
|
|
4479
|
+
mi_call(now_ms(Milliseconds), StateIn, StateIn) :-
|
|
4480
|
+
!,
|
|
4481
|
+
get_time(Seconds),
|
|
4482
|
+
Milliseconds is round(Seconds * 1000).
|
|
4483
|
+
|
|
4484
|
+
%% mi_call(serve(+Name, +Goal), +StateIn, -StateOut)
|
|
4485
|
+
%% Spawn a session-scoped process and register it under Name. Sugar over
|
|
4486
|
+
%% spawn/2 + register/2; the goal decides the process's shape.
|
|
4487
|
+
mi_call(serve(Name, Goal), StateIn, StateIn) :-
|
|
4488
|
+
!,
|
|
4489
|
+
get_session_id(SessionId),
|
|
4490
|
+
copy_term(Goal, GoalCopy),
|
|
4491
|
+
term_string(GoalCopy, GoalText),
|
|
4492
|
+
engine_yield(request_proc(spawn(GoalText))),
|
|
4493
|
+
get_next_signal(SessionId, _),
|
|
4494
|
+
session_proc_result(SessionId, spawn, SpawnResult),
|
|
4495
|
+
retract(session_proc_result(SessionId, spawn, _)),
|
|
4496
|
+
SpawnResult = ok(Pid),
|
|
4497
|
+
term_string(Name, NameText),
|
|
4498
|
+
term_string(Pid, PidText),
|
|
4499
|
+
engine_yield(request_proc(register(NameText, PidText))),
|
|
4500
|
+
get_next_signal(SessionId, _),
|
|
4501
|
+
session_proc_result(SessionId, register, _),
|
|
4502
|
+
retract(session_proc_result(SessionId, register, _)).
|
|
4503
|
+
|
|
4504
|
+
%% mi_call(service_cast(+Target, +Message), +StateIn, -StateOut)
|
|
4505
|
+
mi_call(service_cast(Target, Message), StateIn, StateIn) :-
|
|
4506
|
+
!,
|
|
4507
|
+
get_session_id(SessionId),
|
|
4508
|
+
term_string(Target, TargetText),
|
|
4509
|
+
term_string(Message, MessageText),
|
|
4510
|
+
engine_yield(request_proc(send(TargetText, MessageText))),
|
|
4511
|
+
get_next_signal(SessionId, _),
|
|
4512
|
+
session_proc_result(SessionId, send, _),
|
|
4513
|
+
retract(session_proc_result(SessionId, send, _)).
|
|
4514
|
+
|
|
4515
|
+
%% mi_call(service_call(+Target, +Request, -Reply), +StateIn, -StateOut)
|
|
4516
|
+
mi_call(service_call(Target, Request, Reply), StateIn, StateOut) :-
|
|
4517
|
+
!,
|
|
4518
|
+
mi_call(service_call(Target, Request, Reply, 300000), StateIn, StateOut).
|
|
4519
|
+
|
|
4520
|
+
%% mi_call(service_call(+Target, +Request, -Reply, +TimeoutMs), ...)
|
|
4521
|
+
%% Request/reply against a process using the request(From, Ref, Request) /
|
|
4522
|
+
%% reply(Ref, Value) protocol. Unrelated messages are ignored while waiting.
|
|
4523
|
+
mi_call(service_call(Target, Request, Reply, Timeout), StateIn, StateIn) :-
|
|
4524
|
+
!,
|
|
4525
|
+
get_session_id(SessionId),
|
|
4526
|
+
gensym(reply_ref_, Ref),
|
|
4527
|
+
engine_yield(request_proc(self)),
|
|
4528
|
+
get_next_signal(SessionId, _),
|
|
4529
|
+
session_proc_result(SessionId, self, Me),
|
|
4530
|
+
retract(session_proc_result(SessionId, self, _)),
|
|
4531
|
+
term_string(Target, TargetText),
|
|
4532
|
+
term_string(request(Me, Ref, Request), RequestText),
|
|
4533
|
+
engine_yield(request_proc(send(TargetText, RequestText))),
|
|
4534
|
+
get_next_signal(SessionId, _),
|
|
4535
|
+
session_proc_result(SessionId, send, _),
|
|
4536
|
+
retract(session_proc_result(SessionId, send, _)),
|
|
4537
|
+
service_await_reply(Ref, Reply, Timeout).
|
|
4538
|
+
|
|
4539
|
+
%% service_await_reply(+Ref, -Reply, +TimeoutMs)
|
|
4540
|
+
service_await_reply(Ref, Reply, Timeout) :-
|
|
4541
|
+
get_session_id(SessionId),
|
|
4542
|
+
engine_yield(request_proc(receive(Timeout))),
|
|
4543
|
+
get_next_signal(SessionId, _),
|
|
4544
|
+
session_proc_result(SessionId, receive, Result),
|
|
4545
|
+
retract(session_proc_result(SessionId, receive, _)),
|
|
4546
|
+
( Result = ok(reply(Ref, Reply))
|
|
4547
|
+
-> true
|
|
4548
|
+
; Result = ok(_)
|
|
4549
|
+
-> service_await_reply(Ref, Reply, Timeout)
|
|
4550
|
+
; fail
|
|
4551
|
+
).
|
|
4552
|
+
|
|
4553
|
+
%% mi_call(wait(+Pid[, -Outcome]), +StateIn, -StateOut)
|
|
4554
|
+
%% Block until a process terminates. Outcome is ok(Result), failed(Error), or
|
|
4555
|
+
%% killed(Reason); Result is the process's terminal text as a Prolog string.
|
|
4556
|
+
%% `wait/1` is semidet: it succeeds only on a successful finish.
|
|
4557
|
+
mi_call(wait(Pid), StateIn, StateIn) :-
|
|
4558
|
+
!,
|
|
4559
|
+
mi_call(wait(Pid, Outcome), StateIn, _),
|
|
4560
|
+
Outcome = ok(_).
|
|
4561
|
+
|
|
4562
|
+
mi_call(wait(Pid, Outcome), StateIn, StateIn) :-
|
|
4563
|
+
!,
|
|
4564
|
+
get_session_id(SessionId),
|
|
4565
|
+
term_string(Pid, PidText),
|
|
4566
|
+
engine_yield(request_proc(wait(PidText))),
|
|
4567
|
+
get_next_signal(SessionId, _),
|
|
4568
|
+
session_proc_result(SessionId, wait, Outcome),
|
|
4569
|
+
retract(session_proc_result(SessionId, wait, _)).
|
|
4570
|
+
|
|
4571
|
+
%% ============================================================
|
|
4572
|
+
%% Swarm / pmap: fan a worker over a list concurrently
|
|
4573
|
+
%% ============================================================
|
|
4574
|
+
%% Each item runs in its own process (spawned through the host), calling
|
|
4575
|
+
%% call(Worker, Item, Value). Results preserve input order. `Concurrency` is
|
|
4576
|
+
%% accepted for compatibility and not yet enforced (the host's process limit is).
|
|
4577
|
+
|
|
4578
|
+
proc_self(SessionId, Me) :-
|
|
4579
|
+
engine_yield(request_proc(self)),
|
|
4580
|
+
get_next_signal(SessionId, _),
|
|
4581
|
+
session_proc_result(SessionId, self, Me),
|
|
4582
|
+
retract(session_proc_result(SessionId, self, _)).
|
|
4583
|
+
|
|
4584
|
+
%% mi_call(swarm(+Worker, +Items, -Results), ...)
|
|
4585
|
+
mi_call(swarm(Worker, Items, Results), StateIn, StateOut) :-
|
|
4586
|
+
!,
|
|
4587
|
+
mi_call(swarm(Worker, Items, Results, 4), StateIn, StateOut).
|
|
4588
|
+
|
|
4589
|
+
%% mi_call(swarm(+Worker, +Items, -Results, +Concurrency), ...)
|
|
4590
|
+
%% Windowed fan-out: at most Concurrency items run at once.
|
|
4591
|
+
mi_call(swarm(Worker, Items, Results, Concurrency), StateIn, StateIn) :-
|
|
4592
|
+
!,
|
|
4593
|
+
get_session_id(SessionId),
|
|
4594
|
+
proc_self(SessionId, Me),
|
|
4595
|
+
( integer(Concurrency), Concurrency > 0 -> Conc = Concurrency ; Conc = 4 ),
|
|
4596
|
+
swarm_loop(Items, 1, [], Conc, Worker, Me, SessionId, [], Pairs),
|
|
4597
|
+
keysort(Pairs, Sorted),
|
|
4598
|
+
swarm_values(Sorted, Results).
|
|
4599
|
+
|
|
4600
|
+
%% Accumulate `Acc`, bind the collected pairs to `Pairs` at the base.
|
|
4601
|
+
swarm_loop(Pending, NextIndex, InFlight, Conc, Worker, Me, SessionId, Acc, Pairs) :-
|
|
4602
|
+
( Pending = [Item|Rest],
|
|
4603
|
+
length(InFlight, K), K < Conc
|
|
4604
|
+
-> swarm_spawn_one(Item, NextIndex, Worker, Me, SessionId, SpawnResult),
|
|
4605
|
+
Next is NextIndex + 1,
|
|
4606
|
+
( SpawnResult = ok(_Pid)
|
|
4607
|
+
-> swarm_loop(Rest, Next, [NextIndex|InFlight], Conc, Worker, Me, SessionId, Acc, Pairs)
|
|
4608
|
+
; % The host refused the spawn (e.g. the live-process limit): fail only
|
|
4609
|
+
% this item, so the swarm still completes and the reason is visible
|
|
4610
|
+
% instead of the whole call failing silently.
|
|
4611
|
+
swarm_loop(Rest, Next, InFlight, Conc, Worker, Me, SessionId,
|
|
4612
|
+
[NextIndex-failed(SpawnResult)|Acc], Pairs)
|
|
4613
|
+
)
|
|
4614
|
+
; InFlight = [_|_]
|
|
4615
|
+
-> swarm_receive(Index, Value, SessionId),
|
|
4616
|
+
selectchk(Index, InFlight, Rest),
|
|
4617
|
+
swarm_loop(Pending, NextIndex, Rest, Conc, Worker, Me, SessionId, [Index-Value|Acc], Pairs)
|
|
4618
|
+
; Pairs = Acc
|
|
4619
|
+
).
|
|
4620
|
+
|
|
4621
|
+
swarm_spawn_one(Item, Index, Worker, Me, SessionId, SpawnResult) :-
|
|
4622
|
+
term_string(deepclause_mi:dc_swarm_item(Worker, Item, Me, Index), GoalText),
|
|
4623
|
+
engine_yield(request_proc(spawn(GoalText))),
|
|
4624
|
+
get_next_signal(SessionId, _),
|
|
4625
|
+
session_proc_result(SessionId, spawn, SpawnResult),
|
|
4626
|
+
retract(session_proc_result(SessionId, spawn, _)).
|
|
4627
|
+
|
|
4628
|
+
swarm_receive(Index, Value, SessionId) :-
|
|
4629
|
+
engine_yield(request_proc(receive(0))),
|
|
4630
|
+
get_next_signal(SessionId, _),
|
|
4631
|
+
session_proc_result(SessionId, receive, R),
|
|
4632
|
+
retract(session_proc_result(SessionId, receive, _)),
|
|
4633
|
+
R = ok(swarm_result(Index, Value)).
|
|
4634
|
+
|
|
4635
|
+
swarm_values([], []).
|
|
4636
|
+
swarm_values([_-Value|Rest], [Value|Values]) :- swarm_values(Rest, Values).
|
|
4637
|
+
|
|
4638
|
+
%% dc_swarm_item(+Worker, +Item, +Parent, +Index) — the child goal.
|
|
4639
|
+
%% Catch a thrown error (an undefined worker, a budget, a tool failure) and
|
|
4640
|
+
%% report it as `failed(Error)`. Without the catch the child process crashes and
|
|
4641
|
+
%% never sends a result, so the parent's `swarm_receive` waits forever.
|
|
4642
|
+
%%
|
|
4643
|
+
%% The `call` must stay inline in this clause: a helper predicate defined in
|
|
4644
|
+
%% `deepclause_mi` is reached via the meta-interpreter's raw-Prolog fallback, and
|
|
4645
|
+
%% then `call(Worker, ...)` resolves in `deepclause_mi` instead of the session
|
|
4646
|
+
%% module (so every worker looked undefined).
|
|
4647
|
+
dc_swarm_item(Worker, Item, Parent, Index) :-
|
|
4648
|
+
catch(
|
|
4649
|
+
( call(Worker, Item, Result)
|
|
4650
|
+
-> Outcome = ok(Result)
|
|
4651
|
+
; Outcome = failed
|
|
4652
|
+
),
|
|
4653
|
+
Error,
|
|
4654
|
+
Outcome = failed(Error)
|
|
4655
|
+
),
|
|
4656
|
+
send(Parent, swarm_result(Index, Outcome)).
|
|
4657
|
+
|
|
4658
|
+
%% mi_call(pmap(+Worker, +Items, -Values), ...)
|
|
4659
|
+
%% Like swarm/3, but fails if any item failed.
|
|
4660
|
+
mi_call(pmap(Worker, Items, Values), StateIn, StateIn) :-
|
|
4661
|
+
!,
|
|
4662
|
+
mi_call(swarm(Worker, Items, Results), StateIn, _),
|
|
4663
|
+
pmap_ok(Results, Values).
|
|
4664
|
+
|
|
4665
|
+
pmap_ok([], []).
|
|
4666
|
+
pmap_ok([ok(Value)|Rest], [Value|Values]) :- pmap_ok(Rest, Values).
|
|
4667
|
+
|
|
4147
4668
|
%% ============================================================
|
|
4148
4669
|
%% Tool Scoping Predicates
|
|
4149
4670
|
%% ============================================================
|
|
@@ -5477,6 +5998,30 @@ is_mi_special_predicate(task_named(_,_,_)). %% Transformed form of task/N
|
|
|
5477
5998
|
is_mi_special_predicate(sample_token(_,_)).
|
|
5478
5999
|
is_mi_special_predicate(sample_token(_,_,_)).
|
|
5479
6000
|
is_mi_special_predicate(exec(_,_)).
|
|
6001
|
+
is_mi_special_predicate(spawn(_,_)).
|
|
6002
|
+
is_mi_special_predicate(spawn_opt(_,_,_)).
|
|
6003
|
+
is_mi_special_predicate(self(_)).
|
|
6004
|
+
is_mi_special_predicate(send(_,_)).
|
|
6005
|
+
is_mi_special_predicate(receive(_)).
|
|
6006
|
+
is_mi_special_predicate(receive(_,_)).
|
|
6007
|
+
is_mi_special_predicate(receive_match(_,_,_)).
|
|
6008
|
+
is_mi_special_predicate(exit(_)).
|
|
6009
|
+
is_mi_special_predicate(exit(_,_)).
|
|
6010
|
+
is_mi_special_predicate(process_info(_,_)).
|
|
6011
|
+
is_mi_special_predicate(register(_,_)).
|
|
6012
|
+
is_mi_special_predicate(whereis(_,_)).
|
|
6013
|
+
is_mi_special_predicate(sleep(_)).
|
|
6014
|
+
is_mi_special_predicate(make_ref(_)).
|
|
6015
|
+
is_mi_special_predicate(now_ms(_)).
|
|
6016
|
+
is_mi_special_predicate(serve(_,_)).
|
|
6017
|
+
is_mi_special_predicate(service_cast(_,_)).
|
|
6018
|
+
is_mi_special_predicate(service_call(_,_,_)).
|
|
6019
|
+
is_mi_special_predicate(service_call(_,_,_,_)).
|
|
6020
|
+
is_mi_special_predicate(swarm(_,_,_)).
|
|
6021
|
+
is_mi_special_predicate(swarm(_,_,_,_)).
|
|
6022
|
+
is_mi_special_predicate(pmap(_,_,_)).
|
|
6023
|
+
is_mi_special_predicate(wait(_)).
|
|
6024
|
+
is_mi_special_predicate(wait(_,_)).
|
|
5480
6025
|
is_mi_special_predicate(param(_,_)).
|
|
5481
6026
|
is_mi_special_predicate(param(_,_,_)).
|
|
5482
6027
|
%% Prompt predicates (like task but with fresh memory)
|
package/dist/repl/backend.d.ts
CHANGED
|
@@ -318,4 +318,13 @@ export interface ResolvedBackend {
|
|
|
318
318
|
* provider/model so the runner builds the SDK provider backend.
|
|
319
319
|
*/
|
|
320
320
|
export declare function resolveLlmBackend(options?: ResolveBackendOptions): Promise<ResolvedBackend>;
|
|
321
|
+
/**
|
|
322
|
+
* Wrap a backend so at most `maxConcurrent` model calls are in flight at once.
|
|
323
|
+
*
|
|
324
|
+
* A `swarm`/fan-out otherwise fires one provider call per item simultaneously,
|
|
325
|
+
* which trips rate limits and bursts cost. The wrapper is created once (in
|
|
326
|
+
* `createHarnessRepl`) and shared by every child session, so the limit is per
|
|
327
|
+
* session tree. `maxConcurrent <= 0` returns the backend unchanged.
|
|
328
|
+
*/
|
|
329
|
+
export declare function createLimitedBackend(backend: LLMBackend, maxConcurrent: number): LLMBackend;
|
|
321
330
|
//# sourceMappingURL=backend.d.ts.map
|