@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
package/dist/main.js CHANGED
@@ -4,23 +4,38 @@
4
4
  *
5
5
  * - `agent-usage serve` ingests every minute, polls Claude limits every five, and prints the URL
6
6
  * that gets you in.
7
+ * - `agent-usage login [--open]` asks the running server for a fresh one-time link and prints it.
7
8
  * - `agent-usage ingest [--json]` runs one ingest pass and reports what it found.
8
9
  *
9
10
  * @module
10
11
  */
11
12
  import { NodeRuntime, NodeServices } from "@effect/platform-node";
12
- import { Console, Deferred, Effect, Fiber, Layer, Option, Schema } from "effect";
13
+ import { ConfigProvider, Console, Deferred, Effect, Fiber, Layer, Option, Schema } from "effect";
13
14
  import { Command, Flag } from "effect/cli";
14
15
  import * as Stdio from "effect/Stdio";
15
16
  import * as Stream from "effect/Stream";
16
- import { hostname } from "node:os";
17
+ import { hostname, platform, userInfo } from "node:os";
18
+ // Read at run time from the package.json this file ships next to (`dist/../package.json`).
19
+ import pkg from "../package.json" with { type: "json" };
17
20
  import { databaseLayer } from "./core/Database.js";
18
21
  import { ingestOnce } from "./core/Ingest.js";
19
22
  import { loadConfig } from "./server/Config.js";
20
- import { makeOwnerSessionSecrets, ownerSessionOrigin, ownerSessionUrl } from "./server/OwnerSession.js";
23
+ import { describeIngest } from "./server/IngestSummary.js";
24
+ import { login as requestLogin } from "./server/Login.js";
25
+ import { makeOwnerSessionSecrets, ownerSessionOrigin } from "./server/OwnerSession.js";
21
26
  import { makeServer, Port, PublicOrigin } from "./server/Server.js";
22
27
  import { IngestStatus as IngestStatusSchema } from "./shared/contracts.js";
23
- const config = loadConfig(hostname());
28
+ /** The operating system's name for the user; Claude Code's own fallback when it cannot ask. */
29
+ const osUserName = () => {
30
+ try {
31
+ return userInfo().username;
32
+ }
33
+ catch {
34
+ return "claude-code-user";
35
+ }
36
+ };
37
+ // Empty values kept, for the one variable where an empty value means something.
38
+ const config = loadConfig(hostname(), ConfigProvider.fromEnv({ preserveEmptyStrings: true }), osUserName());
24
39
  const serve = Command.make("serve", {}, Effect.fn(function* () {
25
40
  const stdio = yield* Stdio.Stdio;
26
41
  const settings = yield* config;
@@ -29,21 +44,12 @@ const serve = Command.make("serve", {}, Effect.fn(function* () {
29
44
  const security = yield* makeOwnerSessionSecrets(ownerSessionOrigin("127.0.0.1", port), Option.getOrUndefined(configuredOrigin));
30
45
  const ready = yield* Deferred.make();
31
46
  const server = yield* Layer.launch(makeServer({ config: settings, port, ready, security })).pipe(Effect.forkChild({ startImmediately: true }));
32
- yield* Effect.raceFirst(Deferred.await(ready), Fiber.join(server));
47
+ // The server only ends this race by failing; until it is listening there is no link to print.
48
+ const url = yield* Effect.raceFirst(Deferred.await(ready), Fiber.join(server).pipe(Effect.andThen(Effect.never)));
33
49
  // On stdout and nowhere else: this line is the credential, so it is never logged.
34
- yield* Stream.make(`agent usage: ${ownerSessionUrl(security.browserOrigin, security)}\n`).pipe(Stream.run(stdio.stdout()));
50
+ yield* Stream.make(`agent usage: ${url}\n`).pipe(Stream.run(stdio.stdout()));
35
51
  return yield* Fiber.join(server);
36
52
  })).pipe(Command.withDescription("Record usage continuously and serve the browser view"));
37
- const describeSource = (name, status) => {
38
- if (status.rootMissing)
39
- return `${name}: no sessions directory`;
40
- const skipped = status.skipped.unparseableLine + status.skipped.missingTimestamp + status.skipped.oversizedLine;
41
- return [
42
- `${name}: ${status.filesRead}/${status.filesScanned} files read, ${status.eventsAdded} events added`,
43
- skipped > 0 ? `, ${skipped} lines skipped` : "",
44
- status.unreadable.length > 0 ? `, ${status.unreadable.length} unreadable` : ""
45
- ].join("");
46
- };
47
53
  const encodeStatus = Schema.encodeSync(Schema.fromJsonString(IngestStatusSchema));
48
54
  const ingest = Command.make("ingest", {
49
55
  json: Flag.Boolean("json").pipe(Flag.withDescription("Print the status as one JSON value"), Flag.withDefault(false))
@@ -55,11 +61,15 @@ const ingest = Command.make("ingest", {
55
61
  Effect.provide(databaseLayer(settings.storeDirectory)));
56
62
  if (json)
57
63
  return yield* Console.log(encodeStatus(status));
58
- yield* Console.log(describeSource("claude", status.claude));
59
- yield* Console.log(describeSource("codex", status.codex));
60
- yield* Console.log(`took ${status.finishedAt - status.startedAt}ms`);
64
+ for (const line of describeIngest(status))
65
+ yield* Console.log(line);
61
66
  })).pipe(Command.withDescription("Run one ingest pass and report what it found"));
62
- const cli = Command.make("agent-usage").pipe(Command.withDescription("Claude and Codex subscription usage over time, per ticket and against limits"), Command.withSubcommands([serve, ingest]), Command.run({ version: "0.1.0" }));
67
+ const login = Command.make("login", {
68
+ open: Flag.Boolean("open").pipe(Flag.withDescription("Open the link in the browser too"), Flag.withDefault(false))
69
+ },
70
+ // The user id `login` trusts the socket to belong to; -1 (no POSIX ids) matches no owner.
71
+ ({ open }) => requestLogin(config, open, platform(), process.geteuid?.() ?? -1)).pipe(Command.withDescription("Print a fresh one-time link to the running server"));
72
+ const cli = Command.make("agent-usage").pipe(Command.withDescription("Claude and Codex subscription usage over time, per ticket and against limits"), Command.withSubcommands([serve, login, ingest]), Command.run({ version: pkg.version }));
63
73
  // Executable entry point: the host platform is provided once for this process.
64
74
  NodeRuntime.runMain(cli.pipe(Effect.provide(NodeServices.layer)));
65
75
  //# sourceMappingURL=main.js.map
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"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"}
@@ -30,14 +30,15 @@ declare const UsageApiGroup_base: HttpApiGroup.HttpApiGroup<"usage", HttpApiEndp
30
30
  readonly usedPercent: import("effect/Schema").Finite;
31
31
  readonly resetsAt: import("effect/Schema").NullOr<import("effect/Schema").Int>;
32
32
  }>, import("effect/Schema").TaggedStruct<"Unknown", {
33
- readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "NotSupported", "Fetch", "Parse", "NoData"]>;
33
+ readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "KeychainDenied", "NotSupported", "Fetch", "Parse", "NoData"]>;
34
+ readonly detail: import("effect/Schema").optionalKey<import("effect/Schema").String>;
34
35
  }>]>;
