saeeol 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +14 -14
- package/src/cli/cmd/tui/component/dialog/dialog-agent.tsx +32 -0
- package/src/cli/cmd/tui/component/dialog/dialog-command.tsx +190 -0
- package/src/cli/cmd/tui/component/dialog/dialog-console-org.tsx +103 -0
- package/src/cli/cmd/tui/component/dialog/dialog-go-upsell.tsx +159 -0
- package/src/cli/cmd/tui/component/dialog/dialog-mcp.tsx +86 -0
- package/src/cli/cmd/tui/component/dialog/dialog-model.tsx +238 -0
- package/src/cli/cmd/tui/component/dialog/dialog-provider.tsx +343 -0
- package/src/cli/cmd/tui/component/dialog/dialog-session-delete-failed.tsx +103 -0
- package/src/cli/cmd/tui/component/dialog/dialog-session-list.tsx +301 -0
- package/src/cli/cmd/tui/component/dialog/dialog-session-rename.tsx +35 -0
- package/src/cli/cmd/tui/component/dialog/dialog-skill.tsx +37 -0
- package/src/cli/cmd/tui/component/dialog/dialog-stash.tsx +87 -0
- package/src/cli/cmd/tui/component/dialog/dialog-status.tsx +190 -0
- package/src/cli/cmd/tui/component/dialog/dialog-tag.tsx +44 -0
- package/src/cli/cmd/tui/component/dialog/dialog-theme-list.tsx +50 -0
- package/src/cli/cmd/tui/component/dialog/dialog-variant.tsx +39 -0
- package/src/cli/cmd/tui/component/dialog/dialog-workspace-create.tsx +200 -0
- package/src/cli/cmd/tui/component/dialog/dialog-workspace-unavailable.tsx +81 -0
- package/src/cli/cmd/tui/component/dialog-agent.tsx +1 -32
- package/src/cli/cmd/tui/component/dialog-command.tsx +1 -190
- package/src/cli/cmd/tui/component/dialog-console-org.tsx +1 -103
- package/src/cli/cmd/tui/component/dialog-go-upsell.tsx +1 -159
- package/src/cli/cmd/tui/component/dialog-mcp.tsx +1 -86
- package/src/cli/cmd/tui/component/dialog-model.tsx +1 -238
- package/src/cli/cmd/tui/component/dialog-provider.tsx +1 -343
- package/src/cli/cmd/tui/component/dialog-session-delete-failed.tsx +1 -103
- package/src/cli/cmd/tui/component/dialog-session-list.tsx +1 -301
- package/src/cli/cmd/tui/component/dialog-session-rename.tsx +1 -35
- package/src/cli/cmd/tui/component/dialog-skill.tsx +1 -37
- package/src/cli/cmd/tui/component/dialog-stash.tsx +1 -87
- package/src/cli/cmd/tui/component/dialog-status.tsx +1 -190
- package/src/cli/cmd/tui/component/dialog-tag.tsx +1 -44
- package/src/cli/cmd/tui/component/dialog-theme-list.tsx +1 -50
- package/src/cli/cmd/tui/component/dialog-variant.tsx +1 -39
- package/src/cli/cmd/tui/component/dialog-workspace-create.tsx +1 -200
- package/src/cli/cmd/tui/component/dialog-workspace-unavailable.tsx +1 -81
- package/src/session/compaction-helpers.ts +1 -169
- package/src/session/compaction.ts +1 -712
- package/src/session/core/compaction/compaction-helpers.ts +169 -0
- package/src/session/core/compaction/compaction.ts +712 -0
- package/src/session/core/compaction/overflow.ts +28 -0
- package/src/session/core/instruction.ts +234 -0
- package/src/session/core/llm.ts +504 -0
- package/src/session/core/network.ts +392 -0
- package/src/session/core/processor.ts +731 -0
- package/src/session/core/projectors.ts +139 -0
- package/src/session/core/resolve-tools.ts +241 -0
- package/src/session/core/retry.ts +149 -0
- package/src/session/core/revert.ts +173 -0
- package/src/session/core/run-state.ts +110 -0
- package/src/session/core/schema.ts +35 -0
- package/src/session/core/session-types.ts +160 -0
- package/src/session/core/session.sql.ts +124 -0
- package/src/session/core/session.ts +948 -0
- package/src/session/core/shell-exec.ts +205 -0
- package/src/session/core/status.ts +100 -0
- package/src/session/core/subtask.ts +268 -0
- package/src/session/core/summary.ts +173 -0
- package/src/session/core/system.ts +114 -0
- package/src/session/core/todo.ts +86 -0
- package/src/session/core/user-part.ts +293 -0
- package/src/session/instruction.ts +1 -234
- package/src/session/llm.ts +1 -504
- package/src/session/message/message-errors.ts +83 -0
- package/src/session/message/message-parts.ts +89 -0
- package/src/session/message/message-query.ts +107 -0
- package/src/session/message/message-transform.ts +156 -0
- package/src/session/message/message-types.ts +68 -0
- package/src/session/message/message-v2.ts +73 -0
- package/src/session/message/message.ts +192 -0
- package/src/session/message-errors.ts +1 -83
- package/src/session/message-parts.ts +1 -89
- package/src/session/message-query.ts +1 -107
- package/src/session/message-transform.ts +1 -156
- package/src/session/message-types.ts +1 -68
- package/src/session/message-v2.ts +1 -73
- package/src/session/message.ts +1 -192
- package/src/session/network.ts +1 -392
- package/src/session/overflow.ts +1 -28
- package/src/session/processor.ts +1 -731
- package/src/session/projectors.ts +2 -139
- package/src/session/prompt/prompt-command.ts +93 -0
- package/src/session/prompt/prompt-loop.ts +299 -0
- package/src/session/prompt/prompt-model.ts +44 -0
- package/src/session/prompt/prompt-reminders.ts +120 -0
- package/src/session/prompt/prompt-resolve.ts +42 -0
- package/src/session/prompt/prompt-schemas.ts +128 -0
- package/src/session/prompt/prompt-title.ts +55 -0
- package/src/session/prompt/prompt-types.ts +47 -0
- package/src/session/prompt/prompt-user-msg.ts +80 -0
- package/src/session/prompt/prompt.ts +211 -0
- package/src/session/prompt-command.ts +1 -93
- package/src/session/prompt-loop.ts +1 -299
- package/src/session/prompt-model.ts +1 -44
- package/src/session/prompt-reminders.ts +1 -120
- package/src/session/prompt-resolve.ts +1 -42
- package/src/session/prompt-schemas.ts +1 -128
- package/src/session/prompt-title.ts +1 -55
- package/src/session/prompt-types.ts +1 -47
- package/src/session/prompt-user-msg.ts +1 -80
- package/src/session/prompt.ts +1 -211
- package/src/session/resolve-tools.ts +1 -241
- package/src/session/retry.ts +1 -149
- package/src/session/revert.ts +1 -173
- package/src/session/run-state.ts +1 -110
- package/src/session/schema.ts +1 -35
- package/src/session/session-types.ts +1 -160
- package/src/session/session.sql.ts +1 -124
- package/src/session/session.ts +1 -948
- package/src/session/shell-exec.ts +1 -205
- package/src/session/status.ts +1 -100
- package/src/session/subtask.ts +1 -268
- package/src/session/summary.ts +1 -173
- package/src/session/system.ts +1 -114
- package/src/session/todo.ts +1 -86
- package/src/session/user-part.ts +1 -293
- package/src/tool/apply_patch.ts +1 -334
- package/src/tool/bash.ts +1 -656
- package/src/tool/core/external-directory.ts +55 -0
- package/src/tool/core/invalid.ts +21 -0
- package/src/tool/core/recall.ts +164 -0
- package/src/tool/core/recall.txt +12 -0
- package/src/tool/core/schema.ts +16 -0
- package/src/tool/core/tool.ts +162 -0
- package/src/tool/core/truncate.ts +160 -0
- package/src/tool/core/truncation-dir.ts +4 -0
- package/src/tool/diagnostics.ts +1 -20
- package/src/tool/edit-replacers.ts +1 -288
- package/src/tool/edit-utils.ts +1 -86
- package/src/tool/edit.ts +1 -262
- package/src/tool/external-directory.ts +1 -55
- package/src/tool/file/apply_patch.ts +334 -0
- package/src/tool/file/apply_patch.txt +33 -0
- package/src/tool/file/bash.ts +656 -0
- package/src/tool/file/bash.txt +119 -0
- package/src/tool/file/edit-replacers.ts +288 -0
- package/src/tool/file/edit-utils.ts +86 -0
- package/src/tool/file/edit.ts +262 -0
- package/src/tool/file/edit.txt +10 -0
- package/src/tool/file/read.ts +389 -0
- package/src/tool/file/read.txt +14 -0
- package/src/tool/file/write.ts +114 -0
- package/src/tool/file/write.txt +8 -0
- package/src/tool/glob.ts +1 -115
- package/src/tool/grep.ts +1 -151
- package/src/tool/integration/diagnostics.ts +20 -0
- package/src/tool/integration/lsp.ts +113 -0
- package/src/tool/integration/lsp.txt +24 -0
- package/src/tool/integration/mcp-exa.ts +73 -0
- package/src/tool/integration/package.ts +168 -0
- package/src/tool/integration/registry.ts +375 -0
- package/src/tool/invalid.ts +1 -21
- package/src/tool/lsp.ts +1 -113
- package/src/tool/mcp-exa.ts +1 -73
- package/src/tool/package.ts +1 -168
- package/src/tool/plan.ts +1 -30
- package/src/tool/question.ts +1 -52
- package/src/tool/read.ts +1 -389
- package/src/tool/recall.ts +1 -164
- package/src/tool/registry.ts +1 -375
- package/src/tool/schema.ts +1 -16
- package/src/tool/search/glob.ts +115 -0
- package/src/tool/search/glob.txt +6 -0
- package/src/tool/search/grep.ts +151 -0
- package/src/tool/search/grep.txt +8 -0
- package/src/tool/search/warpgrep.ts +107 -0
- package/src/tool/search/warpgrep.txt +10 -0
- package/src/tool/search/webfetch.ts +202 -0
- package/src/tool/search/webfetch.txt +13 -0
- package/src/tool/search/websearch.ts +71 -0
- package/src/tool/search/websearch.txt +14 -0
- package/src/tool/skill.ts +1 -91
- package/src/tool/task.ts +1 -197
- package/src/tool/todo.ts +1 -62
- package/src/tool/tool.ts +1 -162
- package/src/tool/truncate.ts +1 -160
- package/src/tool/truncation-dir.ts +1 -4
- package/src/tool/warpgrep.ts +1 -107
- package/src/tool/webfetch.ts +1 -202
- package/src/tool/websearch.ts +1 -71
- package/src/tool/workflow/plan-enter.txt +14 -0
- package/src/tool/workflow/plan-exit.txt +13 -0
- package/src/tool/workflow/plan.ts +30 -0
- package/src/tool/workflow/question.ts +52 -0
- package/src/tool/workflow/question.txt +11 -0
- package/src/tool/workflow/skill.ts +91 -0
- package/src/tool/workflow/skill.txt +5 -0
- package/src/tool/workflow/task.ts +197 -0
- package/src/tool/workflow/task.txt +57 -0
- package/src/tool/workflow/todo.ts +62 -0
- package/src/tool/workflow/todowrite.txt +167 -0
- package/src/tool/write.ts +1 -114
package/src/session/network.ts
CHANGED
|
@@ -1,392 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { Bus } from "../bus"
|
|
3
|
-
import { BusEvent } from "../bus/bus-event"
|
|
4
|
-
import { QuestionID } from "../question/schema"
|
|
5
|
-
import { SessionID } from "../session/schema"
|
|
6
|
-
import { InstanceState } from "@/effect/instance-state"
|
|
7
|
-
import { makeRuntime } from "@/effect/run-service"
|
|
8
|
-
import * as Log from "@saeeol/core/util/log"
|
|
9
|
-
import { fn } from "../util/fn"
|
|
10
|
-
import { MCP } from "../mcp"
|
|
11
|
-
import { zod } from "@/util/effect-zod"
|
|
12
|
-
import { withStatics } from "@/util/schema"
|
|
13
|
-
import z from "zod"
|
|
14
|
-
|
|
15
|
-
export namespace SessionNetwork {
|
|
16
|
-
const log = Log.create({ service: "session.network" })
|
|
17
|
-
const codes = new Set([
|
|
18
|
-
"ECONNRESET",
|
|
19
|
-
"ECONNREFUSED",
|
|
20
|
-
"ENOTFOUND",
|
|
21
|
-
"EAI_AGAIN",
|
|
22
|
-
"ETIMEDOUT",
|
|
23
|
-
"ENETUNREACH",
|
|
24
|
-
"EHOSTUNREACH",
|
|
25
|
-
"ENETDOWN",
|
|
26
|
-
"UND_ERR_CONNECT_TIMEOUT",
|
|
27
|
-
"UND_ERR_HEADERS_TIMEOUT",
|
|
28
|
-
"UND_ERR_SOCKET",
|
|
29
|
-
"ERR_SOCKET_CONNECTION_TIMEOUT",
|
|
30
|
-
])
|
|
31
|
-
const urls = ["https://saeeol.ai", "https://example.com", "https://cloudflare.com/cdn-cgi/trace"]
|
|
32
|
-
const POLL_MS = 3_000
|
|
33
|
-
const PROBE_MS = 5_000
|
|
34
|
-
const RESUME_MS = 10_000
|
|
35
|
-
|
|
36
|
-
function chain(err: unknown, seen = new Set<unknown>()): unknown[] {
|
|
37
|
-
if (err === undefined) return []
|
|
38
|
-
if (typeof err === "object" && err !== null) {
|
|
39
|
-
if (seen.has(err)) return []
|
|
40
|
-
seen.add(err)
|
|
41
|
-
}
|
|
42
|
-
const cause = typeof err === "object" && err !== null ? (err as { cause?: unknown }).cause : undefined
|
|
43
|
-
const kids =
|
|
44
|
-
typeof err === "object" && err !== null && Array.isArray((err as { errors?: unknown }).errors)
|
|
45
|
-
? ((err as { errors: unknown[] }).errors ?? [])
|
|
46
|
-
: []
|
|
47
|
-
return [err, ...chain(cause, seen), ...kids.flatMap((item) => chain(item, seen))]
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function msgs(err: unknown) {
|
|
51
|
-
return chain(err).flatMap((item) => {
|
|
52
|
-
const msg =
|
|
53
|
-
item instanceof Error
|
|
54
|
-
? item.message
|
|
55
|
-
: typeof item === "string"
|
|
56
|
-
? item
|
|
57
|
-
: typeof item === "object" && item !== null && typeof (item as { message?: unknown }).message === "string"
|
|
58
|
-
? (item as { message: string }).message
|
|
59
|
-
: undefined
|
|
60
|
-
return msg ? [msg] : []
|
|
61
|
-
})
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export const Wait = Schema.Struct({
|
|
65
|
-
id: QuestionID,
|
|
66
|
-
sessionID: SessionID,
|
|
67
|
-
message: Schema.String,
|
|
68
|
-
restored: Schema.Boolean,
|
|
69
|
-
time: Schema.Struct({
|
|
70
|
-
created: Schema.Number,
|
|
71
|
-
restored: Schema.optional(Schema.Number),
|
|
72
|
-
}),
|
|
73
|
-
})
|
|
74
|
-
.annotate({ identifier: "SessionNetworkWait" })
|
|
75
|
-
.pipe(withStatics((s) => ({ zod: zod(s) })))
|
|
76
|
-
export type Wait = Schema.Schema.Type<typeof Wait>
|
|
77
|
-
|
|
78
|
-
export const Event = {
|
|
79
|
-
Asked: BusEvent.define("session.network.asked", Wait),
|
|
80
|
-
Replied: BusEvent.define(
|
|
81
|
-
"session.network.replied",
|
|
82
|
-
Schema.Struct({
|
|
83
|
-
sessionID: SessionID,
|
|
84
|
-
requestID: QuestionID,
|
|
85
|
-
}),
|
|
86
|
-
),
|
|
87
|
-
Rejected: BusEvent.define(
|
|
88
|
-
"session.network.rejected",
|
|
89
|
-
Schema.Struct({
|
|
90
|
-
sessionID: SessionID,
|
|
91
|
-
requestID: QuestionID,
|
|
92
|
-
}),
|
|
93
|
-
),
|
|
94
|
-
Restored: BusEvent.define(
|
|
95
|
-
"session.network.restored",
|
|
96
|
-
Schema.Struct({
|
|
97
|
-
sessionID: SessionID,
|
|
98
|
-
requestID: QuestionID,
|
|
99
|
-
time: Schema.Number,
|
|
100
|
-
}),
|
|
101
|
-
),
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
interface StateShape {
|
|
105
|
-
pending: Map<
|
|
106
|
-
QuestionID,
|
|
107
|
-
{
|
|
108
|
-
info: Types.Mutable<Wait>
|
|
109
|
-
abort: AbortSignal
|
|
110
|
-
resolve: () => void
|
|
111
|
-
reject: (e: unknown) => void
|
|
112
|
-
}
|
|
113
|
-
>
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
class StateService extends Context.Service<StateService, { readonly get: () => Effect.Effect<StateShape> }>()(
|
|
117
|
-
"@saeeol/SessionNetwork.State",
|
|
118
|
-
) {}
|
|
119
|
-
|
|
120
|
-
const stateLayer = Layer.effect(
|
|
121
|
-
StateService,
|
|
122
|
-
Effect.gen(function* () {
|
|
123
|
-
const is = yield* InstanceState.make(
|
|
124
|
-
Effect.fn("SessionNetwork.state")(function* () {
|
|
125
|
-
return { pending: new Map() } as StateShape
|
|
126
|
-
}),
|
|
127
|
-
)
|
|
128
|
-
return StateService.of({
|
|
129
|
-
get: () => InstanceState.get(is),
|
|
130
|
-
})
|
|
131
|
-
}),
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
const stateRuntime = makeRuntime(StateService, stateLayer)
|
|
135
|
-
const state = (): Promise<StateShape> => stateRuntime.runPromise((svc) => svc.get())
|
|
136
|
-
|
|
137
|
-
export function code(err: unknown) {
|
|
138
|
-
for (const item of chain(err)) {
|
|
139
|
-
const code = (item as { code?: unknown })?.code
|
|
140
|
-
if (typeof code === "string") return code
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export function disconnected(err: unknown) {
|
|
145
|
-
for (const item of chain(err)) {
|
|
146
|
-
const match = (item as { code?: unknown })?.code
|
|
147
|
-
if (typeof match === "string" && codes.has(match)) return true
|
|
148
|
-
}
|
|
149
|
-
for (const item of chain(err)) {
|
|
150
|
-
if (item instanceof DOMException && item.name === "TimeoutError") return true
|
|
151
|
-
}
|
|
152
|
-
return msgs(err).some((item) => {
|
|
153
|
-
const msg = item.toLowerCase()
|
|
154
|
-
if (msg.includes("load failed")) return true
|
|
155
|
-
if (msg.includes("failed to fetch")) return true
|
|
156
|
-
if (msg.includes("fetch failed")) return true
|
|
157
|
-
if (msg.includes("network connection was lost")) return true
|
|
158
|
-
if (msg.includes("network is unreachable")) return true
|
|
159
|
-
if (msg.includes("socket connection")) return true
|
|
160
|
-
if (msg.includes("socket hang up")) return true
|
|
161
|
-
if (msg.includes("connection timed out")) return true
|
|
162
|
-
if (msg.includes("connection terminated")) return true
|
|
163
|
-
if (msg.includes("connect timeout")) return true
|
|
164
|
-
if (msg.includes("unable to connect") && msg.includes("access the url")) return true
|
|
165
|
-
return false
|
|
166
|
-
})
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export function message(err: unknown) {
|
|
170
|
-
for (const item of chain(err)) {
|
|
171
|
-
if (item instanceof DOMException && item.name === "TimeoutError") return "Request timed out"
|
|
172
|
-
}
|
|
173
|
-
const match = code(err)
|
|
174
|
-
if (match === "ECONNRESET") return "Connection reset by server"
|
|
175
|
-
if (match === "ECONNREFUSED") return "Connection refused"
|
|
176
|
-
if (match === "ENOTFOUND") return "Host not found"
|
|
177
|
-
if (match === "EAI_AGAIN") return "DNS lookup failed"
|
|
178
|
-
if (match === "ETIMEDOUT") return "Connection timed out"
|
|
179
|
-
if (match === "ENETUNREACH") return "Network is unreachable"
|
|
180
|
-
if (match === "EHOSTUNREACH") return "Host is unreachable"
|
|
181
|
-
if (match === "ENETDOWN") return "Network is down"
|
|
182
|
-
if (match === "UND_ERR_CONNECT_TIMEOUT") return "Connection timed out"
|
|
183
|
-
if (match === "UND_ERR_HEADERS_TIMEOUT") return "Request timed out"
|
|
184
|
-
if (match === "UND_ERR_SOCKET") return "Network socket failed"
|
|
185
|
-
if (match === "ERR_SOCKET_CONNECTION_TIMEOUT") return "Connection timed out"
|
|
186
|
-
const matchMsg = msgs(err).find((item) => {
|
|
187
|
-
const msg = item.toLowerCase()
|
|
188
|
-
return msg.includes("unable to connect") && msg.includes("access the url")
|
|
189
|
-
})
|
|
190
|
-
if (matchMsg) return matchMsg
|
|
191
|
-
if (msgs(err).some((item) => item.toLowerCase().includes("failed to fetch"))) return "Network request failed"
|
|
192
|
-
if (msgs(err).some((item) => item.toLowerCase().includes("fetch failed"))) return "Network request failed"
|
|
193
|
-
return "Network connection failed"
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
async function check(url: string) {
|
|
197
|
-
const ctl = new AbortController()
|
|
198
|
-
const timer = setTimeout(() => ctl.abort(), PROBE_MS)
|
|
199
|
-
return fetch(url, {
|
|
200
|
-
method: "HEAD",
|
|
201
|
-
signal: ctl.signal,
|
|
202
|
-
})
|
|
203
|
-
.then((res) => res.status < 500)
|
|
204
|
-
.catch(() => false)
|
|
205
|
-
.finally(() => clearTimeout(timer))
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
async function probe() {
|
|
209
|
-
return Promise.any(
|
|
210
|
-
urls.map(async (url) => {
|
|
211
|
-
if (await check(url)) return true
|
|
212
|
-
throw new Error("network probe failed")
|
|
213
|
-
}),
|
|
214
|
-
).catch(() => false)
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
async function delay(abort: AbortSignal) {
|
|
218
|
-
if (abort.aborted) return false
|
|
219
|
-
return new Promise<boolean>((resolve) => {
|
|
220
|
-
const timer = setTimeout(() => {
|
|
221
|
-
abort.removeEventListener("abort", onAbort)
|
|
222
|
-
resolve(true)
|
|
223
|
-
}, RESUME_MS)
|
|
224
|
-
function onAbort() {
|
|
225
|
-
clearTimeout(timer)
|
|
226
|
-
resolve(false)
|
|
227
|
-
}
|
|
228
|
-
abort.addEventListener("abort", onAbort, { once: true })
|
|
229
|
-
})
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
async function resume(input: { requestID: QuestionID; abort: AbortSignal }) {
|
|
233
|
-
if (!(await delay(input.abort))) return
|
|
234
|
-
const s = await state()
|
|
235
|
-
const req = s.pending.get(input.requestID)
|
|
236
|
-
if (!req || !req.info.restored) return
|
|
237
|
-
await reply({ requestID: input.requestID })
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
async function watch(input: { requestID: QuestionID; abort: AbortSignal }) {
|
|
241
|
-
while (!input.abort.aborted) {
|
|
242
|
-
await Bun.sleep(POLL_MS)
|
|
243
|
-
if (input.abort.aborted) return
|
|
244
|
-
const s = await state()
|
|
245
|
-
const req = s.pending.get(input.requestID)
|
|
246
|
-
if (!req || req.info.restored) return
|
|
247
|
-
const ok = await probe().catch(() => false)
|
|
248
|
-
if (!ok) continue
|
|
249
|
-
await restore({ requestID: input.requestID })
|
|
250
|
-
return
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export async function ask(input: { sessionID: SessionID; message: string; abort: AbortSignal }) {
|
|
255
|
-
const s = await state()
|
|
256
|
-
const id = QuestionID.ascending()
|
|
257
|
-
const info: Wait = {
|
|
258
|
-
id,
|
|
259
|
-
sessionID: input.sessionID,
|
|
260
|
-
message: input.message,
|
|
261
|
-
restored: false,
|
|
262
|
-
time: {
|
|
263
|
-
created: Date.now(),
|
|
264
|
-
},
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const promise = new Promise<void>((resolve, reject) => {
|
|
268
|
-
const onAbort = () => {
|
|
269
|
-
if (!s.pending.has(id)) return
|
|
270
|
-
input.abort.removeEventListener("abort", onAbort)
|
|
271
|
-
s.pending.delete(id)
|
|
272
|
-
Bus.publish(Event.Rejected, {
|
|
273
|
-
sessionID: input.sessionID,
|
|
274
|
-
requestID: id,
|
|
275
|
-
})
|
|
276
|
-
reject(new DOMException("Aborted", "AbortError"))
|
|
277
|
-
}
|
|
278
|
-
s.pending.set(id, {
|
|
279
|
-
info,
|
|
280
|
-
abort: input.abort,
|
|
281
|
-
resolve: () => {
|
|
282
|
-
input.abort.removeEventListener("abort", onAbort)
|
|
283
|
-
resolve()
|
|
284
|
-
},
|
|
285
|
-
reject: (err) => {
|
|
286
|
-
input.abort.removeEventListener("abort", onAbort)
|
|
287
|
-
reject(err)
|
|
288
|
-
},
|
|
289
|
-
})
|
|
290
|
-
input.abort.addEventListener("abort", onAbort, { once: true })
|
|
291
|
-
if (input.abort.aborted) {
|
|
292
|
-
onAbort()
|
|
293
|
-
return
|
|
294
|
-
}
|
|
295
|
-
log.warn("waiting for network", { sessionID: input.sessionID, requestID: id, message: input.message })
|
|
296
|
-
Bus.publish(Event.Asked, info)
|
|
297
|
-
void watch({ requestID: id, abort: input.abort }).catch((err) => {
|
|
298
|
-
log.error("restore watch failed", { err, requestID: id })
|
|
299
|
-
})
|
|
300
|
-
})
|
|
301
|
-
return { id, promise }
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
export const restore = fn(
|
|
305
|
-
z.object({
|
|
306
|
-
requestID: QuestionID.zod,
|
|
307
|
-
}),
|
|
308
|
-
async (input) => {
|
|
309
|
-
const s = await state()
|
|
310
|
-
const requestID = input.requestID as QuestionID
|
|
311
|
-
const req = s.pending.get(requestID)
|
|
312
|
-
if (!req || req.info.restored) return
|
|
313
|
-
const time = Date.now()
|
|
314
|
-
req.info.restored = true
|
|
315
|
-
req.info.time = { ...req.info.time, restored: time }
|
|
316
|
-
log.info("network restored", { sessionID: req.info.sessionID, requestID })
|
|
317
|
-
Bus.publish(Event.Restored, {
|
|
318
|
-
sessionID: req.info.sessionID,
|
|
319
|
-
requestID: req.info.id,
|
|
320
|
-
time,
|
|
321
|
-
})
|
|
322
|
-
void resume({ requestID, abort: req.abort }).catch((err) => {
|
|
323
|
-
log.error("auto resume failed", { err, requestID })
|
|
324
|
-
})
|
|
325
|
-
},
|
|
326
|
-
)
|
|
327
|
-
|
|
328
|
-
export const reply = fn(
|
|
329
|
-
z.object({
|
|
330
|
-
requestID: QuestionID.zod,
|
|
331
|
-
}),
|
|
332
|
-
async (input) => {
|
|
333
|
-
const s = await state()
|
|
334
|
-
const requestID = input.requestID as QuestionID
|
|
335
|
-
const req = s.pending.get(requestID)
|
|
336
|
-
if (!req) {
|
|
337
|
-
log.warn("reply for unknown request", { requestID })
|
|
338
|
-
return
|
|
339
|
-
}
|
|
340
|
-
s.pending.delete(requestID)
|
|
341
|
-
void MCP.status()
|
|
342
|
-
.then((statuses) => {
|
|
343
|
-
for (const [name, s] of Object.entries(statuses)) {
|
|
344
|
-
if (s.status === "failed") {
|
|
345
|
-
MCP.connect(name).catch((err) => {
|
|
346
|
-
log.error("remote reconnect failed", { name, err })
|
|
347
|
-
})
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
})
|
|
351
|
-
.catch((err) => {
|
|
352
|
-
log.error("failed to get MCP status for reconnect", { err })
|
|
353
|
-
})
|
|
354
|
-
Bus.publish(Event.Replied, {
|
|
355
|
-
sessionID: req.info.sessionID,
|
|
356
|
-
requestID: req.info.id,
|
|
357
|
-
})
|
|
358
|
-
req.resolve()
|
|
359
|
-
},
|
|
360
|
-
)
|
|
361
|
-
|
|
362
|
-
export const reject = fn(
|
|
363
|
-
z.object({
|
|
364
|
-
requestID: QuestionID.zod,
|
|
365
|
-
}),
|
|
366
|
-
async (input) => {
|
|
367
|
-
const s = await state()
|
|
368
|
-
const requestID = input.requestID as QuestionID
|
|
369
|
-
const req = s.pending.get(requestID)
|
|
370
|
-
if (!req) {
|
|
371
|
-
log.warn("reject for unknown request", { requestID })
|
|
372
|
-
return
|
|
373
|
-
}
|
|
374
|
-
s.pending.delete(requestID)
|
|
375
|
-
Bus.publish(Event.Rejected, {
|
|
376
|
-
sessionID: req.info.sessionID,
|
|
377
|
-
requestID: req.info.id,
|
|
378
|
-
})
|
|
379
|
-
req.reject(new RejectedError())
|
|
380
|
-
},
|
|
381
|
-
)
|
|
382
|
-
|
|
383
|
-
export async function list() {
|
|
384
|
-
return state().then((s) => Array.from(s.pending.values()).map((item) => item.info))
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
export class RejectedError extends Error {
|
|
388
|
-
constructor() {
|
|
389
|
-
super("Network reconnect was rejected")
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
}
|
|
1
|
+
export * from "./core/network"
|
package/src/session/overflow.ts
CHANGED
|
@@ -1,28 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type { Provider } from "@/provider/provider"
|
|
3
|
-
import { ProviderTransform } from "@/provider/transform"
|
|
4
|
-
import type { MessageV2 } from "./message-v2"
|
|
5
|
-
import { SaeeolSessionOverflow } from "@/saeeol/session/overflow"
|
|
6
|
-
|
|
7
|
-
const COMPACTION_BUFFER = 20_000
|
|
8
|
-
|
|
9
|
-
export function usable(input: { cfg: Config.Info; model: Provider.Model }) {
|
|
10
|
-
const context = input.model.limit.context
|
|
11
|
-
if (context === 0) return 0
|
|
12
|
-
|
|
13
|
-
const reserved =
|
|
14
|
-
input.cfg.compaction?.reserved ?? Math.min(COMPACTION_BUFFER, ProviderTransform.maxOutputTokens(input.model))
|
|
15
|
-
return input.model.limit.input
|
|
16
|
-
? Math.max(0, input.model.limit.input - reserved)
|
|
17
|
-
: Math.max(0, context - ProviderTransform.maxOutputTokens(input.model))
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function isOverflow(input: { cfg: Config.Info; tokens: MessageV2.Assistant["tokens"]; model: Provider.Model }) {
|
|
21
|
-
if (input.cfg.compaction?.auto === false) return false
|
|
22
|
-
if (input.model.limit.context === 0) return false
|
|
23
|
-
|
|
24
|
-
const count =
|
|
25
|
-
input.tokens.total || input.tokens.input + input.tokens.output + input.tokens.cache.read + input.tokens.cache.write
|
|
26
|
-
const cap = SaeeolSessionOverflow.limit({ cfg: input.cfg, model: input.model, usable: usable(input) })
|
|
27
|
-
return count >= cap
|
|
28
|
-
}
|
|
1
|
+
export * from "./core/compaction/overflow"
|