@knpkv/agent-usage 0.1.0 → 0.2.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.
Files changed (62) hide show
  1. package/README.md +129 -20
  2. package/dist/client/assets/index-BWajfpNv.js +55 -0
  3. package/dist/client/assets/{index-CUuLXODk.css → index-B_xl-_rU.css} +1 -1
  4. package/dist/client/index.html +2 -2
  5. package/dist/core/ClaudeLimitSamples.d.ts +30 -0
  6. package/dist/core/ClaudeLimitSamples.js +69 -0
  7. package/dist/core/ClaudeLimitSamples.js.map +1 -0
  8. package/dist/core/ClaudeLimits.d.ts +38 -4
  9. package/dist/core/ClaudeLimits.js +66 -19
  10. package/dist/core/ClaudeLimits.js.map +1 -1
  11. package/dist/core/ClaudeLimitsLive.d.ts +33 -7
  12. package/dist/core/ClaudeLimitsLive.js +54 -10
  13. package/dist/core/ClaudeLimitsLive.js.map +1 -1
  14. package/dist/core/Database.d.ts +9 -1
  15. package/dist/core/Database.js +6 -2
  16. package/dist/core/Database.js.map +1 -1
  17. package/dist/core/Ingest.d.ts +7 -1
  18. package/dist/core/Ingest.js +36 -6
  19. package/dist/core/Ingest.js.map +1 -1
  20. package/dist/core/Model.d.ts +19 -7
  21. package/dist/core/Model.js +15 -3
  22. package/dist/core/Model.js.map +1 -1
  23. package/dist/core/Report.js +21 -7
  24. package/dist/core/Report.js.map +1 -1
  25. package/dist/core/Store.js +14 -12
  26. package/dist/core/Store.js.map +1 -1
  27. package/dist/main.js +30 -20
  28. package/dist/main.js.map +1 -1
  29. package/dist/server/Api.d.ts +130 -94
  30. package/dist/server/Config.d.ts +22 -3
  31. package/dist/server/Config.js +66 -4
  32. package/dist/server/Config.js.map +1 -1
  33. package/dist/server/ControlSocket.d.ts +73 -0
  34. package/dist/server/ControlSocket.js +270 -0
  35. package/dist/server/ControlSocket.js.map +1 -0
  36. package/dist/server/HttpApplication.d.ts +1 -1
  37. package/dist/server/HttpApplication.js +2 -1
  38. package/dist/server/HttpApplication.js.map +1 -1
  39. package/dist/server/IngestSummary.d.ts +8 -0
  40. package/dist/server/IngestSummary.js +32 -0
  41. package/dist/server/IngestSummary.js.map +1 -0
  42. package/dist/server/Live.d.ts +4 -0
  43. package/dist/server/Live.js +49 -0
  44. package/dist/server/Live.js.map +1 -0
  45. package/dist/server/Login.d.ts +34 -0
  46. package/dist/server/Login.js +74 -0
  47. package/dist/server/Login.js.map +1 -0
  48. package/dist/server/OwnerSession.d.ts +15 -8
  49. package/dist/server/OwnerSession.js +33 -25
  50. package/dist/server/OwnerSession.js.map +1 -1
  51. package/dist/server/Runtime.d.ts +3 -1
  52. package/dist/server/Runtime.js +32 -8
  53. package/dist/server/Runtime.js.map +1 -1
  54. package/dist/server/Server.d.ts +2 -2
  55. package/dist/server/Server.js +19 -6
  56. package/dist/server/Server.js.map +1 -1
  57. package/dist/shared/contracts.d.ts +51 -6
  58. package/dist/shared/contracts.js +11 -1
  59. package/dist/shared/contracts.js.map +1 -1
  60. package/dist/tsconfig.tsbuildinfo +1 -1
  61. package/package.json +3 -3
  62. package/dist/client/assets/index-DB-VXWqy.js +0 -55
