@aryasaatvik/motel 0.4.0 → 0.5.1
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/AGENTS.md +2 -2
- package/README.md +1 -1
- package/package.json +7 -7
- package/skills/motel-debug/references/effect.md +1 -1
- package/src/cli.ts +15 -15
- package/src/httpApi.ts +1 -1
- package/src/localServer.ts +5 -5
- package/src/mcp.ts +3 -2
- package/src/motel.ts +2 -2
- package/src/services/AsyncIngest.ts +19 -8
- package/src/services/ingestRpc.ts +2 -2
- package/src/services/telemetryWorker.ts +1 -3
- package/src/ui/aiState.ts +1 -1
- package/src/ui/atoms.ts +1 -1
- package/src/ui/serviceSelection.test.ts +1 -1
- package/web/dist/assets/index-BZhmmoqP.js +21 -0
- package/web/dist/index.html +1 -1
- package/web/dist/assets/index-CN7ClqOl.js +0 -21
package/AGENTS.md
CHANGED
|
@@ -90,7 +90,7 @@ The repo is wired up with `@effect/language-service` as a `tsconfig.json` `plugi
|
|
|
90
90
|
- `src/ui/useKeyboardNav.ts` centralises the keyboard handlers and
|
|
91
91
|
cross-pane navigation state transitions.
|
|
92
92
|
- `src/motel.ts` composes and runs the public Effect command tree; `src/cli.ts` exports typed telemetry query leaves and handlers.
|
|
93
|
-
- `src/runtime.ts` wires the Effect
|
|
93
|
+
- `src/runtime.ts` wires the Effect runtime and OTEL trace + log exporters.
|
|
94
94
|
- `src/localServer.ts` starts the local Bun OTLP/query server.
|
|
95
95
|
- `src/httpApi.ts` defines the typed Effect HttpApi surface and OpenAPI spec for the local server.
|
|
96
96
|
- `src/httpListPolicy.ts` owns pure HTTP list/search parameter decoding, bounds, cursors, and pagination metadata shaping.
|
|
@@ -118,7 +118,7 @@ The repo is wired up with `@effect/language-service` as a `tsconfig.json` `plugi
|
|
|
118
118
|
## Effect Observability Guidance
|
|
119
119
|
- Inspect the target repo’s existing Effect runtime and observability wiring before adding anything new.
|
|
120
120
|
- Prefer the repo’s existing Effect-native observability APIs if available.
|
|
121
|
-
- If `effect/
|
|
121
|
+
- If `effect/observability` is already the best fit, prefer it over adding `@effect/opentelemetry`.
|
|
122
122
|
- Only add new OpenTelemetry SDK packages when the repo already uses them or they are clearly required.
|
|
123
123
|
- Merge telemetry into the main runtime once, not per-feature.
|
|
124
124
|
- Prefer structured log annotations so fields like `sessionID`, `modelID`, `providerID`, and `tool` are queryable.
|
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ curl -fsSL https://bun.sh/install | bash
|
|
|
50
50
|
the keyboard cheat sheet, or `c` to copy paste-ready setup instructions
|
|
51
51
|
for any Effect/OTEL app you want to trace.
|
|
52
52
|
|
|
53
|
-
Requirements: [Bun](https://bun.sh/)
|
|
53
|
+
Requirements: [Bun](https://bun.sh/) matching `package.json` `engines.bun` (`>=1.3.0`).
|
|
54
54
|
|
|
55
55
|
### macOS service from the maintained checkout
|
|
56
56
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aryasaatvik/motel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "A local OpenTelemetry ingest + TUI viewer for development, backed by SQLite.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -91,17 +91,17 @@
|
|
|
91
91
|
"prepublishOnly": "bun run web:build"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
|
-
"@effect/language-service": "0.87.
|
|
94
|
+
"@effect/language-service": "0.87.2",
|
|
95
95
|
"@types/bun": "^1.3.14",
|
|
96
96
|
"@types/react": "^19.2.17",
|
|
97
97
|
"tegami": "1.4.0",
|
|
98
98
|
"typescript": "^6.0.3"
|
|
99
99
|
},
|
|
100
100
|
"dependencies": {
|
|
101
|
-
"@effect/atom-react": "4.0.0
|
|
102
|
-
"@effect/opentelemetry": "4.0.0
|
|
103
|
-
"@effect/platform-bun": "4.0.0
|
|
104
|
-
"@effect/platform-node-shared": "4.0.0
|
|
101
|
+
"@effect/atom-react": "4.0.0",
|
|
102
|
+
"@effect/opentelemetry": "4.0.0",
|
|
103
|
+
"@effect/platform-bun": "4.0.0",
|
|
104
|
+
"@effect/platform-node-shared": "4.0.0",
|
|
105
105
|
"@opentelemetry/api": "^1.9.0",
|
|
106
106
|
"@opentelemetry/exporter-logs-otlp-http": "^0.219.0",
|
|
107
107
|
"@opentelemetry/exporter-trace-otlp-http": "^0.219.0",
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
"@opentelemetry/sdk-trace-node": "^2.8.0",
|
|
113
113
|
"@opentui/core": "0.4.2",
|
|
114
114
|
"@opentui/react": "0.4.2",
|
|
115
|
-
"effect": "4.0.0
|
|
115
|
+
"effect": "4.0.0",
|
|
116
116
|
"protobufjs": "7.6.4",
|
|
117
117
|
"react": "^19.2.7",
|
|
118
118
|
"scheduler": "^0.27.0"
|
|
@@ -6,7 +6,7 @@ Apply these only when the target repo already uses Effect or `@effect/*`.
|
|
|
6
6
|
|
|
7
7
|
- Inspect the existing runtime and observability wiring before adding anything new.
|
|
8
8
|
- Prefer the repo's existing Effect-native observability APIs if they already exist.
|
|
9
|
-
- If `effect/
|
|
9
|
+
- If `effect/observability` is already the best fit, prefer it over adding new OTEL packages.
|
|
10
10
|
- Merge telemetry into the main runtime once, not per feature or per request path.
|
|
11
11
|
|
|
12
12
|
## Instrumentation
|
package/src/cli.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Console, Effect, Option, References } from "effect"
|
|
2
|
-
import { Argument, Command } from "effect/
|
|
2
|
+
import { Argument, Command } from "effect/cli"
|
|
3
3
|
import { config } from "./config.js"
|
|
4
4
|
import { otelServerInstructions } from "./instructions.js"
|
|
5
5
|
import { attributeFiltersFromArgs, isAttributeFilterToken } from "./queryFilters.js"
|
|
@@ -16,7 +16,7 @@ const query = <A>(effect: Effect.Effect<A, unknown, TelemetryStoreReadonly>) =>
|
|
|
16
16
|
|
|
17
17
|
const optional = (value: Option.Option<string>, fallback?: string) => Option.getOrElse(value, () => fallback)
|
|
18
18
|
|
|
19
|
-
const searchOperand = Argument.
|
|
19
|
+
const searchOperand = Argument.String("service-or-filter").pipe(
|
|
20
20
|
Argument.mapTryCatch(
|
|
21
21
|
(value) => {
|
|
22
22
|
if (value.startsWith("attr.") && !isAttributeFilterToken(value)) {
|
|
@@ -34,8 +34,8 @@ const services = Command.make("services", {}, () =>
|
|
|
34
34
|
).pipe(Command.withDescription("List observed telemetry services"))
|
|
35
35
|
|
|
36
36
|
const traces = Command.make("traces", {
|
|
37
|
-
service: Argument.
|
|
38
|
-
limit: Argument.
|
|
37
|
+
service: Argument.String("service").pipe(Argument.optional),
|
|
38
|
+
limit: Argument.Int("limit").pipe(Argument.optional),
|
|
39
39
|
}, ({ service, limit }) =>
|
|
40
40
|
query(Effect.flatMap(TelemetryStoreReadonly, (store) =>
|
|
41
41
|
store.listRecentTraces(optional(service, config.otel.serviceName)!, {
|
|
@@ -45,13 +45,13 @@ const traces = Command.make("traces", {
|
|
|
45
45
|
).pipe(Command.withDescription("List recent traces"))
|
|
46
46
|
|
|
47
47
|
const trace = Command.make("trace", {
|
|
48
|
-
traceId: Argument.
|
|
48
|
+
traceId: Argument.String("trace-id"),
|
|
49
49
|
}, ({ traceId }) =>
|
|
50
50
|
query(Effect.flatMap(TelemetryStoreReadonly, (store) => store.getTrace(traceId))),
|
|
51
51
|
).pipe(Command.withDescription("Get one trace"))
|
|
52
52
|
|
|
53
53
|
const span = Command.make("span", {
|
|
54
|
-
spanId: Argument.
|
|
54
|
+
spanId: Argument.String("span-id"),
|
|
55
55
|
}, ({ spanId }) =>
|
|
56
56
|
Effect.promise(() => fetch(`${config.otel.queryUrl}/api/spans/${encodeURIComponent(spanId)}`).then((response) => response.json())).pipe(
|
|
57
57
|
Effect.andThen(json),
|
|
@@ -59,7 +59,7 @@ const span = Command.make("span", {
|
|
|
59
59
|
).pipe(Command.withDescription("Get one span"))
|
|
60
60
|
|
|
61
61
|
const traceSpans = Command.make("trace-spans", {
|
|
62
|
-
traceId: Argument.
|
|
62
|
+
traceId: Argument.String("trace-id"),
|
|
63
63
|
}, ({ traceId }) =>
|
|
64
64
|
query(Effect.flatMap(TelemetryStoreReadonly, (store) => store.listTraceSpans(traceId))),
|
|
65
65
|
).pipe(Command.withDescription("List spans in one trace"))
|
|
@@ -102,8 +102,8 @@ const searchTraces = Command.make("search-traces", {
|
|
|
102
102
|
}).pipe(Command.withDescription("Search trace summaries by service, operation, and attributes"))
|
|
103
103
|
|
|
104
104
|
const traceStats = Command.make("trace-stats", {
|
|
105
|
-
groupBy: Argument.
|
|
106
|
-
agg: Argument.
|
|
105
|
+
groupBy: Argument.String("groupBy"),
|
|
106
|
+
agg: Argument.Literals("aggregation", ["count", "avg_duration", "p95_duration", "error_rate"]),
|
|
107
107
|
args: searchOperand,
|
|
108
108
|
}, ({ groupBy, agg, args }) => {
|
|
109
109
|
const values = args as ReadonlyArray<string>
|
|
@@ -121,7 +121,7 @@ const instructions = Command.make("instructions", {}, () => Console.log(otelServ
|
|
|
121
121
|
.pipe(Command.withDescription("Print Effect telemetry setup instructions"))
|
|
122
122
|
|
|
123
123
|
const logs = Command.make("logs", {
|
|
124
|
-
service: Argument.
|
|
124
|
+
service: Argument.String("service").pipe(Argument.optional),
|
|
125
125
|
}, ({ service }) =>
|
|
126
126
|
query(Effect.flatMap(TelemetryStoreReadonly, (store) => store.listRecentLogs(optional(service, config.otel.serviceName)!))),
|
|
127
127
|
).pipe(Command.withDescription("List recent logs"))
|
|
@@ -141,7 +141,7 @@ const searchLogs = Command.make("search-logs", {
|
|
|
141
141
|
}).pipe(Command.withDescription("Search logs by service, body, and attributes"))
|
|
142
142
|
|
|
143
143
|
const logStats = Command.make("log-stats", {
|
|
144
|
-
groupBy: Argument.
|
|
144
|
+
groupBy: Argument.String("groupBy"),
|
|
145
145
|
args: searchOperand,
|
|
146
146
|
}, ({ groupBy, args }) => {
|
|
147
147
|
const values = args as ReadonlyArray<string>
|
|
@@ -156,13 +156,13 @@ const logStats = Command.make("log-stats", {
|
|
|
156
156
|
}).pipe(Command.withDescription("Aggregate log metrics"))
|
|
157
157
|
|
|
158
158
|
const traceLogs = Command.make("trace-logs", {
|
|
159
|
-
traceId: Argument.
|
|
159
|
+
traceId: Argument.String("trace-id"),
|
|
160
160
|
}, ({ traceId }) =>
|
|
161
161
|
query(Effect.flatMap(TelemetryStoreReadonly, (store) => store.listTraceLogs(traceId))),
|
|
162
162
|
).pipe(Command.withDescription("List logs for one trace"))
|
|
163
163
|
|
|
164
164
|
const spanLogs = Command.make("span-logs", {
|
|
165
|
-
spanId: Argument.
|
|
165
|
+
spanId: Argument.String("span-id"),
|
|
166
166
|
}, ({ spanId }) =>
|
|
167
167
|
query(Effect.flatMap(TelemetryStoreReadonly, (store) => store.searchLogs({
|
|
168
168
|
spanId,
|
|
@@ -171,8 +171,8 @@ const spanLogs = Command.make("span-logs", {
|
|
|
171
171
|
).pipe(Command.withDescription("List logs for one span"))
|
|
172
172
|
|
|
173
173
|
const facets = Command.make("facets", {
|
|
174
|
-
type: Argument.
|
|
175
|
-
field: Argument.
|
|
174
|
+
type: Argument.Literals("type", ["traces", "logs"]),
|
|
175
|
+
field: Argument.String("field"),
|
|
176
176
|
}, ({ type, field }) =>
|
|
177
177
|
query(Effect.flatMap(TelemetryStoreReadonly, (store) => store.listFacets({ type, field, limit: 20 }))),
|
|
178
178
|
).pipe(Command.withDescription("List facet values"))
|
package/src/httpApi.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema } from "effect"
|
|
2
|
-
import { HttpApi, HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/
|
|
2
|
+
import { HttpApi, HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/http-api"
|
|
3
3
|
import {
|
|
4
4
|
AiCallSummary, AiCallDetail,
|
|
5
5
|
FacetItem, StatsItem, TraceSpanStatus,
|
package/src/localServer.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import path from "node:path"
|
|
2
2
|
import { Effect, FileSystem, Layer } from "effect"
|
|
3
3
|
import { config } from "./config.js"
|
|
4
|
-
import { HttpApiBuilder, HttpApiScalar } from "effect/
|
|
5
|
-
import * as HttpMiddleware from "effect/
|
|
6
|
-
import * as HttpRouter from "effect/
|
|
7
|
-
import * as HttpServerResponse from "effect/
|
|
8
|
-
import * as HttpStaticServer from "effect/
|
|
4
|
+
import { HttpApiBuilder, HttpApiScalar } from "effect/http-api"
|
|
5
|
+
import * as HttpMiddleware from "effect/http/HttpMiddleware"
|
|
6
|
+
import * as HttpRouter from "effect/http/HttpRouter"
|
|
7
|
+
import * as HttpServerResponse from "effect/http/HttpServerResponse"
|
|
8
|
+
import * as HttpStaticServer from "effect/http/HttpStaticServer"
|
|
9
9
|
import * as BunHttpServer from "@effect/platform-bun/BunHttpServer"
|
|
10
10
|
import { MotelHttpApi } from "./httpApi.js"
|
|
11
11
|
import { AI_LIST, LOG_LIST, LOG_STATS, SPAN_LIST, TRACE_LIST, TRACE_STATS, listMeta, logCursorArgs, paginateLogs, paginateSummaries, parseLimit, parseListParams as decodeListParams, parseLookbackMinutes, requestUrl as decodeRequestUrl, traceCursorArgs, type ListBounds, type ListParams } from "./httpListPolicy.js"
|
package/src/mcp.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { BunRuntime, BunStdio } from "@effect/platform-bun"
|
|
3
3
|
import { Effect, Layer, Logger, Schema } from "effect"
|
|
4
4
|
import { MOTEL_VERSION } from "./registry.js"
|
|
5
|
-
import { McpProtocol, McpServer, Tool, Toolkit } from "effect/
|
|
5
|
+
import { McpProtocol, McpServer, Tool, Toolkit } from "effect/ai"
|
|
6
6
|
import { TraceSpanStatus } from "./domain.js"
|
|
7
7
|
import { MotelClient, MotelClientLive } from "./motelClient.js"
|
|
8
8
|
import { Locator, LocatorLive } from "./locator.js"
|
|
@@ -433,7 +433,8 @@ const ServerLayer = McpServer.toolkit(MotelToolkit).pipe(
|
|
|
433
433
|
}),
|
|
434
434
|
),
|
|
435
435
|
Layer.provide(BunStdio.layer),
|
|
436
|
-
|
|
436
|
+
// stdout carries the MCP stdio protocol, so logs must go to stderr.
|
|
437
|
+
Layer.provide(Layer.merge(Logger.layer([Logger.consolePretty()]), Layer.succeed(Logger.LogToStderr, true))),
|
|
437
438
|
)
|
|
438
439
|
|
|
439
440
|
Layer.launch(ServerLayer).pipe(BunRuntime.runMain)
|
package/src/motel.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { BunRuntime, BunServices } from "@effect/platform-bun"
|
|
4
4
|
import { Console, Effect, Layer } from "effect"
|
|
5
|
-
import { CliOutput, Command, Flag } from "effect/
|
|
5
|
+
import { CliOutput, Command, Flag } from "effect/cli"
|
|
6
6
|
import packageJson from "../package.json" with { type: "json" }
|
|
7
7
|
import { queryCommands } from "./cli.js"
|
|
8
8
|
import { applyManagedDaemonEnv } from "./daemon.js"
|
|
@@ -40,7 +40,7 @@ const restart = Command.make("restart", {}, () =>
|
|
|
40
40
|
|
|
41
41
|
const serviceManager = createLaunchAgentManager()
|
|
42
42
|
const serviceInstall = Command.make("install", {
|
|
43
|
-
replace: Flag.
|
|
43
|
+
replace: Flag.Boolean("replace").pipe(Flag.withDefault(false)),
|
|
44
44
|
}, ({ replace }) =>
|
|
45
45
|
serviceManager.install(replace).pipe(Effect.andThen(json)),
|
|
46
46
|
).pipe(Command.withDescription("Install the per-user Motel LaunchAgent"))
|
|
@@ -20,11 +20,10 @@
|
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
22
|
import * as BunWorker from "@effect/platform-bun/BunWorker"
|
|
23
|
-
import { Context, Effect, Layer, Scope, Schema } from "effect"
|
|
24
|
-
import * as RpcClient from "effect/
|
|
25
|
-
import type { RpcClientError } from "effect/
|
|
26
|
-
import
|
|
27
|
-
import type { WorkerError } from "effect/unstable/workers/WorkerError"
|
|
23
|
+
import { Context, Effect, Latch, Layer, Scope, Schema } from "effect"
|
|
24
|
+
import * as RpcClient from "effect/rpc/RpcClient"
|
|
25
|
+
import type { RpcClientError } from "effect/rpc/RpcClientError"
|
|
26
|
+
import type { WorkerError } from "effect/workers/WorkerError"
|
|
28
27
|
import { IngestProgress, WriterEvent, type IngestReadiness } from "../ingestReadiness.ts"
|
|
29
28
|
import { IngestRpcs } from "./ingestRpc.ts"
|
|
30
29
|
|
|
@@ -52,14 +51,22 @@ export const AsyncIngestLive = Layer.effect(
|
|
|
52
51
|
const event = Schema.decodeUnknownSync(WriterEvent)(data)
|
|
53
52
|
progress.receive(event)
|
|
54
53
|
}
|
|
54
|
+
// Opens once the current worker has answered the platform handshake (or
|
|
55
|
+
// died). Effect's worker close message is only received after that
|
|
56
|
+
// handshake; one posted earlier is dropped and the platform finalizer
|
|
57
|
+
// then waits five seconds before terminating the worker.
|
|
58
|
+
let handshake = Latch.makeUnsafe(true)
|
|
55
59
|
const WorkerProtocol = RpcClient.layerProtocolWorker({ size: 1 }).pipe(
|
|
56
|
-
Layer.provide(RpcSerialization.layerMsgPack),
|
|
57
60
|
Layer.provide(BunWorker.layer(() => {
|
|
58
61
|
const worker = new Worker(new URL("./telemetryWorker.ts", import.meta.url), {
|
|
59
62
|
env: { ...process.env, MOTEL_INGEST_DIAGNOSTICS_CHANNEL: channelName },
|
|
60
63
|
})
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
const spawned = Latch.makeUnsafe(false)
|
|
65
|
+
handshake = spawned
|
|
66
|
+
const settle = () => spawned.openUnsafe()
|
|
67
|
+
worker.addEventListener("message", settle, { once: true })
|
|
68
|
+
worker.addEventListener("error", () => { settle(); progress.fail() })
|
|
69
|
+
worker.addEventListener("close", () => { settle(); progress.fail() })
|
|
63
70
|
return worker
|
|
64
71
|
})),
|
|
65
72
|
)
|
|
@@ -76,6 +83,10 @@ export const AsyncIngestLive = Layer.effect(
|
|
|
76
83
|
const getClient = yield* Effect.cached(Effect.gen(function*() {
|
|
77
84
|
const clientScope = yield* Scope.fork(scope, "sequential")
|
|
78
85
|
const protocolContext = yield* Layer.buildWithScope(WorkerProtocol, clientScope)
|
|
86
|
+
// Added after the protocol's finalizers, so it runs before them: a
|
|
87
|
+
// shutdown during worker startup waits for the handshake and then
|
|
88
|
+
// closes the writer gracefully instead of timing out and terminating it.
|
|
89
|
+
yield* Scope.addFinalizer(clientScope, Effect.suspend(() => handshake.await).pipe(Effect.timeoutOption("5 seconds")))
|
|
79
90
|
return yield* RpcClient.make(IngestRpcs).pipe(
|
|
80
91
|
Effect.provide(protocolContext),
|
|
81
92
|
Effect.provideService(Scope.Scope, clientScope),
|
|
@@ -18,8 +18,8 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
import { Schema } from "effect"
|
|
21
|
-
import * as Rpc from "effect/
|
|
22
|
-
import * as RpcGroup from "effect/
|
|
21
|
+
import * as Rpc from "effect/rpc/Rpc"
|
|
22
|
+
import * as RpcGroup from "effect/rpc/RpcGroup"
|
|
23
23
|
|
|
24
24
|
export class IngestError extends Schema.TaggedError<IngestError>()("IngestError", {
|
|
25
25
|
message: Schema.String,
|
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
import { BunRuntime } from "@effect/platform-bun"
|
|
18
18
|
import * as BunWorkerRunner from "@effect/platform-bun/BunWorkerRunner"
|
|
19
19
|
import { Effect, Layer } from "effect"
|
|
20
|
-
import * as
|
|
21
|
-
import * as RpcServer from "effect/unstable/rpc/RpcServer"
|
|
20
|
+
import * as RpcServer from "effect/rpc/RpcServer"
|
|
22
21
|
import type { OtlpLogExportRequest, OtlpTraceExportRequest } from "../otlp.ts"
|
|
23
22
|
import { WriterDiagnostics, type WriterEvent } from "../ingestReadiness.ts"
|
|
24
23
|
import { IngestError, IngestRpcs } from "./ingestRpc.ts"
|
|
@@ -57,7 +56,6 @@ const WorkerLive = RpcServer.layer(IngestRpcs).pipe(
|
|
|
57
56
|
Layer.provide(IngestHandlers),
|
|
58
57
|
Layer.provide(TelemetryStoreWorkerLive),
|
|
59
58
|
Layer.provide(RpcServer.layerProtocolWorkerRunner),
|
|
60
|
-
Layer.provide(RpcSerialization.layerMsgPack),
|
|
61
59
|
Layer.provide(BunWorkerRunner.layer),
|
|
62
60
|
)
|
|
63
61
|
|
package/src/ui/aiState.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Effect } from "effect"
|
|
2
|
-
import * as Atom from "effect/
|
|
2
|
+
import * as Atom from "effect/reactivity/Atom"
|
|
3
3
|
import type { AiCallDetail } from "../domain.ts"
|
|
4
4
|
import { queryRuntime } from "../runtime.ts"
|
|
5
5
|
import { TelemetryStoreReadonly } from "../services/TelemetryStore.ts"
|
package/src/ui/atoms.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as Atom from "effect/
|
|
1
|
+
import * as Atom from "effect/reactivity/Atom"
|
|
2
2
|
import { config, explicitServiceName } from "../config.ts"
|
|
3
3
|
import type { LogItem, TraceItem, TraceSummaryItem } from "../domain.ts"
|
|
4
4
|
import type { ThemeName } from "./theme.ts"
|
|
@@ -20,7 +20,7 @@ describe("initial TUI service selection", () => {
|
|
|
20
20
|
|
|
21
21
|
// Fresh processes exercise import-time config and persistence without module-cache leakage.
|
|
22
22
|
const result = Bun.spawnSync([process.execPath, "--no-env-file", "--eval", `
|
|
23
|
-
import * as AtomRegistry from "effect/
|
|
23
|
+
import * as AtomRegistry from "effect/reactivity/AtomRegistry"
|
|
24
24
|
import { config } from "./src/config.ts"
|
|
25
25
|
import { selectedTraceServiceAtom } from "./src/ui/atoms.ts"
|
|
26
26
|
const registry = AtomRegistry.make()
|