35
36
  }>>;
36
37
  }>>;
37
38
  readonly latest: import("effect/Schema").$Array<import("effect/Schema").Struct<{
38
39
  readonly agent: import("effect/Schema").Literals<readonly ["claude", "codex"]>;
39
40
  readonly machine: import("effect/Schema").NonEmptyString;
40
- readonly source: import("effect/Schema").Literals<readonly ["claude-oauth-usage", "codex-rollout"]>;
41
+ readonly source: import("effect/Schema").Literals<readonly ["claude-oauth-usage", "claude-statusline", "codex-rollout"]>;
41
42
  readonly label: import("effect/Schema").NonEmptyString;
42
43
  readonly windowMinutes: import("effect/Schema").NullOr<import("effect/Schema").Int>;
43
44
  readonly observedAt: import("effect/Schema").Int;
@@ -45,7 +46,8 @@ declare const UsageApiGroup_base: HttpApiGroup.HttpApiGroup<"usage", HttpApiEndp
45
46
  readonly usedPercent: import("effect/Schema").Finite;
46
47
  readonly resetsAt: import("effect/Schema").NullOr<import("effect/Schema").Int>;
47
48
  }>, import("effect/Schema").TaggedStruct<"Unknown", {
48
- readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "NotSupported", "Fetch", "Parse", "NoData"]>;
49
+ readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "KeychainDenied", "NotSupported", "Fetch", "Parse", "NoData"]>;
50
+ readonly detail: import("effect/Schema").optionalKey<import("effect/Schema").String>;
49
51
  }>]>;
50
52
  }>>;
51
53
  readonly balances: import("effect/Schema").$Array<import("effect/Schema").Struct<{
@@ -62,7 +64,8 @@ declare const UsageApiGroup_base: HttpApiGroup.HttpApiGroup<"usage", HttpApiEndp
62
64
  readonly credits: import("effect/Schema").Finite;
63
65
  }>, import("effect/Schema").TaggedStruct<"Unlimited", {}>, import("effect/Schema").TaggedStruct<"Exhausted", {}>, import("effect/Schema").TaggedStruct<"Disabled", {}>]>;
64
66
  }>, import("effect/Schema").TaggedStruct<"Unknown", {
65
- readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "NotSupported", "Fetch", "Parse", "NoData"]>;
67
+ readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "KeychainDenied", "NotSupported", "Fetch", "Parse", "NoData"]>;
68
+ readonly detail: import("effect/Schema").optionalKey<import("effect/Schema").String>;
66
69
  }>]>;
67
70
  }>>;
68
71
  }>>, import("effect/Schema").toCodecJson<typeof ApiError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"status", "GET", "/api/status", never, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
@@ -100,6 +103,21 @@ declare const UsageApiGroup_base: HttpApiGroup.HttpApiGroup<"usage", HttpApiEndp
100
103
  readonly reason: import("effect/Schema").String;
101
104
  }>>;
102
105
  }>;