@@ -0,0 +1,73 @@
1
+ import { Duration, Effect, FileSystem, Path, Schema } from "effect";
2
+ import { type OwnerSessionSecretsContract } from "./OwnerSession.js";
3
+ export declare const SOCKET_FILE = "serve.sock";
4
+ export declare const LOCK_FILE = "serve.lock";
5
+ /**
6
+ * The longest socket path, in bytes, that binds everywhere this runs: macOS holds 104 bytes
7
+ * including the terminating NUL, Linux 108.
8
+ */
9
+ export declare const SOCKET_PATH_LIMIT = 103;
10
+ /** How long either side waits for the other before giving up on one exchange. */
11
+ export declare const EXCHANGE_DEADLINE: Duration.Duration;
12
+ declare const ServerNotRunning_base: Schema.Class<ServerNotRunning, Schema.TaggedStruct<"ServerNotRunning", {
13
+ readonly path: Schema.String;
14
+ }>, import("effect/Cause").YieldableError>;
15
+ /** No server is listening on this store: start `agent-usage serve`. */
16
+ export declare class ServerNotRunning extends ServerNotRunning_base {
17
+ get message(): string;
18
+ }
19
+ declare const ServerAlreadyRunning_base: Schema.Class<ServerAlreadyRunning, Schema.TaggedStruct<"ServerAlreadyRunning", {
20
+ readonly path: Schema.String;
21
+ }>, import("effect/Cause").YieldableError>;
22
+ /** A server already runs on this store; a second one would fight it for the store. */
23
+ export declare class ServerAlreadyRunning extends ServerAlreadyRunning_base {
24
+ get message(): string;
25
+ }
26
+ declare const SocketPathUnsafe_base: Schema.Class<SocketPathUnsafe, Schema.TaggedStruct<"SocketPathUnsafe", {
27
+ readonly path: Schema.String;
28
+ readonly reason: Schema.String;
29
+ }>, import("effect/Cause").YieldableError>;
30
+ /** Something at the socket path is not this user's socket: a symlink, a plain file, a foreign owner. */
31
+ export declare class SocketPathUnsafe extends SocketPathUnsafe_base {
32
+ get message(): string;
33
+ }
34
+ declare const SocketRefused_base: Schema.Class<SocketRefused, Schema.TaggedStruct<"SocketRefused", {
35
+ readonly path: Schema.String;
36
+ readonly reason: Schema.String;
37
+ }>, import("effect/Cause").YieldableError>;
38
+ /** The socket or lock is there but could not be used: no permission, no answer in time, or another failure. */
39
+ export declare class SocketRefused extends SocketRefused_base {
40
+ get message(): string;
41
+ }
42
+ declare const SocketPathTooLong_base: Schema.Class<SocketPathTooLong, Schema.TaggedStruct<"SocketPathTooLong", {
43
+ readonly path: Schema.String;
44
+ readonly bytes: Schema.Number;
45
+ }>, import("effect/Cause").YieldableError>;
46
+ /** The store directory is too deep for a Unix socket path, so this store has no `login`. */
47
+ export declare class SocketPathTooLong extends SocketPathTooLong_base {
48
+ get message(): string;
49
+ }
50
+ declare const LoginReplyInvalid_base: Schema.Class<LoginReplyInvalid, Schema.TaggedStruct<"LoginReplyInvalid", {
51
+ readonly reply: Schema.String;
52
+ }>, import("effect/Cause").YieldableError>;
53
+ /** The server answered with something that is not a link. */
54
+ export declare class LoginReplyInvalid extends LoginReplyInvalid_base {
55
+ }
56
+ /**
57
+ * Holds the store's lock and listens on `<directory>/serve.sock` for the life of the scope; returns
58
+ * the socket path, or nothing (and logs why) when the path is too long for a Unix socket. Requests
59
+ * wait for `listening` before a link is minted. Fails with {@link ServerAlreadyRunning} when another
60
+ * server runs on this store and {@link SocketPathUnsafe} when the path holds anything but this
61
+ * user's socket.
62
+ */
63
+ export declare const controlSocket: (directory: string, secrets: OwnerSessionSecretsContract, listening: Effect.Effect<void, never, never>) => Effect.Effect<string | undefined, ServerAlreadyRunning | SocketPathUnsafe | SocketRefused | import("../core/Store.js").StoreError, import("effect/Crypto").Crypto | FileSystem.FileSystem | Path.Path | import("effect/reactivity/Reactivity").Reactivity | import("effect/Scope").Scope>;
64
+ /**
65
+ * Asks the server running on this store for a fresh one-time link, trusting only a socket owned by
66
+ * `self`, the user id this process runs as. Fails with
67
+ * {@link ServerNotRunning} when nothing listens, {@link SocketPathTooLong} when the store has no
68
+ * control socket, {@link SocketPathUnsafe} when the path is not this user's socket,
69
+ * {@link SocketRefused} when the socket may not be used or does not answer within
70
+ * {@link EXCHANGE_DEADLINE}, and {@link LoginReplyInvalid} when the answer is not a link.
71
+ */
72
+ export declare const requestLoginUrl: (directory: string, self: number) => Effect.Effect<string, LoginReplyInvalid | ServerNotRunning | SocketPathTooLong | SocketPathUnsafe | SocketRefused, FileSystem.FileSystem | Path.Path>;
73
+ export {};
@@ -0,0 +1,270 @@
1
+ /**
2
+ * The control socket `agent-usage login` asks the running server for a fresh one-time link over.
3
+ *
4
+ * **Mental model**
5
+ *
6
+ * - **The store directory is the door.** The socket is `serve.sock` in the store directory, which
7
+ * the database layer keeps owner-only (`0700`); the socket itself is `0600`. Reaching it already
8
+ * proves the caller is the owner, so the request needs no credential of its own.
9
+ * - **Nothing at the path is trusted.** A symlink, a file that is not a socket, or a socket another
10
+ * user owns is refused, by the server before binding and by `login` before connecting.
11
+ * - **One server per store, held by a lock the kernel keeps.** Before anything else the server
12
+ * takes an exclusive SQLite lock on `serve.lock` in the store directory and keeps it for its life;
13
+ * the operating system drops it when the process ends, however it ends. A second server finds it
14
+ * taken and refuses to start. Holding the lock, the server knows any socket at the path is one a
15
+ * dead server left behind, so it removes it and binds; no probing, no race between servers.
16
+ * - **Short paths only.** A Unix socket path is limited to about a hundred bytes. A store directory
17
+ * too deep for one still runs and still holds the lock, without `login`, and says so.
18
+ * - **One question, one answer.** The client sends `mint`; once the HTTP listener is up, the server
19
+ * mints a link through the same path as the startup link (one use, one minute) and replies with it
20
+ * as one JSON line. Both sides give up after {@link EXCHANGE_DEADLINE}.
21
+ *
22
+ * @module
23
+ */
24
+ import { NodeSocket, NodeSocketServer } from "@effect/platform-node";
25
+ import { SqliteClient } from "@effect/sql-sqlite-node";
26
+ import { PairingCode } from "@knpkv/browser-pairing/schema";
27
+ import { Duration, Effect, FileSystem, Option, Path, Predicate, Schema } from "effect";
28
+ import { prepareStoreDirectory } from "../core/Database.js";
29
+ import { isLoopbackHostname, mintBootstrapUrl } from "./OwnerSession.js";
30
+ export const SOCKET_FILE = "serve.sock";
31
+ export const LOCK_FILE = "serve.lock";
32
+ /**
33
+ * The longest socket path, in bytes, that binds everywhere this runs: macOS holds 104 bytes
34
+ * including the terminating NUL, Linux 108.
35
+ */
36
+ export const SOCKET_PATH_LIMIT = 103;
37
+ /** How long either side waits for the other before giving up on one exchange. */
38
+ export const EXCHANGE_DEADLINE = Duration.seconds(5);
39
+ /** No server is listening on this store: start `agent-usage serve`. */
40
+ export class ServerNotRunning extends Schema.TaggedError()("ServerNotRunning", {
41
+ path: Schema.String
42
+ }) {
43
+ get message() {
44
+ return `no agent-usage server is listening at ${this.path}`;
45
+ }
46
+ }
47
+ /** A server already runs on this store; a second one would fight it for the store. */
48
+ export class ServerAlreadyRunning extends Schema.TaggedError()("ServerAlreadyRunning", {
49
+ path: Schema.String
50
+ }) {
51
+ get message() {
52
+ return `agent-usage is already running on this store (${this.path}); use \`agent-usage login\` to get in`;
53
+ }
54
+ }
55
+ /** Something at the socket path is not this user's socket: a symlink, a plain file, a foreign owner. */
56
+ export class SocketPathUnsafe extends Schema.TaggedError()("SocketPathUnsafe", {
57
+ path: Schema.String,
58
+ reason: Schema.String
59
+ }) {
60
+ get message() {
61
+ return `refusing the control socket at ${this.path}: ${this.reason}`;
62
+ }
63
+ }
64
+ /** The socket or lock is there but could not be used: no permission, no answer in time, or another failure. */
65
+ export class SocketRefused extends Schema.TaggedError()("SocketRefused", {
66
+ path: Schema.String,
67
+ reason: Schema.String
68
+ }) {
69
+ get message() {
70
+ return `the control socket at ${this.path} could not be used (${this.reason})`;
71
+ }
72
+ }
73
+ /** The store directory is too deep for a Unix socket path, so this store has no `login`. */
74
+ export class SocketPathTooLong extends Schema.TaggedError()("SocketPathTooLong", {
75
+ path: Schema.String,
76
+ bytes: Schema.Number
77
+ }) {
78
+ get message() {
79
+ return `the control socket path ${this.path} is ${this.bytes} bytes, over the ${SOCKET_PATH_LIMIT}-byte limit for a Unix socket`;
80
+ }
81
+ }
82
+ /** The server answered with something that is not a link. */
83
+ export class LoginReplyInvalid extends Schema.TaggedError()("LoginReplyInvalid", {
84
+ reply: Schema.String
85
+ }) {
86
+ }
87
+ const isPairingCode = Schema.is(PairingCode);
88
+ /**
89
+ * A sign-in link as this server mints them: plain HTTP, a loopback host, and in the fragment a code
90
+ * of the shape the page will accept.
91
+ */
92
+ const isLoginUrl = (value) => {
93
+ if (!URL.canParse(value))
94
+ return false;
95
+ const url = new URL(value);
96
+ const prefix = "#bootstrap_token=";
97
+ return url.protocol === "http:" && isLoopbackHostname(url.hostname) && url.pathname === "/" &&
98
+ url.search === "" && url.hash.startsWith(prefix) && isPairingCode(url.hash.slice(prefix.length));
99
+ };
100
+ const LoginUrl = Schema.String.check(Schema.makeFilter(isLoginUrl, { expected: "a loopback link carrying a one-time code" }));
101
+ const LoginReply = Schema.fromJsonString(Schema.Struct({ url: LoginUrl }));
102
+ const encodeReply = Schema.encodeSync(LoginReply);
103
+ const decodeReply = Schema.decodeUnknownOption(LoginReply);
104
+ /** A Node system error, as far as this module reads one. */
105
+ const Errno = Schema.Struct({ code: Schema.String });
106
+ const decodeErrno = Schema.decodeUnknownOption(Errno);
107
+ /** The system error code (`ECONNREFUSED`, `EACCES`, `EEXIST`) behind a filesystem or socket failure. */
108
+ const errnoOf = (failure) => {
109
+ const cause = failure._tag === "PlatformError" ? failure.cause : failure.reason.cause;
110
+ return Option.getOrUndefined(Option.map(decodeErrno(cause), (errno) => errno.code));
111
+ };
112
+ /** `readlink` on something that is not a link fails with EINVAL; nothing else means "not a link". */
113
+ const isNotALink = (error) => errnoOf(error) === "EINVAL";
114
+ /** The socket path for a store, refused when it is too long to bind. */
115
+ const socketPathFor = Effect.fnUntraced(function* (directory) {
116
+ const path = yield* Path.Path;
117
+ const socketPath = path.join(directory, SOCKET_FILE);
118
+ const bytes = new TextEncoder().encode(socketPath).byteLength;
119
+ if (bytes > SOCKET_PATH_LIMIT)
120
+ return yield* new SocketPathTooLong({ path: socketPath, bytes });
121
+ return socketPath;
122
+ });
123
+ /**
124
+ * What is at `socketPath`: nothing, or a socket owned by `self` (this process's user id) in a store
125
+ * directory `self` also owns. Anything else is refused: another account could have bound it.
126
+ */
127
+ const inspect = Effect.fnUntraced(function* (directory, socketPath, self) {
128
+ const fs = yield* FileSystem.FileSystem;
129
+ const unsafe = (reason) => new SocketPathUnsafe({ path: socketPath, reason });
130
+ const link = yield* Effect.result(fs.readLink(socketPath));
131
+ if (link._tag === "Success")
132
+ return yield* unsafe("it is a symbolic link");
133
+ if (link.failure.reason._tag === "NotFound")
134
+ return undefined;
135
+ if (!isNotALink(link.failure))
136
+ return yield* unsafe(`it could not be inspected (${link.failure.reason._tag})`);
137
+ const [info, store] = yield* Effect.all([fs.stat(socketPath), fs.stat(directory)]).pipe(Effect.mapError((error) => unsafe(`it could not be inspected (${error.reason._tag})`)));
138
+ if (Option.getOrUndefined(store.uid) !== self)
139
+ return yield* unsafe("another user owns the store directory");
140
+ if (info.type !== "Socket")
141
+ return yield* unsafe(`it is a ${info.type}, not a socket`);
142
+ if (Option.getOrUndefined(info.uid) !== self)
143
+ return yield* unsafe("another user owns it");
144
+ return { inode: Option.getOrUndefined(info.ino) };
145
+ });
146
+ /**
147
+ * Reads from an open connection until a full line arrives or the peer closes it. The reader must be
148
+ * acquired before anything is written: acquiring it is what opens the connection.
149
+ */
150
+ const readLine = (reader) => Effect.gen(function* () {
151
+ const decoder = new TextDecoder();
152
+ let text = "";
153
+ while (!text.includes("\n")) {
154
+ const batch = yield* Effect.result(reader.pull);
155
+ if (batch._tag === "Failure") {
156
+ if (batch.failure.reason._tag === "SocketCloseError")
157
+ return text;
158
+ return yield* batch.failure;
159
+ }
160
+ for (const chunk of batch.success)
161
+ text += Predicate.isString(chunk) ? chunk : decoder.decode(chunk);
162
+ }
163
+ return text;
164
+ });
165
+ /** One connection: a `mint` request answered with a fresh link, anything else with an error. */
166
+ const answer = (secrets, listening) => (socket) => Effect.scoped(Effect.gen(function* () {
167
+ const reader = yield* socket.reader;
168
+ const write = yield* socket.writer;
169
+ const request = yield* readLine(reader);
170
+ if (request.trim() !== "mint")
171
+ return yield* write.write("{\"error\":\"unknown request\"}\n");
172
+ // Never before the HTTP listener is up: a code minted earlier would be one nobody could spend.
173
+ yield* listening;
174
+ const url = yield* mintBootstrapUrl(secrets);
175
+ yield* write.write(`${encodeReply({ url })}\n`);
176
+ })).pipe(Effect.timeout(EXCHANGE_DEADLINE), Effect.ignore);
177
+ /**
178
+ * Takes the store's exclusive lock for the life of the scope: an SQLite database opened in exclusive
179
+ * locking mode and written once, so its lock is held until the connection closes or the process
180
+ * ends. Fails with {@link ServerAlreadyRunning} when another server holds it.
181
+ */
182
+ const holdStoreLock = Effect.fnUntraced(function* (directory) {
183
+ const fs = yield* FileSystem.FileSystem;
184
+ const path = yield* Path.Path;
185
+ const lockPath = path.join(directory, LOCK_FILE);
186
+ const link = yield* Effect.result(fs.readLink(lockPath));
187
+ if (link._tag === "Success")
188
+ return yield* new SocketPathUnsafe({ path: lockPath, reason: "it is a symbolic link" });
189
+ const client = yield* SqliteClient.make({ filename: lockPath, disableWAL: true, busyTimeout: 0 });
190
+ yield* Effect.all([
191
+ client.unsafe("PRAGMA locking_mode = EXCLUSIVE"),
192
+ client.unsafe("BEGIN EXCLUSIVE"),
193
+ client.unsafe("COMMIT")
194
+ ], { discard: true }).pipe(Effect.mapError((error) => error.reason._tag === "LockTimeoutError"
195
+ ? new ServerAlreadyRunning({ path: lockPath })
196
+ : new SocketRefused({ path: lockPath, reason: error.reason._tag })));
197
+ yield* fs.chmod(lockPath, 0o600).pipe(Effect.mapError((error) => new SocketPathUnsafe({ path: lockPath, reason: error.reason._tag })));
198
+ // This process just created or opened it for writing: its owner is who this process runs as.
199
+ const info = yield* fs.stat(lockPath).pipe(Effect.mapError((error) => new SocketPathUnsafe({ path: lockPath, reason: error.reason._tag })));
200
+ const self = Option.getOrUndefined(info.uid);
201
+ if (self === undefined)
202
+ return yield* new SocketPathUnsafe({ path: lockPath, reason: "it has no owner to compare" });
203
+ return self;
204
+ });
205
+ /**
206
+ * Holds the store's lock and listens on `<directory>/serve.sock` for the life of the scope; returns
207
+ * the socket path, or nothing (and logs why) when the path is too long for a Unix socket. Requests
208
+ * wait for `listening` before a link is minted. Fails with {@link ServerAlreadyRunning} when another
209
+ * server runs on this store and {@link SocketPathUnsafe} when the path holds anything but this
210
+ * user's socket.
211
+ */
212
+ export const controlSocket = Effect.fn("ControlSocket.listen")(function* (directory, secrets, listening) {
213
+ const fs = yield* FileSystem.FileSystem;
214
+ // The directory must be the store's, checked, before its lock is taken inside it.
215
+ yield* prepareStoreDirectory(directory);
216
+ const self = yield* holdStoreLock(directory);
217
+ const located = yield* Effect.result(socketPathFor(directory));
218
+ if (located._tag === "Failure") {
219
+ yield* Effect.logWarning(`agent-usage login is unavailable: ${located.failure.message}`);
220
+ return undefined;
221
+ }
222
+ const socketPath = located.success;
223
+ // With the lock held, a socket here is one a server that died left behind.
224
+ const found = yield* inspect(directory, socketPath, self);
225
+ if (found !== undefined) {
226
+ yield* fs.remove(socketPath).pipe(Effect.mapError((error) => new SocketPathUnsafe({ path: socketPath, reason: error.reason._tag })));
227
+ }
228
+ const server = yield* NodeSocketServer.make({ path: socketPath }).pipe(Effect.mapError((error) => new SocketRefused({ path: socketPath, reason: errnoOf(error) ?? error.reason._tag })));
229
+ yield* Effect.addFinalizer(() => fs.remove(socketPath).pipe(Effect.ignore));
230
+ yield* fs.chmod(socketPath, 0o600).pipe(Effect.mapError((error) => new SocketPathUnsafe({ path: socketPath, reason: error.reason._tag })));
231
+ if ((yield* inspect(directory, socketPath, self)) === undefined) {
232
+ return yield* new SocketPathUnsafe({ path: socketPath, reason: "it vanished after binding" });
233
+ }
234
+ yield* Effect.forkScoped(server.run(answer(secrets, listening)));
235
+ return socketPath;
236
+ });
237
+ /**
238
+ * Asks the server running on this store for a fresh one-time link, trusting only a socket owned by
239
+ * `self`, the user id this process runs as. Fails with
240
+ * {@link ServerNotRunning} when nothing listens, {@link SocketPathTooLong} when the store has no
241
+ * control socket, {@link SocketPathUnsafe} when the path is not this user's socket,
242
+ * {@link SocketRefused} when the socket may not be used or does not answer within
243
+ * {@link EXCHANGE_DEADLINE}, and {@link LoginReplyInvalid} when the answer is not a link.
244
+ */
245
+ export const requestLoginUrl = Effect.fn("ControlSocket.requestLoginUrl")(function* (directory, self) {
246
+ const socketPath = yield* socketPathFor(directory);
247
+ const found = yield* inspect(directory, socketPath, self);
248
+ if (found === undefined)
249
+ return yield* new ServerNotRunning({ path: socketPath });
250
+ const reply = yield* Effect.scoped(Effect.gen(function* () {
251
+ const socket = yield* NodeSocket.makeNet({ path: socketPath });
252
+ const reader = yield* socket.reader;
253
+ const write = yield* socket.writer;
254
+ yield* write.write("mint\n");
255
+ return yield* readLine(reader);
256
+ })).pipe(Effect.mapError((error) => {
257
+ const code = errnoOf(error);
258
+ return code === "ECONNREFUSED" || code === "ENOENT"
259
+ ? new ServerNotRunning({ path: socketPath })
260
+ : new SocketRefused({ path: socketPath, reason: code ?? error.reason._tag });
261
+ }), Effect.timeoutOrElse({
262
+ duration: EXCHANGE_DEADLINE,
263
+ orElse: () => Effect.fail(new SocketRefused({ path: socketPath, reason: "the server did not answer in time" }))
264
+ }));
265
+ const decoded = decodeReply(reply.trim());
266
+ if (Option.isNone(decoded))
267
+ return yield* new LoginReplyInvalid({ reply: reply.trim().slice(0, 200) });
268
+ return decoded.value.url;
269
+ });
270
+ //# sourceMappingURL=ControlSocket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ControlSocket.js","sourceRoot":"","sources":["../../src/server/ControlSocket.ts"],"names":[],"mappings":"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"}
@@ -4,4 +4,4 @@ import { HttpRouter } from "effect/http";
4
4
  /** True only when `candidate` is `root` itself or one of its path-segment descendants. */
