@alook/cli 0.0.92 → 0.0.93

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
@@ -14923,6 +14923,21 @@ var WorkspaceFileReportSchema = exports_external.object({
14923
14923
  error: exports_external.string().optional(),
14924
14924
  path: exports_external.string()
14925
14925
  });
14926
+ var SkillEntrySchema = exports_external.object({
14927
+ name: exports_external.string(),
14928
+ description: exports_external.string(),
14929
+ isGlobal: exports_external.boolean().optional()
14930
+ });
14931
+ var SkillItemSchema = exports_external.object({
14932
+ name: exports_external.string(),
14933
+ description: exports_external.string()
14934
+ });
14935
+ var SkillSyncRequestSchema = exports_external.object({
14936
+ scope: exports_external.enum(["global", "agent"]),
14937
+ agent_id: exports_external.string().min(1).optional(),
14938
+ runtime: exports_external.enum(["claude", "codex", "opencode"]),
14939
+ skills: exports_external.array(SkillItemSchema)
14940
+ });
14926
14941
  var StudioMemberSchema = exports_external.object({
14927
14942
  name: exports_external.string().optional(),
14928
14943
  role: exports_external.enum(["leader", "researcher", "engineer", "assistant"]),
@@ -14938,7 +14953,7 @@ var CreateStudioRequestSchema = exports_external.object({
14938
14953
  scenario: exports_external.string().max(50).optional(),
14939
14954
  members: exports_external.array(StudioMemberSchema).min(1).max(4)
14940
14955
  }).refine((v) => v.members.some((m) => m.role === "leader"), { message: "at least one member must have the leader role" });
14941
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/entity.js
14956
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/entity.js
14942
14957
  var entityKind = Symbol.for("drizzle:entityKind");
14943
14958
  var hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
14944
14959
  function is(value, type) {
@@ -14963,10 +14978,10 @@ function is(value, type) {
14963
14978
  return false;
14964
14979
  }
14965
14980
 
14966
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/table.utils.js
14981
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/table.utils.js
14967
14982
  var TableName = Symbol.for("drizzle:Name");
14968
14983
 
14969
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/table.js
14984
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/table.js
14970
14985
  var Schema = Symbol.for("drizzle:Schema");
14971
14986
  var Columns = Symbol.for("drizzle:Columns");
14972
14987
  var ExtraConfigColumns = Symbol.for("drizzle:ExtraConfigColumns");
@@ -15004,7 +15019,7 @@ class Table {
15004
15019
  }
15005
15020
  }
15006
15021
 
15007
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/column.js
15022
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/column.js
15008
15023
  class Column {
15009
15024
  constructor(table, config2) {
15010
15025
  this.table = table;
@@ -15054,7 +15069,7 @@ class Column {
15054
15069
  }
15055
15070
  }
15056
15071
 
15057
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/column-builder.js
15072
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/column-builder.js
15058
15073
  class ColumnBuilder {
15059
15074
  static [entityKind] = "ColumnBuilder";
15060
15075
  config;
@@ -15110,17 +15125,17 @@ class ColumnBuilder {
15110
15125
  }
15111
15126
  }
15112
15127
 
15113
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/tracing-utils.js
15128
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/tracing-utils.js
15114
15129
  function iife(fn, ...args) {
15115
15130
  return fn(...args);
15116
15131
  }
15117
15132
 
15118
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/pg-core/unique-constraint.js
15133
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/pg-core/unique-constraint.js
15119
15134
  function uniqueKeyName(table, columns) {
15120
15135
  return `${table[TableName]}_${columns.join("_")}_unique`;
15121
15136
  }
15122
15137
 
15123
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/pg-core/columns/common.js
15138
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/pg-core/columns/common.js
15124
15139
  class PgColumn extends Column {
15125
15140
  constructor(table, config2) {
15126
15141
  if (!config2.uniqueName) {
@@ -15169,7 +15184,7 @@ class ExtraConfigColumn extends PgColumn {
15169
15184
  }
15170
15185
  }
15171
15186
 
15172
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/pg-core/columns/enum.js
15187
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/pg-core/columns/enum.js
15173
15188
  class PgEnumObjectColumn extends PgColumn {
15174
15189
  static [entityKind] = "PgEnumObjectColumn";
15175
15190
  enum;
@@ -15199,7 +15214,7 @@ class PgEnumColumn extends PgColumn {
15199
15214
  }
15200
15215
  }
15201
15216
 
15202
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/subquery.js
15217
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/subquery.js
15203
15218
  class Subquery {
15204
15219
  static [entityKind] = "Subquery";
15205
15220
  constructor(sql, fields, alias, isWith = false, usedTables = []) {
@@ -15214,10 +15229,10 @@ class Subquery {
15214
15229
  }
15215
15230
  }
15216
15231
 
15217
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/version.js
15232
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/version.js
15218
15233
  var version2 = "0.45.2";
15219
15234
 
15220
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/tracing.js
15235
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/tracing.js
15221
15236
  var otel;
15222
15237
  var rawTracer;
15223
15238
  var tracer = {
@@ -15244,10 +15259,10 @@ var tracer = {
15244
15259
  }
15245
15260
  };
15246
15261
 
15247
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/view-common.js
15262
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/view-common.js
15248
15263
  var ViewBaseConfig = Symbol.for("drizzle:ViewBaseConfig");
15249
15264
 
15250
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sql/sql.js
15265
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sql/sql.js
15251
15266
  function isSQLWrapper(value) {
15252
15267
  return value !== null && value !== undefined && typeof value.getSQL === "function";
15253
15268
  }
@@ -15607,7 +15622,7 @@ Subquery.prototype.getSQL = function() {
15607
15622
  return new SQL([this]);
15608
15623
  };
15609
15624
 
15610
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/utils.js
15625
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/utils.js
15611
15626
  function getColumnNameAndConfig(a, b) {
15612
15627
  return {
15613
15628
  name: typeof a === "string" && a.length > 0 ? a : "",
@@ -15616,7 +15631,7 @@ function getColumnNameAndConfig(a, b) {
15616
15631
  }
15617
15632
  var textDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder;
15618
15633
 
15619
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/foreign-keys.js
15634
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/foreign-keys.js
15620
15635
  class ForeignKeyBuilder {
15621
15636
  static [entityKind] = "SQLiteForeignKeyBuilder";
15622
15637
  reference;
@@ -15684,7 +15699,7 @@ function foreignKey(config2) {
15684
15699
  return new ForeignKeyBuilder(mappedConfig);
15685
15700
  }
15686
15701
 
15687
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/unique-constraint.js
15702
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/unique-constraint.js
15688
15703
  function uniqueKeyName2(table, columns) {
15689
15704
  return `${table[TableName]}_${columns.join("_")}_unique`;
15690
15705
  }
@@ -15729,7 +15744,7 @@ class UniqueConstraint {
15729
15744
  }
15730
15745
  }
15731
15746
 
15732
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/common.js
15747
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/common.js
15733
15748
  class SQLiteColumnBuilder extends ColumnBuilder {
15734
15749
  static [entityKind] = "SQLiteColumnBuilder";
15735
15750
  foreignKeyConfigs = [];
@@ -15780,7 +15795,7 @@ class SQLiteColumn extends Column {
15780
15795
  static [entityKind] = "SQLiteColumn";
15781
15796
  }
15782
15797
 
15783
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/blob.js
15798
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/blob.js
15784
15799
  class SQLiteBigIntBuilder extends SQLiteColumnBuilder {
15785
15800
  static [entityKind] = "SQLiteBigIntBuilder";
15786
15801
  constructor(name) {
@@ -15868,7 +15883,7 @@ function blob(a, b) {
15868
15883
  return new SQLiteBlobBufferBuilder(name);
15869
15884
  }
15870
15885
 
15871
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/custom.js
15886
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/custom.js
15872
15887
  class SQLiteCustomColumnBuilder extends SQLiteColumnBuilder {
15873
15888
  static [entityKind] = "SQLiteCustomColumnBuilder";
15874
15889
  constructor(name, fieldConfig, customTypeParams) {
@@ -15909,7 +15924,7 @@ function customType(customTypeParams) {
15909
15924
  };
15910
15925
  }
15911
15926
 
15912
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/integer.js
15927
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/integer.js
15913
15928
  class SQLiteBaseIntegerBuilder extends SQLiteColumnBuilder {
15914
15929
  static [entityKind] = "SQLiteBaseIntegerBuilder";
15915
15930
  constructor(name, dataType, columnType) {
@@ -16011,7 +16026,7 @@ function integer2(a, b) {
16011
16026
  return new SQLiteIntegerBuilder(name);
16012
16027
  }
16013
16028
 
16014
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/numeric.js
16029
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/numeric.js
16015
16030
  class SQLiteNumericBuilder extends SQLiteColumnBuilder {
16016
16031
  static [entityKind] = "SQLiteNumericBuilder";
16017
16032
  constructor(name) {
@@ -16081,7 +16096,7 @@ function numeric(a, b) {
16081
16096
  return mode === "number" ? new SQLiteNumericNumberBuilder(name) : mode === "bigint" ? new SQLiteNumericBigIntBuilder(name) : new SQLiteNumericBuilder(name);
16082
16097
  }
16083
16098
 
16084
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/real.js
16099
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/real.js
16085
16100
  class SQLiteRealBuilder extends SQLiteColumnBuilder {
16086
16101
  static [entityKind] = "SQLiteRealBuilder";
16087
16102
  constructor(name) {
@@ -16102,7 +16117,7 @@ function real(name) {
16102
16117
  return new SQLiteRealBuilder(name ?? "");
16103
16118
  }
16104
16119
 
16105
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/text.js
16120
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/text.js
16106
16121
  class SQLiteTextBuilder extends SQLiteColumnBuilder {
16107
16122
  static [entityKind] = "SQLiteTextBuilder";
16108
16123
  constructor(name, config2) {
@@ -16157,7 +16172,7 @@ function text(a, b = {}) {
16157
16172
  return new SQLiteTextBuilder(name, config2);
16158
16173
  }
16159
16174
 
16160
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/all.js
16175
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/columns/all.js
16161
16176
  function getSQLiteColumnBuilders() {
16162
16177
  return {
16163
16178
  blob,
@@ -16169,7 +16184,7 @@ function getSQLiteColumnBuilders() {
16169
16184
  };
16170
16185
  }
16171
16186
 
16172
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/table.js
16187
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/table.js
16173
16188
  var InlineForeignKeys = Symbol.for("drizzle:SQLiteInlineForeignKeys");
16174
16189
 
16175
16190
  class SQLiteTable extends Table {
@@ -16203,7 +16218,7 @@ var sqliteTable = (name, columns, extraConfig) => {
16203
16218
  return sqliteTableBase(name, columns, extraConfig);
16204
16219
  };
16205
16220
 
16206
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/indexes.js
16221
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/indexes.js
16207
16222
  class IndexBuilderOn {
16208
16223
  constructor(name, unique2) {
16209
16224
  this.name = name;
@@ -16246,7 +16261,7 @@ function index(name) {
16246
16261
  return new IndexBuilderOn(name, false);
16247
16262
  }
16248
16263
 
16249
- // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260517.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/primary-keys.js
16264
+ // ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_bun-types@1.3.14_kysely@0.28.17/node_modules/drizzle-orm/sqlite-core/primary-keys.js
16250
16265
  function primaryKey(...config2) {
16251
16266
  if (config2[0].columns) {
16252
16267
  return new PrimaryKeyBuilder(config2[0].columns, config2[0].name);
@@ -16815,6 +16830,23 @@ var workspaceFileRequest = sqliteTable("workspace_file_request", {
16815
16830
  }, (t) => [
16816
16831
  index("idx_wfr_workspace_status").on(t.workspaceId, t.status)
16817
16832
  ]);
16833
+ var agentSkill = sqliteTable("agent_skill", {
16834
+ id: text("id").primaryKey().$defaultFn(() => "as_" + nanoid3()),
16835
+ workspaceId: text("workspace_id").notNull().references(() => workspace.id, { onDelete: "cascade" }),
16836
+ agentId: text("agent_id"),
16837
+ runtime: text("runtime").notNull(),
16838
+ name: text("name").notNull(),
16839
+ description: text("description").notNull().default(""),
16840
+ syncedAt: text("synced_at").notNull().$defaultFn(() => new Date().toISOString())
16841
+ }, (t) => [
16842
+ unique("agent_skill_ws_runtime_name_agent").on(t.workspaceId, t.runtime, t.name, t.agentId),
16843
+ index("idx_as_workspace_runtime").on(t.workspaceId, t.runtime),
16844
+ index("idx_as_agent_runtime").on(t.agentId, t.runtime),
16845
+ foreignKey({
16846
+ columns: [t.agentId, t.workspaceId],
16847
+ foreignColumns: [agent.id, agent.workspaceId]
16848
+ }).onDelete("cascade")
16849
+ ]);
16818
16850
  // ../shared/src/db/queries/task.ts
16819
16851
  var DEFAULT_STALE_SECONDS = Number(process.env.ALOOK_STALE_DISPATCH_TIMEOUT_S) || 20;
16820
16852
  var DEFAULT_STALE_RUNNING_SECONDS = Number(process.env.ALOOK_STALE_RUNNING_TIMEOUT_S) || 3600;
@@ -17319,7 +17351,7 @@ function statusCommand() {
17319
17351
  // commands/daemon.ts
17320
17352
  import { Command as Command3 } from "commander";
17321
17353
  import { spawn as spawn6 } from "child_process";
17322
- import { openSync as openSync2, closeSync as closeSync2, mkdirSync as mkdirSync8 } from "fs";
17354
+ import { openSync as openSync2, closeSync as closeSync2, mkdirSync as mkdirSync9 } from "fs";
17323
17355
  import { dirname as dirname4 } from "path";
17324
17356
 
17325
17357
  // daemon/client.ts
@@ -17439,6 +17471,9 @@ class DaemonClient {
17439
17471
  reportFileData(token, body) {
17440
17472
  return this.request("POST", "/api/daemon/workspace/report", token, body);
17441
17473
  }
17474
+ syncSkills(token, body) {
17475
+ return this.request("POST", "/api/daemon/skills/sync", token, body);
17476
+ }
17442
17477
  }
17443
17478
 
17444
17479
  // daemon/health.ts
@@ -20002,6 +20037,349 @@ function validatePath(agentWorkdir, requestedPath) {
20002
20037
  return resolved;
20003
20038
  }
20004
20039
 
20040
+ // daemon/skill-scanner.ts
20041
+ import { existsSync as existsSync2, mkdirSync as mkdirSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync7, readdirSync as readdirSync2, statSync as statSync3, realpathSync } from "fs";
20042
+ import { join as join10, basename } from "path";
20043
+ import { homedir as homedir2 } from "os";
20044
+ import { createHash as createHash2 } from "crypto";
20045
+ var log8 = createLogger2({ module: "skill-scanner" });
20046
+ function getCacheDir() {
20047
+ return join10(configDir(), "skills");
20048
+ }
20049
+ function parseFrontmatter(content) {
20050
+ const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
20051
+ if (!match)
20052
+ return null;
20053
+ const block = match[1];
20054
+ const nameMatch = block.match(/^name:\s*(.+)$/m);
20055
+ const descMatch = block.match(/^description:\s*(.+)$/m);
20056
+ if (!nameMatch)
20057
+ return null;
20058
+ return {
20059
+ name: nameMatch[1].trim().replace(/^["']|["']$/g, ""),
20060
+ description: descMatch ? descMatch[1].trim().replace(/^["']|["']$/g, "") : ""
20061
+ };
20062
+ }
20063
+ function safeReadDir(dir) {
20064
+ try {
20065
+ if (!existsSync2(dir))
20066
+ return [];
20067
+ return readdirSync2(dir);
20068
+ } catch {
20069
+ return [];
20070
+ }
20071
+ }
20072
+ function findSkillFiles(baseDir, pattern) {
20073
+ const results = [];
20074
+ if (!existsSync2(baseDir))
20075
+ return results;
20076
+ if (pattern === "*/SKILL.md") {
20077
+ for (const entry of safeReadDir(baseDir)) {
20078
+ const skillPath = join10(baseDir, entry, "SKILL.md");
20079
+ try {
20080
+ if (existsSync2(skillPath) && statSync3(skillPath).isFile()) {
20081
+ results.push(skillPath);
20082
+ }
20083
+ } catch {}
20084
+ }
20085
+ } else if (pattern === "**/skills/*/SKILL.md") {
20086
+ walkForSkills(baseDir, results);
20087
+ } else if (pattern === "*.md") {
20088
+ for (const entry of safeReadDir(baseDir)) {
20089
+ if (entry.endsWith(".md")) {
20090
+ const filePath = join10(baseDir, entry);
20091
+ try {
20092
+ if (statSync3(filePath).isFile()) {
20093
+ results.push(filePath);
20094
+ }
20095
+ } catch {}
20096
+ }
20097
+ }
20098
+ }
20099
+ return results;
20100
+ }
20101
+ function walkForSkills(dir, results, depth = 0) {
20102
+ if (depth > 5)
20103
+ return;
20104
+ try {
20105
+ for (const entry of readdirSync2(dir)) {
20106
+ const full = join10(dir, entry);
20107
+ try {
20108
+ const st = statSync3(full);
20109
+ if (st.isDirectory()) {
20110
+ if (entry === "skills") {
20111
+ for (const skillDir of safeReadDir(full)) {
20112
+ const skillPath = join10(full, skillDir, "SKILL.md");
20113
+ try {
20114
+ if (existsSync2(skillPath) && statSync3(skillPath).isFile()) {
20115
+ results.push(skillPath);
20116
+ }
20117
+ } catch {}
20118
+ }
20119
+ } else {
20120
+ walkForSkills(full, results, depth + 1);
20121
+ }
20122
+ }
20123
+ } catch {}
20124
+ }
20125
+ } catch {}
20126
+ }
20127
+ function scanFrontmatterSkills(paths) {
20128
+ const skills = new Map;
20129
+ for (const filePath of paths) {
20130
+ try {
20131
+ const content = readFileSync8(filePath, "utf-8");
20132
+ const meta3 = parseFrontmatter(content);
20133
+ if (meta3 && !skills.has(meta3.name)) {
20134
+ skills.set(meta3.name, meta3);
20135
+ }
20136
+ } catch {}
20137
+ }
20138
+ return Array.from(skills.values());
20139
+ }
20140
+ function scanClaudeGlobalSkills() {
20141
+ const home = homedir2();
20142
+ const allSkills = [];
20143
+ const directPaths = findSkillFiles(join10(home, ".claude", "skills"), "*/SKILL.md");
20144
+ allSkills.push(...scanFrontmatterSkills(directPaths));
20145
+ const pluginCacheDir = join10(home, ".claude", "plugins", "cache");
20146
+ const pluginPaths = findSkillFiles(pluginCacheDir, "**/skills/*/SKILL.md");
20147
+ const names = new Set(allSkills.map((s) => s.name));
20148
+ for (const filePath of pluginPaths) {
20149
+ try {
20150
+ const content = readFileSync8(filePath, "utf-8");
20151
+ const meta3 = parseFrontmatter(content);
20152
+ if (meta3 && !names.has(meta3.name)) {
20153
+ names.add(meta3.name);
20154
+ allSkills.push(meta3);
20155
+ }
20156
+ } catch {}
20157
+ }
20158
+ return allSkills;
20159
+ }
20160
+ function scanClaudeAgentSkills(workdir) {
20161
+ const paths = findSkillFiles(join10(workdir, ".claude", "skills"), "*/SKILL.md");
20162
+ return scanFrontmatterSkills(paths);
20163
+ }
20164
+ function scanCodexGlobalSkills() {
20165
+ const home = homedir2();
20166
+ const allSkills = [];
20167
+ const paths = [
20168
+ ...findSkillFiles(join10(home, ".agents", "skills"), "*/SKILL.md"),
20169
+ ...findSkillFiles(join10(home, ".codex", "skills", ".system"), "*/SKILL.md")
20170
+ ];
20171
+ allSkills.push(...scanFrontmatterSkills(paths));
20172
+ const codexPluginDir = join10(home, ".codex", "plugins", "cache");
20173
+ const pluginPaths = findSkillFiles(codexPluginDir, "**/skills/*/SKILL.md");
20174
+ const names = new Set(allSkills.map((s) => s.name));
20175
+ for (const filePath of pluginPaths) {
20176
+ try {
20177
+ const content = readFileSync8(filePath, "utf-8");
20178
+ const meta3 = parseFrontmatter(content);
20179
+ if (meta3 && !names.has(meta3.name)) {
20180
+ names.add(meta3.name);
20181
+ allSkills.push(meta3);
20182
+ }
20183
+ } catch {}
20184
+ }
20185
+ return allSkills;
20186
+ }
20187
+ function scanCodexAgentSkills(workdir) {
20188
+ const paths = findSkillFiles(join10(workdir, ".agents", "skills"), "*/SKILL.md");
20189
+ return scanFrontmatterSkills(paths);
20190
+ }
20191
+ function scanOpenCodeMdFiles(dir) {
20192
+ const skills = [];
20193
+ const files = findSkillFiles(dir, "*.md");
20194
+ for (const filePath of files) {
20195
+ try {
20196
+ const content = readFileSync8(filePath, "utf-8");
20197
+ const name = basename(filePath, ".md");
20198
+ const firstLine = content.split(`
20199
+ `).find((l) => l.trim().length > 0) ?? "";
20200
+ skills.push({ name, description: firstLine.replace(/^#\s*/, "").trim() });
20201
+ } catch {}
20202
+ }
20203
+ return skills;
20204
+ }
20205
+ function scanOpenCodeGlobalSkills() {
20206
+ const home = homedir2();
20207
+ const skills = [];
20208
+ const names = new Set;
20209
+ for (const s of scanOpenCodeMdFiles(join10(home, ".config", "opencode", "commands"))) {
20210
+ if (!names.has(s.name)) {
20211
+ names.add(s.name);
20212
+ skills.push(s);
20213
+ }
20214
+ }
20215
+ for (const s of scanOpenCodeMdFiles(join10(home, ".config", "opencode", "skills"))) {
20216
+ if (!names.has(s.name)) {
20217
+ names.add(s.name);
20218
+ skills.push(s);
20219
+ }
20220
+ }
20221
+ return skills;
20222
+ }
20223
+ function scanOpenCodeAgentSkills(workdir) {
20224
+ const skills = [];
20225
+ const names = new Set;
20226
+ for (const s of scanOpenCodeMdFiles(join10(workdir, ".opencode", "commands"))) {
20227
+ if (!names.has(s.name)) {
20228
+ names.add(s.name);
20229
+ skills.push(s);
20230
+ }
20231
+ }
20232
+ for (const s of scanOpenCodeMdFiles(join10(workdir, ".opencode", "skills"))) {
20233
+ if (!names.has(s.name)) {
20234
+ names.add(s.name);
20235
+ skills.push(s);
20236
+ }
20237
+ }
20238
+ return skills;
20239
+ }
20240
+ function computeHash(skills) {
20241
+ return createHash2("md5").update(JSON.stringify(skills)).digest("hex");
20242
+ }
20243
+ function globalCachePath(runtime) {
20244
+ return join10(getCacheDir(), "global", `${runtime}.json`);
20245
+ }
20246
+ function agentCachePath(agentId, runtime) {
20247
+ return join10(getCacheDir(), "agents", agentId, `${runtime}.json`);
20248
+ }
20249
+ function readCacheHash(filePath) {
20250
+ try {
20251
+ if (!existsSync2(filePath))
20252
+ return null;
20253
+ const data = JSON.parse(readFileSync8(filePath, "utf-8"));
20254
+ return data.hash ?? null;
20255
+ } catch {
20256
+ return null;
20257
+ }
20258
+ }
20259
+ function writeCacheFile(filePath, hash2, skills) {
20260
+ const dir = join10(filePath, "..");
20261
+ mkdirSync7(dir, { recursive: true });
20262
+ const data = { hash: hash2, skills };
20263
+ writeFileSync7(filePath, JSON.stringify(data, null, 2), "utf-8");
20264
+ }
20265
+ var scanTimer = null;
20266
+ var scannerConfig = null;
20267
+ var clientRef = null;
20268
+ function discoverTargets() {
20269
+ if (!scannerConfig)
20270
+ return [];
20271
+ const rootExists = existsSync2(scannerConfig.workspacesRoot);
20272
+ const rootReal = rootExists ? realpathSync(scannerConfig.workspacesRoot) : null;
20273
+ const targets = [];
20274
+ for (const ws of scannerConfig.workspaces) {
20275
+ const agentIds = new Set(ws.agentIds);
20276
+ if (rootReal) {
20277
+ const wsDir = join10(scannerConfig.workspacesRoot, ws.workspaceId);
20278
+ try {
20279
+ if (existsSync2(wsDir)) {
20280
+ for (const dir of readdirSync2(wsDir)) {
20281
+ if (existsSync2(join10(wsDir, dir, "workdir")))
20282
+ agentIds.add(dir);
20283
+ }
20284
+ }
20285
+ } catch {}
20286
+ }
20287
+ for (const agentId of agentIds) {
20288
+ let validWorkdir = null;
20289
+ if (rootReal) {
20290
+ const workdir = join10(scannerConfig.workspacesRoot, ws.workspaceId, agentId, "workdir");
20291
+ if (existsSync2(workdir)) {
20292
+ try {
20293
+ if (realpathSync(workdir).startsWith(rootReal))
20294
+ validWorkdir = workdir;
20295
+ } catch {}
20296
+ }
20297
+ }
20298
+ for (const runtime of scannerConfig.runtimes) {
20299
+ targets.push({ agentId, workdir: validWorkdir, runtime, token: ws.token });
20300
+ }
20301
+ }
20302
+ }
20303
+ return targets;
20304
+ }
20305
+ function getGlobalScanner(runtime) {
20306
+ if (runtime === "claude")
20307
+ return scanClaudeGlobalSkills;
20308
+ if (runtime === "codex")
20309
+ return scanCodexGlobalSkills;
20310
+ return scanOpenCodeGlobalSkills;
20311
+ }
20312
+ function getAgentScanner(runtime) {
20313
+ if (runtime === "claude")
20314
+ return scanClaudeAgentSkills;
20315
+ if (runtime === "codex")
20316
+ return scanCodexAgentSkills;
20317
+ return scanOpenCodeAgentSkills;
20318
+ }
20319
+ function runScan() {
20320
+ if (!scannerConfig || !clientRef)
20321
+ return;
20322
+ if (scannerConfig.workspaces.length === 0)
20323
+ return;
20324
+ for (const runtime of scannerConfig.runtimes) {
20325
+ try {
20326
+ const skills = getGlobalScanner(runtime)();
20327
+ const hash2 = computeHash(skills);
20328
+ const prevHash = readCacheHash(globalCachePath(runtime));
20329
+ if (prevHash !== hash2) {
20330
+ const skillItems = skills.map((s) => ({ name: s.name, description: s.description }));
20331
+ log8.info(`Syncing global ${runtime} — ${skills.length} skills`);
20332
+ const syncPromises = scannerConfig.workspaces.map((ws) => clientRef.syncSkills(ws.token, {
20333
+ scope: "global",
20334
+ runtime,
20335
+ skills: skillItems
20336
+ }));
20337
+ Promise.all(syncPromises).then(() => {
20338
+ writeCacheFile(globalCachePath(runtime), hash2, skills);
20339
+ }).catch((e) => log8.debug("Global skill sync failed", e));
20340
+ }
20341
+ } catch (e) {
20342
+ log8.debug(`Global scan error for ${runtime}`, e);
20343
+ }
20344
+ }
20345
+ const targets = discoverTargets();
20346
+ for (const target of targets) {
20347
+ if (!target.workdir)
20348
+ continue;
20349
+ try {
20350
+ const skills = getAgentScanner(target.runtime)(target.workdir);
20351
+ const hash2 = computeHash(skills);
20352
+ const prevHash = readCacheHash(agentCachePath(target.agentId, target.runtime));
20353
+ if (prevHash !== hash2) {
20354
+ const skillItems = skills.map((s) => ({ name: s.name, description: s.description }));
20355
+ log8.info(`Syncing ${target.agentId}:${target.runtime} — ${skills.length} agent skills`);
20356
+ clientRef.syncSkills(target.token, {
20357
+ scope: "agent",
20358
+ agent_id: target.agentId,
20359
+ runtime: target.runtime,
20360
+ skills: skillItems
20361
+ }).then(() => {
20362
+ writeCacheFile(agentCachePath(target.agentId, target.runtime), hash2, skills);
20363
+ }).catch((e) => log8.debug("Agent skill sync failed", e));
20364
+ }
20365
+ } catch (e) {
20366
+ log8.debug(`Agent scan error for ${target.agentId}:${target.runtime}`, e);
20367
+ }
20368
+ }
20369
+ }
20370
+ function startSkillScanner(client, config2, interval = 60000) {
20371
+ clientRef = client;
20372
+ scannerConfig = config2;
20373
+ runScan();
20374
+ scanTimer = setInterval(runScan, interval);
20375
+ }
20376
+ function stopSkillScanner() {
20377
+ if (scanTimer) {
20378
+ clearInterval(scanTimer);
20379
+ scanTimer = null;
20380
+ }
20381
+ }
20382
+
20005
20383
  // lib/shell-env.ts
20006
20384
  import { execSync as execSync3 } from "child_process";
20007
20385
  var PASSTHROUGH_VARS = ["ALOOK_PROJECT_ROOT", "ALOOK_SERVER_URL", "ALOOK_CMD_PREFIX", "ALOOK_HEALTH_PORT"];
@@ -20036,15 +20414,15 @@ function resolveLoginShellEnv() {
20036
20414
  }
20037
20415
 
20038
20416
  // daemon/daemon.ts
20039
- import { existsSync as existsSync2, mkdirSync as mkdirSync7, openSync, closeSync, readdirSync as readdirSync2, statSync as statSync3, unlinkSync as unlinkSync5 } from "fs";
20417
+ import { existsSync as existsSync3, mkdirSync as mkdirSync8, openSync, closeSync, readdirSync as readdirSync3, statSync as statSync4, unlinkSync as unlinkSync5 } from "fs";
20040
20418
  import { readdir as readdir2, readFile as readFile2, unlink, stat as fsStat } from "fs/promises";
20041
20419
  import { execSync as execSync4, spawn as spawn5 } from "child_process";
20042
20420
  import { fileURLToPath as fileURLToPath2 } from "url";
20043
- import { dirname as dirname3, join as join10 } from "path";
20044
- var log8 = createLogger2({ module: "daemon" });
20421
+ import { dirname as dirname3, join as join11 } from "path";
20422
+ var log9 = createLogger2({ module: "daemon" });
20045
20423
  var _dir = dirname3(fileURLToPath2(import.meta.url));
20046
- var sessionRunnerPath = existsSync2(join10(_dir, "session-runner.js")) ? join10(_dir, "session-runner.js") : join10(_dir, "session-runner.ts");
20047
- var meetingRunnerPath = existsSync2(join10(_dir, "meeting-runner.js")) ? join10(_dir, "meeting-runner.js") : join10(_dir, "meeting-runner.ts");
20424
+ var sessionRunnerPath = existsSync3(join11(_dir, "session-runner.js")) ? join11(_dir, "session-runner.js") : join11(_dir, "session-runner.ts");
20425
+ var meetingRunnerPath = existsSync3(join11(_dir, "meeting-runner.js")) ? join11(_dir, "meeting-runner.js") : join11(_dir, "meeting-runner.ts");
20048
20426
  function isCommandAvailable2(cmd) {
20049
20427
  try {
20050
20428
  const check2 = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
@@ -20059,16 +20437,16 @@ function pruneSessionRunnerLogs() {
20059
20437
  const logDir = sessionRunnerLogDir();
20060
20438
  let entries;
20061
20439
  try {
20062
- entries = readdirSync2(logDir).filter((f) => f.endsWith(".log"));
20440
+ entries = readdirSync3(logDir).filter((f) => f.endsWith(".log"));
20063
20441
  } catch {
20064
20442
  return;
20065
20443
  }
20066
20444
  if (entries.length <= MAX_SESSION_RUNNER_LOGS)
20067
20445
  return;
20068
20446
  const withMtime = entries.map((name) => {
20069
- const full = join10(logDir, name);
20447
+ const full = join11(logDir, name);
20070
20448
  try {
20071
- return { name, mtime: statSync3(full).mtimeMs };
20449
+ return { name, mtime: statSync4(full).mtimeMs };
20072
20450
  } catch {
20073
20451
  return { name, mtime: 0 };
20074
20452
  }
@@ -20076,7 +20454,7 @@ function pruneSessionRunnerLogs() {
20076
20454
  withMtime.sort((a, b) => b.mtime - a.mtime);
20077
20455
  for (const entry of withMtime.slice(MAX_SESSION_RUNNER_LOGS)) {
20078
20456
  try {
20079
- unlinkSync5(join10(logDir, entry.name));
20457
+ unlinkSync5(join11(logDir, entry.name));
20080
20458
  } catch {}
20081
20459
  }
20082
20460
  }
@@ -20117,7 +20495,7 @@ function isValidMarker(data) {
20117
20495
  var MARKER_STALE_MS = 24 * 60 * 60 * 1000;
20118
20496
  var TMP_STALE_MS = 60 * 60 * 1000;
20119
20497
  async function reconcilePendingCompletions(workspacesRoot) {
20120
- const dir = join10(workspacesRoot, ".pending_completions");
20498
+ const dir = join11(workspacesRoot, ".pending_completions");
20121
20499
  let entries;
20122
20500
  try {
20123
20501
  entries = await readdir2(dir);
@@ -20128,15 +20506,15 @@ async function reconcilePendingCompletions(workspacesRoot) {
20128
20506
  if (!name.endsWith(".tmp"))
20129
20507
  continue;
20130
20508
  try {
20131
- const s = await fsStat(join10(dir, name));
20509
+ const s = await fsStat(join11(dir, name));
20132
20510
  if (Date.now() - s.mtimeMs > TMP_STALE_MS) {
20133
- await unlink(join10(dir, name));
20511
+ await unlink(join11(dir, name));
20134
20512
  }
20135
20513
  } catch {}
20136
20514
  }
20137
20515
  const jsonFiles = entries.filter((f) => f.endsWith(".json"));
20138
20516
  for (const name of jsonFiles) {
20139
- const filePath = join10(dir, name);
20517
+ const filePath = join11(dir, name);
20140
20518
  try {
20141
20519
  let raw;
20142
20520
  try {
@@ -20148,14 +20526,14 @@ async function reconcilePendingCompletions(workspacesRoot) {
20148
20526
  try {
20149
20527
  parsed = JSON.parse(raw);
20150
20528
  } catch {
20151
- log8.warn(`reconcile: malformed marker ${name}, deleting`);
20529
+ log9.warn(`reconcile: malformed marker ${name}, deleting`);
20152
20530
  try {
20153
20531
  await unlink(filePath);
20154
20532
  } catch {}
20155
20533
  continue;
20156
20534
  }
20157
20535
  if (!isValidMarker(parsed)) {
20158
- log8.warn(`reconcile: invalid marker structure ${name}, deleting`);
20536
+ log9.warn(`reconcile: invalid marker structure ${name}, deleting`);
20159
20537
  try {
20160
20538
  await unlink(filePath);
20161
20539
  } catch {}
@@ -20164,7 +20542,7 @@ async function reconcilePendingCompletions(workspacesRoot) {
20164
20542
  const marker = parsed;
20165
20543
  const age = Date.now() - new Date(marker.createdAt).getTime();
20166
20544
  if (age > MARKER_STALE_MS) {
20167
- log8.warn(`reconcile: stale marker ${name} (${Math.round(age / 3600000)}h old), deleting`);
20545
+ log9.warn(`reconcile: stale marker ${name} (${Math.round(age / 3600000)}h old), deleting`);
20168
20546
  try {
20169
20547
  await unlink(filePath);
20170
20548
  } catch {}
@@ -20180,7 +20558,7 @@ async function reconcilePendingCompletions(workspacesRoot) {
20180
20558
  try {
20181
20559
  await unlink(filePath);
20182
20560
  } catch (delErr) {
20183
- log8.warn(`reconcile: delivered marker ${name} but failed to delete: ${delErr}`);
20561
+ log9.warn(`reconcile: delivered marker ${name} but failed to delete: ${delErr}`);
20184
20562
  }
20185
20563
  } catch (deliverErr) {
20186
20564
  if (isClientError2(deliverErr)) {
@@ -20188,11 +20566,11 @@ async function reconcilePendingCompletions(workspacesRoot) {
20188
20566
  await unlink(filePath);
20189
20567
  } catch {}
20190
20568
  } else {
20191
- log8.debug(`reconcile: delivery failed for ${name}, will retry next cycle`);
20569
+ log9.debug(`reconcile: delivery failed for ${name}, will retry next cycle`);
20192
20570
  }
20193
20571
  }
20194
20572
  } catch (e) {
20195
- log8.debug(`reconcile: error processing ${name}`, e);
20573
+ log9.debug(`reconcile: error processing ${name}`, e);
20196
20574
  }
20197
20575
  }
20198
20576
  }
@@ -20203,7 +20581,7 @@ async function startDaemon(profile, serverUrl) {
20203
20581
  }
20204
20582
  process.once("exit", () => releaseDaemonPid(profile));
20205
20583
  const bailOnUnexpected = (label, err) => {
20206
- log8.error(`${label} — shutting down`, err);
20584
+ log9.error(`${label} — shutting down`, err);
20207
20585
  releaseDaemonPid(profile);
20208
20586
  process.exit(1);
20209
20587
  };
@@ -20216,21 +20594,21 @@ async function startDaemon(profile, serverUrl) {
20216
20594
  if (marker) {
20217
20595
  clearUpdateMarker(profile);
20218
20596
  if (marker === config2.cliVersion) {
20219
- log8.info(`Cleared update marker — now running v${config2.cliVersion}`);
20597
+ log9.info(`Cleared update marker — now running v${config2.cliVersion}`);
20220
20598
  } else {
20221
- log8.info(`Cleared stale update marker (was v${marker}, running v${config2.cliVersion}) — update will be retried`);
20599
+ log9.info(`Cleared stale update marker (was v${marker}, running v${config2.cliVersion}) — update will be retried`);
20222
20600
  }
20223
20601
  }
20224
20602
  const cliConfig = loadCLIConfigForProfile(profile);
20225
20603
  const workspaces = cliConfig.watched_workspaces || [];
20226
20604
  if (workspaces.length === 0) {
20227
- log8.error("No watched workspaces configured.");
20605
+ log9.error("No watched workspaces configured.");
20228
20606
  process.exit(1);
20229
20607
  return;
20230
20608
  }
20231
20609
  const hasPerWorkspaceTokens = workspaces.every((ws) => !!ws.token);
20232
20610
  if (!hasPerWorkspaceTokens) {
20233
- log8.error(`Config uses old format. Run '${cmdPrefix()} register --token <token>' for each workspace to upgrade.`);
20611
+ log9.error(`Config uses old format. Run '${cmdPrefix()} register --token <token>' for each workspace to upgrade.`);
20234
20612
  process.exit(1);
20235
20613
  return;
20236
20614
  }
@@ -20250,11 +20628,11 @@ async function startDaemon(profile, serverUrl) {
20250
20628
  }
20251
20629
  }
20252
20630
  if (providers.length === 0) {
20253
- log8.error("No agent CLI tools found on PATH.");
20631
+ log9.error("No agent CLI tools found on PATH.");
20254
20632
  process.exit(1);
20255
20633
  return;
20256
20634
  }
20257
- log8.info(`Detected providers: ${providers.map((p) => `${p.type}@${p.version}`).join(", ")}`);
20635
+ log9.info(`Detected providers: ${providers.map((p) => `${p.type}@${p.version}`).join(", ")}`);
20258
20636
  const workspaceStates = [];
20259
20637
  const runtimeIndex = new Map;
20260
20638
  for (const ws of workspaces) {
@@ -20262,7 +20640,7 @@ async function startDaemon(profile, serverUrl) {
20262
20640
  type: p.type,
20263
20641
  version: p.version
20264
20642
  }));
20265
- log8.info(`Registering workspace ${ws.id} (${ws.name ?? "unnamed"}) with ${runtimes.length} runtime(s)...`);
20643
+ log9.info(`Registering workspace ${ws.id} (${ws.name ?? "unnamed"}) with ${runtimes.length} runtime(s)...`);
20266
20644
  let resp;
20267
20645
  try {
20268
20646
  resp = await client.register(ws.token, {
@@ -20275,13 +20653,13 @@ async function startDaemon(profile, serverUrl) {
20275
20653
  });
20276
20654
  } catch (e) {
20277
20655
  if (e instanceof Error && e.message.startsWith("HTTP 401")) {
20278
- log8.warn(`Workspace ${ws.id} token invalid — skipping (run '${cmdPrefix()} register --token <token>' to fix)`);
20656
+ log9.warn(`Workspace ${ws.id} token invalid — skipping (run '${cmdPrefix()} register --token <token>' to fix)`);
20279
20657
  } else {
20280
- log8.error(`Failed to register workspace ${ws.id}, skipping`, e);
20658
+ log9.error(`Failed to register workspace ${ws.id}, skipping`, e);
20281
20659
  }
20282
20660
  continue;
20283
20661
  }
20284
- log8.info(`Workspace ${ws.id} registered — ${resp.runtimes.length} runtime(s)`);
20662
+ log9.info(`Workspace ${ws.id} registered — ${resp.runtimes.length} runtime(s)`);
20285
20663
  const runtimeIds = resp.runtimes.map((r) => r.id);
20286
20664
  workspaceStates.push({ workspaceId: ws.id, token: ws.token, runtimeIds });
20287
20665
  for (let i = 0;i < runtimeIds.length; i++) {
@@ -20293,13 +20671,13 @@ async function startDaemon(profile, serverUrl) {
20293
20671
  }
20294
20672
  }
20295
20673
  if (workspaceStates.length === 0) {
20296
- log8.error("No workspaces registered successfully.");
20674
+ log9.error("No workspaces registered successfully.");
20297
20675
  process.exit(1);
20298
20676
  return;
20299
20677
  }
20300
20678
  const allRuntimeIds = workspaceStates.flatMap((ws) => ws.runtimeIds);
20301
20679
  health.setRuntimeCount(allRuntimeIds.length);
20302
- log8.info(`Daemon started — ${allRuntimeIds.length} runtime(s) across ${workspaceStates.length} workspace(s)`);
20680
+ log9.info(`Daemon started — ${allRuntimeIds.length} runtime(s) across ${workspaceStates.length} workspace(s)`);
20303
20681
  const activeTasks = new Set;
20304
20682
  const knownAgentIds = new Set(workspaces.flatMap((ws) => ws.agent_ids ?? []));
20305
20683
  function syncAgentId(agentId, workspaceId) {
@@ -20334,7 +20712,7 @@ async function startDaemon(profile, serverUrl) {
20334
20712
  cfg.watched_workspaces = (cfg.watched_workspaces || []).filter((w) => w.id !== workspaceId);
20335
20713
  saveCLIConfigForProfile(profile, cfg);
20336
20714
  } catch {}
20337
- log8.info(`Workspace ${workspaceId} deleted server-side — removed from config`);
20715
+ log9.info(`Workspace ${workspaceId} deleted server-side — removed from config`);
20338
20716
  }
20339
20717
  const pollCycle = async () => {
20340
20718
  let remaining = config2.maxConcurrentTasks - activeTasks.size;
@@ -20360,7 +20738,7 @@ async function startDaemon(profile, serverUrl) {
20360
20738
  handleCliUpdate(pending_update.version, () => requestRestart(), profile);
20361
20739
  }
20362
20740
  if (pending_rescan) {
20363
- log8.info("Rescan requested — restarting daemon to re-detect runtimes");
20741
+ log9.info("Rescan requested — restarting daemon to re-detect runtimes");
20364
20742
  for (const id of evictedIds) {
20365
20743
  evictWorkspace(id);
20366
20744
  }
@@ -20373,19 +20751,19 @@ async function startDaemon(profile, serverUrl) {
20373
20751
  activeTasks.add(task.id);
20374
20752
  remaining--;
20375
20753
  handleTask(client, config2, runtimeIndex, task, ws.token, activeTasks).catch((e) => {
20376
- log8.error("Task error", e);
20754
+ log9.error("Task error", e);
20377
20755
  activeTasks.delete(task.id);
20378
20756
  });
20379
20757
  }
20380
20758
  if (file_requests) {
20381
20759
  for (const req of file_requests) {
20382
- handleFileRequest(client, config2, ws.workspaceId, req, ws.token).catch((e) => log8.debug("File request error", e));
20760
+ handleFileRequest(client, config2, ws.workspaceId, req, ws.token).catch((e) => log9.debug("File request error", e));
20383
20761
  }
20384
20762
  }
20385
20763
  if (meetings) {
20386
20764
  for (const m of meetings) {
20387
- const agentBaseDir = join10(config2.workspacesRoot, m.workspace_id, m.agent_id, "workdir");
20388
- const timelineDir = join10(agentBaseDir, ".context_timeline");
20765
+ const agentBaseDir = join11(config2.workspacesRoot, m.workspace_id, m.agent_id, "workdir");
20766
+ const timelineDir = join11(agentBaseDir, ".context_timeline");
20389
20767
  spawnMeetingRunner({
20390
20768
  meetingId: m.id,
20391
20769
  meetingUrl: m.meeting_url,
@@ -20402,9 +20780,9 @@ async function startDaemon(profile, serverUrl) {
20402
20780
  }
20403
20781
  } catch (e) {
20404
20782
  if (e instanceof Error && e.message.startsWith("HTTP 401")) {
20405
- log8.warn(`Workspace ${ws.workspaceId} poll returned 401 — will retry next cycle`);
20783
+ log9.warn(`Workspace ${ws.workspaceId} poll returned 401 — will retry next cycle`);
20406
20784
  } else {
20407
- log8.debug("Poll error", e);
20785
+ log9.debug("Poll error", e);
20408
20786
  }
20409
20787
  }
20410
20788
  }
@@ -20412,7 +20790,7 @@ async function startDaemon(profile, serverUrl) {
20412
20790
  evictWorkspace(id);
20413
20791
  }
20414
20792
  if (workspaceStates.length === 0) {
20415
- log8.info("All workspaces evicted — shutting down");
20793
+ log9.info("All workspaces evicted — shutting down");
20416
20794
  shutdown();
20417
20795
  }
20418
20796
  };
@@ -20420,7 +20798,7 @@ async function startDaemon(profile, serverUrl) {
20420
20798
  const heartbeatPing = () => {
20421
20799
  for (const ws of workspaceStates) {
20422
20800
  client.heartbeat(ws.token, config2.daemonId).catch((e) => {
20423
- log8.debug("heartbeat failed", { workspaceId: ws.workspaceId, err: String(e) });
20801
+ log9.debug("heartbeat failed", { workspaceId: ws.workspaceId, err: String(e) });
20424
20802
  });
20425
20803
  }
20426
20804
  };
@@ -20445,7 +20823,7 @@ async function startDaemon(profile, serverUrl) {
20445
20823
  syncAgentId(task.agentId, ws.workspaceId);
20446
20824
  activeTasks.add(task.id);
20447
20825
  handleTask(client, config2, runtimeIndex, task, ws.token, activeTasks).catch((e) => {
20448
- log8.error("WS task error", e);
20826
+ log9.error("WS task error", e);
20449
20827
  activeTasks.delete(task.id);
20450
20828
  });
20451
20829
  }
@@ -20454,7 +20832,7 @@ async function startDaemon(profile, serverUrl) {
20454
20832
  const ws = workspaceStates.find((w) => w.workspaceId === msg.workspaceId);
20455
20833
  if (ws) {
20456
20834
  for (const req of msg.requests) {
20457
- handleFileRequest(client, config2, ws.workspaceId, req, ws.token).catch((e) => log8.debug("WS file request error", e));
20835
+ handleFileRequest(client, config2, ws.workspaceId, req, ws.token).catch((e) => log9.debug("WS file request error", e));
20458
20836
  }
20459
20837
  }
20460
20838
  break;
@@ -20464,8 +20842,8 @@ async function startDaemon(profile, serverUrl) {
20464
20842
  const ws = workspaceStates.find((w) => w.workspaceId === m.workspace_id);
20465
20843
  if (!ws)
20466
20844
  continue;
20467
- const agentBaseDir = join10(config2.workspacesRoot, m.workspace_id, m.agent_id, "workdir");
20468
- const timelineDir = join10(agentBaseDir, ".context_timeline");
20845
+ const agentBaseDir = join11(config2.workspacesRoot, m.workspace_id, m.agent_id, "workdir");
20846
+ const timelineDir = join11(agentBaseDir, ".context_timeline");
20469
20847
  spawnMeetingRunner({
20470
20848
  meetingId: m.id,
20471
20849
  meetingUrl: m.meeting_url,
@@ -20489,7 +20867,7 @@ async function startDaemon(profile, serverUrl) {
20489
20867
  }
20490
20868
  break;
20491
20869
  case "daemon.rescan":
20492
- log8.info("WS rescan requested — restarting daemon");
20870
+ log9.info("WS rescan requested — restarting daemon");
20493
20871
  requestRestart();
20494
20872
  break;
20495
20873
  case "daemon.kill": {
@@ -20517,7 +20895,7 @@ async function startDaemon(profile, serverUrl) {
20517
20895
  });
20518
20896
  activeTasks.add(killTask.id);
20519
20897
  handleTask(client, config2, runtimeIndex, killTask, ws.token, activeTasks).catch((e) => {
20520
- log8.error("WS kill task error", e);
20898
+ log9.error("WS kill task error", e);
20521
20899
  activeTasks.delete(killTask.id);
20522
20900
  });
20523
20901
  }
@@ -20531,11 +20909,11 @@ async function startDaemon(profile, serverUrl) {
20531
20909
  machineToken: firstToken,
20532
20910
  onMessage: handleWsPush,
20533
20911
  onConnected: () => {
20534
- log8.info("WS connected — switching to low-frequency poll");
20912
+ log9.info("WS connected — switching to low-frequency poll");
20535
20913
  updatePollInterval(config2.wsPollInterval);
20536
20914
  },
20537
20915
  onDisconnected: () => {
20538
- log8.info("WS disconnected — reverting to high-frequency poll");
20916
+ log9.info("WS disconnected — reverting to high-frequency poll");
20539
20917
  updatePollInterval(config2.pollInterval);
20540
20918
  }
20541
20919
  }) : null;
@@ -20543,16 +20921,25 @@ async function startDaemon(profile, serverUrl) {
20543
20921
  const sweepTick = async () => {
20544
20922
  for (const ws of workspaceStates) {
20545
20923
  client.sweep(ws.token, config2.daemonId).catch((e) => {
20546
- log8.debug("sweep ping failed", { workspaceId: ws.workspaceId, err: String(e) });
20924
+ log9.debug("sweep ping failed", { workspaceId: ws.workspaceId, err: String(e) });
20547
20925
  });
20548
20926
  }
20549
20927
  try {
20550
20928
  await reconcilePendingCompletions(config2.workspacesRoot);
20551
20929
  } catch (e) {
20552
- log8.debug("reconciliation error", e);
20930
+ log9.debug("reconciliation error", e);
20553
20931
  }
20554
20932
  };
20555
20933
  const sweepTimer = setInterval(sweepTick, config2.sweepInterval);
20934
+ startSkillScanner(client, {
20935
+ workspacesRoot: config2.workspacesRoot,
20936
+ workspaces: workspaces.map((ws) => ({
20937
+ workspaceId: ws.id,
20938
+ token: ws.token,
20939
+ agentIds: ws.agent_ids ?? []
20940
+ })),
20941
+ runtimes: providers.map((p) => p.type)
20942
+ }, 60000);
20556
20943
  let shuttingDown = false;
20557
20944
  let restartRequested = false;
20558
20945
  const requestRestart = () => {
@@ -20563,10 +20950,11 @@ async function startDaemon(profile, serverUrl) {
20563
20950
  if (shuttingDown)
20564
20951
  return;
20565
20952
  shuttingDown = true;
20566
- log8.info(restartRequested ? "Restarting..." : "Shutting down...");
20953
+ log9.info(restartRequested ? "Restarting..." : "Shutting down...");
20567
20954
  clearInterval(pollTimer);
20568
20955
  clearInterval(heartbeatTimer);
20569
20956
  clearInterval(sweepTimer);
20957
+ stopSkillScanner();
20570
20958
  wsClient?.close();
20571
20959
  const shutdownMs = restartRequested ? 30000 : Number(process.env.ALOOK_SHUTDOWN_TIMEOUT_MS) || 5000;
20572
20960
  const timeout = setTimeout(() => process.exit(1), shutdownMs);
@@ -20587,10 +20975,10 @@ async function startDaemon(profile, serverUrl) {
20587
20975
  const logPath = daemonLogFilePath();
20588
20976
  let logFd;
20589
20977
  try {
20590
- mkdirSync7(dirname3(logPath), { recursive: true, mode: 448 });
20978
+ mkdirSync8(dirname3(logPath), { recursive: true, mode: 448 });
20591
20979
  logFd = openSync(logPath, "a", 384);
20592
20980
  } catch (e) {
20593
- log8.error(`Failed to open daemon log file ${logPath}`, e);
20981
+ log9.error(`Failed to open daemon log file ${logPath}`, e);
20594
20982
  }
20595
20983
  const child = spawn5(process.execPath, args, {
20596
20984
  detached: true,
@@ -20600,7 +20988,7 @@ async function startDaemon(profile, serverUrl) {
20600
20988
  child.unref();
20601
20989
  if (logFd != null)
20602
20990
  closeSync(logFd);
20603
- log8.info(`Spawned new daemon (pid=${child.pid}), logs: ${logPath}`);
20991
+ log9.info(`Spawned new daemon (pid=${child.pid}), logs: ${logPath}`);
20604
20992
  }
20605
20993
  clearTimeout(timeout);
20606
20994
  process.exit(0);
@@ -20611,7 +20999,7 @@ async function startDaemon(profile, serverUrl) {
20611
20999
  process.on("SIGHUP", async () => {
20612
21000
  if (shuttingDown)
20613
21001
  return;
20614
- log8.info("SIGHUP received — reloading config...");
21002
+ log9.info("SIGHUP received — reloading config...");
20615
21003
  try {
20616
21004
  const freshConfig = loadCLIConfigForProfile(profile);
20617
21005
  const freshWorkspaces = freshConfig.watched_workspaces || [];
@@ -20619,7 +21007,7 @@ async function startDaemon(profile, serverUrl) {
20619
21007
  const newWorkspaces = freshWorkspaces.filter((ws) => ws.token && !existingIds.has(ws.id));
20620
21008
  for (const ws of newWorkspaces) {
20621
21009
  const runtimes = providers.map((p) => ({ type: p.type, version: p.version }));
20622
- log8.info(`Registering new workspace ${ws.id} (${ws.name ?? "unnamed"})...`);
21010
+ log9.info(`Registering new workspace ${ws.id} (${ws.name ?? "unnamed"})...`);
20623
21011
  try {
20624
21012
  const resp = await client.register(ws.token, {
20625
21013
  workspace_id: ws.id,
@@ -20638,34 +21026,34 @@ async function startDaemon(profile, serverUrl) {
20638
21026
  provider: providers[i].type
20639
21027
  });
20640
21028
  }
20641
- log8.info(`Workspace ${ws.id} added — ${runtimeIds.length} runtime(s)`);
21029
+ log9.info(`Workspace ${ws.id} added — ${runtimeIds.length} runtime(s)`);
20642
21030
  } catch (e) {
20643
- log8.error(`Failed to register new workspace ${ws.id}`, e);
21031
+ log9.error(`Failed to register new workspace ${ws.id}`, e);
20644
21032
  }
20645
21033
  }
20646
21034
  if (newWorkspaces.length > 0) {
20647
21035
  health.setRuntimeCount(workspaceStates.reduce((sum, w) => sum + w.runtimeIds.length, 0));
20648
- log8.info(`Reload complete — now polling ${workspaceStates.length} workspace(s)`);
21036
+ log9.info(`Reload complete — now polling ${workspaceStates.length} workspace(s)`);
20649
21037
  } else {
20650
- log8.info("Reload complete — no new workspaces found");
21038
+ log9.info("Reload complete — no new workspaces found");
20651
21039
  }
20652
21040
  } catch (e) {
20653
- log8.error("Failed to reload config", e);
21041
+ log9.error("Failed to reload config", e);
20654
21042
  }
20655
21043
  });
20656
21044
  await pollCycle();
20657
21045
  }
20658
21046
  function spawnSessionRunner(input) {
20659
21047
  const logDir = sessionRunnerLogDir();
20660
- mkdirSync7(logDir, { recursive: true });
20661
- const logFilePath = join10(logDir, `${input.task.id}.log`);
21048
+ mkdirSync8(logDir, { recursive: true });
21049
+ const logFilePath = join11(logDir, `${input.task.id}.log`);
20662
21050
  input.logFilePath = logFilePath;
20663
21051
  const encoded = Buffer.from(JSON.stringify(input)).toString("base64");
20664
21052
  let fd;
20665
21053
  try {
20666
21054
  fd = openSync(logFilePath, "a");
20667
21055
  } catch (e) {
20668
- log8.error(`Failed to open log file ${logFilePath}`, e);
21056
+ log9.error(`Failed to open log file ${logFilePath}`, e);
20669
21057
  }
20670
21058
  const child = spawn5(process.execPath, [sessionRunnerPath, encoded], {
20671
21059
  detached: true,
@@ -20678,14 +21066,14 @@ function spawnSessionRunner(input) {
20678
21066
  }
20679
21067
  function spawnMeetingRunner(input) {
20680
21068
  const logDir = sessionRunnerLogDir();
20681
- mkdirSync7(logDir, { recursive: true });
20682
- const logFilePath = join10(logDir, `meeting-${input.meetingId}.log`);
21069
+ mkdirSync8(logDir, { recursive: true });
21070
+ const logFilePath = join11(logDir, `meeting-${input.meetingId}.log`);
20683
21071
  const encoded = Buffer.from(JSON.stringify(input)).toString("base64");
20684
21072
  let fd;
20685
21073
  try {
20686
21074
  fd = openSync(logFilePath, "a");
20687
21075
  } catch (e) {
20688
- log8.error(`Failed to open meeting log file ${logFilePath}`, e);
21076
+ log9.error(`Failed to open meeting log file ${logFilePath}`, e);
20689
21077
  }
20690
21078
  const child = spawn5(process.execPath, [meetingRunnerPath, encoded], {
20691
21079
  detached: true,
@@ -20694,11 +21082,11 @@ function spawnMeetingRunner(input) {
20694
21082
  child.unref();
20695
21083
  if (fd != null)
20696
21084
  closeSync(fd);
20697
- log8.info(`Spawned meeting runner for ${input.meetingId} (pid=${child.pid})`);
21085
+ log9.info(`Spawned meeting runner for ${input.meetingId} (pid=${child.pid})`);
20698
21086
  return child;
20699
21087
  }
20700
21088
  async function handleFileRequest(client, config2, workspaceId, req, token) {
20701
- const agentWorkdir = join10(config2.workspacesRoot, workspaceId, req.agent_id, "workdir");
21089
+ const agentWorkdir = join11(config2.workspacesRoot, workspaceId, req.agent_id, "workdir");
20702
21090
  const resolved = validatePath(agentWorkdir, req.path);
20703
21091
  if (!resolved) {
20704
21092
  await client.reportFileData(token, { request_id: req.id, error: "invalid path", path: req.path });
@@ -20721,7 +21109,7 @@ async function handleFileRequest(client, config2, workspaceId, req, token) {
20721
21109
  }
20722
21110
  }
20723
21111
  async function handleTask(client, config2, runtimeIndex, task, token, activeTasks) {
20724
- log8.info(`Task ${task.id} claimed agent=${task.agentId}`);
21112
+ log9.info(`Task ${task.id} claimed agent=${task.agentId}`);
20725
21113
  if (task.type === TASK_TYPES.KILL_TASK) {
20726
21114
  const targetTaskId = task.context?.target_task_id;
20727
21115
  if (!targetTaskId) {
@@ -20729,8 +21117,8 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
20729
21117
  activeTasks.delete(task.id);
20730
21118
  return;
20731
21119
  }
20732
- const agentBaseDir = join10(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir");
20733
- const timelineDir = join10(agentBaseDir, ".context_timeline");
21120
+ const agentBaseDir = join11(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir");
21121
+ const timelineDir = join11(agentBaseDir, ".context_timeline");
20734
21122
  const MAX_WAIT_MS = Number(process.env.ALOOK_KILL_TASK_MAX_WAIT_MS) || 15000;
20735
21123
  const POLL_MS = Number(process.env.ALOOK_KILL_TASK_POLL_MS) || 200;
20736
21124
  const waitStart = Date.now();
@@ -20750,18 +21138,18 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
20750
21138
  try {
20751
21139
  process.kill(pid, "SIGTERM");
20752
21140
  await client.failTask(token, task.id, "killed");
20753
- log8.info(`Kill task ${task.id}: sent SIGTERM to pid=${pid} for target=${targetTaskId}`);
21141
+ log9.info(`Kill task ${task.id}: sent SIGTERM to pid=${pid} for target=${targetTaskId}`);
20754
21142
  } catch (e) {
20755
21143
  if (e?.code === "ESRCH") {
20756
21144
  await client.failTask(token, task.id, "target process already exited");
20757
- log8.info(`Kill task ${task.id}: target pid=${pid} already exited`);
21145
+ log9.info(`Kill task ${task.id}: target pid=${pid} already exited`);
20758
21146
  } else {
20759
21147
  await client.failTask(token, task.id, `kill failed: ${e}`);
20760
21148
  }
20761
21149
  }
20762
21150
  } else {
20763
21151
  await client.failTask(token, task.id, "target not found in timeline");
20764
- log8.info(`Kill task ${task.id}: target ${targetTaskId} not found in timeline`);
21152
+ log9.info(`Kill task ${task.id}: target ${targetTaskId} not found in timeline`);
20765
21153
  }
20766
21154
  activeTasks.delete(task.id);
20767
21155
  return;
@@ -20781,17 +21169,17 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
20781
21169
  }
20782
21170
  const provider = runtimeData.provider;
20783
21171
  if (task.contextKey) {
20784
- const agentBaseDir = join10(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir");
21172
+ const agentBaseDir = join11(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir");
20785
21173
  cleanupStaleIntents(agentBaseDir);
20786
- const timelineDir = join10(agentBaseDir, ".context_timeline");
21174
+ const timelineDir = join11(agentBaseDir, ".context_timeline");
20787
21175
  const lockAcquired = acquireSteeringLock(agentBaseDir, task.contextKey);
20788
21176
  if (!lockAcquired) {
20789
- log8.warn(`Steering lock contention for context_key=${task.contextKey}, proceeding without steering`);
21177
+ log9.warn(`Steering lock contention for context_key=${task.contextKey}, proceeding without steering`);
20790
21178
  } else {
20791
21179
  try {
20792
21180
  const predecessor = findRunningEntryByContextKey(timelineDir, task.contextKey, provider);
20793
21181
  if (predecessor && predecessor.task_id !== task.id) {
20794
- log8.info(`Steering: task ${task.id} supersedes predecessor ${predecessor.task_id} (context_key=${task.contextKey})`);
21182
+ log9.info(`Steering: task ${task.id} supersedes predecessor ${predecessor.task_id} (context_key=${task.contextKey})`);
20795
21183
  if (predecessor.pid != null) {
20796
21184
  writeKillIntent(agentBaseDir, {
20797
21185
  reason: "superseded",
@@ -20801,12 +21189,12 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
20801
21189
  });
20802
21190
  try {
20803
21191
  process.kill(predecessor.pid, "SIGTERM");
20804
- log8.info(`Steering: sent SIGTERM to predecessor pid=${predecessor.pid}`);
21192
+ log9.info(`Steering: sent SIGTERM to predecessor pid=${predecessor.pid}`);
20805
21193
  } catch (e) {
20806
21194
  if (e?.code === "ESRCH") {
20807
- log8.info(`Steering: predecessor pid=${predecessor.pid} already exited`);
21195
+ log9.info(`Steering: predecessor pid=${predecessor.pid} already exited`);
20808
21196
  } else {
20809
- log8.warn(`Steering: kill failed for pid=${predecessor.pid}`, e);
21197
+ log9.warn(`Steering: kill failed for pid=${predecessor.pid}`, e);
20810
21198
  }
20811
21199
  }
20812
21200
  const waitStart = Date.now();
@@ -20819,14 +21207,14 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
20819
21207
  await new Promise((r) => setTimeout(r, POLL_MS));
20820
21208
  }
20821
21209
  if (findRunningPidByTaskId(timelineDir, predecessor.task_id) != null) {
20822
- log8.warn(`Steering: predecessor pid=${predecessor.pid} did not exit within ${MAX_WAIT_MS}ms, proceeding anyway`);
21210
+ log9.warn(`Steering: predecessor pid=${predecessor.pid} did not exit within ${MAX_WAIT_MS}ms, proceeding anyway`);
20823
21211
  }
20824
21212
  }
20825
21213
  try {
20826
21214
  await client.supersedeTask(token, predecessor.task_id);
20827
- log8.info(`Steering: predecessor ${predecessor.task_id} marked superseded`);
21215
+ log9.info(`Steering: predecessor ${predecessor.task_id} marked superseded`);
20828
21216
  } catch (e) {
20829
- log8.warn(`Steering: failed to mark predecessor superseded server-side`, e);
21217
+ log9.warn(`Steering: failed to mark predecessor superseded server-side`, e);
20830
21218
  }
20831
21219
  }
20832
21220
  } finally {
@@ -20854,8 +21242,8 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
20854
21242
  activeTasks.delete(task.id);
20855
21243
  if (code !== 0) {
20856
21244
  const msg = code === null ? `session-runner killed by signal (task ${task.id})` : `session-runner crashed (exit code ${code}, task ${task.id})`;
20857
- log8.warn(msg);
20858
- const timelineDir = join10(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir", ".context_timeline");
21245
+ log9.warn(msg);
21246
+ const timelineDir = join11(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir", ".context_timeline");
20859
21247
  updateEntry(timelineDir, task.id, (entry) => {
20860
21248
  entry.pid = null;
20861
21249
  entry.status = "failed";
@@ -20865,10 +21253,10 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
20865
21253
  await client.failTask(token, task.id, msg);
20866
21254
  } catch (e) {
20867
21255
  if (isClientError2(e)) {
20868
- log8.info(`Backstop: task ${task.id} already in terminal state`);
21256
+ log9.info(`Backstop: task ${task.id} already in terminal state`);
20869
21257
  return;
20870
21258
  }
20871
- log8.error(`Backstop: failed to report crash for task ${task.id}`, e);
21259
+ log9.error(`Backstop: failed to report crash for task ${task.id}`, e);
20872
21260
  try {
20873
21261
  await writeMarkerFile(config2.workspacesRoot, {
20874
21262
  taskId: task.id,
@@ -20882,7 +21270,7 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
20882
21270
  }
20883
21271
  }
20884
21272
  });
20885
- log8.info(`Task ${task.id} dispatched to session-runner (pid=${child.pid})`);
21273
+ log9.info(`Task ${task.id} dispatched to session-runner (pid=${child.pid})`);
20886
21274
  }
20887
21275
 
20888
21276
  // commands/daemon.ts
@@ -20920,7 +21308,7 @@ async function startInBackground(profile, serverUrl) {
20920
21308
  return;
20921
21309
  }
20922
21310
  const logPath = daemonLogFilePath();
20923
- mkdirSync8(dirname4(logPath), { recursive: true, mode: 448 });
21311
+ mkdirSync9(dirname4(logPath), { recursive: true, mode: 448 });
20924
21312
  const logFd = openSync2(logPath, "a", 384);
20925
21313
  const child = spawn6(process.execPath, buildChildArgs(profile, serverUrl), {
20926
21314
  detached: true,
@@ -21041,8 +21429,8 @@ function configCommand() {
21041
21429
 
21042
21430
  // commands/email.ts
21043
21431
  import { Command as Command5 } from "commander";
21044
- import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync8, statSync as statSync4 } from "fs";
21045
- import { basename, join as join11 } from "path";
21432
+ import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync10, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
21433
+ import { basename as basename2, join as join12 } from "path";
21046
21434
  import PostalMime from "postal-mime";
21047
21435
 
21048
21436
  // lib/flags.ts
@@ -21056,7 +21444,7 @@ function resolveAgentId(opts) {
21056
21444
  }
21057
21445
 
21058
21446
  // commands/email.ts
21059
- var log9 = createLogger2({ module: "email" });
21447
+ var log10 = createLogger2({ module: "email" });
21060
21448
  var VALID_STATUSES = ["unread", "read", "archived", "sent"];
21061
21449
  var VALID_FOLDERS = ["inbox", "sent", "untrust"];
21062
21450
  var EMAIL_BASE = tempDir("alook-emails");
@@ -21153,7 +21541,7 @@ function emailCommand() {
21153
21541
  process.exit(1);
21154
21542
  }
21155
21543
  }
21156
- const emailDir_base = join11(EMAIL_BASE, workspaceId, agentId);
21544
+ const emailDir_base = join12(EMAIL_BASE, workspaceId, agentId);
21157
21545
  try {
21158
21546
  let query = `/api/email?agentId=${agentId}`;
21159
21547
  if (opts.status)
@@ -21173,11 +21561,11 @@ function emailCommand() {
21173
21561
  printJSON(emails2);
21174
21562
  return;
21175
21563
  }
21176
- mkdirSync9(emailDir_base, { recursive: true });
21564
+ mkdirSync10(emailDir_base, { recursive: true });
21177
21565
  const downloadedPaths = [];
21178
21566
  for (const email3 of emails2) {
21179
- const emailDir = join11(emailDir_base, email3.id);
21180
- mkdirSync9(emailDir, { recursive: true });
21567
+ const emailDir = join12(emailDir_base, email3.id);
21568
+ mkdirSync10(emailDir, { recursive: true });
21181
21569
  const metadata = {
21182
21570
  id: email3.id,
21183
21571
  from: email3.from_email,
@@ -21189,8 +21577,8 @@ function emailCommand() {
21189
21577
  in_reply_to: email3.in_reply_to || "",
21190
21578
  references: email3.references || ""
21191
21579
  };
21192
- const metadataPath = join11(emailDir, "metadata.json");
21193
- writeFileSync7(metadataPath, JSON.stringify(metadata, null, 2));
21580
+ const metadataPath = join12(emailDir, "metadata.json");
21581
+ writeFileSync8(metadataPath, JSON.stringify(metadata, null, 2));
21194
21582
  downloadedPaths.push(metadataPath);
21195
21583
  let rawMime;
21196
21584
  try {
@@ -21198,25 +21586,25 @@ function emailCommand() {
21198
21586
  } catch (err) {
21199
21587
  const msg = err instanceof Error ? err.message : String(err);
21200
21588
  if (msg.includes("404")) {
21201
- log9.warn(`email body not available for ${email3.id}, skipping`);
21589
+ log10.warn(`email body not available for ${email3.id}, skipping`);
21202
21590
  continue;
21203
21591
  }
21204
21592
  throw err;
21205
21593
  }
21206
21594
  const parsed = await new PostalMime().parse(rawMime);
21207
21595
  if (parsed.text) {
21208
- const bodyPath = join11(emailDir, "body.txt");
21209
- writeFileSync7(bodyPath, parsed.text);
21596
+ const bodyPath = join12(emailDir, "body.txt");
21597
+ writeFileSync8(bodyPath, parsed.text);
21210
21598
  downloadedPaths.push(bodyPath);
21211
21599
  }
21212
21600
  if (parsed.html) {
21213
- const htmlPath = join11(emailDir, "body.html");
21214
- writeFileSync7(htmlPath, parsed.html);
21601
+ const htmlPath = join12(emailDir, "body.html");
21602
+ writeFileSync8(htmlPath, parsed.html);
21215
21603
  downloadedPaths.push(htmlPath);
21216
21604
  }
21217
21605
  if (parsed.attachments && parsed.attachments.length > 0) {
21218
- const attDir = join11(emailDir, "attachments");
21219
- mkdirSync9(attDir, { recursive: true });
21606
+ const attDir = join12(emailDir, "attachments");
21607
+ mkdirSync10(attDir, { recursive: true });
21220
21608
  const usedFilenames = new Set;
21221
21609
  for (let i = 0;i < parsed.attachments.length; i++) {
21222
21610
  const att = parsed.attachments[i];
@@ -21225,7 +21613,7 @@ function emailCommand() {
21225
21613
  filename = `${i}-${filename}`;
21226
21614
  }
21227
21615
  usedFilenames.add(filename);
21228
- const attPath = join11(attDir, filename);
21616
+ const attPath = join12(attDir, filename);
21229
21617
  const content = att.content;
21230
21618
  let buf;
21231
21619
  if (typeof content === "string") {
@@ -21235,7 +21623,7 @@ function emailCommand() {
21235
21623
  } else {
21236
21624
  buf = Buffer.from(content);
21237
21625
  }
21238
- writeFileSync7(attPath, buf);
21626
+ writeFileSync8(attPath, buf);
21239
21627
  downloadedPaths.push(attPath);
21240
21628
  }
21241
21629
  }
@@ -21276,7 +21664,7 @@ function emailCommand() {
21276
21664
  const client = new APIClient(serverUrl, token, workspaceId);
21277
21665
  let htmlBody;
21278
21666
  try {
21279
- htmlBody = readFileSync8(opts.bodyFile, "utf-8");
21667
+ htmlBody = readFileSync9(opts.bodyFile, "utf-8");
21280
21668
  } catch (err) {
21281
21669
  console.error(`Error: cannot read body file "${opts.bodyFile}": ${err instanceof Error ? err.message : err}`);
21282
21670
  process.exit(1);
@@ -21292,13 +21680,13 @@ function emailCommand() {
21292
21680
  let bytes;
21293
21681
  let size;
21294
21682
  try {
21295
- bytes = readFileSync8(path2);
21296
- size = statSync4(path2).size;
21683
+ bytes = readFileSync9(path2);
21684
+ size = statSync5(path2).size;
21297
21685
  } catch (err) {
21298
21686
  console.error(`Error: cannot read attachment "${path2}": ${err instanceof Error ? err.message : err}`);
21299
21687
  process.exit(1);
21300
21688
  }
21301
- const filename = basename(path2);
21689
+ const filename = basename2(path2);
21302
21690
  const contentType = guessContentType(filename);
21303
21691
  const form = new FormData;
21304
21692
  form.append("file", new Blob([new Uint8Array(bytes)], { type: contentType }), filename);
@@ -21320,7 +21708,7 @@ function emailCommand() {
21320
21708
  references = [parentEmail.references, parentEmail.message_id].filter(Boolean).join(" ").trim() || undefined;
21321
21709
  }
21322
21710
  } catch {
21323
- log9.warn(`could not fetch parent email ${opts.inReplyTo}, sending without threading`);
21711
+ log10.warn(`could not fetch parent email ${opts.inReplyTo}, sending without threading`);
21324
21712
  }
21325
21713
  }
21326
21714
  const conversationId = process.env.ALOOK_CONVERSATION_ID;
@@ -21405,13 +21793,13 @@ function emailCommand() {
21405
21793
  let bytes;
21406
21794
  let size;
21407
21795
  try {
21408
- bytes = readFileSync8(path2);
21409
- size = statSync4(path2).size;
21796
+ bytes = readFileSync9(path2);
21797
+ size = statSync5(path2).size;
21410
21798
  } catch (err) {
21411
21799
  console.error(`Error: cannot read attachment "${path2}": ${err instanceof Error ? err.message : err}`);
21412
21800
  process.exit(1);
21413
21801
  }
21414
- const filename = basename(path2);
21802
+ const filename = basename2(path2);
21415
21803
  const contentType = guessContentType(filename);
21416
21804
  const form = new FormData;
21417
21805
  form.append("file", new Blob([new Uint8Array(bytes)], { type: contentType }), filename);
@@ -21752,7 +22140,7 @@ function calendarCommand() {
21752
22140
 
21753
22141
  // commands/issue.ts
21754
22142
  import { Command as Command7 } from "commander";
21755
- import { readFileSync as readFileSync9 } from "fs";
22143
+ import { readFileSync as readFileSync10 } from "fs";
21756
22144
  var VALID_STATUSES2 = ["todo", "in_progress", "review", "done", "closed", "canceled", "failed"];
21757
22145
  function resolveClientOpts3(command, agentId) {
21758
22146
  let root = command;
@@ -21776,7 +22164,7 @@ function readBody(opts) {
21776
22164
  process.exit(1);
21777
22165
  }
21778
22166
  if (opts.bodyFile)
21779
- return readFileSync9(opts.bodyFile, "utf-8");
22167
+ return readFileSync10(opts.bodyFile, "utf-8");
21780
22168
  return opts.body ?? "";
21781
22169
  }
21782
22170
  function printIssue(issue3) {
@@ -21974,8 +22362,8 @@ ${result.output}`);
21974
22362
 
21975
22363
  // commands/sync.ts
21976
22364
  import { Command as Command10 } from "commander";
21977
- import { readFileSync as readFileSync10 } from "fs";
21978
- import { basename as basename2 } from "path";
22365
+ import { readFileSync as readFileSync11 } from "fs";
22366
+ import { basename as basename3 } from "path";
21979
22367
  var MIME_BY_EXT2 = {
21980
22368
  ".pdf": "application/pdf",
21981
22369
  ".png": "image/png",
@@ -22023,12 +22411,12 @@ function syncCommand() {
22023
22411
  const client = new APIClient(serverUrl, token, workspaceId);
22024
22412
  let bytes;
22025
22413
  try {
22026
- bytes = readFileSync10(opts.file);
22414
+ bytes = readFileSync11(opts.file);
22027
22415
  } catch (err) {
22028
22416
  console.error(`Error: cannot read file "${opts.file}": ${err.message}`);
22029
22417
  process.exit(1);
22030
22418
  }
22031
- const filename = basename2(opts.file);
22419
+ const filename = basename3(opts.file);
22032
22420
  const contentType = guessContentType2(filename);
22033
22421
  const form = new FormData;
22034
22422
  form.append("file", new Blob([new Uint8Array(bytes)], { type: contentType }), filename);