@jini-ai/daemon 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/agent-executor.d.ts +458 -0
- package/dist/agent-executor.d.ts.map +1 -0
- package/dist/agent-executor.js +1277 -0
- package/dist/agent-executor.js.map +1 -0
- package/dist/artifacts/index.d.ts +14 -0
- package/dist/artifacts/index.d.ts.map +1 -0
- package/dist/artifacts/index.js +14 -0
- package/dist/artifacts/index.js.map +1 -0
- package/dist/artifacts/manifest.d.ts +90 -0
- package/dist/artifacts/manifest.d.ts.map +1 -0
- package/dist/artifacts/manifest.js +229 -0
- package/dist/artifacts/manifest.js.map +1 -0
- package/dist/artifacts/publication-guard.d.ts +28 -0
- package/dist/artifacts/publication-guard.d.ts.map +1 -0
- package/dist/artifacts/publication-guard.js +77 -0
- package/dist/artifacts/publication-guard.js.map +1 -0
- package/dist/artifacts/runtime-compat.d.ts +37 -0
- package/dist/artifacts/runtime-compat.d.ts.map +1 -0
- package/dist/artifacts/runtime-compat.js +33 -0
- package/dist/artifacts/runtime-compat.js.map +1 -0
- package/dist/artifacts/store.d.ts +85 -0
- package/dist/artifacts/store.d.ts.map +1 -0
- package/dist/artifacts/store.js +92 -0
- package/dist/artifacts/store.js.map +1 -0
- package/dist/artifacts/stub-guard.d.ts +73 -0
- package/dist/artifacts/stub-guard.d.ts.map +1 -0
- package/dist/artifacts/stub-guard.js +198 -0
- package/dist/artifacts/stub-guard.js.map +1 -0
- package/dist/artifacts/text-suppression.d.ts +68 -0
- package/dist/artifacts/text-suppression.d.ts.map +1 -0
- package/dist/artifacts/text-suppression.js +184 -0
- package/dist/artifacts/text-suppression.js.map +1 -0
- package/dist/close-status.d.ts +86 -0
- package/dist/close-status.d.ts.map +1 -0
- package/dist/close-status.js +91 -0
- package/dist/close-status.js.map +1 -0
- package/dist/continuation/continuation-transport.d.ts +41 -0
- package/dist/continuation/continuation-transport.d.ts.map +1 -0
- package/dist/continuation/continuation-transport.js +18 -0
- package/dist/continuation/continuation-transport.js.map +1 -0
- package/dist/continuation/index.d.ts +4 -0
- package/dist/continuation/index.d.ts.map +1 -0
- package/dist/continuation/index.js +4 -0
- package/dist/continuation/index.js.map +1 -0
- package/dist/continuation/journal.d.ts +37 -0
- package/dist/continuation/journal.d.ts.map +1 -0
- package/dist/continuation/journal.js +23 -0
- package/dist/continuation/journal.js.map +1 -0
- package/dist/continuation/run-start-handler.d.ts +75 -0
- package/dist/continuation/run-start-handler.d.ts.map +1 -0
- package/dist/continuation/run-start-handler.js +32 -0
- package/dist/continuation/run-start-handler.js.map +1 -0
- package/dist/delegated-tool-bridge.d.ts +53 -0
- package/dist/delegated-tool-bridge.d.ts.map +1 -0
- package/dist/delegated-tool-bridge.js +92 -0
- package/dist/delegated-tool-bridge.js.map +1 -0
- package/dist/event-log.d.ts +134 -0
- package/dist/event-log.d.ts.map +1 -0
- package/dist/event-log.js +108 -0
- package/dist/event-log.js.map +1 -0
- package/dist/frontend-capability-tools.d.ts +102 -0
- package/dist/frontend-capability-tools.d.ts.map +1 -0
- package/dist/frontend-capability-tools.js +68 -0
- package/dist/frontend-capability-tools.js.map +1 -0
- package/dist/frontend-session-registry.d.ts +127 -0
- package/dist/frontend-session-registry.d.ts.map +1 -0
- package/dist/frontend-session-registry.js +180 -0
- package/dist/frontend-session-registry.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/legacy-data-migration.d.ts +104 -0
- package/dist/legacy-data-migration.d.ts.map +1 -0
- package/dist/legacy-data-migration.js +239 -0
- package/dist/legacy-data-migration.js.map +1 -0
- package/dist/routines/index.d.ts +12 -0
- package/dist/routines/index.d.ts.map +1 -0
- package/dist/routines/index.js +12 -0
- package/dist/routines/index.js.map +1 -0
- package/dist/routines/routine-store.d.ts +77 -0
- package/dist/routines/routine-store.d.ts.map +1 -0
- package/dist/routines/routine-store.js +162 -0
- package/dist/routines/routine-store.js.map +1 -0
- package/dist/routines/schedule.d.ts +72 -0
- package/dist/routines/schedule.d.ts.map +1 -0
- package/dist/routines/schedule.js +263 -0
- package/dist/routines/schedule.js.map +1 -0
- package/dist/routines/scheduler.d.ts +34 -0
- package/dist/routines/scheduler.d.ts.map +1 -0
- package/dist/routines/scheduler.js +330 -0
- package/dist/routines/scheduler.js.map +1 -0
- package/dist/routines/types.d.ts +131 -0
- package/dist/routines/types.d.ts.map +1 -0
- package/dist/routines/types.js +9 -0
- package/dist/routines/types.js.map +1 -0
- package/dist/run/core/failure-taxonomy.d.ts +27 -0
- package/dist/run/core/failure-taxonomy.d.ts.map +1 -0
- package/dist/run/core/failure-taxonomy.js +16 -0
- package/dist/run/core/failure-taxonomy.js.map +1 -0
- package/dist/run/core/index.d.ts +5 -0
- package/dist/run/core/index.d.ts.map +1 -0
- package/dist/run/core/index.js +5 -0
- package/dist/run/core/index.js.map +1 -0
- package/dist/run/core/result.d.ts +25 -0
- package/dist/run/core/result.d.ts.map +1 -0
- package/dist/run/core/result.js +52 -0
- package/dist/run/core/result.js.map +1 -0
- package/dist/run/core/retry.d.ts +106 -0
- package/dist/run/core/retry.d.ts.map +1 -0
- package/dist/run/core/retry.js +210 -0
- package/dist/run/core/retry.js.map +1 -0
- package/dist/run/diagnostics/diagnostics.d.ts +86 -0
- package/dist/run/diagnostics/diagnostics.d.ts.map +1 -0
- package/dist/run/diagnostics/diagnostics.js +211 -0
- package/dist/run/diagnostics/diagnostics.js.map +1 -0
- package/dist/run/diagnostics/index.d.ts +3 -0
- package/dist/run/diagnostics/index.d.ts.map +1 -0
- package/dist/run/diagnostics/index.js +3 -0
- package/dist/run/diagnostics/index.js.map +1 -0
- package/dist/run/index.d.ts +16 -0
- package/dist/run/index.d.ts.map +1 -0
- package/dist/run/index.js +16 -0
- package/dist/run/index.js.map +1 -0
- package/dist/run-lifecycle.d.ts +118 -0
- package/dist/run-lifecycle.d.ts.map +1 -0
- package/dist/run-lifecycle.js +451 -0
- package/dist/run-lifecycle.js.map +1 -0
- package/dist/terminal-session.d.ts +139 -0
- package/dist/terminal-session.d.ts.map +1 -0
- package/dist/terminal-session.js +316 -0
- package/dist/terminal-session.js.map +1 -0
- package/dist/tokens.d.ts +9 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +19 -0
- package/dist/tokens.js.map +1 -0
- package/dist/tool-executor.d.ts +97 -0
- package/dist/tool-executor.d.ts.map +1 -0
- package/dist/tool-executor.js +198 -0
- package/dist/tool-executor.js.map +1 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for describing the origin of the Work and
|
|
141
|
+
reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Support. While redistributing the Work or
|
|
166
|
+
Derivative Works thereof, You may choose to offer, and charge a
|
|
167
|
+
fee for, acceptance of support, warranty, indemnity, or other
|
|
168
|
+
liability obligations and/or rights consistent with this License.
|
|
169
|
+
However, in accepting such obligations, You may act only on Your
|
|
170
|
+
own behalf and on Your sole responsibility, not on behalf of any
|
|
171
|
+
other Contributor, and only if You agree to indemnify, defend,
|
|
172
|
+
and hold each Contributor harmless for any liability incurred by,
|
|
173
|
+
or claims asserted against, such Contributor by reason of your
|
|
174
|
+
accepting any such warranty or support.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright 2026 Open Design contributors
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
|
@@ -0,0 +1,458 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `AgentExecutor` — the driver `RunLifecycle`'s own module doc names as the
|
|
3
|
+
* missing piece: *"It does not spawn or signal a subprocess... A driver...
|
|
4
|
+
* calls `emit()` for agent/stdout/stderr/error events, observes cancellation
|
|
5
|
+
* via `onCancelRequested`, and calls `finish()` once it knows the real
|
|
6
|
+
* outcome."* This module is that driver — it wires `@jini-ai/agent-runtime`'s
|
|
7
|
+
* registry/launch-resolution/stream-parsers (previously a complete but
|
|
8
|
+
* disconnected library, zero callers anywhere outside its own package) into
|
|
9
|
+
* a real `node:child_process` spawn, feeding both `RunLifecycle.emit()` and
|
|
10
|
+
* this package's own `@jini-ai/protocol` event envelope.
|
|
11
|
+
*
|
|
12
|
+
* ## v1 scope: 23 of 24 registered agent defs
|
|
13
|
+
*
|
|
14
|
+
* `@jini-ai/agent-runtime`'s registry ships 24 built-in defs across four
|
|
15
|
+
* `streamFormat` families. The JSON-stream-parser family — the four
|
|
16
|
+
* `createXStreamHandler`-shaped parsers (`claude-stream-json`,
|
|
17
|
+
* `json-event-stream`, `copilot-stream-json`, `qoder-stream-json`), covering
|
|
18
|
+
* 9 defs (amp, codebuddy, claude, codex, cursor-agent, opencode, mimo,
|
|
19
|
+
* copilot, qoder) — plus all 9 `acp-json-rpc` defs, plus the one `pi-rpc`
|
|
20
|
+
* def (`pi`), are wired here. ACP and pi-rpc each own their own JSON-RPC
|
|
21
|
+
* prompt-delivery protocol, so each takes its own lifecycle branch rather
|
|
22
|
+
* than being treated as a stdout-tail parser; pi-rpc's events arrive through
|
|
23
|
+
* the exact same `{type, ...}` vocabulary `translateAgentRuntimeEvent`
|
|
24
|
+
* already handles for ACP/JSON-stream (confirmed by reading every
|
|
25
|
+
* `mapPiRpcEvent` `send()` call site — no new translation code was needed),
|
|
26
|
+
* so only the driver wiring (spawn → attach → cancel → finish) was new for it.
|
|
27
|
+
*
|
|
28
|
+
* 4 of the 5 `streamFormat: 'plain'` defs — grok-build, aider, deepseek,
|
|
29
|
+
* qwen — are also driven, per
|
|
30
|
+
* `ADS-memory/reports/proposals/PROP-plain-format-agent-driving-2026-07-21.md`'s
|
|
31
|
+
* recommended "Option B": no structured stream parser at all. Every raw
|
|
32
|
+
* `child.stdout` chunk is forwarded verbatim as a `text_delta` `'agent'`
|
|
33
|
+
* event, live, as it arrives — never buffered until close (see
|
|
34
|
+
* `wireChildLifecycle`'s `streamFormat === 'plain'` branch). Prompt delivery
|
|
35
|
+
* across the 4 is not uniform: qwen already fit the pre-existing stdin-only
|
|
36
|
+
* guard; grok-build stages the prompt to a temp file via
|
|
37
|
+
* `preparePromptFileForAgent` (its path threaded into `buildArgs` through a
|
|
38
|
+
* `RuntimeContext`, cleaned up after the child exits on every path,
|
|
39
|
+
* including pre-spawn/spawn-failure ones); aider/deepseek carry the prompt
|
|
40
|
+
* on argv and are guarded pre-spawn by `checkPromptArgvBudget` plus the two
|
|
41
|
+
* Windows CreateProcess command-line-expansion guards
|
|
42
|
+
* (`checkWindowsCmdShimCommandLineBudget`/`checkWindowsDirectExeCommandLineBudget`).
|
|
43
|
+
*
|
|
44
|
+
* The 5th plain def, **antigravity, is deliberately still rejected.** It
|
|
45
|
+
* needs two concerns unrelated to `streamFormat: 'plain'` itself — buffering
|
|
46
|
+
* stdout until close so a leaked OAuth URL can be suppressed before it
|
|
47
|
+
* reaches the client, and a cross-run lock serializing writes to its shared
|
|
48
|
+
* `settings.json` model-selection file — that the proposal doc explicitly
|
|
49
|
+
* scoped out to its own follow-up (see that doc's §2c/§3). `run()` guards it
|
|
50
|
+
* with its own `def.id === 'antigravity'` check, ahead of (and independent
|
|
51
|
+
* of) the generic plain-format prompt-delivery/dispatch logic. `run()`
|
|
52
|
+
* rejects cleanly (never a bare throw) with an `AgentExecutorError` for any
|
|
53
|
+
* def outside the supported 23 — see `isSupportedStreamFormat`.
|
|
54
|
+
*
|
|
55
|
+
* ## Invariant
|
|
56
|
+
*
|
|
57
|
+
* `RunLifecycle.start()` already transitions a run to `'running'` before
|
|
58
|
+
* `run()` is ever called. Every *pre-spawn* failure path in `run()` — unknown
|
|
59
|
+
* `agentId`, an unsupported `streamFormat`/prompt-delivery shape, an
|
|
60
|
+
* unresolvable binary, or a spawn error — calls `lifecycle.finish({status:
|
|
61
|
+
* 'failed', resumable: false, code: null, signal: null})` itself before
|
|
62
|
+
* rejecting, so a run can never get stuck `'running'` with no watchdog.
|
|
63
|
+
* `resumable` is unconditionally `false` on these paths — there is no spawned
|
|
64
|
+
* child, hence nothing a classifier could examine (see
|
|
65
|
+
* `FailureClassificationContext`'s own doc).
|
|
66
|
+
*
|
|
67
|
+
* For a run that *did* spawn and then failed, `resumable` is decided by
|
|
68
|
+
* `classifyFailure` (gap 4 — see `ClassifyFailure`'s own doc), an injectable
|
|
69
|
+
* port with no default of its own in this module (`undefined` stays
|
|
70
|
+
* byte-identical to pre-gap-4 behavior — every `'failed'` outcome
|
|
71
|
+
* resumable:false). OD's ~20-vendor-CLI text-matching failure classifier was
|
|
72
|
+
* deliberately never ported (see `run/core/failure-taxonomy.ts`'s own doc and
|
|
73
|
+
* `source-map.md`). The real zero-config classifier lives in `@jini-ai/daemon`'s
|
|
74
|
+
* `run/core/retry.ts` (`resumableFromProcessExit`/`classifyProcessExitFailure`)
|
|
75
|
+
* and is wired in by `@jini-ai/node-host`'s `createLocalNodeDaemon` — see that
|
|
76
|
+
* package's own source-map.md, and `run/core/retry.ts`'s own doc for the
|
|
77
|
+
* classification policy and its 2026-07-22 merge-time reconciliation against
|
|
78
|
+
* a second, independently-built (and rejected) classifier that once lived in
|
|
79
|
+
* this module.
|
|
80
|
+
*/
|
|
81
|
+
import { spawn as nodeSpawn } from 'node:child_process';
|
|
82
|
+
import type { Principal } from '@jini-ai/core';
|
|
83
|
+
import type { RunAgentPayload, RunErrorPayload } from '@jini-ai/protocol';
|
|
84
|
+
import { applyAgentLaunchEnv, getAgentDef, resolveAgentLaunch, attachAcpSession, attachPiRpcSession, preparePromptFileForAgent, type AcpPermissionHandler } from '@jini-ai/agent-runtime';
|
|
85
|
+
import { collectProcessTreePids, createCommandInvocation, listProcessSnapshots, stopProcesses } from '@jini-ai/platform';
|
|
86
|
+
import type { RunByteJournal } from './continuation/journal.js';
|
|
87
|
+
import type { RunRetrySideEffectState } from './run/core/index.js';
|
|
88
|
+
import type { ToolExecutor } from './tool-executor.js';
|
|
89
|
+
import type { RunLifecycle } from './run-lifecycle.js';
|
|
90
|
+
declare const SUPPORTED_STREAM_FORMATS: readonly ["claude-stream-json", "json-event-stream", "copilot-stream-json", "qoder-stream-json", "acp-json-rpc", "pi-rpc", "plain"];
|
|
91
|
+
/** The families of the registry's stream-format this driver implements — see module doc. */
|
|
92
|
+
export type SupportedStreamFormat = (typeof SUPPORTED_STREAM_FORMATS)[number];
|
|
93
|
+
/**
|
|
94
|
+
* Narrows a `RuntimeAgentDef.streamFormat` string to the supported
|
|
95
|
+
* families.
|
|
96
|
+
* @param value - The def's raw `streamFormat` string.
|
|
97
|
+
* @returns `true` when `value` is one of the JSON-stream-parser, ACP, pi-rpc, or plain formats this driver wires.
|
|
98
|
+
* @complexity O(1) — fixed membership check.
|
|
99
|
+
* @overallScore 100/100
|
|
100
|
+
*/
|
|
101
|
+
export declare function isSupportedStreamFormat(value: string): value is SupportedStreamFormat;
|
|
102
|
+
/**
|
|
103
|
+
* Result of translating one parsed stream event into this engine's
|
|
104
|
+
* vocabulary. `'agent'` is the common case (forward as a `RunAgentPayload`
|
|
105
|
+
* via the `'agent'` run event); `'error'` and `'turn-end'` are the two
|
|
106
|
+
* type values `run()` handles specially rather than passing through (see
|
|
107
|
+
* module doc); `'ignored'` covers anything the 4 parsers never actually
|
|
108
|
+
* produce plus defensively malformed/non-record input.
|
|
109
|
+
*
|
|
110
|
+
* `'agent'`'s optional `sessionId` (gap 5, session resume — see
|
|
111
|
+
* `RunEndPayload.sessionRef`'s doc in `@jini-ai/protocol`) is a daemon-internal
|
|
112
|
+
* side channel, not part of the `RunAgentPayload` wire payload itself:
|
|
113
|
+
* OpenCode's `sessionID`/Codex's `thread_id`/Qoder's and Claude's
|
|
114
|
+
* `session_id` all arrive on a `'status'` event alongside fields
|
|
115
|
+
* `RunAgentPayload`'s `'status'` variant already models (`label`/`model`/
|
|
116
|
+
* `ttftMs`/`detail`) but has no room for a session id itself — surfacing it
|
|
117
|
+
* here lets a lifecycle-wiring function capture it into a local variable and
|
|
118
|
+
* thread it into its own terminal `finish()` call, without widening the
|
|
119
|
+
* public wire protocol just to carry a value that only this module reads.
|
|
120
|
+
*
|
|
121
|
+
* `'turn-end'`'s optional `stopReason` (gap 3, capability-routed
|
|
122
|
+
* continuation transport) is the same kind of internal side channel: the
|
|
123
|
+
* claude-stream parser deliberately emits `stopReason` *after* every
|
|
124
|
+
* `tool_use` block in the same assistant message has already been
|
|
125
|
+
* translated (so a caller can decide whether to keep stdin open before
|
|
126
|
+
* closing it), but v1 (pre-gap-3) discarded it and closed stdin
|
|
127
|
+
* unconditionally on any `turn-end` — see `packages/daemon/source-map.md`'s
|
|
128
|
+
* "Design decision 2" note. `wireChildLifecycle` now reads it to decide
|
|
129
|
+
* whether `stop_reason: 'tool_use'` means "inject a tool result and keep
|
|
130
|
+
* going" (gap 3, gated — see `ContinuationOptions`) or "close stdin as
|
|
131
|
+
* before" (the unconditional default when no continuation is configured).
|
|
132
|
+
*/
|
|
133
|
+
export type AgentRuntimeEventTranslation = {
|
|
134
|
+
readonly kind: 'agent';
|
|
135
|
+
readonly payload: RunAgentPayload;
|
|
136
|
+
readonly sessionId?: string;
|
|
137
|
+
} | {
|
|
138
|
+
readonly kind: 'error';
|
|
139
|
+
readonly payload: RunErrorPayload;
|
|
140
|
+
} | {
|
|
141
|
+
readonly kind: 'turn-end';
|
|
142
|
+
readonly stopReason?: string;
|
|
143
|
+
} | {
|
|
144
|
+
readonly kind: 'ignored';
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Narrows one parser-emitted `{type, ...}` record into this engine's
|
|
148
|
+
* `RunAgentPayload` union (or the `error`/`turn-end`/`ignored` routing
|
|
149
|
+
* `run()` special-cases). Pure — no I/O, no closure state — so every
|
|
150
|
+
* variant each of the 4 supported parsers can produce is directly
|
|
151
|
+
* assertable in isolation.
|
|
152
|
+
*
|
|
153
|
+
* Defensive by construction: several real parser emissions carry fields
|
|
154
|
+
* looser than `RunAgentPayload`'s types promise (e.g. copilot's
|
|
155
|
+
* `tool.execution_start` emits `id: data.toolCallId ?? null` — a literal
|
|
156
|
+
* `null`, not the `string` `RunAgentPayload['tool_use']['id']` demands).
|
|
157
|
+
* Every field read here is defensively coerced (`asString`/
|
|
158
|
+
* `asOptionalString`/`asOptionalNumber`) rather than trusted, so a
|
|
159
|
+
* malformed or null field degrades to a safe default instead of
|
|
160
|
+
* propagating `null`/`undefined` into a field typed as required, or
|
|
161
|
+
* throwing.
|
|
162
|
+
*
|
|
163
|
+
* @param rawEvent - One event as delivered to a stream parser's `onEvent` callback.
|
|
164
|
+
* @returns The routing + payload this event maps to.
|
|
165
|
+
* @complexity O(1) — one discriminant switch, no iteration.
|
|
166
|
+
* @overallScore 100/100
|
|
167
|
+
*/
|
|
168
|
+
export declare function translateAgentRuntimeEvent(rawEvent: unknown): AgentRuntimeEventTranslation;
|
|
169
|
+
/** Machine-readable failure reasons `run()` can reject with — every one is preceded by a `lifecycle.finish({status:'failed'})` call (see module doc's Invariant section). */
|
|
170
|
+
export type AgentExecutorErrorCode = 'AGENT_NOT_FOUND' | 'AGENT_RUNTIME_UNSUPPORTED' | 'AGENT_BINARY_NOT_RESOLVED' | 'AGENT_SPAWN_FAILED' | 'AGENT_PROMPT_TOO_LARGE';
|
|
171
|
+
/** Thrown by `AgentExecutor.run()` on every failure path — never a bare `Error`, so callers can branch on `.code` instead of parsing `.message`. */
|
|
172
|
+
export declare class AgentExecutorError extends Error {
|
|
173
|
+
readonly code: AgentExecutorErrorCode;
|
|
174
|
+
constructor(code: AgentExecutorErrorCode, message: string);
|
|
175
|
+
}
|
|
176
|
+
export interface AgentExecutorRunInput {
|
|
177
|
+
readonly runId: string;
|
|
178
|
+
readonly agentId: string;
|
|
179
|
+
readonly prompt: string;
|
|
180
|
+
readonly cwd: string;
|
|
181
|
+
/** Optional host-selected model id, forwarded to every runtime transport. */
|
|
182
|
+
readonly model?: string;
|
|
183
|
+
/** Optional host-selected reasoning effort, forwarded to runtime argv builders. */
|
|
184
|
+
readonly reasoning?: string;
|
|
185
|
+
/** Host-validated image files forwarded through argv, ACP, or pi-rpc. */
|
|
186
|
+
readonly imagePaths?: readonly string[];
|
|
187
|
+
/** Additional host-validated directories the runtime may read. */
|
|
188
|
+
readonly extraAllowedDirs?: readonly string[];
|
|
189
|
+
/** Trusted root that must contain pi-rpc image paths after realpath resolution. */
|
|
190
|
+
readonly uploadRoot?: string;
|
|
191
|
+
/**
|
|
192
|
+
* Credential(s) this run's selected agent/provider needs (e.g. `{ ANTHROPIC_API_KEY: '...' }`),
|
|
193
|
+
* delegated explicitly by the host and merged into the baseline-allowlisted env below. Never
|
|
194
|
+
* read implicitly from `process.env` — see SEC-001.
|
|
195
|
+
*/
|
|
196
|
+
readonly credentialEnv?: Record<string, string>;
|
|
197
|
+
/**
|
|
198
|
+
* Explicit escape hatch: when supplied, used verbatim as the spawned subprocess's entire
|
|
199
|
+
* environment (no allowlist filtering) — for tests and hosts that have already done their own
|
|
200
|
+
* scoping. When omitted (the default), the subprocess gets only `BASELINE_AGENT_ENV_KEYS` from
|
|
201
|
+
* the host's real env plus `credentialEnv`, never a full `process.env` passthrough. A spawned
|
|
202
|
+
* coding-agent CLI is prompt-influenced and must be treated as potentially adversarial; it must
|
|
203
|
+
* not inherit secrets the daemon process happens to hold for unrelated reasons. See SEC-001
|
|
204
|
+
* (`ADS-memory/reports/proposals/PROP-agent-subprocess-env-allowlist-2026-07-21.md`) and locked
|
|
205
|
+
* architecture decision C8 (`foundry/docs/jini-port/extraction-plan.md`).
|
|
206
|
+
*/
|
|
207
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
208
|
+
}
|
|
209
|
+
export interface AgentExecutor {
|
|
210
|
+
/**
|
|
211
|
+
* Spawns `agentId`'s CLI for `runId`, wires its stdout/stderr into
|
|
212
|
+
* `lifecycle.emit()`, and resolves once the child process is confirmed
|
|
213
|
+
* spawned (fire-and-forget from there — see module doc). Callers await
|
|
214
|
+
* `lifecycle.waitForTerminal(runId)` separately for completion.
|
|
215
|
+
* @throws {@link AgentExecutorError} on every failure path — the
|
|
216
|
+
* underlying run is always already transitioned to `'failed'` via
|
|
217
|
+
* `lifecycle.finish()` before this rejects (see module doc's Invariant).
|
|
218
|
+
*/
|
|
219
|
+
run(input: AgentExecutorRunInput): Promise<void>;
|
|
220
|
+
}
|
|
221
|
+
/** Which caller invoked {@link terminateChildTreeBestEffort} — carried through to `onCleanupFailure` (SEC-007) for diagnosis. */
|
|
222
|
+
export type AgentCleanupFailurePhase = 'cancel' | 'acp-attach-failure' | 'pi-rpc-attach-failure';
|
|
223
|
+
export interface AgentCleanupFailureContext {
|
|
224
|
+
readonly runId: string;
|
|
225
|
+
readonly phase: AgentCleanupFailurePhase;
|
|
226
|
+
readonly pid: number;
|
|
227
|
+
readonly error: unknown;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Gap 3 (capability-routed continuation transport) — host-owned config for the
|
|
231
|
+
* `'stdin-injection'` transport (claude/codebuddy only; see
|
|
232
|
+
* `resolveContinuationTransport`'s doc). **Absent by default, and absent means
|
|
233
|
+
* zero behavior change**: with no `ContinuationOptions`, every `turn_end`
|
|
234
|
+
* closes stdin exactly as it always has (v1 behavior, unconditionally).
|
|
235
|
+
*
|
|
236
|
+
* `autonomousToolNames` is this task's answer to the debate's Unresolved
|
|
237
|
+
* Delta (how does the loop distinguish "the agent is continuing
|
|
238
|
+
* autonomously" from "the agent is waiting on a human"): rather than
|
|
239
|
+
* inferring intent from the stream, the *host* pre-declares which tool
|
|
240
|
+
* names are safe to auto-resolve and re-inject without a human in the loop.
|
|
241
|
+
* A `tool_use` whose name is not in this set is left exactly as it was
|
|
242
|
+
* before gap 3 — stdin closes, the run proceeds to its normal terminal
|
|
243
|
+
* state — even though a `stopReason: 'tool_use'` was observed. This sidesteps
|
|
244
|
+
* building unproven intent-detection: nothing auto-continues unless a host
|
|
245
|
+
* has explicitly vetted that specific tool as autonomous-safe. A
|
|
246
|
+
* human-facing "ask the user a question" tool is simply never added to this
|
|
247
|
+
* set; `packages/chat-core/src/question-form.ts`'s existing text-tag
|
|
248
|
+
* mechanism (a new `Run` per turn, not mid-turn injection) already covers
|
|
249
|
+
* that case without needing this transport at all.
|
|
250
|
+
*/
|
|
251
|
+
export interface ContinuationOptions {
|
|
252
|
+
/** Injected tool results are authorized through this — the same deny-by-default gate every other tool execution path in this codebase uses. No parallel authorization path. */
|
|
253
|
+
readonly toolExecutor: ToolExecutor;
|
|
254
|
+
/** The principal an injected tool call is authorized as. */
|
|
255
|
+
readonly principal: Principal;
|
|
256
|
+
/** Tool names this host has pre-classified as safe to auto-resolve without human involvement. See this interface's own doc for why this — not stream-inferred intent — is gap 3's answer to the human-in-the-loop pause question. */
|
|
257
|
+
readonly autonomousToolNames: ReadonlySet<string>;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Gap 3, part 2 (MCP-callback continuation transport — the spawn-time half the spike's own
|
|
261
|
+
* commit message named as undone: "Item 4 ... NOT done yet"). `resolveContinuationTransport`
|
|
262
|
+
* already resolves `'mcp-callback'` for every def with `externalMcpInjection !== undefined`, but
|
|
263
|
+
* nothing in this file ever *acted* on that resolution — `execute_delegated_tool`
|
|
264
|
+
* (`@jini-ai/mcp`'s `../server/tools/delegated-tool.ts`) only does anything useful once the spawned
|
|
265
|
+
* CLI's own client actually launches `jini-mcp` as its MCP server subprocess, and the only
|
|
266
|
+
* `externalMcpInjection` strategy that mechanism is wired for here is `'claude-mcp-json'`
|
|
267
|
+
* (`claude`/`codebuddy` — see `@jini-ai/agent-runtime`'s `types.ts` doc on the other three
|
|
268
|
+
* strategies: `'acp-merge'` delivers `mcpServers` through the ACP `session/new` params
|
|
269
|
+
* `wireAcpLifecycle`/`attachAcpSession` already carry, and `'opencode-env-content'`/
|
|
270
|
+
* `'mimo-env-content'` deliver through spawn-env content, neither of which needs or wants a
|
|
271
|
+
* written file — a future task wiring those two would extend `wireAcpLifecycle`'s existing
|
|
272
|
+
* `envFormat`/`mcpServers` passthrough or `applyAgentLaunchEnv`'s env composition respectively,
|
|
273
|
+
* not this function).
|
|
274
|
+
*
|
|
275
|
+
* **Host-resolved, not this package's to know.** `command`/`daemonUrl` have no default the way
|
|
276
|
+
* `journal`/`continuation`/`classifyFailure` don't either — there is no "real" install layout or
|
|
277
|
+
* loopback URL this package could assume on a caller's behalf (matching every other seam on this
|
|
278
|
+
* interface that defaults to *nothing* rather than a real implementation).
|
|
279
|
+
*/
|
|
280
|
+
export interface McpJsonInjectionOptions {
|
|
281
|
+
/** Absolute path (or PATH-resolvable name) to the `jini-mcp` bin entry (`packages/mcp/src/bin/serve.ts`) this driver tells the spawned CLI to launch as its own MCP server subprocess. */
|
|
282
|
+
readonly command: string;
|
|
283
|
+
/** Extra argv for `command`. @default [] */
|
|
284
|
+
readonly args?: readonly string[];
|
|
285
|
+
/** The daemon's own loopback base URL the spawned `jini-mcp` process calls back into via `JINI_DAEMON_URL` (see `packages/mcp/src/bin/serve.ts`'s `DAEMON_URL_ENV_VAR`). */
|
|
286
|
+
readonly daemonUrl: string;
|
|
287
|
+
/** Reads an existing `.mcp.json` at the given absolute path so this driver merges rather than clobbers a project's own file. Rejecting (ENOENT or otherwise) is treated as "no existing file" — see `writeMcpJsonForRun`. @default the real `fs.promises.readFile` (utf8) */
|
|
288
|
+
readonly readFile?: (path: string) => Promise<string>;
|
|
289
|
+
/** Writes the merged `.mcp.json` content back out. @default the real `fs.promises.writeFile` (utf8) */
|
|
290
|
+
readonly writeFile?: (path: string, content: string) => Promise<void>;
|
|
291
|
+
}
|
|
292
|
+
/** One `.mcp.json` `mcpServers` entry — the shape Claude Code's own config schema expects. */
|
|
293
|
+
interface McpJsonServerEntry {
|
|
294
|
+
readonly command: string;
|
|
295
|
+
readonly args: string[];
|
|
296
|
+
readonly env: {
|
|
297
|
+
readonly JINI_RUN_ID: string;
|
|
298
|
+
readonly JINI_DAEMON_URL: string;
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Builds this run's `mcpServers.jini` entry — pure, so every field mapping is directly
|
|
303
|
+
* assertable without touching the filesystem.
|
|
304
|
+
* @complexity O(1).
|
|
305
|
+
* @overallScore 100/100
|
|
306
|
+
*/
|
|
307
|
+
export declare function buildMcpJsonServerEntry(runId: string, options: Pick<McpJsonInjectionOptions, 'command' | 'args' | 'daemonUrl'>): McpJsonServerEntry;
|
|
308
|
+
/**
|
|
309
|
+
* Merges {@link JINI_MCP_SERVER_KEY} into an existing `.mcp.json`'s `mcpServers` map, preserving
|
|
310
|
+
* every other key and every other registered server untouched. A missing (`existingRaw ===
|
|
311
|
+
* undefined`), empty, or unparseable-as-a-JSON-object existing file all degrade to "start from an
|
|
312
|
+
* empty document" rather than throwing — an unparseable project `.mcp.json` is a pre-existing
|
|
313
|
+
* problem this driver did not create and cannot safely repair, so it is deliberately overwritten
|
|
314
|
+
* with a fresh, valid file containing just this run's bridge entry rather than left broken or
|
|
315
|
+
* left blocking the run. Pure — no I/O — so every branch is directly assertable.
|
|
316
|
+
* @complexity O(1) plus `JSON.parse`/`JSON.stringify`'s own cost on a small config file.
|
|
317
|
+
* @overallScore 100/100
|
|
318
|
+
*/
|
|
319
|
+
export declare function mergeMcpJsonContent(existingRaw: string | undefined, serverEntry: McpJsonServerEntry): string;
|
|
320
|
+
/**
|
|
321
|
+
* Gap 4 of the run/chat orchestration Final Recommendation: what
|
|
322
|
+
* `classifyFailure` (see `CreateAgentExecutorOptions.classifyFailure`) is
|
|
323
|
+
* given to decide whether a `'failed'` run is `resumable`. `code`/`signal`
|
|
324
|
+
* are the only *content-level* signals cheaply available at every one of the
|
|
325
|
+
* three lifecycle-wiring close handlers without new stderr/stdout buffering
|
|
326
|
+
* machinery (a host wanting output-pattern-based classification, the way
|
|
327
|
+
* OD's own ~20-vendor text-matching classifier worked, would need its own
|
|
328
|
+
* listener for that — an honest scope limit, not an oversight).
|
|
329
|
+
*
|
|
330
|
+
* `sideEffects` (2026-07-22) carries the two `RunRetrySideEffectState` fields
|
|
331
|
+
* every `wire*Lifecycle` driver already tracks live from the translated
|
|
332
|
+
* agent-event stream it's processing anyway — `userVisibleOutputSeen` (a
|
|
333
|
+
* non-empty `text_delta`/`thinking_delta`) and `toolCallSeen` (a `tool_use`)
|
|
334
|
+
* — so `decideSafeRunRetry`'s matching suppression guards are genuinely
|
|
335
|
+
* exercised, not permanently dead code. Two related fields are deliberately
|
|
336
|
+
* absent: `cancelRequested` is never included because it's structurally
|
|
337
|
+
* always `false` by the time a classifier runs at all (a cancelled run's
|
|
338
|
+
* status already routes to `'cancelled'` before `classifyFailure` is ever
|
|
339
|
+
* consulted — see each `wire*Lifecycle` close handler); `artifactWriteSeen`/
|
|
340
|
+
* `liveArtifactSeen` have no real signal to derive them from at all —
|
|
341
|
+
* `@jini-ai/protocol`'s `RunAgentEventPayload` union (`events.ts`) has no
|
|
342
|
+
* `'artifact'`/`'live_artifact'` event kind yet (Jini's own generalized
|
|
343
|
+
* GenUI/artifact surface isn't built — see this repo's "A2UI full protocol
|
|
344
|
+
* deferred" scope note), unlike OD, which `RunRetrySideEffectState`'s shape
|
|
345
|
+
* was carried over from.
|
|
346
|
+
*/
|
|
347
|
+
export interface FailureClassificationContext {
|
|
348
|
+
readonly runId: string;
|
|
349
|
+
readonly agentId: string;
|
|
350
|
+
readonly code: number | null;
|
|
351
|
+
readonly signal: string | null;
|
|
352
|
+
readonly sideEffects: Pick<RunRetrySideEffectState, 'userVisibleOutputSeen' | 'toolCallSeen'>;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Host-owned failure classifier — gap 4. Decides, for one specific
|
|
356
|
+
* `'failed'` run, whether `RunLifecycle.finish()`'s `resumable` flag should
|
|
357
|
+
* be `true`. Never consulted for `'succeeded'`/`'cancelled'` outcomes, and
|
|
358
|
+
* never consulted for a pre-spawn failure (`failBeforeSpawn`'s call sites) —
|
|
359
|
+
* those represent failures where no child process ever ran, so there is
|
|
360
|
+
* nothing a classifier could meaningfully examine.
|
|
361
|
+
*/
|
|
362
|
+
export type ClassifyFailure = (context: FailureClassificationContext) => boolean | Promise<boolean>;
|
|
363
|
+
export interface CreateAgentExecutorOptions {
|
|
364
|
+
readonly lifecycle: RunLifecycle;
|
|
365
|
+
/** @default the real `@jini-ai/agent-runtime` registry lookup */
|
|
366
|
+
readonly getAgentDef?: typeof getAgentDef;
|
|
367
|
+
/** @default the real `@jini-ai/agent-runtime` launch resolver */
|
|
368
|
+
readonly resolveAgentLaunch?: typeof resolveAgentLaunch;
|
|
369
|
+
/** @default the real `@jini-ai/agent-runtime` PATH-env composer */
|
|
370
|
+
readonly applyAgentLaunchEnv?: typeof applyAgentLaunchEnv;
|
|
371
|
+
/** @default the real `@jini-ai/platform` cross-platform invocation builder */
|
|
372
|
+
readonly createCommandInvocation?: typeof createCommandInvocation;
|
|
373
|
+
/** @default `node:child_process`'s `spawn` */
|
|
374
|
+
readonly spawn?: typeof nodeSpawn;
|
|
375
|
+
/** @default the real `@jini-ai/agent-runtime` ACP session transport */
|
|
376
|
+
readonly attachAcpSession?: typeof attachAcpSession;
|
|
377
|
+
/**
|
|
378
|
+
* Host-owned policy for ACP agents' native tool calls. The ACP agent still
|
|
379
|
+
* executes its own selected option; Jini-registered tool execution belongs
|
|
380
|
+
* to `createDelegatedToolBridge`, not this permission callback.
|
|
381
|
+
*/
|
|
382
|
+
readonly acpPermissionHandler?: AcpPermissionHandler;
|
|
383
|
+
/** @default the real `@jini-ai/agent-runtime` pi-rpc session transport */
|
|
384
|
+
readonly attachPiRpcSession?: typeof attachPiRpcSession;
|
|
385
|
+
/**
|
|
386
|
+
* Stages a `promptViaFile` def's (grok-build) composed prompt to a temp
|
|
387
|
+
* file before `buildArgs` runs. Touches the real filesystem by default
|
|
388
|
+
* (`fs.mkdtemp`/`fs.writeFile`/`fs.rm`) — injectable so tests can drive
|
|
389
|
+
* it without real disk I/O, matching this factory's "no real subprocess,
|
|
390
|
+
* filesystem, or PATH lookup by default in tests" convention.
|
|
391
|
+
* @default the real `@jini-ai/agent-runtime` prompt-file stager
|
|
392
|
+
*/
|
|
393
|
+
readonly preparePromptFileForAgent?: typeof preparePromptFileForAgent;
|
|
394
|
+
/** @default the real `@jini-ai/platform` process-snapshot enumerator */
|
|
395
|
+
readonly listProcessSnapshots?: typeof listProcessSnapshots;
|
|
396
|
+
/** @default the real `@jini-ai/platform` descendant-PID collector */
|
|
397
|
+
readonly collectProcessTreePids?: typeof collectProcessTreePids;
|
|
398
|
+
/** @default the real `@jini-ai/platform` SIGTERM→SIGKILL escalator */
|
|
399
|
+
readonly stopProcesses?: typeof stopProcesses;
|
|
400
|
+
/** Host-owned sink for a process-tree cleanup failure (SEC-007) — e.g. EPERM stopping descendants. @default logs a redacted diagnostic via `console.error` */
|
|
401
|
+
readonly onCleanupFailure?: (context: AgentCleanupFailureContext) => void;
|
|
402
|
+
/**
|
|
403
|
+
* Gap 1's byte-journal (`packages/daemon/src/continuation/journal.ts`) — records every byte
|
|
404
|
+
* this driver sends to or receives from a child agent process, independent of and prior to any
|
|
405
|
+
* parsed/translated event. Covers `writePromptToStdin` (sent) and every `child.stdout`/
|
|
406
|
+
* `child.stderr` `'data'` handler this driver owns (received); does not cover ACP/pi-rpc's own
|
|
407
|
+
* prompt delivery, which happens inside their respective attach functions' own transport, out
|
|
408
|
+
* of this driver's direct view — see `WireAcpLifecycleContext.journal`'s doc.
|
|
409
|
+
* @default no journal — recording is entirely opt-in, unlike every other seam on this
|
|
410
|
+
* interface (which default to a real implementation): there is no generic "real" journal
|
|
411
|
+
* storage this package can default to without a caller-supplied `EventLog` instance.
|
|
412
|
+
*/
|
|
413
|
+
readonly journal?: RunByteJournal;
|
|
414
|
+
/**
|
|
415
|
+
* Gap 3's stdin-tool-result injection config — see `ContinuationOptions`'s own doc, especially
|
|
416
|
+
* on why `autonomousToolNames` (not stream-inferred intent) is this task's answer to the
|
|
417
|
+
* human-in-the-loop pause question.
|
|
418
|
+
* @default undefined — every `turn_end` closes stdin unconditionally, byte-identical to
|
|
419
|
+
* pre-gap-3 behavior. Opt-in only, like `journal`: there is no safe default allowlist of
|
|
420
|
+
* "tools okay to auto-continue without a human" this package can supply on a caller's behalf.
|
|
421
|
+
*/
|
|
422
|
+
readonly continuation?: ContinuationOptions;
|
|
423
|
+
/**
|
|
424
|
+
* Gap 4's failure classifier — see `ClassifyFailure`'s own doc.
|
|
425
|
+
* @default undefined — every `'failed'` run stays `resumable: false`, byte-identical to
|
|
426
|
+
* pre-gap-4 behavior. No default classifier exists: OD's own ~20-vendor-CLI text-matching
|
|
427
|
+
* failure classifier was deliberately never ported (see this module's own doc), so there is no
|
|
428
|
+
* generic "real" classification logic this package could supply on a caller's behalf.
|
|
429
|
+
*/
|
|
430
|
+
readonly classifyFailure?: ClassifyFailure;
|
|
431
|
+
/**
|
|
432
|
+
* Gap 3, part 2's spawn-time `.mcp.json` injection — see {@link McpJsonInjectionOptions}'s own
|
|
433
|
+
* doc for the full design (why only `'claude-mcp-json'`-injection defs, why host-resolved).
|
|
434
|
+
* @default undefined — no `.mcp.json` is written and no filesystem access beyond what already
|
|
435
|
+
* happened (prompt-file staging) occurs on this path, byte-identical to pre-this-task behavior.
|
|
436
|
+
* Opt-in only, like `journal`/`continuation`/`classifyFailure`: there is no safe default
|
|
437
|
+
* `command`/`daemonUrl` this package could assume on a caller's behalf.
|
|
438
|
+
*/
|
|
439
|
+
readonly mcpJsonInjection?: McpJsonInjectionOptions;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Creates the `AgentExecutor` reference implementation: an in-process
|
|
443
|
+
* `RunLifecycle` driver over real (by default) `@jini-ai/agent-runtime`
|
|
444
|
+
* registry lookup, launch resolution, and stream parsing, plus a real
|
|
445
|
+
* `node:child_process.spawn`. Every collaborator is an injectable seam
|
|
446
|
+
* (matching this package's established convention — see
|
|
447
|
+
* `tool-executor.ts`/`run-lifecycle.ts`) so tests can drive a fake child
|
|
448
|
+
* process and a fake registry without touching the filesystem or spawning
|
|
449
|
+
* a real subprocess.
|
|
450
|
+
*
|
|
451
|
+
* @param options.lifecycle - The `RunLifecycle` this executor drives — its `start()` must already have been called for any `runId` passed to `run()`.
|
|
452
|
+
* @returns An `AgentExecutor` whose `run()` never bare-throws (see module doc's Invariant).
|
|
453
|
+
* @complexity `run()`'s own setup is O(1); steady-state cost is the chosen stream parser's.
|
|
454
|
+
* @overallScore 100/100
|
|
455
|
+
*/
|
|
456
|
+
export declare function createAgentExecutor(options: CreateAgentExecutorOptions): AgentExecutor;
|
|
457
|
+
export {};
|
|
458
|
+
//# sourceMappingURL=agent-executor.d.ts.map
|