5
5
  export declare const isWithinDirectory: (path: Path.Path, root: string, candidate: string) => boolean;
6
6
  /** Supply the store, runtime state and owner secrets; listener and platform belong to the executable. */
7
- export declare const application: Layer.Layer<never, never, FileSystem.FileSystem | import("effect/http/Etag").Generator | import("effect/http/HttpPlatform").HttpPlatform | HttpRouter.HttpRouter | import("./OwnerSession.js").OwnerSessionSecrets | Path.Path | HttpRouter.Request<"Error", import("effect/PlatformError").BadArgument> | HttpRouter.Request<"Error", import("effect/http/HttpBody").HttpBodyError> | HttpRouter.Request<"Error", import("effect/PlatformError").PlatformError> | HttpRouter.Request<"Requires", FileSystem.FileSystem> | HttpRouter.Request<"Requires", import("./OwnerSession.js").OwnerSessionSecrets> | HttpRouter.Request<"Requires", Path.Path> | import("./Runtime.js").RuntimeState | import("../core/Store.js").UsageStore>;
7
+ export declare const application: Layer.Layer<never, never, FileSystem.FileSystem | import("effect/http/Etag").Generator | import("effect/http/HttpPlatform").HttpPlatform | HttpRouter.HttpRouter | import("./OwnerSession.js").OwnerSessionSecrets | Path.Path | HttpRouter.Request<"Error", import("effect/PlatformError").BadArgument> | HttpRouter.Request<"Error", import("effect/http/HttpBody").HttpBodyError> | HttpRouter.Request<"Error", import("effect/PlatformError").PlatformError> | HttpRouter.Request<"Error", import("effect/socket/Socket").SocketError> | HttpRouter.Request<"Requires", FileSystem.FileSystem> | HttpRouter.Request<"Requires", import("./OwnerSession.js").OwnerSessionSecrets> | HttpRouter.Request<"Requires", Path.Path> | HttpRouter.Request<"Requires", import("./Runtime.js").RuntimeState> | import("./Runtime.js").RuntimeState | import("../core/Store.js").UsageStore>;
@@ -4,6 +4,7 @@ import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/http";
4
4
  import { HttpApiBuilder } from "effect/http-api";
