@alook/cli 0.0.91 → 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 +545 -154
- package/dist/session-runner.js +66 -28
- package/package.json +3 -3
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
@@ -18257,6 +18292,9 @@ class OpenCodeBackend {
|
|
|
18257
18292
|
if (options.resumeSessionId) {
|
|
18258
18293
|
args.push("--session", options.resumeSessionId);
|
|
18259
18294
|
}
|
|
18295
|
+
if (options.cwd) {
|
|
18296
|
+
args.push("--dir", options.cwd);
|
|
18297
|
+
}
|
|
18260
18298
|
args.push(prompt);
|
|
18261
18299
|
const proc = spawn3(this.cliPath, args, {
|
|
18262
18300
|
cwd: options.cwd,
|
|
@@ -19999,6 +20037,349 @@ function validatePath(agentWorkdir, requestedPath) {
|
|
|
19999
20037
|
return resolved;
|
|
20000
20038
|
}
|
|
20001
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
|
+
|
|
20002
20383
|
// lib/shell-env.ts
|
|
20003
20384
|
import { execSync as execSync3 } from "child_process";
|
|
20004
20385
|
var PASSTHROUGH_VARS = ["ALOOK_PROJECT_ROOT", "ALOOK_SERVER_URL", "ALOOK_CMD_PREFIX", "ALOOK_HEALTH_PORT"];
|
|
@@ -20033,15 +20414,15 @@ function resolveLoginShellEnv() {
|
|
|
20033
20414
|
}
|
|
20034
20415
|
|
|
20035
20416
|
// daemon/daemon.ts
|
|
20036
|
-
import { existsSync as
|
|
20417
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync8, openSync, closeSync, readdirSync as readdirSync3, statSync as statSync4, unlinkSync as unlinkSync5 } from "fs";
|
|
20037
20418
|
import { readdir as readdir2, readFile as readFile2, unlink, stat as fsStat } from "fs/promises";
|
|
20038
20419
|
import { execSync as execSync4, spawn as spawn5 } from "child_process";
|
|
20039
20420
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
20040
|
-
import { dirname as dirname3, join as
|
|
20041
|
-
var
|
|
20421
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
20422
|
+
var log9 = createLogger2({ module: "daemon" });
|
|
20042
20423
|
var _dir = dirname3(fileURLToPath2(import.meta.url));
|
|
20043
|
-
var sessionRunnerPath =
|
|
20044
|
-
var meetingRunnerPath =
|
|
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");
|
|
20045
20426
|
function isCommandAvailable2(cmd) {
|
|
20046
20427
|
try {
|
|
20047
20428
|
const check2 = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
@@ -20056,16 +20437,16 @@ function pruneSessionRunnerLogs() {
|
|
|
20056
20437
|
const logDir = sessionRunnerLogDir();
|
|
20057
20438
|
let entries;
|
|
20058
20439
|
try {
|
|
20059
|
-
entries =
|
|
20440
|
+
entries = readdirSync3(logDir).filter((f) => f.endsWith(".log"));
|
|
20060
20441
|
} catch {
|
|
20061
20442
|
return;
|
|
20062
20443
|
}
|
|
20063
20444
|
if (entries.length <= MAX_SESSION_RUNNER_LOGS)
|
|
20064
20445
|
return;
|
|
20065
20446
|
const withMtime = entries.map((name) => {
|
|
20066
|
-
const full =
|
|
20447
|
+
const full = join11(logDir, name);
|
|
20067
20448
|
try {
|
|
20068
|
-
return { name, mtime:
|
|
20449
|
+
return { name, mtime: statSync4(full).mtimeMs };
|
|
20069
20450
|
} catch {
|
|
20070
20451
|
return { name, mtime: 0 };
|
|
20071
20452
|
}
|
|
@@ -20073,7 +20454,7 @@ function pruneSessionRunnerLogs() {
|
|
|
20073
20454
|
withMtime.sort((a, b) => b.mtime - a.mtime);
|
|
20074
20455
|
for (const entry of withMtime.slice(MAX_SESSION_RUNNER_LOGS)) {
|
|
20075
20456
|
try {
|
|
20076
|
-
unlinkSync5(
|
|
20457
|
+
unlinkSync5(join11(logDir, entry.name));
|
|
20077
20458
|
} catch {}
|
|
20078
20459
|
}
|
|
20079
20460
|
}
|
|
@@ -20114,7 +20495,7 @@ function isValidMarker(data) {
|
|
|
20114
20495
|
var MARKER_STALE_MS = 24 * 60 * 60 * 1000;
|
|
20115
20496
|
var TMP_STALE_MS = 60 * 60 * 1000;
|
|
20116
20497
|
async function reconcilePendingCompletions(workspacesRoot) {
|
|
20117
|
-
const dir =
|
|
20498
|
+
const dir = join11(workspacesRoot, ".pending_completions");
|
|
20118
20499
|
let entries;
|
|
20119
20500
|
try {
|
|
20120
20501
|
entries = await readdir2(dir);
|
|
@@ -20125,15 +20506,15 @@ async function reconcilePendingCompletions(workspacesRoot) {
|
|
|
20125
20506
|
if (!name.endsWith(".tmp"))
|
|
20126
20507
|
continue;
|
|
20127
20508
|
try {
|
|
20128
|
-
const s = await fsStat(
|
|
20509
|
+
const s = await fsStat(join11(dir, name));
|
|
20129
20510
|
if (Date.now() - s.mtimeMs > TMP_STALE_MS) {
|
|
20130
|
-
await unlink(
|
|
20511
|
+
await unlink(join11(dir, name));
|
|
20131
20512
|
}
|
|
20132
20513
|
} catch {}
|
|
20133
20514
|
}
|
|
20134
20515
|
const jsonFiles = entries.filter((f) => f.endsWith(".json"));
|
|
20135
20516
|
for (const name of jsonFiles) {
|
|
20136
|
-
const filePath =
|
|
20517
|
+
const filePath = join11(dir, name);
|
|
20137
20518
|
try {
|
|
20138
20519
|
let raw;
|
|
20139
20520
|
try {
|
|
@@ -20145,14 +20526,14 @@ async function reconcilePendingCompletions(workspacesRoot) {
|
|
|
20145
20526
|
try {
|
|
20146
20527
|
parsed = JSON.parse(raw);
|
|
20147
20528
|
} catch {
|
|
20148
|
-
|
|
20529
|
+
log9.warn(`reconcile: malformed marker ${name}, deleting`);
|
|
20149
20530
|
try {
|
|
20150
20531
|
await unlink(filePath);
|
|
20151
20532
|
} catch {}
|
|
20152
20533
|
continue;
|
|
20153
20534
|
}
|
|
20154
20535
|
if (!isValidMarker(parsed)) {
|
|
20155
|
-
|
|
20536
|
+
log9.warn(`reconcile: invalid marker structure ${name}, deleting`);
|
|
20156
20537
|
try {
|
|
20157
20538
|
await unlink(filePath);
|
|
20158
20539
|
} catch {}
|
|
@@ -20161,7 +20542,7 @@ async function reconcilePendingCompletions(workspacesRoot) {
|
|
|
20161
20542
|
const marker = parsed;
|
|
20162
20543
|
const age = Date.now() - new Date(marker.createdAt).getTime();
|
|
20163
20544
|
if (age > MARKER_STALE_MS) {
|
|
20164
|
-
|
|
20545
|
+
log9.warn(`reconcile: stale marker ${name} (${Math.round(age / 3600000)}h old), deleting`);
|
|
20165
20546
|
try {
|
|
20166
20547
|
await unlink(filePath);
|
|
20167
20548
|
} catch {}
|
|
@@ -20177,7 +20558,7 @@ async function reconcilePendingCompletions(workspacesRoot) {
|
|
|
20177
20558
|
try {
|
|
20178
20559
|
await unlink(filePath);
|
|
20179
20560
|
} catch (delErr) {
|
|
20180
|
-
|
|
20561
|
+
log9.warn(`reconcile: delivered marker ${name} but failed to delete: ${delErr}`);
|
|
20181
20562
|
}
|
|
20182
20563
|
} catch (deliverErr) {
|
|
20183
20564
|
if (isClientError2(deliverErr)) {
|
|
@@ -20185,11 +20566,11 @@ async function reconcilePendingCompletions(workspacesRoot) {
|
|
|
20185
20566
|
await unlink(filePath);
|
|
20186
20567
|
} catch {}
|
|
20187
20568
|
} else {
|
|
20188
|
-
|
|
20569
|
+
log9.debug(`reconcile: delivery failed for ${name}, will retry next cycle`);
|
|
20189
20570
|
}
|
|
20190
20571
|
}
|
|
20191
20572
|
} catch (e) {
|
|
20192
|
-
|
|
20573
|
+
log9.debug(`reconcile: error processing ${name}`, e);
|
|
20193
20574
|
}
|
|
20194
20575
|
}
|
|
20195
20576
|
}
|
|
@@ -20200,7 +20581,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20200
20581
|
}
|
|
20201
20582
|
process.once("exit", () => releaseDaemonPid(profile));
|
|
20202
20583
|
const bailOnUnexpected = (label, err) => {
|
|
20203
|
-
|
|
20584
|
+
log9.error(`${label} — shutting down`, err);
|
|
20204
20585
|
releaseDaemonPid(profile);
|
|
20205
20586
|
process.exit(1);
|
|
20206
20587
|
};
|
|
@@ -20213,21 +20594,21 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20213
20594
|
if (marker) {
|
|
20214
20595
|
clearUpdateMarker(profile);
|
|
20215
20596
|
if (marker === config2.cliVersion) {
|
|
20216
|
-
|
|
20597
|
+
log9.info(`Cleared update marker — now running v${config2.cliVersion}`);
|
|
20217
20598
|
} else {
|
|
20218
|
-
|
|
20599
|
+
log9.info(`Cleared stale update marker (was v${marker}, running v${config2.cliVersion}) — update will be retried`);
|
|
20219
20600
|
}
|
|
20220
20601
|
}
|
|
20221
20602
|
const cliConfig = loadCLIConfigForProfile(profile);
|
|
20222
20603
|
const workspaces = cliConfig.watched_workspaces || [];
|
|
20223
20604
|
if (workspaces.length === 0) {
|
|
20224
|
-
|
|
20605
|
+
log9.error("No watched workspaces configured.");
|
|
20225
20606
|
process.exit(1);
|
|
20226
20607
|
return;
|
|
20227
20608
|
}
|
|
20228
20609
|
const hasPerWorkspaceTokens = workspaces.every((ws) => !!ws.token);
|
|
20229
20610
|
if (!hasPerWorkspaceTokens) {
|
|
20230
|
-
|
|
20611
|
+
log9.error(`Config uses old format. Run '${cmdPrefix()} register --token <token>' for each workspace to upgrade.`);
|
|
20231
20612
|
process.exit(1);
|
|
20232
20613
|
return;
|
|
20233
20614
|
}
|
|
@@ -20247,11 +20628,11 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20247
20628
|
}
|
|
20248
20629
|
}
|
|
20249
20630
|
if (providers.length === 0) {
|
|
20250
|
-
|
|
20631
|
+
log9.error("No agent CLI tools found on PATH.");
|
|
20251
20632
|
process.exit(1);
|
|
20252
20633
|
return;
|
|
20253
20634
|
}
|
|
20254
|
-
|
|
20635
|
+
log9.info(`Detected providers: ${providers.map((p) => `${p.type}@${p.version}`).join(", ")}`);
|
|
20255
20636
|
const workspaceStates = [];
|
|
20256
20637
|
const runtimeIndex = new Map;
|
|
20257
20638
|
for (const ws of workspaces) {
|
|
@@ -20259,7 +20640,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20259
20640
|
type: p.type,
|
|
20260
20641
|
version: p.version
|
|
20261
20642
|
}));
|
|
20262
|
-
|
|
20643
|
+
log9.info(`Registering workspace ${ws.id} (${ws.name ?? "unnamed"}) with ${runtimes.length} runtime(s)...`);
|
|
20263
20644
|
let resp;
|
|
20264
20645
|
try {
|
|
20265
20646
|
resp = await client.register(ws.token, {
|
|
@@ -20272,13 +20653,13 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20272
20653
|
});
|
|
20273
20654
|
} catch (e) {
|
|
20274
20655
|
if (e instanceof Error && e.message.startsWith("HTTP 401")) {
|
|
20275
|
-
|
|
20656
|
+
log9.warn(`Workspace ${ws.id} token invalid — skipping (run '${cmdPrefix()} register --token <token>' to fix)`);
|
|
20276
20657
|
} else {
|
|
20277
|
-
|
|
20658
|
+
log9.error(`Failed to register workspace ${ws.id}, skipping`, e);
|
|
20278
20659
|
}
|
|
20279
20660
|
continue;
|
|
20280
20661
|
}
|
|
20281
|
-
|
|
20662
|
+
log9.info(`Workspace ${ws.id} registered — ${resp.runtimes.length} runtime(s)`);
|
|
20282
20663
|
const runtimeIds = resp.runtimes.map((r) => r.id);
|
|
20283
20664
|
workspaceStates.push({ workspaceId: ws.id, token: ws.token, runtimeIds });
|
|
20284
20665
|
for (let i = 0;i < runtimeIds.length; i++) {
|
|
@@ -20290,13 +20671,13 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20290
20671
|
}
|
|
20291
20672
|
}
|
|
20292
20673
|
if (workspaceStates.length === 0) {
|
|
20293
|
-
|
|
20674
|
+
log9.error("No workspaces registered successfully.");
|
|
20294
20675
|
process.exit(1);
|
|
20295
20676
|
return;
|
|
20296
20677
|
}
|
|
20297
20678
|
const allRuntimeIds = workspaceStates.flatMap((ws) => ws.runtimeIds);
|
|
20298
20679
|
health.setRuntimeCount(allRuntimeIds.length);
|
|
20299
|
-
|
|
20680
|
+
log9.info(`Daemon started — ${allRuntimeIds.length} runtime(s) across ${workspaceStates.length} workspace(s)`);
|
|
20300
20681
|
const activeTasks = new Set;
|
|
20301
20682
|
const knownAgentIds = new Set(workspaces.flatMap((ws) => ws.agent_ids ?? []));
|
|
20302
20683
|
function syncAgentId(agentId, workspaceId) {
|
|
@@ -20331,7 +20712,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20331
20712
|
cfg.watched_workspaces = (cfg.watched_workspaces || []).filter((w) => w.id !== workspaceId);
|
|
20332
20713
|
saveCLIConfigForProfile(profile, cfg);
|
|
20333
20714
|
} catch {}
|
|
20334
|
-
|
|
20715
|
+
log9.info(`Workspace ${workspaceId} deleted server-side — removed from config`);
|
|
20335
20716
|
}
|
|
20336
20717
|
const pollCycle = async () => {
|
|
20337
20718
|
let remaining = config2.maxConcurrentTasks - activeTasks.size;
|
|
@@ -20357,7 +20738,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20357
20738
|
handleCliUpdate(pending_update.version, () => requestRestart(), profile);
|
|
20358
20739
|
}
|
|
20359
20740
|
if (pending_rescan) {
|
|
20360
|
-
|
|
20741
|
+
log9.info("Rescan requested — restarting daemon to re-detect runtimes");
|
|
20361
20742
|
for (const id of evictedIds) {
|
|
20362
20743
|
evictWorkspace(id);
|
|
20363
20744
|
}
|
|
@@ -20370,19 +20751,19 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20370
20751
|
activeTasks.add(task.id);
|
|
20371
20752
|
remaining--;
|
|
20372
20753
|
handleTask(client, config2, runtimeIndex, task, ws.token, activeTasks).catch((e) => {
|
|
20373
|
-
|
|
20754
|
+
log9.error("Task error", e);
|
|
20374
20755
|
activeTasks.delete(task.id);
|
|
20375
20756
|
});
|
|
20376
20757
|
}
|
|
20377
20758
|
if (file_requests) {
|
|
20378
20759
|
for (const req of file_requests) {
|
|
20379
|
-
handleFileRequest(client, config2, ws.workspaceId, req, ws.token).catch((e) =>
|
|
20760
|
+
handleFileRequest(client, config2, ws.workspaceId, req, ws.token).catch((e) => log9.debug("File request error", e));
|
|
20380
20761
|
}
|
|
20381
20762
|
}
|
|
20382
20763
|
if (meetings) {
|
|
20383
20764
|
for (const m of meetings) {
|
|
20384
|
-
const agentBaseDir =
|
|
20385
|
-
const timelineDir =
|
|
20765
|
+
const agentBaseDir = join11(config2.workspacesRoot, m.workspace_id, m.agent_id, "workdir");
|
|
20766
|
+
const timelineDir = join11(agentBaseDir, ".context_timeline");
|
|
20386
20767
|
spawnMeetingRunner({
|
|
20387
20768
|
meetingId: m.id,
|
|
20388
20769
|
meetingUrl: m.meeting_url,
|
|
@@ -20399,9 +20780,9 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20399
20780
|
}
|
|
20400
20781
|
} catch (e) {
|
|
20401
20782
|
if (e instanceof Error && e.message.startsWith("HTTP 401")) {
|
|
20402
|
-
|
|
20783
|
+
log9.warn(`Workspace ${ws.workspaceId} poll returned 401 — will retry next cycle`);
|
|
20403
20784
|
} else {
|
|
20404
|
-
|
|
20785
|
+
log9.debug("Poll error", e);
|
|
20405
20786
|
}
|
|
20406
20787
|
}
|
|
20407
20788
|
}
|
|
@@ -20409,7 +20790,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20409
20790
|
evictWorkspace(id);
|
|
20410
20791
|
}
|
|
20411
20792
|
if (workspaceStates.length === 0) {
|
|
20412
|
-
|
|
20793
|
+
log9.info("All workspaces evicted — shutting down");
|
|
20413
20794
|
shutdown();
|
|
20414
20795
|
}
|
|
20415
20796
|
};
|
|
@@ -20417,7 +20798,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20417
20798
|
const heartbeatPing = () => {
|
|
20418
20799
|
for (const ws of workspaceStates) {
|
|
20419
20800
|
client.heartbeat(ws.token, config2.daemonId).catch((e) => {
|
|
20420
|
-
|
|
20801
|
+
log9.debug("heartbeat failed", { workspaceId: ws.workspaceId, err: String(e) });
|
|
20421
20802
|
});
|
|
20422
20803
|
}
|
|
20423
20804
|
};
|
|
@@ -20442,7 +20823,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20442
20823
|
syncAgentId(task.agentId, ws.workspaceId);
|
|
20443
20824
|
activeTasks.add(task.id);
|
|
20444
20825
|
handleTask(client, config2, runtimeIndex, task, ws.token, activeTasks).catch((e) => {
|
|
20445
|
-
|
|
20826
|
+
log9.error("WS task error", e);
|
|
20446
20827
|
activeTasks.delete(task.id);
|
|
20447
20828
|
});
|
|
20448
20829
|
}
|
|
@@ -20451,7 +20832,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20451
20832
|
const ws = workspaceStates.find((w) => w.workspaceId === msg.workspaceId);
|
|
20452
20833
|
if (ws) {
|
|
20453
20834
|
for (const req of msg.requests) {
|
|
20454
|
-
handleFileRequest(client, config2, ws.workspaceId, req, ws.token).catch((e) =>
|
|
20835
|
+
handleFileRequest(client, config2, ws.workspaceId, req, ws.token).catch((e) => log9.debug("WS file request error", e));
|
|
20455
20836
|
}
|
|
20456
20837
|
}
|
|
20457
20838
|
break;
|
|
@@ -20461,8 +20842,8 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20461
20842
|
const ws = workspaceStates.find((w) => w.workspaceId === m.workspace_id);
|
|
20462
20843
|
if (!ws)
|
|
20463
20844
|
continue;
|
|
20464
|
-
const agentBaseDir =
|
|
20465
|
-
const timelineDir =
|
|
20845
|
+
const agentBaseDir = join11(config2.workspacesRoot, m.workspace_id, m.agent_id, "workdir");
|
|
20846
|
+
const timelineDir = join11(agentBaseDir, ".context_timeline");
|
|
20466
20847
|
spawnMeetingRunner({
|
|
20467
20848
|
meetingId: m.id,
|
|
20468
20849
|
meetingUrl: m.meeting_url,
|
|
@@ -20486,7 +20867,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20486
20867
|
}
|
|
20487
20868
|
break;
|
|
20488
20869
|
case "daemon.rescan":
|
|
20489
|
-
|
|
20870
|
+
log9.info("WS rescan requested — restarting daemon");
|
|
20490
20871
|
requestRestart();
|
|
20491
20872
|
break;
|
|
20492
20873
|
case "daemon.kill": {
|
|
@@ -20514,7 +20895,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20514
20895
|
});
|
|
20515
20896
|
activeTasks.add(killTask.id);
|
|
20516
20897
|
handleTask(client, config2, runtimeIndex, killTask, ws.token, activeTasks).catch((e) => {
|
|
20517
|
-
|
|
20898
|
+
log9.error("WS kill task error", e);
|
|
20518
20899
|
activeTasks.delete(killTask.id);
|
|
20519
20900
|
});
|
|
20520
20901
|
}
|
|
@@ -20528,11 +20909,11 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20528
20909
|
machineToken: firstToken,
|
|
20529
20910
|
onMessage: handleWsPush,
|
|
20530
20911
|
onConnected: () => {
|
|
20531
|
-
|
|
20912
|
+
log9.info("WS connected — switching to low-frequency poll");
|
|
20532
20913
|
updatePollInterval(config2.wsPollInterval);
|
|
20533
20914
|
},
|
|
20534
20915
|
onDisconnected: () => {
|
|
20535
|
-
|
|
20916
|
+
log9.info("WS disconnected — reverting to high-frequency poll");
|
|
20536
20917
|
updatePollInterval(config2.pollInterval);
|
|
20537
20918
|
}
|
|
20538
20919
|
}) : null;
|
|
@@ -20540,16 +20921,25 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20540
20921
|
const sweepTick = async () => {
|
|
20541
20922
|
for (const ws of workspaceStates) {
|
|
20542
20923
|
client.sweep(ws.token, config2.daemonId).catch((e) => {
|
|
20543
|
-
|
|
20924
|
+
log9.debug("sweep ping failed", { workspaceId: ws.workspaceId, err: String(e) });
|
|
20544
20925
|
});
|
|
20545
20926
|
}
|
|
20546
20927
|
try {
|
|
20547
20928
|
await reconcilePendingCompletions(config2.workspacesRoot);
|
|
20548
20929
|
} catch (e) {
|
|
20549
|
-
|
|
20930
|
+
log9.debug("reconciliation error", e);
|
|
20550
20931
|
}
|
|
20551
20932
|
};
|
|
20552
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);
|
|
20553
20943
|
let shuttingDown = false;
|
|
20554
20944
|
let restartRequested = false;
|
|
20555
20945
|
const requestRestart = () => {
|
|
@@ -20560,10 +20950,11 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20560
20950
|
if (shuttingDown)
|
|
20561
20951
|
return;
|
|
20562
20952
|
shuttingDown = true;
|
|
20563
|
-
|
|
20953
|
+
log9.info(restartRequested ? "Restarting..." : "Shutting down...");
|
|
20564
20954
|
clearInterval(pollTimer);
|
|
20565
20955
|
clearInterval(heartbeatTimer);
|
|
20566
20956
|
clearInterval(sweepTimer);
|
|
20957
|
+
stopSkillScanner();
|
|
20567
20958
|
wsClient?.close();
|
|
20568
20959
|
const shutdownMs = restartRequested ? 30000 : Number(process.env.ALOOK_SHUTDOWN_TIMEOUT_MS) || 5000;
|
|
20569
20960
|
const timeout = setTimeout(() => process.exit(1), shutdownMs);
|
|
@@ -20584,10 +20975,10 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20584
20975
|
const logPath = daemonLogFilePath();
|
|
20585
20976
|
let logFd;
|
|
20586
20977
|
try {
|
|
20587
|
-
|
|
20978
|
+
mkdirSync8(dirname3(logPath), { recursive: true, mode: 448 });
|
|
20588
20979
|
logFd = openSync(logPath, "a", 384);
|
|
20589
20980
|
} catch (e) {
|
|
20590
|
-
|
|
20981
|
+
log9.error(`Failed to open daemon log file ${logPath}`, e);
|
|
20591
20982
|
}
|
|
20592
20983
|
const child = spawn5(process.execPath, args, {
|
|
20593
20984
|
detached: true,
|
|
@@ -20597,7 +20988,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20597
20988
|
child.unref();
|
|
20598
20989
|
if (logFd != null)
|
|
20599
20990
|
closeSync(logFd);
|
|
20600
|
-
|
|
20991
|
+
log9.info(`Spawned new daemon (pid=${child.pid}), logs: ${logPath}`);
|
|
20601
20992
|
}
|
|
20602
20993
|
clearTimeout(timeout);
|
|
20603
20994
|
process.exit(0);
|
|
@@ -20608,7 +20999,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20608
20999
|
process.on("SIGHUP", async () => {
|
|
20609
21000
|
if (shuttingDown)
|
|
20610
21001
|
return;
|
|
20611
|
-
|
|
21002
|
+
log9.info("SIGHUP received — reloading config...");
|
|
20612
21003
|
try {
|
|
20613
21004
|
const freshConfig = loadCLIConfigForProfile(profile);
|
|
20614
21005
|
const freshWorkspaces = freshConfig.watched_workspaces || [];
|
|
@@ -20616,7 +21007,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20616
21007
|
const newWorkspaces = freshWorkspaces.filter((ws) => ws.token && !existingIds.has(ws.id));
|
|
20617
21008
|
for (const ws of newWorkspaces) {
|
|
20618
21009
|
const runtimes = providers.map((p) => ({ type: p.type, version: p.version }));
|
|
20619
|
-
|
|
21010
|
+
log9.info(`Registering new workspace ${ws.id} (${ws.name ?? "unnamed"})...`);
|
|
20620
21011
|
try {
|
|
20621
21012
|
const resp = await client.register(ws.token, {
|
|
20622
21013
|
workspace_id: ws.id,
|
|
@@ -20635,34 +21026,34 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20635
21026
|
provider: providers[i].type
|
|
20636
21027
|
});
|
|
20637
21028
|
}
|
|
20638
|
-
|
|
21029
|
+
log9.info(`Workspace ${ws.id} added — ${runtimeIds.length} runtime(s)`);
|
|
20639
21030
|
} catch (e) {
|
|
20640
|
-
|
|
21031
|
+
log9.error(`Failed to register new workspace ${ws.id}`, e);
|
|
20641
21032
|
}
|
|
20642
21033
|
}
|
|
20643
21034
|
if (newWorkspaces.length > 0) {
|
|
20644
21035
|
health.setRuntimeCount(workspaceStates.reduce((sum, w) => sum + w.runtimeIds.length, 0));
|
|
20645
|
-
|
|
21036
|
+
log9.info(`Reload complete — now polling ${workspaceStates.length} workspace(s)`);
|
|
20646
21037
|
} else {
|
|
20647
|
-
|
|
21038
|
+
log9.info("Reload complete — no new workspaces found");
|
|
20648
21039
|
}
|
|
20649
21040
|
} catch (e) {
|
|
20650
|
-
|
|
21041
|
+
log9.error("Failed to reload config", e);
|
|
20651
21042
|
}
|
|
20652
21043
|
});
|
|
20653
21044
|
await pollCycle();
|
|
20654
21045
|
}
|
|
20655
21046
|
function spawnSessionRunner(input) {
|
|
20656
21047
|
const logDir = sessionRunnerLogDir();
|
|
20657
|
-
|
|
20658
|
-
const logFilePath =
|
|
21048
|
+
mkdirSync8(logDir, { recursive: true });
|
|
21049
|
+
const logFilePath = join11(logDir, `${input.task.id}.log`);
|
|
20659
21050
|
input.logFilePath = logFilePath;
|
|
20660
21051
|
const encoded = Buffer.from(JSON.stringify(input)).toString("base64");
|
|
20661
21052
|
let fd;
|
|
20662
21053
|
try {
|
|
20663
21054
|
fd = openSync(logFilePath, "a");
|
|
20664
21055
|
} catch (e) {
|
|
20665
|
-
|
|
21056
|
+
log9.error(`Failed to open log file ${logFilePath}`, e);
|
|
20666
21057
|
}
|
|
20667
21058
|
const child = spawn5(process.execPath, [sessionRunnerPath, encoded], {
|
|
20668
21059
|
detached: true,
|
|
@@ -20675,14 +21066,14 @@ function spawnSessionRunner(input) {
|
|
|
20675
21066
|
}
|
|
20676
21067
|
function spawnMeetingRunner(input) {
|
|
20677
21068
|
const logDir = sessionRunnerLogDir();
|
|
20678
|
-
|
|
20679
|
-
const logFilePath =
|
|
21069
|
+
mkdirSync8(logDir, { recursive: true });
|
|
21070
|
+
const logFilePath = join11(logDir, `meeting-${input.meetingId}.log`);
|
|
20680
21071
|
const encoded = Buffer.from(JSON.stringify(input)).toString("base64");
|
|
20681
21072
|
let fd;
|
|
20682
21073
|
try {
|
|
20683
21074
|
fd = openSync(logFilePath, "a");
|
|
20684
21075
|
} catch (e) {
|
|
20685
|
-
|
|
21076
|
+
log9.error(`Failed to open meeting log file ${logFilePath}`, e);
|
|
20686
21077
|
}
|
|
20687
21078
|
const child = spawn5(process.execPath, [meetingRunnerPath, encoded], {
|
|
20688
21079
|
detached: true,
|
|
@@ -20691,11 +21082,11 @@ function spawnMeetingRunner(input) {
|
|
|
20691
21082
|
child.unref();
|
|
20692
21083
|
if (fd != null)
|
|
20693
21084
|
closeSync(fd);
|
|
20694
|
-
|
|
21085
|
+
log9.info(`Spawned meeting runner for ${input.meetingId} (pid=${child.pid})`);
|
|
20695
21086
|
return child;
|
|
20696
21087
|
}
|
|
20697
21088
|
async function handleFileRequest(client, config2, workspaceId, req, token) {
|
|
20698
|
-
const agentWorkdir =
|
|
21089
|
+
const agentWorkdir = join11(config2.workspacesRoot, workspaceId, req.agent_id, "workdir");
|
|
20699
21090
|
const resolved = validatePath(agentWorkdir, req.path);
|
|
20700
21091
|
if (!resolved) {
|
|
20701
21092
|
await client.reportFileData(token, { request_id: req.id, error: "invalid path", path: req.path });
|
|
@@ -20718,7 +21109,7 @@ async function handleFileRequest(client, config2, workspaceId, req, token) {
|
|
|
20718
21109
|
}
|
|
20719
21110
|
}
|
|
20720
21111
|
async function handleTask(client, config2, runtimeIndex, task, token, activeTasks) {
|
|
20721
|
-
|
|
21112
|
+
log9.info(`Task ${task.id} claimed agent=${task.agentId}`);
|
|
20722
21113
|
if (task.type === TASK_TYPES.KILL_TASK) {
|
|
20723
21114
|
const targetTaskId = task.context?.target_task_id;
|
|
20724
21115
|
if (!targetTaskId) {
|
|
@@ -20726,8 +21117,8 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
20726
21117
|
activeTasks.delete(task.id);
|
|
20727
21118
|
return;
|
|
20728
21119
|
}
|
|
20729
|
-
const agentBaseDir =
|
|
20730
|
-
const timelineDir =
|
|
21120
|
+
const agentBaseDir = join11(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir");
|
|
21121
|
+
const timelineDir = join11(agentBaseDir, ".context_timeline");
|
|
20731
21122
|
const MAX_WAIT_MS = Number(process.env.ALOOK_KILL_TASK_MAX_WAIT_MS) || 15000;
|
|
20732
21123
|
const POLL_MS = Number(process.env.ALOOK_KILL_TASK_POLL_MS) || 200;
|
|
20733
21124
|
const waitStart = Date.now();
|
|
@@ -20747,18 +21138,18 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
20747
21138
|
try {
|
|
20748
21139
|
process.kill(pid, "SIGTERM");
|
|
20749
21140
|
await client.failTask(token, task.id, "killed");
|
|
20750
|
-
|
|
21141
|
+
log9.info(`Kill task ${task.id}: sent SIGTERM to pid=${pid} for target=${targetTaskId}`);
|
|
20751
21142
|
} catch (e) {
|
|
20752
21143
|
if (e?.code === "ESRCH") {
|
|
20753
21144
|
await client.failTask(token, task.id, "target process already exited");
|
|
20754
|
-
|
|
21145
|
+
log9.info(`Kill task ${task.id}: target pid=${pid} already exited`);
|
|
20755
21146
|
} else {
|
|
20756
21147
|
await client.failTask(token, task.id, `kill failed: ${e}`);
|
|
20757
21148
|
}
|
|
20758
21149
|
}
|
|
20759
21150
|
} else {
|
|
20760
21151
|
await client.failTask(token, task.id, "target not found in timeline");
|
|
20761
|
-
|
|
21152
|
+
log9.info(`Kill task ${task.id}: target ${targetTaskId} not found in timeline`);
|
|
20762
21153
|
}
|
|
20763
21154
|
activeTasks.delete(task.id);
|
|
20764
21155
|
return;
|
|
@@ -20778,17 +21169,17 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
20778
21169
|
}
|
|
20779
21170
|
const provider = runtimeData.provider;
|
|
20780
21171
|
if (task.contextKey) {
|
|
20781
|
-
const agentBaseDir =
|
|
21172
|
+
const agentBaseDir = join11(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir");
|
|
20782
21173
|
cleanupStaleIntents(agentBaseDir);
|
|
20783
|
-
const timelineDir =
|
|
21174
|
+
const timelineDir = join11(agentBaseDir, ".context_timeline");
|
|
20784
21175
|
const lockAcquired = acquireSteeringLock(agentBaseDir, task.contextKey);
|
|
20785
21176
|
if (!lockAcquired) {
|
|
20786
|
-
|
|
21177
|
+
log9.warn(`Steering lock contention for context_key=${task.contextKey}, proceeding without steering`);
|
|
20787
21178
|
} else {
|
|
20788
21179
|
try {
|
|
20789
21180
|
const predecessor = findRunningEntryByContextKey(timelineDir, task.contextKey, provider);
|
|
20790
21181
|
if (predecessor && predecessor.task_id !== task.id) {
|
|
20791
|
-
|
|
21182
|
+
log9.info(`Steering: task ${task.id} supersedes predecessor ${predecessor.task_id} (context_key=${task.contextKey})`);
|
|
20792
21183
|
if (predecessor.pid != null) {
|
|
20793
21184
|
writeKillIntent(agentBaseDir, {
|
|
20794
21185
|
reason: "superseded",
|
|
@@ -20798,12 +21189,12 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
20798
21189
|
});
|
|
20799
21190
|
try {
|
|
20800
21191
|
process.kill(predecessor.pid, "SIGTERM");
|
|
20801
|
-
|
|
21192
|
+
log9.info(`Steering: sent SIGTERM to predecessor pid=${predecessor.pid}`);
|
|
20802
21193
|
} catch (e) {
|
|
20803
21194
|
if (e?.code === "ESRCH") {
|
|
20804
|
-
|
|
21195
|
+
log9.info(`Steering: predecessor pid=${predecessor.pid} already exited`);
|
|
20805
21196
|
} else {
|
|
20806
|
-
|
|
21197
|
+
log9.warn(`Steering: kill failed for pid=${predecessor.pid}`, e);
|
|
20807
21198
|
}
|
|
20808
21199
|
}
|
|
20809
21200
|
const waitStart = Date.now();
|
|
@@ -20816,14 +21207,14 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
20816
21207
|
await new Promise((r) => setTimeout(r, POLL_MS));
|
|
20817
21208
|
}
|
|
20818
21209
|
if (findRunningPidByTaskId(timelineDir, predecessor.task_id) != null) {
|
|
20819
|
-
|
|
21210
|
+
log9.warn(`Steering: predecessor pid=${predecessor.pid} did not exit within ${MAX_WAIT_MS}ms, proceeding anyway`);
|
|
20820
21211
|
}
|
|
20821
21212
|
}
|
|
20822
21213
|
try {
|
|
20823
21214
|
await client.supersedeTask(token, predecessor.task_id);
|
|
20824
|
-
|
|
21215
|
+
log9.info(`Steering: predecessor ${predecessor.task_id} marked superseded`);
|
|
20825
21216
|
} catch (e) {
|
|
20826
|
-
|
|
21217
|
+
log9.warn(`Steering: failed to mark predecessor superseded server-side`, e);
|
|
20827
21218
|
}
|
|
20828
21219
|
}
|
|
20829
21220
|
} finally {
|
|
@@ -20851,8 +21242,8 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
20851
21242
|
activeTasks.delete(task.id);
|
|
20852
21243
|
if (code !== 0) {
|
|
20853
21244
|
const msg = code === null ? `session-runner killed by signal (task ${task.id})` : `session-runner crashed (exit code ${code}, task ${task.id})`;
|
|
20854
|
-
|
|
20855
|
-
const timelineDir =
|
|
21245
|
+
log9.warn(msg);
|
|
21246
|
+
const timelineDir = join11(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir", ".context_timeline");
|
|
20856
21247
|
updateEntry(timelineDir, task.id, (entry) => {
|
|
20857
21248
|
entry.pid = null;
|
|
20858
21249
|
entry.status = "failed";
|
|
@@ -20862,10 +21253,10 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
20862
21253
|
await client.failTask(token, task.id, msg);
|
|
20863
21254
|
} catch (e) {
|
|
20864
21255
|
if (isClientError2(e)) {
|
|
20865
|
-
|
|
21256
|
+
log9.info(`Backstop: task ${task.id} already in terminal state`);
|
|
20866
21257
|
return;
|
|
20867
21258
|
}
|
|
20868
|
-
|
|
21259
|
+
log9.error(`Backstop: failed to report crash for task ${task.id}`, e);
|
|
20869
21260
|
try {
|
|
20870
21261
|
await writeMarkerFile(config2.workspacesRoot, {
|
|
20871
21262
|
taskId: task.id,
|
|
@@ -20879,7 +21270,7 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
20879
21270
|
}
|
|
20880
21271
|
}
|
|
20881
21272
|
});
|
|
20882
|
-
|
|
21273
|
+
log9.info(`Task ${task.id} dispatched to session-runner (pid=${child.pid})`);
|
|
20883
21274
|
}
|
|
20884
21275
|
|
|
20885
21276
|
// commands/daemon.ts
|
|
@@ -20917,7 +21308,7 @@ async function startInBackground(profile, serverUrl) {
|
|
|
20917
21308
|
return;
|
|
20918
21309
|
}
|
|
20919
21310
|
const logPath = daemonLogFilePath();
|
|
20920
|
-
|
|
21311
|
+
mkdirSync9(dirname4(logPath), { recursive: true, mode: 448 });
|
|
20921
21312
|
const logFd = openSync2(logPath, "a", 384);
|
|
20922
21313
|
const child = spawn6(process.execPath, buildChildArgs(profile, serverUrl), {
|
|
20923
21314
|
detached: true,
|
|
@@ -21038,8 +21429,8 @@ function configCommand() {
|
|
|
21038
21429
|
|
|
21039
21430
|
// commands/email.ts
|
|
21040
21431
|
import { Command as Command5 } from "commander";
|
|
21041
|
-
import { writeFileSync as
|
|
21042
|
-
import { basename, join as
|
|
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";
|
|
21043
21434
|
import PostalMime from "postal-mime";
|
|
21044
21435
|
|
|
21045
21436
|
// lib/flags.ts
|
|
@@ -21053,7 +21444,7 @@ function resolveAgentId(opts) {
|
|
|
21053
21444
|
}
|
|
21054
21445
|
|
|
21055
21446
|
// commands/email.ts
|
|
21056
|
-
var
|
|
21447
|
+
var log10 = createLogger2({ module: "email" });
|
|
21057
21448
|
var VALID_STATUSES = ["unread", "read", "archived", "sent"];
|
|
21058
21449
|
var VALID_FOLDERS = ["inbox", "sent", "untrust"];
|
|
21059
21450
|
var EMAIL_BASE = tempDir("alook-emails");
|
|
@@ -21150,7 +21541,7 @@ function emailCommand() {
|
|
|
21150
21541
|
process.exit(1);
|
|
21151
21542
|
}
|
|
21152
21543
|
}
|
|
21153
|
-
const emailDir_base =
|
|
21544
|
+
const emailDir_base = join12(EMAIL_BASE, workspaceId, agentId);
|
|
21154
21545
|
try {
|
|
21155
21546
|
let query = `/api/email?agentId=${agentId}`;
|
|
21156
21547
|
if (opts.status)
|
|
@@ -21170,11 +21561,11 @@ function emailCommand() {
|
|
|
21170
21561
|
printJSON(emails2);
|
|
21171
21562
|
return;
|
|
21172
21563
|
}
|
|
21173
|
-
|
|
21564
|
+
mkdirSync10(emailDir_base, { recursive: true });
|
|
21174
21565
|
const downloadedPaths = [];
|
|
21175
21566
|
for (const email3 of emails2) {
|
|
21176
|
-
const emailDir =
|
|
21177
|
-
|
|
21567
|
+
const emailDir = join12(emailDir_base, email3.id);
|
|
21568
|
+
mkdirSync10(emailDir, { recursive: true });
|
|
21178
21569
|
const metadata = {
|
|
21179
21570
|
id: email3.id,
|
|
21180
21571
|
from: email3.from_email,
|
|
@@ -21186,8 +21577,8 @@ function emailCommand() {
|
|
|
21186
21577
|
in_reply_to: email3.in_reply_to || "",
|
|
21187
21578
|
references: email3.references || ""
|
|
21188
21579
|
};
|
|
21189
|
-
const metadataPath =
|
|
21190
|
-
|
|
21580
|
+
const metadataPath = join12(emailDir, "metadata.json");
|
|
21581
|
+
writeFileSync8(metadataPath, JSON.stringify(metadata, null, 2));
|
|
21191
21582
|
downloadedPaths.push(metadataPath);
|
|
21192
21583
|
let rawMime;
|
|
21193
21584
|
try {
|
|
@@ -21195,25 +21586,25 @@ function emailCommand() {
|
|
|
21195
21586
|
} catch (err) {
|
|
21196
21587
|
const msg = err instanceof Error ? err.message : String(err);
|
|
21197
21588
|
if (msg.includes("404")) {
|
|
21198
|
-
|
|
21589
|
+
log10.warn(`email body not available for ${email3.id}, skipping`);
|
|
21199
21590
|
continue;
|
|
21200
21591
|
}
|
|
21201
21592
|
throw err;
|
|
21202
21593
|
}
|
|
21203
21594
|
const parsed = await new PostalMime().parse(rawMime);
|
|
21204
21595
|
if (parsed.text) {
|
|
21205
|
-
const bodyPath =
|
|
21206
|
-
|
|
21596
|
+
const bodyPath = join12(emailDir, "body.txt");
|
|
21597
|
+
writeFileSync8(bodyPath, parsed.text);
|
|
21207
21598
|
downloadedPaths.push(bodyPath);
|
|
21208
21599
|
}
|
|
21209
21600
|
if (parsed.html) {
|
|
21210
|
-
const htmlPath =
|
|
21211
|
-
|
|
21601
|
+
const htmlPath = join12(emailDir, "body.html");
|
|
21602
|
+
writeFileSync8(htmlPath, parsed.html);
|
|
21212
21603
|
downloadedPaths.push(htmlPath);
|
|
21213
21604
|
}
|
|
21214
21605
|
if (parsed.attachments && parsed.attachments.length > 0) {
|
|
21215
|
-
const attDir =
|
|
21216
|
-
|
|
21606
|
+
const attDir = join12(emailDir, "attachments");
|
|
21607
|
+
mkdirSync10(attDir, { recursive: true });
|
|
21217
21608
|
const usedFilenames = new Set;
|
|
21218
21609
|
for (let i = 0;i < parsed.attachments.length; i++) {
|
|
21219
21610
|
const att = parsed.attachments[i];
|
|
@@ -21222,7 +21613,7 @@ function emailCommand() {
|
|
|
21222
21613
|
filename = `${i}-${filename}`;
|
|
21223
21614
|
}
|
|
21224
21615
|
usedFilenames.add(filename);
|
|
21225
|
-
const attPath =
|
|
21616
|
+
const attPath = join12(attDir, filename);
|
|
21226
21617
|
const content = att.content;
|
|
21227
21618
|
let buf;
|
|
21228
21619
|
if (typeof content === "string") {
|
|
@@ -21232,7 +21623,7 @@ function emailCommand() {
|
|
|
21232
21623
|
} else {
|
|
21233
21624
|
buf = Buffer.from(content);
|
|
21234
21625
|
}
|
|
21235
|
-
|
|
21626
|
+
writeFileSync8(attPath, buf);
|
|
21236
21627
|
downloadedPaths.push(attPath);
|
|
21237
21628
|
}
|
|
21238
21629
|
}
|
|
@@ -21273,7 +21664,7 @@ function emailCommand() {
|
|
|
21273
21664
|
const client = new APIClient(serverUrl, token, workspaceId);
|
|
21274
21665
|
let htmlBody;
|
|
21275
21666
|
try {
|
|
21276
|
-
htmlBody =
|
|
21667
|
+
htmlBody = readFileSync9(opts.bodyFile, "utf-8");
|
|
21277
21668
|
} catch (err) {
|
|
21278
21669
|
console.error(`Error: cannot read body file "${opts.bodyFile}": ${err instanceof Error ? err.message : err}`);
|
|
21279
21670
|
process.exit(1);
|
|
@@ -21289,13 +21680,13 @@ function emailCommand() {
|
|
|
21289
21680
|
let bytes;
|
|
21290
21681
|
let size;
|
|
21291
21682
|
try {
|
|
21292
|
-
bytes =
|
|
21293
|
-
size =
|
|
21683
|
+
bytes = readFileSync9(path2);
|
|
21684
|
+
size = statSync5(path2).size;
|
|
21294
21685
|
} catch (err) {
|
|
21295
21686
|
console.error(`Error: cannot read attachment "${path2}": ${err instanceof Error ? err.message : err}`);
|
|
21296
21687
|
process.exit(1);
|
|
21297
21688
|
}
|
|
21298
|
-
const filename =
|
|
21689
|
+
const filename = basename2(path2);
|
|
21299
21690
|
const contentType = guessContentType(filename);
|
|
21300
21691
|
const form = new FormData;
|
|
21301
21692
|
form.append("file", new Blob([new Uint8Array(bytes)], { type: contentType }), filename);
|
|
@@ -21317,7 +21708,7 @@ function emailCommand() {
|
|
|
21317
21708
|
references = [parentEmail.references, parentEmail.message_id].filter(Boolean).join(" ").trim() || undefined;
|
|
21318
21709
|
}
|
|
21319
21710
|
} catch {
|
|
21320
|
-
|
|
21711
|
+
log10.warn(`could not fetch parent email ${opts.inReplyTo}, sending without threading`);
|
|
21321
21712
|
}
|
|
21322
21713
|
}
|
|
21323
21714
|
const conversationId = process.env.ALOOK_CONVERSATION_ID;
|
|
@@ -21402,13 +21793,13 @@ function emailCommand() {
|
|
|
21402
21793
|
let bytes;
|
|
21403
21794
|
let size;
|
|
21404
21795
|
try {
|
|
21405
|
-
bytes =
|
|
21406
|
-
size =
|
|
21796
|
+
bytes = readFileSync9(path2);
|
|
21797
|
+
size = statSync5(path2).size;
|
|
21407
21798
|
} catch (err) {
|
|
21408
21799
|
console.error(`Error: cannot read attachment "${path2}": ${err instanceof Error ? err.message : err}`);
|
|
21409
21800
|
process.exit(1);
|
|
21410
21801
|
}
|
|
21411
|
-
const filename =
|
|
21802
|
+
const filename = basename2(path2);
|
|
21412
21803
|
const contentType = guessContentType(filename);
|
|
21413
21804
|
const form = new FormData;
|
|
21414
21805
|
form.append("file", new Blob([new Uint8Array(bytes)], { type: contentType }), filename);
|
|
@@ -21749,7 +22140,7 @@ function calendarCommand() {
|
|
|
21749
22140
|
|
|
21750
22141
|
// commands/issue.ts
|
|
21751
22142
|
import { Command as Command7 } from "commander";
|
|
21752
|
-
import { readFileSync as
|
|
22143
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
21753
22144
|
var VALID_STATUSES2 = ["todo", "in_progress", "review", "done", "closed", "canceled", "failed"];
|
|
21754
22145
|
function resolveClientOpts3(command, agentId) {
|
|
21755
22146
|
let root = command;
|
|
@@ -21773,7 +22164,7 @@ function readBody(opts) {
|
|
|
21773
22164
|
process.exit(1);
|
|
21774
22165
|
}
|
|
21775
22166
|
if (opts.bodyFile)
|
|
21776
|
-
return
|
|
22167
|
+
return readFileSync10(opts.bodyFile, "utf-8");
|
|
21777
22168
|
return opts.body ?? "";
|
|
21778
22169
|
}
|
|
21779
22170
|
function printIssue(issue3) {
|
|
@@ -21971,8 +22362,8 @@ ${result.output}`);
|
|
|
21971
22362
|
|
|
21972
22363
|
// commands/sync.ts
|
|
21973
22364
|
import { Command as Command10 } from "commander";
|
|
21974
|
-
import { readFileSync as
|
|
21975
|
-
import { basename as
|
|
22365
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
22366
|
+
import { basename as basename3 } from "path";
|
|
21976
22367
|
var MIME_BY_EXT2 = {
|
|
21977
22368
|
".pdf": "application/pdf",
|
|
21978
22369
|
".png": "image/png",
|
|
@@ -22020,12 +22411,12 @@ function syncCommand() {
|
|
|
22020
22411
|
const client = new APIClient(serverUrl, token, workspaceId);
|
|
22021
22412
|
let bytes;
|
|
22022
22413
|
try {
|
|
22023
|
-
bytes =
|
|
22414
|
+
bytes = readFileSync11(opts.file);
|
|
22024
22415
|
} catch (err) {
|
|
22025
22416
|
console.error(`Error: cannot read file "${opts.file}": ${err.message}`);
|
|
22026
22417
|
process.exit(1);
|
|
22027
22418
|
}
|
|
22028
|
-
const filename =
|
|
22419
|
+
const filename = basename3(opts.file);
|
|
22029
22420
|
const contentType = guessContentType2(filename);
|
|
22030
22421
|
const form = new FormData;
|
|
22031
22422
|
form.append("file", new Blob([new Uint8Array(bytes)], { type: contentType }), filename);
|