106
+ readonly claudeLimitSamples: import("effect/Schema").Struct<{
107
+ readonly rootMissing: import("effect/Schema").Boolean;
108
+ readonly filesScanned: import("effect/Schema").Int;
109
+ readonly filesRead: import("effect/Schema").Int;
110
+ readonly eventsAdded: import("effect/Schema").Int;
111
+ readonly skipped: import("effect/Schema").Struct<{
112
+ readonly unparseableLine: import("effect/Schema").Int;
113
+ readonly missingTimestamp: import("effect/Schema").Int;
114
+ readonly oversizedLine: import("effect/Schema").Int;
115
+ }>;
116
+ readonly unreadable: import("effect/Schema").$Array<import("effect/Schema").Struct<{
117
+ readonly fileKey: import("effect/Schema").String;
118
+ readonly reason: import("effect/Schema").String;
119
+ }>>;
120
+ }>;
103
121
  }>>;
104
122
  readonly ingestFailure: import("effect/Schema").NullOr<import("effect/Schema").String>;
105
123
  readonly limitsFailure: import("effect/Schema").NullOr<import("effect/Schema").String>;
@@ -159,7 +177,113 @@ declare const UsageApiGroup_base: HttpApiGroup.HttpApiGroup<"usage", HttpApiEndp
159
177
  }>>, import("effect/Schema").toCodecJson<typeof ApiError>, never, never>, false>;
160
178
  export declare class UsageApiGroup extends UsageApiGroup_base {
161
179
  }