5
5
  import { AgentUsageApi } from "./Api.js";
6
6
  import { UsageLive } from "./Handlers.js";
7
+ import { LiveRouter } from "./Live.js";
7
8
  import { ownerSessionAuthLayer, OwnerSessionBootstrapRouter } from "./OwnerSession.js";
8
9
  const mimeTypes = new Map([
9
10
  [".css", "text/css"],
@@ -66,5 +67,5 @@ const StaticRouter = HttpRouter.use((router) => router.add("GET", "/*", serveSta
66
67
  const NoStore = HttpRouter.middleware((httpEffect) => Effect.map(httpEffect, HttpServerResponse.setHeader("cache-control", "private, no-store")));
67
68
  const ApiRoutes = HttpApiBuilder.layer(AgentUsageApi).pipe(Layer.provide(UsageLive), Layer.provide(ownerSessionAuthLayer), Layer.provide(NoStore.layer));
68
69
  /** Supply the store, runtime state and owner secrets; listener and platform belong to the executable. */
69
- export const application = Layer.mergeAll(ApiRoutes, OwnerSessionBootstrapRouter, StaticRouter).pipe(Layer.orDie);
70
+ export const application = Layer.mergeAll(ApiRoutes, OwnerSessionBootstrapRouter, LiveRouter, StaticRouter).pipe(Layer.orDie);
70
71
  //# sourceMappingURL=HttpApplication.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"HttpApplication.js","sourceRoot":"","sources":["../../src/server/HttpApplication.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"HttpApplication.js","sourceRoot":"","sources":["../../src/server/HttpApplication.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The plain-text summary `agent-usage ingest` prints after one pass: a line per source, then how
3
+ * long the pass took.
4
+ *
5
+ * @module
6
+ */
7
+ import type { IngestStatus } from "../core/Ingest.js";
8
+ export declare const describeIngest: (status: IngestStatus) => ReadonlyArray<string>;
@@ -0,0 +1,32 @@
1
+ const skippedLines = (status) => status.skipped.unparseableLine + status.skipped.missingTimestamp + status.skipped.oversizedLine;
2
+ const describeSource = (name, status) => {
3
+ if (status.rootMissing)
4
+ return `${name}: no sessions directory`;
5
+ const skipped = skippedLines(status);
6
+ return [
7
+ `${name}: ${status.filesRead}/${status.filesScanned} files read, ${status.eventsAdded} events added`,
8
+ skipped > 0 ? `, ${skipped} lines skipped` : "",
9
+ status.unreadable.length > 0 ? `, ${status.unreadable.length} unreadable` : ""
10
+ ].join("");
11
+ };
12
+ /** The claude-statusline limit log: absent until claude-statusline has written one. */
13
+ const describeLimitLog = (status) => {
14
+ if (status.rootMissing)
15
+ return "claude-statusline limits: none logged yet";
16
+ if (status.filesRead === 0 && status.unreadable.length > 0) {
17
+ return `claude-statusline limits: unreadable (${status.unreadable.map((entry) => entry.reason).join(", ")})`;
18
+ }
19
+ const skipped = skippedLines(status);
20
+ return [
21
+ "claude-statusline limits: read",
22
+ skipped > 0 ? `, ${skipped} lines skipped` : "",
23
+ status.unreadable.length > 0 ? `, unreadable (${status.unreadable.map((entry) => entry.reason).join(", ")})` : ""
24
+ ].join("");
25
+ };
26
+ export const describeIngest = (status) => [
27
+ describeSource("claude", status.claude),
28
+ describeSource("codex", status.codex),
29
+ describeLimitLog(status.claudeLimitSamples),
30
+ `took ${status.finishedAt - status.startedAt}ms`
31
+ ];
32
+ //# sourceMappingURL=IngestSummary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IngestSummary.js","sourceRoot":"","sources":["../../src/server/IngestSummary.ts"],"names":[],"mappings":"AAQA,MAAM,YAAY,GAAG,CAAC,MAAoB,EAAU,EAAE,CACpD,MAAM,CAAC,OAAO,CAAC,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAA;AAEjG,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,MAAoB,EAAU,EAAE;IACpE,IAAI,MAAM,CAAC,WAAW;QAAE,OAAO,GAAG,IAAI,yBAAyB,CAAA;IAC/D,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IACpC,OAAO;QACL,GAAG,IAAI,KAAK,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,YAAY,gBAAgB,MAAM,CAAC,WAAW,eAAe;QACpG,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,gBAAgB,CAAC,CAAC,CAAC,EAAE;QAC/C,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,UAAU,CAAC,MAAM,aAAa,CAAC,CAAC,CAAC,EAAE;KAC/E,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACZ,CAAC,CAAA;AAED,uFAAuF;AACvF,MAAM,gBAAgB,GAAG,CAAC,MAAoB,EAAU,EAAE;IACxD,IAAI,MAAM,CAAC,WAAW;QAAE,OAAO,2CAA2C,CAAA;IAC1E,IAAI,MAAM,CAAC,SAAS,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3D,OAAO,yCAAyC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAA;IAC9G,CAAC;IACD,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IACpC,OAAO;QACL,gCAAgC;QAChC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,OAAO,gBAAgB,CAAC,CAAC,CAAC,EAAE;QAC/C,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;KAClH,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACZ,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAoB,EAAyB,EAAE,CAAC;IAC7E,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC;IACvC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC;IACrC,gBAAgB,CAAC,MAAM,CAAC,kBAAkB,CAAC;IAC3C,QAAQ,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,SAAS,IAAI;CACjD,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { HttpRouter } from "effect/http";
2
+ import { OwnerSessionSecrets } from "./OwnerSession.js";
3
+ import { RuntimeState } from "./Runtime.js";
4
+ export declare const LiveRouter: import("effect/Layer").Layer<never, never, HttpRouter.HttpRouter | HttpRouter.Request<"Error", import("effect/socket/Socket").SocketError> | HttpRouter.Request<"Requires", OwnerSessionSecrets> | HttpRouter.Request<"Requires", RuntimeState>>;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * The live-updates socket: `GET /api/live` upgrades to a WebSocket that sends the current
3
+ * {@link LiveVersions} and then every change, so the page refetches a read only when it moved.
4
+ *
5
+ * **Mental model**
6
+ *
7
+ * - **The same door as every read.** The upgrade is admitted by the owner-session check the API
8
+ * uses, unchanged: the session cookie, the page's own origin, Fetch Metadata, a read method.
9
+ * Anything else is refused before the socket exists.
10
+ * - **Versions, not data.** A message names which reads moved; the page fetches them through the
11
+ * ordinary authenticated routes, so the socket adds no second path to the data.
12
+ * - **Moved after commit.** The runtime moves a counter once the store holds the change, so a
13
+ * refetch triggered by a message always sees it.
14
+ *
15
+ * @module
16
+ */
17
+ import { Effect, Schema, Stream, SubscriptionRef } from "effect";
18
+ import { HttpRouter, HttpServerRequest, HttpServerResponse } from "effect/http";
19
+ import { LiveVersions } from "../shared/contracts.js";
20
+ import { authorizeOwnerRequest, OwnerSessionSecrets } from "./OwnerSession.js";
21
+ import { RuntimeState } from "./Runtime.js";
22
+ const encodeVersions = Schema.encodeSync(Schema.fromJsonString(LiveVersions));
23
+ const refusal = (status, message) => HttpServerResponse.text(message, { status, headers: { "cache-control": "private, no-store" } });
24
+ const live = Effect.gen(function* () {
25
+ const request = yield* HttpServerRequest.HttpServerRequest;
26
+ const secrets = yield* OwnerSessionSecrets;
27
+ const state = yield* RuntimeState;
28
+ const admitted = yield* Effect.result(authorizeOwnerRequest({
29
+ credential: request.cookies["agent_usage_owner"] ?? "",
30
+ fetchSite: request.headers["sec-fetch-site"],
31
+ method: request.method,
32
+ origin: request.headers.origin
33
+ }, secrets));
34
+ if (admitted._tag === "Failure") {
35
+ return admitted.failure._tag === "UnauthorizedApiError"
36
+ ? refusal(401, admitted.failure.message)
37
+ : refusal(403, admitted.failure.message);
38
+ }
39
+ const socket = yield* request.upgrade;
40
+ const write = yield* socket.writer;
41
+ const reader = yield* socket.reader;
42
+ // Messages from the page are not expected; reading only notices that it went away.
43
+ const closed = Effect.forever(reader.pull).pipe(Effect.ignore);
44
+ const pushing = SubscriptionRef.changes(state.versions).pipe(Stream.runForEach((versions) => write.write(encodeVersions(versions))), Effect.ignore);
45
+ yield* Effect.raceFirst(pushing, closed);
46
+ return HttpServerResponse.empty();
47
+ }).pipe(Effect.scoped, Effect.catchTag("HttpServerError", () => Effect.succeed(refusal(403, "Not a WebSocket upgrade"))));
48
+ export const LiveRouter = HttpRouter.use((router) => router.add("GET", "/api/live", live));
49
+ //# sourceMappingURL=Live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Live.js","sourceRoot":"","sources":["../../src/server/Live.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AAChE,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAC9E,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,MAAM,cAAc,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,CAAA;AAE7E,MAAM,OAAO,GAAG,CAAC,MAAiB,EAAE,OAAe,EAAE,EAAE,CACrD,kBAAkB,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,eAAe,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAA;AAEjG,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,iBAAiB,CAAC,iBAAiB,CAAA;IAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,mBAAmB,CAAA;IAC1C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,YAAY,CAAA;IACjC,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,CACzD;QACE,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,IAAI,EAAE;QACtD,SAAS,EAAE,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC;QAC5C,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,MAAM;KAC/B,EACD,OAAO,CACR,CAAC,CAAA;IACF,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,sBAAsB;YACrD,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;YACxC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5C,CAAC;IACD,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAA;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAA;IAClC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAA;IACnC,mFAAmF;IACnF,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC9D,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC1D,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,EACtE,MAAM,CAAC,MAAM,CACd,CAAA;IACD,KAAK,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IACxC,OAAO,kBAAkB,CAAC,KAAK,EAAE,CAAA;AACnC,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,MAAM,EACb,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,yBAAyB,CAAC,CAAC,CAAC,CAClG,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAA"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `agent-usage login`: a fresh one-time link from the running server, printed and optionally opened.
3
+ *
4
+ * The link goes to stdout and nowhere else, like the startup link: it is the credential. Failures
5
+ * go to stderr as one sentence saying what to do, and end the process with a nonzero exit.
6
+ *
7
+ * @module
8
+ */
9
+ import { Effect, Runtime, Schema } from "effect";
10
+ import { ChildProcessSpawner } from "effect/process";
11
+ import { type LoginReplyInvalid, type ServerNotRunning, type SocketPathTooLong, type SocketPathUnsafe, type SocketRefused } from "./ControlSocket.js";
12
+ export type LoginFailure = ServerNotRunning | SocketPathTooLong | SocketPathUnsafe | SocketRefused | LoginReplyInvalid;
13
+ declare const LoginFailed_base: Schema.Class<LoginFailed, Schema.TaggedStruct<"LoginFailed", {
14
+ readonly reason: Schema.String;
15
+ }>, import("effect/Cause").YieldableError>;
16
+ /** The failure, already explained on stderr: the runtime exits nonzero without logging it again. */
17
+ export declare class LoginFailed extends LoginFailed_base {
18
+ readonly [Runtime.errorReported] = false;
19
+ }
20
+ /** One sentence per failure, naming what to do about it. */
21
+ export declare const describeLoginFailure: (failure: LoginFailure) => string;
22
+ /** The command that opens a URL in the default browser, where there is one this tool knows. */
23
+ export declare const openerFor: (platform: string) => "open" | "xdg-open" | undefined;
24
+ /**
25
+ * Reads the store directory from `config`, asks the server running there for a link, prints it, and
26
+ * opens it when asked. Every failure, an unreadable configuration included, goes to stderr only, so
27
+ * stdout carries the link or nothing.
28
+ */
29
+ export declare const login: <E extends {
30
+ readonly message: string;
31
+ }, R>(config: Effect.Effect<{
32
+ readonly storeDirectory: string;
33
+ }, E, R>, open: boolean, platform: string, self: number) => Effect.Effect<void, LoginFailed, R | ChildProcessSpawner.ChildProcessSpawner | import("effect/FileSystem").FileSystem | import("effect/Path").Path>;
34
+ export {};