@alook/daemon 0.1.23 → 0.1.25

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 (3) hide show
  1. package/dist/cli/index.js +1623 -201
  2. package/dist/index.js +1575 -205
  3. package/package.json +4 -2
package/dist/cli/index.js CHANGED
@@ -98,7 +98,7 @@ var init_nanoid = () => {};
98
98
  // src/cli/index.ts
99
99
  import { Command, CommanderError } from "commander";
100
100
  import { realpathSync as realpathSync2 } from "node:fs";
101
- import { randomUUID as randomUUID9 } from "node:crypto";
101
+ import { randomUUID as randomUUID10 } from "node:crypto";
102
102
  import { pathToFileURL as pathToFileURL2 } from "node:url";
103
103
 
104
104
  // ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
@@ -14397,6 +14397,7 @@ var exports_community_machine_schema = {};
14397
14397
  __export(exports_community_machine_schema, {
14398
14398
  communityMachineToken: () => communityMachineToken,
14399
14399
  communityMachineCredential: () => communityMachineCredential,
14400
+ communityMachineBackendQuota: () => communityMachineBackendQuota,
14400
14401
  communityMachine: () => communityMachine,
14401
14402
  communityDiagnosticReport: () => communityDiagnosticReport,
14402
14403
  communityBotBinding: () => communityBotBinding,
@@ -16000,6 +16001,8 @@ var user = sqliteTable("user", {
16000
16001
  email: text("email").unique().notNull(),
16001
16002
  emailVerified: integer2("emailVerified", { mode: "boolean" }),
16002
16003
  image: text("image"),
16004
+ avatarVersion: integer2("avatarVersion").notNull().default(0),
16005
+ avatarObjectKey: text("avatarObjectKey"),
16003
16006
  createdAt: text("createdAt").notNull().$defaultFn(() => new Date().toISOString()),
16004
16007
  updatedAt: text("updatedAt").notNull().$defaultFn(() => new Date().toISOString()),
16005
16008
  isBot: integer2("isBot", { mode: "boolean" }).notNull().default(false),
@@ -16673,8 +16676,23 @@ var communityBotBinding = sqliteTable("community_bot_binding", {
16673
16676
  runtime: text("runtime").notNull(),
16674
16677
  instruction: text("instruction").notNull().default(""),
16675
16678
  modelName: text("model_name"),
16679
+ reasoningEffort: text("reasoning_effort"),
16680
+ runtimeConfigRevision: integer2("runtime_config_revision").notNull().default(0),
16676
16681
  createdAt: text("created_at").notNull().$defaultFn(() => new Date().toISOString())
16677
16682
  }, (t) => [index("idx_community_bot_binding_machine").on(t.machineId)]);
16683
+ var communityMachineBackendQuota = sqliteTable("community_machine_backend_quota", {
16684
+ machineId: text("machine_id").notNull().references(() => communityMachine.id, { onDelete: "cascade" }),
16685
+ agentBackendId: text("agent_backend_id").$type().notNull(),
16686
+ sourceEpoch: text("source_epoch").notNull(),
16687
+ status: text("status").$type().notNull(),
16688
+ planName: text("plan_name"),
16689
+ freshForSeconds: integer2("fresh_for_seconds"),
16690
+ limits: text("limits", { mode: "json" }).$type(),
16691
+ errorCode: text("error_code"),
16692
+ retryable: integer2("retryable", { mode: "boolean" }),
16693
+ observedAt: text("observed_at").notNull(),
16694
+ updatedAt: text("updated_at").notNull()
16695
+ }, (t) => [primaryKey({ columns: [t.machineId, t.agentBackendId] })]);
16678
16696
  var communityAgentRunnerKey = sqliteTable("community_agent_runner_key", {
16679
16697
  id: text("id").primaryKey().$defaultFn(() => "crkid_" + nanoid3()),
16680
16698
  userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
@@ -16853,6 +16871,11 @@ var HostCommandSchema = exports_external.discriminatedUnion("type", [
16853
16871
  config: exports_external.unknown(),
16854
16872
  launchId: exports_external.string().min(1)
16855
16873
  }),
16874
+ exports_external.object({
16875
+ type: exports_external.literal("agent:runtime_config_update"),
16876
+ agentId: exports_external.string().min(1),
16877
+ config: exports_external.unknown()
16878
+ }),
16856
16879
  exports_external.object({
16857
16880
  type: exports_external.literal("machine:reset_all"),
16858
16881
  resets: exports_external.array(exports_external.object({
@@ -16892,13 +16915,15 @@ var HostCommandSchema = exports_external.discriminatedUnion("type", [
16892
16915
  import * as fs from "fs";
16893
16916
  import * as path from "path";
16894
16917
  // ../shared/src/constants/community.ts
16918
+ var MAX_FOLDER_NAME_LENGTH = 100;
16895
16919
  var MAX_PROFILE_NAME_LENGTH = 100;
16896
16920
  var MAX_PROFILE_ABOUT_LENGTH = 1000;
16897
16921
  var MAX_MESSAGE_CONTENT_LENGTH = 4000;
16898
16922
  var MAX_EMOJI_BYTES = 32;
16899
16923
  var MAX_ATTACHMENTS_PER_MESSAGE = 10;
16900
16924
  var MAX_ATTACHMENT_SIZE_BYTES = 25 * 1024 * 1024;
16901
- var MAX_ATTACHMENT_THUMBNAIL_SIZE_BYTES = 50 * 1024;
16925
+ var MAX_ATTACHMENT_THUMBNAIL_EDGE_PX = 1024;
16926
+ var MAX_ATTACHMENT_THUMBNAIL_SIZE_BYTES = 512 * 1024;
16902
16927
  var MAX_SERVER_ICON_SIZE_BYTES = 5 * 1024 * 1024;
16903
16928
  var ALLOWED_ICON_MIME_TYPES = [
16904
16929
  "image/png",
@@ -16907,6 +16932,92 @@ var ALLOWED_ICON_MIME_TYPES = [
16907
16932
  "image/gif"
16908
16933
  ];
16909
16934
  var MAX_ICON_SOURCE_FILE_SIZE_BYTES = 15 * 1024 * 1024;
16935
+ // ../shared/src/provider-telemetry.ts
16936
+ var safeToken = exports_external.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
16937
+ var boundedText = exports_external.string().min(1).refine((value) => new TextEncoder().encode(value).length <= 64, { message: "must be at most 64 UTF-8 bytes" });
16938
+ var DailyUsageMetricSchema = safeToken.nullable();
16939
+ var DailyUsageSnapshotSchema = exports_external.object({
16940
+ botId: exports_external.string().min(1),
16941
+ day: exports_external.string().regex(/^\d{4}-\d{2}-\d{2}$/),
16942
+ metrics: exports_external.object({
16943
+ input: DailyUsageMetricSchema,
16944
+ output: DailyUsageMetricSchema,
16945
+ cache: DailyUsageMetricSchema
16946
+ }).strict()
16947
+ }).strict();
16948
+ var QuotaProductIdentitySchema = exports_external.discriminatedUnion("kind", [
16949
+ exports_external.object({ kind: exports_external.literal("reported"), id: boundedText, displayName: boundedText }).strict(),
16950
+ exports_external.object({ kind: exports_external.literal("unknown"), displayName: boundedText }).strict()
16951
+ ]);
16952
+ var QuotaModelIdentitySchema = exports_external.discriminatedUnion("kind", [
16953
+ exports_external.object({ kind: exports_external.literal("reported"), id: boundedText }).strict(),
16954
+ exports_external.object({ kind: exports_external.literal("not_applicable") }).strict(),
16955
+ exports_external.object({ kind: exports_external.literal("unknown") }).strict()
16956
+ ]);
16957
+ var QuotaWindowIdentitySchema = exports_external.discriminatedUnion("kind", [
16958
+ exports_external.object({
16959
+ kind: exports_external.literal("rolling"),
16960
+ durationSeconds: exports_external.number().int().positive().max(Number.MAX_SAFE_INTEGER),
16961
+ displayName: boundedText
16962
+ }).strict(),
16963
+ exports_external.object({
16964
+ kind: exports_external.literal("calendar"),
16965
+ period: exports_external.enum(["day", "week", "month"]),
16966
+ displayName: boundedText
16967
+ }).strict(),
16968
+ exports_external.object({
16969
+ kind: exports_external.literal("provider_defined"),
16970
+ id: boundedText,
16971
+ durationSeconds: exports_external.number().int().positive().max(Number.MAX_SAFE_INTEGER).optional(),
16972
+ displayName: boundedText
16973
+ }).strict()
16974
+ ]);
16975
+ var QuotaLimitSchema = exports_external.object({
16976
+ bucket: exports_external.object({
16977
+ limitId: boundedText,
16978
+ product: QuotaProductIdentitySchema,
16979
+ model: QuotaModelIdentitySchema,
16980
+ window: QuotaWindowIdentitySchema
16981
+ }).strict(),
16982
+ usedPercent: exports_external.number().finite().min(0).max(100),
16983
+ resetsAt: exports_external.string().datetime({ offset: true }).optional()
16984
+ }).strict();
16985
+ function quotaIdentity(limit) {
16986
+ const { product, model, window: window2, limitId } = limit.bucket;
16987
+ const productKey = product.kind === "reported" ? `reported:${product.id}` : "unknown";
16988
+ const modelKey = model.kind === "reported" ? `reported:${model.id}` : model.kind;
16989
+ const windowKey = window2.kind === "rolling" ? `rolling:${window2.durationSeconds}` : window2.kind === "calendar" ? `calendar:${window2.period}` : `provider_defined:${window2.id}:${window2.durationSeconds === undefined ? "absent" : window2.durationSeconds}`;
16990
+ return `${productKey}\x00${modelKey}\x00${windowKey}\x00${limitId}`;
16991
+ }
16992
+ var AvailableQuotaObservationSchema = exports_external.object({
16993
+ status: exports_external.literal("available"),
16994
+ sourceEpoch: exports_external.string().regex(/^[A-Za-z0-9_-]{22}$/),
16995
+ planName: boundedText.optional(),
16996
+ freshForSeconds: exports_external.number().int().positive().max(86400),
16997
+ limits: exports_external.array(QuotaLimitSchema).min(1).max(8)
16998
+ }).strict().superRefine((value, ctx) => {
16999
+ const identities = new Set;
17000
+ for (const [index2, limit] of value.limits.entries()) {
17001
+ const identity = quotaIdentity(limit);
17002
+ if (identities.has(identity)) {
17003
+ ctx.addIssue({ code: "custom", message: "duplicate quota bucket identity", path: ["limits", index2] });
17004
+ }
17005
+ identities.add(identity);
17006
+ }
17007
+ });
17008
+ var ProviderQuotaObservationSchema = exports_external.union([
17009
+ AvailableQuotaObservationSchema,
17010
+ exports_external.object({
17011
+ status: exports_external.literal("error"),
17012
+ sourceEpoch: exports_external.string().regex(/^[A-Za-z0-9_-]{22}$/),
17013
+ code: exports_external.enum(["unavailable", "unauthorized", "network", "provider_error", "invalid_response"]),
17014
+ retryable: exports_external.boolean()
17015
+ }).strict()
17016
+ ]);
17017
+ var ProviderQuotaSnapshotSchema = exports_external.object({
17018
+ agentBackendId: exports_external.enum(["claude", "codex"]),
17019
+ observation: ProviderQuotaObservationSchema
17020
+ }).strict();
16910
17021
  // ../shared/src/utils/slug.ts
16911
17022
  init_nanoid();
16912
17023
  var slugId = customAlphabet("0123456789abcdefghijklmnopqrstuvwxyz");
@@ -17063,10 +17174,13 @@ var ActivateTokenRuntimeSchema = exports_external.object({
17063
17174
  type: exports_external.string().min(1),
17064
17175
  version: exports_external.string().optional().default("")
17065
17176
  });
17177
+ var COMMUNITY_RUNTIME_ID_MAX = 64;
17178
+ var COMMUNITY_RUNTIME_VERSION_MAX = 64;
17179
+ var COMMUNITY_RUNTIME_LIST_MAX = 64;
17066
17180
  var ActivateTokenRequestSchema = exports_external.object({
17067
17181
  token: exports_external.string().min(1),
17068
17182
  hostname: exports_external.string().min(1),
17069
- runtimes: exports_external.array(ActivateTokenRuntimeSchema).min(1)
17183
+ runtimes: exports_external.array(ActivateTokenRuntimeSchema).min(1).max(COMMUNITY_RUNTIME_LIST_MAX)
17070
17184
  });
17071
17185
  var RegisterDaemonRequestSchema = exports_external.object({
17072
17186
  workspace_id: exports_external.string().min(1).optional(),
@@ -17074,7 +17188,7 @@ var RegisterDaemonRequestSchema = exports_external.object({
17074
17188
  device_name: exports_external.string().optional().default(""),
17075
17189
  cli_version: exports_external.string().optional().default(""),
17076
17190
  workspaces_root: exports_external.string().optional().default(""),
17077
- runtimes: exports_external.array(DaemonRuntimeItemSchema).min(1)
17191
+ runtimes: exports_external.array(DaemonRuntimeItemSchema).min(1).max(COMMUNITY_RUNTIME_LIST_MAX)
17078
17192
  });
17079
17193
  var DeregisterRequestSchema = exports_external.object({
17080
17194
  daemon_id: exports_external.string().min(1)
@@ -17417,16 +17531,61 @@ var CreateThreadRequestSchema = exports_external.object({
17417
17531
  content: exports_external.string().optional().default(""),
17418
17532
  attachment_ids: exports_external.array(exports_external.string()).optional()
17419
17533
  });
17420
- var COMMUNITY_RUNTIME_ID_MAX = 64;
17421
- var COMMUNITY_RUNTIME_VERSION_MAX = 64;
17422
- var COMMUNITY_RUNTIME_LIST_MAX = 64;
17423
17534
  var RUNTIME_ID_RE = /^[A-Za-z0-9._@/-]+$/;
17535
+ var REASONING_EFFORT_RE = /^[A-Za-z0-9._-]+$/;
17536
+ var COMMUNITY_REASONING_EFFORT_MAX = 32;
17537
+ var COMMUNITY_REASONING_DESCRIPTION_MAX = 256;
17538
+ var COMMUNITY_REASONING_OPTIONS_MAX = 16;
17539
+ var COMMUNITY_REASONING_MODELS_MAX = 64;
17540
+ var ReasoningEffortSchema = exports_external.string().min(1).max(COMMUNITY_REASONING_EFFORT_MAX).regex(REASONING_EFFORT_RE, "invalid reasoning effort charset");
17541
+ var RuntimeReasoningOptionSchema = exports_external.object({
17542
+ value: ReasoningEffortSchema,
17543
+ description: exports_external.string().max(COMMUNITY_REASONING_DESCRIPTION_MAX).optional()
17544
+ });
17545
+ var RuntimeReasoningModelSchema = exports_external.object({
17546
+ id: exports_external.string().min(1).max(100),
17547
+ supportedReasoningEfforts: exports_external.array(exports_external.unknown()).max(COMMUNITY_REASONING_OPTIONS_MAX).transform((options) => {
17548
+ const seen = new Set;
17549
+ return options.flatMap((candidate) => {
17550
+ const parsed = RuntimeReasoningOptionSchema.safeParse(candidate);
17551
+ if (!parsed.success)
17552
+ return [];
17553
+ const option = parsed.data;
17554
+ if (seen.has(option.value))
17555
+ return [];
17556
+ seen.add(option.value);
17557
+ return [option];
17558
+ });
17559
+ }),
17560
+ defaultReasoningEffort: ReasoningEffortSchema.optional().catch(undefined)
17561
+ }).transform((model) => {
17562
+ const { defaultReasoningEffort, ...rest } = model;
17563
+ return defaultReasoningEffort !== undefined && model.supportedReasoningEfforts.some((option) => option.value === defaultReasoningEffort) ? { ...rest, defaultReasoningEffort } : rest;
17564
+ });
17565
+ var RuntimeReasoningCatalogSchema = exports_external.object({
17566
+ updateMode: exports_external.enum(["live_next_turn", "context_preserving_restart", "unsupported"]),
17567
+ defaultModelId: exports_external.string().min(1).max(100).optional().catch(undefined),
17568
+ models: exports_external.array(exports_external.unknown()).max(COMMUNITY_REASONING_MODELS_MAX).transform((models) => {
17569
+ const seen = new Set;
17570
+ return models.flatMap((candidate) => {
17571
+ const parsed = RuntimeReasoningModelSchema.safeParse(candidate);
17572
+ if (!parsed.success)
17573
+ return [];
17574
+ const model = parsed.data;
17575
+ if (seen.has(model.id))
17576
+ return [];
17577
+ seen.add(model.id);
17578
+ return [model];
17579
+ });
17580
+ })
17581
+ });
17424
17582
  var CommunityMachineRuntimeSchema = exports_external.object({
17425
17583
  id: exports_external.string().min(1).max(COMMUNITY_RUNTIME_ID_MAX).regex(RUNTIME_ID_RE, "invalid runtime id charset"),
17426
17584
  version: exports_external.string().max(COMMUNITY_RUNTIME_VERSION_MAX).optional(),
17427
17585
  status: exports_external.enum(["healthy", "unhealthy"]).catch("healthy").default("healthy"),
17428
17586
  lastError: exports_external.string().max(128).optional(),
17429
- lastErrorAt: exports_external.string().optional()
17587
+ lastErrorAt: exports_external.string().optional(),
17588
+ reasoning: RuntimeReasoningCatalogSchema.optional().catch(undefined)
17430
17589
  });
17431
17590
  var CommunityMachineRuntimeListSchema = exports_external.array(CommunityMachineRuntimeSchema).max(COMMUNITY_RUNTIME_LIST_MAX).transform((list) => {
17432
17591
  const seen = new Set;
@@ -17439,6 +17598,17 @@ var CommunityMachineRuntimeListSchema = exports_external.array(CommunityMachineR
17439
17598
  }
17440
17599
  return out;
17441
17600
  });
17601
+ var CommunityRunningAgentListSchema = exports_external.array(exports_external.string()).transform((list) => {
17602
+ const seen = new Set;
17603
+ const out = [];
17604
+ for (const id of list) {
17605
+ if (seen.has(id))
17606
+ continue;
17607
+ seen.add(id);
17608
+ out.push(id);
17609
+ }
17610
+ return out;
17611
+ });
17442
17612
  var CommunityMachineSummarySchema = exports_external.object({
17443
17613
  id: exports_external.string(),
17444
17614
  hostname: exports_external.string(),
@@ -17462,16 +17632,17 @@ var HostReadyMessageSchema = exports_external.object({
17462
17632
  type: exports_external.literal("ready"),
17463
17633
  runtimeReport: CommunityMachineRuntimeListSchema,
17464
17634
  capabilities: exports_external.array(exports_external.string().min(1).max(64)).max(16).optional().default([]),
17465
- runningAgents: exports_external.array(exports_external.string()).default([]),
17635
+ runningAgents: CommunityRunningAgentListSchema.default([]),
17466
17636
  hostname: exports_external.string().optional(),
17467
17637
  platform: exports_external.string().optional(),
17468
17638
  arch: exports_external.string().optional(),
17469
17639
  osRelease: exports_external.string().optional(),
17470
- daemonVersion: exports_external.string().optional()
17640
+ daemonVersion: exports_external.string().optional(),
17641
+ providerQuotas: exports_external.array(ProviderQuotaSnapshotSchema).max(2).optional().default([])
17471
17642
  });
17472
17643
  var CommunityDaemonReadySchema = exports_external.object({
17473
17644
  runtimeReport: CommunityMachineRuntimeListSchema.optional(),
17474
- runningAgents: exports_external.array(exports_external.string()).default([]),
17645
+ runningAgents: CommunityRunningAgentListSchema.default([]),
17475
17646
  hostname: exports_external.string().optional(),
17476
17647
  os: exports_external.string().optional(),
17477
17648
  arch: exports_external.string().optional(),
@@ -17488,7 +17659,9 @@ var SessionErrorFrameSchema = exports_external.object({
17488
17659
  var AgentActivityMessageSchema = exports_external.object({
17489
17660
  type: exports_external.literal("agent_activity"),
17490
17661
  agentId: exports_external.string(),
17491
- state: exports_external.enum(["idle", "starting", "running", "stopping"])
17662
+ state: exports_external.enum(["idle", "starting", "running", "stopping"]),
17663
+ dailyUsage: exports_external.array(DailyUsageSnapshotSchema).max(7).optional(),
17664
+ quota: ProviderQuotaSnapshotSchema.optional()
17492
17665
  });
17493
17666
  var AgentTypingMessageSchema = exports_external.object({
17494
17667
  type: exports_external.literal("agent_typing"),
@@ -17563,15 +17736,17 @@ var CommunityBotCreateRequestSchema = exports_external.object({
17563
17736
  machineId: exports_external.string().min(1),
17564
17737
  runtime: exports_external.string().min(1),
17565
17738
  image: BotImageUrlSchema.optional(),
17566
- model: exports_external.string().trim().min(1).max(100).nullable().optional()
17739
+ model: exports_external.string().trim().min(1).max(100).nullable().optional(),
17740
+ reasoningEffort: ReasoningEffortSchema.nullable().optional()
17567
17741
  });
17568
17742
  var CommunityBotPatchRequestSchema = exports_external.object({
17569
17743
  name: exports_external.string().trim().min(COMMUNITY_BOT_NAME_MIN).max(COMMUNITY_BOT_NAME_MAX).refine(isMentionSafeName, { message: MENTION_SAFE_NAME_MSG }).optional(),
17570
17744
  description: exports_external.string().max(COMMUNITY_BOT_DESCRIPTION_MAX).optional(),
17571
17745
  image: BotImageUrlSchema.nullable().optional(),
17572
17746
  model: exports_external.string().trim().min(1).max(100).nullable().optional(),
17573
- runtime: exports_external.string().trim().min(1).max(COMMUNITY_RUNTIME_ID_MAX).optional()
17574
- }).refine((v) => v.name !== undefined || v.description !== undefined || v.image !== undefined || v.runtime !== undefined || ("model" in v), {
17747
+ runtime: exports_external.string().trim().min(1).max(COMMUNITY_RUNTIME_ID_MAX).optional(),
17748
+ reasoningEffort: ReasoningEffortSchema.nullable().optional()
17749
+ }).refine((v) => v.name !== undefined || v.description !== undefined || v.image !== undefined || v.runtime !== undefined || ("reasoningEffort" in v) || ("model" in v), {
17575
17750
  message: "at least one field must be provided"
17576
17751
  });
17577
17752
  var CommunityBotAddToServerRequestSchema = exports_external.object({
@@ -17773,6 +17948,7 @@ __export(exports_community_schema, {
17773
17948
  communityChannelMember: () => communityChannelMember,
17774
17949
  communityChannel: () => communityChannel,
17775
17950
  communityCategory: () => communityCategory,
17951
+ communityBotDailyTokenUsage: () => communityBotDailyTokenUsage,
17776
17952
  communityBotDailyActivity: () => communityBotDailyActivity,
17777
17953
  communityBotApprovalRequest: () => communityBotApprovalRequest,
17778
17954
  communityBotActivityEvent: () => communityBotActivityEvent,
@@ -18025,6 +18201,17 @@ var communityBotDailyActivity = sqliteTable("community_bot_daily_activity", {
18025
18201
  handledCount: integer2("handled_count").notNull().default(0),
18026
18202
  sentCount: integer2("sent_count").notNull().default(0)
18027
18203
  }, (t) => [primaryKey({ columns: [t.botId, t.day] })]);
18204
+ var communityBotDailyTokenUsage = sqliteTable("community_bot_daily_token_usage", {
18205
+ botId: text("bot_id").notNull().references(() => user.id, { onDelete: "cascade" }),
18206
+ day: text("day").notNull(),
18207
+ inputTokens: integer2("input_tokens"),
18208
+ outputTokens: integer2("output_tokens"),
18209
+ cacheTokens: integer2("cache_tokens"),
18210
+ updatedAt: text("updated_at").notNull()
18211
+ }, (t) => [
18212
+ primaryKey({ columns: [t.botId, t.day] }),
18213
+ index("idx_community_bot_daily_token_usage_day").on(t.day)
18214
+ ]);
18028
18215
  var communityMessageMark = sqliteTable("community_message_mark", {
18029
18216
  id: text("id").primaryKey().$defaultFn(() => nanoid3()),
18030
18217
  userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
@@ -18149,7 +18336,8 @@ var listedMessageProjection = {
18149
18336
  clientNonce: communityMessage.clientNonce,
18150
18337
  authorName: user.name,
18151
18338
  authorEmail: user.email,
18152
- authorImage: user.image
18339
+ authorImage: user.image,
18340
+ authorAvatarVersion: user.avatarVersion
18153
18341
  };
18154
18342
 
18155
18343
  // ../shared/src/db/queries/user.ts
@@ -18159,6 +18347,7 @@ var publicUserColumns = {
18159
18347
  email: user.email,
18160
18348
  emailVerified: user.emailVerified,
18161
18349
  image: user.image,
18350
+ avatarVersion: user.avatarVersion,
18162
18351
  createdAt: user.createdAt,
18163
18352
  updatedAt: user.updatedAt,
18164
18353
  discriminator: user.discriminator
@@ -18169,6 +18358,12 @@ var internalUserColumns = {
18169
18358
  ownerUserId: user.ownerUserId,
18170
18359
  deletedAt: user.deletedAt
18171
18360
  };
18361
+ var avatarPublishColumns = {
18362
+ id: user.id,
18363
+ image: user.image,
18364
+ avatarVersion: user.avatarVersion,
18365
+ avatarObjectKey: user.avatarObjectKey
18366
+ };
18172
18367
 
18173
18368
  // ../shared/src/db/queries/community/channel.ts
18174
18369
  var CHANNEL_COLUMNS = {
@@ -18221,7 +18416,8 @@ var friendApprovalProfileSchema = exports_external.strictObject({
18221
18416
  id: string4,
18222
18417
  name: string4,
18223
18418
  discriminator: string4,
18224
- image: nullableString
18419
+ image: nullableString,
18420
+ avatarVersion: exports_external.number().int().nonnegative()
18225
18421
  });
18226
18422
  var FriendApprovalPayloadSchema = exports_external.strictObject({
18227
18423
  friendshipId: string4,
@@ -18247,6 +18443,7 @@ var messageSchema = exports_external.strictObject({
18247
18443
  authorId: string4,
18248
18444
  authorName: string4,
18249
18445
  authorAvatar: string4.optional(),
18446
+ authorAvatarVersion: exports_external.number().int().nonnegative(),
18250
18447
  content: string4,
18251
18448
  type: exports_external.enum(["chat", "system"]),
18252
18449
  systemKind: exports_external.literal("thread").optional(),
@@ -18254,6 +18451,7 @@ var messageSchema = exports_external.strictObject({
18254
18451
  replyToId: nullableString.optional(),
18255
18452
  replyTo: exports_external.strictObject({
18256
18453
  id: string4,
18454
+ authorId: string4.optional(),
18257
18455
  authorName: string4,
18258
18456
  text: string4,
18259
18457
  deleted: exports_external.boolean().optional()
@@ -18448,6 +18646,7 @@ var communityMemberJoinSchema = exports_external.strictObject({
18448
18646
  name: string4,
18449
18647
  discriminator: string4,
18450
18648
  avatar: string4.optional(),
18649
+ avatarVersion: exports_external.number().int().nonnegative(),
18451
18650
  role: string4,
18452
18651
  joinedAt: string4
18453
18652
  })
@@ -18550,6 +18749,22 @@ var communityStatusUpdateSchema = exports_external.strictObject({
18550
18749
  statusEmoji: nullableString,
18551
18750
  statusText: nullableString
18552
18751
  });
18752
+ var communityIdentityUpdateSchema = exports_external.strictObject({
18753
+ type: exports_external.literal("community:identity.update"),
18754
+ userId: string4,
18755
+ avatar: string4,
18756
+ avatarVersion: exports_external.number().int().positive()
18757
+ });
18758
+ var communityProfileUpdateSchema = exports_external.strictObject({
18759
+ type: exports_external.literal("community:profile.update"),
18760
+ userId: string4,
18761
+ name: string4,
18762
+ discriminator: string4,
18763
+ aboutMe: string4,
18764
+ bannerColor: nullableString,
18765
+ kind: exports_external.enum(["human", "bot"]),
18766
+ ownerUserId: nullableString
18767
+ });
18553
18768
  var machineRuntimeSchema = CommunityMachineRuntimeSchema.strict();
18554
18769
  var CommunityMachineSummarySchema2 = exports_external.strictObject({
18555
18770
  id: string4,
@@ -18638,6 +18853,8 @@ var CommunityWsEventDiscriminatedSchema = exports_external.discriminatedUnion("t
18638
18853
  communityInboxChangedSchema,
18639
18854
  communityPresenceUpdateSchema,
18640
18855
  communityStatusUpdateSchema,
18856
+ communityIdentityUpdateSchema,
18857
+ communityProfileUpdateSchema,
18641
18858
  communityMachineCreatedSchema,
18642
18859
  communityMachineStatusSchema,
18643
18860
  communityMachineUpdatedSchema,
@@ -18684,6 +18901,8 @@ var WS_EVENTS = {
18684
18901
  INBOX_CHANGED: "community:inbox.changed",
18685
18902
  PRESENCE_UPDATE: "community:presence.update",
18686
18903
  STATUS_UPDATE: "community:status.update",
18904
+ IDENTITY_UPDATE: "community:identity.update",
18905
+ PROFILE_UPDATE: "community:profile.update",
18687
18906
  MACHINE_CREATED: "community:machine.created",
18688
18907
  MACHINE_STATUS: "community:machine.status",
18689
18908
  MACHINE_UPDATED: "community:machine.updated",
@@ -18760,6 +18979,43 @@ var COMMUNITY_BROWSER_EVENT_BATCH_ENVELOPE_BYTES = 1024;
18760
18979
  var COMMUNITY_BROWSER_EVENT_BATCH_MAX_BYTES = MESSAGE_DELIVERY_MAX_EVENTS_PER_USER * COMMUNITY_BROWSER_EVENT_MAX_BYTES + COMMUNITY_BROWSER_EVENT_BATCH_ENVELOPE_BYTES;
18761
18980
  // ../shared/src/db/index.ts
18762
18981
  var allSchema = { ...exports_schema, ...exports_community_schema, ...exports_community_machine_schema };
18982
+ // ../shared/src/community-server-rail.ts
18983
+ var MAX_SERVER_RAIL_COMMANDS = 3;
18984
+ var idSchema = exports_external.string().trim().min(1);
18985
+ var idsSchema = exports_external.array(idSchema);
18986
+ var reorderServersSchema = exports_external.strictObject({
18987
+ kind: exports_external.literal("reorder-servers"),
18988
+ serverIds: idsSchema
18989
+ });
18990
+ var reorderFoldersSchema = exports_external.strictObject({
18991
+ kind: exports_external.literal("reorder-folders"),
18992
+ folderIds: idsSchema
18993
+ });
18994
+ var replaceFolderItemsSchema = exports_external.strictObject({
18995
+ kind: exports_external.literal("replace-folder-items"),
18996
+ folderId: idSchema,
18997
+ serverIds: idsSchema.min(1)
18998
+ });
18999
+ var deleteFolderSchema = exports_external.strictObject({
19000
+ kind: exports_external.literal("delete-folder"),
19001
+ folderId: idSchema
19002
+ });
19003
+ var createFolderSchema = exports_external.strictObject({
19004
+ kind: exports_external.literal("create-folder"),
19005
+ clientId: idSchema,
19006
+ name: exports_external.string().trim().min(1).max(MAX_FOLDER_NAME_LENGTH),
19007
+ serverIds: idsSchema.min(1)
19008
+ });
19009
+ var serverRailCommandSchema = exports_external.discriminatedUnion("kind", [
19010
+ reorderServersSchema,
19011
+ reorderFoldersSchema,
19012
+ replaceFolderItemsSchema,
19013
+ deleteFolderSchema,
19014
+ createFolderSchema
19015
+ ]);
19016
+ var serverRailCommitRequestSchema = exports_external.strictObject({
19017
+ commands: exports_external.array(serverRailCommandSchema).min(1).max(MAX_SERVER_RAIL_COMMANDS)
19018
+ });
18763
19019
  // ../shared/src/db/queries/task.ts
18764
19020
  var DEFAULT_STALE_SECONDS = Number(process.env.ALOOK_STALE_DISPATCH_TIMEOUT_S) || 20;
18765
19021
  var DEFAULT_STALE_RUNNING_SECONDS = Number(process.env.ALOOK_STALE_RUNNING_TIMEOUT_S) || 3600;
@@ -19225,7 +19481,7 @@ import * as fs12 from "fs";
19225
19481
  import * as path13 from "path";
19226
19482
  import * as crypto5 from "crypto";
19227
19483
  import * as os3 from "os";
19228
- import { homedir as homedir5 } from "os";
19484
+ import { homedir as homedir6 } from "os";
19229
19485
 
19230
19486
  // src/discovery.ts
19231
19487
  import * as path9 from "path";
@@ -20005,6 +20261,9 @@ class ProcessLane {
20005
20261
  return false;
20006
20262
  return proc.kill("SIGINT");
20007
20263
  }
20264
+ updateSettings(input) {
20265
+ return this.driver.updateSettings?.(input) ?? Promise.resolve({ status: "unsupported" });
20266
+ }
20008
20267
  attachProcess(proc) {
20009
20268
  proc.stdout?.on("data", (chunk2) => {
20010
20269
  const chunkText = chunk2.toString();
@@ -20392,25 +20651,19 @@ class ClaudeEventNormalizer {
20392
20651
  }
20393
20652
  buildUsageTelemetry(event) {
20394
20653
  const u = event?.usage;
20395
- if (!u && event?.total_cost_usd == null)
20654
+ if (!u)
20396
20655
  return null;
20656
+ const metric = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
20657
+ const cacheParts = [u.cache_read_input_tokens, u.cache_creation_input_tokens].filter((value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0);
20658
+ const cache = cacheParts.length > 0 && Number.isSafeInteger(cacheParts.reduce((sum, value) => sum + value, 0)) ? cacheParts.reduce((sum, value) => sum + value, 0) : null;
20397
20659
  return {
20398
20660
  kind: "telemetry",
20399
20661
  name: "token_usage",
20400
20662
  source: "claude_result_usage",
20401
- usageKind: "per_turn",
20402
- attrs: {
20403
- inputTokens: u?.input_tokens,
20404
- outputTokens: u?.output_tokens,
20405
- cachedInputTokens: u?.cache_read_input_tokens,
20406
- cacheCreationInputTokens: u?.cache_creation_input_tokens,
20407
- totalCostUsd: event?.total_cost_usd,
20408
- durationMs: event?.duration_ms,
20409
- durationApiMs: event?.duration_api_ms,
20410
- numTurns: event?.num_turns,
20411
- resultSubtype: event?.subtype,
20412
- resultIsError: event?.is_error,
20413
- serviceTier: u?.service_tier
20663
+ usage: {
20664
+ input: metric(u.input_tokens),
20665
+ output: metric(u.output_tokens),
20666
+ cache
20414
20667
  }
20415
20668
  };
20416
20669
  }
@@ -20642,49 +20895,153 @@ class ClaudeDriver {
20642
20895
  }
20643
20896
 
20644
20897
  // agent-driver/dist/adapters/codex/telemetry.js
20645
- function mapCodexTelemetry(method, params) {
20898
+ function metric(value) {
20899
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : null;
20900
+ }
20901
+ function nonCachedInput(input, cached2) {
20902
+ if (typeof input !== "number" || !Number.isSafeInteger(input) || input < 0 || typeof cached2 !== "number" || !Number.isSafeInteger(cached2) || cached2 < 0 || cached2 > input)
20903
+ return null;
20904
+ return input - cached2;
20905
+ }
20906
+ function canonicalId(value, fallback) {
20907
+ return typeof value === "string" && value.length > 0 && new TextEncoder().encode(value).length <= 64 ? value : fallback;
20908
+ }
20909
+ function mappedPlanName(value) {
20910
+ switch (value) {
20911
+ case "free":
20912
+ return "Free";
20913
+ case "plus":
20914
+ return "Plus";
20915
+ case "pro":
20916
+ return "Pro";
20917
+ case "team":
20918
+ return "Team";
20919
+ case "business":
20920
+ return "Business";
20921
+ case "enterprise":
20922
+ return "Enterprise";
20923
+ case "edu":
20924
+ return "Education";
20925
+ default:
20926
+ return;
20927
+ }
20928
+ }
20929
+ function quotaWindow(minutes, slot) {
20930
+ if (typeof minutes !== "number" || !Number.isSafeInteger(minutes) || minutes <= 0)
20931
+ return null;
20932
+ if (minutes === 1440)
20933
+ return { kind: "calendar", period: "day", displayName: "Daily usage limit" };
20934
+ if (minutes === 10080)
20935
+ return { kind: "calendar", period: "week", displayName: "Weekly usage limit" };
20936
+ if (minutes === 43200)
20937
+ return { kind: "calendar", period: "month", displayName: "Monthly usage limit" };
20938
+ return {
20939
+ kind: "rolling",
20940
+ durationSeconds: minutes * 60,
20941
+ displayName: slot === "primary" && minutes === 300 ? "5 hour usage limit" : `${minutes} minute usage limit`
20942
+ };
20943
+ }
20944
+ function resetIso(value) {
20945
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) {
20946
+ const date5 = new Date(value < 10000000000 ? value * 1000 : value);
20947
+ return Number.isNaN(date5.getTime()) ? undefined : date5.toISOString();
20948
+ }
20949
+ if (typeof value === "string") {
20950
+ const date5 = new Date(value);
20951
+ return Number.isNaN(date5.getTime()) ? undefined : date5.toISOString();
20952
+ }
20953
+ return;
20954
+ }
20955
+ function mapCodexQuotaSnapshots(snapshots, sourceEpoch) {
20956
+ const limits = [];
20957
+ let planName;
20958
+ for (const snapshot of snapshots) {
20959
+ const limitId = canonicalId(snapshot?.limitId ?? snapshot?.limit_id, "codex");
20960
+ const spark = /spark/i.test(limitId) || /spark/i.test(String(snapshot?.limitName ?? snapshot?.limit_name ?? ""));
20961
+ const product = spark ? { kind: "reported", id: "codex-spark", displayName: "Spark" } : { kind: "reported", id: "codex", displayName: "Codex" };
20962
+ const model = spark ? { kind: "reported", id: "gpt-5.3-codex-spark" } : { kind: "not_applicable" };
20963
+ planName ??= mappedPlanName(snapshot?.planType ?? snapshot?.plan_type);
20964
+ for (const slot of ["primary", "secondary"]) {
20965
+ const value = snapshot?.[slot];
20966
+ const window2 = quotaWindow(value?.windowDurationMins ?? value?.window_duration_mins, slot);
20967
+ const usedPercent = value?.usedPercent ?? value?.used_percent;
20968
+ if (!window2 || typeof usedPercent !== "number" || !Number.isFinite(usedPercent) || usedPercent < 0 || usedPercent > 100)
20969
+ continue;
20970
+ const resetsAt = resetIso(value?.resetsAt ?? value?.resets_at);
20971
+ limits.push({
20972
+ bucket: { limitId, product, model, window: window2 },
20973
+ usedPercent,
20974
+ ...resetsAt ? { resetsAt } : {}
20975
+ });
20976
+ }
20977
+ }
20978
+ if (limits.length === 0) {
20979
+ return {
20980
+ kind: "telemetry",
20981
+ name: "rate_limits",
20982
+ source: "codex_account_rate_limits_updated",
20983
+ quota: { status: "error", sourceEpoch, code: "invalid_response", retryable: true }
20984
+ };
20985
+ }
20986
+ return {
20987
+ kind: "telemetry",
20988
+ name: "rate_limits",
20989
+ source: "codex_account_rate_limits_updated",
20990
+ quota: {
20991
+ status: "available",
20992
+ sourceEpoch,
20993
+ ...planName ? { planName } : {},
20994
+ freshForSeconds: 300,
20995
+ limits
20996
+ }
20997
+ };
20998
+ }
20999
+ function mapCodexTelemetry(method, params, sourceEpoch) {
20646
21000
  if (method === "thread/tokenUsage/updated") {
20647
- const u = params?.usage ?? params ?? {};
20648
- return [
20649
- {
20650
- kind: "telemetry",
20651
- name: "token_usage",
20652
- source: "codex_thread_token_usage_updated",
20653
- usageKind: "cumulative_session",
20654
- attrs: {
20655
- totalTokens: u.totalTokens ?? u.total_tokens,
20656
- inputTokens: u.inputTokens ?? u.input_tokens,
20657
- cachedInputTokens: u.cachedInputTokens ?? u.cached_input_tokens,
20658
- outputTokens: u.outputTokens ?? u.output_tokens,
20659
- reasoningOutputTokens: u.reasoningOutputTokens ?? u.reasoning_output_tokens,
20660
- modelContextWindow: u.modelContextWindow ?? u.model_context_window,
20661
- cachedInputRatio: u.cachedInputRatio,
20662
- contextUtilization: u.contextUtilization
20663
- }
21001
+ const u = params?.tokenUsage?.last ?? params?.token_usage?.last;
21002
+ if (!u)
21003
+ return [];
21004
+ const input = u.inputTokens ?? u.input_tokens;
21005
+ const cached2 = u.cachedInputTokens ?? u.cached_input_tokens;
21006
+ return [{
21007
+ kind: "telemetry",
21008
+ name: "token_usage",
21009
+ source: "codex_thread_token_usage_updated",
21010
+ usage: {
21011
+ input: nonCachedInput(input, cached2),
21012
+ output: metric(u.outputTokens ?? u.output_tokens),
21013
+ cache: metric(cached2)
20664
21014
  }
20665
- ];
21015
+ }];
20666
21016
  }
20667
21017
  if (method === "account/rateLimits/updated") {
20668
- const r = params ?? {};
20669
- return [
20670
- {
20671
- kind: "telemetry",
20672
- name: "rate_limits",
20673
- source: "codex_account_rate_limits_updated",
20674
- attrs: {
20675
- limitId: r.limitId,
20676
- planType: r.planType,
20677
- usedPercent: r.usedPercent,
20678
- windowDurationMins: r.windowDurationMins,
20679
- resetsAt: r.resetsAt
20680
- }
20681
- }
20682
- ];
21018
+ return [mapCodexQuotaSnapshots([params?.rateLimits ?? params ?? {}], sourceEpoch)];
20683
21019
  }
20684
21020
  return [];
20685
21021
  }
20686
21022
 
20687
21023
  // agent-driver/dist/adapters/codex/normalizer.js
21024
+ import { randomBytes } from "node:crypto";
21025
+ var codexQuotaSourceEpoch = randomBytes(16).toString("base64url");
21026
+ var codexQuotaSourceGeneration = 0;
21027
+ var codexAccountFingerprint = null;
21028
+ function rotateCodexQuotaSource() {
21029
+ codexQuotaSourceEpoch = randomBytes(16).toString("base64url");
21030
+ codexQuotaSourceGeneration += 1;
21031
+ codexAccountFingerprint = null;
21032
+ }
21033
+ function observeCodexAccount(result) {
21034
+ const account2 = result?.account;
21035
+ const fingerprint = account2 && typeof account2 === "object" ? JSON.stringify([
21036
+ account2.type ?? "unknown",
21037
+ account2.email ?? null,
21038
+ account2.planType ?? account2.plan_type ?? null
21039
+ ]) : "none";
21040
+ if (codexAccountFingerprint !== null && codexAccountFingerprint !== fingerprint) {
21041
+ rotateCodexQuotaSource();
21042
+ }
21043
+ codexAccountFingerprint = fingerprint;
21044
+ }
20688
21045
  function normalizeFileChangeInput(item) {
20689
21046
  const paths = [];
20690
21047
  const seen = new Set;
@@ -20707,6 +21064,12 @@ function normalizeFileChangeInput(item) {
20707
21064
  }
20708
21065
 
20709
21066
  class CodexEventNormalizer {
21067
+ quotaReadRequestIds = new Set;
21068
+ accountReadRequestIds = new Set;
21069
+ rateLimitSnapshots = new Map;
21070
+ quotaSnapshotInitialized = false;
21071
+ quotaSourceGeneration = codexQuotaSourceGeneration;
21072
+ pendingTurnUsage = null;
20710
21073
  threadId = null;
20711
21074
  turnId = null;
20712
21075
  terminalTurn = null;
@@ -20717,10 +21080,69 @@ class CodexEventNormalizer {
20717
21080
  get currentTurnId() {
20718
21081
  return this.turnId;
20719
21082
  }
21083
+ registerQuotaReadRequest(requestId) {
21084
+ this.quotaReadRequestIds.add(requestId);
21085
+ }
21086
+ registerAccountReadRequest(requestId) {
21087
+ this.accountReadRequestIds.add(requestId);
21088
+ }
21089
+ syncQuotaSourceGeneration() {
21090
+ if (this.quotaSourceGeneration === codexQuotaSourceGeneration)
21091
+ return;
21092
+ this.quotaSourceGeneration = codexQuotaSourceGeneration;
21093
+ this.rateLimitSnapshots.clear();
21094
+ this.quotaSnapshotInitialized = false;
21095
+ }
21096
+ quotaSnapshots(value) {
21097
+ const byLimitId = value?.rateLimitsByLimitId ?? value?.rate_limits_by_limit_id;
21098
+ if (byLimitId && typeof byLimitId === "object" && !Array.isArray(byLimitId)) {
21099
+ return Object.entries(byLimitId).flatMap(([key2, snapshot2]) => {
21100
+ if (!snapshot2 || typeof snapshot2 !== "object" || Array.isArray(snapshot2))
21101
+ return [];
21102
+ return [[key2, {
21103
+ ...snapshot2,
21104
+ limitId: snapshot2.limitId ?? snapshot2.limit_id ?? key2
21105
+ }]];
21106
+ });
21107
+ }
21108
+ const snapshot = value?.rateLimits ?? value?.rate_limits ?? value;
21109
+ if (!snapshot || typeof snapshot !== "object" || Array.isArray(snapshot))
21110
+ return [];
21111
+ const record2 = snapshot;
21112
+ const key = typeof record2.limitId === "string" ? record2.limitId : typeof record2.limit_id === "string" ? record2.limit_id : "codex";
21113
+ return [[key, { ...record2, limitId: key }]];
21114
+ }
21115
+ replaceQuotaSnapshots(value) {
21116
+ this.syncQuotaSourceGeneration();
21117
+ this.rateLimitSnapshots.clear();
21118
+ for (const [key, snapshot] of this.quotaSnapshots(value)) {
21119
+ this.rateLimitSnapshots.set(key, snapshot);
21120
+ }
21121
+ this.quotaSnapshotInitialized = true;
21122
+ return [mapCodexQuotaSnapshots([...this.rateLimitSnapshots.values()], codexQuotaSourceEpoch)];
21123
+ }
21124
+ mergeQuotaSnapshots(value) {
21125
+ this.syncQuotaSourceGeneration();
21126
+ for (const [key, update] of this.quotaSnapshots(value)) {
21127
+ const merged = {
21128
+ ...this.rateLimitSnapshots.get(key) ?? {},
21129
+ limitId: key
21130
+ };
21131
+ for (const [field, fieldValue] of Object.entries(update)) {
21132
+ if (fieldValue !== undefined && fieldValue !== null)
21133
+ merged[field] = fieldValue;
21134
+ }
21135
+ this.rateLimitSnapshots.set(key, merged);
21136
+ }
21137
+ if (!this.quotaSnapshotInitialized)
21138
+ return [];
21139
+ return [mapCodexQuotaSnapshots([...this.rateLimitSnapshots.values()], codexQuotaSourceEpoch)];
21140
+ }
20720
21141
  adoptThreadId(threadId) {
20721
21142
  if (threadId !== this.threadId) {
20722
21143
  this.turnId = null;
20723
21144
  this.terminalTurn = null;
21145
+ this.pendingTurnUsage = null;
20724
21146
  }
20725
21147
  this.threadId = threadId;
20726
21148
  }
@@ -20738,6 +21160,25 @@ class CodexEventNormalizer {
20738
21160
  const msg = tryParseJsonLine(line);
20739
21161
  if (!msg)
20740
21162
  return [];
21163
+ if (msg?.id !== undefined && this.accountReadRequestIds.delete(msg.id)) {
21164
+ if (!msg.error) {
21165
+ observeCodexAccount(msg.result);
21166
+ this.syncQuotaSourceGeneration();
21167
+ }
21168
+ return [];
21169
+ }
21170
+ if (msg?.id !== undefined && this.quotaReadRequestIds.delete(msg.id)) {
21171
+ this.syncQuotaSourceGeneration();
21172
+ if (msg.error) {
21173
+ return [{
21174
+ kind: "telemetry",
21175
+ name: "rate_limits",
21176
+ source: "codex_account_rate_limits_read",
21177
+ quota: { status: "error", sourceEpoch: codexQuotaSourceEpoch, code: "provider_error", retryable: true }
21178
+ }];
21179
+ }
21180
+ return this.replaceQuotaSnapshots(msg.result ?? {});
21181
+ }
20741
21182
  if (msg?.error && msg.id !== undefined) {
20742
21183
  return [{ kind: "error", message: msg.error?.message ?? "Codex RPC error" }];
20743
21184
  }
@@ -20762,6 +21203,7 @@ class CodexEventNormalizer {
20762
21203
  return [];
20763
21204
  this.turnId = params.turn.id;
20764
21205
  this.terminalTurn = null;
21206
+ this.pendingTurnUsage = null;
20765
21207
  return [
20766
21208
  {
20767
21209
  kind: "turn_owner",
@@ -20790,24 +21232,36 @@ class CodexEventNormalizer {
20790
21232
  case "turn/completed":
20791
21233
  if (!this.acceptRootTerminal(params))
20792
21234
  return [];
21235
+ const usage = this.pendingTurnUsage;
21236
+ this.pendingTurnUsage = null;
20793
21237
  if (params.turn.status === "failed") {
20794
21238
  return [
21239
+ ...usage ? [usage] : [],
20795
21240
  { kind: "error", message: "Codex turn failed" },
20796
21241
  { kind: "turn_end", sessionId: this.threadId ?? undefined, turnOwner: this.turnReceipt(params.threadId, params.turn.id) }
20797
21242
  ];
20798
21243
  }
20799
21244
  if (params.turn.status === "interrupted") {
20800
- return [{ kind: "error", message: "Codex turn interrupted" }, { kind: "turn_end", sessionId: this.threadId ?? undefined, turnOwner: this.turnReceipt(params.threadId, params.turn.id) }];
21245
+ return [...usage ? [usage] : [], { kind: "error", message: "Codex turn interrupted" }, { kind: "turn_end", sessionId: this.threadId ?? undefined, turnOwner: this.turnReceipt(params.threadId, params.turn.id) }];
20801
21246
  }
20802
- return [{ kind: "turn_end", sessionId: this.threadId ?? undefined, turnOwner: this.turnReceipt(params.threadId, params.turn.id) }];
21247
+ return [...usage ? [usage] : [], { kind: "turn_end", sessionId: this.threadId ?? undefined, turnOwner: this.turnReceipt(params.threadId, params.turn.id) }];
20803
21248
  case "error":
20804
21249
  if (params?.willRetry === true) {
20805
21250
  return [{ kind: "runtime_recovery", stage: "retrying", source: "codex_stream" }];
20806
21251
  }
20807
21252
  return [{ kind: "error", message: params?.error?.message ?? params?.message ?? "Codex error" }];
20808
- case "thread/tokenUsage/updated":
21253
+ case "thread/tokenUsage/updated": {
21254
+ const usage2 = mapCodexTelemetry(method, params, codexQuotaSourceEpoch)[0];
21255
+ if (usage2)
21256
+ this.pendingTurnUsage = usage2;
21257
+ return [];
21258
+ }
20809
21259
  case "account/rateLimits/updated":
20810
- return mapCodexTelemetry(method, params);
21260
+ return this.mergeQuotaSnapshots(params);
21261
+ case "account/updated":
21262
+ rotateCodexQuotaSource();
21263
+ this.syncQuotaSourceGeneration();
21264
+ return [];
20811
21265
  default:
20812
21266
  return [];
20813
21267
  }
@@ -20920,7 +21374,53 @@ function resolveCodexHomeRootFromEnv(env = process.env, opts = {}) {
20920
21374
  return path6.join(opts.defaultHomeDir ?? os.homedir(), ".codex");
20921
21375
  }
20922
21376
 
21377
+ // agent-driver/dist/internal/errors.js
21378
+ var MAX_PUBLIC_ERROR_MESSAGE = 1000;
21379
+ var CREDENTIAL_NAME = String.raw`(?:[A-Za-z0-9]{1,32}[_-]){0,4}(?:api[_-]?key|access[_-]?key|secret(?:[_-]?access[_-]?key)?|client[_-]?secret|access[_-]?token|auth(?:orization)?|password|passwd|token|voucher)(?:[_-][A-Za-z0-9]{1,32}){0,4}`;
21380
+ var QUOTED_CREDENTIAL_ASSIGNMENT = new RegExp(String.raw`(["'])(${CREDENTIAL_NAME})\1\s*[:=]\s*(["'])[^"'\r\n]*\3`, "gi");
21381
+ var CREDENTIAL_ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9_-])((?:${CREDENTIAL_NAME})\s*[:=]\s*)(?!\[redacted\])[^\s,;}\]]+`, "gi");
21382
+ function scrubDriverErrorMessage(value, fallback = "Runtime operation failed") {
21383
+ const text2 = value instanceof Error ? value.message : String(value ?? "");
21384
+ const scrubbed = text2.replace(/\b(?:cmk|cmt|crk)_[A-Za-z0-9_-]+\b/g, "[redacted-token]").replace(/(Authorization\s*:\s*)(?:Bearer|Basic)\s+[^\s,;]+/gi, "$1[redacted]").replace(/Bearer\s+[A-Za-z0-9._\-]+/gi, "Bearer [redacted]").replace(/\b(?:sk|sk-ant|sk-proj|xox[abprs])-[A-Za-z0-9._\-]+/gi, "[redacted-token]").replace(QUOTED_CREDENTIAL_ASSIGNMENT, "$1$2$1:$3[redacted]$3").replace(CREDENTIAL_ASSIGNMENT, "$1[redacted]").replace(/(?<![A-Za-z0-9._%+\-])[A-Za-z0-9._%+\-]{1,320}@[A-Za-z0-9.\-]{1,255}\.[A-Za-z]{2,63}/g, "[redacted-email]").replace(/([?&])([^=\s]+)=([^&\s]+)/g, "$1$2=[redacted]").replace(/\/(?:Users|home)\/[^\r\n,;]+/g, "[redacted-path]").replace(/[A-Za-z]:\\Users\\[^\r\n,;]+/gi, "[redacted-path]").replace(/\\\\[^\\\s]+\\[^\r\n,;]+/g, "[redacted-path]").replace(/(?:[A-Za-z]:\\|\/)(?:[^\s/:]+[\\/]){1,}[^\s:]*/g, "[redacted-path]").trim();
21385
+ return (scrubbed || fallback).slice(0, MAX_PUBLIC_ERROR_MESSAGE);
21386
+ }
21387
+ function scrubDriverError(error51) {
21388
+ return {
21389
+ ...error51,
21390
+ code: stableErrorCode(error51.code, "runtime_error"),
21391
+ message: scrubDriverErrorMessage(error51.message),
21392
+ ...error51.details ? { details: scrubDetails(error51.details) } : {}
21393
+ };
21394
+ }
21395
+ function scrubDetails(details) {
21396
+ const scrubValue = (value, key) => {
21397
+ if (key && /api[_-]?key|access[_-]?token|auth(?:orization)?|password|passwd|secret|token/i.test(key)) {
21398
+ return "[redacted]";
21399
+ }
21400
+ if (typeof value === "string")
21401
+ return scrubDriverErrorMessage(value, "[redacted]");
21402
+ if (Array.isArray(value))
21403
+ return value.map((item) => scrubValue(item));
21404
+ if (value && typeof value === "object") {
21405
+ return Object.fromEntries(Object.entries(value).map(([childKey, child]) => [
21406
+ childKey,
21407
+ scrubValue(child, childKey)
21408
+ ]));
21409
+ }
21410
+ return value;
21411
+ };
21412
+ return scrubValue(details);
21413
+ }
21414
+ function stableErrorCode(value, fallback) {
21415
+ const code = String(value ?? "");
21416
+ return /^[A-Za-z0-9_.-]{1,100}$/.test(code) ? code : fallback;
21417
+ }
21418
+
20923
21419
  // agent-driver/dist/adapters/codex/index.js
21420
+ var SETTINGS_UPDATE_TIMEOUT_MS = 5000;
21421
+ var MODEL_LIST_TIMEOUT_MS = 5000;
21422
+ var MODEL_LIST_MAX = 64;
21423
+ var MODEL_EFFORT_MAX = 16;
20924
21424
  function isCodexMissingRolloutError(message2) {
20925
21425
  return /\bno\s+rollout\s+found\b/i.test(message2) || /\bmissing\s+rollout\b/i.test(message2) || /\brollout\b.*\b(not found|missing)\b/i.test(message2) || /\b(not found|missing)\b.*\brollout\b/i.test(message2);
20926
21426
  }
@@ -20941,19 +21441,157 @@ class CodexDriver {
20941
21441
  }
20942
21442
  };
20943
21443
  eventNormalizer = new CodexEventNormalizer;
21444
+ pendingAccountReadRequestIds = new Set;
20944
21445
  requestId = 0;
20945
21446
  codexHomeRoot = null;
20946
21447
  proc = null;
20947
21448
  pendingInitialPrompt = null;
20948
21449
  pendingResumeFallbackParams = null;
21450
+ pendingSettingsUpdates = new Map;
20949
21451
  nextRequestId() {
20950
21452
  return ++this.requestId;
20951
21453
  }
21454
+ requestAccountQuotaSnapshot() {
21455
+ if (!this.proc?.stdin || this.proc.stdin.destroyed)
21456
+ return;
21457
+ const accountReadRequestId = this.nextRequestId();
21458
+ this.pendingAccountReadRequestIds.add(accountReadRequestId);
21459
+ this.eventNormalizer.registerAccountReadRequest(accountReadRequestId);
21460
+ this.proc.stdin.write(jsonRpcRequest("account/read", { refreshToken: false }, accountReadRequestId) + `
21461
+ `);
21462
+ }
21463
+ requestQuotaSnapshot() {
21464
+ if (!this.proc?.stdin || this.proc.stdin.destroyed)
21465
+ return;
21466
+ const quotaReadRequestId = this.nextRequestId();
21467
+ this.eventNormalizer.registerQuotaReadRequest(quotaReadRequestId);
21468
+ this.proc.stdin.write(jsonRpcRequest("account/rateLimits/read", {}, quotaReadRequestId) + `
21469
+ `);
21470
+ }
20952
21471
  get codexHome() {
20953
21472
  return this.codexHomeRoot;
20954
21473
  }
20955
- probe(command) {
20956
- return probeCliRuntime("codex", {}, command);
21474
+ async probe(command) {
21475
+ const result = await probeCliRuntime("codex", {}, command);
21476
+ if (result.status !== "healthy")
21477
+ return result;
21478
+ return {
21479
+ ...result,
21480
+ reasoning: await this.probeReasoningCatalog(command)
21481
+ };
21482
+ }
21483
+ async probeReasoningCatalog(command) {
21484
+ const spec = resolveSpawnSpec("codex", ["app-server", "--listen", "stdio://"], command);
21485
+ let proc;
21486
+ try {
21487
+ proc = spawnAgentProcess(spec.command, spec.args, {
21488
+ cwd: process.cwd(),
21489
+ env: { ...process.env, CI: "1" },
21490
+ shell: spec.shell
21491
+ });
21492
+ } catch {
21493
+ return;
21494
+ }
21495
+ return new Promise((resolve2) => {
21496
+ let settled = false;
21497
+ let buffer = "";
21498
+ let nextId = 0;
21499
+ let initializeId = 0;
21500
+ let listId = 0;
21501
+ const models = [];
21502
+ const seenModels = new Set;
21503
+ let defaultModelId;
21504
+ const finish = (catalog) => {
21505
+ if (settled)
21506
+ return;
21507
+ settled = true;
21508
+ clearTimeout(timer);
21509
+ const done = proc.pid ? killProcessTree(proc.pid, { graceMs: 250 }).catch(() => {}) : Promise.resolve().then(() => {
21510
+ proc.kill("SIGTERM");
21511
+ });
21512
+ done.finally(() => resolve2(catalog));
21513
+ };
21514
+ const requestModelPage = (cursor) => {
21515
+ listId = ++nextId;
21516
+ proc.stdin?.write(jsonRpcRequest("model/list", { limit: Math.min(MODEL_LIST_MAX - models.length, MODEL_LIST_MAX), includeHidden: false, ...cursor ? { cursor } : {} }, listId) + `
21517
+ `);
21518
+ };
21519
+ const consumeModel = (value) => {
21520
+ if (!value || typeof value !== "object" || models.length >= MODEL_LIST_MAX)
21521
+ return;
21522
+ const model = value;
21523
+ const id = typeof model.id === "string" ? model.id.trim() : "";
21524
+ if (!id || id.length > 100 || seenModels.has(id))
21525
+ return;
21526
+ const rawOptions = Array.isArray(model.supportedReasoningEfforts) ? model.supportedReasoningEfforts : [];
21527
+ const seenEfforts = new Set;
21528
+ const supportedReasoningEfforts = rawOptions.flatMap((raw) => {
21529
+ if (!raw || typeof raw !== "object")
21530
+ return [];
21531
+ const option = raw;
21532
+ const value2 = typeof option.reasoningEffort === "string" ? option.reasoningEffort.trim() : "";
21533
+ if (!value2 || value2.length > 32 || !/^[A-Za-z0-9._-]+$/.test(value2) || seenEfforts.has(value2))
21534
+ return [];
21535
+ seenEfforts.add(value2);
21536
+ const description = typeof option.description === "string" ? option.description.slice(0, 256) : undefined;
21537
+ return [{ value: value2, ...description ? { description } : {} }];
21538
+ }).slice(0, MODEL_EFFORT_MAX);
21539
+ const candidateDefault = typeof model.defaultReasoningEffort === "string" ? model.defaultReasoningEffort : undefined;
21540
+ seenModels.add(id);
21541
+ if (model.isDefault === true)
21542
+ defaultModelId = id;
21543
+ models.push({
21544
+ id,
21545
+ supportedReasoningEfforts,
21546
+ ...candidateDefault && supportedReasoningEfforts.some((item) => item.value === candidateDefault) ? { defaultReasoningEffort: candidateDefault } : {}
21547
+ });
21548
+ };
21549
+ const onLine = (line) => {
21550
+ let message2;
21551
+ try {
21552
+ message2 = JSON.parse(line);
21553
+ } catch {
21554
+ return;
21555
+ }
21556
+ if (message2.id === initializeId) {
21557
+ if (message2.error)
21558
+ return finish();
21559
+ requestModelPage();
21560
+ return;
21561
+ }
21562
+ if (message2.id !== listId)
21563
+ return;
21564
+ if (message2.error || !message2.result || typeof message2.result !== "object")
21565
+ return finish();
21566
+ const result = message2.result;
21567
+ for (const model of Array.isArray(result.data) ? result.data : [])
21568
+ consumeModel(model);
21569
+ const cursor = typeof result.nextCursor === "string" ? result.nextCursor : undefined;
21570
+ if (cursor && models.length < MODEL_LIST_MAX)
21571
+ return requestModelPage(cursor);
21572
+ finish({
21573
+ updateMode: "live_next_turn",
21574
+ ...defaultModelId ? { defaultModelId } : {},
21575
+ models
21576
+ });
21577
+ };
21578
+ const timer = setTimeout(() => finish(), MODEL_LIST_TIMEOUT_MS);
21579
+ timer.unref?.();
21580
+ proc.stdout?.on("data", (chunk2) => {
21581
+ buffer += chunk2.toString();
21582
+ const lines = buffer.split(`
21583
+ `);
21584
+ buffer = lines.pop() ?? "";
21585
+ for (const line of lines)
21586
+ if (line.trim())
21587
+ onLine(line);
21588
+ });
21589
+ proc.on("error", () => finish());
21590
+ proc.on("exit", () => finish());
21591
+ initializeId = ++nextId;
21592
+ proc.stdin?.write(jsonRpcRequest("initialize", { clientInfo: { name: "alook-agent-driver-probe", version: "0.1.24" }, capabilities: { experimentalApi: true } }, initializeId) + `
21593
+ `);
21594
+ });
20957
21595
  }
20958
21596
  async openLane(ctx, options) {
20959
21597
  return createProcessLane(this, ctx, { onRawStdoutLine: options?.onRawStdoutLine });
@@ -20969,6 +21607,9 @@ class CodexDriver {
20969
21607
  shell: spec.shell
20970
21608
  });
20971
21609
  this.proc = proc;
21610
+ proc.once("exit", () => {
21611
+ this.failPendingSettingsUpdates("settings_process_exited", "Codex exited before acknowledging the settings update");
21612
+ });
20972
21613
  const initialPrompt = ctx.prompt?.trim() ? ctx.prompt : null;
20973
21614
  this.pendingInitialPrompt = initialPrompt;
20974
21615
  queueMicrotask(() => {
@@ -20997,11 +21638,21 @@ class CodexDriver {
20997
21638
  proc.stdin?.write(jsonRpcRequest("thread/start", freshParams, this.nextRequestId()) + `
20998
21639
  `);
20999
21640
  }
21641
+ this.requestAccountQuotaSnapshot();
21000
21642
  });
21001
21643
  return { process: proc };
21002
21644
  }
21003
21645
  normalizeLine(line) {
21646
+ const settingsResponse = this.consumeSettingsUpdateResponse(line);
21647
+ if (settingsResponse)
21648
+ return [];
21649
+ const parsed = tryParseJsonLine(line);
21004
21650
  const events = this.eventNormalizer.normalizeLine(line);
21651
+ if (typeof parsed?.id === "number" && this.pendingAccountReadRequestIds.delete(parsed.id)) {
21652
+ this.requestQuotaSnapshot();
21653
+ }
21654
+ if (parsed?.method === "account/updated")
21655
+ this.requestAccountQuotaSnapshot();
21005
21656
  if (this.pendingResumeFallbackParams && this.proc?.stdin && !this.proc.stdin.destroyed) {
21006
21657
  const rolloutErr = events.find((e) => e.kind === "error" && isCodexMissingRolloutError(e.message));
21007
21658
  if (rolloutErr) {
@@ -21025,6 +21676,90 @@ class CodexDriver {
21025
21676
  }
21026
21677
  return events;
21027
21678
  }
21679
+ updateSettings(input) {
21680
+ const threadId = this.eventNormalizer.currentSessionId;
21681
+ const stdin = this.proc?.stdin;
21682
+ if (!threadId || !stdin || stdin.destroyed || stdin.writableEnded || stdin.writable === false) {
21683
+ return Promise.resolve({
21684
+ status: "failed",
21685
+ error: this.settingsError("process", "settings_thread_unavailable", "Codex thread is not available for a settings update", true)
21686
+ });
21687
+ }
21688
+ const id = this.nextRequestId();
21689
+ return new Promise((resolve2) => {
21690
+ const timer = setTimeout(() => {
21691
+ if (!this.pendingSettingsUpdates.delete(id))
21692
+ return;
21693
+ resolve2({
21694
+ status: "failed",
21695
+ error: this.settingsError("timeout", "settings_update_timeout", "Codex did not acknowledge the settings update before the deadline", true)
21696
+ });
21697
+ }, SETTINGS_UPDATE_TIMEOUT_MS);
21698
+ timer.unref?.();
21699
+ this.pendingSettingsUpdates.set(id, { resolve: resolve2, timer });
21700
+ try {
21701
+ stdin.write(jsonRpcRequest("thread/settings/update", { threadId, effort: input.reasoningEffort }, id) + `
21702
+ `);
21703
+ } catch (error51) {
21704
+ clearTimeout(timer);
21705
+ this.pendingSettingsUpdates.delete(id);
21706
+ resolve2({
21707
+ status: "failed",
21708
+ error: this.settingsError("process", "settings_update_write_failed", String(error51), true)
21709
+ });
21710
+ }
21711
+ });
21712
+ }
21713
+ consumeSettingsUpdateResponse(line) {
21714
+ let value;
21715
+ try {
21716
+ value = JSON.parse(line);
21717
+ } catch {
21718
+ return false;
21719
+ }
21720
+ if (!value || typeof value !== "object")
21721
+ return false;
21722
+ const record2 = value;
21723
+ if (typeof record2.id !== "number")
21724
+ return false;
21725
+ const pending = this.pendingSettingsUpdates.get(record2.id);
21726
+ if (!pending)
21727
+ return false;
21728
+ clearTimeout(pending.timer);
21729
+ this.pendingSettingsUpdates.delete(record2.id);
21730
+ const error51 = record2.error;
21731
+ if (!error51 || typeof error51 !== "object") {
21732
+ pending.resolve({ status: "applied" });
21733
+ return true;
21734
+ }
21735
+ const rpcError = error51;
21736
+ const message2 = typeof rpcError.message === "string" ? rpcError.message : "Codex rejected the settings update";
21737
+ if (rpcError.code === -32601 || /method\s+not\s+found/i.test(message2)) {
21738
+ pending.resolve({
21739
+ status: "unsupported",
21740
+ error: this.settingsError("protocol", "settings_update_unsupported", "Codex does not support live reasoning settings updates", false)
21741
+ });
21742
+ } else {
21743
+ pending.resolve({
21744
+ status: "failed",
21745
+ error: this.settingsError("protocol", "settings_update_rejected", message2, true)
21746
+ });
21747
+ }
21748
+ return true;
21749
+ }
21750
+ settingsError(category, code, message2, retryable) {
21751
+ return { category, code, message: scrubDriverErrorMessage(message2), retryable };
21752
+ }
21753
+ failPendingSettingsUpdates(code, message2) {
21754
+ for (const [id, pending] of this.pendingSettingsUpdates) {
21755
+ clearTimeout(pending.timer);
21756
+ this.pendingSettingsUpdates.delete(id);
21757
+ pending.resolve({
21758
+ status: "failed",
21759
+ error: this.settingsError("process", code, message2, true)
21760
+ });
21761
+ }
21762
+ }
21028
21763
  get currentSessionId() {
21029
21764
  return this.eventNormalizer.currentSessionId;
21030
21765
  }
@@ -21343,15 +22078,6 @@ class CursorAcpLane {
21343
22078
  }
21344
22079
  this.activePrompt = null;
21345
22080
  this.openToolCalls.clear();
21346
- const usage = record2(result.usage);
21347
- if (usage) {
21348
- this.events.emit("runtime_event", {
21349
- kind: "telemetry",
21350
- name: "token_usage",
21351
- source: "cursor.acp",
21352
- attrs: usage
21353
- });
21354
- }
21355
22081
  this.events.emit("runtime_event", {
21356
22082
  kind: "turn_end",
21357
22083
  sessionId: this.sessionId ?? undefined,
@@ -21701,10 +22427,10 @@ class CursorDriver {
21701
22427
  }
21702
22428
 
21703
22429
  // agent-driver/dist/adapters/opencode/index.js
21704
- import { randomBytes as randomBytes2 } from "node:crypto";
22430
+ import { randomBytes as randomBytes3 } from "node:crypto";
21705
22431
 
21706
22432
  // agent-driver/dist/adapters/opencode/service-lane.js
21707
- import { randomBytes } from "node:crypto";
22433
+ import { randomBytes as randomBytes2 } from "node:crypto";
21708
22434
  import { EventEmitter as EventEmitter3 } from "node:events";
21709
22435
  import { createServer as createServer2 } from "node:net";
21710
22436
  var SUPPORTED_VERSION = "1.17.20";
@@ -21843,7 +22569,7 @@ class OpenCodeServiceLane {
21843
22569
  this.ctx = ctx;
21844
22570
  this.options = options;
21845
22571
  this.fetchFn = options.fetch ?? fetch;
21846
- this.password = options.password ?? randomBytes(32).toString("base64url");
22572
+ this.password = options.password ?? randomBytes2(32).toString("base64url");
21847
22573
  }
21848
22574
  get currentSessionId() {
21849
22575
  return this.sessionId;
@@ -22457,12 +23183,20 @@ class OpenCodeServiceLane {
22457
23183
  });
22458
23184
  }
22459
23185
  const tokens = record3(data.tokens);
22460
- if (tokens) {
23186
+ if (tokens && data.finish !== "tool-calls") {
23187
+ const cache = record3(tokens.cache);
23188
+ const metric2 = (value2) => typeof value2 === "number" && Number.isSafeInteger(value2) && value2 >= 0 ? value2 : null;
23189
+ const cacheParts = [cache?.read, cache?.write].filter((value2) => typeof value2 === "number" && Number.isSafeInteger(value2) && value2 >= 0);
23190
+ const cacheTotal = cacheParts.reduce((sum, value2) => sum + value2, 0);
22461
23191
  this.events.emit("runtime_event", {
22462
23192
  kind: "telemetry",
22463
23193
  name: "token_usage",
22464
23194
  source: "opencode.v2",
22465
- attrs: tokens
23195
+ usage: {
23196
+ input: metric2(tokens.input),
23197
+ output: metric2(tokens.output),
23198
+ cache: cacheParts.length > 0 && Number.isSafeInteger(cacheTotal) ? cacheTotal : null
23199
+ }
22466
23200
  });
22467
23201
  }
22468
23202
  break;
@@ -22768,7 +23502,7 @@ class OpenCodeServiceLane {
22768
23502
  return headers;
22769
23503
  }
22770
23504
  newMessageId() {
22771
- return `msg_${randomBytes(16).toString("hex")}`;
23505
+ return `msg_${randomBytes2(16).toString("hex")}`;
22772
23506
  }
22773
23507
  diagnostic(severity, message2) {
22774
23508
  this.events.emit("runtime_event", {
@@ -22833,7 +23567,7 @@ class OpenCodeServiceLane {
22833
23567
 
22834
23568
  // agent-driver/dist/adapters/opencode/index.js
22835
23569
  function createOpenCodeMessageId() {
22836
- return `msg_${randomBytes2(16).toString("hex")}`;
23570
+ return `msg_${randomBytes3(16).toString("hex")}`;
22837
23571
  }
22838
23572
 
22839
23573
  class OpenCodeDriver {
@@ -23611,48 +24345,6 @@ function assertInstructionFileName(name) {
23611
24345
  }
23612
24346
  }
23613
24347
 
23614
- // agent-driver/dist/internal/errors.js
23615
- var MAX_PUBLIC_ERROR_MESSAGE = 1000;
23616
- var CREDENTIAL_NAME = String.raw`(?:[A-Za-z0-9]{1,32}[_-]){0,4}(?:api[_-]?key|access[_-]?key|secret(?:[_-]?access[_-]?key)?|client[_-]?secret|access[_-]?token|auth(?:orization)?|password|passwd|token|voucher)(?:[_-][A-Za-z0-9]{1,32}){0,4}`;
23617
- var QUOTED_CREDENTIAL_ASSIGNMENT = new RegExp(String.raw`(["'])(${CREDENTIAL_NAME})\1\s*[:=]\s*(["'])[^"'\r\n]*\3`, "gi");
23618
- var CREDENTIAL_ASSIGNMENT = new RegExp(String.raw`(?<![A-Za-z0-9_-])((?:${CREDENTIAL_NAME})\s*[:=]\s*)(?!\[redacted\])[^\s,;}\]]+`, "gi");
23619
- function scrubDriverErrorMessage(value, fallback = "Runtime operation failed") {
23620
- const text2 = value instanceof Error ? value.message : String(value ?? "");
23621
- const scrubbed = text2.replace(/\b(?:cmk|cmt|crk)_[A-Za-z0-9_-]+\b/g, "[redacted-token]").replace(/(Authorization\s*:\s*)(?:Bearer|Basic)\s+[^\s,;]+/gi, "$1[redacted]").replace(/Bearer\s+[A-Za-z0-9._\-]+/gi, "Bearer [redacted]").replace(/\b(?:sk|sk-ant|sk-proj|xox[abprs])-[A-Za-z0-9._\-]+/gi, "[redacted-token]").replace(QUOTED_CREDENTIAL_ASSIGNMENT, "$1$2$1:$3[redacted]$3").replace(CREDENTIAL_ASSIGNMENT, "$1[redacted]").replace(/(?<![A-Za-z0-9._%+\-])[A-Za-z0-9._%+\-]{1,320}@[A-Za-z0-9.\-]{1,255}\.[A-Za-z]{2,63}/g, "[redacted-email]").replace(/([?&])([^=\s]+)=([^&\s]+)/g, "$1$2=[redacted]").replace(/\/(?:Users|home)\/[^\r\n,;]+/g, "[redacted-path]").replace(/[A-Za-z]:\\Users\\[^\r\n,;]+/gi, "[redacted-path]").replace(/\\\\[^\\\s]+\\[^\r\n,;]+/g, "[redacted-path]").replace(/(?:[A-Za-z]:\\|\/)(?:[^\s/:]+[\\/]){1,}[^\s:]*/g, "[redacted-path]").trim();
23622
- return (scrubbed || fallback).slice(0, MAX_PUBLIC_ERROR_MESSAGE);
23623
- }
23624
- function scrubDriverError(error51) {
23625
- return {
23626
- ...error51,
23627
- code: stableErrorCode(error51.code, "runtime_error"),
23628
- message: scrubDriverErrorMessage(error51.message),
23629
- ...error51.details ? { details: scrubDetails(error51.details) } : {}
23630
- };
23631
- }
23632
- function scrubDetails(details) {
23633
- const scrubValue = (value, key) => {
23634
- if (key && /api[_-]?key|access[_-]?token|auth(?:orization)?|password|passwd|secret|token/i.test(key)) {
23635
- return "[redacted]";
23636
- }
23637
- if (typeof value === "string")
23638
- return scrubDriverErrorMessage(value, "[redacted]");
23639
- if (Array.isArray(value))
23640
- return value.map((item) => scrubValue(item));
23641
- if (value && typeof value === "object") {
23642
- return Object.fromEntries(Object.entries(value).map(([childKey, child]) => [
23643
- childKey,
23644
- scrubValue(child, childKey)
23645
- ]));
23646
- }
23647
- return value;
23648
- };
23649
- return scrubValue(details);
23650
- }
23651
- function stableErrorCode(value, fallback) {
23652
- const code = String(value ?? "");
23653
- return /^[A-Za-z0-9_.-]{1,100}$/.test(code) ? code : fallback;
23654
- }
23655
-
23656
24348
  // agent-driver/dist/controller/logical-session.js
23657
24349
  import { mkdirSync as mkdirSync4 } from "node:fs";
23658
24350
  var SEMANTIC_ASSEMBLER_MAX_BYTES = 1048576;
@@ -23770,6 +24462,8 @@ class LogicalAgentSession {
23770
24462
  toolBoundaryFlushDisabled = false;
23771
24463
  safeBoundaryFlush;
23772
24464
  safeBoundaryDelivery;
24465
+ settingsUpdateTail = Promise.resolve();
24466
+ settingsUpdatePending = false;
23773
24467
  turnAdmission;
23774
24468
  instructionsMaterialized = false;
23775
24469
  lifecycleGeneration = 0;
@@ -23825,6 +24519,35 @@ class LogicalAgentSession {
23825
24519
  send(message2) {
23826
24520
  return this.admit("send", message2);
23827
24521
  }
24522
+ updateSettings(input) {
24523
+ if (this.state === "closed" || this.state === "stopping" || this.finishing) {
24524
+ return Promise.resolve({
24525
+ status: "failed",
24526
+ error: driverError("process", "settings_session_closed", "Runtime session is closed", true)
24527
+ });
24528
+ }
24529
+ this.settingsUpdatePending = true;
24530
+ const operation = this.settingsUpdateTail.then(async () => {
24531
+ if (!this.lane?.updateSettings)
24532
+ return { status: "unsupported" };
24533
+ try {
24534
+ return await this.lane.updateSettings(input);
24535
+ } catch (error51) {
24536
+ return {
24537
+ status: "failed",
24538
+ error: driverError("process", "settings_update_failed", String(error51), true)
24539
+ };
24540
+ }
24541
+ });
24542
+ this.settingsUpdateTail = operation.then((result) => {
24543
+ if (result.status === "applied") {
24544
+ this.settingsUpdatePending = false;
24545
+ return;
24546
+ }
24547
+ return new Promise(() => {});
24548
+ });
24549
+ return operation;
24550
+ }
23828
24551
  async interrupt(input) {
23829
24552
  if (this.state === "closed" || this.state === "stopping" || this.finishing)
23830
24553
  return { status: "closed" };
@@ -23986,7 +24709,7 @@ class LogicalAgentSession {
23986
24709
  }
23987
24710
  return receipt;
23988
24711
  }
23989
- if (this.state === "idle" && (this.queued.length > 0 || this.safeBoundaryFlush !== undefined || this.safeBoundaryDelivery !== undefined)) {
24712
+ if (this.state === "idle" && (this.queued.length > 0 || this.safeBoundaryFlush !== undefined || this.safeBoundaryDelivery !== undefined || this.settingsUpdatePending)) {
23990
24713
  return this.queue(message2, "runtime_busy");
23991
24714
  }
23992
24715
  return this.startTurn([message2], "prompt");
@@ -24294,11 +25017,10 @@ class LogicalAgentSession {
24294
25017
  }
24295
25018
  return;
24296
25019
  case "telemetry": {
24297
- const details = jsonValue(event.attrs);
24298
25020
  if (event.name === "token_usage") {
24299
- this.emit({ type: "token_usage", turnId, source: event.source, usage: {}, details });
25021
+ this.emit({ type: "token_usage", turnId, source: event.source, usage: event.usage });
24300
25022
  } else {
24301
- this.emit({ type: "rate_limits", turnId, source: event.source, details });
25023
+ this.emit({ type: "rate_limits", turnId, source: event.source, quota: event.quota });
24302
25024
  }
24303
25025
  return;
24304
25026
  }
@@ -24399,7 +25121,7 @@ class LogicalAgentSession {
24399
25121
  if (this.adapter.execution.lifetime === "turn") {
24400
25122
  this.processTurnEnded = true;
24401
25123
  } else {
24402
- Promise.resolve().then(() => this.safeBoundaryFlush).then(() => this.startNextQueued());
25124
+ Promise.resolve().then(() => this.safeBoundaryFlush).then(() => this.settingsUpdateTail).then(() => this.startNextQueued());
24403
25125
  }
24404
25126
  }
24405
25127
  flushSafeBoundaryQueue() {
@@ -24899,8 +25621,14 @@ function createAgentDriverSdkWithRegistry(options) {
24899
25621
  assertAdapterCompatibility(String(registration.id), registration.capabilities, adapter);
24900
25622
  const command = capabilities2.commandOverride ? input.command : undefined;
24901
25623
  const result = await adapter.probe(command);
24902
- if (result.status === "healthy")
24903
- return { status: "healthy", version: result.version, capabilities: capabilities2 };
25624
+ if (result.status === "healthy") {
25625
+ return {
25626
+ status: "healthy",
25627
+ version: result.version,
25628
+ capabilities: capabilities2,
25629
+ reasoning: result.reasoning
25630
+ };
25631
+ }
24904
25632
  return {
24905
25633
  status: "unhealthy",
24906
25634
  error: {
@@ -24909,7 +25637,8 @@ function createAgentDriverSdkWithRegistry(options) {
24909
25637
  message: `Backend ${input.backend} is unavailable`,
24910
25638
  retryable: true
24911
25639
  },
24912
- capabilities: capabilities2
25640
+ capabilities: capabilities2,
25641
+ reasoning: result.reasoning
24913
25642
  };
24914
25643
  } catch (error51) {
24915
25644
  const contractInvalid = error51 instanceof Error && (error51.message.startsWith("Adapter ") || error51.message.startsWith("Agent backend registration "));
@@ -25061,7 +25790,12 @@ async function detectRuntimes() {
25061
25790
  const driver = getDriver(id);
25062
25791
  const probe = await driver.probe();
25063
25792
  if (probe.status === "healthy") {
25064
- results.push({ id, status: "healthy", version: probe.version });
25793
+ results.push({
25794
+ id,
25795
+ status: "healthy",
25796
+ version: probe.version,
25797
+ reasoning: probe.reasoning
25798
+ });
25065
25799
  } else {
25066
25800
  results.push({
25067
25801
  id,
@@ -25177,7 +25911,7 @@ import * as path12 from "node:path";
25177
25911
  import { WebSocket } from "ws";
25178
25912
 
25179
25913
  // src/daemon/createDaemon.ts
25180
- import { homedir as homedir4 } from "os";
25914
+ import { homedir as homedir5 } from "os";
25181
25915
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync8 } from "node:fs";
25182
25916
 
25183
25917
  // src/util/rotatingFileSink.ts
@@ -25865,23 +26599,43 @@ class WsControlChannel {
25865
26599
  this.ws.send(JSON.stringify(frame));
25866
26600
  }
25867
26601
  resyncOnConnect() {
26602
+ const sendActivities = (activities, counts) => {
26603
+ for (const activity of activities) {
26604
+ this.sendFrame({ type: "agent_activity", ...activity });
26605
+ }
26606
+ this.log.info("resync sent", {
26607
+ ready: counts.ready,
26608
+ sessions: counts.sessions,
26609
+ activities: activities.length,
26610
+ pendingAuditEvents: this.pendingBotAuditEvents.size
26611
+ });
26612
+ };
25868
26613
  if (this.resyncProvider) {
25869
- const { ready, sessions, activities } = this.resyncProvider();
25870
- this.sendFrame({ type: "ready", ...ready });
25871
- for (const s of sessions)
25872
- this.sendFrame({ type: "agent_session", ...s });
25873
- const liveActivities = activities ?? [];
25874
- for (const a of liveActivities)
25875
- this.sendFrame({ type: "agent_activity", ...a });
26614
+ const socketAtStart = this.ws;
26615
+ const snapshot = this.resyncProvider();
26616
+ this.sendFrame({ type: "ready", ...snapshot.ready });
26617
+ for (const session2 of snapshot.sessions) {
26618
+ this.sendFrame({ type: "agent_session", ...session2 });
26619
+ }
25876
26620
  for (const frame of this.pendingBotAuditEvents.values())
25877
26621
  this.sendFrame(frame);
25878
26622
  this.scheduleAuditRetry();
25879
- this.log.info("resync sent", {
25880
- ready: ready.runtimeReport.length,
25881
- sessions: sessions.length,
25882
- activities: liveActivities.length,
25883
- pendingAuditEvents: this.pendingBotAuditEvents.size
25884
- });
26623
+ const activities = snapshot.activities ?? [];
26624
+ const counts = {
26625
+ ready: snapshot.ready.runtimeReport.length,
26626
+ sessions: snapshot.sessions.length
26627
+ };
26628
+ if (activities instanceof Promise) {
26629
+ activities.then((resolved) => {
26630
+ if (this.ws === socketAtStart && this.statusValue === "open") {
26631
+ sendActivities(resolved, counts);
26632
+ }
26633
+ }).catch((err) => {
26634
+ this.log.warn("resync provider failed", { err: describeErr(err) });
26635
+ });
26636
+ } else {
26637
+ sendActivities(activities, counts);
26638
+ }
25885
26639
  }
25886
26640
  for (const hook of this.resyncHooks) {
25887
26641
  try {
@@ -26687,6 +27441,29 @@ function reduceManager(state, event) {
26687
27441
  a.inbox = [...a.inbox, event.message];
26688
27442
  a.idleSince = null;
26689
27443
  });
27444
+ case "runtime_config_queued":
27445
+ return mutate(state, event.agentId, (a) => {
27446
+ if (!a.inbox.some((message2) => message2.id === event.message.id)) {
27447
+ a.inbox = [...a.inbox, event.message];
27448
+ }
27449
+ syncExecutionProjection(a);
27450
+ a.idleSince = null;
27451
+ });
27452
+ case "runtime_config_applied": {
27453
+ const existing = state.agents[event.agentId];
27454
+ if (!existing)
27455
+ return { state, effects: [] };
27456
+ const agent2 = clone2(existing);
27457
+ if (agent2.status !== "running" || leaseIsWorking(agent2.execution.lease) || agent2.pendingAdmissions.length > 0 || agent2.inbox.length === 0)
27458
+ return { state, effects: [] };
27459
+ const messages = drainInbox(agent2);
27460
+ return commit(state, agent2, messages.map((message2) => ({
27461
+ type: "send",
27462
+ agentId: event.agentId,
27463
+ message: message2,
27464
+ mode: "idle"
27465
+ })));
27466
+ }
26690
27467
  case "turn_started": {
26691
27468
  const existing = state.agents[event.agentId];
26692
27469
  if (!existing || existing.execution.sessionInstanceId !== event.sessionInstanceId)
@@ -26894,7 +27671,7 @@ function onTurnCompleted(state, agentId, sessionInstanceId, nowMs, turnId, endRe
26894
27671
  agent2.stalledSessionId = null;
26895
27672
  syncExecutionProjection(agent2);
26896
27673
  const clearEffects = clearedStallSessionId === null ? [] : [{ type: "clear_stall_recovery", agentId, sessionId: clearedStallSessionId }];
26897
- if (agent2.inbox.length > 0) {
27674
+ if (agent2.inbox.length > 0 && !agent2.resetting) {
26898
27675
  const messages = drainInbox(agent2);
26899
27676
  return commit(state, agent2, [
26900
27677
  ...clearEffects,
@@ -27154,6 +27931,144 @@ function toAgentBackendSelection(config2) {
27154
27931
  function runtimeModelName(config2) {
27155
27932
  return config2?.model.kind === "default" ? undefined : config2?.model.name;
27156
27933
  }
27934
+ // agent-driver/dist/provider-quota.js
27935
+ import { execFile } from "node:child_process";
27936
+ import { readFile } from "node:fs/promises";
27937
+ import { homedir as homedir3 } from "node:os";
27938
+ import { join as join11 } from "node:path";
27939
+ import { promisify } from "node:util";
27940
+ import { randomBytes as randomBytes5 } from "node:crypto";
27941
+ var execFileAsync = promisify(execFile);
27942
+ var claudeAccessToken = null;
27943
+ var claudeSourceEpoch = randomBytes5(16).toString("base64url");
27944
+ function parseCredentials(value) {
27945
+ try {
27946
+ const parsed = JSON.parse(value);
27947
+ return parsed && typeof parsed === "object" ? parsed : null;
27948
+ } catch {
27949
+ return null;
27950
+ }
27951
+ }
27952
+ async function claudeCredentials(options) {
27953
+ const platform = options.platform ?? process.platform;
27954
+ if (platform === "darwin") {
27955
+ try {
27956
+ const value = options.readKeychain ? await options.readKeychain() : (await execFileAsync("security", ["find-generic-password", "-s", "Claude Code-credentials", "-w"], {
27957
+ timeout: 3000,
27958
+ maxBuffer: 256 * 1024
27959
+ })).stdout;
27960
+ const parsed = parseCredentials(value.trim());
27961
+ if (parsed)
27962
+ return parsed;
27963
+ } catch {}
27964
+ }
27965
+ const env = options.env ?? process.env;
27966
+ const root = env.CLAUDE_CONFIG_DIR || join11(options.home ?? homedir3(), ".claude");
27967
+ try {
27968
+ const value = options.readCredentialsFile ? await options.readCredentialsFile(join11(root, ".credentials.json")) : await readFile(join11(root, ".credentials.json"), "utf8");
27969
+ return parseCredentials(value);
27970
+ } catch {
27971
+ return null;
27972
+ }
27973
+ }
27974
+ function mappedPlanName2(value) {
27975
+ switch (value) {
27976
+ case "free":
27977
+ return "Free";
27978
+ case "pro":
27979
+ return "Pro";
27980
+ case "max":
27981
+ return "Max";
27982
+ case "team":
27983
+ return "Team";
27984
+ case "enterprise":
27985
+ return "Enterprise";
27986
+ default:
27987
+ return;
27988
+ }
27989
+ }
27990
+ function resetIso2(value) {
27991
+ if (typeof value !== "string")
27992
+ return;
27993
+ const date5 = new Date(value);
27994
+ return Number.isNaN(date5.getTime()) ? undefined : date5.toISOString();
27995
+ }
27996
+ function claudeLimit(key, value) {
27997
+ if (!value || typeof value !== "object")
27998
+ return null;
27999
+ const row = value;
28000
+ if (typeof row.utilization !== "number" || !Number.isFinite(row.utilization) || row.utilization < 0 || row.utilization > 100)
28001
+ return null;
28002
+ const model = key.includes("sonnet") ? { kind: "reported", id: "claude-sonnet" } : key.includes("opus") ? { kind: "reported", id: "claude-opus" } : { kind: "not_applicable" };
28003
+ const window2 = key === "five_hour" ? { kind: "rolling", durationSeconds: 18000, displayName: "5 hour usage limit" } : { kind: "rolling", durationSeconds: 604800, displayName: "7 day usage limit" };
28004
+ const resetsAt = resetIso2(row.resets_at ?? row.resetsAt);
28005
+ return {
28006
+ bucket: {
28007
+ limitId: key,
28008
+ product: { kind: "reported", id: "claude", displayName: "Claude" },
28009
+ model,
28010
+ window: window2
28011
+ },
28012
+ usedPercent: row.utilization,
28013
+ ...resetsAt ? { resetsAt } : {}
28014
+ };
28015
+ }
28016
+ async function readClaudeQuota(options) {
28017
+ const env = options.env ?? process.env;
28018
+ if (env.ANTHROPIC_API_KEY || env.ANTHROPIC_BASE_URL)
28019
+ return null;
28020
+ const credentials = await claudeCredentials(options);
28021
+ const token = credentials?.claudeAiOauth?.accessToken;
28022
+ if (typeof token !== "string" || token.length === 0)
28023
+ return null;
28024
+ if (claudeAccessToken !== token) {
28025
+ claudeAccessToken = token;
28026
+ claudeSourceEpoch = randomBytes5(16).toString("base64url");
28027
+ }
28028
+ let response;
28029
+ try {
28030
+ response = await (options.fetchUsage ?? fetch)("https://api.anthropic.com/api/oauth/usage", {
28031
+ headers: {
28032
+ authorization: `Bearer ${token}`,
28033
+ "anthropic-beta": "oauth-2025-04-20"
28034
+ },
28035
+ signal: AbortSignal.timeout(5000)
28036
+ });
28037
+ } catch {
28038
+ return { status: "error", sourceEpoch: claudeSourceEpoch, code: "network", retryable: true };
28039
+ }
28040
+ if (response.status === 401 || response.status === 403) {
28041
+ return { status: "error", sourceEpoch: claudeSourceEpoch, code: "unauthorized", retryable: false };
28042
+ }
28043
+ if (!response.ok) {
28044
+ return { status: "error", sourceEpoch: claudeSourceEpoch, code: "provider_error", retryable: response.status === 429 || response.status >= 500 };
28045
+ }
28046
+ let body;
28047
+ try {
28048
+ body = await response.json();
28049
+ } catch {
28050
+ return { status: "error", sourceEpoch: claudeSourceEpoch, code: "invalid_response", retryable: true };
28051
+ }
28052
+ if (!body || typeof body !== "object") {
28053
+ return { status: "error", sourceEpoch: claudeSourceEpoch, code: "invalid_response", retryable: true };
28054
+ }
28055
+ const record4 = body;
28056
+ const limits = ["five_hour", "seven_day", "seven_day_sonnet", "seven_day_opus"].map((key) => claudeLimit(key, record4[key])).filter((limit) => limit !== null);
28057
+ if (limits.length === 0) {
28058
+ return { status: "error", sourceEpoch: claudeSourceEpoch, code: "invalid_response", retryable: true };
28059
+ }
28060
+ const planName = mappedPlanName2(credentials?.claudeAiOauth?.subscriptionType);
28061
+ return {
28062
+ status: "available",
28063
+ sourceEpoch: claudeSourceEpoch,
28064
+ ...planName ? { planName } : {},
28065
+ freshForSeconds: 300,
28066
+ limits
28067
+ };
28068
+ }
28069
+ async function readBuiltinProviderQuota(backend, options = {}) {
28070
+ return backend === "claude" ? readClaudeQuota(options) : null;
28071
+ }
27157
28072
  // src/runtime/errorDiagnostics.ts
27158
28073
  function scrubRuntimeErrorDiagnosticText(value) {
27159
28074
  return scrubDriverErrorMessage(value);
@@ -27749,9 +28664,13 @@ class AgentProcessManager {
27749
28664
  state;
27750
28665
  sessions = new Map;
27751
28666
  runtimeConfigs = new Map;
28667
+ appliedRuntimeConfigs = new Map;
28668
+ pendingRuntimeConfigUpdates = new Map;
28669
+ runtimeConfigApplyRunning = new Set;
27752
28670
  resumeSessions = new Map;
27753
28671
  launchIds = new Map;
27754
28672
  liveSessions = new Map;
28673
+ liveBackendIds = new Map;
27755
28674
  activeSpawnState = new Map;
27756
28675
  publishedAgentActivity = new Map;
27757
28676
  traceProcessNonce = randomUUID5();
@@ -27780,19 +28699,156 @@ class AgentProcessManager {
27780
28699
  this.state = createInitialManagerState(this.opts.staleThresholdMs, this.opts.idleTimeoutMs, this.opts.resetStuckThresholdMs, this.opts.stoppingStuckThresholdMs, this.opts.idleResetTimeoutMs);
27781
28700
  }
27782
28701
  register(agentId, launch) {
27783
- if (launch?.runtimeConfig)
27784
- this.runtimeConfigs.set(agentId, launch.runtimeConfig);
28702
+ const runtimeConfigAcceptance = launch?.runtimeConfig ? this.acceptRuntimeConfig(agentId, launch.runtimeConfig) : undefined;
27785
28703
  if (launch?.sessionId)
27786
28704
  this.resumeSessions.set(agentId, launch.sessionId);
27787
28705
  if (launch?.launchId)
27788
28706
  this.launchIds.set(agentId, launch.launchId);
27789
28707
  this.dispatch({ type: "register", agentId });
28708
+ const registered = this.state.agents[agentId];
28709
+ if (launch?.runtimeConfig && launch.applyRuntimeConfig !== false && (runtimeConfigAcceptance === "accepted" || this.pendingRuntimeConfigUpdates.has(agentId)) && this.sessions.has(agentId) && registered && !isActivelyWorking(registered)) {
28710
+ this.convergeRuntimeConfig(agentId);
28711
+ }
28712
+ }
28713
+ async updateRuntimeConfig(agentId, config2) {
28714
+ const accepted = this.acceptRuntimeConfig(agentId, config2);
28715
+ if (accepted === "stale" || accepted === "idempotent")
28716
+ return accepted;
28717
+ const session2 = this.sessions.get(agentId);
28718
+ if (!session2) {
28719
+ this.pendingRuntimeConfigUpdates.delete(agentId);
28720
+ return "saved_for_start";
28721
+ }
28722
+ const agent2 = this.state.agents[agentId];
28723
+ if (agent2 && (agent2.turnActive || isActivelyWorking(agent2)))
28724
+ return "deferred";
28725
+ return this.convergeRuntimeConfig(agentId);
28726
+ }
28727
+ acceptRuntimeConfig(agentId, config2) {
28728
+ const desired = this.runtimeConfigs.get(agentId);
28729
+ const revision = config2.runtimeConfigRevision ?? 0;
28730
+ const desiredRevision = desired?.runtimeConfigRevision ?? 0;
28731
+ if (desired && revision < desiredRevision)
28732
+ return "stale";
28733
+ if (desired && revision === desiredRevision) {
28734
+ if (this.runtimeConfigTuple(desired) !== this.runtimeConfigTuple(config2)) {
28735
+ throw new Error(`Conflicting runtime config for ${agentId} at revision ${revision}`);
28736
+ }
28737
+ this.runtimeConfigs.set(agentId, config2);
28738
+ return "idempotent";
28739
+ }
28740
+ this.runtimeConfigs.set(agentId, config2);
28741
+ this.pendingRuntimeConfigUpdates.set(agentId, config2);
28742
+ return "accepted";
28743
+ }
28744
+ runtimeConfigTuple(config2) {
28745
+ return JSON.stringify({
28746
+ version: config2.version,
28747
+ runtime: config2.runtime,
28748
+ model: config2.model,
28749
+ mode: config2.mode,
28750
+ reasoningEffort: config2.reasoningEffort ?? null,
28751
+ provider: config2.provider ?? null,
28752
+ command: config2.command ?? null,
28753
+ disallowedTools: config2.disallowedTools ?? null,
28754
+ envVars: config2.envVars ?? null
28755
+ });
28756
+ }
28757
+ runtimeLaunchTuple(config2) {
28758
+ return JSON.stringify({
28759
+ version: config2.version,
28760
+ runtime: config2.runtime,
28761
+ model: config2.model,
28762
+ mode: config2.mode,
28763
+ provider: config2.provider ?? null,
28764
+ command: config2.command ?? null,
28765
+ disallowedTools: config2.disallowedTools ?? null,
28766
+ envVars: config2.envVars ?? null
28767
+ });
28768
+ }
28769
+ async convergeRuntimeConfig(agentId, restartOnFailure = true) {
28770
+ if (this.runtimeConfigApplyRunning.has(agentId))
28771
+ return "deferred";
28772
+ const session2 = this.sessions.get(agentId);
28773
+ if (!session2)
28774
+ return "saved_for_start";
28775
+ this.runtimeConfigApplyRunning.add(agentId);
28776
+ try {
28777
+ while (this.sessions.get(agentId) === session2) {
28778
+ const desired = this.pendingRuntimeConfigUpdates.get(agentId) ?? this.runtimeConfigs.get(agentId);
28779
+ if (!desired)
28780
+ return "idempotent";
28781
+ const desiredRevision = desired.runtimeConfigRevision ?? 0;
28782
+ const applied = this.appliedRuntimeConfigs.get(agentId);
28783
+ const appliedRevision = applied?.runtimeConfigRevision ?? -1;
28784
+ if (applied && desiredRevision <= appliedRevision) {
28785
+ this.pendingRuntimeConfigUpdates.delete(agentId);
28786
+ return desiredRevision === appliedRevision ? "idempotent" : "stale";
28787
+ }
28788
+ const canApplyNatively = applied && this.runtimeLaunchTuple(applied) === this.runtimeLaunchTuple(desired) && typeof session2.updateSettings === "function";
28789
+ let result = { status: "unsupported" };
28790
+ if (canApplyNatively) {
28791
+ try {
28792
+ result = await session2.updateSettings({
28793
+ reasoningEffort: desired.reasoningEffort ?? null
28794
+ });
28795
+ } catch (error51) {
28796
+ this.log.warn("runtime config live apply threw; restarting at safe boundary", {
28797
+ agentId,
28798
+ revision: desiredRevision,
28799
+ error: String(error51)
28800
+ });
28801
+ if (restartOnFailure)
28802
+ await this.restartForRuntimeConfig(agentId, session2);
28803
+ return "saved_for_start";
28804
+ }
28805
+ }
28806
+ if (result.status !== "applied") {
28807
+ this.log.warn("runtime config live apply unavailable; restarting at safe boundary", {
28808
+ agentId,
28809
+ revision: desiredRevision,
28810
+ status: result.status,
28811
+ code: result.error?.code
28812
+ });
28813
+ if (restartOnFailure)
28814
+ await this.restartForRuntimeConfig(agentId, session2);
28815
+ return "saved_for_start";
28816
+ }
28817
+ this.appliedRuntimeConfigs.set(agentId, desired);
28818
+ if ((this.pendingRuntimeConfigUpdates.get(agentId)?.runtimeConfigRevision ?? -1) === desiredRevision) {
28819
+ this.pendingRuntimeConfigUpdates.delete(agentId);
28820
+ }
28821
+ const latestRevision = this.runtimeConfigs.get(agentId)?.runtimeConfigRevision ?? 0;
28822
+ if (latestRevision <= desiredRevision) {
28823
+ this.dispatch({ type: "runtime_config_applied", agentId });
28824
+ return "applied";
28825
+ }
28826
+ }
28827
+ return "saved_for_start";
28828
+ } finally {
28829
+ this.runtimeConfigApplyRunning.delete(agentId);
28830
+ }
28831
+ }
28832
+ async restartForRuntimeConfig(agentId, session2) {
28833
+ if (this.sessions.get(agentId) !== session2)
28834
+ return;
28835
+ this.opts.timeline?.fenceSession(agentId);
28836
+ this.markResetting(agentId);
28837
+ await this.stop(agentId);
27790
28838
  }
27791
28839
  deliver(agentId, message2) {
27792
28840
  const normalized = message2.id ? message2 : {
27793
28841
  ...message2,
27794
28842
  id: message2.seq !== undefined ? `${agentId}:source:${message2.seq}` : `${agentId}:synthetic:${this.nextDeliveryOrdinal++}`
27795
28843
  };
28844
+ if (this.sessions.has(agentId) && this.pendingRuntimeConfigUpdates.has(agentId)) {
28845
+ this.dispatch({
28846
+ type: "runtime_config_queued",
28847
+ agentId,
28848
+ message: normalized
28849
+ });
28850
+ return this.state.agents[agentId] !== undefined;
28851
+ }
27796
28852
  const effects = this.dispatch({ type: "wake", agentId, message: normalized, nowMs: this.now() });
27797
28853
  return effects.length > 0;
27798
28854
  }
@@ -27836,7 +28892,11 @@ class AgentProcessManager {
27836
28892
  this.emitErrorAudit(agentId, "reset", "resume_control_update_failed", "Reset aborted because resume control could not be persisted");
27837
28893
  throw new Error("Reset aborted because resume control could not be persisted");
27838
28894
  }
27839
- this.register(agentId, { runtimeConfig: opts.runtimeConfig, launchId: opts.launchId });
28895
+ this.register(agentId, {
28896
+ runtimeConfig: opts.runtimeConfig,
28897
+ launchId: opts.launchId,
28898
+ applyRuntimeConfig: false
28899
+ });
27840
28900
  if (!opts.forgetSession)
27841
28901
  this.opts.timeline?.fenceSession(agentId);
27842
28902
  this.abortCurrentTurn(agentId, opts.abortCause);
@@ -27937,6 +28997,9 @@ class AgentProcessManager {
27937
28997
  const agent2 = this.state.agents[agentId];
27938
28998
  return agent2 ? this.deriveActivity(agent2) : null;
27939
28999
  }
29000
+ agentBackendId(agentId) {
29001
+ return this.liveBackendIds.get(agentId) ?? null;
29002
+ }
27940
29003
  statusProjection(nowMs) {
27941
29004
  return Object.values(this.state.agents).map((a) => ({
27942
29005
  agentId: a.agentId,
@@ -28462,6 +29525,7 @@ ${this.opts.wakePromptFooter}` : text2;
28462
29525
  throw new Error(`AgentProcessManager: spawn for ${agentId} has no command`);
28463
29526
  const prompt = this.withFooter(first.text);
28464
29527
  const driver = this.opts.driverFor(agentId, this.runtimeConfigs.get(agentId));
29528
+ this.liveBackendIds.set(agentId, driver.id);
28465
29529
  const base = this.opts.baseContextFor(agentId);
28466
29530
  const configuredRuntime = this.runtimeConfigs.get(agentId) ?? base.config?.runtimeConfig;
28467
29531
  this.log.info("spawning agent", {
@@ -28582,7 +29646,10 @@ ${this.opts.wakePromptFooter}` : text2;
28582
29646
  if (state.session && this.sessions.get(agentId) === state.session)
28583
29647
  this.sessions.delete(agentId);
28584
29648
  this.liveSessions.delete(agentId);
29649
+ if (this.activeSpawnState.get(agentId) === state)
29650
+ this.liveBackendIds.delete(agentId);
28585
29651
  if (this.activeSpawnState.get(agentId) === state) {
29652
+ this.appliedRuntimeConfigs.delete(agentId);
28586
29653
  this.activeSpawnState.delete(agentId);
28587
29654
  this.nonCleanEndMarker.delete(agentId);
28588
29655
  }
@@ -28630,6 +29697,10 @@ ${this.opts.wakePromptFooter}` : text2;
28630
29697
  state.session = session2;
28631
29698
  state.sessionInstanceId = session2.sessionInstanceId;
28632
29699
  this.sessions.set(agentId, session2);
29700
+ this.appliedRuntimeConfigs.set(agentId, runtimeConfig);
29701
+ if ((this.pendingRuntimeConfigUpdates.get(agentId)?.runtimeConfigRevision ?? -1) <= (runtimeConfig.runtimeConfigRevision ?? 0)) {
29702
+ this.pendingRuntimeConfigUpdates.delete(agentId);
29703
+ }
28633
29704
  this.dispatch({
28634
29705
  type: "attach_session",
28635
29706
  agentId,
@@ -28863,6 +29934,12 @@ ${this.opts.wakePromptFooter}` : text2;
28863
29934
  runtime: runtimeId
28864
29935
  });
28865
29936
  }
29937
+ if (event.type === "token_usage") {
29938
+ this.opts.onTokenUsage?.({ agentId, backendId: runtimeId, usage: event.usage });
29939
+ }
29940
+ if (event.type === "rate_limits") {
29941
+ this.opts.onProviderQuota?.({ agentId, backendId: runtimeId, quota: event.quota });
29942
+ }
28866
29943
  if (event.type === "turn_started") {
28867
29944
  const timelineTurnOwner = {
28868
29945
  sessionInstanceId: event.sessionInstanceId,
@@ -28977,7 +30054,7 @@ ${this.opts.wakePromptFooter}` : text2;
28977
30054
  this.logSessionEnded(agentId, "turn_end");
28978
30055
  const marker = this.nonCleanEndMarker.get(agentId);
28979
30056
  this.nonCleanEndMarker.delete(agentId);
28980
- this.dispatch(marker !== undefined ? {
30057
+ const completionEvent = marker !== undefined ? {
28981
30058
  type: "turn_completed",
28982
30059
  agentId,
28983
30060
  sessionInstanceId: event.sessionInstanceId,
@@ -28992,7 +30069,26 @@ ${this.opts.wakePromptFooter}` : text2;
28992
30069
  sessionInstanceId: event.sessionInstanceId,
28993
30070
  nowMs: this.now(),
28994
30071
  turnId: event.turnId
28995
- }, owner);
30072
+ };
30073
+ if (this.pendingRuntimeConfigUpdates.has(agentId) && this.sessions.get(agentId) === owner.session) {
30074
+ this.convergeRuntimeConfig(agentId, false).then((result) => {
30075
+ if (result === "saved_for_start" && owner.session)
30076
+ this.markResetting(agentId);
30077
+ this.dispatch(completionEvent, owner);
30078
+ if (result === "saved_for_start" && owner.session) {
30079
+ this.restartForRuntimeConfig(agentId, owner.session);
30080
+ }
30081
+ }).catch((error51) => {
30082
+ this.log.error("runtime config convergence failed", { agentId, error: String(error51) });
30083
+ if (owner.session)
30084
+ this.markResetting(agentId);
30085
+ this.dispatch(completionEvent, owner);
30086
+ if (owner.session)
30087
+ this.restartForRuntimeConfig(agentId, owner.session);
30088
+ });
30089
+ return;
30090
+ }
30091
+ this.dispatch(completionEvent, owner);
28996
30092
  }
28997
30093
  }
28998
30094
  }
@@ -29067,7 +30163,8 @@ class AgentRouter {
29067
30163
  version: r.version,
29068
30164
  status: r.status ?? "healthy",
29069
30165
  lastError: r.lastError,
29070
- lastErrorAt: r.lastErrorAt
30166
+ lastErrorAt: r.lastErrorAt,
30167
+ reasoning: r.reasoning
29071
30168
  });
29072
30169
  }
29073
30170
  }
@@ -29076,7 +30173,7 @@ class AgentRouter {
29076
30173
  this.opts.channel.onResync?.(() => ({
29077
30174
  ready: this.buildReady(),
29078
30175
  sessions: this.opts.manager.liveSessionReports(),
29079
- activities: this.opts.manager.liveAgentActivities()
30176
+ activities: this.opts.resyncActivities ? this.opts.resyncActivities() : this.opts.manager.liveAgentActivities()
29080
30177
  }));
29081
30178
  await this.opts.channel.reportReady(this.buildReady());
29082
30179
  }
@@ -29089,7 +30186,8 @@ class AgentRouter {
29089
30186
  platform: this.opts.platform,
29090
30187
  arch: this.opts.arch,
29091
30188
  osRelease: this.opts.osRelease,
29092
- daemonVersion: this.opts.daemonVersion
30189
+ daemonVersion: this.opts.daemonVersion,
30190
+ ...this.opts.providerQuotas ? { providerQuotas: this.opts.providerQuotas() } : {}
29093
30191
  };
29094
30192
  }
29095
30193
  healthyRuntimeIds() {
@@ -29311,6 +30409,27 @@ class AgentRouter {
29311
30409
  rewakePrompt: MODEL_SWITCH_REWAKE_PROMPT
29312
30410
  }));
29313
30411
  break;
30412
+ case "agent:runtime_config_update": {
30413
+ this.log.info("agent:runtime_config_update received", {
30414
+ agentId: cmd.agentId,
30415
+ revision: cmd.config.runtimeConfigRevision ?? 0
30416
+ });
30417
+ try {
30418
+ const result = await this.opts.manager.updateRuntimeConfig(cmd.agentId, cmd.config);
30419
+ this.log.info("agent:runtime_config_update accepted", {
30420
+ agentId: cmd.agentId,
30421
+ revision: cmd.config.runtimeConfigRevision ?? 0,
30422
+ result
30423
+ });
30424
+ } catch (err) {
30425
+ this.log.warn("agent:runtime_config_update rejected", {
30426
+ agentId: cmd.agentId,
30427
+ revision: cmd.config.runtimeConfigRevision ?? 0,
30428
+ error: err instanceof Error ? err.message : String(err)
30429
+ });
30430
+ }
30431
+ break;
30432
+ }
29314
30433
  case "agent:stop":
29315
30434
  this.log.info("agent:stop received", { agentId: cmd.agentId });
29316
30435
  try {
@@ -29368,8 +30487,8 @@ function createTypingScopeTracker() {
29368
30487
  }
29369
30488
  // src/timeline/timeline.ts
29370
30489
  import * as fs9 from "node:fs";
29371
- import { createHash as createHash2, randomBytes as randomBytes4 } from "node:crypto";
29372
- import { basename as basename3, dirname as dirname5, join as join11 } from "node:path";
30490
+ import { createHash as createHash2, randomBytes as randomBytes6 } from "node:crypto";
30491
+ import { basename as basename3, dirname as dirname5, join as join12 } from "node:path";
29373
30492
 
29374
30493
  // src/timeline/filelock.ts
29375
30494
  import * as fs8 from "fs";
@@ -29712,7 +30831,7 @@ function scanTimelineFile(filePath) {
29712
30831
  }
29713
30832
  }
29714
30833
  function atomicReplaceTimeline(filePath, lines) {
29715
- const tempPath = join11(dirname5(filePath), `.${basename3(filePath)}.${process.pid}.${randomBytes4(12).toString("hex")}.tmp`);
30834
+ const tempPath = join12(dirname5(filePath), `.${basename3(filePath)}.${process.pid}.${randomBytes6(12).toString("hex")}.tmp`);
29716
30835
  let fd = null;
29717
30836
  try {
29718
30837
  fd = fs9.openSync(tempPath, "wx", 384);
@@ -29796,14 +30915,14 @@ function readRecentEntries(timelineDir, opts = {}) {
29796
30915
  const filenames = recentFilenames(maxDays, now).reverse();
29797
30916
  const entries = [];
29798
30917
  for (const filename of filenames) {
29799
- entries.push(...readJsonl(join11(timelineDir, filename)));
30918
+ entries.push(...readJsonl(join12(timelineDir, filename)));
29800
30919
  }
29801
30920
  return entries;
29802
30921
  }
29803
30922
  function readResumeControlState(timelineDir) {
29804
30923
  if (timelineDirectoryState(timelineDir) !== "safe")
29805
30924
  return { kind: "missing" };
29806
- const filePath = join11(timelineDir, RESUME_CONTROL_FILENAME);
30925
+ const filePath = join12(timelineDir, RESUME_CONTROL_FILENAME);
29807
30926
  let source;
29808
30927
  try {
29809
30928
  source = fs9.lstatSync(filePath);
@@ -29879,8 +30998,8 @@ function updateResumeControlState(timelineDir, update) {
29879
30998
  `;
29880
30999
  if (Buffer.byteLength(body, "utf8") > RESUME_CONTROL_MAX_BYTES)
29881
31000
  return false;
29882
- const filePath = join11(timelineDir, RESUME_CONTROL_FILENAME);
29883
- const tempPath = join11(timelineDir, `.${RESUME_CONTROL_FILENAME}.${process.pid}.${randomBytes4(12).toString("hex")}.tmp`);
31001
+ const filePath = join12(timelineDir, RESUME_CONTROL_FILENAME);
31002
+ const tempPath = join12(timelineDir, `.${RESUME_CONTROL_FILENAME}.${process.pid}.${randomBytes6(12).toString("hex")}.tmp`);
29884
31003
  let fd = null;
29885
31004
  try {
29886
31005
  fd = fs9.openSync(tempPath, "wx", 384);
@@ -29910,7 +31029,7 @@ function appendTrackedEntry(timelineDir, entry, now = new Date) {
29910
31029
  if (timelineDirectoryState(timelineDir) !== "safe")
29911
31030
  return { status: "rejected", reason: "unsafe" };
29912
31031
  const filename = filenameForDate(now);
29913
- const filePath = join11(timelineDir, filename);
31032
+ const filePath = join12(timelineDir, filename);
29914
31033
  const lockPath = lockPathFor(timelineDir, filename);
29915
31034
  try {
29916
31035
  if (!acquireLock(lockPath))
@@ -29938,7 +31057,7 @@ function updateTrackedEntry(timelineDir, handle, update) {
29938
31057
  if (!DATE_FILENAME_PATTERN.test(handle.filename) || basename3(handle.filename) !== handle.filename) {
29939
31058
  return { status: "rejected", reason: "unsafe" };
29940
31059
  }
29941
- const filePath = join11(timelineDir, handle.filename);
31060
+ const filePath = join12(timelineDir, handle.filename);
29942
31061
  const lockPath = lockPathFor(timelineDir, handle.filename);
29943
31062
  try {
29944
31063
  if (!acquireLock(lockPath))
@@ -29997,10 +31116,10 @@ async function sweepTimelineHistory(workingDirectoryBase, opts = {}) {
29997
31116
  return;
29998
31117
  }
29999
31118
  for (const agentName of agentNames) {
30000
- const agentDir = join11(workingDirectoryBase, agentName);
31119
+ const agentDir = join12(workingDirectoryBase, agentName);
30001
31120
  if (!isRealDirectory(agentDir))
30002
31121
  continue;
30003
- const timelineDir = join11(agentDir, ".context_timeline");
31122
+ const timelineDir = join12(agentDir, ".context_timeline");
30004
31123
  if (!isRealDirectory(timelineDir))
30005
31124
  continue;
30006
31125
  let filenames;
@@ -30010,7 +31129,7 @@ async function sweepTimelineHistory(workingDirectoryBase, opts = {}) {
30010
31129
  continue;
30011
31130
  }
30012
31131
  for (const filename of filenames) {
30013
- const filePath = join11(timelineDir, filename);
31132
+ const filePath = join12(timelineDir, filename);
30014
31133
  let source;
30015
31134
  try {
30016
31135
  source = fs9.lstatSync(filePath);
@@ -30754,8 +31873,8 @@ class MessageReminderScheduler {
30754
31873
 
30755
31874
  // src/manager/agentDriverHost.ts
30756
31875
  import { randomUUID as randomUUID6 } from "node:crypto";
30757
- import { homedir as homedir3 } from "node:os";
30758
- import { join as join12 } from "node:path";
31876
+ import { homedir as homedir4 } from "node:os";
31877
+ import { join as join13 } from "node:path";
30759
31878
 
30760
31879
  // src/drivers/gitIdentityEnv.ts
30761
31880
  import { execFileSync as execFileSync3 } from "child_process";
@@ -30880,7 +31999,7 @@ function createDaemonAgentDriverHost(ctx, onRawLine) {
30880
31999
  hostUser: readHostGitIdentity() ?? undefined
30881
32000
  }),
30882
32001
  platformProtected: {
30883
- ALOOK_HOME: process.env.ALOOK_HOME ?? join12(homedir3(), ".alook"),
32002
+ ALOOK_HOME: process.env.ALOOK_HOME ?? join13(homedir4(), ".alook"),
30884
32003
  ALOOK_ID: ctx.agentId,
30885
32004
  ALOOK_CLI: ctx.agentCliPath,
30886
32005
  ALOOK_SERVER_URL: ctx.config.serverUrl,
@@ -30985,6 +32104,182 @@ class DaemonSelfSleepScheduler {
30985
32104
  }
30986
32105
  }
30987
32106
 
32107
+ // src/telemetry/dailyTokenUsage.ts
32108
+ import { chmod, mkdir, open, readFile as readFile2, rename, rm } from "node:fs/promises";
32109
+ import { dirname as dirname6, join as join14 } from "node:path";
32110
+ import { randomUUID as randomUUID7 } from "node:crypto";
32111
+ function dayKey(at) {
32112
+ return at.toISOString().slice(0, 10);
32113
+ }
32114
+ function retainedDays(at) {
32115
+ const days = new Set;
32116
+ for (let offset = 0;offset < 7; offset += 1) {
32117
+ days.add(dayKey(new Date(at.getTime() - offset * 86400000)));
32118
+ }
32119
+ return days;
32120
+ }
32121
+ function isMetric(value) {
32122
+ return value === null || typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
32123
+ }
32124
+ function isSnapshot(value) {
32125
+ if (!value || typeof value !== "object")
32126
+ return false;
32127
+ const snapshot = value;
32128
+ const metrics = snapshot.metrics;
32129
+ return typeof snapshot.botId === "string" && snapshot.botId.length > 0 && typeof snapshot.day === "string" && /^\d{4}-\d{2}-\d{2}$/.test(snapshot.day) && !!metrics && isMetric(metrics.input) && isMetric(metrics.output) && isMetric(metrics.cache);
32130
+ }
32131
+ function mergeMetric(existing, delta, hasExistingSnapshot) {
32132
+ if (delta === null)
32133
+ return null;
32134
+ if (!Number.isSafeInteger(delta) || delta < 0) {
32135
+ throw new RangeError("token usage delta must be a non-negative safe integer");
32136
+ }
32137
+ if (!hasExistingSnapshot)
32138
+ return delta;
32139
+ if (existing === null)
32140
+ return null;
32141
+ const sum = existing + delta;
32142
+ if (!Number.isSafeInteger(sum))
32143
+ throw new RangeError("daily token usage exceeds safe integer range");
32144
+ return sum;
32145
+ }
32146
+ function emptySnapshot(botId, day) {
32147
+ return {
32148
+ botId,
32149
+ day,
32150
+ metrics: {
32151
+ input: null,
32152
+ output: null,
32153
+ cache: null
32154
+ }
32155
+ };
32156
+ }
32157
+
32158
+ class DailyTokenUsageStore {
32159
+ now;
32160
+ tail = Promise.resolve();
32161
+ loaded = false;
32162
+ data = { version: 1, bots: {} };
32163
+ filePath;
32164
+ constructor(workingDirectoryBase, now = () => new Date) {
32165
+ this.now = now;
32166
+ this.filePath = join14(workingDirectoryBase, ".telemetry", "daily-token-usage.json");
32167
+ }
32168
+ record(botId, delta) {
32169
+ return this.enqueue(async () => {
32170
+ await this.load();
32171
+ const at = this.now();
32172
+ this.prune(at);
32173
+ const day = dayKey(at);
32174
+ const snapshots = this.data.bots[botId] ?? [];
32175
+ const existing = snapshots.find((snapshot) => snapshot.day === day);
32176
+ const next = existing ?? emptySnapshot(botId, day);
32177
+ next.metrics = {
32178
+ input: mergeMetric(next.metrics.input, delta.input, existing !== undefined),
32179
+ output: mergeMetric(next.metrics.output, delta.output, existing !== undefined),
32180
+ cache: mergeMetric(next.metrics.cache, delta.cache, existing !== undefined)
32181
+ };
32182
+ if (!existing)
32183
+ snapshots.push(next);
32184
+ snapshots.sort((a, b) => a.day.localeCompare(b.day));
32185
+ this.data.bots[botId] = snapshots;
32186
+ await this.persist();
32187
+ });
32188
+ }
32189
+ snapshots(botId) {
32190
+ let result = [];
32191
+ return this.enqueue(async () => {
32192
+ await this.load();
32193
+ if (this.prune(this.now()))
32194
+ await this.persist();
32195
+ result = (this.data.bots[botId] ?? []).map((snapshot) => structuredClone(snapshot));
32196
+ }).then(() => result);
32197
+ }
32198
+ enqueue(operation) {
32199
+ const result = this.tail.then(operation, operation);
32200
+ this.tail = result.then(() => {
32201
+ return;
32202
+ }, () => {
32203
+ return;
32204
+ });
32205
+ return result;
32206
+ }
32207
+ async load() {
32208
+ if (this.loaded)
32209
+ return;
32210
+ let source;
32211
+ try {
32212
+ source = await readFile2(this.filePath, "utf8");
32213
+ } catch (error51) {
32214
+ if (!error51 || typeof error51 !== "object" || !("code" in error51) || error51.code !== "ENOENT") {
32215
+ throw error51;
32216
+ }
32217
+ this.data = { version: 1, bots: {} };
32218
+ this.loaded = true;
32219
+ return;
32220
+ }
32221
+ const parsed = JSON.parse(source);
32222
+ if (!parsed || typeof parsed !== "object" || parsed.version !== 1) {
32223
+ throw new Error("invalid daily token usage file version");
32224
+ }
32225
+ const bots = parsed.bots;
32226
+ if (!bots || typeof bots !== "object" || Array.isArray(bots)) {
32227
+ throw new Error("invalid daily token usage bots map");
32228
+ }
32229
+ const valid = {};
32230
+ for (const [botId, value] of Object.entries(bots)) {
32231
+ if (!Array.isArray(value) || !value.every(isSnapshot) || value.some((snapshot) => snapshot.botId !== botId)) {
32232
+ throw new Error(`invalid daily token usage snapshots for bot ${botId}`);
32233
+ }
32234
+ if (value.length > 0) {
32235
+ valid[botId] = value;
32236
+ }
32237
+ }
32238
+ this.data = { version: 1, bots: valid };
32239
+ this.loaded = true;
32240
+ }
32241
+ prune(at) {
32242
+ const keep = retainedDays(at);
32243
+ let changed = false;
32244
+ for (const [botId, snapshots] of Object.entries(this.data.bots)) {
32245
+ const retained = snapshots.filter((snapshot) => keep.has(snapshot.day)).sort((a, b) => a.day.localeCompare(b.day)).slice(-7);
32246
+ if (retained.length !== snapshots.length || retained.some((snapshot, index2) => snapshot !== snapshots[index2]))
32247
+ changed = true;
32248
+ if (retained.length === 0)
32249
+ delete this.data.bots[botId];
32250
+ else
32251
+ this.data.bots[botId] = retained;
32252
+ }
32253
+ return changed;
32254
+ }
32255
+ async persist() {
32256
+ const directory = dirname6(this.filePath);
32257
+ await mkdir(directory, { recursive: true, mode: 448 });
32258
+ const temporary = `${this.filePath}.${randomUUID7()}.tmp`;
32259
+ try {
32260
+ const file2 = await open(temporary, "wx", 384);
32261
+ try {
32262
+ await file2.writeFile(JSON.stringify(this.data), { encoding: "utf8" });
32263
+ await file2.sync();
32264
+ } finally {
32265
+ await file2.close();
32266
+ }
32267
+ await rename(temporary, this.filePath);
32268
+ await chmod(this.filePath, 384);
32269
+ try {
32270
+ const directoryHandle = await open(directory, "r");
32271
+ try {
32272
+ await directoryHandle.sync();
32273
+ } finally {
32274
+ await directoryHandle.close();
32275
+ }
32276
+ } catch {}
32277
+ } catch (error51) {
32278
+ await rm(temporary, { force: true }).catch(() => {});
32279
+ throw error51;
32280
+ }
32281
+ }
32282
+ }
30988
32283
  // src/daemon/createDaemon.ts
30989
32284
  var WARMUP_BACKOFF_MS = [250, 500, 1000, 2000, 4000];
30990
32285
  var WARMUP_CEILING_MS = 30000;
@@ -31122,9 +32417,25 @@ function createBuiltinDaemonSessionFactory(onRuntimeRawLine) {
31122
32417
  }
31123
32418
  async function createDaemon(opts) {
31124
32419
  const log2 = opts.logger ?? createLogger2({ header: "@alook/daemon" });
31125
- const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${homedir4()}/.alook`) + "/daemon";
32420
+ const fallbackBase = (process.env.ALOOK_PROJECT_ROOT || `${homedir5()}/.alook`) + "/daemon";
31126
32421
  const workingDirectoryBase = opts.workingDirectoryBase ?? fallbackBase;
31127
32422
  const workdirFor = (agentId) => `${workingDirectoryBase}/${agentId}`;
32423
+ const dailyTokenUsage2 = new DailyTokenUsageStore(workingDirectoryBase);
32424
+ const providerQuotaReader = opts.providerQuotaReader ?? (opts.sessionFactory ? async () => null : readBuiltinProviderQuota);
32425
+ const providerQuotaByBackend = new Map;
32426
+ let requestReadyQuotaResend = () => {};
32427
+ const recordProviderQuota = (backendId, quota) => {
32428
+ const previous = providerQuotaByBackend.get(backendId);
32429
+ if (previous?.observation.status === "available" && quota.status === "error" && previous.observation.sourceEpoch === quota.sourceEpoch)
32430
+ return;
32431
+ providerQuotaByBackend.set(backendId, {
32432
+ agentBackendId: backendId,
32433
+ observation: structuredClone(quota)
32434
+ });
32435
+ if (previous && previous.observation.sourceEpoch !== quota.sourceEpoch) {
32436
+ requestReadyQuotaResend();
32437
+ }
32438
+ };
31128
32439
  sweepTimelineHistory(workingDirectoryBase).catch(() => {
31129
32440
  log2.warn("timeline startup sweep failed");
31130
32441
  });
@@ -31140,6 +32451,27 @@ async function createDaemon(opts) {
31140
32451
  });
31141
32452
  let channelRef = null;
31142
32453
  let managerRef = null;
32454
+ const providerQuotaSnapshots = () => [...providerQuotaByBackend.values()].map((snapshot) => structuredClone(snapshot));
32455
+ const activityPayload = async (info) => {
32456
+ if (info.state !== "idle")
32457
+ return info;
32458
+ const backendId = managerRef?.agentBackendId(info.agentId);
32459
+ if (backendId === "claude") {
32460
+ const observed = await providerQuotaReader("claude");
32461
+ if (observed)
32462
+ recordProviderQuota("claude", observed);
32463
+ }
32464
+ const quota = backendId === "claude" || backendId === "codex" ? providerQuotaByBackend.get(backendId) : undefined;
32465
+ const dailyUsage = await dailyTokenUsage2.snapshots(info.agentId);
32466
+ return {
32467
+ ...info,
32468
+ ...dailyUsage.length > 0 ? { dailyUsage } : {},
32469
+ ...quota ? { quota: structuredClone(quota) } : {}
32470
+ };
32471
+ };
32472
+ let reportAgentActivity = (info) => {
32473
+ channelRef?.reportAgentActivity?.(info);
32474
+ };
31143
32475
  let reminderSchedulerRef = null;
31144
32476
  const selfSleepScheduler = opts.onSelfSleep ? new DaemonSelfSleepScheduler({
31145
32477
  onSleep: opts.onSelfSleep,
@@ -31204,7 +32536,7 @@ async function createDaemon(opts) {
31204
32536
  function reassertAgentActivity(agentId) {
31205
32537
  const state = managerRef?.agentActivity(agentId);
31206
32538
  if (state)
31207
- channel2.reportAgentActivity?.({ agentId, state });
32539
+ reportAgentActivity({ agentId, state });
31208
32540
  }
31209
32541
  function startTypingHeartbeat(agentId) {
31210
32542
  stopTypingHeartbeat(agentId);
@@ -31348,6 +32680,20 @@ async function createDaemon(opts) {
31348
32680
  logger: log2.child("ws")
31349
32681
  });
31350
32682
  channelRef = channel2;
32683
+ const activityReportTails = new Map;
32684
+ reportAgentActivity = (info) => {
32685
+ const prior = activityReportTails.get(info.agentId) ?? Promise.resolve();
32686
+ const next = prior.then(async () => {
32687
+ await channel2.reportAgentActivity(await activityPayload(info));
32688
+ }).catch(() => {
32689
+ log2.warn("agent activity telemetry report failed", { agentId: info.agentId, state: info.state });
32690
+ });
32691
+ activityReportTails.set(info.agentId, next);
32692
+ next.finally(() => {
32693
+ if (activityReportTails.get(info.agentId) === next)
32694
+ activityReportTails.delete(info.agentId);
32695
+ });
32696
+ };
31351
32697
  function restorePendingIdleResetEvents(agentId) {
31352
32698
  for (const pending of timeline2.pendingIdleResetEvents(agentId)) {
31353
32699
  channel2.restorePendingBotAuditEvent({
@@ -31466,7 +32812,7 @@ async function createDaemon(opts) {
31466
32812
  onAgentSession: (info) => void channel2.reportAgentSession(info),
31467
32813
  onAgentActivity: (info) => {
31468
32814
  selfSleepScheduler?.observeAgentActivity(info.agentId, info.state === "running");
31469
- channel2.reportAgentActivity?.(info);
32815
+ reportAgentActivity(info);
31470
32816
  if (info.state === "starting" || info.state === "running") {
31471
32817
  if (!typingHeartbeats.has(info.agentId)) {
31472
32818
  startTypingHeartbeat(info.agentId);
@@ -31475,6 +32821,16 @@ async function createDaemon(opts) {
31475
32821
  emitTypingStopsAndClear(info.agentId);
31476
32822
  }
31477
32823
  },
32824
+ onTokenUsage: ({ agentId, usage }) => {
32825
+ dailyTokenUsage2.record(agentId, usage).catch(() => {
32826
+ log2.warn("daily token usage persistence failed", { agentId });
32827
+ });
32828
+ },
32829
+ onProviderQuota: ({ backendId, quota }) => {
32830
+ if (backendId !== "claude" && backendId !== "codex")
32831
+ return;
32832
+ recordProviderQuota(backendId, quota);
32833
+ },
31478
32834
  onBotAuditEvent: (agentId, event, context) => emitBotAuditEvent(agentId, event, context),
31479
32835
  onAgentLocallyStopped: (info) => router?.markLocallyStopped(info.agentId),
31480
32836
  onRuntimeRawLine,
@@ -31521,6 +32877,11 @@ async function createDaemon(opts) {
31521
32877
  arch: opts.arch,
31522
32878
  osRelease: opts.osRelease,
31523
32879
  daemonVersion: opts.daemonVersion,
32880
+ providerQuotas: providerQuotaSnapshots,
32881
+ resyncActivities: async () => {
32882
+ const activities = await Promise.all(manager.liveAgentActivities().map((info) => activityPayload(info)));
32883
+ return activities.filter((activity) => manager.agentActivity(activity.agentId) === activity.state);
32884
+ },
31524
32885
  typingTracker,
31525
32886
  logger: log2.child("router"),
31526
32887
  onBeforeAgent: async (agentId) => {
@@ -31536,6 +32897,10 @@ async function createDaemon(opts) {
31536
32897
  await enrollAgent(agentId);
31537
32898
  }
31538
32899
  });
32900
+ requestReadyQuotaResend = () => {
32901
+ if (router)
32902
+ channel2.sendReady?.(router.buildReady());
32903
+ };
31539
32904
  channel2.onCommand(createSelfUpdateCommandListener(opts.handleSelfUpdate));
31540
32905
  channel2.onCommand(createDiagnosticsCommandListener({
31541
32906
  handleDiagnosticCommand: opts.handleDiagnosticCommand,
@@ -31565,6 +32930,11 @@ async function createDaemon(opts) {
31565
32930
  resyncPendingWakes();
31566
32931
  resyncPendingDiagnostics();
31567
32932
  });
32933
+ if (opts.runtimeReport.some((runtime) => runtime.id === "claude")) {
32934
+ const observed = await providerQuotaReader("claude");
32935
+ if (observed)
32936
+ recordProviderQuota("claude", observed);
32937
+ }
31568
32938
  channel2.connect();
31569
32939
  await router.start();
31570
32940
  selfSleepScheduler?.start();
@@ -32375,7 +33745,7 @@ async function buildDiagnosticBundle(args) {
32375
33745
  };
32376
33746
  }
32377
33747
  // src/diagnostics/coordinator.ts
32378
- import { createHash as createHash4, randomBytes as randomBytes5 } from "node:crypto";
33748
+ import { createHash as createHash4, randomBytes as randomBytes7 } from "node:crypto";
32379
33749
  import {
32380
33750
  chmodSync as chmodSync2,
32381
33751
  closeSync as closeSync4,
@@ -32391,7 +33761,7 @@ import {
32391
33761
  unlinkSync as unlinkSync6,
32392
33762
  writeSync
32393
33763
  } from "node:fs";
32394
- import { join as join13 } from "node:path";
33764
+ import { join as join15 } from "node:path";
32395
33765
  class CoordinatorError extends Error {
32396
33766
  code;
32397
33767
  constructor(code) {
@@ -32401,7 +33771,7 @@ class CoordinatorError extends Error {
32401
33771
  }
32402
33772
  function defaultFsOps() {
32403
33773
  return {
32404
- randomSuffix: () => randomBytes5(12).toString("hex"),
33774
+ randomSuffix: () => randomBytes7(12).toString("hex"),
32405
33775
  open: (path11, flags, mode) => openSync4(path11, flags, mode),
32406
33776
  write: (fd, bytes) => {
32407
33777
  writeSync(fd, bytes);
@@ -32458,15 +33828,15 @@ function commandFrom(sidecar) {
32458
33828
  }
32459
33829
  function createDiagnosticReportCoordinator(args) {
32460
33830
  const fsOps = args.fsOps ?? defaultFsOps();
32461
- const dir = join13(args.machineDir, "diagnostics");
33831
+ const dir = join15(args.machineDir, "diagnostics");
32462
33832
  let stopped = false;
32463
33833
  let active = null;
32464
33834
  const retryCancels = new Set;
32465
33835
  const checkpoint = (point) => {
32466
33836
  args.checkpoint?.(point);
32467
33837
  };
32468
- const archivePath = (reportId) => join13(dir, `report-${reportId}.ndjson.gz`);
32469
- const sidecarPath = (reportId) => join13(dir, `report-${reportId}.json`);
33838
+ const archivePath = (reportId) => join15(dir, `report-${reportId}.ndjson.gz`);
33839
+ const sidecarPath = (reportId) => join15(dir, `report-${reportId}.json`);
32470
33840
  const ensureDir = () => {
32471
33841
  if (existsSync7(dir)) {
32472
33842
  const stat = lstatSync5(dir);
@@ -32500,7 +33870,7 @@ function createDiagnosticReportCoordinator(args) {
32500
33870
  let temp = "";
32501
33871
  let fd = null;
32502
33872
  for (let attempt = 0;attempt < 32; attempt += 1) {
32503
- temp = join13(dir, `.${sidecar.reportId}.${sidecar.phase}.${fsOps.randomSuffix()}.tmp`);
33873
+ temp = join15(dir, `.${sidecar.reportId}.${sidecar.phase}.${fsOps.randomSuffix()}.tmp`);
32504
33874
  try {
32505
33875
  fd = fsOps.open(temp, "wx", 384);
32506
33876
  break;
@@ -32617,7 +33987,7 @@ function createDiagnosticReportCoordinator(args) {
32617
33987
  return ready;
32618
33988
  };
32619
33989
  const buildAndCommit = async (command, collecting) => {
32620
- const temp = join13(dir, `.${command.reportId}.archive.${fsOps.randomSuffix()}.tmp`);
33990
+ const temp = join15(dir, `.${command.reportId}.archive.${fsOps.randomSuffix()}.tmp`);
32621
33991
  const artifact2 = await args.buildBundle({ command, outputPath: temp });
32622
33992
  checkpoint("archive_temp_written");
32623
33993
  const fd = fsOps.open(artifact2.path, "r+");
@@ -33465,7 +34835,7 @@ var LEGACY_DAEMON_ID_PATTERN = /^[a-f0-9]{12}$/;
33465
34835
  var DEFAULT_SERVER_URL = "https://alook.ai";
33466
34836
  var DEFAULT_WS_URL = "wss://alook.ai/api/ws/community-daemon";
33467
34837
  function resolveDefaultBaseDir() {
33468
- const root = process.env.ALOOK_PROJECT_ROOT || path13.join(homedir5(), ".alook");
34838
+ const root = process.env.ALOOK_PROJECT_ROOT || path13.join(homedir6(), ".alook");
33469
34839
  return path13.join(root, "daemon");
33470
34840
  }
33471
34841
  var DEFAULT_BASE_DIR = resolveDefaultBaseDir();
@@ -34518,6 +35888,61 @@ async function armMessageReminderFromEnv(input, env = process.env, fetchImpl = f
34518
35888
  return { armed: false, reason: "local reminder returned an invalid response" };
34519
35889
  }
34520
35890
 
35891
+ // src/cli/imageThumbnail.ts
35892
+ var RASTER_CONTENT_TYPES = new Set([
35893
+ "image/png",
35894
+ "image/jpeg",
35895
+ "image/webp",
35896
+ "image/gif"
35897
+ ]);
35898
+ var QUALITIES = [80, 70, 60, 50, 40, 30, 20];
35899
+ var DIMENSION_ATTEMPTS = 10;
35900
+ var DIMENSION_SCALE = 0.85;
35901
+ async function prepareCommunityImageUpload(bytes, contentType) {
35902
+ if (!RASTER_CONTENT_TYPES.has(contentType))
35903
+ return {};
35904
+ let required2 = bytes.byteLength > MAX_ATTACHMENT_THUMBNAIL_SIZE_BYTES;
35905
+ try {
35906
+ const { default: sharp } = await import("sharp");
35907
+ const metadata = await sharp(bytes, { failOn: "error" }).metadata();
35908
+ const width = metadata.width;
35909
+ const height = metadata.height;
35910
+ if (!width || !height) {
35911
+ if (required2)
35912
+ throw new Error("missing image dimensions");
35913
+ return {};
35914
+ }
35915
+ required2 = required2 || Math.max(width, height) > MAX_ATTACHMENT_THUMBNAIL_EDGE_PX;
35916
+ if (!required2)
35917
+ return { width, height };
35918
+ const fittedScale = Math.min(1, MAX_ATTACHMENT_THUMBNAIL_EDGE_PX / Math.max(width, height));
35919
+ const fittedWidth = Math.max(1, Math.round(width * fittedScale));
35920
+ const fittedHeight = Math.max(1, Math.round(height * fittedScale));
35921
+ for (let attempt = 0;attempt < DIMENSION_ATTEMPTS; attempt++) {
35922
+ const scale = DIMENSION_SCALE ** attempt;
35923
+ const targetWidth = Math.max(1, Math.round(fittedWidth * scale));
35924
+ const targetHeight = Math.max(1, Math.round(fittedHeight * scale));
35925
+ for (const quality of QUALITIES) {
35926
+ const jpeg = await sharp(bytes, { failOn: "error" }).resize({
35927
+ width: targetWidth,
35928
+ height: targetHeight,
35929
+ fit: "inside",
35930
+ withoutEnlargement: true
35931
+ }).jpeg({ quality }).toBuffer();
35932
+ if (jpeg.byteLength <= MAX_ATTACHMENT_THUMBNAIL_SIZE_BYTES) {
35933
+ return { thumbnail: new Uint8Array(jpeg), width, height };
35934
+ }
35935
+ }
35936
+ }
35937
+ throw new Error("no policy-compliant JPEG candidate");
35938
+ } catch {
35939
+ if (required2) {
35940
+ throw new Error("could not generate a required image preview");
35941
+ }
35942
+ return {};
35943
+ }
35944
+ }
35945
+
34521
35946
  // src/cli/index.ts
34522
35947
  function messagesInLocalTime(messages) {
34523
35948
  return messages.map((m) => ({ ...m, time: toLocalISO(m.time) }));
@@ -34724,7 +36149,7 @@ ${MESSAGE_SEND_STDIN_POLICY}`);
34724
36149
  }
34725
36150
  replyToSeq = n;
34726
36151
  }
34727
- const nonce = randomUUID9();
36152
+ const nonce = randomUUID10();
34728
36153
  const res = await sendWithRetry(api2, {
34729
36154
  agentId: agent2,
34730
36155
  channel: channel2,
@@ -34835,22 +36260,19 @@ async function cmdAttachmentUpload(opts) {
34835
36260
  let height;
34836
36261
  if (["image/png", "image/jpeg", "image/webp", "image/gif"].includes(contentType)) {
34837
36262
  try {
34838
- const { default: sharp } = await import("sharp");
34839
- const image = sharp(bytes, { failOn: "error" });
34840
- const metadata = await image.metadata();
34841
- if (metadata.width && metadata.height) {
34842
- width = metadata.width;
34843
- height = metadata.height;
34844
- }
34845
- const jpeg = await image.resize({ width: 200, height: 200, fit: "inside", withoutEnlargement: true }).jpeg({ quality: 70 }).toBuffer();
34846
- if (jpeg.byteLength <= MAX_ATTACHMENT_THUMBNAIL_SIZE_BYTES) {
36263
+ const prepared = await prepareCommunityImageUpload(bytes, contentType);
36264
+ width = prepared.width;
36265
+ height = prepared.height;
36266
+ if (prepared.thumbnail) {
34847
36267
  thumbnail = {
34848
- data: new Uint8Array(jpeg),
36268
+ data: prepared.thumbnail,
34849
36269
  filename: "thumbnail.jpg",
34850
36270
  contentType: "image/jpeg"
34851
36271
  };
34852
36272
  }
34853
- } catch {}
36273
+ } catch (error51) {
36274
+ throw new CliError(`message attachment upload: ${error51.message}`);
36275
+ }
34854
36276
  }
34855
36277
  const result = await api2.attachmentUpload({
34856
36278
  agentId: agent2,