162
- declare const AgentUsageApi_base: HttpApi.HttpApi<"AgentUsageApi", HttpApiGroup.HttpApiGroup<"usage", HttpApiEndpoint.HttpApiEndpoint<"usage", "GET", "/api/usage", never, import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
180
+ declare const AgentUsageApi_base: HttpApi.HttpApi<"AgentUsageApi", HttpApiGroup.HttpApiGroup<"usage", HttpApiEndpoint.HttpApiEndpoint<"status", "GET", "/api/status", never, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
181
+ readonly machine: import("effect/Schema").String;
182
+ readonly ingest: import("effect/Schema").NullOr<import("effect/Schema").Struct<{
183
+ readonly startedAt: import("effect/Schema").Int;
184
+ readonly finishedAt: import("effect/Schema").Int;
185
+ readonly claude: import("effect/Schema").Struct<{
186
+ readonly rootMissing: import("effect/Schema").Boolean;
187
+ readonly filesScanned: import("effect/Schema").Int;
188
+ readonly filesRead: import("effect/Schema").Int;
189
+ readonly eventsAdded: import("effect/Schema").Int;
190
+ readonly skipped: import("effect/Schema").Struct<{
191
+ readonly unparseableLine: import("effect/Schema").Int;
192
+ readonly missingTimestamp: import("effect/Schema").Int;
193
+ readonly oversizedLine: import("effect/Schema").Int;
194
+ }>;
195
+ readonly unreadable: import("effect/Schema").$Array<import("effect/Schema").Struct<{
196
+ readonly fileKey: import("effect/Schema").String;
197
+ readonly reason: import("effect/Schema").String;
198
+ }>>;
199
+ }>;
200
+ readonly codex: import("effect/Schema").Struct<{
201
+ readonly rootMissing: import("effect/Schema").Boolean;
202
+ readonly filesScanned: import("effect/Schema").Int;
203
+ readonly filesRead: import("effect/Schema").Int;
204
+ readonly eventsAdded: import("effect/Schema").Int;
205
+ readonly skipped: import("effect/Schema").Struct<{
206
+ readonly unparseableLine: import("effect/Schema").Int;
207
+ readonly missingTimestamp: import("effect/Schema").Int;
208
+ readonly oversizedLine: import("effect/Schema").Int;
209
+ }>;
210
+ readonly unreadable: import("effect/Schema").$Array<import("effect/Schema").Struct<{
211
+ readonly fileKey: import("effect/Schema").String;
212
+ readonly reason: import("effect/Schema").String;
213
+ }>>;
214
+ }>;
215
+ readonly claudeLimitSamples: import("effect/Schema").Struct<{
216
+ readonly rootMissing: import("effect/Schema").Boolean;
217
+ readonly filesScanned: import("effect/Schema").Int;
218
+ readonly filesRead: import("effect/Schema").Int;
219
+ readonly eventsAdded: import("effect/Schema").Int;
220
+ readonly skipped: import("effect/Schema").Struct<{
221
+ readonly unparseableLine: import("effect/Schema").Int;
222
+ readonly missingTimestamp: import("effect/Schema").Int;
223
+ readonly oversizedLine: import("effect/Schema").Int;
224
+ }>;
225
+ readonly unreadable: import("effect/Schema").$Array<import("effect/Schema").Struct<{
226
+ readonly fileKey: import("effect/Schema").String;
227
+ readonly reason: import("effect/Schema").String;
228
+ }>>;
229
+ }>;
230
+ }>>;
231
+ readonly ingestFailure: import("effect/Schema").NullOr<import("effect/Schema").String>;
232
+ readonly limitsFailure: import("effect/Schema").NullOr<import("effect/Schema").String>;
233
+ readonly ticketLookupFailures: import("effect/Schema").$Array<import("effect/Schema").String>;
234
+ }>>, never, OwnerSessionAuth, never> | HttpApiEndpoint.HttpApiEndpoint<"limits", "GET", "/api/limits", never, import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
235
+ readonly from: import("effect/Schema").compose<import("effect/Schema").Int, import("effect/Schema").NumberFromString>;
236
+ readonly to: import("effect/Schema").compose<import("effect/Schema").Int, import("effect/Schema").NumberFromString>;
237
+ }>>, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
238
+ readonly series: import("effect/Schema").$Array<import("effect/Schema").Struct<{
239
+ readonly agent: import("effect/Schema").Literals<readonly ["claude", "codex"]>;
240
+ readonly label: import("effect/Schema").String;
241
+ readonly windowMinutes: import("effect/Schema").NullOr<import("effect/Schema").Int>;
242
+ readonly points: import("effect/Schema").$Array<import("effect/Schema").Struct<{
243
+ readonly at: import("effect/Schema").Int;
244
+ readonly reading: import("effect/Schema").Union<readonly [import("effect/Schema").TaggedStruct<"Known", {
245
+ readonly usedPercent: import("effect/Schema").Finite;
246
+ readonly resetsAt: import("effect/Schema").NullOr<import("effect/Schema").Int>;
247
+ }>, import("effect/Schema").TaggedStruct<"Unknown", {
248
+ readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "KeychainDenied", "NotSupported", "Fetch", "Parse", "NoData"]>;
249
+ readonly detail: import("effect/Schema").optionalKey<import("effect/Schema").String>;
250
+ }>]>;
251
+ }>>;
252
+ }>>;
253
+ readonly latest: import("effect/Schema").$Array<import("effect/Schema").Struct<{
254
+ readonly agent: import("effect/Schema").Literals<readonly ["claude", "codex"]>;
255
+ readonly machine: import("effect/Schema").NonEmptyString;
256
+ readonly source: import("effect/Schema").Literals<readonly ["claude-oauth-usage", "claude-statusline", "codex-rollout"]>;
257
+ readonly label: import("effect/Schema").NonEmptyString;
258
+ readonly windowMinutes: import("effect/Schema").NullOr<import("effect/Schema").Int>;
259
+ readonly observedAt: import("effect/Schema").Int;
260
+ readonly reading: import("effect/Schema").Union<readonly [import("effect/Schema").TaggedStruct<"Known", {
261
+ readonly usedPercent: import("effect/Schema").Finite;
262
+ readonly resetsAt: import("effect/Schema").NullOr<import("effect/Schema").Int>;
263
+ }>, import("effect/Schema").TaggedStruct<"Unknown", {
264
+ readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "KeychainDenied", "NotSupported", "Fetch", "Parse", "NoData"]>;
265
+ readonly detail: import("effect/Schema").optionalKey<import("effect/Schema").String>;
266
+ }>]>;
267
+ }>>;
268
+ readonly balances: import("effect/Schema").$Array<import("effect/Schema").Struct<{
269
+ readonly kind: import("effect/Schema").Literals<readonly ["claude-extra-usage", "codex-credits"]>;
270
+ readonly machine: import("effect/Schema").NonEmptyString;
271
+ readonly observedAt: import("effect/Schema").Int;
272
+ readonly value: import("effect/Schema").Union<readonly [import("effect/Schema").TaggedStruct<"Known", {
273
+ readonly balance: import("effect/Schema").Union<readonly [import("effect/Schema").TaggedStruct<"Amount", {
274
+ readonly leftMinor: import("effect/Schema").Finite;
275
+ readonly limitMinor: import("effect/Schema").Finite;
276
+ readonly decimals: import("effect/Schema").Int;
277
+ readonly currency: import("effect/Schema").String;
278
+ }>, import("effect/Schema").TaggedStruct<"Credits", {
279
+ readonly credits: import("effect/Schema").Finite;
280
+ }>, import("effect/Schema").TaggedStruct<"Unlimited", {}>, import("effect/Schema").TaggedStruct<"Exhausted", {}>, import("effect/Schema").TaggedStruct<"Disabled", {}>]>;
281
+ }>, import("effect/Schema").TaggedStruct<"Unknown", {
282
+ readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "KeychainDenied", "NotSupported", "Fetch", "Parse", "NoData"]>;
283
+ readonly detail: import("effect/Schema").optionalKey<import("effect/Schema").String>;
284
+ }>]>;
285
+ }>>;
286
+ }>>, import("effect/Schema").toCodecJson<typeof ApiError>, OwnerSessionAuth, never> | HttpApiEndpoint.HttpApiEndpoint<"usage", "GET", "/api/usage", never, import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
163
287
  readonly from: import("effect/Schema").compose<import("effect/Schema").Int, import("effect/Schema").NumberFromString>;
164
288
  readonly to: import("effect/Schema").compose<import("effect/Schema").Int, import("effect/Schema").NumberFromString>;
165
289
  readonly timeZone: import("effect/Schema").String;
@@ -211,94 +335,6 @@ declare const AgentUsageApi_base: HttpApi.HttpApi<"AgentUsageApi", HttpApiGroup.
211
335
  readonly prefix: import("effect/Schema").String;
212
336
  readonly requests: import("effect/Schema").Int;
213
337
  }>>;
