@getpaseo/server 0.10.1 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server/server/agent/providers/opencode/tool-call-detail-parser.js +16 -6
- package/dist/server/server/agent/providers/opencode/v2/api.d.ts +1 -1
- package/dist/server/server/agent/providers/opencode/v2/permissions.js +3 -2
- package/dist/server/server/agent/providers/opencode/v2/session.d.ts +2 -1
- package/dist/server/server/agent/providers/opencode/v2/session.js +13 -8
- package/dist/server/server/agent/providers/opencode/v2/turns.d.ts +20 -5
- package/dist/server/server/agent/providers/opencode/v2/turns.js +168 -72
- package/dist/server/server/agent/providers/opencode/v2/usage.d.ts +21 -0
- package/dist/server/server/agent/providers/opencode/v2/usage.js +48 -0
- package/dist/server/web-ui/_expo/static/js/web/{index-cefb3a051a5e61705f20366980a641f6.js → index-48b52108bb348a6334547c3c03400d50.js} +1 -1
- package/dist/server/web-ui/_expo/static/js/web/index-48b52108bb348a6334547c3c03400d50.js.br +0 -0
- package/dist/server/web-ui/_expo/static/js/web/{index-cefb3a051a5e61705f20366980a641f6.js.gz → index-48b52108bb348a6334547c3c03400d50.js.gz} +0 -0
- package/dist/server/web-ui/index.html +1 -1
- package/dist/server/web-ui/index.html.br +0 -0
- package/dist/server/web-ui/index.html.gz +0 -0
- package/package.json +6 -6
- package/dist/server/web-ui/_expo/static/js/web/index-cefb3a051a5e61705f20366980a641f6.js.br +0 -0
|
@@ -164,6 +164,14 @@ function deriveOpencodeTaskDetail(input, output, error, metadata) {
|
|
|
164
164
|
actions: [],
|
|
165
165
|
};
|
|
166
166
|
}
|
|
167
|
+
function toOpencodeEditInput(value) {
|
|
168
|
+
return {
|
|
169
|
+
filePath: value.filePath,
|
|
170
|
+
oldString: nonEmptyString(value.oldString),
|
|
171
|
+
newString: nonEmptyString(value.newString),
|
|
172
|
+
unifiedDiff: undefined,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
167
175
|
const OpencodeEditInputSchema = z.union([
|
|
168
176
|
z
|
|
169
177
|
.object({
|
|
@@ -172,12 +180,12 @@ const OpencodeEditInputSchema = z.union([
|
|
|
172
180
|
newString: z.string().optional(),
|
|
173
181
|
})
|
|
174
182
|
.passthrough()
|
|
175
|
-
.transform(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
183
|
+
.transform(toOpencodeEditInput),
|
|
184
|
+
// OpenCode v2's edit tool names the file `path`.
|
|
185
|
+
z
|
|
186
|
+
.object({ path: z.string(), oldString: z.string(), newString: z.string() })
|
|
187
|
+
.passthrough()
|
|
188
|
+
.transform((value) => toOpencodeEditInput({ ...value, filePath: value.path })),
|
|
181
189
|
ToolEditInputSchema,
|
|
182
190
|
]);
|
|
183
191
|
const OpencodeEditOutputSchema = z.union([z.string().transform(() => null), ToolEditOutputSchema]);
|
|
@@ -199,6 +207,8 @@ const OpencodeKnownToolDetailSchema = z.union([
|
|
|
199
207
|
toolDetailBranchByToolName("edit", OpencodeEditInputSchema, OpencodeEditOutputSchema, toEditToolDetail),
|
|
200
208
|
toolDetailBranchByToolName("apply_patch", OpencodeEditInputSchema, OpencodeEditOutputSchema, toEditToolDetail),
|
|
201
209
|
toolDetailBranchByToolName("apply_patch", OpencodeApplyPatchTextInputSchema, z.unknown(), (input) => toEditToolDetail(input, null)),
|
|
210
|
+
// OpenCode v2 reports apply_patch as `patch`.
|
|
211
|
+
toolDetailBranchByToolName("patch", OpencodeApplyPatchTextInputSchema, z.unknown(), (input) => toEditToolDetail(input, null)),
|
|
202
212
|
toolDetailBranchByToolName("apply_diff", OpencodeEditInputSchema, OpencodeEditOutputSchema, toEditToolDetail),
|
|
203
213
|
toolDetailBranchByToolName("search", ToolSearchInputSchema, z.unknown(), (input) => toSearchToolDetail({ input, toolName: "search" })),
|
|
204
214
|
toolDetailBranchByToolName("grep", ToolSearchInputSchema, OpencodeGrepOutputSchema, (input, output) => toSearchToolDetail({ input, output, toolName: "grep" })),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { OpenCodeClient } from "@opencode/client";
|
|
2
2
|
export interface V2Api {
|
|
3
3
|
server: OpenCodeClient["server"];
|
|
4
|
-
session: Pick<OpenCodeClient["session"], "create" | "get" | "list" | "active" | "remove" | "switchAgent" | "switchModel" | "environment" | "instructions" | "prompt" | "command" | "compact" | "
|
|
4
|
+
session: Pick<OpenCodeClient["session"], "create" | "get" | "list" | "active" | "remove" | "switchAgent" | "switchModel" | "environment" | "instructions" | "prompt" | "command" | "compact" | "interrupt" | "revert" | "log"> & {
|
|
5
5
|
form: Pick<OpenCodeClient["session"]["form"], "list" | "reply" | "cancel">;
|
|
6
6
|
};
|
|
7
7
|
plugin: Pick<OpenCodeClient["plugin"], "list">;
|
|
@@ -94,10 +94,11 @@ export class SessionPermissions {
|
|
|
94
94
|
title: form.title,
|
|
95
95
|
input: {
|
|
96
96
|
questions: form.fields.map((field) => ({
|
|
97
|
-
header: field.key,
|
|
98
|
-
question: field.title ?? field.key,
|
|
97
|
+
header: field.title ?? field.key,
|
|
98
|
+
question: field.description ?? field.title ?? field.key,
|
|
99
99
|
options: "options" in field ? field.options : undefined,
|
|
100
100
|
multiple: field.type === "multiselect",
|
|
101
|
+
allowOther: "custom" in field && field.custom === true,
|
|
101
102
|
})),
|
|
102
103
|
},
|
|
103
104
|
};
|
|
@@ -20,6 +20,7 @@ export declare class OpenCodeV2Session implements AgentSession {
|
|
|
20
20
|
private readonly permissions;
|
|
21
21
|
private readonly turns;
|
|
22
22
|
private readonly children;
|
|
23
|
+
private readonly usage;
|
|
23
24
|
private stream;
|
|
24
25
|
private streamAbort;
|
|
25
26
|
private exited;
|
|
@@ -63,7 +64,7 @@ export declare class OpenCodeV2Session implements AgentSession {
|
|
|
63
64
|
describePersistence(): AgentPersistenceHandle;
|
|
64
65
|
run(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<import("../../../agent-sdk-types.js").AgentRunResult>;
|
|
65
66
|
startTurn(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<{
|
|
66
|
-
turnId:
|
|
67
|
+
turnId: string;
|
|
67
68
|
}>;
|
|
68
69
|
steerActiveTurn(prompt: AgentPromptInput, options: SteerActiveTurnOptions): Promise<SteerResult>;
|
|
69
70
|
interrupt(): Promise<void>;
|
|
@@ -13,6 +13,7 @@ import { features } from "./configuration.js";
|
|
|
13
13
|
import { commands } from "./commands.js";
|
|
14
14
|
import { messages } from "./history.js";
|
|
15
15
|
import { SessionPermissions } from "./permissions.js";
|
|
16
|
+
import { SessionUsage } from "./usage.js";
|
|
16
17
|
export class OpenCodeV2Session {
|
|
17
18
|
constructor(connection, info, config, logger, persist, requiresPaseoPlugin, unbind, bindChild, acquire, moved) {
|
|
18
19
|
this.connection = connection;
|
|
@@ -57,11 +58,19 @@ export class OpenCodeV2Session {
|
|
|
57
58
|
await this.reconcile();
|
|
58
59
|
return { info: this.info, history: this.history };
|
|
59
60
|
},
|
|
61
|
+
reportReconciliationError: (error) => this.logger.warn({ error: toDiagnosticErrorMessage(error) }, "OpenCode turn reconciliation failed; retrying"),
|
|
60
62
|
clearPermissions: async () => {
|
|
61
63
|
for (const request of this.permissions.list())
|
|
62
64
|
await this.permissions.respondToPermission(request.id, { behavior: "deny" });
|
|
63
65
|
},
|
|
64
66
|
});
|
|
67
|
+
this.usage = new SessionUsage({
|
|
68
|
+
client: () => this.client,
|
|
69
|
+
cwd: config.cwd,
|
|
70
|
+
info: () => this.info,
|
|
71
|
+
emit: (event) => this.emit(event),
|
|
72
|
+
reportError: (error) => this.logger.warn({ error: toDiagnosticErrorMessage(error) }, "OpenCode context usage update failed"),
|
|
73
|
+
});
|
|
65
74
|
}
|
|
66
75
|
get id() {
|
|
67
76
|
return this.info.id;
|
|
@@ -377,9 +386,7 @@ export class OpenCodeV2Session {
|
|
|
377
386
|
await this.client.session.environment({ sessionID: this.id, variables: this.launchEnv });
|
|
378
387
|
await this.reconcile();
|
|
379
388
|
await this.children.reconcile(this.id);
|
|
380
|
-
|
|
381
|
-
if (active[this.id])
|
|
382
|
-
this.turns.observeActiveTurn();
|
|
389
|
+
await this.turns.reconcile();
|
|
383
390
|
}
|
|
384
391
|
scheduleReconcile() {
|
|
385
392
|
if (this.refreshTimer || this.closed)
|
|
@@ -422,12 +429,9 @@ export class OpenCodeV2Session {
|
|
|
422
429
|
return;
|
|
423
430
|
}
|
|
424
431
|
this.permissions.observe(event);
|
|
425
|
-
|
|
426
|
-
|
|
432
|
+
this.usage.observe(event);
|
|
433
|
+
this.turns.observe(event);
|
|
427
434
|
this.scheduleReconcile();
|
|
428
|
-
if (event.type !== "session.execution.started" || this.turns.id)
|
|
429
|
-
return;
|
|
430
|
-
this.turns.observeActiveTurn();
|
|
431
435
|
}
|
|
432
436
|
async consume(ready, fail) {
|
|
433
437
|
const signal = AbortSignal.any([this.abort.signal, this.streamAbort.signal]);
|
|
@@ -466,6 +470,7 @@ export class OpenCodeV2Session {
|
|
|
466
470
|
return;
|
|
467
471
|
this.closed = true;
|
|
468
472
|
this.abort.abort();
|
|
473
|
+
this.turns.close();
|
|
469
474
|
this.streamAbort.abort();
|
|
470
475
|
if (this.refreshTimer)
|
|
471
476
|
clearTimeout(this.refreshTimer);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SessionInfo, SessionMessageInfo } from "@opencode/client";
|
|
1
|
+
import type { OpenCodeEvent, SessionInfo, SessionMessageInfo } from "@opencode/client";
|
|
2
2
|
import type { AgentPromptInput, AgentRunOptions, AgentStreamEvent, SteerActiveTurnOptions, SteerResult } from "../../../agent-sdk-types.js";
|
|
3
3
|
import type { V2Api } from "./api.js";
|
|
4
4
|
interface TurnSnapshot {
|
|
@@ -13,28 +13,43 @@ interface TurnOptions {
|
|
|
13
13
|
emit(event: AgentStreamEvent): void;
|
|
14
14
|
reconcile(): Promise<TurnSnapshot>;
|
|
15
15
|
clearPermissions(): Promise<void>;
|
|
16
|
+
reportReconciliationError(error: unknown): void;
|
|
16
17
|
}
|
|
17
18
|
export declare class SessionTurns {
|
|
18
19
|
private readonly options;
|
|
19
20
|
private turn;
|
|
20
21
|
private stopping;
|
|
21
22
|
private stopFailed;
|
|
22
|
-
|
|
23
|
+
private revision;
|
|
24
|
+
private execution;
|
|
25
|
+
private sequence;
|
|
26
|
+
private refresh;
|
|
27
|
+
private dirty;
|
|
28
|
+
private retryTimer;
|
|
23
29
|
constructor(options: TurnOptions);
|
|
24
30
|
get id(): string | undefined;
|
|
25
31
|
get hasStructuredOutput(): boolean;
|
|
26
32
|
fail(error: Error): void;
|
|
33
|
+
private release;
|
|
34
|
+
close(): void;
|
|
35
|
+
private createTurn;
|
|
27
36
|
startTurn(prompt: AgentPromptInput, options?: AgentRunOptions): Promise<{
|
|
28
|
-
turnId:
|
|
37
|
+
turnId: string;
|
|
29
38
|
}>;
|
|
30
39
|
private submit;
|
|
40
|
+
observe(event: OpenCodeEvent): void;
|
|
41
|
+
private requestReconciliation;
|
|
42
|
+
private scheduleRecovery;
|
|
43
|
+
reconcile(): Promise<void>;
|
|
44
|
+
private drainReconciliation;
|
|
45
|
+
private reconcileTurn;
|
|
31
46
|
private dispatch;
|
|
32
47
|
private finish;
|
|
33
|
-
private
|
|
48
|
+
private readExecution;
|
|
34
49
|
private promptInput;
|
|
35
50
|
steerActiveTurn(prompt: AgentPromptInput, options: SteerActiveTurnOptions): Promise<SteerResult>;
|
|
36
51
|
interrupt(): Promise<void>;
|
|
37
|
-
observeActiveTurn
|
|
52
|
+
private observeActiveTurn;
|
|
38
53
|
}
|
|
39
54
|
export {};
|
|
40
55
|
//# sourceMappingURL=turns.d.ts.map
|
|
@@ -4,13 +4,24 @@ import { toDiagnosticErrorMessage } from "../../diagnostic-utils.js";
|
|
|
4
4
|
import { renderPromptAttachmentAsText } from "../../../prompt-attachments.js";
|
|
5
5
|
import { usageFromV2 } from "./mapping.js";
|
|
6
6
|
import { commands } from "./commands.js";
|
|
7
|
+
function isExecutionEvent(event) {
|
|
8
|
+
return (event.type === "session.execution.started" ||
|
|
9
|
+
event.type === "session.execution.succeeded" ||
|
|
10
|
+
event.type === "session.execution.failed" ||
|
|
11
|
+
event.type === "session.execution.interrupted");
|
|
12
|
+
}
|
|
7
13
|
export class SessionTurns {
|
|
8
14
|
constructor(options) {
|
|
9
15
|
this.options = options;
|
|
10
16
|
this.turn = null;
|
|
11
17
|
this.stopping = null;
|
|
12
18
|
this.stopFailed = false;
|
|
13
|
-
this.
|
|
19
|
+
this.revision = 0;
|
|
20
|
+
this.execution = null;
|
|
21
|
+
this.sequence = 0;
|
|
22
|
+
this.refresh = null;
|
|
23
|
+
this.dirty = false;
|
|
24
|
+
this.retryTimer = null;
|
|
14
25
|
}
|
|
15
26
|
get id() {
|
|
16
27
|
return this.turn?.id;
|
|
@@ -20,14 +31,47 @@ export class SessionTurns {
|
|
|
20
31
|
}
|
|
21
32
|
fail(error) {
|
|
22
33
|
const turn = this.turn;
|
|
34
|
+
if (!turn)
|
|
35
|
+
return;
|
|
36
|
+
this.release(turn);
|
|
37
|
+
this.options.emit({
|
|
38
|
+
type: "turn_failed",
|
|
39
|
+
provider: "opencode",
|
|
40
|
+
turnId: turn.id,
|
|
41
|
+
error: toDiagnosticErrorMessage(error),
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
release(turn) {
|
|
23
45
|
this.turn = null;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
46
|
+
this.revision += 1;
|
|
47
|
+
if (this.retryTimer)
|
|
48
|
+
clearTimeout(this.retryTimer);
|
|
49
|
+
this.retryTimer = null;
|
|
50
|
+
turn.settle();
|
|
51
|
+
}
|
|
52
|
+
close() {
|
|
53
|
+
if (this.turn)
|
|
54
|
+
this.release(this.turn);
|
|
55
|
+
}
|
|
56
|
+
createTurn(submitted, accepted, output) {
|
|
57
|
+
let settle;
|
|
58
|
+
const completion = new Promise((resolve) => {
|
|
59
|
+
settle = resolve;
|
|
60
|
+
});
|
|
61
|
+
const turn = {
|
|
62
|
+
id: randomUUID(),
|
|
63
|
+
submitted,
|
|
64
|
+
completion,
|
|
65
|
+
settle,
|
|
66
|
+
accepted,
|
|
67
|
+
output,
|
|
68
|
+
};
|
|
69
|
+
this.turn = turn;
|
|
70
|
+
this.execution = null;
|
|
71
|
+
this.revision += 1;
|
|
72
|
+
this.options.emit({ type: "turn_started", provider: "opencode", turnId: turn.id });
|
|
73
|
+
this.scheduleRecovery();
|
|
74
|
+
return turn;
|
|
31
75
|
}
|
|
32
76
|
async startTurn(prompt, options) {
|
|
33
77
|
await this.stopping;
|
|
@@ -35,42 +79,117 @@ export class SessionTurns {
|
|
|
35
79
|
throw new Error("OpenCode session is closed");
|
|
36
80
|
if (this.turn)
|
|
37
81
|
throw new Error("OpenCode session already has an active turn");
|
|
38
|
-
this.executionError = null;
|
|
39
|
-
const id = randomUUID();
|
|
40
82
|
const input = this.promptInput(prompt);
|
|
41
83
|
let accept;
|
|
42
84
|
const submitted = new Promise((resolve) => {
|
|
43
85
|
accept = resolve;
|
|
44
86
|
});
|
|
45
87
|
const output = options?.outputSchema === undefined ? undefined : structuredOutput(options.outputSchema);
|
|
46
|
-
const
|
|
47
|
-
this.turn
|
|
48
|
-
return { turnId: id };
|
|
49
|
-
}
|
|
50
|
-
async submit(
|
|
51
|
-
// Defer until startTurn publishes ownership, including for immediately resolved test transports.
|
|
52
|
-
await Promise.resolve();
|
|
53
|
-
this.options.emit({ type: "turn_started", provider: "opencode", turnId: id });
|
|
88
|
+
const turn = this.createTurn(submitted, false, output);
|
|
89
|
+
void this.submit(turn, input, accept, options);
|
|
90
|
+
return { turnId: turn.id };
|
|
91
|
+
}
|
|
92
|
+
async submit(turn, input, accept, options) {
|
|
54
93
|
try {
|
|
55
|
-
await this.dispatch(input, options, output);
|
|
56
|
-
|
|
57
|
-
|
|
94
|
+
await this.dispatch(input, options, turn.output);
|
|
95
|
+
if (this.turn !== turn)
|
|
96
|
+
return;
|
|
97
|
+
turn.accepted = true;
|
|
98
|
+
this.revision += 1;
|
|
99
|
+
// Covers a fast execution whose terminal event preceded the admission response.
|
|
100
|
+
this.requestReconciliation();
|
|
58
101
|
}
|
|
59
102
|
catch (error) {
|
|
60
|
-
if (this.turn
|
|
61
|
-
this.
|
|
62
|
-
this.options.emit({
|
|
63
|
-
type: "turn_failed",
|
|
64
|
-
provider: "opencode",
|
|
65
|
-
turnId: id,
|
|
66
|
-
error: toDiagnosticErrorMessage(error),
|
|
67
|
-
});
|
|
68
|
-
}
|
|
103
|
+
if (this.turn === turn)
|
|
104
|
+
this.fail(new Error(toDiagnosticErrorMessage(error)));
|
|
69
105
|
}
|
|
70
106
|
finally {
|
|
71
107
|
accept();
|
|
72
108
|
}
|
|
73
109
|
}
|
|
110
|
+
observe(event) {
|
|
111
|
+
if (!isExecutionEvent(event) || event.durable.seq <= this.sequence)
|
|
112
|
+
return;
|
|
113
|
+
this.revision += 1;
|
|
114
|
+
if (event.type === "session.execution.started")
|
|
115
|
+
this.observeActiveTurn();
|
|
116
|
+
this.execution = event;
|
|
117
|
+
this.sequence = event.durable.seq;
|
|
118
|
+
this.requestReconciliation();
|
|
119
|
+
}
|
|
120
|
+
requestReconciliation() {
|
|
121
|
+
void this.reconcile().catch((error) => this.options.reportReconciliationError(error));
|
|
122
|
+
}
|
|
123
|
+
// Recovery reads state; a quiet stream (including SSE comment heartbeats) is not a reason to reconnect.
|
|
124
|
+
scheduleRecovery() {
|
|
125
|
+
if (this.retryTimer || !this.turn || this.options.signal.aborted)
|
|
126
|
+
return;
|
|
127
|
+
this.retryTimer = setTimeout(() => {
|
|
128
|
+
this.retryTimer = null;
|
|
129
|
+
this.requestReconciliation();
|
|
130
|
+
}, 5000);
|
|
131
|
+
this.retryTimer.unref();
|
|
132
|
+
}
|
|
133
|
+
reconcile() {
|
|
134
|
+
this.dirty = true;
|
|
135
|
+
if (this.refresh)
|
|
136
|
+
return this.refresh;
|
|
137
|
+
this.refresh = Promise.resolve()
|
|
138
|
+
.then(() => this.drainReconciliation())
|
|
139
|
+
.finally(() => {
|
|
140
|
+
this.refresh = null;
|
|
141
|
+
this.scheduleRecovery();
|
|
142
|
+
});
|
|
143
|
+
return this.refresh;
|
|
144
|
+
}
|
|
145
|
+
async drainReconciliation() {
|
|
146
|
+
while (this.dirty && !this.options.signal.aborted) {
|
|
147
|
+
this.dirty = false;
|
|
148
|
+
await this.reconcileTurn();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
async reconcileTurn() {
|
|
152
|
+
const revision = this.revision;
|
|
153
|
+
const turn = this.turn;
|
|
154
|
+
const active = await this.options.client().session.active({ signal: this.options.signal });
|
|
155
|
+
if (revision !== this.revision) {
|
|
156
|
+
this.dirty = true;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
if (active[this.options.id]) {
|
|
160
|
+
this.observeActiveTurn();
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (!turn?.accepted)
|
|
164
|
+
return;
|
|
165
|
+
// Idle outcome survives shutdown, and /event has no replay. Recover the latest
|
|
166
|
+
// durable execution even when its start or terminal was lost across reconnect.
|
|
167
|
+
const execution = await this.readExecution();
|
|
168
|
+
if (revision !== this.revision) {
|
|
169
|
+
this.dirty = true;
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
if (!execution)
|
|
173
|
+
return;
|
|
174
|
+
this.execution = execution;
|
|
175
|
+
this.sequence = execution.durable.seq;
|
|
176
|
+
if (execution.type === "session.execution.started" ||
|
|
177
|
+
(execution.type === "session.execution.interrupted" && execution.data.reason === "shutdown"))
|
|
178
|
+
return;
|
|
179
|
+
// Read the final history only after observing idle. Never turn an observation transport error into an execution failure.
|
|
180
|
+
const snapshot = await this.options.reconcile();
|
|
181
|
+
if (revision !== this.revision) {
|
|
182
|
+
this.dirty = true;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
this.finish(turn, snapshot, execution);
|
|
187
|
+
}
|
|
188
|
+
catch (error) {
|
|
189
|
+
if (this.turn === turn)
|
|
190
|
+
this.fail(new Error(toDiagnosticErrorMessage(error)));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
74
193
|
async dispatch(input, options, output) {
|
|
75
194
|
const command = input.text.match(/^\/([^\s]+)(?:\s+([\s\S]*))?$/);
|
|
76
195
|
if (command?.[1] === "compact" || command?.[1] === "summarize") {
|
|
@@ -104,50 +223,41 @@ export class SessionTurns {
|
|
|
104
223
|
},
|
|
105
224
|
});
|
|
106
225
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (this.turn?.id !== id)
|
|
113
|
-
return;
|
|
114
|
-
if (info.outcome !== "failed" && info.outcome !== "interrupted")
|
|
115
|
-
this.turn.output?.assert(history);
|
|
116
|
-
const failure = info.outcome === "failed" ? (this.executionError ?? (await this.readExecutionError())) : null;
|
|
117
|
-
if (this.turn?.id !== id)
|
|
118
|
-
return;
|
|
119
|
-
this.turn = null;
|
|
120
|
-
if (info.outcome === "interrupted")
|
|
226
|
+
finish(turn, { info, history }, execution) {
|
|
227
|
+
if (execution.type === "session.execution.succeeded")
|
|
228
|
+
turn.output?.assert(history);
|
|
229
|
+
this.release(turn);
|
|
230
|
+
if (execution.type === "session.execution.interrupted")
|
|
121
231
|
this.options.emit({
|
|
122
232
|
type: "turn_canceled",
|
|
123
233
|
provider: "opencode",
|
|
124
|
-
turnId: id,
|
|
234
|
+
turnId: turn.id,
|
|
125
235
|
reason: "OpenCode interrupted execution",
|
|
126
236
|
});
|
|
127
|
-
else if (
|
|
237
|
+
else if (execution.type === "session.execution.failed")
|
|
128
238
|
this.options.emit({
|
|
129
239
|
type: "turn_failed",
|
|
130
240
|
provider: "opencode",
|
|
131
|
-
turnId: id,
|
|
132
|
-
error:
|
|
241
|
+
turnId: turn.id,
|
|
242
|
+
error: execution.data.error.message,
|
|
133
243
|
});
|
|
134
244
|
else
|
|
135
245
|
this.options.emit({
|
|
136
246
|
type: "turn_completed",
|
|
137
247
|
provider: "opencode",
|
|
138
|
-
turnId: id,
|
|
248
|
+
turnId: turn.id,
|
|
139
249
|
usage: usageFromV2(info),
|
|
140
250
|
});
|
|
141
251
|
}
|
|
142
|
-
async
|
|
143
|
-
let
|
|
252
|
+
async readExecution() {
|
|
253
|
+
let execution = this.execution;
|
|
144
254
|
for await (const event of this.options
|
|
145
255
|
.client()
|
|
146
|
-
.session.log({ sessionID: this.options.id, follow: false }, { signal: this.options.signal })) {
|
|
147
|
-
if (event.
|
|
148
|
-
|
|
256
|
+
.session.log({ sessionID: this.options.id, follow: false, after: this.sequence }, { signal: this.options.signal })) {
|
|
257
|
+
if (isExecutionEvent(event) && event.durable.seq > (execution?.durable.seq ?? this.sequence))
|
|
258
|
+
execution = event;
|
|
149
259
|
}
|
|
150
|
-
return
|
|
260
|
+
return execution;
|
|
151
261
|
}
|
|
152
262
|
promptInput(prompt) {
|
|
153
263
|
if (typeof prompt === "string")
|
|
@@ -187,6 +297,7 @@ export class SessionTurns {
|
|
|
187
297
|
// A stop sent before the queued prompt is accepted would interrupt an idle session.
|
|
188
298
|
await turn?.submitted;
|
|
189
299
|
await this.options.client().session.interrupt({ sessionID: this.options.id });
|
|
300
|
+
await this.reconcile();
|
|
190
301
|
await turn?.completion;
|
|
191
302
|
})();
|
|
192
303
|
this.stopping = stop;
|
|
@@ -203,24 +314,9 @@ export class SessionTurns {
|
|
|
203
314
|
await this.stopping;
|
|
204
315
|
}
|
|
205
316
|
observeActiveTurn() {
|
|
206
|
-
if (this.turn)
|
|
317
|
+
if (this.turn || this.options.signal.aborted)
|
|
207
318
|
return;
|
|
208
|
-
|
|
209
|
-
const completion = Promise.resolve()
|
|
210
|
-
.then(() => this.finish(id))
|
|
211
|
-
.catch((error) => {
|
|
212
|
-
if (this.turn?.id !== id)
|
|
213
|
-
return;
|
|
214
|
-
this.turn = null;
|
|
215
|
-
this.options.emit({
|
|
216
|
-
type: "turn_failed",
|
|
217
|
-
provider: "opencode",
|
|
218
|
-
turnId: id,
|
|
219
|
-
error: toDiagnosticErrorMessage(error),
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
this.turn = { id, submitted: Promise.resolve(), completion };
|
|
223
|
-
this.options.emit({ type: "turn_started", provider: "opencode", turnId: id });
|
|
319
|
+
this.createTurn(Promise.resolve(), true);
|
|
224
320
|
}
|
|
225
321
|
}
|
|
226
322
|
//# sourceMappingURL=turns.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { OpenCodeEvent, SessionInfo } from "@opencode/client";
|
|
2
|
+
import type { AgentStreamEvent } from "../../../agent-sdk-types.js";
|
|
3
|
+
import type { V2Api } from "./api.js";
|
|
4
|
+
interface UsageOptions {
|
|
5
|
+
client(): V2Api;
|
|
6
|
+
cwd: string;
|
|
7
|
+
info(): SessionInfo;
|
|
8
|
+
emit(event: AgentStreamEvent): void;
|
|
9
|
+
reportError(error: unknown): void;
|
|
10
|
+
}
|
|
11
|
+
export declare class SessionUsage {
|
|
12
|
+
private readonly options;
|
|
13
|
+
private readonly limits;
|
|
14
|
+
private reports;
|
|
15
|
+
constructor(options: UsageOptions);
|
|
16
|
+
observe(event: OpenCodeEvent): void;
|
|
17
|
+
private report;
|
|
18
|
+
private contextLimit;
|
|
19
|
+
}
|
|
20
|
+
export {};
|
|
21
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { usageFromV2 } from "./mapping.js";
|
|
2
|
+
// A step is one model call, so its tokens are the context that call used.
|
|
3
|
+
function contextWindowUsedTokens(tokens) {
|
|
4
|
+
return tokens.input + tokens.output + tokens.reasoning + tokens.cache.read + tokens.cache.write;
|
|
5
|
+
}
|
|
6
|
+
export class SessionUsage {
|
|
7
|
+
constructor(options) {
|
|
8
|
+
this.options = options;
|
|
9
|
+
this.limits = new Map();
|
|
10
|
+
this.reports = Promise.resolve();
|
|
11
|
+
}
|
|
12
|
+
observe(event) {
|
|
13
|
+
if (event.type !== "session.step.ended")
|
|
14
|
+
return;
|
|
15
|
+
const { tokens } = event.data;
|
|
16
|
+
// Reports stay in step order while a model's context limit is still being looked up.
|
|
17
|
+
this.reports = this.reports
|
|
18
|
+
.then(() => this.report(tokens))
|
|
19
|
+
.catch((error) => this.options.reportError(error));
|
|
20
|
+
}
|
|
21
|
+
async report(tokens) {
|
|
22
|
+
const model = this.options.info().model;
|
|
23
|
+
const contextWindowMaxTokens = model ? await this.contextLimit(model) : undefined;
|
|
24
|
+
this.options.emit({
|
|
25
|
+
type: "usage_updated",
|
|
26
|
+
provider: "opencode",
|
|
27
|
+
usage: {
|
|
28
|
+
...usageFromV2(this.options.info()),
|
|
29
|
+
contextWindowUsedTokens: contextWindowUsedTokens(tokens),
|
|
30
|
+
...(contextWindowMaxTokens === undefined ? {} : { contextWindowMaxTokens }),
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
contextLimit(model) {
|
|
35
|
+
const key = `${model.providerID}/${model.id}`;
|
|
36
|
+
const cached = this.limits.get(key);
|
|
37
|
+
if (cached)
|
|
38
|
+
return cached;
|
|
39
|
+
const limit = this.options
|
|
40
|
+
.client()
|
|
41
|
+
.model.list({ location: { directory: this.options.cwd } })
|
|
42
|
+
.then((catalog) => catalog.data.find((entry) => entry.providerID === model.providerID && entry.id === model.id)?.limit.context);
|
|
43
|
+
this.limits.set(key, limit);
|
|
44
|
+
limit.catch(() => this.limits.delete(key));
|
|
45
|
+
return limit;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -15106,7 +15106,7 @@ __d(function(g,r,i,_a,m,e,d){'use strict';const t=r(d[0]);m.exports=(s,c,n)=>t(s
|
|
|
15106
15106
|
__d(function(g,r,i,_a,m,e,d){'use strict';const t=r(d[0]);m.exports=(s,c,n)=>t(s,c,n)<=0},3461,[3456]);
|
|
15107
15107
|
__d(function(g,r,i,a,m,e,d){'use strict';const t=r(d[0]);m.exports=(n,c,s)=>{try{c=new t(c,s)}catch(t){return!1}return c.test(n)}},3462,[3451]);
|
|
15108
15108
|
__d(function(g,r,i,a,m,_e,d){"use strict";function e(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(_e,'__esModule',{value:!0}),_e.resolveAppVersion=function(){const e=u(t.default?.version);if(e)return e;const o=u(n.default.expoConfig?.version);if(o)return o;const f=u(n.default.manifest?.version);if(f)return f;return null};var n=e(r(d[0])),t=e(r(d[1]));function u(e){if("string"!=typeof e)return null;const n=e.trim();return 0===n.length?null:n}},3463,[701,3464]);
|
|
15109
|
-
__d(function(e,t,r,o,i,a,n){i.exports={name:"@getpaseo/app",version:"0.10.
|
|
15109
|
+
__d(function(e,t,r,o,i,a,n){i.exports={name:"@getpaseo/app",version:"0.10.2",private:!0,main:"index.ts",scripts:{start:"npm run start:expo","start:expo":"cross-env APP_VARIANT=development expo start","reset-project":"node ./scripts/reset-project.js","eas-build-post-install":"npm --prefix ../.. run build:app-deps && npm run build:terminal-webview",android:"npm run android:development","android:development":"npm --prefix ../.. run build:client && cross-env APP_VARIANT=development expo prebuild --platform android --clean --non-interactive && cross-env APP_VARIANT=development expo run:android --variant=debug","android:production":"npm --prefix ../.. run build:client && cross-env APP_VARIANT=production expo prebuild --platform android --clean --non-interactive && cross-env APP_VARIANT=production expo run:android --variant=release","android:release":"npm run android:production","android:clear":"node -e \"require('node:fs').rmSync('android', { recursive: true, force: true })\"",ios:"npm --prefix ../.. run build:client && expo run:ios","ios:release":"npm --prefix ../.. run build:client && expo run:ios --configuration Release",web:"npm --prefix ../.. run build:client && concurrently --kill-others --names protocol,client,expo --prefix-colors yellow,blue,magenta \"npm --prefix ../.. run watch:protocol\" \"npm --prefix ../.. run watch:client\" \"npm run web:expo\"","web:expo":"expo start --web",lint:"expo lint",typecheck:"tsgo --noEmit",test:"vitest run","test:browser":"vitest run --project browser","test:e2e":"playwright test --project=browser","test:e2e:diff-performance":"cross-env PASEO_DIFF_PERF_E2E=1 playwright test --project=browser e2e/browser/diff-performance.spec.ts","test:e2e:stream-smoothness":"cross-env PASEO_AGENT_STREAM_PERF_E2E=1 playwright test --project=browser e2e/browser/agent-stream-smoothness.spec.ts","test:e2e:real":"cross-env E2E_FORK_PASEO_HOME_FROM=../../.dev/paseo-home playwright test --project=real-provider","test:e2e:relay-deployment":"npm --prefix ../.. run build:server && npm --prefix ../.. run build:daemon-web-ui && cross-env E2E_FORK_PASEO_HOME_FROM=../../.dev/paseo-home playwright test --project=relay-deployment e2e/browser/relay-deployment-reconnect.real.spec.ts","test:e2e:ui":"playwright test --ui",build:"npm run build:web","build:web":"npm --prefix ../.. run build:app-deps && expo export --platform web","profile:composer-typing":"node ./scripts/profile-composer-typing.mjs","profile:explorer-toggle":"node ./scripts/profile-explorer-toggle.mjs","profile:side-pane":"playwright test --config playwright.profile.config.ts side-pane-performance.spec.ts","profile:workspace-switching":"node ./scripts/profile-workspace-switching.mjs","profile:workspace-tabs":"node ./scripts/profile-workspace-tabs.mjs","deploy:web":"npm run build:web && wrangler pages deploy dist --project-name paseo-app --branch main","build:terminal-webview":"node ./scripts/build-terminal-webview-html.mjs","build:mermaid-runtime":"node ./src/components/markdown/fence/mermaid/build-runtime.mjs"},dependencies:{"@codemirror/commands":"6.10.4","@codemirror/language":"6.12.4","@codemirror/search":"6.7.1","@codemirror/state":"6.7.1","@codemirror/view":"6.43.6","@dnd-kit/core":"^6.3.1","@dnd-kit/sortable":"^10.0.0","@dnd-kit/utilities":"^3.2.2","@floating-ui/react-native":"^0.10.7","@getpaseo/client":"*","@getpaseo/expo-two-way-audio":"*","@getpaseo/highlight":"*","@getpaseo/plugin":"*","@getpaseo/protocol":"*","@gorhom/bottom-sheet":"^5.2.14","@gorhom/portal":"^1.0.14","@marijn/find-cluster-break":"^1.0.2","@mattermost/react-native-paste-input":"2.0.1","@react-native-async-storage/async-storage":"2.2.0","@react-native-masked-view/masked-view":"^0.3.2","@react-native/normalize-colors":"^0.81.5","@react-navigation/native":"^7.1.8","@replit/codemirror-vim":"6.3.0","@shopify/react-native-skia":"2.2.12","@tanstack/react-query":"^5.90.11","@tanstack/react-virtual":"^3.13.21","@xterm/addon-clipboard":"^0.3.0-beta.213","@xterm/addon-fit":"^0.12.0-beta.213","@xterm/addon-image":"^0.10.0-beta.213","@xterm/addon-ligatures":"^0.11.0-beta.213","@xterm/addon-search":"^0.17.0-beta.213","@xterm/addon-unicode11":"^0.10.0-beta.213","@xterm/addon-web-links":"^0.13.0-beta.213","@xterm/addon-webgl":"^0.20.0-beta.212","@xterm/xterm":"^6.1.0-beta.213",buffer:"^6.0.3",expo:"^54.0.18","expo-asset":"~12.0.12","expo-audio":"~1.0.13","expo-build-properties":"^1.0.9","expo-camera":"~17.0.10","expo-clipboard":"~8.0.7","expo-constants":"~18.0.9","expo-crypto":"^15.0.8","expo-dev-client":"^6.0.15","expo-document-picker":"~14.0.8","expo-file-system":"~19.0.17","expo-haptics":"~15.0.7","expo-image":"~3.0.10","expo-image-manipulator":"~14.0.8","expo-image-picker":"^17.0.8","expo-keep-awake":"^15.0.7","expo-linking":"~8.0.8","expo-localization":"~17.0.9","expo-notifications":"^0.32.16","expo-router":"~6.0.13","expo-sharing":"^14.0.8","expo-splash-screen":"~31.0.10","expo-sqlite":"~16.0.10","expo-system-ui":"~6.0.7","fast-deep-equal":"^3.1.3",htmlparser2:"^12.0.0",i18next:"^26.3.0","lucide-react-native":"^0.546.0","markdown-it":"^10.0.0",mermaid:"^11.16.0","mnemonic-id":"^3.2.7",qrcode:"^1.5.4",react:"19.1.0","react-dom":"19.1.0","react-freeze":"1.0.4","react-i18next":"^17.0.8","react-native":"0.81.5","react-native-draggable-flatlist":"^4.0.3","react-native-edge-to-edge":"^1.7.0","react-native-gesture-handler":"~2.28.0","react-native-keyboard-controller":"1.21.12","react-native-markdown-display":"^7.0.2","react-native-nitro-modules":"0.35.5","react-native-reanimated":"~4.3.1","react-native-safe-area-context":"~5.6.0","react-native-screens":"~4.16.0","react-native-svg":"^15.14.0","react-native-uitextview":"^2.2.0","react-native-unistyles":"^3.2.4","react-native-web":"~0.21.0","react-native-webview":"^13.16.0","react-native-worklets":"~0.8.3","tiny-invariant":"^1.3.3",turndown:"^7.2.4","turndown-plugin-gfm":"^1.0.2","use-sync-external-store":"^1.6.0",yaml:"^2.8.4",zod:"^4.4.3",zustand:"^5.0.9"},devDependencies:{"@playwright/test":"^1.56.1","@testing-library/dom":"^10.4.1","@testing-library/react":"^16.3.2","@types/markdown-it":"^14.1.2","@types/node":"~22.19.0","@types/qrcode":"^1.5.6","@types/react":"~19.2.0","@types/turndown":"^5.0.6","@types/ws":"^8.18.1","@vitest/browser":"^4.1.7","@vitest/browser-playwright":"^4.1.7","@xterm/headless":"^6.1.0-beta.213",dotenv:"^17.2.3","eas-cli":"^16.24.1",esbuild:"0.28.1",eslint:"^9.25.0","eslint-config-expo":"~10.0.0","expo-gradle-jvmargs":"^1.1.2","fake-indexeddb":"^6.2.5",jsdom:"^20.0.3","material-icon-theme":"^5.32.0",playwright:"^1.56.1","serve-sim":"^0.1.40",typescript:"~5.9.2",vitest:"^4.1.6",wrangler:"^4.105.0",ws:"^8.20.0"},reanimated:{staticFeatureFlags:{FORCE_REACT_RENDER_FOR_SETTLED_ANIMATIONS:!1}}}},3464,[]);
|
|
15110
15110
|
__d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createPluginClientRuntime=function(P,I){const v=(0,c.createPluginSurfaceRuntime)(I,P);if(!v)throw new Error("Plugin host is offline");const f=(0,l.createPluginClientStateSource)(P.serverId),w=(0,o.createPluginCapabilities)(P,v,(0,s.createPluginNavigation)({serverId:P.serverId,workspaceId:null}));return Object.assign({},w,{hosts:(0,n.createPluginHosts)((0,t.getHostRuntimeStore)(),P.lifetime.signal),addComposerPill:t=>u.pluginButtonStore.addComposerPill(P,t),addHeaderButton:t=>u.pluginButtonStore.addHeaderButton(P,t),openPanel(t,n){p({installation:P,runtime:v,state:f,panelId:t,options:n})}})};var t=r(d[0]),n=r(d[1]),o=r(d[2]),l=r(d[3]),s=r(d[4]),u=r(d[5]),c=r(d[6]);function p(t){const{installation:n,runtime:l,state:u,panelId:c,options:p}=t,P=p.workspaceId.trim(),I=p.agentId?.trim(),v=(0,s.createPluginNavigation)({serverId:n.serverId,workspaceId:P}),f=I?(0,o.createPluginAgentActionContext)({plugin:n,runtime:l,navigation:v,state:u,workspaceId:P,agentId:I}):(0,o.createPluginWorkspaceActionContext)({plugin:n,runtime:l,navigation:v,state:u,workspaceId:P});if(!f)throw new Error("Plugin panel context is unavailable");f.openPanel(c,{location:p.location})}},3465,[3466,3636,3639,3648,3653,3665,3670]);
|
|
15111
15111
|
__d(function(g,r,i,a,m,_e,d){"use strict";const e=["password"];function t(e){return e&&e.__esModule?e:{default:e}}Object.defineProperty(_e,'__esModule',{value:!0}),_e.isHostRuntimeConnected=X,_e.isHostRuntimeDirectoryLoading=Y,Object.defineProperty(_e,"HostRuntimeController",{enumerable:!0,get:function(){return de}}),_e.readInitialDaemonConnectionHint=fe,_e.hasConfiguredLocalDaemonOverride=function(){return null!==Ce()},Object.defineProperty(_e,"HostRuntimeStore",{enumerable:!0,get:function(){return Ie}}),_e.getHostRuntimeStore=Re,_e.getHostRuntimeConnectionStatusSince=function(e){return Re().getConnectionStatusSince(e)},_e.useHostRuntimeSnapshot=function(e){const t=(0,s.c)(5);let n;t[0]===Symbol.for("react.memo_cache_sentinel")?(n=Re(),t[0]=n):n=t[0];const c=n;let l,h,u;t[1]!==e?(l=t=>c.subscribe(e,t),h=()=>c.getSnapshot(e),u=()=>c.getSnapshot(e),t[1]=e,t[2]=l,t[3]=h,t[4]=u):(l=t[2],h=t[3],u=t[4]);return(0,o.useSyncExternalStore)(l,h,u)},_e.useHostRuntimeClient=function(e){const t=(0,s.c)(5);let n;t[0]===Symbol.for("react.memo_cache_sentinel")?(n=Re(),t[0]=n):n=t[0];const c=n;let l,h,u;t[1]!==e?(l=t=>c.subscribe(e,t),h=()=>c.getSnapshot(e)?.client??null,u=()=>c.getSnapshot(e)?.client??null,t[1]=e,t[2]=l,t[3]=h,t[4]=u):(l=t[2],h=t[3],u=t[4]);return(0,o.useSyncExternalStore)(l,h,u)},_e.useHostRuntimeIsConnected=function(e){const t=(0,s.c)(5);let n;t[0]===Symbol.for("react.memo_cache_sentinel")?(n=Re(),t[0]=n):n=t[0];const c=n;let l,h,u;t[1]!==e?(l=t=>c.subscribe(e,t),h=()=>X(c.getSnapshot(e)),u=()=>X(c.getSnapshot(e)),t[1]=e,t[2]=l,t[3]=h,t[4]=u):(l=t[2],h=t[3],u=t[4]);return(0,o.useSyncExternalStore)(l,h,u)},_e.useHostRuntimeConnectionStatus=function(e){const t=(0,s.c)(5);let n;t[0]===Symbol.for("react.memo_cache_sentinel")?(n=Re(),t[0]=n):n=t[0];const c=n;let l,h,u;t[1]!==e?(l=t=>c.subscribe(e,t),h=()=>c.getSnapshot(e)?.connectionStatus??"connecting",u=()=>c.getSnapshot(e)?.connectionStatus??"connecting",t[1]=e,t[2]=l,t[3]=h,t[4]=u):(l=t[2],h=t[3],u=t[4]);return(0,o.useSyncExternalStore)(l,h,u)},_e.useHostRuntimeConnectionStatuses=function(e){const t=(0,s.c)(7);let n;t[0]===Symbol.for("react.memo_cache_sentinel")?(n=Re(),t[0]=n):n=t[0];const c=n;let l,h,u;t[1]===Symbol.for("react.memo_cache_sentinel")?(l=e=>c.subscribeAll(e),h=()=>c.getVersion(),u=()=>c.getVersion(),t[1]=l,t[2]=h,t[3]=u):(l=t[1],h=t[2],u=t[3]);(0,o.useSyncExternalStore)(l,h,u);let p;if(t[4]!==e){let n;t[6]===Symbol.for("react.memo_cache_sentinel")?(n=e=>[e,c.getSnapshot(e)?.connectionStatus??"connecting"],t[6]=n):n=t[6];const s=e.map(n);p=new Map(s),t[4]=e,t[5]=p}else p=t[5];return p},_e.useHostRuntimeLastError=function(e){const t=(0,s.c)(5);let n;t[0]===Symbol.for("react.memo_cache_sentinel")?(n=Re(),t[0]=n):n=t[0];const c=n;let l,h,u;t[1]!==e?(l=t=>c.subscribe(e,t),h=()=>c.getSnapshot(e)?.lastError??null,u=()=>c.getSnapshot(e)?.lastError??null,t[1]=e,t[2]=l,t[3]=h,t[4]=u):(l=t[2],h=t[3],u=t[4]);return(0,o.useSyncExternalStore)(l,h,u)},_e.useHostRuntimeAgentDirectoryStatus=function(e){const t=(0,s.c)(5);let n;t[0]===Symbol.for("react.memo_cache_sentinel")?(n=Re(),t[0]=n):n=t[0];const c=n;let l,h,u;t[1]!==e?(l=t=>c.subscribe(e,t),h=()=>c.getSnapshot(e)?.agentDirectoryStatus??"idle",u=()=>c.getSnapshot(e)?.agentDirectoryStatus??"idle",t[1]=e,t[2]=l,t[3]=h,t[4]=u):(l=t[2],h=t[3],u=t[4]);return(0,o.useSyncExternalStore)(l,h,u)},_e.useHostRuntimeIsDirectoryLoading=function(e){const t=(0,s.c)(5);let n;t[0]===Symbol.for("react.memo_cache_sentinel")?(n=Re(),t[0]=n):n=t[0];const c=n;let l,h,u;t[1]!==e?(l=t=>c.subscribe(e,t),h=()=>Y(c.getSnapshot(e)),u=()=>Y(c.getSnapshot(e)),t[1]=e,t[2]=l,t[3]=h,t[4]=u):(l=t[2],h=t[3],u=t[4]);return(0,o.useSyncExternalStore)(l,h,u)},_e.useHosts=function(){const e=(0,s.c)(4);let t;e[0]===Symbol.for("react.memo_cache_sentinel")?(t=Re(),e[0]=t):t=e[0];const n=t;let c,l,h;e[1]===Symbol.for("react.memo_cache_sentinel")?(c=e=>n.subscribeHostList(e),l=()=>n.getHosts(),h=()=>n.getHosts(),e[1]=c,e[2]=l,e[3]=h):(c=e[1],l=e[2],h=e[3]);return(0,o.useSyncExternalStore)(c,l,h)},_e.useHostRegistryStatus=function(){const e=(0,s.c)(4);let t;e[0]===Symbol.for("react.memo_cache_sentinel")?(t=Re(),e[0]=t):t=e[0];const n=t;let c,l,h;e[1]===Symbol.for("react.memo_cache_sentinel")?(c=e=>n.subscribeHostList(e),l=()=>n.getHostRegistryStatus(),h=()=>n.getHostRegistryStatus(),e[1]=c,e[2]=l,e[3]=h):(c=e[1],l=e[2],h=e[3]);return(0,o.useSyncExternalStore)(c,l,h)},_e.useHostRegistryLoaded=function(){const e=(0,s.c)(4);let t;e[0]===Symbol.for("react.memo_cache_sentinel")?(t=Re(),e[0]=t):t=e[0];const n=t;let c,l,h;e[1]===Symbol.for("react.memo_cache_sentinel")?(c=e=>n.subscribeHostList(e),l=()=>n.isHostRegistryLoaded(),h=()=>n.isHostRegistryLoaded(),e[1]=c,e[2]=l,e[3]=h):(c=e[1],l=e[2],h=e[3]);return(0,o.useSyncExternalStore)(c,l,h)},_e.useHostMutations=function(){const e=(0,s.c)(2);let t;e[0]===Symbol.for("react.memo_cache_sentinel")?(t=Re(),e[0]=t):t=e[0];const n=t;let o;e[1]===Symbol.for("react.memo_cache_sentinel")?(o={upsertDirectConnection:e=>n.upsertDirectConnection(e),probeAndUpsertDirectConnection:e=>n.probeAndUpsertDirectConnection(e),probeAndUpsertRemoteSshConnection:e=>n.probeAndUpsertRemoteSshConnection(e),upsertRelayConnection:e=>n.upsertRelayConnection(e),upsertConnectionFromOffer:(e,t)=>n.upsertConnectionFromOffer(e,t),upsertConnectionFromOfferUrl:(e,t,s)=>n.upsertConnectionFromOfferUrl(e,t,s),probeAndUpsertConnectionFromOfferUrl:(e,t)=>n.probeAndUpsertConnectionFromOfferUrl(e,t),renameHost:(e,t)=>n.renameHost(e,t),setHostColor:(e,t)=>n.setHostColor(e,t),setHostBadgeDisplay:(e,t)=>n.setHostBadgeDisplay(e,t),removeHost:e=>n.removeHost(e),removeConnection:(e,t)=>n.removeConnection(e,t)},e[1]=o):o=e[1];return o};var n=t(r(d[0])),s=r(d[1]),o=r(d[2]),c=t(r(d[3])),l=t(r(d[4])),h=r(d[5]),u=r(d[6]),p=r(d[7]),y=r(d[8]),S=r(d[9]),f=r(d[10]),C=r(d[11]),v=r(d[12]),b=r(d[13]),w=r(d[14]),I=r(d[15]),A=r(d[16]),H=r(d[17]),R=r(d[18]),D=r(d[19]),E=r(d[20]),O=r(d[21]),P=r(d[22]),L=r(d[23]),T=r(d[24]),_=r(d[25]),M=r(d[26]),B=r(d[27]),F=r(d[28]),k=r(d[29]),j=r(d[30]),q=r(d[31]),U=r(d[32]),x=r(d[33]),V=r(d[34]),W=r(d[35]),$=r(d[36]),N=r(d[37]),G=r(d[38]),z=r(d[39]),K=r(d[40]),Q=r(d[41]);function J(e,t,n){e[t]=n}function X(e){return"online"===e?.connectionStatus}function Y(e){return!e||("initial_loading"===e.agentDirectoryStatus||"revalidating"===e.agentDirectoryStatus||!e.hasEverLoadedAgentDirectory&&("connecting"===e.connectionStatus||"online"===e.connectionStatus))}function Z(e){return e instanceof Error?e.message:String(e)}function ee(e){let t=0;for(let n=0;n<e.length;n+=1)t=31*t+e.charCodeAt(n)|0;return`h_${Math.abs(t).toString(16)}`}function te(e){return"directSocket"===e.type?{type:"directSocket",endpoint:e.path,display:"socket"}:"directPipe"===e.type?{type:"directPipe",endpoint:e.path,display:"pipe"}:"remoteSsh"===e.type?{type:"remoteSsh",endpoint:e.host,display:e.host}:"directTcp"===e.type?{type:"directTcp",endpoint:e.endpoint,display:e.endpoint}:{type:"relay",endpoint:e.relayEndpoint,display:"relay"}}function ne(e){return"connecting"===e.tag||"online"===e.tag||"offline"===e.tag||"error"===e.tag?{id:e.activeConnectionId,connection:e.activeConnection}:{id:null,connection:null}}function se(e,t,n){const s=n.state.status;return"connected"===s?{tag:"online",activeConnectionId:e,activeConnection:t,lastOnlineAt:(new Date).toISOString()}:"connecting"===s||"idle"===s?{tag:"connecting",activeConnectionId:e,activeConnection:t}:"disposed"===s?{tag:"offline",activeConnectionId:e,activeConnection:t}:null}function oe(e,t,n){const s=se(e,t,n);if(s)return s;const o=("disconnected"===n.state.status?n.state.reason??null:null)??n.lastError??null;return o&&"client_closed"!==o?{tag:"error",activeConnectionId:e,activeConnection:t,message:o}:{tag:"offline",activeConnectionId:e,activeConnection:t}}function ie(e){const{state:t,event:n}=e;if("select_connection"===n.type)return{tag:"connecting",activeConnectionId:n.connectionId,activeConnection:n.connection};if("connect_failed"===n.type){const e=ne(t);return{tag:"error",activeConnectionId:e.id,activeConnection:e.connection,message:n.message}}if("no_connections"===n.type||"stopped"===n.type)return{tag:"offline",activeConnectionId:null,activeConnection:null};const s=ne(t);return s.id&&s.connection?oe(s.id,s.connection,n):"booting"===t.tag?t:{tag:"offline",activeConnectionId:null,activeConnection:null}}function re(e,t){return"booting"===e.tag?{activeConnectionId:null,activeConnection:null,connectionStatus:"connecting",lastError:null,lastOnlineAt:null,connectionEpoch:t}:"connecting"===e.tag?{activeConnectionId:e.activeConnectionId,activeConnection:e.activeConnection,connectionStatus:"connecting",lastError:null,lastOnlineAt:null,connectionEpoch:t}:"online"===e.tag?{activeConnectionId:e.activeConnectionId,activeConnection:e.activeConnection,connectionStatus:"online",lastError:null,lastOnlineAt:e.lastOnlineAt,connectionEpoch:t}:"offline"===e.tag?{activeConnectionId:e.activeConnectionId,activeConnection:e.activeConnection,connectionStatus:"offline",lastError:null,lastOnlineAt:null,connectionEpoch:t}:{activeConnectionId:e.activeConnectionId,activeConnection:e.activeConnection,connectionStatus:"error",lastError:e.message,lastOnlineAt:null,connectionEpoch:t}}function ce(e){return e.connections.map(e=>({connectionId:e.id,connection:e}))}function ae(e,t){return t?e.connections.find(e=>e.id===t)??null:null}function le(e,t,n,s){if(t)return 1e4;if(n)return 12e4;const o=s-e;return o<1e4?2e3:o<3e4?5e3:o<6e4?1e4:3e4}function he(){const e="function"==typeof(0,D.getDesktopHost)()?.browser?.executeAutomationCommand?{[O.CLIENT_CAPS.browserHost]:{supportedCommands:[...P.BROWSER_AUTOMATION_COMMAND_NAMES],hostKind:"desktop app"}}:void 0,t=Object.assign({},e);return{createClient:({host:e,connection:n,clientId:s,runtimeGeneration:o})=>{const c=(0,R.createDesktopDaemonTransportFactory)(),l={webSocketFactory:(0,Q.createAppWebSocketFactory)()},u=Object.assign({suppressSendErrors:!0,clientId:s,clientType:"mobile",appVersion:(0,S.resolveAppVersion)()??void 0,runtimeGeneration:o,capabilities:t,trace:z.nativePerformanceTrace,providerSnapshots:"wire"},e.password?{password:e.password}:{},{localCredential:()=>(0,E.readDesktopManagedLocalCredential)(n)});if("directSocket"===n.type||"directPipe"===n.type)return new h.DaemonClient(Object.assign({},u,c?{transportFactory:c}:{},{url:(0,R.buildDesktopDaemonTransportUrl)({transportType:"directSocket"===n.type?"socket":"pipe",transportPath:n.path})}));if("remoteSsh"===n.type){if(!c)throw new Error("Remote SSH is only available in the desktop app.");return new h.DaemonClient(Object.assign({},u,{transportFactory:c,url:(0,R.buildDesktopDaemonTransportUrl)(Object.assign({transportType:"ssh",host:n.host},void 0!==n.sshPort?{sshPort:n.sshPort}:{},void 0!==n.daemonPort?{daemonPort:n.daemonPort}:{}))}))}return"directTcp"===n.type?new h.DaemonClient(Object.assign({},u,l,{url:(0,y.buildDaemonWebSocketUrl)(n.endpoint,{useTls:n.useTls??!1})})):new h.DaemonClient(Object.assign({},u,l,{url:(0,y.buildRelayWebSocketUrl)({endpoint:n.relayEndpoint,useTls:n.useTls??(0,y.shouldUseTlsForDefaultHostedRelay)(n.relayEndpoint),serverId:e.serverId}),e2ee:{enabled:!0,daemonPublicKeyB64:n.daemonPublicKeyB64}}))},connectToDaemon:({host:e,connection:n,timeoutMs:s})=>(0,b.connectToDaemon)(n,Object.assign({},e.serverId?{serverId:e.serverId}:{},e.password?{password:e.password}:{},{localCredential:()=>(0,E.readDesktopManagedLocalCredential)(n)},void 0!==s?{timeoutMs:s}:{},{capabilities:t,trace:z.nativePerformanceTrace})),getClientId:()=>(0,w.getOrCreateClientId)(),mountClientHandlers:({client:t,host:n})=>{const s=(0,B.mountServerDataPushRouter)({client:t,queryClient:M.queryClient,serverId:n.serverId});if(!e)return s;const o=(0,F.mountBrowserAutomationDaemonClientHandler)(t,{serverId:n.serverId});return()=>{o(),s()}}}}class de{connectionEpoch=0;listeners=new Set;activeClient=null;unsubscribeClientStatus=null;unsubscribeClientHandlers=null;probeIntervalHandle=null;started=!1;connectionFirstSeenAt=new Map;connectionLastProbedAt=new Map;switchCandidateConnectionId=null;switchCandidateHitCount=0;clientIdPromise=null;clientIdHash=null;switchRequestVersion=0;probeRequestVersion=0;probeCycleInFlight=null;authRejectedConnectionIds=new Set;constructor(e){this.host=e.host,this.deps=e.deps??he(),this.onReconcileServerId=e.onReconcileServerId??null,this.connectionMachineState={tag:"booting"},this.snapshot=Object.assign({serverId:this.host.serverId},re(this.connectionMachineState,this.connectionEpoch),{client:null,agentDirectoryStatus:"idle",agentDirectoryError:null,hasEverLoadedAgentDirectory:!1,probeByConnectionId:new Map,clientGeneration:0})}getSnapshot(){return this.snapshot}getClient(){return this.snapshot.client}subscribe(e){return this.listeners.add(e),()=>{this.listeners.delete(e)}}async start(e){this.started||(this.started=!0,this.trackConnectionFirstSeen(),e?.initialConnection&&await this.switchToConnection({connectionId:e.initialConnection.connectionId,existingClient:e.initialConnection.existingClient}),await this.runProbeCycleNow(),!1!==e?.autoProbe&&(this.probeIntervalHandle=setInterval(()=>{this.runProbeCycleNow()},2e3)))}async stop(){if(this.switchRequestVersion+=1,this.probeRequestVersion+=1,this.started=!1,this.probeIntervalHandle&&(clearInterval(this.probeIntervalHandle),this.probeIntervalHandle=null),this.unsubscribeClientStatus&&(this.unsubscribeClientStatus(),this.unsubscribeClientStatus=null),this.unsubscribeClientHandlers&&(this.unsubscribeClientHandlers(),this.unsubscribeClientHandlers=null),this.activeClient){const e=this.activeClient;this.activeClient=null,await e.close().catch(()=>{})}this.applyConnectionEvent({type:"stopped"}),this.updateSnapshot(Object.assign({},re(this.connectionMachineState,this.connectionEpoch),{client:null}))}async updateHost(e){const t=this.host.password!==e.password;t&&(this.probeRequestVersion+=1,this.authRejectedConnectionIds.clear(),this.updateSnapshot({authFailureReason:null}));const n=this.snapshot.activeConnectionId,s=ae(this.host,n);this.host=e,this.trackConnectionFirstSeen();const o=ae(this.host,n);n&&s&&o&&(!(0,l.default)(s,o)||t)&&(this.connectionLastProbedAt.delete(n),await this.switchToConnection({connectionId:n})),t&&this.connectionLastProbedAt.clear(),t&&await this.probeCycleInFlight,await this.runProbeCycleNow()}ensureConnected(e){this.activeClient?.ensureConnected(e)}markAgentDirectorySyncLoading(){const e=this.snapshot.hasEverLoadedAgentDirectory?"revalidating":"initial_loading";this.updateSnapshot({agentDirectoryStatus:e,agentDirectoryError:null})}markAgentDirectorySyncReady(){this.updateSnapshot({agentDirectoryStatus:"ready",agentDirectoryError:null,hasEverLoadedAgentDirectory:!0})}markAgentDirectorySyncError(e){const t=this.snapshot.hasEverLoadedAgentDirectory;this.updateSnapshot({agentDirectoryStatus:t?"error_after_ready":"error_before_first_success",agentDirectoryError:e,hasEverLoadedAgentDirectory:t})}markAgentDirectorySyncIdle(){this.updateSnapshot({agentDirectoryStatus:this.snapshot.hasEverLoadedAgentDirectory?"ready":"idle",agentDirectoryError:null})}markStartupError(e){this.applyConnectionEvent({type:"connect_failed",message:e}),this.updateSnapshot(Object.assign({},re(this.connectionMachineState,this.connectionEpoch)))}async activateConnection(e){await this.switchToConnection(e)}async runProbeCycleNow(){if(this.probeCycleInFlight)return this.probeCycleInFlight;const e=this.runProbeCycle().finally(()=>{this.probeCycleInFlight===e&&(this.probeCycleInFlight=null)});return this.probeCycleInFlight=e,e}async runProbeCycle(){const e=++this.probeRequestVersion;if(0===this.host.connections.length){if(!this.isCurrentProbeRequest(e))return;return this.applyConnectionEvent({type:"no_connections"}),void this.updateSnapshot(Object.assign({},re(this.connectionMachineState,this.connectionEpoch),{probeByConnectionId:new Map}))}const t=performance.now(),n="online"===this.snapshot.connectionStatus,s=this.snapshot.activeConnectionId,o=n&&null!==s,c=this.host.connections.filter(e=>{if(this.authRejectedConnectionIds.has(e.id))return!1;const c=this.connectionLastProbedAt.get(e.id);if(null==c)return!0;const l=le(this.connectionFirstSeenAt.get(e.id)??t,n&&e.id===s,o,t);return t-c>=l});if(0===c.length)return;const l=new Map(this.snapshot.probeByConnectionId);for(const e of c){this.connectionLastProbedAt.set(e.id,performance.now());const t=l.get(e.id);n&&e.id===s&&"available"===t?.status||l.set(e.id,{status:"pending",latencyMs:null})}this.updateSnapshot({probeByConnectionId:new Map(l)});let u=c.length,p=null,y=null;const S=()=>{this.isCurrentProbeRequest(e)&&this.updateSnapshot({probeByConnectionId:new Map(l)})},f=async(t,n)=>{for(;!this.snapshot.activeConnectionId;){if(!y)return y=this.switchToConnection({connectionId:t,expectedProbeVersion:e,existingClient:n}).finally(()=>{y=null}),await y,this.snapshot.activeConnectionId===t;await y}return!1},C=async()=>{if(u>0||!this.isCurrentProbeRequest(e))return;const t=this.snapshot.activeConnectionId,n=t?l.get(t):null;if(!t||!ae(this.host,t)){const t=(0,H.selectBestConnection)({candidates:ce(this.host),probeByConnectionId:l});if(t)await this.switchToConnection({connectionId:t,expectedProbeVersion:e});else if(p){const e=new h.DaemonAuthenticationError(p).message;this.applyConnectionEvent({type:"connect_failed",message:e}),this.updateSnapshot(Object.assign({},re(this.connectionMachineState,this.connectionEpoch),{authFailureReason:p}))}return}if(this.isConnectionUnavailable(t,n)){const n=(0,H.selectBestConnection)({candidates:ce(this.host),probeByConnectionId:l});return n&&n!==t&&await this.switchToConnection({connectionId:n,expectedProbeVersion:e}),this.switchCandidateConnectionId=null,void(this.switchCandidateHitCount=0)}if(!n||"available"!==n.status)return;const s=Array.from(l.entries()).filter(e=>"available"===e[1].status).map(([e,t])=>({connectionId:e,latencyMs:t.latencyMs})).sort((e,t)=>e.latencyMs-t.latencyMs)[0]??null;if(!s||s.connectionId===t)return this.switchCandidateConnectionId=null,void(this.switchCandidateHitCount=0);if(n.latencyMs-s.latencyMs<40)return this.switchCandidateConnectionId=null,void(this.switchCandidateHitCount=0);this.switchCandidateConnectionId===s.connectionId?this.switchCandidateHitCount+=1:(this.switchCandidateConnectionId=s.connectionId,this.switchCandidateHitCount=1),this.switchCandidateHitCount>=3&&(this.switchCandidateConnectionId=null,this.switchCandidateHitCount=0,await this.switchToConnection({connectionId:s.connectionId,expectedProbeVersion:e}))};await new Promise(t=>{for(const n of c)(async()=>{let s=null,o=!1;try{const t=this.snapshot.activeConnectionId===n.id?this.snapshot.client:null;if(t)s=t;else{const{client:e,serverId:t}=await this.deps.connectToDaemon({host:this.host,connection:n});if(t!==this.host.serverId){if(!me(this.host.serverId)||!this.onReconcileServerId)throw await e.close().catch(()=>{}),new Error(`Connection resolved to ${t}, expected ${this.host.serverId}.`);this.onReconcileServerId(this.host.serverId,t)}s=e,o=!0}if(!this.isCurrentProbeRequest(e))return;const c=await f(n.id,s);if(o=o&&!c,t){const s=t.getLastLivenessRttMs();if(!this.isCurrentProbeRequest(e))return;return void(null!==s&&(l.set(n.id,{status:"available",latencyMs:s}),S()))}const h=await s.measureLatency({timeoutMs:5e3});if(!this.isCurrentProbeRequest(e))return;l.set(n.id,{status:"available",latencyMs:h}),S()}catch(t){if(this.isCurrentProbeRequest(e)){const e=(0,b.getConnectionAuthFailureReason)(t);e&&(this.authRejectedConnectionIds.add(n.id),p=e),l.set(n.id,{status:"unavailable",latencyMs:null}),S()}}finally{s&&o&&await s.close().catch(()=>{}),u-=1,C().finally(()=>{0===u&&t()})}})()})}isConnectionUnavailable(e,t){return"unavailable"===t?.status||this.authRejectedConnectionIds.has(e)}updateSnapshot(e){const t=Object.assign({},e);let n=this.host.serverId!==this.snapshot.serverId;for(const s of Object.keys(e)){const o=e[s];(0,l.default)(this.snapshot[s],o)?J(t,s,this.snapshot[s]):n=!0}if(n){this.snapshot=Object.assign({},this.snapshot,t,{serverId:this.host.serverId});for(const e of this.listeners)e()}}applyConnectionEvent(e){const t=this.connectionMachineState,n=ie({state:t,event:e});"online"!==t.tag&&"online"===n.tag&&(this.connectionEpoch+=1),this.connectionMachineState=n,this.logConnectionTransition({from:t.tag,to:n.tag,event:e})}logConnectionTransition(e){}trackConnectionFirstSeen(){const e=performance.now(),t=new Set(this.host.connections.map(e=>e.id));for(const e of this.connectionFirstSeenAt.keys())t.has(e)||(this.connectionFirstSeenAt.delete(e),this.connectionLastProbedAt.delete(e));for(const t of this.host.connections)this.connectionFirstSeenAt.has(t.id)||this.connectionFirstSeenAt.set(t.id,e)}isCurrentSwitchRequest(e){return e===this.switchRequestVersion}isCurrentProbeRequest(e){return e===this.probeRequestVersion}canProceedForProbe(e){return void 0===e||this.isCurrentProbeRequest(e)}async abortSwitchWithClient(e){e&&await e.close().catch(()=>{})}isSwitchStillValid(e,t){return this.isCurrentSwitchRequest(e)&&this.canProceedForProbe(t)}async resolveClientIdForSwitch(e){try{return await this.resolveClientId()}catch(t){if(await this.abortSwitchWithClient(e.existingClient),!this.isCurrentSwitchRequest(e.requestVersion))return null;const n=Z(t);return this.applyConnectionEvent({type:"connect_failed",message:`Failed to resolve client id: ${n}`}),this.updateSnapshot(Object.assign({},re(this.connectionMachineState,this.connectionEpoch))),null}}async disposePreviousActiveClient(){if(this.unsubscribeClientStatus&&(this.unsubscribeClientStatus(),this.unsubscribeClientStatus=null),this.unsubscribeClientHandlers&&(this.unsubscribeClientHandlers(),this.unsubscribeClientHandlers=null),this.activeClient){const e=this.activeClient;this.activeClient=null,await e.close().catch(()=>{})}}buildAgentDirectoryStatusPatch(){if(this.snapshot.hasEverLoadedAgentDirectory)return{};const e=this.connectionMachineState.tag;return"connecting"===e||"online"===e?{agentDirectoryStatus:"initial_loading",agentDirectoryError:null}:"error"===e?{agentDirectoryStatus:"error_before_first_success",agentDirectoryError:this.connectionMachineState.message}:{agentDirectoryStatus:"idle",agentDirectoryError:null}}async switchToConnection(e){const{connectionId:t,expectedProbeVersion:n,existingClient:s}=e;if(!this.canProceedForProbe(n))return void await this.abortSwitchWithClient(s);const o=ae(this.host,t);if(!o)return void await this.abortSwitchWithClient(s);const c=++this.switchRequestVersion,l=await this.resolveClientIdForSwitch({existingClient:s,requestVersion:c});if(null===l)return;if(!this.isSwitchStillValid(c,n))return void await this.abortSwitchWithClient(s);if(await this.disposePreviousActiveClient(),!this.isSwitchStillValid(c,n))return void await this.abortSwitchWithClient(s);const u=this.snapshot.clientGeneration+1,p=s??this.deps.createClient({host:this.host,connection:o,clientId:l,runtimeGeneration:u});if(p.setReconnectEnabled(!0),!this.isSwitchStillValid(c,n))return void await p.close().catch(()=>{});this.activeClient=p,this.applyConnectionEvent({type:"select_connection",connectionId:o.id,connection:te(o)}),this.snapshot=Object.assign({},this.snapshot,{clientGeneration:u}),this.updateSnapshot(Object.assign({},re(this.connectionMachineState,this.connectionEpoch),{client:null}));const y=async e=>{if(!this.isCurrentSwitchRequest(c)||this.activeClient!==p)return;const t=(0,b.getConnectionAuthFailureReason)(e);if(t&&this.authRejectedConnectionIds.add(o.id),this.unsubscribeClientStatus?.(),this.unsubscribeClientStatus=null,this.unsubscribeClientHandlers?.(),this.unsubscribeClientHandlers=null,p.setReconnectEnabled(!1),this.applyConnectionEvent({type:"connect_failed",message:Z(e)}),this.updateSnapshot(Object.assign({},re(this.connectionMachineState,this.connectionEpoch),{client:null,authFailureReason:t})),t){const e=new Map(this.snapshot.probeByConnectionId);e.set(o.id,{status:"unavailable",latencyMs:null}),this.updateSnapshot({probeByConnectionId:e});for(const e of this.host.connections)this.authRejectedConnectionIds.has(e.id)||this.connectionLastProbedAt.delete(e.id)}try{await p.close()}catch{}t&&this.host.connections.some(e=>!this.authRejectedConnectionIds.has(e.id))&&this.runProbeCycleNow()};try{if(s||await p.connect(),!this.isCurrentSwitchRequest(c)||this.activeClient!==p)return;this.unsubscribeClientHandlers=this.deps.mountClientHandlers?.({client:p,host:this.host,connection:o})??null,this.unsubscribeClientStatus=p.subscribeConnectionStatus(e=>{this.isCurrentSwitchRequest(c)&&this.activeClient===p&&(p.authFailureReason?y(new h.DaemonAuthenticationError(p.authFailureReason)):(this.applyConnectionEvent({type:"client_state",state:e,lastError:p.lastError}),this.updateSnapshot(Object.assign({},re(this.connectionMachineState,this.connectionEpoch),this.buildAgentDirectoryStatusPatch(),{client:p,authFailureReason:null}))))})}catch(e){await y(e)}}adoptReconciledServerId(e){this.host=Object.assign({},this.host,{serverId:e}),this.snapshot=Object.assign({},this.snapshot,{serverId:e});for(const e of this.listeners)e()}resolveClientId(){return this.clientIdPromise||(this.clientIdPromise=this.deps.getClientId().then(e=>(this.clientIdHash=ee(e),e))),this.clientIdPromise}}const ue="@paseo:daemon-registry",pe="localhost:6767",ye=2500,ge="__PASEO_INITIAL_DAEMON_CONNECTION__",Se=I.z.object({listen:I.z.string().trim().min(1),useTls:I.z.boolean().optional().default(!1)});function fe(e){if(!(e?.isWebRuntime??v.isWeb)||"undefined"==typeof globalThis)return null;const t=Se.safeParse(Reflect.get(globalThis,ge));return t.success?t.data:null}function Ce(){return null}function ve(e){if(e.trim().startsWith("relay://")||e.includes("#connect="))return(0,y.parseRelayConnectionUri)(e);const t="#offer=",n=e.indexOf(t);if(-1===n)throw new Error("Missing #offer= fragment");const s=e.slice(n+7).trim();if(!s)throw new Error("Offer payload is empty");const o=(0,y.decodeOfferFragmentPayload)(s);return{offer:f.ConnectionOfferSchema.parse(o)}}function me(e){return e.startsWith("local:")}function be(e){return new Promise(t=>setTimeout(t,e))}function we(e,t,n){const s=e.get(t);void 0!==s&&(e.delete(t),e.set(n,s))}class Ie{controllers=new Map;serverListeners=new Map;globalListeners=new Set;hostListListeners=new Set;version=0;hostListVersion=0;hostRegistryLoaded=!1;hosts=[];hostAppearanceMutationTail=Promise.resolve();hostRegistryStatus="loading";lastConnectionStatusByServer=new Map;connectionStatusStartedAtByServer=new Map;queuedAgentDrainInFlight=new Set;directorySyncByServer=new Map;nextCancellationRequestId=0;timelineReplicaByServer=new Map;configuredOverrideBootstrapInFlight=null;bootPromise=null;constructor(e){this.deps=e?.deps??he(),this.storage=e?.storage??c.default,this.replicaCache=new W.ReplicaCache(e?.replicaRowStore??(0,$.createReplicaRowStore)()),this.revokePushNotifications=e?.revokePushNotifications??K.revokePushNotifications}getHosts(){return this.hosts}getHostRegistryStatus(){return this.hostRegistryStatus}subscribeHostList(e){return this.hostListListeners.add(e),()=>{this.hostListListeners.delete(e)}}getHostListVersion(){return this.hostListVersion}isHostRegistryLoaded(){return this.hostRegistryLoaded}boot(){return this.bootPromise||(this.bootPromise=this.runBoot()),this.bootPromise}async runBoot(){await this.loadFromStorage(),this.markHostRegistryLoaded();let e=null;try{e=await(0,A.readValidatedString)(this.storage,"@paseo:e2e",I.z.string().min(1))}catch{return}if(e)return;if((0,C.shouldUseDesktopDaemon)())return;const t=this.deps.readInitialConnectionHint?this.deps.readInitialConnectionHint():fe();if(t){if(await this.bootstrapInitialConnectionHint(t))return}await this.bootstrapDefaultLocalhost()}async loadFromStorage(){let e=!1,t=[];try{const n=await(0,A.readValidatedJson)(this.storage,ue,u.StoredHostRegistrySchema);if(n){const s=[];for(const t of n){const n=(0,u.normalizeStoredHostProfile)(t);if(!n){await this.storage.removeItem(ue),s.length=0;break}t.connections.some(e=>"directTcp"===e.type&&e.password)&&(e=!0),s.push(n)}t=s.filter(e=>!me(e.serverId)),t.length!==s.length&&(e=!0)}this.hosts=t,this.replicaCache.setHosts(t.map(e=>e.serverId)),G.projectIconCache.setHosts(t.map(e=>e.serverId)),await G.projectIconCache.restore(),this.syncHosts(t);for(const e of t)this.directorySyncByServer.get(e.serverId)?.restoreCachedDirectory().catch(()=>{})}catch(e){console.error("[HostRuntime] Failed to load host registry from storage",e)}finally{this.hostRegistryStatus="ready",this.emitHostList(),e&&this.persistHosts().catch(e=>console.error("[HostRuntime] Failed to persist host registry",e))}}markHostRegistryLoaded(){this.hostRegistryLoaded||(this.hostRegistryLoaded=!0,this.emitHostList())}async bootstrapDefaultLocalhost(){const e=(0,u.connectionFromListen)(pe);if(e&&!(0,u.registryHasConnection)(this.hosts,e))try{await this.probeAndUpsertConnection({connection:e,timeoutMs:ye})}catch(e){console.warn("[HostRuntime] bootstrap probe failed",{endpoint:pe,error:e})}}bootstrapConfiguredOverride(e){const t=(0,u.connectionFromListen)(e);if(!t)return;if((0,u.registryHasConnection)(this.hosts,t))return;if(this.configuredOverrideBootstrapInFlight)return;const n=this.runConfiguredOverrideBootstrap(e,t).finally(()=>{this.configuredOverrideBootstrapInFlight===n&&(this.configuredOverrideBootstrapInFlight=null)});this.configuredOverrideBootstrapInFlight=n}async runConfiguredOverrideBootstrap(e,t){let n=0;for(;!(0,u.registryHasConnection)(this.hosts,t);){n+=1;try{return void await this.probeAndUpsertConnection({connection:t,timeoutMs:ye})}catch(t){1!==n&&n%10!=0||console.warn("[HostRuntime] configured bootstrap probe failed",{endpoint:e,attempt:n,error:t}),await be(1e3)}}}async bootstrapInitialConnectionHint(e){const t=(0,u.connectionFromListen)(e.listen);if(!t)return!1;const n="directTcp"===t.type?Object.assign({},t,{useTls:e.useTls??t.useTls??!1}):t;if((0,u.registryHasConnection)(this.hosts,n))return!0;try{return await this.probeAndUpsertConnection({connection:n,timeoutMs:ye}),!0}catch(t){return console.warn("[HostRuntime] initial connection hint probe failed",{listen:e.listen,useTls:e.useTls,error:t}),!1}}reconcileServerId(e,t){if(e===t)return;const n=this.controllers.get(e);if(!n)return;if(this.controllers.has(t))return;we(this.controllers,e,t),we(this.lastConnectionStatusByServer,e,t),we(this.connectionStatusStartedAtByServer,e,t),this.replicaCache.reconcileServerId(e,t),G.projectIconCache.reconcileServerId(e,t),this.directorySyncByServer.get(e)?.dispose(),this.directorySyncByServer.delete(e),this.timelineReplicaByServer.delete(e);const s=new V.DirectorySync(t,{onAgentStoppedRunning:e=>this.drainQueuedAgentMessage(t,e),markAgentLoading:()=>n.markAgentDirectorySyncLoading(),markAgentReady:()=>n.markAgentDirectorySyncReady(),markAgentError:e=>n.markAgentDirectorySyncError(e)},this.replicaCache);this.directorySyncByServer.set(t,s),this.timelineReplicaByServer.set(t,(0,N.createTimelineReplica)({serverId:t,storage:this.replicaCache,prepareAgent:e=>s.prepareAgentRoute(e)})),n.adoptReconciledServerId(t);const o=n.getSnapshot();this.clearHostReplica(e),this.syncSessionReplica(t,o),s.connectionChanged({client:o.client,status:"online"===o.connectionStatus?"online":"offline",source:{clientGeneration:o.clientGeneration,connectionEpoch:o.connectionEpoch}});const c=this.serverListeners.get(e);if(c){this.serverListeners.delete(e);const n=this.serverListeners.get(t)??new Set;for(const e of c)n.add(e);this.serverListeners.set(t,n)}this.hosts=this.hosts.map(n=>n.serverId===e?Object.assign({},n,{serverId:t,updatedAt:(new Date).toISOString()}):n),this.emitHostList(),this.emit(t),this.persistHosts().catch(e=>console.error("[HostRuntime] Failed to persist host registry",e))}async upsertDirectConnection(e){const t=(0,y.normalizeHostPort)(e.endpoint),n=e.password?.trim();return this.upsertHostConnection({serverId:e.serverId,label:e.label,password:n,connection:{id:`direct:${t}`,type:"directTcp",endpoint:t,useTls:e.useTls??!1},existingClient:e.existingClient})}async probeAndUpsertConnection(e){if("relay"===e.connection.type)throw new Error("Cannot probe a relay connection without a server id.");const t=Object.assign({serverId:""},e.password?{password:e.password}:{},{label:e.label??e.connection.id,appearance:(0,p.defaultHostAppearance)(),lifecycle:{},connections:[e.connection],preferredConnectionId:e.connection.id,createdAt:new Date(0).toISOString(),updatedAt:new Date(0).toISOString()}),{client:n,serverId:s,hostname:o}=await this.deps.connectToDaemon(Object.assign({host:t,connection:e.connection},void 0!==e.timeoutMs?{timeoutMs:e.timeoutMs}:{}));return{profile:await this.upsertHostConnection({serverId:s,label:e.label??o??void 0,password:e.password,connection:e.connection,existingClient:n}),serverId:s,hostname:o}}async probeAndUpsertDirectConnection(e){const t=(0,y.normalizeHostPort)(e.endpoint),n=e.password?.trim();return this.probeAndUpsertConnection({label:e.label,password:n,connection:{id:`direct:${t}`,type:"directTcp",endpoint:t,useTls:e.useTls??!1}})}async probeAndUpsertRemoteSshConnection(e){return this.probeAndUpsertConnection({label:e.label,connection:(0,u.createRemoteSshHostConnection)(e)})}async upsertRelayConnection(e){const t=(0,y.normalizeHostPort)(e.relayEndpoint),n=e.useTls??!1,s=e.daemonPublicKeyB64.trim();if(!s)throw new Error("daemonPublicKeyB64 is required");const o=void 0!==e.useTls,c=await this.upsertHostConnection({serverId:e.serverId,label:e.label,connection:Object.assign({id:n?`relay:wss:${t}`:`relay:${t}`,type:"relay",relayEndpoint:t},o?{useTls:n}:{},{daemonPublicKeyB64:s})});return e.password?(await this.setHostPassword(c.serverId,e.password),this.hosts.find(e=>e.serverId===c.serverId)??c):c}async upsertConnectionFromOffer(e,t,n){const s=e.relay.useTls??(0,y.shouldUseTlsForDefaultHostedRelay)(e.relay.endpoint);return this.upsertRelayConnection({serverId:e.serverId,relayEndpoint:e.relay.endpoint,useTls:s,daemonPublicKeyB64:e.daemonPublicKeyB64,label:t,password:n})}async upsertConnectionFromOfferUrl(e,t,n){const s=ve(e);return this.upsertConnectionFromOffer(s.offer,t,n??s.password)}async probeAndUpsertConnectionFromOfferUrl(e,t){const n=ve(e),s=n.offer,o=t??n.password,c=s.relay.useTls??(0,y.shouldUseTlsForDefaultHostedRelay)(s.relay.endpoint),l=(0,y.normalizeHostPort)(s.relay.endpoint),h={id:c?`relay:wss:${l}`:`relay:${l}`,type:"relay",relayEndpoint:l,useTls:c,daemonPublicKeyB64:s.daemonPublicKeyB64},u=Object.assign({serverId:s.serverId},o?{password:o}:{},{label:s.serverId,appearance:(0,p.defaultHostAppearance)(),lifecycle:{},connections:[h],preferredConnectionId:h.id,createdAt:new Date(0).toISOString(),updatedAt:new Date(0).toISOString()}),{client:S,hostname:f}=await this.deps.connectToDaemon({host:u,connection:h});await S.close().catch(()=>{});return{profile:await this.upsertConnectionFromOffer(s,f??void 0,o),serverId:s.serverId,hostname:f}}async importConnectionLink(e,t){if("openProject"===t){return{status:"connected",serverId:(await this.upsertConnectionFromOfferUrl(e)).serverId}}try{const{serverId:t}=await this.probeAndUpsertConnectionFromOfferUrl(e);return{status:"connected",serverId:t}}catch(e){if(!(0,b.getConnectionAuthFailureReason)(e))throw e;return{status:"password_required"}}}async upsertConnectionFromListen(e){const t=e.listenAddress.trim(),n=e.serverId.trim(),s=(0,u.connectionFromListen)(t);if(!s)throw new Error(`Unsupported listen address: ${e.listenAddress}`);if(!n)throw new Error("Desktop daemon did not return a server id.");return this.upsertHostConnection({serverId:n,label:e.hostname??void 0,connection:s})}async updateHost(e,t){const n=(new Date).toISOString(),s=this.hosts.map(s=>s.serverId===e?Object.assign({},t(s),{updatedAt:n}):s);this.setHostsAndSync(s),await this.persistHosts()}async renameHost(e,t){await this.updateHost(e,e=>Object.assign({},e,{label:t}))}async setHostPassword(t,s){await this.updateHost(t,t=>{const o=(0,n.default)(t,e);return s?Object.assign({},o,{password:s}):o})}async setHostColor(e,t){await this.updateHostAppearance(e,e=>Object.assign({},e,{appearance:Object.assign({},e.appearance,{color:t})}))}async setHostBadgeDisplay(e,t){await this.updateHostAppearance(e,e=>Object.assign({},e,{appearance:Object.assign({},e.appearance,{badgeDisplay:t})}))}updateHostAppearance(e,t){const n=this.hostAppearanceMutationTail.then(()=>this.applyHostAppearance(e,t));return this.hostAppearanceMutationTail=n.catch(()=>{}),n}async applyHostAppearance(e,t){const n=(new Date).toISOString(),s=this.hosts.map(s=>s.serverId===e?Object.assign({},t(s),{updatedAt:n}):s);await this.persistHosts(s),this.setHostsAndSync(s)}async removeHost(e){await this.revokePushNotifications({client:this.getClient(e),serverId:e});const t=this.hosts.filter(t=>t.serverId!==e);this.setHostsAndSync(t),await this.persistHosts()}async removeConnection(e,t){const n=this.hosts.find(t=>t.serverId===e);if(1===n?.connections.length&&n.connections[0]?.id===t)return void await this.removeHost(e);const s=(new Date).toISOString(),o=this.hosts.map(n=>{if(n.serverId!==e)return n;const o=n.connections.filter(e=>e.id!==t);if(0===o.length)return null;const c=n.preferredConnectionId===t?o[0]?.id??null:n.preferredConnectionId;return Object.assign({},n,{connections:o,preferredConnectionId:c,updatedAt:s})}).filter(e=>null!==e);this.setHostsAndSync(o),await this.persistHosts()}async upsertHostConnection(e){const t=(new Date).toISOString(),n=(0,u.upsertHostConnectionInProfiles)({profiles:this.hosts,serverId:e.serverId,label:e.label,connection:e.connection,password:e.password,now:t});this.setHostsAndSync(n,{initialConnectionByServerId:e.existingClient?new Map([[e.serverId,{connectionId:e.connection.id,existingClient:e.existingClient}]]):void 0}),this.persistHosts().catch(e=>console.error("[HostRuntime] Failed to persist host registry",e));const s=n.find(t=>t.serverId===e.serverId);if(!s)throw new Error(`Host ${e.serverId} was not inserted`);return s}setHostsAndSync(e,t){this.hosts=e,this.syncHosts(e,t),this.emitHostList()}async persistHosts(e=this.hosts){await this.storage.setItem(ue,JSON.stringify(e))}emitHostList(){this.hostListVersion+=1;for(const e of this.hostListListeners)e()}syncHosts(e,t){this.replicaCache.setHosts(e.map(e=>e.serverId)),G.projectIconCache.setHosts(e.map(e=>e.serverId));const n=new Set(e.map(e=>e.serverId));for(const[e,t]of this.controllers)n.has(e)||(this.controllers.delete(e),this.lastConnectionStatusByServer.delete(e),this.connectionStatusStartedAtByServer.delete(e),this.directorySyncByServer.get(e)?.dispose(),this.directorySyncByServer.delete(e),this.timelineReplicaByServer.delete(e),this.clearHostReplica(e),t.stop(),this.emit(e));for(const n of e){const e=t?.initialConnectionByServerId?.get(n.serverId),s=this.controllers.get(n.serverId);if(s){s.updateHost(n),e&&s.activateConnection(e).catch(()=>{e.existingClient.close().catch(()=>{})});continue}const o=new de({host:n,deps:this.deps,onReconcileServerId:(e,t)=>this.reconcileServerId(e,t)});this.controllers.set(n.serverId,o),L.useSessionStore.getState().initializeSession(n.serverId,null);const c=new V.DirectorySync(n.serverId,{onAgentStoppedRunning:e=>this.drainQueuedAgentMessage(n.serverId,e),markAgentLoading:()=>o.markAgentDirectorySyncLoading(),markAgentReady:()=>o.markAgentDirectorySyncReady(),markAgentError:e=>o.markAgentDirectorySyncError(e)},this.replicaCache);this.directorySyncByServer.set(n.serverId,c),this.timelineReplicaByServer.set(n.serverId,(0,N.createTimelineReplica)({serverId:n.serverId,storage:this.replicaCache,prepareAgent:e=>c.prepareAgentRoute(e)}));const l=o.getSnapshot();this.lastConnectionStatusByServer.set(n.serverId,l.connectionStatus),this.connectionStatusStartedAtByServer.set(n.serverId,Date.now()),o.subscribe(()=>{const e=o.getSnapshot();this.syncSessionReplica(e.serverId,e),this.syncDirectoryConnection(e.serverId),this.emit(e.serverId)}),o.start(e?{initialConnection:e}:{}).catch(e=>{const t=e instanceof Error?e.message:String(e);o.markStartupError(t)}),this.emit(n.serverId)}}syncSessionReplica(e,t){if(!t.client)return;const n=L.useSessionStore.getState();n.initializeSession(e,t.client,t.clientGeneration),n.updateSessionClient(e,t.client,t.clientGeneration)}clearHostReplica(e){L.useSessionStore.getState().clearSession(e),T.useWorkspaceSetupStore.getState().clearServer(e)}syncDirectoryConnection(e){const t=this.controllers.get(e);if(!t)return this.lastConnectionStatusByServer.delete(e),void this.connectionStatusStartedAtByServer.delete(e);const n=t.getSnapshot(),s=this.directorySyncByServer.get(e);s?.connectionChanged({client:n.client,status:"online"===n.connectionStatus?"online":"offline",source:{clientGeneration:n.clientGeneration,connectionEpoch:n.connectionEpoch}});const o=this.lastConnectionStatusByServer.get(e),c=o!==n.connectionStatus,l="online"!==n.connectionStatus&&"idle"!==n.connectionStatus;!c||void 0!==o&&"online"!==o&&"idle"!==o&&l||this.connectionStatusStartedAtByServer.set(e,Date.now()),this.lastConnectionStatusByServer.set(e,n.connectionStatus);"online"===n.connectionStatus&&"online"!==o&&(L.useSessionStore.getState().bumpHistorySyncGeneration(e),(0,_.invalidateCheckoutGitQueriesForServer)(M.queryClient,e),(0,B.invalidateServerDataQueriesAfterReconnect)({queryClient:M.queryClient,serverId:e}),M.queryClient.invalidateQueries({queryKey:k.schedulesQueryBaseKey}))}drainQueuedAgentMessage(e,t){const n=`${e}:${t}`;if(this.queuedAgentDrainInFlight.has(n))return;const s=L.useSessionStore.getState().sessions[e],o=s?.queuedMessages.get(t),c=s?.client;if(!c||!o?.length||!0===s.initializingAgents.get(t))return;this.queuedAgentDrainInFlight.add(n);const l=o[0];(0,j.sendQueuedComposerMessageNow)({agentId:t,messageId:l.id,queue:{read:t=>L.useSessionStore.getState().sessions[e]?.queuedMessages.get(t)??[],write:t=>L.useSessionStore.getState().setQueuedMessages(e,t)},submitMessage:async({text:n,attachments:s})=>{const o=!0===L.useSessionStore.getState().sessions[e]?.serverInfo?.features?.forgeSearch;await(0,j.dispatchComposerAgentMessage)({client:c,agentId:t,text:n,attachments:s,attachmentSubmitFormat:(0,U.resolveComposerAttachmentSubmitFormat)({supportsForgeAttachments:o}),encodeImages:x.encodeImages,submission:(0,q.createMessageSubmissionWriter)(e)})}}).then(n=>("failed"===n.status&&console.error("[HostRuntime] failed to drain queued agent message",{serverId:e,agentId:t,error:n.errorMessage}),n)).finally(()=>{this.queuedAgentDrainInFlight.delete(n)})}applyAgentTurnLiveness(e,t,n){this.directorySyncByServer.get(e)?.applyAgentTurnLiveness(t,n)}beginAgentCancellation(e,t){const n=++this.nextCancellationRequestId;return this.applyAgentTurnLiveness(e,t,{type:"cancellation_started",requestId:n}),n}settleAgentCancellation(e,t,n){this.applyAgentTurnLiveness(e,t,{type:"cancellation_settled",requestId:n})}acceptAgentSnapshot(e,t){return this.requireDirectory(e).acceptAgent(t)}archiveAgentSnapshot(e,t,n){this.requireDirectory(e).archiveAgent(t,n)}restoreAgentSnapshot(e,t,n){const s=this.requireDirectory(e);n?s.acceptAgent(n):s.removeAgent(t)}acceptWorkspaceSnapshots(e,t){this.requireDirectory(e).acceptWorkspaces(t)}acceptProjectSnapshot(e,t){this.requireDirectory(e).acceptProject(t)}removeWorkspaceSnapshot(e,t){this.requireDirectory(e).removeWorkspace(t)}requireDirectory(e){const t=this.directorySyncByServer.get(e);if(!t)throw new Error(`Unknown host runtime for serverId ${e}`);return t}getSnapshot(e){return this.controllers.get(e)?.getSnapshot()??null}getConnectionStatusSince(e){return this.connectionStatusStartedAtByServer.get(e)??null}getVersion(){return this.version}getClient(e){return this.controllers.get(e)?.getClient()??null}subscribe(e,t){const n=this.serverListeners.get(e)??new Set;return n.add(t),this.serverListeners.set(e,n),()=>{const n=this.serverListeners.get(e);n&&(n.delete(t),0===n.size&&this.serverListeners.delete(e))}}subscribeAll(e){return this.globalListeners.add(e),()=>{this.globalListeners.delete(e)}}getEarliestOnlineHostServerId(){let e=null,t=null;for(const n of this.hosts){const s=this.getSnapshot(n.serverId);X(s)&&s?.lastOnlineAt&&((!t||s.lastOnlineAt<t)&&(t=s.lastOnlineAt,e=n.serverId))}return e}ensureConnectedAll(e){for(const t of this.controllers.values())t.ensureConnected(e)}setAppVisible(e){e?this.ensureConnectedAll({verify:!0}):this.replicaCache.flush()}runProbeCycleNow(e){return e?this.controllers.get(e)?.runProbeCycleNow()??Promise.resolve():Promise.all(Array.from(this.controllers.values(),e=>e.runProbeCycleNow())).then(()=>{})}async refreshAgentDirectory(e){const t=this.directorySyncByServer.get(e.serverId);if(!t)throw new Error(`Unknown host runtime for serverId ${e.serverId}`);return t.refreshAgents(e)}async refreshWorkspaceDirectory(e){const t=this.directorySyncByServer.get(e.serverId);if(!t)throw new Error(`Unknown host runtime for serverId ${e.serverId}`);await t.refreshWorkspaces({subscribe:e.subscribe})}async refreshDirectories(e){const t=this.directorySyncByServer.get(e);if(!t)throw new Error(`Unknown host runtime for serverId ${e}`);await t.refreshDemand()}acquireDirectoryDemand(e){const t=this.directorySyncByServer.get(e);if(!t)return()=>{};const n={};return t.setDemand(n,!0),()=>t.setDemand(n,!1)}async prepareAgentRoute(e,t){const n=this.directorySyncByServer.get(e);if(!n)throw new Error(`Unknown host runtime for serverId ${e}`);await n.prepareAgentRoute(t)}async prepareWorkspaceRoute(e,t){const n=this.directorySyncByServer.get(e);if(!n)throw new Error(`Unknown host runtime for serverId ${e}`);await n.prepareWorkspaceRoute(t)}async prepareAgentTimeline(e,t){const n=this.timelineReplicaByServer.get(e);if(!n)throw new Error(`Unknown host runtime for serverId ${e}`);await n.prepare(t)}async fetchAgentTimeline(e,t,n){const s=this.directorySyncByServer.get(e);if(!s)throw new Error(`Unknown host runtime for serverId ${e}`);const o=L.useSessionStore.getState().sessions[e]?.viewedTimelineSync,c=await s.fetchTimeline(t,n);return o&&L.useSessionStore.getState().sessions[e]?.viewedTimelineSync===o&&(o.flushStreamAgent(t),o.applyTimelineResponse(c)),c}createViewedTimelineOwner(e,t){const n=this.directorySyncByServer.get(e);if(!n)throw new Error(`Unknown host runtime for serverId ${e}`);const s=this.timelineReplicaByServer.get(e);if(!s)throw new Error(`Unknown host runtime for serverId ${e}`);return(0,N.createViewedTimelineOwner)({serverId:e,replica:s,replaceDemandedAgentIds:e=>n.setAgentRouteDemand(e),drainQueuedAgentMessage:t=>this.drainQueuedAgentMessage(e,t),ports:t})}emit(e){this.version+=1;const t=this.serverListeners.get(e);if(t){for(const e of t)e();for(const e of this.globalListeners)e()}else for(const e of this.globalListeners)e()}}let Ae=null;const He="__paseoHostRuntimeStore";function Re(){if(Ae)return Ae;const e=Reflect.get(globalThis,He);return e instanceof Ie?(Ae=e,e):(Ae=new Ie,Reflect.set(globalThis,He,Ae),Ae)}},3466,[35,453,36,884,3467,3468,3518,3521,3523,3463,3524,3525,880,3527,3528,2898,2979,3531,3529,881,3532,3479,3491,3420,3533,3540,848,3542,3553,3571,3573,3584,3575,3585,3591,3621,3625,3626,3630,3632,3634,3635]);
|
|
15112
15112
|
__d(function(g,r,_i,_a,m,e,d){'use strict';m.exports=function t(n,f){if(n===f)return!0;if(n&&f&&'object'==typeof n&&'object'==typeof f){if(n.constructor!==f.constructor)return!1;var i,o,u;if(Array.isArray(n)){if((i=n.length)!=f.length)return!1;for(o=i;0!==o--;)if(!t(n[o],f[o]))return!1;return!0}if(n instanceof Map&&f instanceof Map){if(n.size!==f.size)return!1;for(o of n.entries())if(!f.has(o[0]))return!1;for(o of n.entries())if(!t(o[1],f.get(o[0])))return!1;return!0}if(n instanceof Set&&f instanceof Set){if(n.size!==f.size)return!1;for(o of n.entries())if(!f.has(o[0]))return!1;return!0}if(ArrayBuffer.isView(n)&&ArrayBuffer.isView(f)){if((i=n.length)!=f.length)return!1;for(o=i;0!==o--;)if(n[o]!==f[o])return!1;return!0}if(n.constructor===RegExp)return n.source===f.source&&n.flags===f.flags;if(n.valueOf!==Object.prototype.valueOf)return n.valueOf()===f.valueOf();if(n.toString!==Object.prototype.toString)return n.toString()===f.toString();if((i=(u=Object.keys(n)).length)!==Object.keys(f).length)return!1;for(o=i;0!==o--;)if(!Object.prototype.hasOwnProperty.call(f,u[o]))return!1;for(o=i;0!==o--;){var s=u[o];if(!t(n[s],f[s]))return!1}return!0}return n!=n&&f!=f}},3467,[]);
|
|
Binary file
|
|
Binary file
|
|
@@ -85,6 +85,6 @@
|
|
|
85
85
|
<body>
|
|
86
86
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
|
87
87
|
<div id="root"></div>
|
|
88
|
-
<script src="/_expo/static/js/web/index-
|
|
88
|
+
<script src="/_expo/static/js/web/index-48b52108bb348a6334547c3c03400d50.js" defer></script>
|
|
89
89
|
</body>
|
|
90
90
|
</html>
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpaseo/server",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "Paseo backend server",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist/server",
|
|
@@ -107,11 +107,11 @@
|
|
|
107
107
|
"@agentclientprotocol/sdk": "^0.17.1",
|
|
108
108
|
"@anthropic-ai/claude-agent-sdk": "0.3.246",
|
|
109
109
|
"@anthropic-ai/sdk": "^0.104.2",
|
|
110
|
-
"@getpaseo/client": "0.10.
|
|
111
|
-
"@getpaseo/highlight": "0.10.
|
|
112
|
-
"@getpaseo/plugin": "0.10.
|
|
113
|
-
"@getpaseo/protocol": "0.10.
|
|
114
|
-
"@getpaseo/relay": "0.10.
|
|
110
|
+
"@getpaseo/client": "0.10.2",
|
|
111
|
+
"@getpaseo/highlight": "0.10.2",
|
|
112
|
+
"@getpaseo/plugin": "0.10.2",
|
|
113
|
+
"@getpaseo/protocol": "0.10.2",
|
|
114
|
+
"@getpaseo/relay": "0.10.2",
|
|
115
115
|
"@isaacs/ttlcache": "^2.1.4",
|
|
116
116
|
"@modelcontextprotocol/sdk": "1.29.0",
|
|
117
117
|
"@opencode-ai/sdk": "1.14.46",
|