@alook/daemon 0.1.42 → 0.1.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -22157,33 +22157,102 @@ var AttentionScopeSchema = exports_external.strictObject({
22157
22157
  });
22158
22158
  var AttentionItemSchema = exports_external.strictObject({
22159
22159
  id,
22160
- kind: exports_external.enum(["mention", "reply", "friend_request"]),
22160
+ kind: exports_external.enum(["mention", "reply", "friend_request", "forum_post"]),
22161
22161
  sourceId: id,
22162
22162
  scopeId: id.nullable().optional(),
22163
22163
  messageId: id.nullable().optional(),
22164
- actorUserId: id,
22165
- createdAt: exports_external.string()
22164
+ actorUserId: id.nullable().optional(),
22165
+ createdAt: exports_external.string(),
22166
+ childChannelId: id.optional(),
22167
+ openerSeq: exports_external.number().int().nonnegative().optional(),
22168
+ readTarget: exports_external.strictObject({
22169
+ channelId: id,
22170
+ seq: exports_external.number().int().nonnegative()
22171
+ }).optional()
22166
22172
  }).superRefine((item, ctx) => {
22167
22173
  if (item.kind === "friend_request") {
22168
- if (item.scopeId != null || item.messageId != null) {
22174
+ if (!item.actorUserId || item.scopeId != null || item.messageId != null) {
22169
22175
  ctx.addIssue({ code: "custom", message: "friend request cannot reference a scope or message" });
22170
22176
  }
22177
+ if (item.childChannelId || item.openerSeq !== undefined || item.readTarget) {
22178
+ ctx.addIssue({ code: "custom", message: "friend request cannot carry forum presentation refs" });
22179
+ }
22171
22180
  return;
22172
22181
  }
22173
22182
  if (!item.scopeId || !item.messageId) {
22174
22183
  ctx.addIssue({ code: "custom", message: "message attention requires scope and message refs" });
22175
22184
  }
22185
+ if (item.kind === "forum_post") {
22186
+ if (item.actorUserId != null || !item.childChannelId || item.openerSeq === undefined || !item.readTarget || item.sourceId !== item.childChannelId || item.readTarget.seq !== item.openerSeq) {
22187
+ ctx.addIssue({ code: "custom", message: "forum post requires exact child, opener, and read-target refs" });
22188
+ }
22189
+ return;
22190
+ }
22191
+ if (!item.actorUserId) {
22192
+ ctx.addIssue({ code: "custom", message: "message attention requires an actor" });
22193
+ }
22194
+ if (item.childChannelId || item.openerSeq !== undefined || item.readTarget) {
22195
+ ctx.addIssue({ code: "custom", message: "mention or reply cannot carry forum presentation refs" });
22196
+ }
22197
+ });
22198
+ var AttentionIncludedServerSchema = exports_external.strictObject({
22199
+ id,
22200
+ name: exports_external.string(),
22201
+ discriminator: exports_external.string()
22202
+ });
22203
+ var AttentionIncludedChannelSchema = exports_external.strictObject({
22204
+ id,
22205
+ serverId: id,
22206
+ name: exports_external.string(),
22207
+ type: exports_external.enum(["text", "forum", "thread"]),
22208
+ parentChannelId: id.nullable(),
22209
+ parentMessageId: id.nullable(),
22210
+ creatorId: id.nullable(),
22211
+ archived: exports_external.boolean(),
22212
+ lastMessageAt: exports_external.string().nullable(),
22213
+ openerSeq: exports_external.number().int().nonnegative().optional(),
22214
+ openerUnread: exports_external.boolean().optional()
22215
+ });
22216
+ var AttentionIncludedDmSchema = exports_external.strictObject({
22217
+ id,
22218
+ userId: id,
22219
+ name: exports_external.string(),
22220
+ discriminator: exports_external.string(),
22221
+ avatar: exports_external.string(),
22222
+ avatarVersion: exports_external.number().int().nonnegative(),
22223
+ lastMessageAt: exports_external.string(),
22224
+ lastUnreadSeq: exports_external.number().int().nonnegative()
22225
+ });
22226
+ var AttentionIncludedProfileSchema = exports_external.strictObject({
22227
+ userId: id,
22228
+ name: exports_external.string(),
22229
+ discriminator: exports_external.string(),
22230
+ avatar: exports_external.string(),
22231
+ avatarVersion: exports_external.number().int().nonnegative()
22232
+ });
22233
+ var AttentionIncludedMessageSchema = exports_external.strictObject({
22234
+ id,
22235
+ channelId: id,
22236
+ type: exports_external.enum(["chat", "system"]),
22237
+ authorId: id.optional(),
22238
+ authorName: exports_external.string().optional(),
22239
+ seq: exports_external.number().int().nonnegative(),
22240
+ createdAt: exports_external.string(),
22241
+ content: exports_external.string()
22176
22242
  });
22177
22243
  var AttentionIncludedSchema = exports_external.strictObject({
22178
- profiles: exports_external.array(exports_external.unknown()).optional(),
22179
- messages: exports_external.array(exports_external.unknown()).optional()
22244
+ servers: exports_external.array(AttentionIncludedServerSchema),
22245
+ channels: exports_external.array(AttentionIncludedChannelSchema),
22246
+ dms: exports_external.array(AttentionIncludedDmSchema),
22247
+ profiles: exports_external.array(AttentionIncludedProfileSchema),
22248
+ messages: exports_external.array(AttentionIncludedMessageSchema)
22180
22249
  });
22181
22250
  var AccountAttentionSnapshotSchema = exports_external.strictObject({
22182
22251
  scopes: exports_external.array(AttentionScopeSchema),
22183
22252
  items: exports_external.array(AttentionItemSchema),
22184
22253
  limit: exports_external.number().int().positive(),
22185
22254
  truncated: exports_external.boolean(),
22186
- included: AttentionIncludedSchema.optional()
22255
+ included: AttentionIncludedSchema
22187
22256
  }).superRefine((snapshot, ctx) => {
22188
22257
  const scopeIds = new Set;
22189
22258
  for (const scope of snapshot.scopes) {
@@ -22193,6 +22262,47 @@ var AccountAttentionSnapshotSchema = exports_external.strictObject({
22193
22262
  scopeIds.add(scope.scopeId);
22194
22263
  }
22195
22264
  const itemIds = new Set;
22265
+ const serverById = new Map(snapshot.included.servers.map((server) => [server.id, server]));
22266
+ const channelById = new Map(snapshot.included.channels.map((channel2) => [channel2.id, channel2]));
22267
+ const dmById = new Map(snapshot.included.dms.map((dm) => [dm.id, dm]));
22268
+ const profileById = new Map(snapshot.included.profiles.map((profile) => [profile.userId, profile]));
22269
+ const messageById = new Map(snapshot.included.messages.map((message2) => [message2.id, message2]));
22270
+ const rejectDuplicates = (values, kind) => {
22271
+ const seen = new Set;
22272
+ for (const value of values) {
22273
+ if (seen.has(value))
22274
+ ctx.addIssue({ code: "custom", message: `duplicate included ${kind}: ${value}` });
22275
+ seen.add(value);
22276
+ }
22277
+ };
22278
+ rejectDuplicates(snapshot.included.servers.map((server) => server.id), "server");
22279
+ rejectDuplicates(snapshot.included.channels.map((channel2) => channel2.id), "channel");
22280
+ rejectDuplicates(snapshot.included.dms.map((dm) => dm.id), "dm");
22281
+ rejectDuplicates(snapshot.included.profiles.map((profile) => profile.userId), "profile");
22282
+ rejectDuplicates(snapshot.included.messages.map((message2) => message2.id), "message");
22283
+ for (const scope of snapshot.scopes) {
22284
+ if (scope.serverId) {
22285
+ const channel2 = channelById.get(scope.channelId);
22286
+ if (!serverById.has(scope.serverId) || !channel2 || channel2.serverId !== scope.serverId) {
22287
+ ctx.addIssue({ code: "custom", message: `attention scope references missing owner: ${scope.scopeId}` });
22288
+ continue;
22289
+ }
22290
+ if (scope.parentChannelId) {
22291
+ const parent = channelById.get(scope.parentChannelId);
22292
+ const opener = channel2.parentMessageId ? messageById.get(channel2.parentMessageId) : undefined;
22293
+ if (channel2.parentChannelId !== scope.parentChannelId || !parent || parent.serverId !== scope.serverId || !opener || opener.channelId !== parent.id || channel2.openerSeq !== opener.seq || channel2.openerUnread === undefined) {
22294
+ ctx.addIssue({ code: "custom", message: `attention scope references missing parent: ${scope.scopeId}` });
22295
+ }
22296
+ } else if (channel2.parentChannelId !== null) {
22297
+ ctx.addIssue({ code: "custom", message: `attention scope parent mismatch: ${scope.scopeId}` });
22298
+ }
22299
+ } else {
22300
+ const dm = dmById.get(scope.channelId);
22301
+ if (!dm || !profileById.has(dm.userId)) {
22302
+ ctx.addIssue({ code: "custom", message: `attention scope references missing DM owner: ${scope.scopeId}` });
22303
+ }
22304
+ }
22305
+ }
22196
22306
  for (const item of snapshot.items) {
22197
22307
  if (itemIds.has(item.id)) {
22198
22308
  ctx.addIssue({ code: "custom", message: `duplicate attention item: ${item.id}` });
@@ -22201,6 +22311,29 @@ var AccountAttentionSnapshotSchema = exports_external.strictObject({
22201
22311
  if (item.scopeId && !scopeIds.has(item.scopeId)) {
22202
22312
  ctx.addIssue({ code: "custom", message: `attention item references missing scope: ${item.scopeId}` });
22203
22313
  }
22314
+ if (item.kind === "friend_request") {
22315
+ if (!item.actorUserId || !profileById.has(item.actorUserId)) {
22316
+ ctx.addIssue({ code: "custom", message: `friend request references missing profile: ${item.id}` });
22317
+ }
22318
+ continue;
22319
+ }
22320
+ const scope = item.scopeId ? snapshot.scopes.find((candidate) => candidate.scopeId === item.scopeId) : undefined;
22321
+ const message2 = item.messageId ? messageById.get(item.messageId) : undefined;
22322
+ if (!scope || !message2) {
22323
+ ctx.addIssue({ code: "custom", message: `attention item references missing message: ${item.id}` });
22324
+ continue;
22325
+ }
22326
+ if (item.kind === "forum_post") {
22327
+ const parent = channelById.get(scope.channelId);
22328
+ const child = item.childChannelId ? channelById.get(item.childChannelId) : undefined;
22329
+ if (!scope.serverId || parent?.type !== "forum" || child?.type !== "thread" || child.parentChannelId !== parent.id || child.parentMessageId !== message2.id || message2.channelId !== parent.id || message2.seq !== item.openerSeq || item.readTarget?.channelId !== parent.id) {
22330
+ ctx.addIssue({ code: "custom", message: `forum post references incomplete presentation owners: ${item.id}` });
22331
+ }
22332
+ continue;
22333
+ }
22334
+ if (message2.channelId !== scope.channelId || !item.actorUserId || !profileById.has(item.actorUserId)) {
22335
+ ctx.addIssue({ code: "custom", message: `message attention references incomplete owners: ${item.id}` });
22336
+ }
22204
22337
  }
22205
22338
  });
22206
22339
  // ../shared/src/constants/community.ts
@@ -24476,7 +24609,9 @@ var COMMUNITY_BROWSER_EVENT_BATCH_MAX_BYTES = MESSAGE_DELIVERY_MAX_EVENTS_PER_US
24476
24609
  var exports_billing_schema = {};
24477
24610
  __export(exports_billing_schema, {
24478
24611
  userBilling: () => userBilling,
24479
- billingPrice: () => billingPrice
24612
+ billingPurchaseDelivery: () => billingPurchaseDelivery,
24613
+ billingPrice: () => billingPrice,
24614
+ billingAnalyticsConsent: () => billingAnalyticsConsent
24480
24615
  });
24481
24616
  var billingPrice = sqliteTable("billing_price", {
24482
24617
  priceId: text("price_id").primaryKey(),
@@ -24497,6 +24632,28 @@ var userBilling = sqliteTable("user_billing", {
24497
24632
  uniqueIndex("uq_user_billing_customer").on(t.customerId),
24498
24633
  uniqueIndex("uq_user_billing_subscription").on(t.subscriptionId)
24499
24634
  ]);
24635
+ var billingAnalyticsConsent = sqliteTable("billing_analytics_consent", {
24636
+ userId: text("user_id").primaryKey().references(() => user.id, { onDelete: "cascade" }),
24637
+ decision: text("decision").$type().notNull(),
24638
+ sourceVersion: integer2("source_version").notNull(),
24639
+ revision: integer2("revision").notNull().default(1),
24640
+ updatedAt: text("updated_at").notNull().$defaultFn(() => new Date().toISOString())
24641
+ });
24642
+ var billingPurchaseDelivery = sqliteTable("billing_purchase_delivery", {
24643
+ invoiceId: text("invoice_id").primaryKey(),
24644
+ userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
24645
+ status: text("status").$type().notNull(),
24646
+ reason: text("reason").notNull(),
24647
+ purchaseType: text("purchase_type").$type(),
24648
+ currency: text("currency"),
24649
+ valueMinor: integer2("value_minor"),
24650
+ planId: text("plan_id"),
24651
+ validationJson: text("validation_json"),
24652
+ claimedAt: text("claimed_at").notNull().$defaultFn(() => new Date().toISOString()),
24653
+ finalizedAt: text("finalized_at")
24654
+ }, (t) => [
24655
+ index("idx_billing_purchase_delivery_user_claimed").on(t.userId, t.claimedAt)
24656
+ ]);
24500
24657
 
24501
24658
  // ../shared/src/db/community-funnel-analytics-schema.ts
24502
24659
  var exports_community_funnel_analytics_schema = {};
@@ -36453,7 +36610,7 @@ var MEMORY_MAINTENANCE_PROMPT = `The daemon is preparing to reset this idle sess
36453
36610
  2. Facts: Verify claims, especially work progress, against the latest original records. Search the context timeline and task discussions through their latest outcomes. Correct outdated or unsupported claims; keep uncertainty explicit.
36454
36611
  3. Durability: Keep only lasting facts, preferences, and reusable lessons or procedures. Remove task status, milestones, temporary plans, and diaries; extract a reusable lesson only when useful. Keep memory.md brief with links; put procedures, scope, and reasons in experiences. Reason from first principles: distill specific events into underlying causes, constraints, and reusable principles. Omit incidental dates and details; retain context only when it changes the principle’s validity or scope.
36455
36612
 
36456
- Edit only your own memory files.
36613
+ Edit only your own memory files. This review is internal maintenance; perform it silently. Do not proactively send the owner, users, or channels progress updates, completion notices, or details about your memory state. Communicate task-relevant results, questions, and blockers normally. If nothing needs a user-facing response, send no message.
36457
36614
 
36458
36615
  If new work arrives, handle it first and defer nap. Otherwise, after completing the review and any needed edits, your final action is to run the following command without --handoff. Do not finish with only a written reply. This instruction authorizes that nap:
36459
36616
 
@@ -38698,7 +38855,7 @@ var REWAKE_PROMPT = `Your session was reset by your owner. Prior conversation co
38698
38855
  2. Facts: Verify claims, especially work progress, against the latest original records. Search the context timeline and task discussions through their latest outcomes. Correct outdated or unsupported claims; keep uncertainty explicit.
38699
38856
  3. Durability: Keep only lasting facts, preferences, and reusable lessons or procedures. Remove task status, milestones, temporary plans, and diaries; extract a reusable lesson only when useful. Keep memory.md brief with links; put procedures, scope, and reasons in experiences. Reason from first principles: distill specific events into underlying causes, constraints, and reusable principles. Omit incidental dates and details; retain context only when it changes the principle’s validity or scope.
38700
38857
 
38701
- Edit only your own memory files.
38858
+ Edit only your own memory files. This review is internal maintenance; perform it silently. Do not proactively send the owner, users, or channels progress updates, completion notices, or details about your memory state. Communicate task-relevant results, questions, and blockers normally. If nothing needs a user-facing response, send no message.
38702
38859
 
38703
38860
  After completing the review and any needed edits, resume outstanding work and handle your inbox messages.`;
38704
38861
  var MODEL_SWITCH_REWAKE_PROMPT = "You were just switched to a different model. Continue any unfinished work.";
package/dist/index.js CHANGED
@@ -10715,7 +10715,7 @@ var MEMORY_MAINTENANCE_PROMPT = `The daemon is preparing to reset this idle sess
10715
10715
  2. Facts: Verify claims, especially work progress, against the latest original records. Search the context timeline and task discussions through their latest outcomes. Correct outdated or unsupported claims; keep uncertainty explicit.
10716
10716
  3. Durability: Keep only lasting facts, preferences, and reusable lessons or procedures. Remove task status, milestones, temporary plans, and diaries; extract a reusable lesson only when useful. Keep memory.md brief with links; put procedures, scope, and reasons in experiences. Reason from first principles: distill specific events into underlying causes, constraints, and reusable principles. Omit incidental dates and details; retain context only when it changes the principle’s validity or scope.
10717
10717
 
10718
- Edit only your own memory files.
10718
+ Edit only your own memory files. This review is internal maintenance; perform it silently. Do not proactively send the owner, users, or channels progress updates, completion notices, or details about your memory state. Communicate task-relevant results, questions, and blockers normally. If nothing needs a user-facing response, send no message.
10719
10719
 
10720
10720
  If new work arrives, handle it first and defer nap. Otherwise, after completing the review and any needed edits, your final action is to run the following command without --handoff. Do not finish with only a written reply. This instruction authorizes that nap:
10721
10721
 
@@ -34921,7 +34921,7 @@ var REWAKE_PROMPT = `Your session was reset by your owner. Prior conversation co
34921
34921
  2. Facts: Verify claims, especially work progress, against the latest original records. Search the context timeline and task discussions through their latest outcomes. Correct outdated or unsupported claims; keep uncertainty explicit.
34922
34922
  3. Durability: Keep only lasting facts, preferences, and reusable lessons or procedures. Remove task status, milestones, temporary plans, and diaries; extract a reusable lesson only when useful. Keep memory.md brief with links; put procedures, scope, and reasons in experiences. Reason from first principles: distill specific events into underlying causes, constraints, and reusable principles. Omit incidental dates and details; retain context only when it changes the principle’s validity or scope.
34923
34923
 
34924
- Edit only your own memory files.
34924
+ Edit only your own memory files. This review is internal maintenance; perform it silently. Do not proactively send the owner, users, or channels progress updates, completion notices, or details about your memory state. Communicate task-relevant results, questions, and blockers normally. If nothing needs a user-facing response, send no message.
34925
34925
 
34926
34926
  After completing the review and any needed edits, resume outstanding work and handle your inbox messages.`;
34927
34927
  var MODEL_SWITCH_REWAKE_PROMPT = "You were just switched to a different model. Continue any unfinished work.";
@@ -36096,33 +36096,102 @@ var AttentionScopeSchema = exports_external.strictObject({
36096
36096
  });
36097
36097
  var AttentionItemSchema = exports_external.strictObject({
36098
36098
  id,
36099
- kind: exports_external.enum(["mention", "reply", "friend_request"]),
36099
+ kind: exports_external.enum(["mention", "reply", "friend_request", "forum_post"]),
36100
36100
  sourceId: id,
36101
36101
  scopeId: id.nullable().optional(),
36102
36102
  messageId: id.nullable().optional(),
36103
- actorUserId: id,
36104
- createdAt: exports_external.string()
36103
+ actorUserId: id.nullable().optional(),
36104
+ createdAt: exports_external.string(),
36105
+ childChannelId: id.optional(),
36106
+ openerSeq: exports_external.number().int().nonnegative().optional(),
36107
+ readTarget: exports_external.strictObject({
36108
+ channelId: id,
36109
+ seq: exports_external.number().int().nonnegative()
36110
+ }).optional()
36105
36111
  }).superRefine((item, ctx) => {
36106
36112
  if (item.kind === "friend_request") {
36107
- if (item.scopeId != null || item.messageId != null) {
36113
+ if (!item.actorUserId || item.scopeId != null || item.messageId != null) {
36108
36114
  ctx.addIssue({ code: "custom", message: "friend request cannot reference a scope or message" });
36109
36115
  }
36116
+ if (item.childChannelId || item.openerSeq !== undefined || item.readTarget) {
36117
+ ctx.addIssue({ code: "custom", message: "friend request cannot carry forum presentation refs" });
36118
+ }
36110
36119
  return;
36111
36120
  }
36112
36121
  if (!item.scopeId || !item.messageId) {
36113
36122
  ctx.addIssue({ code: "custom", message: "message attention requires scope and message refs" });
36114
36123
  }
36124
+ if (item.kind === "forum_post") {
36125
+ if (item.actorUserId != null || !item.childChannelId || item.openerSeq === undefined || !item.readTarget || item.sourceId !== item.childChannelId || item.readTarget.seq !== item.openerSeq) {
36126
+ ctx.addIssue({ code: "custom", message: "forum post requires exact child, opener, and read-target refs" });
36127
+ }
36128
+ return;
36129
+ }
36130
+ if (!item.actorUserId) {
36131
+ ctx.addIssue({ code: "custom", message: "message attention requires an actor" });
36132
+ }
36133
+ if (item.childChannelId || item.openerSeq !== undefined || item.readTarget) {
36134
+ ctx.addIssue({ code: "custom", message: "mention or reply cannot carry forum presentation refs" });
36135
+ }
36136
+ });
36137
+ var AttentionIncludedServerSchema = exports_external.strictObject({
36138
+ id,
36139
+ name: exports_external.string(),
36140
+ discriminator: exports_external.string()
36141
+ });
36142
+ var AttentionIncludedChannelSchema = exports_external.strictObject({
36143
+ id,
36144
+ serverId: id,
36145
+ name: exports_external.string(),
36146
+ type: exports_external.enum(["text", "forum", "thread"]),
36147
+ parentChannelId: id.nullable(),
36148
+ parentMessageId: id.nullable(),
36149
+ creatorId: id.nullable(),
36150
+ archived: exports_external.boolean(),
36151
+ lastMessageAt: exports_external.string().nullable(),
36152
+ openerSeq: exports_external.number().int().nonnegative().optional(),
36153
+ openerUnread: exports_external.boolean().optional()
36154
+ });
36155
+ var AttentionIncludedDmSchema = exports_external.strictObject({
36156
+ id,
36157
+ userId: id,
36158
+ name: exports_external.string(),
36159
+ discriminator: exports_external.string(),
36160
+ avatar: exports_external.string(),
36161
+ avatarVersion: exports_external.number().int().nonnegative(),
36162
+ lastMessageAt: exports_external.string(),
36163
+ lastUnreadSeq: exports_external.number().int().nonnegative()
36164
+ });
36165
+ var AttentionIncludedProfileSchema = exports_external.strictObject({
36166
+ userId: id,
36167
+ name: exports_external.string(),
36168
+ discriminator: exports_external.string(),
36169
+ avatar: exports_external.string(),
36170
+ avatarVersion: exports_external.number().int().nonnegative()
36171
+ });
36172
+ var AttentionIncludedMessageSchema = exports_external.strictObject({
36173
+ id,
36174
+ channelId: id,
36175
+ type: exports_external.enum(["chat", "system"]),
36176
+ authorId: id.optional(),
36177
+ authorName: exports_external.string().optional(),
36178
+ seq: exports_external.number().int().nonnegative(),
36179
+ createdAt: exports_external.string(),
36180
+ content: exports_external.string()
36115
36181
  });
36116
36182
  var AttentionIncludedSchema = exports_external.strictObject({
36117
- profiles: exports_external.array(exports_external.unknown()).optional(),
36118
- messages: exports_external.array(exports_external.unknown()).optional()
36183
+ servers: exports_external.array(AttentionIncludedServerSchema),
36184
+ channels: exports_external.array(AttentionIncludedChannelSchema),
36185
+ dms: exports_external.array(AttentionIncludedDmSchema),
36186
+ profiles: exports_external.array(AttentionIncludedProfileSchema),
36187
+ messages: exports_external.array(AttentionIncludedMessageSchema)
36119
36188
  });
36120
36189
  var AccountAttentionSnapshotSchema = exports_external.strictObject({
36121
36190
  scopes: exports_external.array(AttentionScopeSchema),
36122
36191
  items: exports_external.array(AttentionItemSchema),
36123
36192
  limit: exports_external.number().int().positive(),
36124
36193
  truncated: exports_external.boolean(),
36125
- included: AttentionIncludedSchema.optional()
36194
+ included: AttentionIncludedSchema
36126
36195
  }).superRefine((snapshot, ctx) => {
36127
36196
  const scopeIds = new Set;
36128
36197
  for (const scope of snapshot.scopes) {
@@ -36132,6 +36201,47 @@ var AccountAttentionSnapshotSchema = exports_external.strictObject({
36132
36201
  scopeIds.add(scope.scopeId);
36133
36202
  }
36134
36203
  const itemIds = new Set;
36204
+ const serverById = new Map(snapshot.included.servers.map((server) => [server.id, server]));
36205
+ const channelById = new Map(snapshot.included.channels.map((channel2) => [channel2.id, channel2]));
36206
+ const dmById = new Map(snapshot.included.dms.map((dm) => [dm.id, dm]));
36207
+ const profileById = new Map(snapshot.included.profiles.map((profile) => [profile.userId, profile]));
36208
+ const messageById = new Map(snapshot.included.messages.map((message2) => [message2.id, message2]));
36209
+ const rejectDuplicates = (values, kind) => {
36210
+ const seen = new Set;
36211
+ for (const value of values) {
36212
+ if (seen.has(value))
36213
+ ctx.addIssue({ code: "custom", message: `duplicate included ${kind}: ${value}` });
36214
+ seen.add(value);
36215
+ }
36216
+ };
36217
+ rejectDuplicates(snapshot.included.servers.map((server) => server.id), "server");
36218
+ rejectDuplicates(snapshot.included.channels.map((channel2) => channel2.id), "channel");
36219
+ rejectDuplicates(snapshot.included.dms.map((dm) => dm.id), "dm");
36220
+ rejectDuplicates(snapshot.included.profiles.map((profile) => profile.userId), "profile");
36221
+ rejectDuplicates(snapshot.included.messages.map((message2) => message2.id), "message");
36222
+ for (const scope of snapshot.scopes) {
36223
+ if (scope.serverId) {
36224
+ const channel2 = channelById.get(scope.channelId);
36225
+ if (!serverById.has(scope.serverId) || !channel2 || channel2.serverId !== scope.serverId) {
36226
+ ctx.addIssue({ code: "custom", message: `attention scope references missing owner: ${scope.scopeId}` });
36227
+ continue;
36228
+ }
36229
+ if (scope.parentChannelId) {
36230
+ const parent = channelById.get(scope.parentChannelId);
36231
+ const opener = channel2.parentMessageId ? messageById.get(channel2.parentMessageId) : undefined;
36232
+ if (channel2.parentChannelId !== scope.parentChannelId || !parent || parent.serverId !== scope.serverId || !opener || opener.channelId !== parent.id || channel2.openerSeq !== opener.seq || channel2.openerUnread === undefined) {
36233
+ ctx.addIssue({ code: "custom", message: `attention scope references missing parent: ${scope.scopeId}` });
36234
+ }
36235
+ } else if (channel2.parentChannelId !== null) {
36236
+ ctx.addIssue({ code: "custom", message: `attention scope parent mismatch: ${scope.scopeId}` });
36237
+ }
36238
+ } else {
36239
+ const dm = dmById.get(scope.channelId);
36240
+ if (!dm || !profileById.has(dm.userId)) {
36241
+ ctx.addIssue({ code: "custom", message: `attention scope references missing DM owner: ${scope.scopeId}` });
36242
+ }
36243
+ }
36244
+ }
36135
36245
  for (const item of snapshot.items) {
36136
36246
  if (itemIds.has(item.id)) {
36137
36247
  ctx.addIssue({ code: "custom", message: `duplicate attention item: ${item.id}` });
@@ -36140,6 +36250,29 @@ var AccountAttentionSnapshotSchema = exports_external.strictObject({
36140
36250
  if (item.scopeId && !scopeIds.has(item.scopeId)) {
36141
36251
  ctx.addIssue({ code: "custom", message: `attention item references missing scope: ${item.scopeId}` });
36142
36252
  }
36253
+ if (item.kind === "friend_request") {
36254
+ if (!item.actorUserId || !profileById.has(item.actorUserId)) {
36255
+ ctx.addIssue({ code: "custom", message: `friend request references missing profile: ${item.id}` });
36256
+ }
36257
+ continue;
36258
+ }
36259
+ const scope = item.scopeId ? snapshot.scopes.find((candidate) => candidate.scopeId === item.scopeId) : undefined;
36260
+ const message2 = item.messageId ? messageById.get(item.messageId) : undefined;
36261
+ if (!scope || !message2) {
36262
+ ctx.addIssue({ code: "custom", message: `attention item references missing message: ${item.id}` });
36263
+ continue;
36264
+ }
36265
+ if (item.kind === "forum_post") {
36266
+ const parent = channelById.get(scope.channelId);
36267
+ const child = item.childChannelId ? channelById.get(item.childChannelId) : undefined;
36268
+ if (!scope.serverId || parent?.type !== "forum" || child?.type !== "thread" || child.parentChannelId !== parent.id || child.parentMessageId !== message2.id || message2.channelId !== parent.id || message2.seq !== item.openerSeq || item.readTarget?.channelId !== parent.id) {
36269
+ ctx.addIssue({ code: "custom", message: `forum post references incomplete presentation owners: ${item.id}` });
36270
+ }
36271
+ continue;
36272
+ }
36273
+ if (message2.channelId !== scope.channelId || !item.actorUserId || !profileById.has(item.actorUserId)) {
36274
+ ctx.addIssue({ code: "custom", message: `message attention references incomplete owners: ${item.id}` });
36275
+ }
36143
36276
  }
36144
36277
  });
36145
36278
  // ../shared/src/constants/community.ts
@@ -38414,7 +38547,9 @@ var COMMUNITY_BROWSER_EVENT_BATCH_MAX_BYTES = MESSAGE_DELIVERY_MAX_EVENTS_PER_US
38414
38547
  var exports_billing_schema = {};
38415
38548
  __export(exports_billing_schema, {
38416
38549
  userBilling: () => userBilling,
38417
- billingPrice: () => billingPrice
38550
+ billingPurchaseDelivery: () => billingPurchaseDelivery,
38551
+ billingPrice: () => billingPrice,
38552
+ billingAnalyticsConsent: () => billingAnalyticsConsent
38418
38553
  });
38419
38554
  var billingPrice = sqliteTable("billing_price", {
38420
38555
  priceId: text("price_id").primaryKey(),
@@ -38435,6 +38570,28 @@ var userBilling = sqliteTable("user_billing", {
38435
38570
  uniqueIndex("uq_user_billing_customer").on(t.customerId),
38436
38571
  uniqueIndex("uq_user_billing_subscription").on(t.subscriptionId)
38437
38572
  ]);
38573
+ var billingAnalyticsConsent = sqliteTable("billing_analytics_consent", {
38574
+ userId: text("user_id").primaryKey().references(() => user.id, { onDelete: "cascade" }),
38575
+ decision: text("decision").$type().notNull(),
38576
+ sourceVersion: integer2("source_version").notNull(),
38577
+ revision: integer2("revision").notNull().default(1),
38578
+ updatedAt: text("updated_at").notNull().$defaultFn(() => new Date().toISOString())
38579
+ });
38580
+ var billingPurchaseDelivery = sqliteTable("billing_purchase_delivery", {
38581
+ invoiceId: text("invoice_id").primaryKey(),
38582
+ userId: text("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
38583
+ status: text("status").$type().notNull(),
38584
+ reason: text("reason").notNull(),
38585
+ purchaseType: text("purchase_type").$type(),
38586
+ currency: text("currency"),
38587
+ valueMinor: integer2("value_minor"),
38588
+ planId: text("plan_id"),
38589
+ validationJson: text("validation_json"),
38590
+ claimedAt: text("claimed_at").notNull().$defaultFn(() => new Date().toISOString()),
38591
+ finalizedAt: text("finalized_at")
38592
+ }, (t) => [
38593
+ index("idx_billing_purchase_delivery_user_claimed").on(t.userId, t.claimedAt)
38594
+ ]);
38438
38595
 
38439
38596
  // ../shared/src/db/community-funnel-analytics-schema.ts
38440
38597
  var exports_community_funnel_analytics_schema = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alook/daemon",
3
- "version": "0.1.42",
3
+ "version": "0.1.43",
4
4
  "description": "Alook agent daemon — host-side runtime backend, process manager, credential proxy, and control plane.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/alookai/alook#readme",