214
- }>>, import("effect/Schema").toCodecJson<typeof ApiError>, OwnerSessionAuth, never> | HttpApiEndpoint.HttpApiEndpoint<"limits", "GET", "/api/limits", never, import("effect/Schema").toCodecStringTree<import("effect/Schema").Struct<{
215
- readonly from: import("effect/Schema").compose<import("effect/Schema").Int, import("effect/Schema").NumberFromString>;
216
- readonly to: import("effect/Schema").compose<import("effect/Schema").Int, import("effect/Schema").NumberFromString>;
217
- }>>, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
218
- readonly series: import("effect/Schema").$Array<import("effect/Schema").Struct<{
219
- readonly agent: import("effect/Schema").Literals<readonly ["claude", "codex"]>;
220
- readonly label: import("effect/Schema").String;
221
- readonly windowMinutes: import("effect/Schema").NullOr<import("effect/Schema").Int>;
222
- readonly points: import("effect/Schema").$Array<import("effect/Schema").Struct<{
223
- readonly at: import("effect/Schema").Int;
224
- readonly reading: import("effect/Schema").Union<readonly [import("effect/Schema").TaggedStruct<"Known", {
225
- readonly usedPercent: import("effect/Schema").Finite;
226
- readonly resetsAt: import("effect/Schema").NullOr<import("effect/Schema").Int>;
227
- }>, import("effect/Schema").TaggedStruct<"Unknown", {
228
- readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "NotSupported", "Fetch", "Parse", "NoData"]>;
229
- }>]>;
230
- }>>;
231
- }>>;
232
- readonly latest: import("effect/Schema").$Array<import("effect/Schema").Struct<{
233
- readonly agent: import("effect/Schema").Literals<readonly ["claude", "codex"]>;
234
- readonly machine: import("effect/Schema").NonEmptyString;
235
- readonly source: import("effect/Schema").Literals<readonly ["claude-oauth-usage", "codex-rollout"]>;
236
- readonly label: import("effect/Schema").NonEmptyString;
237
- readonly windowMinutes: import("effect/Schema").NullOr<import("effect/Schema").Int>;
238
- readonly observedAt: import("effect/Schema").Int;
239
- readonly reading: import("effect/Schema").Union<readonly [import("effect/Schema").TaggedStruct<"Known", {
240
- readonly usedPercent: import("effect/Schema").Finite;
241
- readonly resetsAt: import("effect/Schema").NullOr<import("effect/Schema").Int>;
242
- }>, import("effect/Schema").TaggedStruct<"Unknown", {
243
- readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "NotSupported", "Fetch", "Parse", "NoData"]>;
244
- }>]>;
245
- }>>;
246
- readonly balances: import("effect/Schema").$Array<import("effect/Schema").Struct<{
247
- readonly kind: import("effect/Schema").Literals<readonly ["claude-extra-usage", "codex-credits"]>;
248
- readonly machine: import("effect/Schema").NonEmptyString;
249
- readonly observedAt: import("effect/Schema").Int;
250
- readonly value: import("effect/Schema").Union<readonly [import("effect/Schema").TaggedStruct<"Known", {
251
- readonly balance: import("effect/Schema").Union<readonly [import("effect/Schema").TaggedStruct<"Amount", {
252
- readonly leftMinor: import("effect/Schema").Finite;
253
- readonly limitMinor: import("effect/Schema").Finite;
254
- readonly decimals: import("effect/Schema").Int;
255
- readonly currency: import("effect/Schema").String;
256
- }>, import("effect/Schema").TaggedStruct<"Credits", {
257
- readonly credits: import("effect/Schema").Finite;
258
- }>, import("effect/Schema").TaggedStruct<"Unlimited", {}>, import("effect/Schema").TaggedStruct<"Exhausted", {}>, import("effect/Schema").TaggedStruct<"Disabled", {}>]>;
259
- }>, import("effect/Schema").TaggedStruct<"Unknown", {
260
- readonly reason: import("effect/Schema").Literals<readonly ["NoAuth", "AuthExpired", "NotSupported", "Fetch", "Parse", "NoData"]>;
261
- }>]>;
262
- }>>;
263
- }>>, import("effect/Schema").toCodecJson<typeof ApiError>, OwnerSessionAuth, never> | HttpApiEndpoint.HttpApiEndpoint<"status", "GET", "/api/status", never, never, never, never, import("effect/Schema").toCodecJson<import("effect/Schema").Struct<{
264
- readonly machine: import("effect/Schema").String;
265
- readonly ingest: import("effect/Schema").NullOr<import("effect/Schema").Struct<{
266
- readonly startedAt: import("effect/Schema").Int;
267
- readonly finishedAt: import("effect/Schema").Int;
268
- readonly claude: import("effect/Schema").Struct<{
269
- readonly rootMissing: import("effect/Schema").Boolean;
270
- readonly filesScanned: import("effect/Schema").Int;
271
- readonly filesRead: import("effect/Schema").Int;
272
- readonly eventsAdded: import("effect/Schema").Int;
273
- readonly skipped: import("effect/Schema").Struct<{
274
- readonly unparseableLine: import("effect/Schema").Int;
275
- readonly missingTimestamp: import("effect/Schema").Int;
276
- readonly oversizedLine: import("effect/Schema").Int;
277
- }>;
278
- readonly unreadable: import("effect/Schema").$Array<import("effect/Schema").Struct<{
279
- readonly fileKey: import("effect/Schema").String;
280
- readonly reason: import("effect/Schema").String;
281
- }>>;
282
- }>;
283
- readonly codex: import("effect/Schema").Struct<{
284
- readonly rootMissing: import("effect/Schema").Boolean;
285
- readonly filesScanned: import("effect/Schema").Int;
286
- readonly filesRead: import("effect/Schema").Int;
287
- readonly eventsAdded: import("effect/Schema").Int;
288
- readonly skipped: import("effect/Schema").Struct<{
289
- readonly unparseableLine: import("effect/Schema").Int;
290
- readonly missingTimestamp: import("effect/Schema").Int;
291
- readonly oversizedLine: import("effect/Schema").Int;
292
- }>;
293
- readonly unreadable: import("effect/Schema").$Array<import("effect/Schema").Struct<{
294
- readonly fileKey: import("effect/Schema").String;
295
- readonly reason: import("effect/Schema").String;
296
- }>>;
297
- }>;
298
- }>>;
299
- readonly ingestFailure: import("effect/Schema").NullOr<import("effect/Schema").String>;
300
- readonly limitsFailure: import("effect/Schema").NullOr<import("effect/Schema").String>;
301
- readonly ticketLookupFailures: import("effect/Schema").$Array<import("effect/Schema").String>;
302
- }>>, never, OwnerSessionAuth, never>, false>>;
338
+ }>>, import("effect/Schema").toCodecJson<typeof ApiError>, OwnerSessionAuth, never>, false>>;
303
339
  export declare class AgentUsageApi extends AgentUsageApi_base {
304
340
  }
