@inhuman.tools/harness-sdk 0.0.0-stage → 0.2.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.
Files changed (123) hide show
  1. package/LICENSE.md +7 -0
  2. package/dist/client-agents-tree.d.ts +123 -0
  3. package/dist/client-agents-tree.d.ts.map +1 -0
  4. package/dist/client-agents-tree.js +504 -0
  5. package/dist/client-agents-tree.js.map +1 -0
  6. package/dist/client-agents.d.ts +50 -0
  7. package/dist/client-agents.d.ts.map +1 -0
  8. package/dist/client-agents.js +299 -0
  9. package/dist/client-agents.js.map +1 -0
  10. package/dist/client.d.ts +89 -0
  11. package/dist/client.d.ts.map +1 -0
  12. package/dist/client.js +589 -0
  13. package/dist/client.js.map +1 -0
  14. package/dist/index.d.ts +10 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +10 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/launch/continue-pick.d.ts +17 -0
  19. package/dist/launch/continue-pick.d.ts.map +1 -0
  20. package/dist/launch/continue-pick.js +20 -0
  21. package/dist/launch/continue-pick.js.map +1 -0
  22. package/dist/launch/index.d.ts +6 -0
  23. package/dist/launch/index.d.ts.map +1 -0
  24. package/dist/launch/index.js +6 -0
  25. package/dist/launch/index.js.map +1 -0
  26. package/dist/launch/model-flags.d.ts +44 -0
  27. package/dist/launch/model-flags.d.ts.map +1 -0
  28. package/dist/launch/model-flags.js +216 -0
  29. package/dist/launch/model-flags.js.map +1 -0
  30. package/dist/launch/streams.d.ts +15 -0
  31. package/dist/launch/streams.d.ts.map +1 -0
  32. package/dist/launch/streams.js +2 -0
  33. package/dist/launch/streams.js.map +1 -0
  34. package/dist/launch/term-continue.d.ts +13 -0
  35. package/dist/launch/term-continue.d.ts.map +1 -0
  36. package/dist/launch/term-continue.js +17 -0
  37. package/dist/launch/term-continue.js.map +1 -0
  38. package/dist/launch/term-session-key.d.ts +8 -0
  39. package/dist/launch/term-session-key.d.ts.map +1 -0
  40. package/dist/launch/term-session-key.js +76 -0
  41. package/dist/launch/term-session-key.js.map +1 -0
  42. package/dist/observable-abort-signal.d.ts +7 -0
  43. package/dist/observable-abort-signal.d.ts.map +1 -0
  44. package/dist/observable-abort-signal.js +56 -0
  45. package/dist/observable-abort-signal.js.map +1 -0
  46. package/dist/open-external.d.ts +2 -0
  47. package/dist/open-external.d.ts.map +1 -0
  48. package/dist/open-external.js +24 -0
  49. package/dist/open-external.js.map +1 -0
  50. package/dist/paths.d.ts +7 -0
  51. package/dist/paths.d.ts.map +1 -0
  52. package/dist/paths.js +16 -0
  53. package/dist/paths.js.map +1 -0
  54. package/dist/text/agent-cover.d.ts +43 -0
  55. package/dist/text/agent-cover.d.ts.map +1 -0
  56. package/dist/text/agent-cover.js +123 -0
  57. package/dist/text/agent-cover.js.map +1 -0
  58. package/dist/text/format-shell.d.ts +5 -0
  59. package/dist/text/format-shell.d.ts.map +1 -0
  60. package/dist/text/format-shell.js +53 -0
  61. package/dist/text/format-shell.js.map +1 -0
  62. package/dist/text/identity.d.ts +67 -0
  63. package/dist/text/identity.d.ts.map +1 -0
  64. package/dist/text/identity.js +433 -0
  65. package/dist/text/identity.js.map +1 -0
  66. package/dist/text/index.d.ts +14 -0
  67. package/dist/text/index.d.ts.map +1 -0
  68. package/dist/text/index.js +15 -0
  69. package/dist/text/index.js.map +1 -0
  70. package/dist/text/liveness.d.ts +62 -0
  71. package/dist/text/liveness.d.ts.map +1 -0
  72. package/dist/text/liveness.js +270 -0
  73. package/dist/text/liveness.js.map +1 -0
  74. package/dist/text/mcp-identity.d.ts +25 -0
  75. package/dist/text/mcp-identity.d.ts.map +1 -0
  76. package/dist/text/mcp-identity.js +133 -0
  77. package/dist/text/mcp-identity.js.map +1 -0
  78. package/dist/text/pretty-identity.d.ts +15 -0
  79. package/dist/text/pretty-identity.d.ts.map +1 -0
  80. package/dist/text/pretty-identity.js +112 -0
  81. package/dist/text/pretty-identity.js.map +1 -0
  82. package/dist/text/sugarcoat.d.ts +29 -0
  83. package/dist/text/sugarcoat.d.ts.map +1 -0
  84. package/dist/text/sugarcoat.js +148 -0
  85. package/dist/text/sugarcoat.js.map +1 -0
  86. package/dist/text/unwrap-program.d.ts +2 -0
  87. package/dist/text/unwrap-program.d.ts.map +1 -0
  88. package/dist/text/unwrap-program.js +137 -0
  89. package/dist/text/unwrap-program.js.map +1 -0
  90. package/dist/text/work-text.d.ts +72 -0
  91. package/dist/text/work-text.d.ts.map +1 -0
  92. package/dist/text/work-text.js +337 -0
  93. package/dist/text/work-text.js.map +1 -0
  94. package/dist/transport/unix.d.ts +19 -0
  95. package/dist/transport/unix.d.ts.map +1 -0
  96. package/dist/transport/unix.js +68 -0
  97. package/dist/transport/unix.js.map +1 -0
  98. package/package.json +79 -3
  99. package/src/client-agents-tree.ts +642 -0
  100. package/src/client-agents.ts +230 -0
  101. package/src/client.ts +686 -0
  102. package/src/index.ts +27 -0
  103. package/src/launch/continue-pick.ts +28 -0
  104. package/src/launch/index.ts +5 -0
  105. package/src/launch/model-flags.ts +273 -0
  106. package/src/launch/streams.ts +13 -0
  107. package/src/launch/term-continue.ts +31 -0
  108. package/src/launch/term-session-key.ts +70 -0
  109. package/src/observable-abort-signal.ts +66 -0
  110. package/src/open-external.ts +22 -0
  111. package/src/paths.ts +20 -0
  112. package/src/text/agent-cover.ts +136 -0
  113. package/src/text/format-shell.ts +52 -0
  114. package/src/text/identity.ts +473 -0
  115. package/src/text/index.ts +29 -0
  116. package/src/text/liveness.ts +322 -0
  117. package/src/text/mcp-identity.ts +148 -0
  118. package/src/text/pretty-identity.ts +120 -0
  119. package/src/text/sugarcoat.ts +165 -0
  120. package/src/text/unwrap-program.ts +133 -0
  121. package/src/text/work-text.ts +388 -0
  122. package/src/transport/unix.ts +84 -0
  123. package/README.md +0 -3
