@zyraxon-ai/server 19.0.3 → 19.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/dist/api.d.ts +2 -0
  2. package/dist/api.d.ts.map +1 -0
  3. package/dist/api.js +8 -0
  4. package/dist/api.js.map +1 -0
  5. package/dist/auth.d.ts +26 -0
  6. package/dist/auth.d.ts.map +1 -0
  7. package/dist/auth.js +36 -0
  8. package/dist/auth.js.map +1 -0
  9. package/dist/cors.d.ts +8 -0
  10. package/dist/cors.d.ts.map +1 -0
  11. package/dist/cors.js +36 -0
  12. package/dist/cors.js.map +1 -0
  13. package/dist/handlers/agent.d.ts +2 -0
  14. package/dist/handlers/agent.d.ts.map +1 -0
  15. package/dist/handlers/agent.js +9 -0
  16. package/dist/handlers/agent.js.map +1 -0
  17. package/dist/handlers/command.d.ts +2 -0
  18. package/dist/handlers/command.d.ts.map +1 -0
  19. package/dist/handlers/command.js +6 -0
  20. package/dist/handlers/command.js.map +1 -0
  21. package/dist/handlers/credential.d.ts +2 -0
  22. package/dist/handlers/credential.d.ts.map +1 -0
  23. package/dist/handlers/credential.js +14 -0
  24. package/dist/handlers/credential.js.map +1 -0
  25. package/dist/handlers/event.d.ts +2 -0
  26. package/dist/handlers/event.d.ts.map +1 -0
  27. package/dist/handlers/event.js +41 -0
  28. package/dist/handlers/event.js.map +1 -0
  29. package/dist/handlers/fs.d.ts +2 -0
  30. package/dist/handlers/fs.d.ts.map +1 -0
  31. package/dist/handlers/fs.js +25 -0
  32. package/dist/handlers/fs.js.map +1 -0
  33. package/dist/handlers/health.d.ts +2 -0
  34. package/dist/handlers/health.d.ts.map +1 -0
  35. package/dist/handlers/health.js +5 -0
  36. package/dist/handlers/health.js.map +1 -0
  37. package/dist/handlers/integration.d.ts +2 -0
  38. package/dist/handlers/integration.d.ts.map +1 -0
  39. package/dist/handlers/integration.js +61 -0
  40. package/dist/handlers/integration.js.map +1 -0
  41. package/dist/handlers/location.d.ts +2 -0
  42. package/dist/handlers/location.d.ts.map +1 -0
  43. package/dist/handlers/location.js +13 -0
  44. package/dist/handlers/location.js.map +1 -0
  45. package/dist/handlers/message.d.ts +2 -0
  46. package/dist/handlers/message.d.ts.map +1 -0
  47. package/dist/handlers/message.js +57 -0
  48. package/dist/handlers/message.js.map +1 -0
  49. package/dist/handlers/model.d.ts +2 -0
  50. package/dist/handlers/model.d.ts.map +1 -0
  51. package/dist/handlers/model.js +12 -0
  52. package/dist/handlers/model.js.map +1 -0
  53. package/dist/handlers/permission.d.ts +2 -0
  54. package/dist/handlers/permission.d.ts.map +1 -0
  55. package/dist/handlers/permission.js +70 -0
  56. package/dist/handlers/permission.js.map +1 -0
  57. package/dist/handlers/project-copy.d.ts +2 -0
  58. package/dist/handlers/project-copy.d.ts.map +1 -0
  59. package/dist/handlers/project-copy.js +42 -0
  60. package/dist/handlers/project-copy.js.map +1 -0
  61. package/dist/handlers/provider.d.ts +2 -0
  62. package/dist/handlers/provider.d.ts.map +1 -0
  63. package/dist/handlers/provider.js +24 -0
  64. package/dist/handlers/provider.js.map +1 -0
  65. package/dist/handlers/pty.d.ts +2 -0
  66. package/dist/handlers/pty.d.ts.map +1 -0
  67. package/dist/handlers/pty.js +142 -0
  68. package/dist/handlers/pty.js.map +1 -0
  69. package/dist/handlers/question.d.ts +2 -0
  70. package/dist/handlers/question.d.ts.map +1 -0
  71. package/dist/handlers/question.js +39 -0
  72. package/dist/handlers/question.js.map +1 -0
  73. package/dist/handlers/reference.d.ts +2 -0
  74. package/dist/handlers/reference.d.ts.map +1 -0
  75. package/dist/handlers/reference.js +6 -0
  76. package/dist/handlers/reference.js.map +1 -0
  77. package/dist/handlers/session.d.ts +2 -0
  78. package/dist/handlers/session.d.ts.map +1 -0
  79. package/dist/handlers/session.js +206 -0
  80. package/dist/handlers/session.js.map +1 -0
  81. package/dist/handlers/skill.d.ts +2 -0
  82. package/dist/handlers/skill.d.ts.map +1 -0
  83. package/dist/handlers/skill.js +6 -0
  84. package/dist/handlers/skill.js.map +1 -0
  85. package/dist/handlers.d.ts +3 -0
  86. package/dist/handlers.d.ts.map +1 -0
  87. package/dist/handlers.js +21 -0
  88. package/dist/handlers.js.map +1 -0
  89. package/dist/location.d.ts +21 -0
  90. package/dist/location.d.ts.map +1 -0
  91. package/dist/location.js +48 -0
  92. package/dist/location.js.map +1 -0
  93. package/dist/middleware/authorization.d.ts +6 -0
  94. package/dist/middleware/authorization.d.ts.map +1 -0
  95. package/dist/middleware/authorization.js +51 -0
  96. package/dist/middleware/authorization.js.map +1 -0
  97. package/dist/middleware/schema-error.d.ts +4 -0
  98. package/dist/middleware/schema-error.d.ts.map +1 -0
  99. package/dist/middleware/schema-error.js +16 -0
  100. package/dist/middleware/schema-error.js.map +1 -0
  101. package/dist/middleware/session-location.d.ts +16 -0
  102. package/dist/middleware/session-location.d.ts.map +1 -0
  103. package/dist/middleware/session-location.js +44 -0
  104. package/dist/middleware/session-location.js.map +1 -0
  105. package/dist/pty-environment.d.ts +14 -0
  106. package/dist/pty-environment.d.ts.map +1 -0
  107. package/dist/pty-environment.js +10 -0
  108. package/dist/pty-environment.js.map +1 -0
  109. package/dist/routes.d.ts +9 -0
  110. package/dist/routes.d.ts.map +1 -0
  111. package/dist/routes.js +51 -0
  112. package/dist/routes.js.map +1 -0
  113. package/package.json +14 -10
  114. package/src/api.ts +0 -8
  115. package/src/auth.ts +0 -63
  116. package/src/cors.ts +0 -34
  117. package/src/handlers/agent.ts +0 -13
  118. package/src/handlers/command.ts +0 -8
  119. package/src/handlers/credential.ts +0 -22
  120. package/src/handlers/event.ts +0 -52
  121. package/src/handlers/fs.ts +0 -39
  122. package/src/handlers/health.ts +0 -7
  123. package/src/handlers/integration.ts +0 -104
  124. package/src/handlers/location.ts +0 -18
  125. package/src/handlers/message.ts +0 -81
  126. package/src/handlers/model.ts +0 -17
  127. package/src/handlers/permission.ts +0 -98
  128. package/src/handlers/project-copy.ts +0 -68
  129. package/src/handlers/provider.ts +0 -32
  130. package/src/handlers/pty.ts +0 -223
  131. package/src/handlers/question.ts +0 -62
  132. package/src/handlers/reference.ts +0 -8
  133. package/src/handlers/session.ts +0 -385
  134. package/src/handlers/skill.ts +0 -8
  135. package/src/handlers.ts +0 -40
  136. package/src/location.ts +0 -60
  137. package/src/middleware/authorization.ts +0 -58
  138. package/src/middleware/schema-error.ts +0 -20
  139. package/src/middleware/session-location.ts +0 -67
  140. package/src/pty-environment.ts +0 -19
  141. package/src/routes.ts +0 -68
  142. package/sst-env.d.ts +0 -10
  143. package/tsconfig.json +0 -8