@@ -4,18 +4,32 @@
4
4
  * - `AGENT_USAGE_HOME` — the store directory (default `~/.local/share/agent-usage`)
5
5
  * - `AGENT_USAGE_MACHINE` — the Machine name (default: the short, lower-cased hostname)
6
6
  * - `CLAUDE_CONFIG_DIR` / `CODEX_HOME` — the agents' own roots (default `~/.claude`, `~/.codex`)
7
+ * - `CLAUDE_SECURESTORAGE_CONFIG_DIR` — where Claude Code keeps its credentials when it differs from
8
+ * the config directory; with `CLAUDE_CONFIG_DIR` it decides the macOS Keychain item's name
9
+ * - `AGENT_USAGE_CLAUDE_LIMITS` — the Claude limit samples claude-statusline appends (default
10
+ * `${XDG_STATE_HOME:-~/.local/state}/agent-usage/claude-limits.jsonl`)
7
11
  * - `AGENT_USAGE_PROJECTS` — extra Known Projects, comma-separated (`RPS,ABC`), for projects typed in
8
12
  * sessions before any branch named them
9
13
  *
10
14
  * @module
11
15
  */
12
- import { Config, Effect, Path } from "effect";
16
+ import { Config, ConfigProvider, Crypto, Effect, Path } from "effect";
13
17
  import type { SourceRoots } from "../core/Ingest.js";
18
+ /** Where Claude Code keeps the OAuth credentials a limit poll reads. */
19
+ export interface ClaudeCredentialsLocation {
20
+ /** Linux: `<secure storage dir>/.credentials.json`. */
21
+ readonly file: string;
22
+ /** macOS: the login Keychain item's service name… */
23
+ readonly keychainService: string;
24
+ /** …and its account, the user name. */
25
+ readonly keychainAccount: string;
26
+ }
14
27
  export interface AgentUsageConfig {
15
28
  readonly storeDirectory: string;
16
29
  /** Known Projects from configuration, added to those branches and paths name. */
17
30
  readonly projects: ReadonlyArray<string>;
18
31
  readonly claudeConfigDir: string;
32
+ readonly claudeCredentials: ClaudeCredentialsLocation;
19
33
  readonly roots: SourceRoots;
20
34
  }
21
35
  /**
@@ -23,5 +37,10 @@ export interface AgentUsageConfig {
23
37
  * `Example-MacBook.local` and `Example-MacBook` name the same Machine.
24
38
  */
25
39
  export declare const machineName: (hostname: string) => string;
26
- /** Reads the configuration; `hostname` comes from the executable, the only place that may ask. */
27
- export declare const loadConfig: (hostname: string) => Effect.Effect<AgentUsageConfig, Config.ConfigError, Path.Path>;
40
+ /**
41
+ * Reads the configuration; `hostname` comes from the executable, the only place that may ask.
42
+ * `exactEnvironment` is the environment with empty values kept, which the executable builds; it
43
+ * is read only where an empty value means something (`CLAUDE_SECURESTORAGE_CONFIG_DIR`).
44
+ * `osUser` is the operating system's name for the user, the Keychain account when `USER` is unset.
45
+ */
46
+ export declare const loadConfig: (hostname: string, exactEnvironment?: ConfigProvider.ConfigProvider, osUser?: string) => Effect.Effect<AgentUsageConfig, Config.ConfigError | import("effect/PlatformError").PlatformError, Crypto.Crypto | Path.Path>;
@@ -4,12 +4,49 @@
4
4
  * - `AGENT_USAGE_HOME` — the store directory (default `~/.local/share/agent-usage`)
5
5
  * - `AGENT_USAGE_MACHINE` — the Machine name (default: the short, lower-cased hostname)
6
6
  * - `CLAUDE_CONFIG_DIR` / `CODEX_HOME` — the agents' own roots (default `~/.claude`, `~/.codex`)
7
+ * - `CLAUDE_SECURESTORAGE_CONFIG_DIR` — where Claude Code keeps its credentials when it differs from
8
+ * the config directory; with `CLAUDE_CONFIG_DIR` it decides the macOS Keychain item's name
9
+ * - `AGENT_USAGE_CLAUDE_LIMITS` — the Claude limit samples claude-statusline appends (default
10
+ * `${XDG_STATE_HOME:-~/.local/state}/agent-usage/claude-limits.jsonl`)
7
11
  * - `AGENT_USAGE_PROJECTS` — extra Known Projects, comma-separated (`RPS,ABC`), for projects typed in
