@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.
- package/LICENSE.md +7 -0
- package/dist/client-agents-tree.d.ts +123 -0
- package/dist/client-agents-tree.d.ts.map +1 -0
- package/dist/client-agents-tree.js +504 -0
- package/dist/client-agents-tree.js.map +1 -0
- package/dist/client-agents.d.ts +50 -0
- package/dist/client-agents.d.ts.map +1 -0
- package/dist/client-agents.js +299 -0
- package/dist/client-agents.js.map +1 -0
- package/dist/client.d.ts +89 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +589 -0
- package/dist/client.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/launch/continue-pick.d.ts +17 -0
- package/dist/launch/continue-pick.d.ts.map +1 -0
- package/dist/launch/continue-pick.js +20 -0
- package/dist/launch/continue-pick.js.map +1 -0
- package/dist/launch/index.d.ts +6 -0
- package/dist/launch/index.d.ts.map +1 -0
- package/dist/launch/index.js +6 -0
- package/dist/launch/index.js.map +1 -0
- package/dist/launch/model-flags.d.ts +44 -0
- package/dist/launch/model-flags.d.ts.map +1 -0
- package/dist/launch/model-flags.js +216 -0
- package/dist/launch/model-flags.js.map +1 -0
- package/dist/launch/streams.d.ts +15 -0
- package/dist/launch/streams.d.ts.map +1 -0
- package/dist/launch/streams.js +2 -0
- package/dist/launch/streams.js.map +1 -0
- package/dist/launch/term-continue.d.ts +13 -0
- package/dist/launch/term-continue.d.ts.map +1 -0
- package/dist/launch/term-continue.js +17 -0
- package/dist/launch/term-continue.js.map +1 -0
- package/dist/launch/term-session-key.d.ts +8 -0
- package/dist/launch/term-session-key.d.ts.map +1 -0
- package/dist/launch/term-session-key.js +76 -0
- package/dist/launch/term-session-key.js.map +1 -0
- package/dist/observable-abort-signal.d.ts +7 -0
- package/dist/observable-abort-signal.d.ts.map +1 -0
- package/dist/observable-abort-signal.js +56 -0
- package/dist/observable-abort-signal.js.map +1 -0
- package/dist/open-external.d.ts +2 -0
- package/dist/open-external.d.ts.map +1 -0
- package/dist/open-external.js +24 -0
- package/dist/open-external.js.map +1 -0
- package/dist/paths.d.ts +7 -0
- package/dist/paths.d.ts.map +1 -0
- package/dist/paths.js +16 -0
- package/dist/paths.js.map +1 -0
- package/dist/text/agent-cover.d.ts +43 -0
- package/dist/text/agent-cover.d.ts.map +1 -0
- package/dist/text/agent-cover.js +123 -0
- package/dist/text/agent-cover.js.map +1 -0
- package/dist/text/format-shell.d.ts +5 -0
- package/dist/text/format-shell.d.ts.map +1 -0
- package/dist/text/format-shell.js +53 -0
- package/dist/text/format-shell.js.map +1 -0
- package/dist/text/identity.d.ts +67 -0
- package/dist/text/identity.d.ts.map +1 -0
- package/dist/text/identity.js +433 -0
- package/dist/text/identity.js.map +1 -0
- package/dist/text/index.d.ts +14 -0
- package/dist/text/index.d.ts.map +1 -0
- package/dist/text/index.js +15 -0
- package/dist/text/index.js.map +1 -0
- package/dist/text/liveness.d.ts +62 -0
- package/dist/text/liveness.d.ts.map +1 -0
- package/dist/text/liveness.js +270 -0
- package/dist/text/liveness.js.map +1 -0
- package/dist/text/mcp-identity.d.ts +25 -0
- package/dist/text/mcp-identity.d.ts.map +1 -0
- package/dist/text/mcp-identity.js +133 -0
- package/dist/text/mcp-identity.js.map +1 -0
- package/dist/text/pretty-identity.d.ts +15 -0
- package/dist/text/pretty-identity.d.ts.map +1 -0
- package/dist/text/pretty-identity.js +112 -0
- package/dist/text/pretty-identity.js.map +1 -0
- package/dist/text/sugarcoat.d.ts +29 -0
- package/dist/text/sugarcoat.d.ts.map +1 -0
- package/dist/text/sugarcoat.js +148 -0
- package/dist/text/sugarcoat.js.map +1 -0
- package/dist/text/unwrap-program.d.ts +2 -0
- package/dist/text/unwrap-program.d.ts.map +1 -0
- package/dist/text/unwrap-program.js +137 -0
- package/dist/text/unwrap-program.js.map +1 -0
- package/dist/text/work-text.d.ts +72 -0
- package/dist/text/work-text.d.ts.map +1 -0
- package/dist/text/work-text.js +337 -0
- package/dist/text/work-text.js.map +1 -0
- package/dist/transport/unix.d.ts +19 -0
- package/dist/transport/unix.d.ts.map +1 -0
- package/dist/transport/unix.js +68 -0
- package/dist/transport/unix.js.map +1 -0
- package/package.json +79 -3
- package/src/client-agents-tree.ts +642 -0
- package/src/client-agents.ts +230 -0
- package/src/client.ts +686 -0
- package/src/index.ts +27 -0
- package/src/launch/continue-pick.ts +28 -0
- package/src/launch/index.ts +5 -0
- package/src/launch/model-flags.ts +273 -0
- package/src/launch/streams.ts +13 -0
- package/src/launch/term-continue.ts +31 -0
- package/src/launch/term-session-key.ts +70 -0
- package/src/observable-abort-signal.ts +66 -0
- package/src/open-external.ts +22 -0
- package/src/paths.ts +20 -0
- package/src/text/agent-cover.ts +136 -0
- package/src/text/format-shell.ts +52 -0
- package/src/text/identity.ts +473 -0
- package/src/text/index.ts +29 -0
- package/src/text/liveness.ts +322 -0
- package/src/text/mcp-identity.ts +148 -0
- package/src/text/pretty-identity.ts +120 -0
- package/src/text/sugarcoat.ts +165 -0
- package/src/text/unwrap-program.ts +133 -0
- package/src/text/work-text.ts +388 -0
- package/src/transport/unix.ts +84 -0
- package/README.md +0 -3
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client projection of a worker session. Interned by `sessionId`.
|
|
3
|
+
* Reads the session overview + this tape + the three bots rosters. Does not intern the
|
|
4
|
+
* worker document.
|
|
5
|
+
*/
|
|
6
|
+
import { recordString } from "@inhuman.tools/harness-model/json-record";
|
|
7
|
+
import type { SessionOverview } from "@inhuman.tools/harness-model/kernel";
|
|
8
|
+
import { AgentCallJob, BotCallJob, CallJob } from "@inhuman.tools/harness-model/session";
|
|
9
|
+
import { computed } from "mobx";
|
|
10
|
+
|
|
11
|
+
import type { Client } from "./client.js";
|
|
12
|
+
|
|
13
|
+
export type AgentScope = "one-shot" | "session" | "project" | "global";
|
|
14
|
+
export type AgentRosterScope = Exclude<AgentScope, "one-shot">;
|
|
15
|
+
/** Process. Failed is not this field — a sealed Call fail is `ourRequest`. */
|
|
16
|
+
export type AgentProcessState = "working" | "done";
|
|
17
|
+
/** Interaction. Needs-you is `blocked`, not `working`. */
|
|
18
|
+
export type AgentTempo = "active" | "idle" | "blocked";
|
|
19
|
+
/** This tape's Call to this worker. Cancel is not fail. */
|
|
20
|
+
export type AgentRequestState = "none" | "open" | "ok" | "fail" | "cancelled";
|
|
21
|
+
|
|
22
|
+
export type AgentRosterRow = {
|
|
23
|
+
readonly scope: AgentRosterScope;
|
|
24
|
+
readonly name: string;
|
|
25
|
+
readonly sessionId: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export class ClientAgent {
|
|
29
|
+
constructor(
|
|
30
|
+
readonly client: Client,
|
|
31
|
+
readonly sessionId: string,
|
|
32
|
+
) {}
|
|
33
|
+
|
|
34
|
+
@computed
|
|
35
|
+
get overview(): SessionOverview | null {
|
|
36
|
+
return this.client.kernelRoot.sessions[this.sessionId] ?? null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@computed
|
|
40
|
+
get names(): readonly string[] {
|
|
41
|
+
const names: string[] = [];
|
|
42
|
+
for (const row of this.client.botsRoster) {
|
|
43
|
+
if (row.sessionId === this.sessionId) names.push(row.name);
|
|
44
|
+
}
|
|
45
|
+
return names;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@computed
|
|
49
|
+
get scope(): AgentScope {
|
|
50
|
+
let session = false;
|
|
51
|
+
let project = false;
|
|
52
|
+
let global = false;
|
|
53
|
+
for (const row of this.client.botsRoster) {
|
|
54
|
+
if (row.sessionId !== this.sessionId) continue;
|
|
55
|
+
if (row.scope === "global") global = true;
|
|
56
|
+
else if (row.scope === "project") project = true;
|
|
57
|
+
else session = true;
|
|
58
|
+
}
|
|
59
|
+
if (global) return "global";
|
|
60
|
+
if (project) return "project";
|
|
61
|
+
if (session) return "session";
|
|
62
|
+
return "one-shot";
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@computed
|
|
66
|
+
get oneShot(): boolean {
|
|
67
|
+
const glance = this.overview;
|
|
68
|
+
if (glance != null) return glance.oneShot;
|
|
69
|
+
const call = this.openCall ?? this.lastCall;
|
|
70
|
+
if (call != null) return call instanceof AgentCallJob;
|
|
71
|
+
return this.scope === "one-shot";
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
@computed
|
|
75
|
+
get specName(): string {
|
|
76
|
+
const fromGlance = this.overview?.specName.trim() ?? "";
|
|
77
|
+
if (fromGlance !== "") return fromGlance;
|
|
78
|
+
const named = this.names[0]?.trim() ?? "";
|
|
79
|
+
if (named !== "") return named;
|
|
80
|
+
const call = this.openCall ?? this.lastCall;
|
|
81
|
+
if (call == null) return "";
|
|
82
|
+
const spec = recordString(call.args, "spec");
|
|
83
|
+
return spec === "" && call instanceof BotCallJob ? call.botName.trim() || call.contributionBotName.trim() : spec;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
@computed
|
|
87
|
+
get title(): string {
|
|
88
|
+
const title = this.overview?.title.trim() ?? "";
|
|
89
|
+
return title === "" ? this.specName : title;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
@computed
|
|
93
|
+
get nature(): string {
|
|
94
|
+
const nature = this.overview?.recipeScope ?? "";
|
|
95
|
+
if (nature !== "") return nature;
|
|
96
|
+
const scope = this.scope;
|
|
97
|
+
return scope === "one-shot" ? "" : scope;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
@computed
|
|
101
|
+
get keepAlive(): boolean {
|
|
102
|
+
return this.overview?.keepAlive === true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
@computed
|
|
106
|
+
get model(): string {
|
|
107
|
+
return this.overview?.model.trim() ?? "";
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@computed
|
|
111
|
+
get status(): string {
|
|
112
|
+
return this.overview?.status.trim() ?? "";
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@computed
|
|
116
|
+
get lastMessageAt(): number {
|
|
117
|
+
return this.overview?.lastMessageAt ?? 0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
@computed
|
|
121
|
+
get calls(): readonly CallJob[] {
|
|
122
|
+
const id = this.sessionId;
|
|
123
|
+
return this.client.agentCalls.filter((call) => call.workerSessionId === id);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
@computed
|
|
127
|
+
get openCall(): CallJob | null {
|
|
128
|
+
let found: CallJob | null = null;
|
|
129
|
+
for (const call of this.calls) {
|
|
130
|
+
if (!call.completed) found = call;
|
|
131
|
+
}
|
|
132
|
+
return found;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@computed
|
|
136
|
+
get lastCall(): CallJob | null {
|
|
137
|
+
return this.calls.at(-1) ?? null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@computed
|
|
141
|
+
get interacted(): boolean {
|
|
142
|
+
return this.calls.length > 0;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
@computed
|
|
146
|
+
get ourRequest(): AgentRequestState {
|
|
147
|
+
const open = this.openCall;
|
|
148
|
+
if (open != null) return "open";
|
|
149
|
+
const last = this.lastCall;
|
|
150
|
+
if (last == null) return "none";
|
|
151
|
+
if (last.cancelled) return "cancelled";
|
|
152
|
+
const snap = last.outcomeSnap;
|
|
153
|
+
if (snap?.ok === false) return "fail";
|
|
154
|
+
return "ok";
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@computed
|
|
158
|
+
get midMotion(): boolean {
|
|
159
|
+
return this.overview?.midMotion === true;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@computed
|
|
163
|
+
get openTurn(): boolean {
|
|
164
|
+
return this.overview?.openTurn === true;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
@computed
|
|
168
|
+
get openToolCount(): number {
|
|
169
|
+
return this.overview?.openToolCount ?? 0;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@computed
|
|
173
|
+
get openCallbackCount(): number {
|
|
174
|
+
return this.overview?.openCallbackCount ?? 0;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
@computed
|
|
178
|
+
get asking(): boolean {
|
|
179
|
+
return this.overview?.asking === true;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@computed
|
|
183
|
+
get state(): AgentProcessState {
|
|
184
|
+
if (
|
|
185
|
+
this.asking ||
|
|
186
|
+
this.midMotion ||
|
|
187
|
+
this.openTurn ||
|
|
188
|
+
this.openToolCount > 0 ||
|
|
189
|
+
this.openCallbackCount > 0 ||
|
|
190
|
+
this.openCall != null
|
|
191
|
+
)
|
|
192
|
+
return "working";
|
|
193
|
+
return "done";
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
@computed
|
|
197
|
+
get tempo(): AgentTempo {
|
|
198
|
+
if (this.asking) return "blocked";
|
|
199
|
+
if (
|
|
200
|
+
this.midMotion ||
|
|
201
|
+
this.openTurn ||
|
|
202
|
+
this.openToolCount > 0 ||
|
|
203
|
+
this.openCallbackCount > 0 ||
|
|
204
|
+
this.openCall != null
|
|
205
|
+
)
|
|
206
|
+
return "active";
|
|
207
|
+
return "idle";
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* One-shot and session-scope workers raise the host cover.
|
|
213
|
+
* Project/global confirm elsewhere. Host's own queue head wins.
|
|
214
|
+
*/
|
|
215
|
+
export function hostAskEscalateSessionId(client: Client): string | null {
|
|
216
|
+
if (client.sessionRoot.findRunningTurn()?.approvalHead != null) return null;
|
|
217
|
+
for (const agent of client.agents) {
|
|
218
|
+
if (!escalatesAskToHost(agent)) continue;
|
|
219
|
+
if (!agent.asking && agent.overview?.unfinished !== "ask") continue;
|
|
220
|
+
return agent.sessionId;
|
|
221
|
+
}
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function escalatesAskToHost(agent: ClientAgent): boolean {
|
|
226
|
+
if (agent.sessionId === "" || agent.sessionId === agent.client.sessionId) return false;
|
|
227
|
+
if (agent.scope === "project" || agent.scope === "global") return false;
|
|
228
|
+
if (agent.nature === "project" || agent.nature === "global") return false;
|
|
229
|
+
return agent.oneShot || agent.scope === "session" || agent.nature === "session";
|
|
230
|
+
}
|