package/LICENSE.md ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2026 Merkle Bonsai
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,123 @@
1
+ import { type SessionUnfinished } from "@inhuman.tools/harness-model/session";
2
+ import { type AgentTempo } from "./client-agents.js";
3
+ import type { Client } from "./client.js";
4
+ /** Ceiling for this-project conversations in the drawer. Not a visible-row target. */
5
+ export declare const DRAWER_RECENT_SESSION_LIMIT = 20;
6
+ /** U+25B8. Text play — resident background work. Not emoji. */
7
+ export declare const SESSION_FACE_PLAY = "\u25B8";
8
+ /** U+2016. Text pause — parked leftover work. Not emoji. */
9
+ export declare const SESSION_FACE_PAUSE = "\u2016";
10
+ /** Occupied ask. Paint is `attention` — same hue as the always-approve chip. */
11
+ export declare const SESSION_FACE_ASK = "awaiting approval";
12
+ /** Speech-question pin. Not license cover. */
13
+ export declare const SESSION_FACE_QUESTION = "has a question";
14
+ export type AgentDrawerCall = {
15
+ readonly key: string;
16
+ readonly spec: string;
17
+ readonly tempo: AgentTempo;
18
+ readonly status: string;
19
+ readonly prompt: string;
20
+ readonly notifies: readonly string[];
21
+ readonly result: string;
22
+ readonly sessionId: string;
23
+ readonly oneShot: boolean;
24
+ readonly completed: boolean;
25
+ readonly model: string;
26
+ readonly lastPrompt: string;
27
+ readonly askLine: string;
28
+ readonly unfinished: SessionUnfinished;
29
+ readonly mark: string;
30
+ readonly children: readonly AgentDrawerCall[];
31
+ };
32
+ export type AgentDrawerProgram = {
33
+ readonly key: string;
34
+ readonly name: string;
35
+ readonly children: readonly AgentDrawerCall[];
36
+ };
37
+ export type AgentDrawerCallNode = {
38
+ readonly kind: "program";
39
+ readonly program: AgentDrawerProgram;
40
+ } | {
41
+ readonly kind: "call";
42
+ readonly call: AgentDrawerCall;
43
+ };
44
+ export type AgentDrawerCollaborator = {
45
+ readonly key: string;
46
+ readonly sessionId: string;
47
+ readonly spec: string;
48
+ readonly tempo: AgentTempo;
49
+ readonly status: string;
50
+ readonly keepAlive: boolean;
51
+ readonly prompt: string;
52
+ readonly notifies: readonly string[];
53
+ readonly result: string;
54
+ };
55
+ export type AgentDrawerSession = {
56
+ readonly key: string;
57
+ readonly sessionId: string;
58
+ readonly title: string;
59
+ readonly status: string;
60
+ readonly model: string;
61
+ readonly lastMessageAt: number;
62
+ readonly occupied: boolean;
63
+ readonly resident: boolean;
64
+ readonly periodArmed: boolean;
65
+ readonly openTurn: boolean;
66
+ readonly openToolCount: number;
67
+ readonly unfinished: SessionUnfinished;
68
+ readonly tempo: AgentTempo;
69
+ readonly mark: string;
70
+ readonly lastPrompt: string;
71
+ readonly askLine: string;
72
+ readonly current: boolean;
73
+ };
74
+ export type AgentDrawerRowKind = "call" | "bot" | "session";
75
+ export type AgentDrawerRow = {
76
+ readonly key: string;
77
+ readonly kind: AgentDrawerRowKind;
78
+ readonly spec: string;
79
+ readonly recap: string;
80
+ readonly indent: number;
81
+ readonly prompt: string;
82
+ readonly notifies: readonly string[];
83
+ readonly result: string;
84
+ readonly tempo: AgentTempo;
85
+ readonly model: string;
86
+ readonly mark: string;
87
+ readonly lastPrompt: string;
88
+ readonly askLine: string;
89
+ readonly unfinished: SessionUnfinished;
90
+ readonly current: boolean;
91
+ /** Worker or conversation id. Empty until a Call intern stamps `workerSessionId`. */
92
+ readonly sessionId: string;
93
+ };
94
+ export type AgentDrawerProjection = {
95
+ readonly calls: readonly AgentDrawerCallNode[];
96
+ readonly collaborators: readonly AgentDrawerCollaborator[];
97
+ readonly sessions: readonly AgentDrawerSession[];
98
+ };
99
+ export type AgentMeterGroup = {
100
+ readonly spec: string;
101
+ readonly count: number;
102
+ };
103
+ export type AgentMeterProjection = {
104
+ readonly calls: readonly AgentMeterGroup[];
105
+ readonly bots: readonly string[];
106
+ };
107
+ export declare function projectAgentDrawer(client: Client): AgentDrawerProjection;
108
+ /** Call row for a tape mention. Settled calls stay off `flattenAgentDrawer` and still resolve. */
109
+ export declare function mentionedAgentCall(client: Client, key: string): {
110
+ readonly key: string;
111
+ readonly sessionId: string;
112
+ } | null;
113
+ export declare function flattenAgentDrawer(proj: AgentDrawerProjection): readonly AgentDrawerRow[];
114
+ export declare function projectRecentSessions(client: Client): readonly AgentDrawerSession[];
115
+ export declare function sessionOverviewMark(input: {
116
+ readonly current: boolean;
117
+ readonly occupied: boolean;
118
+ readonly resident: boolean;
119
+ readonly unfinished: SessionUnfinished;
120
+ readonly periodArmed: boolean;
121
+ }): string;
122
+ export declare function projectAgentMeter(client: Client, proj?: AgentDrawerProjection): AgentMeterProjection | null;
123
+ //# sourceMappingURL=client-agents-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-agents-tree.d.ts","sourceRoot":"","sources":["../src/client-agents-tree.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,504 @@
1
+ /**
2
+ * Drawer projection over the existing gatherer. Tape order is the tree.
3
+ * Does not intern workers. Does not wait on Agent.parent.
4
+ *
5
+ * Compact meter: left is the live huddle — unfinished calls whose worker
6
+ * is not a pal. Right is pals this tape already talked to: keepAlive
7
+ * workers, or conversations. One-shots are never pals. A pal
8
+ * currently working stays on the right only. Drawer Subagents rows are
9
+ * unfinished Calls; settled Calls stay off that list. A tape mention
10
+ * still resolves through `mentionedAgentCall`, including a settled Call.
11
+ */
12
+ import { recordString } from "@inhuman.tools/harness-model/json-record";
13
+ import { isConversationOverview, occupiedSessionIds, } from "@inhuman.tools/harness-model/kernel";
14
+ import { AgentCallJob, CallJob, isNoteClaimed, ProgrammaticJob, SessionTurn, reactChunks, BotCallJob, } from "@inhuman.tools/harness-model/session";
15
+ import { comparer, computed } from "mobx";
16
+ import { ClientAgent } from "./client-agents.js";
17
+ /** Ceiling for this-project conversations in the drawer. Not a visible-row target. */
18
+ export const DRAWER_RECENT_SESSION_LIMIT = 20;
19
+ /** U+25B8. Text play — resident background work. Not emoji. */
20
+ export const SESSION_FACE_PLAY = "▸";
21
+ /** U+2016. Text pause — parked leftover work. Not emoji. */
22
+ export const SESSION_FACE_PAUSE = "‖";
23
+ /** Occupied ask. Paint is `attention` — same hue as the always-approve chip. */
24
+ export const SESSION_FACE_ASK = "awaiting approval";
25
+ /** Speech-question pin. Not license cover. */
26
+ export const SESSION_FACE_QUESTION = "has a question";
27
+ const turnCallChunksCache = new WeakMap();
28
+ function turnCallChunks(turn) {
29
+ let box = turnCallChunksCache.get(turn);
30
+ if (box === undefined) {
31
+ box = computed(() => {
32
+ const out = [];
33
+ for (const chunk of reactChunks(turn)) {
34
+ if (chunk instanceof CallJob) {
35
+ out.push(chunk);
36
+ }
37
+ else if (chunk instanceof ProgrammaticJob && chunk.toolCalls.some((inner) => inner instanceof CallJob)) {
38
+ out.push(chunk);
39
+ }
40
+ }
41
+ return out;
42
+ }, { equals: comparer.shallow });
43
+ turnCallChunksCache.set(turn, box);
44
+ }
45
+ return box.get();
46
+ }
47
+ export function projectAgentDrawer(client) {
48
+ const seen = new Set();
49
+ const calls = [];
50
+ for (const turn of tapeTurns(client)) {
51
+ for (const chunk of turnCallChunks(turn)) {
52
+ if (chunk instanceof ProgrammaticJob) {
53
+ const nested = [];
54
+ for (const inner of chunk.toolCalls) {
55
+ if (!(inner instanceof CallJob))
56
+ continue;
57
+ if (seen.has(inner))
58
+ continue;
59
+ seen.add(inner);
60
+ nested.push(projectCall(client, inner));
61
+ }
62
+ if (nested.length === 0)
63
+ continue;
64
+ const expr = chunk.expr.trim();
65
+ const toolName = typeof chunk.toolName === "string" ? chunk.toolName.trim() : "";
66
+ const name = expr !== "" && expr !== "()" ? expr : toolName === "" || toolName === "scheme_repl" ? "scheme" : toolName;
67
+ calls.push({
68
+ kind: "program",
69
+ program: { key: `program:${chunk.toolCallId}`, name, children: nested },
70
+ });
71
+ continue;
72
+ }
73
+ if (!(chunk instanceof CallJob))
74
+ continue;
75
+ if (seen.has(chunk))
76
+ continue;
77
+ seen.add(chunk);
78
+ calls.push({ kind: "call", call: projectCall(client, chunk) });
79
+ }
80
+ }
81
+ for (const leftover of client.agentCalls) {
82
+ if (seen.has(leftover))
83
+ continue;
84
+ seen.add(leftover);
85
+ calls.push({ kind: "call", call: projectCall(client, leftover) });
86
+ }
87
+ return { calls, collaborators: projectCollaborators(client), sessions: projectRecentSessions(client) };
88
+ }
89
+ /** Call row for a tape mention. Settled calls stay off `flattenAgentDrawer` and still resolve. */
90
+ export function mentionedAgentCall(client, key) {
91
+ if (!key.startsWith("call:") || key.length === "call:".length)
92
+ return null;
93
+ const walk = (call) => {
94
+ if (call.key === key)
95
+ return call;
96
+ for (const child of call.children) {
97
+ const hit = walk(child);
98
+ if (hit != null)
99
+ return hit;
100
+ }
101
+ return null;
102
+ };
103
+ for (const node of projectAgentDrawer(client).calls) {
104
+ const roots = node.kind === "program" ? node.program.children : [node.call];
105
+ for (const call of roots) {
106
+ const hit = walk(call);
107
+ if (hit != null)
108
+ return { key: hit.key, sessionId: hit.sessionId };
109
+ }
110
+ }
111
+ return null;
112
+ }
113
+ export function flattenAgentDrawer(proj) {
114
+ const rows = [];
115
+ const emit = (call, indent) => {
116
+ const live = !call.completed;
117
+ if (live)
118
+ rows.push(callRow(call, indent));
119
+ const next = live ? indent + 1 : indent;
120
+ for (const child of call.children)
121
+ emit(child, next);
122
+ };
123
+ for (const node of proj.calls) {
124
+ if (node.kind === "program") {
125
+ for (const call of node.program.children)
126
+ emit(call, 0);
127
+ continue;
128
+ }
129
+ emit(node.call, 0);
130
+ }
131
+ for (const bot of proj.collaborators) {
132
+ rows.push({
133
+ key: bot.key,
134
+ kind: "bot",
135
+ spec: bot.spec,
136
+ recap: bot.status,
137
+ indent: 0,
138
+ prompt: bot.prompt,
139
+ notifies: bot.notifies,
140
+ result: bot.result,
141
+ tempo: bot.tempo,
142
+ model: "",
143
+ mark: "",
144
+ lastPrompt: "",
145
+ askLine: "",
146
+ unfinished: "",
147
+ current: false,
148
+ sessionId: bot.sessionId,
149
+ });
150
+ }
151
+ for (const session of proj.sessions) {
152
+ rows.push({
153
+ key: session.key,
154
+ kind: "session",
155
+ spec: session.title,
156
+ recap: session.status,
157
+ indent: 0,
158
+ prompt: "",
159
+ notifies: [],
160
+ result: "",
161
+ tempo: session.tempo,
162
+ model: session.model,
163
+ mark: session.mark,
164
+ lastPrompt: session.lastPrompt,
165
+ askLine: session.askLine,
166
+ unfinished: session.unfinished,
167
+ current: session.current,
168
+ sessionId: session.sessionId,
169
+ });
170
+ }
171
+ return rows;
172
+ }
173
+ export function projectRecentSessions(client) {
174
+ const occupied = occupiedSessionIds(client.kernelPlexus.awareness);
175
+ const rows = [];
176
+ for (const id of Object.keys(client.projectRoot.sessions)) {
177
+ const sessionId = id.trim();
178
+ if (sessionId === "")
179
+ continue;
180
+ const glance = client.kernelRoot.sessions[sessionId];
181
+ if (!isConversationOverview(glance))
182
+ continue;
183
+ const title = fieldText(glance.title);
184
+ const status = fieldText(glance.status);
185
+ const current = sessionId === client.sessionId;
186
+ // Intern stamps lastMessageAt. Title is first prompt / rename / metadata;
187
+ // status is update_metadata. Either means a session happened.
188
+ if (title === "" && status === "")
189
+ continue;
190
+ const unfinished = unfinishedOf(glance);
191
+ rows.push({
192
+ key: `session:${sessionId}`,
193
+ sessionId,
194
+ title: title === "" ? sessionId : title,
195
+ status,
196
+ lastMessageAt: typeof glance.lastMessageAt === "number" && Number.isFinite(glance.lastMessageAt) ? glance.lastMessageAt : 0,
197
+ occupied: occupied.has(sessionId),
198
+ resident: glance.resident === true,
199
+ periodArmed: glance.periodArmed === true,
200
+ openTurn: glance.openTurn === true,
201
+ openToolCount: fieldCount(glance.openToolCount),
202
+ unfinished,
203
+ lastPrompt: fieldText(glance.lastPrompt),
204
+ askLine: unfinished === "question" ? fieldText(glance.questionLine) : fieldText(glance.askLine),
205
+ current,
206
+ tempo: glance.asking === true || unfinished === "question"
207
+ ? "blocked"
208
+ : glance.midMotion === true ||
209
+ glance.openTurn === true ||
210
+ fieldCount(glance.openToolCount) > 0 ||
211
+ fieldCount(glance.openCallbackCount) > 0
212
+ ? "active"
213
+ : "idle",
214
+ model: fieldText(glance.model),
215
+ mark: sessionOverviewMark({
216
+ current,
217
+ occupied: occupied.has(sessionId),
218
+ resident: glance.resident === true,
219
+ unfinished: unfinishedOf(glance),
220
+ periodArmed: glance.periodArmed === true,
221
+ }),
222
+ });
223
+ }
224
+ rows.sort((a, b) => b.lastMessageAt - a.lastMessageAt || a.sessionId.localeCompare(b.sessionId));
225
+ return rows.slice(0, DRAWER_RECENT_SESSION_LIMIT);
226
+ }
227
+ function fieldText(value) {
228
+ return typeof value === "string" ? value.trim() : "";
229
+ }
230
+ function fieldCount(value) {
231
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : 0;
232
+ }
233
+ function unfinishedOf(glance) {
234
+ const stamped = glance.unfinished;
235
+ switch (true) {
236
+ case stamped === "ask":
237
+ case stamped === "tools":
238
+ case stamped === "turn":
239
+ case stamped === "question":
240
+ return stamped;
241
+ case glance.asking === true:
242
+ return "ask";
243
+ case fieldCount(glance.openToolCount) > 0:
244
+ return "tools";
245
+ case glance.openTurn === true:
246
+ return "turn";
247
+ case glance.midMotion === true && glance.periodArmed !== true:
248
+ return "tools";
249
+ default:
250
+ return "";
251
+ }
252
+ }
253
+ export function sessionOverviewMark(input) {
254
+ switch (true) {
255
+ case input.current:
256
+ return "this session";
257
+ case input.unfinished === "question":
258
+ return SESSION_FACE_QUESTION;
259
+ case input.occupied && input.unfinished === "ask":
260
+ return SESSION_FACE_ASK;
261
+ case input.occupied && input.unfinished !== "":
262
+ return "active";
263
+ case input.occupied:
264
+ return "idle";
265
+ case input.unfinished !== "" && input.resident:
266
+ return SESSION_FACE_PLAY;
267
+ case input.unfinished !== "":
268
+ return SESSION_FACE_PAUSE;
269
+ case input.resident && input.periodArmed:
270
+ return "bot";
271
+ default:
272
+ return "";
273
+ }
274
+ }
275
+ export function projectAgentMeter(client, proj = projectAgentDrawer(client)) {
276
+ const pals = new Set(proj.collaborators.map((bot) => bot.sessionId));
277
+ const live = [];
278
+ for (const node of proj.calls) {
279
+ const bag = node.kind === "program" ? node.program.children : [node.call];
280
+ for (const call of bag) {
281
+ if (call.completed)
282
+ continue;
283
+ if (call.tempo !== "active" && call.tempo !== "blocked")
284
+ continue;
285
+ if (call.sessionId !== "" && pals.has(call.sessionId))
286
+ continue;
287
+ live.push(call.spec);
288
+ }
289
+ }
290
+ if (live.length === 0 && proj.collaborators.length === 0)
291
+ return null;
292
+ const groups = [];
293
+ const index = new Map();
294
+ for (const spec of live) {
295
+ const name = spec.trim() === "" ? "agent" : spec;
296
+ const at = index.get(name);
297
+ if (at === undefined) {
298
+ index.set(name, groups.length);
299
+ groups.push({ spec: name, count: 1 });
300
+ }
301
+ else {
302
+ groups[at] = { spec: name, count: groups[at].count + 1 };
303
+ }
304
+ }
305
+ return { calls: groups, bots: proj.collaborators.map((bot) => bot.spec) };
306
+ }
307
+ function callRow(call, indent) {
308
+ return {
309
+ key: call.key,
310
+ kind: "call",
311
+ spec: call.spec,
312
+ recap: call.status,
313
+ indent,
314
+ prompt: call.prompt,
315
+ notifies: call.notifies,
316
+ result: call.result,
317
+ tempo: call.tempo,
318
+ model: call.model,
319
+ mark: call.mark,
320
+ lastPrompt: call.lastPrompt,
321
+ askLine: call.askLine,
322
+ unfinished: call.unfinished,
323
+ current: false,
324
+ sessionId: call.sessionId,
325
+ };
326
+ }
327
+ function projectCall(client, call) {
328
+ const sessionId = call.workerSessionId.trim();
329
+ const spec = recordString(call.args, "spec");
330
+ const bot = call instanceof BotCallJob ? call.botName.trim() || call.contributionBotName.trim() : "";
331
+ const face = workerFace(client, sessionId, call.completed);
332
+ const faceName = call instanceof AgentCallJob ? fieldText(call.faceName) : "";
333
+ return {
334
+ key: `call:${call.toolCallId}`,
335
+ spec: spec === "" ? (bot === "" ? face.specName || faceName || "agent" : bot) : spec,
336
+ tempo: face.tempo,
337
+ status: face.status,
338
+ prompt: spawnPrompt(call),
339
+ notifies: notifyLines(call),
340
+ result: resultText(call),
341
+ sessionId,
342
+ oneShot: call instanceof AgentCallJob,
343
+ completed: call.completed,
344
+ model: face.model,
345
+ lastPrompt: face.lastPrompt,
346
+ askLine: face.askLine,
347
+ unfinished: face.unfinished,
348
+ mark: face.mark,
349
+ children: kernelChildren(client, sessionId, new Set([client.sessionId])),
350
+ };
351
+ }
352
+ function kernelChildren(client, callerSessionId, path) {
353
+ if (callerSessionId === "" || path.has(callerSessionId))
354
+ return [];
355
+ const nextPath = new Set(path);
356
+ nextPath.add(callerSessionId);
357
+ const out = [];
358
+ const bag = client.kernelRoot.agentCalls;
359
+ for (const id of Object.keys(bag).sort()) {
360
+ const rel = bag[id];
361
+ if (rel == null || rel.callerSessionId !== callerSessionId)
362
+ continue;
363
+ if (nextPath.has(rel.workerSessionId.trim()))
364
+ continue;
365
+ const row = projectRelation(client, id, rel, nextPath);
366
+ if (row != null)
367
+ out.push(row);
368
+ }
369
+ return out;
370
+ }
371
+ function projectRelation(client, id, rel, path) {
372
+ const worker = rel.workerSessionId.trim();
373
+ if (worker === "")
374
+ return null;
375
+ const spec = rel.spec.trim();
376
+ const face = workerFace(client, worker, rel.completed);
377
+ return {
378
+ key: `call:${id}`,
379
+ spec: spec === "" ? "agent" : spec,
380
+ tempo: face.tempo,
381
+ status: face.status,
382
+ prompt: "",
383
+ notifies: [],
384
+ result: "",
385
+ sessionId: worker,
386
+ oneShot: rel.oneShot,
387
+ completed: rel.completed,
388
+ model: face.model,
389
+ lastPrompt: face.lastPrompt,
390
+ askLine: face.askLine,
391
+ unfinished: face.unfinished,
392
+ mark: face.mark,
393
+ children: kernelChildren(client, worker, path),
394
+ };
395
+ }
396
+ function workerFace(client, sessionId, completed) {
397
+ const agent = sessionId === "" ? null : new ClientAgent(client, sessionId);
398
+ const glance = agent?.overview ?? null;
399
+ const unfinished = glance == null ? "" : unfinishedOf(glance);
400
+ const tempo = completed ? "idle" : (agent?.tempo ?? "active");
401
+ return {
402
+ tempo,
403
+ status: agent?.status ?? "",
404
+ model: agent?.model ?? "",
405
+ lastPrompt: fieldText(glance?.lastPrompt),
406
+ askLine: unfinished === "question" ? fieldText(glance?.questionLine) : fieldText(glance?.askLine),
407
+ unfinished,
408
+ mark: callGlanceMark({ unfinished, tempo }),
409
+ specName: fieldText(glance?.specName) || (agent?.specName ?? ""),
410
+ };
411
+ }
412
+ function callGlanceMark(input) {
413
+ if (input.unfinished === "question")
414
+ return SESSION_FACE_QUESTION;
415
+ if (input.unfinished === "ask" || input.tempo === "blocked")
416
+ return SESSION_FACE_ASK;
417
+ if (input.tempo === "active")
418
+ return "active";
419
+ return "";
420
+ }
421
+ function projectCollaborators(client) {
422
+ const seen = new Set();
423
+ const out = [];
424
+ const take = (agent) => {
425
+ if (agent.sessionId === "" || seen.has(agent.sessionId))
426
+ return;
427
+ seen.add(agent.sessionId);
428
+ if (!isCollaborator(client, agent))
429
+ return;
430
+ const last = agent.lastCall;
431
+ const spec = isConversationOverview(agent.overview)
432
+ ? agent.title.trim() || agent.specName
433
+ : agent.specName.trim() || agent.title;
434
+ out.push({
435
+ key: `bot:${agent.sessionId}`,
436
+ sessionId: agent.sessionId,
437
+ spec,
438
+ tempo: agent.tempo,
439
+ status: agent.status,
440
+ keepAlive: agent.keepAlive,
441
+ prompt: last == null ? "" : spawnPrompt(last),
442
+ notifies: last == null ? [] : notifyLines(last),
443
+ result: last == null ? "" : resultText(last),
444
+ });
445
+ };
446
+ for (const agent of client.agents)
447
+ take(agent);
448
+ for (const call of client.agentCalls) {
449
+ const id = call.workerSessionId.trim();
450
+ if (id === "" || seen.has(id))
451
+ continue;
452
+ take(new ClientAgent(client, id));
453
+ }
454
+ return out;
455
+ }
456
+ function isCollaborator(client, agent) {
457
+ if (agent.sessionId === client.sessionId)
458
+ return false;
459
+ if (!agent.interacted)
460
+ return false;
461
+ if (agent.oneShot)
462
+ return false;
463
+ if (agent.keepAlive)
464
+ return true;
465
+ return isConversationOverview(agent.overview) && agent.sessionId in client.projectRoot.sessions;
466
+ }
467
+ function tapeTurns(client) {
468
+ const spine = [];
469
+ const seen = new Set();
470
+ let cell = client.sessionRoot.head;
471
+ while (cell !== null && !seen.has(cell)) {
472
+ seen.add(cell);
473
+ if (cell instanceof SessionTurn)
474
+ spine.push(cell);
475
+ cell = cell.turnTail;
476
+ }
477
+ spine.reverse();
478
+ return spine;
479
+ }
480
+ function spawnPrompt(call) {
481
+ return recordString(call.args, "message");
482
+ }
483
+ function notifyLines(call) {
484
+ const out = [];
485
+ for (const note of call.notifications) {
486
+ if (isNoteClaimed(note))
487
+ continue;
488
+ const message = note.message.trim();
489
+ if (message !== "")
490
+ out.push(message);
491
+ }
492
+ return out;
493
+ }
494
+ function resultText(call) {
495
+ if (!call.completed)
496
+ return "";
497
+ const payload = call.observationPayload();
498
+ if (typeof payload === "string")
499
+ return payload;
500
+ if (payload == null)
501
+ return "";
502
+ return String(payload);
503
+ }
504
+ //# sourceMappingURL=client-agents-tree.js.map