@alook/cli 0.1.32 → 0.1.33

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/index.js CHANGED
@@ -15960,6 +15960,7 @@ __export(exports_schema, {
15960
15960
  user: () => user,
15961
15961
  taskMessage: () => taskMessage,
15962
15962
  session: () => session,
15963
+ nativeOauthAttempt: () => nativeOauthAttempt,
15963
15964
  messageFlag: () => messageFlag,
15964
15965
  message: () => message,
15965
15966
  member: () => member,
@@ -15986,7 +15987,11 @@ __export(exports_schema, {
15986
15987
  agentEmailAccount: () => agentEmailAccount,
15987
15988
  agentAccess: () => agentAccess,
15988
15989
  agent: () => agent,
15989
- account: () => account
15990
+ account: () => account,
15991
+ NATIVE_OAUTH_STATUSES: () => NATIVE_OAUTH_STATUSES,
15992
+ NATIVE_OAUTH_PROVIDERS: () => NATIVE_OAUTH_PROVIDERS,
15993
+ NATIVE_OAUTH_PLATFORMS: () => NATIVE_OAUTH_PLATFORMS,
15994
+ NATIVE_OAUTH_FAILURE_CODES: () => NATIVE_OAUTH_FAILURE_CODES
15990
15995
  });
15991
15996
  init_nanoid();
15992
15997
 
@@ -16121,6 +16126,119 @@ var verification = sqliteTable("verification", {
16121
16126
  createdAt: text("createdAt").notNull().$defaultFn(() => new Date().toISOString()),
16122
16127
  updatedAt: text("updatedAt").notNull().$defaultFn(() => new Date().toISOString())
16123
16128
  });
16129
+ var NATIVE_OAUTH_PROVIDERS = ["github", "google"];
16130
+ var NATIVE_OAUTH_PLATFORMS = [
16131
+ "macos",
16132
+ "windows",
16133
+ "linux",
16134
+ "ios",
16135
+ "android"
16136
+ ];
16137
+ var NATIVE_OAUTH_STATUSES = [
16138
+ "pending",
16139
+ "opened",
16140
+ "ready",
16141
+ "exchanging",
16142
+ "consumed",
16143
+ "failed",
16144
+ "cancelled",
16145
+ "replaced"
16146
+ ];
16147
+ var NATIVE_OAUTH_FAILURE_CODES = [
16148
+ "access_denied",
16149
+ "provider_error",
16150
+ "oauth_callback_failed",
16151
+ "start_failed",
16152
+ "invalid_handoff"
16153
+ ];
16154
+ var nativeOauthAttempt = sqliteTable("native_oauth_attempt", {
16155
+ id: text("id").primaryKey(),
16156
+ instanceKeyHash: text("instance_key_hash").notNull(),
16157
+ stateHash: text("state_hash").notNull(),
16158
+ pkceChallenge: text("pkce_challenge").notNull(),
16159
+ provider: text("provider").$type().notNull(),
16160
+ platform: text("platform").$type().notNull(),
16161
+ redirectPath: text("redirect_path").notNull(),
16162
+ status: text("status").$type().notNull().default("pending"),
16163
+ handoffCodeHash: text("handoff_code_hash"),
16164
+ handoffExpiresAt: integer2("handoff_expires_at"),
16165
+ authKind: text("auth_kind").$type(),
16166
+ failureCode: text("failure_code").$type(),
16167
+ attemptExpiresAt: integer2("attempt_expires_at").notNull(),
16168
+ createdAt: integer2("created_at").notNull(),
16169
+ updatedAt: integer2("updated_at").notNull(),
16170
+ openedAt: integer2("opened_at"),
16171
+ readyAt: integer2("ready_at"),
16172
+ consumedAt: integer2("consumed_at"),
16173
+ failedAt: integer2("failed_at"),
16174
+ cancelledAt: integer2("cancelled_at"),
16175
+ replacedAt: integer2("replaced_at")
16176
+ }, (t) => [
16177
+ index("idx_native_oauth_attempt_instance_status").on(t.instanceKeyHash, t.status),
16178
+ index("idx_native_oauth_attempt_id_status_expiry").on(t.id, t.status, t.attemptExpiresAt),
16179
+ index("idx_native_oauth_attempt_terminal_cleanup").on(t.status, t.updatedAt),
16180
+ uniqueIndex("uq_native_oauth_attempt_instance_live").on(t.instanceKeyHash).where(sql`status IN ('pending', 'opened', 'ready', 'exchanging')`),
16181
+ uniqueIndex("uq_native_oauth_attempt_handoff_hash").on(t.handoffCodeHash).where(sql`handoff_code_hash IS NOT NULL`),
16182
+ check2("ck_native_oauth_attempt_id", sql`length(${t.id}) BETWEEN 22 AND 64 AND ${t.id} NOT GLOB '*[^A-Za-z0-9_-]*'`),
16183
+ check2("ck_native_oauth_attempt_hashes", sql`length(${t.instanceKeyHash}) = 64 AND ${t.instanceKeyHash} NOT GLOB '*[^0-9a-f]*'
16184
+ AND length(${t.stateHash}) = 64 AND ${t.stateHash} NOT GLOB '*[^0-9a-f]*'
16185
+ AND length(${t.pkceChallenge}) = 43 AND ${t.pkceChallenge} NOT GLOB '*[^A-Za-z0-9_-]*'
16186
+ AND (${t.handoffCodeHash} IS NULL OR (length(${t.handoffCodeHash}) = 64 AND ${t.handoffCodeHash} NOT GLOB '*[^0-9a-f]*'))`),
16187
+ check2("ck_native_oauth_attempt_enums", sql`${t.provider} IN ('github', 'google')
16188
+ AND ${t.platform} IN ('macos', 'windows', 'linux', 'ios', 'android')
16189
+ AND ${t.status} IN ('pending', 'opened', 'ready', 'exchanging', 'consumed', 'failed', 'cancelled', 'replaced')
16190
+ AND (${t.authKind} IS NULL OR ${t.authKind} IN ('signin', 'signup'))
16191
+ AND (${t.failureCode} IS NULL OR ${t.failureCode} IN ('access_denied', 'provider_error', 'oauth_callback_failed', 'start_failed', 'invalid_handoff'))`),
16192
+ check2("ck_native_oauth_attempt_redirect", sql`length(${t.redirectPath}) BETWEEN 1 AND 2048
16193
+ AND substr(${t.redirectPath}, 1, 1) = '/'
16194
+ AND substr(${t.redirectPath}, 1, 2) <> '//'
16195
+ AND instr(${t.redirectPath}, char(92)) = 0`),
16196
+ check2("ck_native_oauth_attempt_epochs", sql`typeof(${t.createdAt}) = 'integer' AND ${t.createdAt} BETWEEN 0 AND 9007199254740991
16197
+ AND typeof(${t.updatedAt}) = 'integer' AND ${t.updatedAt} BETWEEN ${t.createdAt} AND 9007199254740991
16198
+ AND typeof(${t.attemptExpiresAt}) = 'integer' AND ${t.attemptExpiresAt} = ${t.createdAt} + 600000
16199
+ AND (${t.handoffExpiresAt} IS NULL OR (typeof(${t.handoffExpiresAt}) = 'integer' AND ${t.handoffExpiresAt} <= ${t.attemptExpiresAt}))`),
16200
+ check2("ck_native_oauth_attempt_state", sql`(
16201
+ ${t.status} = 'pending'
16202
+ AND ${t.openedAt} IS NULL AND ${t.readyAt} IS NULL AND ${t.consumedAt} IS NULL
16203
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16204
+ AND ${t.handoffCodeHash} IS NULL AND ${t.handoffExpiresAt} IS NULL
16205
+ AND ${t.authKind} IS NULL AND ${t.failureCode} IS NULL
16206
+ ) OR (
16207
+ ${t.status} = 'opened'
16208
+ AND ${t.openedAt} IS NOT NULL AND ${t.readyAt} IS NULL AND ${t.consumedAt} IS NULL
16209
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16210
+ AND ${t.handoffCodeHash} IS NULL AND ${t.handoffExpiresAt} IS NULL
16211
+ AND ${t.authKind} IS NULL AND ${t.failureCode} IS NULL
16212
+ ) OR (
16213
+ ${t.status} IN ('ready', 'exchanging')
16214
+ AND ${t.openedAt} IS NOT NULL AND ${t.readyAt} IS NOT NULL AND ${t.consumedAt} IS NULL
16215
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16216
+ AND ${t.handoffCodeHash} IS NOT NULL AND ${t.handoffExpiresAt} IS NOT NULL
16217
+ AND ${t.handoffExpiresAt} = ${t.readyAt} + 120000
16218
+ AND ${t.authKind} IS NOT NULL AND ${t.failureCode} IS NULL
16219
+ ) OR (
16220
+ ${t.status} = 'consumed'
16221
+ AND ${t.openedAt} IS NOT NULL AND ${t.readyAt} IS NOT NULL AND ${t.consumedAt} IS NOT NULL
16222
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16223
+ AND ${t.handoffCodeHash} IS NOT NULL AND ${t.handoffExpiresAt} IS NOT NULL
16224
+ AND ${t.authKind} IS NOT NULL AND ${t.failureCode} IS NULL
16225
+ ) OR (
16226
+ ${t.status} = 'failed'
16227
+ AND ${t.consumedAt} IS NULL AND ${t.failedAt} IS NOT NULL
16228
+ AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16229
+ AND ${t.failureCode} IS NOT NULL
16230
+ ) OR (
16231
+ ${t.status} = 'cancelled'
16232
+ AND ${t.consumedAt} IS NULL AND ${t.cancelledAt} IS NOT NULL
16233
+ AND ${t.failedAt} IS NULL AND ${t.replacedAt} IS NULL
16234
+ AND ${t.failureCode} IS NULL
16235
+ ) OR (
16236
+ ${t.status} = 'replaced'
16237
+ AND ${t.consumedAt} IS NULL AND ${t.replacedAt} IS NOT NULL
16238
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL
16239
+ AND ${t.failureCode} IS NULL
16240
+ )`)
16241
+ ]);
16124
16242
  var workspace = sqliteTable("workspace", {
16125
16243
  id: text("id").primaryKey().$defaultFn(() => "sp_" + nanoid3()),
16126
16244
  name: text("name").notNull(),
@@ -18337,6 +18455,15 @@ function createLogger(opts) {
18337
18455
 
18338
18456
  // ../shared/src/db/queries/_chunk.ts
18339
18457
  var D1_MAX_BIND_PARAMS = 100;
18458
+ function maxInParams(fixedParams) {
18459
+ if (!Number.isInteger(fixedParams) || fixedParams < 0) {
18460
+ throw new Error("fixed params must be a non-negative integer");
18461
+ }
18462
+ if (fixedParams >= D1_MAX_BIND_PARAMS) {
18463
+ throw new Error("fixed params must leave room for at least one IN parameter");
18464
+ }
18465
+ return D1_MAX_BIND_PARAMS - fixedParams;
18466
+ }
18340
18467
  function maxRowsPerInsert(paramsPerRow) {
18341
18468
  if (paramsPerRow < 1)
18342
18469
  throw new Error("paramsPerRow must be >= 1");
@@ -18428,6 +18555,7 @@ var AGENT_MESSAGE_COLUMNS = {
18428
18555
  replyToId: communityMessage.replyToId
18429
18556
  };
18430
18557
  var channelJoinBaselineGuard = sql`${communityMessage.createdAt} > COALESCE(${communityChannelMember.addedAt}, ${communityServerMember.joinedAt}, '')`;
18558
+ var AGENT_UNREAD_CHANNEL_CHUNK_SIZE = maxInParams(13);
18431
18559
 
18432
18560
  // ../shared/src/db/queries/community/mention.ts
18433
18561
  var MENTION_INSERT_MAX_ROWS = maxRowsPerInsert(5);
@@ -19040,6 +19168,10 @@ var serverRailCommandSchema = exports_external.discriminatedUnion("kind", [
19040
19168
  var serverRailCommitRequestSchema = exports_external.strictObject({
19041
19169
  commands: exports_external.array(serverRailCommandSchema).min(1).max(MAX_SERVER_RAIL_COMMANDS)
19042
19170
  });
19171
+ // ../shared/src/db/queries/native-oauth.ts
19172
+ var ATTEMPT_TTL_MS = 10 * 60 * 1000;
19173
+ var HANDOFF_TTL_MS = 2 * 60 * 1000;
19174
+ var RETENTION_MS = 24 * 60 * 60 * 1000;
19043
19175
  // ../shared/src/db/queries/task.ts
19044
19176
  var DEFAULT_STALE_SECONDS = Number(process.env.ALOOK_STALE_DISPATCH_TIMEOUT_S) || 20;
19045
19177
  var DEFAULT_STALE_RUNNING_SECONDS = Number(process.env.ALOOK_STALE_RUNNING_TIMEOUT_S) || 3600;
@@ -19071,6 +19203,80 @@ var FTS_KEYWORDS = new Set(["and", "or", "not", "near"]);
19071
19203
  var FOLDER_ITEM_INSERT_MAX_ROWS = maxRowsPerInsert(3);
19072
19204
  // ../shared/src/db/queries/community/diagnostic-report.ts
19073
19205
  var diagnosticOwner = alias(user, "diagnostic_owner");
19206
+ // ../shared/src/lib/safe-redirect.ts
19207
+ var MAX_REDIRECT_BYTES = 2048;
19208
+ var CONTROL_CHARACTERS = /[\u0000-\u001f\u007f]/;
19209
+ function isSafeCandidate(value) {
19210
+ return value.startsWith("/") && !value.startsWith("//") && !value.includes("\\") && !value.includes("#") && !CONTROL_CHARACTERS.test(value);
19211
+ }
19212
+ function isSafeRedirectPath(value) {
19213
+ if (new TextEncoder().encode(value).byteLength > MAX_REDIRECT_BYTES)
19214
+ return false;
19215
+ if (!isSafeCandidate(value))
19216
+ return false;
19217
+ let decoded = value;
19218
+ for (let depth = 0;depth < 8; depth += 1) {
19219
+ let next;
19220
+ try {
19221
+ next = decodeURIComponent(decoded);
19222
+ } catch {
19223
+ return depth > 0;
19224
+ }
19225
+ if (next === decoded)
19226
+ break;
19227
+ if (!isSafeCandidate(next))
19228
+ return false;
19229
+ decoded = next;
19230
+ if (depth === 7)
19231
+ return false;
19232
+ }
19233
+ try {
19234
+ const base = new URL("https://alook.invalid");
19235
+ const resolved = new URL(value, base);
19236
+ return resolved.origin === base.origin;
19237
+ } catch {
19238
+ return false;
19239
+ }
19240
+ }
19241
+
19242
+ // ../shared/src/lib/native-oauth-contract.ts
19243
+ var ATTEMPT_ID = /^[A-Za-z0-9_-]{22,64}$/;
19244
+ var SHA256_HEX = /^[0-9a-f]{64}$/;
19245
+ var BASE64URL_32_BYTES = /^[A-Za-z0-9_-]{43}$/;
19246
+ var HANDOFF_CODE = /^[A-Za-z0-9_-]{32,128}$/;
19247
+ var nativeOauthProviderSchema = exports_external.enum(["github", "google"]);
19248
+ var nativeOauthPlatformSchema = exports_external.enum([
19249
+ "macos",
19250
+ "windows",
19251
+ "linux",
19252
+ "ios",
19253
+ "android"
19254
+ ]);
19255
+ var nativeOauthAttemptIdSchema = exports_external.string().regex(ATTEMPT_ID);
19256
+ var nativeOauthHandoffCodeSchema = exports_external.string().regex(HANDOFF_CODE);
19257
+ var nativeOauthFailureCodeSchema = exports_external.enum([
19258
+ "access_denied",
19259
+ "provider_error",
19260
+ "oauth_callback_failed",
19261
+ "start_failed",
19262
+ "invalid_handoff"
19263
+ ]);
19264
+ var nativeOauthRegistrationSchema = exports_external.object({
19265
+ attemptId: nativeOauthAttemptIdSchema,
19266
+ stateHash: exports_external.string().regex(SHA256_HEX),
19267
+ codeChallenge: exports_external.string().regex(BASE64URL_32_BYTES),
19268
+ instanceKeyHash: exports_external.string().regex(SHA256_HEX),
19269
+ platform: nativeOauthPlatformSchema,
19270
+ provider: nativeOauthProviderSchema,
19271
+ redirectPath: exports_external.string().refine(isSafeRedirectPath)
19272
+ }).strict();
19273
+ var nativeOauthExchangeSchema = exports_external.object({
19274
+ attemptId: nativeOauthAttemptIdSchema,
19275
+ state: exports_external.string().regex(BASE64URL_32_BYTES),
19276
+ verifier: exports_external.string().regex(BASE64URL_32_BYTES),
19277
+ code: nativeOauthHandoffCodeSchema
19278
+ }).strict();
19279
+ var nativeOauthProofSchema = nativeOauthExchangeSchema.omit({ code: true }).strict();
19074
19280
  // ../shared/src/semver.ts
19075
19281
  function semverGte(a, b) {
19076
19282
  const pa = a.split(".").map(Number);
@@ -15869,6 +15869,7 @@ __export(exports_schema, {
15869
15869
  user: () => user,
15870
15870
  taskMessage: () => taskMessage,
15871
15871
  session: () => session,
15872
+ nativeOauthAttempt: () => nativeOauthAttempt,
15872
15873
  messageFlag: () => messageFlag,
15873
15874
  message: () => message,
15874
15875
  member: () => member,
@@ -15895,7 +15896,11 @@ __export(exports_schema, {
15895
15896
  agentEmailAccount: () => agentEmailAccount,
15896
15897
  agentAccess: () => agentAccess,
15897
15898
  agent: () => agent,
15898
- account: () => account
15899
+ account: () => account,
15900
+ NATIVE_OAUTH_STATUSES: () => NATIVE_OAUTH_STATUSES,
15901
+ NATIVE_OAUTH_PROVIDERS: () => NATIVE_OAUTH_PROVIDERS,
15902
+ NATIVE_OAUTH_PLATFORMS: () => NATIVE_OAUTH_PLATFORMS,
15903
+ NATIVE_OAUTH_FAILURE_CODES: () => NATIVE_OAUTH_FAILURE_CODES
15899
15904
  });
15900
15905
  init_nanoid();
15901
15906
 
@@ -16026,6 +16031,119 @@ var verification = sqliteTable("verification", {
16026
16031
  createdAt: text("createdAt").notNull().$defaultFn(() => new Date().toISOString()),
16027
16032
  updatedAt: text("updatedAt").notNull().$defaultFn(() => new Date().toISOString())
16028
16033
  });
16034
+ var NATIVE_OAUTH_PROVIDERS = ["github", "google"];
16035
+ var NATIVE_OAUTH_PLATFORMS = [
16036
+ "macos",
16037
+ "windows",
16038
+ "linux",
16039
+ "ios",
16040
+ "android"
16041
+ ];
16042
+ var NATIVE_OAUTH_STATUSES = [
16043
+ "pending",
16044
+ "opened",
16045
+ "ready",
16046
+ "exchanging",
16047
+ "consumed",
16048
+ "failed",
16049
+ "cancelled",
16050
+ "replaced"
16051
+ ];
16052
+ var NATIVE_OAUTH_FAILURE_CODES = [
16053
+ "access_denied",
16054
+ "provider_error",
16055
+ "oauth_callback_failed",
16056
+ "start_failed",
16057
+ "invalid_handoff"
16058
+ ];
16059
+ var nativeOauthAttempt = sqliteTable("native_oauth_attempt", {
16060
+ id: text("id").primaryKey(),
16061
+ instanceKeyHash: text("instance_key_hash").notNull(),
16062
+ stateHash: text("state_hash").notNull(),
16063
+ pkceChallenge: text("pkce_challenge").notNull(),
16064
+ provider: text("provider").$type().notNull(),
16065
+ platform: text("platform").$type().notNull(),
16066
+ redirectPath: text("redirect_path").notNull(),
16067
+ status: text("status").$type().notNull().default("pending"),
16068
+ handoffCodeHash: text("handoff_code_hash"),
16069
+ handoffExpiresAt: integer2("handoff_expires_at"),
16070
+ authKind: text("auth_kind").$type(),
16071
+ failureCode: text("failure_code").$type(),
16072
+ attemptExpiresAt: integer2("attempt_expires_at").notNull(),
16073
+ createdAt: integer2("created_at").notNull(),
16074
+ updatedAt: integer2("updated_at").notNull(),
16075
+ openedAt: integer2("opened_at"),
16076
+ readyAt: integer2("ready_at"),
16077
+ consumedAt: integer2("consumed_at"),
16078
+ failedAt: integer2("failed_at"),
16079
+ cancelledAt: integer2("cancelled_at"),
16080
+ replacedAt: integer2("replaced_at")
16081
+ }, (t) => [
16082
+ index("idx_native_oauth_attempt_instance_status").on(t.instanceKeyHash, t.status),
16083
+ index("idx_native_oauth_attempt_id_status_expiry").on(t.id, t.status, t.attemptExpiresAt),
16084
+ index("idx_native_oauth_attempt_terminal_cleanup").on(t.status, t.updatedAt),
16085
+ uniqueIndex("uq_native_oauth_attempt_instance_live").on(t.instanceKeyHash).where(sql`status IN ('pending', 'opened', 'ready', 'exchanging')`),
16086
+ uniqueIndex("uq_native_oauth_attempt_handoff_hash").on(t.handoffCodeHash).where(sql`handoff_code_hash IS NOT NULL`),
16087
+ check2("ck_native_oauth_attempt_id", sql`length(${t.id}) BETWEEN 22 AND 64 AND ${t.id} NOT GLOB '*[^A-Za-z0-9_-]*'`),
16088
+ check2("ck_native_oauth_attempt_hashes", sql`length(${t.instanceKeyHash}) = 64 AND ${t.instanceKeyHash} NOT GLOB '*[^0-9a-f]*'
16089
+ AND length(${t.stateHash}) = 64 AND ${t.stateHash} NOT GLOB '*[^0-9a-f]*'
16090
+ AND length(${t.pkceChallenge}) = 43 AND ${t.pkceChallenge} NOT GLOB '*[^A-Za-z0-9_-]*'
16091
+ AND (${t.handoffCodeHash} IS NULL OR (length(${t.handoffCodeHash}) = 64 AND ${t.handoffCodeHash} NOT GLOB '*[^0-9a-f]*'))`),
16092
+ check2("ck_native_oauth_attempt_enums", sql`${t.provider} IN ('github', 'google')
16093
+ AND ${t.platform} IN ('macos', 'windows', 'linux', 'ios', 'android')
16094
+ AND ${t.status} IN ('pending', 'opened', 'ready', 'exchanging', 'consumed', 'failed', 'cancelled', 'replaced')
16095
+ AND (${t.authKind} IS NULL OR ${t.authKind} IN ('signin', 'signup'))
16096
+ AND (${t.failureCode} IS NULL OR ${t.failureCode} IN ('access_denied', 'provider_error', 'oauth_callback_failed', 'start_failed', 'invalid_handoff'))`),
16097
+ check2("ck_native_oauth_attempt_redirect", sql`length(${t.redirectPath}) BETWEEN 1 AND 2048
16098
+ AND substr(${t.redirectPath}, 1, 1) = '/'
16099
+ AND substr(${t.redirectPath}, 1, 2) <> '//'
16100
+ AND instr(${t.redirectPath}, char(92)) = 0`),
16101
+ check2("ck_native_oauth_attempt_epochs", sql`typeof(${t.createdAt}) = 'integer' AND ${t.createdAt} BETWEEN 0 AND 9007199254740991
16102
+ AND typeof(${t.updatedAt}) = 'integer' AND ${t.updatedAt} BETWEEN ${t.createdAt} AND 9007199254740991
16103
+ AND typeof(${t.attemptExpiresAt}) = 'integer' AND ${t.attemptExpiresAt} = ${t.createdAt} + 600000
16104
+ AND (${t.handoffExpiresAt} IS NULL OR (typeof(${t.handoffExpiresAt}) = 'integer' AND ${t.handoffExpiresAt} <= ${t.attemptExpiresAt}))`),
16105
+ check2("ck_native_oauth_attempt_state", sql`(
16106
+ ${t.status} = 'pending'
16107
+ AND ${t.openedAt} IS NULL AND ${t.readyAt} IS NULL AND ${t.consumedAt} IS NULL
16108
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16109
+ AND ${t.handoffCodeHash} IS NULL AND ${t.handoffExpiresAt} IS NULL
16110
+ AND ${t.authKind} IS NULL AND ${t.failureCode} IS NULL
16111
+ ) OR (
16112
+ ${t.status} = 'opened'
16113
+ AND ${t.openedAt} IS NOT NULL AND ${t.readyAt} IS NULL AND ${t.consumedAt} IS NULL
16114
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16115
+ AND ${t.handoffCodeHash} IS NULL AND ${t.handoffExpiresAt} IS NULL
16116
+ AND ${t.authKind} IS NULL AND ${t.failureCode} IS NULL
16117
+ ) OR (
16118
+ ${t.status} IN ('ready', 'exchanging')
16119
+ AND ${t.openedAt} IS NOT NULL AND ${t.readyAt} IS NOT NULL AND ${t.consumedAt} IS NULL
16120
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16121
+ AND ${t.handoffCodeHash} IS NOT NULL AND ${t.handoffExpiresAt} IS NOT NULL
16122
+ AND ${t.handoffExpiresAt} = ${t.readyAt} + 120000
16123
+ AND ${t.authKind} IS NOT NULL AND ${t.failureCode} IS NULL
16124
+ ) OR (
16125
+ ${t.status} = 'consumed'
16126
+ AND ${t.openedAt} IS NOT NULL AND ${t.readyAt} IS NOT NULL AND ${t.consumedAt} IS NOT NULL
16127
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16128
+ AND ${t.handoffCodeHash} IS NOT NULL AND ${t.handoffExpiresAt} IS NOT NULL
16129
+ AND ${t.authKind} IS NOT NULL AND ${t.failureCode} IS NULL
16130
+ ) OR (
16131
+ ${t.status} = 'failed'
16132
+ AND ${t.consumedAt} IS NULL AND ${t.failedAt} IS NOT NULL
16133
+ AND ${t.cancelledAt} IS NULL AND ${t.replacedAt} IS NULL
16134
+ AND ${t.failureCode} IS NOT NULL
16135
+ ) OR (
16136
+ ${t.status} = 'cancelled'
16137
+ AND ${t.consumedAt} IS NULL AND ${t.cancelledAt} IS NOT NULL
16138
+ AND ${t.failedAt} IS NULL AND ${t.replacedAt} IS NULL
16139
+ AND ${t.failureCode} IS NULL
16140
+ ) OR (
16141
+ ${t.status} = 'replaced'
16142
+ AND ${t.consumedAt} IS NULL AND ${t.replacedAt} IS NOT NULL
16143
+ AND ${t.failedAt} IS NULL AND ${t.cancelledAt} IS NULL
16144
+ AND ${t.failureCode} IS NULL
16145
+ )`)
16146
+ ]);
16029
16147
  var workspace = sqliteTable("workspace", {
16030
16148
  id: text("id").primaryKey().$defaultFn(() => "sp_" + nanoid3()),
16031
16149
  name: text("name").notNull(),
@@ -18241,6 +18359,15 @@ function createLogger(opts) {
18241
18359
 
18242
18360
  // ../shared/src/db/queries/_chunk.ts
18243
18361
  var D1_MAX_BIND_PARAMS = 100;
18362
+ function maxInParams(fixedParams) {
18363
+ if (!Number.isInteger(fixedParams) || fixedParams < 0) {
18364
+ throw new Error("fixed params must be a non-negative integer");
18365
+ }
18366
+ if (fixedParams >= D1_MAX_BIND_PARAMS) {
18367
+ throw new Error("fixed params must leave room for at least one IN parameter");
18368
+ }
18369
+ return D1_MAX_BIND_PARAMS - fixedParams;
18370
+ }
18244
18371
  function maxRowsPerInsert(paramsPerRow) {
18245
18372
  if (paramsPerRow < 1)
18246
18373
  throw new Error("paramsPerRow must be >= 1");
@@ -18332,6 +18459,7 @@ var AGENT_MESSAGE_COLUMNS = {
18332
18459
  replyToId: communityMessage.replyToId
18333
18460
  };
18334
18461
  var channelJoinBaselineGuard = sql`${communityMessage.createdAt} > COALESCE(${communityChannelMember.addedAt}, ${communityServerMember.joinedAt}, '')`;
18462
+ var AGENT_UNREAD_CHANNEL_CHUNK_SIZE = maxInParams(13);
18335
18463
 
18336
18464
  // ../shared/src/db/queries/community/mention.ts
18337
18465
  var MENTION_INSERT_MAX_ROWS = maxRowsPerInsert(5);
@@ -18944,6 +19072,10 @@ var serverRailCommandSchema = exports_external.discriminatedUnion("kind", [
18944
19072
  var serverRailCommitRequestSchema = exports_external.strictObject({
18945
19073
  commands: exports_external.array(serverRailCommandSchema).min(1).max(MAX_SERVER_RAIL_COMMANDS)
18946
19074
  });
19075
+ // ../shared/src/db/queries/native-oauth.ts
19076
+ var ATTEMPT_TTL_MS = 10 * 60 * 1000;
19077
+ var HANDOFF_TTL_MS = 2 * 60 * 1000;
19078
+ var RETENTION_MS = 24 * 60 * 60 * 1000;
18947
19079
  // ../shared/src/db/queries/task.ts
18948
19080
  var DEFAULT_STALE_SECONDS = Number(process.env.ALOOK_STALE_DISPATCH_TIMEOUT_S) || 20;
18949
19081
  var DEFAULT_STALE_RUNNING_SECONDS = Number(process.env.ALOOK_STALE_RUNNING_TIMEOUT_S) || 3600;
@@ -18975,6 +19107,80 @@ var FTS_KEYWORDS = new Set(["and", "or", "not", "near"]);
18975
19107
  var FOLDER_ITEM_INSERT_MAX_ROWS = maxRowsPerInsert(3);
18976
19108
  // ../shared/src/db/queries/community/diagnostic-report.ts
18977
19109
  var diagnosticOwner = alias(user, "diagnostic_owner");
19110
+ // ../shared/src/lib/safe-redirect.ts
19111
+ var MAX_REDIRECT_BYTES = 2048;
19112
+ var CONTROL_CHARACTERS = /[\u0000-\u001f\u007f]/;
19113
+ function isSafeCandidate(value) {
19114
+ return value.startsWith("/") && !value.startsWith("//") && !value.includes("\\") && !value.includes("#") && !CONTROL_CHARACTERS.test(value);
19115
+ }
19116
+ function isSafeRedirectPath(value) {
19117
+ if (new TextEncoder().encode(value).byteLength > MAX_REDIRECT_BYTES)
19118
+ return false;
19119
+ if (!isSafeCandidate(value))
19120
+ return false;
19121
+ let decoded = value;
19122
+ for (let depth = 0;depth < 8; depth += 1) {
19123
+ let next;
19124
+ try {
19125
+ next = decodeURIComponent(decoded);
19126
+ } catch {
19127
+ return depth > 0;
19128
+ }
19129
+ if (next === decoded)
19130
+ break;
19131
+ if (!isSafeCandidate(next))
19132
+ return false;
19133
+ decoded = next;
19134
+ if (depth === 7)
19135
+ return false;
19136
+ }
19137
+ try {
19138
+ const base = new URL("https://alook.invalid");
19139
+ const resolved = new URL(value, base);
19140
+ return resolved.origin === base.origin;
19141
+ } catch {
19142
+ return false;
19143
+ }
19144
+ }
19145
+
19146
+ // ../shared/src/lib/native-oauth-contract.ts
19147
+ var ATTEMPT_ID = /^[A-Za-z0-9_-]{22,64}$/;
19148
+ var SHA256_HEX = /^[0-9a-f]{64}$/;
19149
+ var BASE64URL_32_BYTES = /^[A-Za-z0-9_-]{43}$/;
19150
+ var HANDOFF_CODE = /^[A-Za-z0-9_-]{32,128}$/;
19151
+ var nativeOauthProviderSchema = exports_external.enum(["github", "google"]);
19152
+ var nativeOauthPlatformSchema = exports_external.enum([
19153
+ "macos",
19154
+ "windows",
19155
+ "linux",
19156
+ "ios",
19157
+ "android"
19158
+ ]);
19159
+ var nativeOauthAttemptIdSchema = exports_external.string().regex(ATTEMPT_ID);
19160
+ var nativeOauthHandoffCodeSchema = exports_external.string().regex(HANDOFF_CODE);
19161
+ var nativeOauthFailureCodeSchema = exports_external.enum([
19162
+ "access_denied",
19163
+ "provider_error",
19164
+ "oauth_callback_failed",
19165
+ "start_failed",
19166
+ "invalid_handoff"
19167
+ ]);
19168
+ var nativeOauthRegistrationSchema = exports_external.object({
19169
+ attemptId: nativeOauthAttemptIdSchema,
19170
+ stateHash: exports_external.string().regex(SHA256_HEX),
19171
+ codeChallenge: exports_external.string().regex(BASE64URL_32_BYTES),
19172
+ instanceKeyHash: exports_external.string().regex(SHA256_HEX),
19173
+ platform: nativeOauthPlatformSchema,
19174
+ provider: nativeOauthProviderSchema,
19175
+ redirectPath: exports_external.string().refine(isSafeRedirectPath)
19176
+ }).strict();
19177
+ var nativeOauthExchangeSchema = exports_external.object({
19178
+ attemptId: nativeOauthAttemptIdSchema,
19179
+ state: exports_external.string().regex(BASE64URL_32_BYTES),
19180
+ verifier: exports_external.string().regex(BASE64URL_32_BYTES),
19181
+ code: nativeOauthHandoffCodeSchema
19182
+ }).strict();
19183
+ var nativeOauthProofSchema = nativeOauthExchangeSchema.omit({ code: true }).strict();
18978
19184
  // ../shared/src/mode.ts
18979
19185
  function isLocalUrl(url2) {
18980
19186
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alook/cli",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "description": "Alook CLI — Enable Your Person Colleague",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/alookai/alook#readme",