8
12
  * sessions before any branch named them
9
13
  *
10
14
  * @module
11
15
  */
12
- import { Config, Effect, Path, Schema, SchemaTransformation } from "effect";
16
+ import { Config, ConfigProvider, Crypto, Effect, Path, Schema, SchemaTransformation } from "effect";
17
+ import { Hex } from "effect/encoding";
18
+ const KEYCHAIN_SERVICE = "Claude Code-credentials";
19
+ /**
20
+ * Where Claude Code (2.1.289) keeps its credentials, named the way it names them. The secure-storage
21
+ * directory is `CLAUDE_SECURESTORAGE_CONFIG_DIR` when set (empty meaning the default `~/.claude`),
22
+ * else the config directory. The Keychain item is `Claude Code-credentials`, suffixed with the first
23
+ * eight hex digits of the directory's SHA-256 whenever a non-default directory was chosen, under the
24
+ * user's account. Asking for the bare name with a custom directory reads another account's item.
25
+ *
26
+ * An explicitly empty `CLAUDE_SECURESTORAGE_CONFIG_DIR` means the default directory and the bare
27
+ * item name, as in Claude Code, so it is read from an environment that keeps empty values.
28
+ */
29
+ const claudeCredentialsLocation = (options) => Effect.gen(function* () {
30
+ const path = yield* Path.Path;
31
+ const digests = yield* Crypto.Crypto;
32
+ const unsuffixed = options.secureStorageDir === undefined
33
+ ? !options.configDirChosen
34
+ : options.secureStorageDir === "";
35
+ const directory = (options.secureStorageDir === undefined
36
+ ? options.claudeConfigDir
37
+ : options.secureStorageDir === ""
38
+ ? path.join(options.home, ".claude")
39
+ : options.secureStorageDir).normalize("NFC");
40
+ const suffix = unsuffixed
41
+ ? ""
42
+ : `-${Hex.encode(yield* digests.digest("SHA-256", new TextEncoder().encode(directory))).slice(0, 8)}`;
43
+ const location = {
44
+ file: path.join(directory, ".credentials.json"),
45
+ keychainService: `${KEYCHAIN_SERVICE}${suffix}`,
46
+ keychainAccount: options.user
47
+ };
48
+ return location;
49
+ });
13
50
  /**
14
51
  * The Machine name a hostname gives: the part before the first dot, lower-cased, so macOS's
15
52
  * `Example-MacBook.local` and `Example-MacBook` name the same Machine.
@@ -25,22 +62,47 @@ const Projects = Schema.String.pipe(Schema.decodeTo(Schema.Array(ProjectKey), Sc
25
62
  decode: (raw) => raw.split(",").map((entry) => entry.trim()).filter((entry) => entry !== ""),
26
63
  encode: (keys) => keys.join(",")
27
64
  })));
28
- /** Reads the configuration; `hostname` comes from the executable, the only place that may ask. */
29
- export const loadConfig = (hostname) => Effect.gen(function* () {
65
+ /**
66
+ * Reads the configuration; `hostname` comes from the executable, the only place that may ask.
67
+ * `exactEnvironment` is the environment with empty values kept, which the executable builds; it
68
+ * is read only where an empty value means something (`CLAUDE_SECURESTORAGE_CONFIG_DIR`).
69
+ * `osUser` is the operating system's name for the user, the Keychain account when `USER` is unset.
70
+ */
71
+ export const loadConfig = (hostname, exactEnvironment, osUser = "claude-code-user") => Effect.gen(function* () {
30
72
  const path = yield* Path.Path;
31
73
  const home = yield* Config.String("HOME");
32
74
  const storeDirectory = yield* Config.String("AGENT_USAGE_HOME").pipe(Config.withDefault(path.join(home, ".local", "share", "agent-usage")));
33
75
  const machine = yield* Config.NonEmptyString("AGENT_USAGE_MACHINE").pipe(Config.withDefault(machineName(hostname)));
34
- const claudeConfigDir = yield* Config.String("CLAUDE_CONFIG_DIR").pipe(Config.withDefault(path.join(home, ".claude")));
76
+ const chosenConfigDir = yield* Config.option(Config.String("CLAUDE_CONFIG_DIR"));
77
+ const claudeConfigDir = chosenConfigDir._tag === "Some" ? chosenConfigDir.value : path.join(home, ".claude");
78
+ const secureStorageRead = Config.option(Config.String("CLAUDE_SECURESTORAGE_CONFIG_DIR"));
79
+ const secureStorageDir = yield* (exactEnvironment === undefined
80
+ ? secureStorageRead
81
+ : secureStorageRead.pipe(Effect.provideService(ConfigProvider.ConfigProvider, exactEnvironment)));
82
+ // The Keychain account, as Claude Code names it: USER, else the OS user, kept only when it is a
83
+ // plain name.
84
+ const named = yield* Config.String("USER").pipe(Config.withDefault(osUser));
85
+ const user = /^[a-zA-Z0-9._-]+$/u.test(named) ? named : "claude-code-user";
86
+ const claudeCredentials = yield* claudeCredentialsLocation({
87
+ home,
88
+ user,
89
+ claudeConfigDir,
90
+ configDirChosen: chosenConfigDir._tag === "Some",
91
+ secureStorageDir: secureStorageDir._tag === "Some" ? secureStorageDir.value : undefined
92
+ });
93
+ const stateHome = yield* Config.String("XDG_STATE_HOME").pipe(Config.withDefault(path.join(home, ".local", "state")));
94
+ const claudeLimitSamples = yield* Config.String("AGENT_USAGE_CLAUDE_LIMITS").pipe(Config.withDefault(path.join(stateHome, "agent-usage", "claude-limits.jsonl")));
35
95
  const codexHome = yield* Config.String("CODEX_HOME").pipe(Config.withDefault(path.join(home, ".codex")));
36
96
  const projects = yield* Config.schema(Projects, "AGENT_USAGE_PROJECTS").pipe(Config.withDefault([]));
37
97
  const config = {
38
98
  storeDirectory,
39
99
  projects,
40
100
  claudeConfigDir,
101
+ claudeCredentials,
41
102
  roots: {
42
103
  claudeProjects: path.join(claudeConfigDir, "projects"),
43
104
  codexHome,
105
+ claudeLimitSamples,
44
106
  machine
45
107
  }
46
108
  };
@@ -1 +1 @@
1
- {"version":3,"file":"Config.js","sourceRoot":"","sources":["../../src/server/Config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Config.js","sourceRoot":"","sources":["../../src/server/Config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAA;AACnG,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAA;AAsBrC,MAAM,gBAAgB,GAAG,yBAAyB,CAAA;AAElD;;;;;;;;;GASG;AACH,MAAM,yBAAyB,GAAG,CAAC,OAMlC,EAAE,EAAE,CACH,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAC7B,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAA;IACpC,MAAM,UAAU,GAAG,OAAO,CAAC,gBAAgB,KAAK,SAAS;QACvD,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe;QAC1B,CAAC,CAAC,OAAO,CAAC,gBAAgB,KAAK,EAAE,CAAA;IACnC,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,gBAAgB,KAAK,SAAS;QACvD,CAAC,CAAC,OAAO,CAAC,eAAe;QACzB,CAAC,CAAC,OAAO,CAAC,gBAAgB,KAAK,EAAE;YACjC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC;YACpC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC9C,MAAM,MAAM,GAAG,UAAU;QACvB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAA;IACvG,MAAM,QAAQ,GAA8B;QAC1C,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,mBAAmB,CAAC;QAC/C,eAAe,EAAE,GAAG,gBAAgB,GAAG,MAAM,EAAE;QAC/C,eAAe,EAAE,OAAO,CAAC,IAAI;KAC9B,CAAA;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAC,CAAA;AAEJ;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,QAAgB,EAAU,EAAE;IACtD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,IAAI,EAAE,CAAA;IAChE,OAAO,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAA;AAC3C,CAAC,CAAA;AAED,2DAA2D;AAC3D,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC,CAAA;AAEjF,iGAAiG;AACjG,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CACjC,MAAM,CAAC,QAAQ,CACb,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,EACxB,oBAAoB,CAAC,SAAS,CAAC;IAC7B,MAAM,EAAE,CAAC,GAAW,EAAyB,EAAE,CAC7C,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC;IAC7E,MAAM,EAAE,CAAC,IAA2B,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;CACxD,CAAC,CACH,CACF,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,QAAgB,EAChB,gBAAgD,EAChD,MAAM,GAAG,kBAAkB,EAC3B,EAAE,CACF,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACzC,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAClE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,CAAC,CACtE,CAAA;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,qBAAqB,CAAC,CAAC,IAAI,CACtE,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAC1C,CAAA;IACD,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAA;IAChF,MAAM,eAAe,GAAG,eAAe,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IAC5G,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,iCAAiC,CAAC,CAAC,CAAA;IACzF,MAAM,gBAAgB,GAAG,KAAK,CAAC,CAAC,CAAC,gBAAgB,KAAK,SAAS;QAC7D,CAAC,CAAC,iBAAiB;QACnB,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,cAAc,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;IACnG,gGAAgG;IAChG,cAAc;IACd,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;IAC3E,MAAM,IAAI,GAAG,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAA;IAC1E,MAAM,iBAAiB,GAAG,KAAK,CAAC,CAAC,yBAAyB,CAAC;QACzD,IAAI;QACJ,IAAI;QACJ,eAAe;QACf,eAAe,EAAE,eAAe,CAAC,IAAI,KAAK,MAAM;QAChD,gBAAgB,EAAE,gBAAgB,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;KACxF,CAAC,CAAA;IACF,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAC3D,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CACvD,CAAA;IACD,MAAM,kBAAkB,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,IAAI,CAC/E,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,qBAAqB,CAAC,CAAC,CAC/E,CAAA;IACD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAA;IACxG,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAA;IACpG,MAAM,MAAM,GAAqB;QAC/B,cAAc;QACd,QAAQ;QACR,eAAe;QACf,iBAAiB;QACjB,KAAK,EAAE;YACL,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC;YACtD,SAAS;YACT,kBAAkB;YAClB,OAAO;SACR;KACF,CAAA;IACD,OAAO,MAAM,CAAA;AACf,CAAC,CAAC,CAAA"}