@@ -1,223 +0,0 @@
1
- import { Pty } from "@zyraxon-ai/core/pty"
2
- import { PtyProtocol } from "@zyraxon-ai/core/pty/protocol"
3
- import { PtyTicket } from "@zyraxon-ai/core/pty/ticket"
4
- import { Location } from "@zyraxon-ai/core/location"
5
- import { Effect, Queue } from "effect"
6
- import { HttpServerRequest, HttpServerResponse } from "effect/unstable/http"
7
- import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi"
8
- import * as Socket from "effect/unstable/socket/Socket"
9
- import { Api } from "../api"
10
- import { CorsConfig, isAllowedRequestOrigin } from "../cors"
11
- import { ForbiddenError, PtyNotFoundError } from "@zyraxon-ai/protocol/errors"
12
- import {
13
- PTY_CONNECT_TICKET_QUERY,
14
- PTY_CONNECT_TOKEN_HEADER,
15
- PTY_CONNECT_TOKEN_HEADER_VALUE,
16
- } from "@zyraxon-ai/protocol/groups/pty"
17
- import { response } from "../location"
18
- import { PtyEnvironment } from "../pty-environment"
19
-
20
- const ticketScope = Effect.gen(function* () {
21
- const location = yield* Location.Service
22
- return { directory: location.directory as string, workspaceID: location.workspaceID }
23
- })
24
-
25
- export const PtyHandler = HttpApiBuilder.group(Api, "server.pty", (handlers) =>
26
- Effect.gen(function* () {
27
- const tickets = yield* PtyTicket.Service
28
- const cors = yield* CorsConfig
29
- const environment = yield* PtyEnvironment.Service
30
-
31
- return handlers
32
- .handle(
33
- "pty.list",
34
- Effect.fn(function* () {
35
- return yield* response((yield* Pty.Service).list())
36
- }),
37
- )
38
- .handle(
39
- "pty.create",
40
- Effect.fn(function* (ctx) {
41
- const pty = yield* Pty.Service
42
- const location = yield* Location.Service
43
- const cwd = ctx.payload.cwd || location.directory
44
- return yield* response(
45
- pty.create({
46
- ...ctx.payload,
47
- args: ctx.payload.args ? [...ctx.payload.args] : undefined,
48
- cwd,
49
- env: {
50
- ...ctx.payload.env,
51
- ...(yield* environment.get({ directory: location.directory, cwd })),
52
- },
53
- }),
54
- )
55
- }),
56
- )
57
- .handle(
58
- "pty.get",
59
- Effect.fn(function* (ctx) {
60
- const pty = yield* Pty.Service
61
- return yield* response(
62
- pty.get(ctx.params.ptyID).pipe(
63
- Effect.catchTag(
64
- "Pty.NotFoundError",
65
- () =>
66
- new PtyNotFoundError({
67
- ptyID: ctx.params.ptyID,
68
- message: `PTY session not found: ${ctx.params.ptyID}`,
69
- }),
70
- ),
71
- ),
72
- )
73
- }),
74
- )
75
- .handle(
76
- "pty.update",
77
- Effect.fn(function* (ctx) {
78
- const pty = yield* Pty.Service
79
- return yield* response(
80
- pty
81
- .update(ctx.params.ptyID, {
82
- ...ctx.payload,
83
- size: ctx.payload.size ? { ...ctx.payload.size } : undefined,
84
- })
85
- .pipe(
86
- Effect.catchTag(
87
- "Pty.NotFoundError",
88
- () =>
89
- new PtyNotFoundError({
90
- ptyID: ctx.params.ptyID,
91
- message: `PTY session not found: ${ctx.params.ptyID}`,
92
- }),
93
- ),
94
- ),
95
- )
96
- }),
97
- )
98
- .handle(
99
- "pty.remove",
100
- Effect.fn(function* (ctx) {
101
- const pty = yield* Pty.Service
102
- yield* pty.remove(ctx.params.ptyID).pipe(
103
- Effect.catchTag(
104
- "Pty.NotFoundError",
105
- () =>
106
- new PtyNotFoundError({
107
- ptyID: ctx.params.ptyID,
108
- message: `PTY session not found: ${ctx.params.ptyID}`,
109
- }),
110
- ),
111
- )
112
- return HttpApiSchema.NoContent.make()
113
- }),
114
- )
115
- .handle(
116
- "pty.connectToken",
117
- Effect.fn(function* (ctx) {
118
- const request = yield* HttpServerRequest.HttpServerRequest
119
- // The custom header forces a CORS preflight, so cross-origin browser pages cannot
120
- // mint tickets without passing the server's origin policy.
121
- if (
122
- request.headers[PTY_CONNECT_TOKEN_HEADER] !== PTY_CONNECT_TOKEN_HEADER_VALUE ||
123
- !isAllowedRequestOrigin(request.headers.origin, request.headers.host, cors)
124
- )
125
- return yield* new ForbiddenError({ message: "Invalid PTY connect token request" })
126
- const pty = yield* Pty.Service
127
- yield* pty.get(ctx.params.ptyID).pipe(
128
- Effect.catchTag(
129
- "Pty.NotFoundError",
130
- () =>
131
- new PtyNotFoundError({
132
- ptyID: ctx.params.ptyID,
133
- message: `PTY session not found: ${ctx.params.ptyID}`,
134
- }),
135
- ),
136
- )
137
- return yield* response(tickets.issue({ ptyID: ctx.params.ptyID, ...(yield* ticketScope) }))
138
- }),
139
- )
140
- .handleRaw(
141
- "pty.connect",
142
- Effect.fn("PtyHandler.connect")(function* (ctx) {
143
- const pty = yield* Pty.Service
144
- const exists = yield* pty.get(ctx.params.ptyID).pipe(
145
- Effect.as(true),
146
- Effect.catchTag("Pty.NotFoundError", () => Effect.succeed(false)),
147
- )
148
- if (!exists) return HttpServerResponse.empty({ status: 404 })
149
-
150
- const url = new URL(ctx.request.url, "http://localhost")
151
- const ticket = url.searchParams.get(PTY_CONNECT_TICKET_QUERY)
152
- if (ticket) {
153
- const valid = isAllowedRequestOrigin(ctx.request.headers.origin, ctx.request.headers.host, cors)
154
- ? yield* tickets.consume({ ticket, ptyID: ctx.params.ptyID, ...(yield* ticketScope) })
155
- : false
156
- if (!valid) return HttpServerResponse.empty({ status: 403 })
157
- }
158
- const parsedCursor = url.searchParams.get("cursor")
159
- const cursorNumber = parsedCursor === null ? undefined : Number(parsedCursor)
160
- const cursor =
161
- cursorNumber !== undefined && Number.isSafeInteger(cursorNumber) && cursorNumber >= -1
162
- ? cursorNumber
163
- : undefined
164
-
165
- const socket = yield* Effect.orDie(ctx.request.upgrade)
166
- const write = yield* socket.writer
167
- const closeAccepted = (event: Socket.CloseEvent) =>
168
- socket
169
- .runRaw(() => Effect.void, { onOpen: write(event).pipe(Effect.catch(() => Effect.void)) })
170
- .pipe(
171
- Effect.timeout("1 second"),
172
- Effect.catchReason("SocketError", "SocketCloseError", () => Effect.void),
173
- Effect.catch(() => Effect.void),
174
- )
175
-
176
- // Outbound frames flow through one queue drained by a single writer so replay, live
177
- // output, and the close frame keep their order.
178
- // TODO: Integrate graceful-shutdown socket tracking before clients migrate to this route.
179
- const outbox = yield* Queue.unbounded<string | Uint8Array | Socket.CloseEvent>()
180
- const attachment = yield* pty
181
- .attach(ctx.params.ptyID, {
182
- cursor,
183
- onData: (chunk) => Queue.offerUnsafe(outbox, chunk),
184
- onEnd: () => Queue.offerUnsafe(outbox, new Socket.CloseEvent(1000)),
185
- })
186
- .pipe(
187
- Effect.catchTags({
188
- "Pty.NotFoundError": () =>
189
- closeAccepted(new Socket.CloseEvent(4404, "session not found")).pipe(Effect.as(undefined)),
190
- "Pty.ExitedError": () =>
191
- closeAccepted(new Socket.CloseEvent(4404, "session exited")).pipe(Effect.as(undefined)),
192
- }),
193
- )
194
- if (!attachment) return HttpServerResponse.empty()
195
-
196
- for (const chunk of PtyProtocol.chunks(attachment.replay)) Queue.offerUnsafe(outbox, chunk)
197
- Queue.offerUnsafe(outbox, PtyProtocol.metaFrame(attachment.cursor))
198
- attachment.activate()
199
-
200
- const drain = Effect.gen(function* () {
201
- while (true) {
202
- const item = yield* Queue.take(outbox)
203
- yield* write(item)
204
- if (item instanceof Socket.CloseEvent) return
205
- }
206
- })
207
-
208
- yield* Effect.race(
209
- drain,
210
- socket.runRaw((message) => {
211
- const decoded = PtyProtocol.decodeInput(message)
212
- if (decoded !== undefined) attachment.write(decoded)
213
- }),
214
- ).pipe(
215
- Effect.catchReason("SocketError", "SocketCloseError", () => Effect.void),
216
- Effect.ensuring(Effect.sync(() => attachment.detach())),
217
- Effect.orDie,
218
- )
219
- return HttpServerResponse.empty()
220
- }),
221
- )
222
- }),
223
- )
@@ -1,62 +0,0 @@
1
- import { QuestionV2 } from "@zyraxon-ai/core/question"
2
- import { Effect } from "effect"
3
- import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi"
4
- import { Api } from "../api"
5
- import { QuestionNotFoundError } from "@zyraxon-ai/protocol/errors"
6
- import { response } from "../location"
7
-
8
- function missingRequest(id: QuestionV2.ID) {
9
- return new QuestionNotFoundError({ requestID: id, message: `Question request not found: ${id}` })
10
- }
11
-
12
- export const QuestionHandler = HttpApiBuilder.group(Api, "server.question", (handlers) =>
13
- Effect.gen(function* () {
14
- const withOwnedQuestion = Effect.fnUntraced(function* <A, E>(
15
- sessionID: QuestionV2.Request["sessionID"],
16
- requestID: QuestionV2.ID,
17
- use: (question: QuestionV2.Interface) => Effect.Effect<A, E>,
18
- ) {
19
- const question = yield* QuestionV2.Service
20
- const request = (yield* question.list()).find((request) => request.id === requestID)
21
- if (!request || request.sessionID !== sessionID) return yield* missingRequest(requestID)
22
- return yield* use(question)
23
- })
24
-
25
- return handlers
26
- .handle(
27
- "question.request.list",
28
- Effect.fn(function* () {
29
- return yield* response((yield* QuestionV2.Service).list())
30
- }),
31
- )
32
- .handle(
33
- "session.question.list",
34
- Effect.fn(function* (ctx) {
35
- const requests = yield* (yield* QuestionV2.Service).list()
36
- return { data: requests.filter((request) => request.sessionID === ctx.params.sessionID) }
37
- }),
38
- )
39
- .handle(
40
- "session.question.reply",
41
- Effect.fn(function* (ctx) {
42
- yield* withOwnedQuestion(ctx.params.sessionID, ctx.params.requestID, (question) =>
43
- question
44
- .reply({ requestID: ctx.params.requestID, answers: ctx.payload.answers })
45
- .pipe(Effect.catchTag("QuestionV2.NotFoundError", () => missingRequest(ctx.params.requestID))),
46
- )
47
- return HttpApiSchema.NoContent.make()
48
- }),
49
- )
50
- .handle(
51
- "session.question.reject",
52
- Effect.fn(function* (ctx) {
53
- yield* withOwnedQuestion(ctx.params.sessionID, ctx.params.requestID, (question) =>
54
- question
55
- .reject(ctx.params.requestID)
56
- .pipe(Effect.catchTag("QuestionV2.NotFoundError", () => missingRequest(ctx.params.requestID))),
57
- )
58
- return HttpApiSchema.NoContent.make()
59
- }),
60
- )
61
- }),
62
- )
@@ -1,8 +0,0 @@
1
- import { Reference } from "@zyraxon-ai/core/reference"
2
- import { HttpApiBuilder } from "effect/unstable/httpapi"
3
- import { Api } from "../api"
4
- import { response } from "../location"
5
-
6
- export const ReferenceHandler = HttpApiBuilder.group(Api, "server.reference", (handlers) =>
7
- handlers.handle("reference.list", () => response(Reference.Service.use((reference) => reference.list()))),
8
- )
@@ -1,385 +0,0 @@
1
- import { SessionV2 } from "@zyraxon-ai/core/session"
2
- import { DateTime, Effect, Stream } from "effect"
3
- import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi"
4
- import { Api } from "../api"
5
- import { SessionsCursor } from "@zyraxon-ai/protocol/groups/session"
6
- import {
7
- ConflictError,
8
- InvalidCursorError,
9
- MessageNotFoundError,
10
- ServiceUnavailableError,
11
- SessionNotFoundError,
12
- UnknownError,
13
- } from "@zyraxon-ai/protocol/errors"
14
- import { AbsolutePath } from "@zyraxon-ai/core/schema"
15
-
16
- const DefaultSessionsLimit = 50
17
- const DefaultSessionHistoryLimit = 50
18
-
19
- export const SessionHandler = HttpApiBuilder.group(Api, "server.session", (handlers) =>
20
- Effect.gen(function* () {
21
- const session = yield* SessionV2.Service
22
-
23
- return handlers
24
- .handle(
25
- "session.list",
26
- Effect.fn(function* (ctx) {
27
- const query =
28
- ctx.query.cursor !== undefined
29
- ? yield* SessionsCursor.parse(ctx.query.cursor).pipe(
30
- Effect.mapError(() => new InvalidCursorError({ message: "Invalid cursor" })),
31
- )
32
- : ctx.query
33
- const sessions = yield* session.list({
34
- ...query,
35
- workspaceID: query.workspace,
36
- limit: ctx.query.limit ?? DefaultSessionsLimit,
37
- })
38
- const first = sessions[0]
39
- const last = sessions.at(-1)
40
- return {
41
- data: sessions,
42
- cursor: {
43
- previous: first
44
- ? SessionsCursor.make({
45
- ...query,
46
- anchor: {
47
- id: first.id,
48
- time: DateTime.toEpochMillis(first.time.created),
49
- direction: "previous",
50
- },
51
- })
52
- : undefined,
53
- next: last
54
- ? SessionsCursor.make({
55
- ...query,
56
- anchor: {
57
- id: last.id,
58
- time: DateTime.toEpochMillis(last.time.created),
59
- direction: "next",
60
- },
61
- })
62
- : undefined,
63
- },
64
- }
65
- }),
66
- )
67
- .handle(
68
- "session.create",
69
- Effect.fn(function* (ctx) {
70
- return {
71
- data: yield* session.create({
72
- id: ctx.payload.id,
73
- agent: ctx.payload.agent,
74
- model: ctx.payload.model,
75
- location: ctx.payload.location ?? { directory: AbsolutePath.make(process.cwd()) },
76
- }),
77
- }
78
- }),
79
- )
80
- .handle(
81
- "session.active",
82
- Effect.fn(function* () {
83
- return {
84
- data: Object.fromEntries(
85
- Array.from(yield* session.active, (sessionID) => [sessionID, { type: "running" as const }]),
86
- ),
87
- }
88
- }),
89
- )
90
- .handle(
91
- "session.get",
92
- Effect.fn(function* (ctx) {
93
- return {
94
- data: yield* session.get(ctx.params.sessionID).pipe(
95
- Effect.catchTag(
96
- "Session.NotFoundError",
97
- (error) =>
98
- new SessionNotFoundError({
99
- sessionID: error.sessionID,
100
- message: `Session not found: ${error.sessionID}`,
101
- }),
102
- ),
103
- ),
104
- }
105
- }),
106
- )
107
- .handle(
108
- "session.switchAgent",
109
- Effect.fn(function* (ctx) {
110
- yield* session.switchAgent({ sessionID: ctx.params.sessionID, agent: ctx.payload.agent }).pipe(
111
- Effect.catchTag("Session.NotFoundError", (error) =>
112
- Effect.fail(
113
- new SessionNotFoundError({
114
- sessionID: error.sessionID,
115
- message: `Session not found: ${error.sessionID}`,
116
- }),
117
- ),
118
- ),
119
- )
120
- return HttpApiSchema.NoContent.make()
121
- }),
122
- )
123
- .handle(
124
- "session.switchModel",
125
- Effect.fn(function* (ctx) {
126
- yield* session.switchModel({ sessionID: ctx.params.sessionID, model: ctx.payload.model }).pipe(
127
- Effect.catchTag("Session.NotFoundError", (error) =>
128
- Effect.fail(
129
- new SessionNotFoundError({
130
- sessionID: error.sessionID,
131
- message: `Session not found: ${error.sessionID}`,
132
- }),
133
- ),
134
- ),
135
- )
136
- return HttpApiSchema.NoContent.make()
137
- }),
138
- )
139
- .handle(
140
- "session.prompt",
141
- Effect.fn(function* (ctx) {
142
- return {
143
- data: yield* session
144
- .prompt({
145
- sessionID: ctx.params.sessionID,
146
- id: ctx.payload.id,
147
- prompt: ctx.payload.prompt,
148
- delivery: ctx.payload.delivery,
149
- resume: ctx.payload.resume,
150
- })
151
- .pipe(
152
- Effect.catchTag("Session.NotFoundError", (error) =>
153
- Effect.fail(
154
- new SessionNotFoundError({
155
- sessionID: error.sessionID,
156
- message: `Session not found: ${error.sessionID}`,
157
- }),
158
- ),
159
- ),
160
- Effect.catchTag("Session.PromptConflictError", (error) =>
161
- Effect.fail(
162
- new ConflictError({
163
- message: `Prompt message ID conflicts with an existing durable record: ${error.messageID}`,
164
- resource: error.messageID,
165
- }),
166
- ),
167
- ),
168
- ),
169
- }
170
- }),
171
- )
172
- .handle(
173
- "session.compact",
174
- Effect.fn(function* (ctx) {
175
- yield* session.compact({ sessionID: ctx.params.sessionID }).pipe(
176
- Effect.catchTag("Session.NotFoundError", (error) =>
177
- Effect.fail(
178
- new SessionNotFoundError({
179
- sessionID: error.sessionID,
180
- message: `Session not found: ${error.sessionID}`,
181
- }),
182
- ),
183
- ),
184
- Effect.catchTag("Session.OperationUnavailableError", (error) =>
185
- Effect.fail(
186
- new ServiceUnavailableError({
187
- message: `Session ${error.operation} is not available yet`,
188
- service: `session.${error.operation}`,
189
- }),
190
- ),
191
- ),
192
- )
193
- return HttpApiSchema.NoContent.make()
194
- }),
195
- )
196
- .handle(
197
- "session.wait",
198
- Effect.fn(function* (ctx) {
199
- yield* session.wait(ctx.params.sessionID).pipe(
200
- Effect.catchTag("Session.NotFoundError", (error) =>
201
- Effect.fail(
202
- new SessionNotFoundError({
203
- sessionID: error.sessionID,
204
- message: `Session not found: ${error.sessionID}`,
205
- }),
206
- ),
207
- ),
208
- Effect.catchTag("Session.OperationUnavailableError", (error) =>
209
- Effect.fail(
210
- new ServiceUnavailableError({
211
- message: `Session ${error.operation} is not available yet`,
212
- service: `session.${error.operation}`,
213
- }),
214
- ),
215
- ),
216
- )
217
- return HttpApiSchema.NoContent.make()
218
- }),
219
- )
220
- .handle(
221
- "session.revert.stage",
222
- Effect.fn(function* (ctx) {
223
- return {
224
- data: yield* session.revert.stage({ ...ctx.params, ...ctx.payload }).pipe(
225
- Effect.catchTag(
226
- "Session.NotFoundError",
227
- (error) =>
228
- new SessionNotFoundError({
229
- sessionID: error.sessionID,
230
- message: `Session not found: ${error.sessionID}`,
231
- }),
232
- ),
233
- Effect.catchTag(
234
- "Session.MessageNotFoundError",
235
- (error) =>
236
- new MessageNotFoundError({
237
- sessionID: error.sessionID,
238
- messageID: error.messageID,
239
- message: `Message not found: ${error.messageID}`,
240
- }),
241
- ),
242
- Effect.catchTag("Snapshot.Error", (error) => {
243
- const ref = `err_${crypto.randomUUID().slice(0, 8)}`
244
- return Effect.logError("failed to stage session revert", { cause: error }).pipe(
245
- Effect.andThen(
246
- Effect.fail(
247
- new UnknownError({
248
- message: "Unexpected server error. Check server logs for details.",
249
- ref,
250
- }),
251
- ),
252
- ),
253
- )
254
- }),
255
- ),
256
- }
257
- }),
258
- )
259
- .handle(
260
- "session.revert.clear",
261
- Effect.fn(function* (ctx) {
262
- yield* session.revert.clear(ctx.params.sessionID).pipe(
263
- Effect.catchTag(
264
- "Session.NotFoundError",
265
- (error) =>
266
- new SessionNotFoundError({
267
- sessionID: error.sessionID,
268
- message: `Session not found: ${error.sessionID}`,
269
- }),
270
- ),
271
- Effect.catchTag("Snapshot.Error", (error) => {
272
- const ref = `err_${crypto.randomUUID().slice(0, 8)}`
273
- return Effect.logError("failed to clear session revert", { cause: error }).pipe(
274
- Effect.andThen(
275
- Effect.fail(
276
- new UnknownError({
277
- message: "Unexpected server error. Check server logs for details.",
278
- ref,
279
- }),
280
- ),
281
- ),
282
- )
283
- }),
284
- )
285
- return HttpApiSchema.NoContent.make()
286
- }),
287
- )
288
- .handle(
289
- "session.revert.commit",
290
- Effect.fn(function* (ctx) {
291
- yield* session.revert.commit(ctx.params.sessionID).pipe(
292
- Effect.catchTag(
293
- "Session.NotFoundError",
294
- (error) =>
295
- new SessionNotFoundError({
296
- sessionID: error.sessionID,
297
- message: `Session not found: ${error.sessionID}`,
298
- }),
299
- ),
300
- )
301
- return HttpApiSchema.NoContent.make()
302
- }),
303
- )
304
- .handle(
305
- "session.context",
306
- Effect.fn(function* (ctx) {
307
- return {
308
- data: yield* session.context(ctx.params.sessionID).pipe(
309
- Effect.catchTag("Session.NotFoundError", (error) =>
310
- Effect.fail(
311
- new SessionNotFoundError({
312
- sessionID: error.sessionID,
313
- message: `Session not found: ${error.sessionID}`,
314
- }),
315
- ),
316
- ),
317
- Effect.catchTag("Session.MessageDecodeError", (error) => {
318
- const ref = `err_${crypto.randomUUID().slice(0, 8)}`
319
- return Effect.logError("failed to decode session message").pipe(
320
- Effect.annotateLogs({ ref, sessionID: error.sessionID, messageID: error.messageID }),
321
- Effect.andThen(
322
- Effect.fail(
323
- new UnknownError({ message: "Unexpected server error. Check server logs for details.", ref }),
324
- ),
325
- ),
326
- )
327
- }),
328
- ),
329
- }
330
- }),
331
- )
332
- .handle(
333
- "session.history",
334
- Effect.fn(function* (ctx) {
335
- return yield* session
336
- .history({
337
- sessionID: ctx.params.sessionID,
338
- after: ctx.query.after,
339
- limit: ctx.query.limit ?? DefaultSessionHistoryLimit,
340
- })
341
- .pipe(
342
- Effect.map((page) => ({
343
- data: page.events,
344
- hasMore: page.hasMore,
345
- })),
346
- Effect.catchTag(
347
- "Session.NotFoundError",
348
- (error) =>
349
- new SessionNotFoundError({
350
- sessionID: error.sessionID,
351
- message: `Session not found: ${error.sessionID}`,
352
- }),
353
- ),
354
- )
355
- }),
356
- )
357
- .handle(
358
- "session.events",
359
- Effect.fn((ctx) =>
360
- Effect.succeed(
361
- session.events({ sessionID: ctx.params.sessionID, after: ctx.query.after }).pipe(Stream.orDie),
362
- ),
363
- ),
364
- )
365
- .handle(
366
- "session.interrupt",
367
- Effect.fn(function* (ctx) {
368
- yield* session.interrupt(ctx.params.sessionID)
369
- return HttpApiSchema.NoContent.make()
370
- }),
371
- )
372
- .handle(
373
- "session.message",
374
- Effect.fn(function* (ctx) {
375
- const message = yield* session.message(ctx.params)
376
- if (message) return { data: message }
377
- return yield* new MessageNotFoundError({
378
- sessionID: ctx.params.sessionID,
379
- messageID: ctx.params.messageID,
380
- message: `Message not found: ${ctx.params.messageID}`,
381
- })
382
- }),
383
- )
384
- }),
385
- )
@@ -1,8 +0,0 @@
1
- import { SkillV2 } from "@zyraxon-ai/core/skill"
2
- import { HttpApiBuilder } from "effect/unstable/httpapi"
3
- import { Api } from "../api"
4
- import { response } from "../location"
5
-
6
- export const SkillHandler = HttpApiBuilder.group(Api, "server.skill", (handlers) =>
7
- handlers.handle("skill.list", () => response(SkillV2.Service.use((skill) => skill.list()))),
8
- )