@alook/cli 0.0.102 → 0.0.104
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 +452 -191
- package/dist/session-runner.js +54 -32
- package/package.json +3 -1
package/dist/index.js
CHANGED
|
@@ -15,12 +15,10 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
// src/index.ts
|
|
18
|
-
import { Command as
|
|
18
|
+
import { Command as Command13 } from "commander";
|
|
19
19
|
|
|
20
20
|
// commands/register.ts
|
|
21
21
|
import { Command } from "commander";
|
|
22
|
-
import { execSync } from "child_process";
|
|
23
|
-
import { hostname as hostname4 } from "os";
|
|
24
22
|
|
|
25
23
|
// lib/client.ts
|
|
26
24
|
class APIClient {
|
|
@@ -106,51 +104,6 @@ class APIClient {
|
|
|
106
104
|
}
|
|
107
105
|
}
|
|
108
106
|
|
|
109
|
-
// lib/config.ts
|
|
110
|
-
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
111
|
-
import { join } from "path";
|
|
112
|
-
import { homedir } from "os";
|
|
113
|
-
function configDir() {
|
|
114
|
-
return process.env.ALOOK_PROJECT_ROOT || join(homedir(), ".alook");
|
|
115
|
-
}
|
|
116
|
-
function configPath() {
|
|
117
|
-
return join(configDir(), "config.json");
|
|
118
|
-
}
|
|
119
|
-
function loadCLIConfig() {
|
|
120
|
-
try {
|
|
121
|
-
return JSON.parse(readFileSync(configPath(), "utf-8"));
|
|
122
|
-
} catch {
|
|
123
|
-
return {};
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
function loadCLIConfigForProfile(profile) {
|
|
127
|
-
const cfg = loadCLIConfig();
|
|
128
|
-
const profileName = profile || cfg.default_profile;
|
|
129
|
-
if (profileName && cfg.profiles?.[profileName]) {
|
|
130
|
-
return cfg.profiles[profileName];
|
|
131
|
-
}
|
|
132
|
-
return {
|
|
133
|
-
server_url: cfg.server_url || "",
|
|
134
|
-
watched_workspaces: cfg.watched_workspaces || []
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
function saveCLIConfig(cfg) {
|
|
138
|
-
mkdirSync(configDir(), { recursive: true, mode: 448 });
|
|
139
|
-
writeFileSync(configPath(), JSON.stringify(cfg, null, 2), { mode: 384 });
|
|
140
|
-
}
|
|
141
|
-
function saveCLIConfigForProfile(profile, profileConfig) {
|
|
142
|
-
const cfg = loadCLIConfig();
|
|
143
|
-
if (profile) {
|
|
144
|
-
if (!cfg.profiles)
|
|
145
|
-
cfg.profiles = {};
|
|
146
|
-
cfg.profiles[profile] = profileConfig;
|
|
147
|
-
} else {
|
|
148
|
-
cfg.server_url = profileConfig.server_url;
|
|
149
|
-
cfg.watched_workspaces = profileConfig.watched_workspaces;
|
|
150
|
-
}
|
|
151
|
-
saveCLIConfig(cfg);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
107
|
// ../shared/src/constants.ts
|
|
155
108
|
var TaskStatus = {
|
|
156
109
|
QUEUED: "queued",
|
|
@@ -14605,7 +14558,7 @@ var DaemonPushMessageSchema = exports_external.discriminatedUnion("type", [
|
|
|
14605
14558
|
exports_external.object({ type: exports_external.literal("daemon.evict"), workspaceId: exports_external.string() }),
|
|
14606
14559
|
exports_external.object({ type: exports_external.literal("daemon.update"), version: exports_external.string() }),
|
|
14607
14560
|
exports_external.object({ type: exports_external.literal("daemon.rescan") }),
|
|
14608
|
-
exports_external.object({ type: exports_external.literal("daemon.kill"), workspaceId: exports_external.string(), taskId: exports_external.string(), targetTaskId: exports_external.string() })
|
|
14561
|
+
exports_external.object({ type: exports_external.literal("daemon.kill"), workspaceId: exports_external.string(), agentId: exports_external.string().min(1), taskId: exports_external.string(), targetTaskId: exports_external.string() })
|
|
14609
14562
|
]);
|
|
14610
14563
|
var RegisterResponseSchema = exports_external.object({
|
|
14611
14564
|
runtimes: exports_external.array(exports_external.object({ id: exports_external.string() }))
|
|
@@ -14958,7 +14911,15 @@ var CreateStudioRequestSchema = exports_external.object({
|
|
|
14958
14911
|
scenario: exports_external.string().max(50).optional(),
|
|
14959
14912
|
members: exports_external.array(StudioMemberSchema).min(1).max(4)
|
|
14960
14913
|
}).refine((v) => v.members.some((m) => m.role === "leader"), { message: "at least one member must have the leader role" });
|
|
14961
|
-
|
|
14914
|
+
var RecruitAgentRequestSchema = exports_external.object({
|
|
14915
|
+
instructions: exports_external.string().min(1, "instructions is required"),
|
|
14916
|
+
relationship: exports_external.string().min(1, "relationship is required"),
|
|
14917
|
+
name: exports_external.string().optional(),
|
|
14918
|
+
description: exports_external.string().optional().default(""),
|
|
14919
|
+
model: exports_external.string().max(100).optional(),
|
|
14920
|
+
context_key: exports_external.string().optional()
|
|
14921
|
+
});
|
|
14922
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/entity.js
|
|
14962
14923
|
var entityKind = Symbol.for("drizzle:entityKind");
|
|
14963
14924
|
var hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
|
|
14964
14925
|
function is(value, type) {
|
|
@@ -14983,10 +14944,10 @@ function is(value, type) {
|
|
|
14983
14944
|
return false;
|
|
14984
14945
|
}
|
|
14985
14946
|
|
|
14986
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
14947
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/table.utils.js
|
|
14987
14948
|
var TableName = Symbol.for("drizzle:Name");
|
|
14988
14949
|
|
|
14989
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
14950
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/table.js
|
|
14990
14951
|
var Schema = Symbol.for("drizzle:Schema");
|
|
14991
14952
|
var Columns = Symbol.for("drizzle:Columns");
|
|
14992
14953
|
var ExtraConfigColumns = Symbol.for("drizzle:ExtraConfigColumns");
|
|
@@ -15024,7 +14985,7 @@ class Table {
|
|
|
15024
14985
|
}
|
|
15025
14986
|
}
|
|
15026
14987
|
|
|
15027
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
14988
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/column.js
|
|
15028
14989
|
class Column {
|
|
15029
14990
|
constructor(table, config2) {
|
|
15030
14991
|
this.table = table;
|
|
@@ -15074,7 +15035,7 @@ class Column {
|
|
|
15074
15035
|
}
|
|
15075
15036
|
}
|
|
15076
15037
|
|
|
15077
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15038
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/column-builder.js
|
|
15078
15039
|
class ColumnBuilder {
|
|
15079
15040
|
static [entityKind] = "ColumnBuilder";
|
|
15080
15041
|
config;
|
|
@@ -15130,17 +15091,17 @@ class ColumnBuilder {
|
|
|
15130
15091
|
}
|
|
15131
15092
|
}
|
|
15132
15093
|
|
|
15133
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15094
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/tracing-utils.js
|
|
15134
15095
|
function iife(fn, ...args) {
|
|
15135
15096
|
return fn(...args);
|
|
15136
15097
|
}
|
|
15137
15098
|
|
|
15138
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15099
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/pg-core/unique-constraint.js
|
|
15139
15100
|
function uniqueKeyName(table, columns) {
|
|
15140
15101
|
return `${table[TableName]}_${columns.join("_")}_unique`;
|
|
15141
15102
|
}
|
|
15142
15103
|
|
|
15143
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15104
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/pg-core/columns/common.js
|
|
15144
15105
|
class PgColumn extends Column {
|
|
15145
15106
|
constructor(table, config2) {
|
|
15146
15107
|
if (!config2.uniqueName) {
|
|
@@ -15189,7 +15150,7 @@ class ExtraConfigColumn extends PgColumn {
|
|
|
15189
15150
|
}
|
|
15190
15151
|
}
|
|
15191
15152
|
|
|
15192
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15153
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/pg-core/columns/enum.js
|
|
15193
15154
|
class PgEnumObjectColumn extends PgColumn {
|
|
15194
15155
|
static [entityKind] = "PgEnumObjectColumn";
|
|
15195
15156
|
enum;
|
|
@@ -15219,7 +15180,7 @@ class PgEnumColumn extends PgColumn {
|
|
|
15219
15180
|
}
|
|
15220
15181
|
}
|
|
15221
15182
|
|
|
15222
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15183
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/subquery.js
|
|
15223
15184
|
class Subquery {
|
|
15224
15185
|
static [entityKind] = "Subquery";
|
|
15225
15186
|
constructor(sql, fields, alias, isWith = false, usedTables = []) {
|
|
@@ -15234,10 +15195,10 @@ class Subquery {
|
|
|
15234
15195
|
}
|
|
15235
15196
|
}
|
|
15236
15197
|
|
|
15237
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15198
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/version.js
|
|
15238
15199
|
var version2 = "0.45.2";
|
|
15239
15200
|
|
|
15240
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15201
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/tracing.js
|
|
15241
15202
|
var otel;
|
|
15242
15203
|
var rawTracer;
|
|
15243
15204
|
var tracer = {
|
|
@@ -15264,10 +15225,10 @@ var tracer = {
|
|
|
15264
15225
|
}
|
|
15265
15226
|
};
|
|
15266
15227
|
|
|
15267
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15228
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/view-common.js
|
|
15268
15229
|
var ViewBaseConfig = Symbol.for("drizzle:ViewBaseConfig");
|
|
15269
15230
|
|
|
15270
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15231
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sql/sql.js
|
|
15271
15232
|
function isSQLWrapper(value) {
|
|
15272
15233
|
return value !== null && value !== undefined && typeof value.getSQL === "function";
|
|
15273
15234
|
}
|
|
@@ -15544,7 +15505,7 @@ function sql(strings, ...params) {
|
|
|
15544
15505
|
return new SQL([new StringChunk(str)]);
|
|
15545
15506
|
}
|
|
15546
15507
|
sql2.raw = raw;
|
|
15547
|
-
function
|
|
15508
|
+
function join(chunks, separator) {
|
|
15548
15509
|
const result = [];
|
|
15549
15510
|
for (const [i, chunk] of chunks.entries()) {
|
|
15550
15511
|
if (i > 0 && separator !== undefined) {
|
|
@@ -15554,7 +15515,7 @@ function sql(strings, ...params) {
|
|
|
15554
15515
|
}
|
|
15555
15516
|
return new SQL(result);
|
|
15556
15517
|
}
|
|
15557
|
-
sql2.join =
|
|
15518
|
+
sql2.join = join;
|
|
15558
15519
|
function identifier(value) {
|
|
15559
15520
|
return new Name(value);
|
|
15560
15521
|
}
|
|
@@ -15627,7 +15588,7 @@ Subquery.prototype.getSQL = function() {
|
|
|
15627
15588
|
return new SQL([this]);
|
|
15628
15589
|
};
|
|
15629
15590
|
|
|
15630
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15591
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/utils.js
|
|
15631
15592
|
function getColumnNameAndConfig(a, b) {
|
|
15632
15593
|
return {
|
|
15633
15594
|
name: typeof a === "string" && a.length > 0 ? a : "",
|
|
@@ -15636,7 +15597,7 @@ function getColumnNameAndConfig(a, b) {
|
|
|
15636
15597
|
}
|
|
15637
15598
|
var textDecoder = typeof TextDecoder === "undefined" ? null : new TextDecoder;
|
|
15638
15599
|
|
|
15639
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15600
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/foreign-keys.js
|
|
15640
15601
|
class ForeignKeyBuilder {
|
|
15641
15602
|
static [entityKind] = "SQLiteForeignKeyBuilder";
|
|
15642
15603
|
reference;
|
|
@@ -15704,7 +15665,7 @@ function foreignKey(config2) {
|
|
|
15704
15665
|
return new ForeignKeyBuilder(mappedConfig);
|
|
15705
15666
|
}
|
|
15706
15667
|
|
|
15707
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15668
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/unique-constraint.js
|
|
15708
15669
|
function uniqueKeyName2(table, columns) {
|
|
15709
15670
|
return `${table[TableName]}_${columns.join("_")}_unique`;
|
|
15710
15671
|
}
|
|
@@ -15749,7 +15710,7 @@ class UniqueConstraint {
|
|
|
15749
15710
|
}
|
|
15750
15711
|
}
|
|
15751
15712
|
|
|
15752
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15713
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/columns/common.js
|
|
15753
15714
|
class SQLiteColumnBuilder extends ColumnBuilder {
|
|
15754
15715
|
static [entityKind] = "SQLiteColumnBuilder";
|
|
15755
15716
|
foreignKeyConfigs = [];
|
|
@@ -15800,7 +15761,7 @@ class SQLiteColumn extends Column {
|
|
|
15800
15761
|
static [entityKind] = "SQLiteColumn";
|
|
15801
15762
|
}
|
|
15802
15763
|
|
|
15803
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15764
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/columns/blob.js
|
|
15804
15765
|
class SQLiteBigIntBuilder extends SQLiteColumnBuilder {
|
|
15805
15766
|
static [entityKind] = "SQLiteBigIntBuilder";
|
|
15806
15767
|
constructor(name) {
|
|
@@ -15888,7 +15849,7 @@ function blob(a, b) {
|
|
|
15888
15849
|
return new SQLiteBlobBufferBuilder(name);
|
|
15889
15850
|
}
|
|
15890
15851
|
|
|
15891
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15852
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/columns/custom.js
|
|
15892
15853
|
class SQLiteCustomColumnBuilder extends SQLiteColumnBuilder {
|
|
15893
15854
|
static [entityKind] = "SQLiteCustomColumnBuilder";
|
|
15894
15855
|
constructor(name, fieldConfig, customTypeParams) {
|
|
@@ -15929,7 +15890,7 @@ function customType(customTypeParams) {
|
|
|
15929
15890
|
};
|
|
15930
15891
|
}
|
|
15931
15892
|
|
|
15932
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15893
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/columns/integer.js
|
|
15933
15894
|
class SQLiteBaseIntegerBuilder extends SQLiteColumnBuilder {
|
|
15934
15895
|
static [entityKind] = "SQLiteBaseIntegerBuilder";
|
|
15935
15896
|
constructor(name, dataType, columnType) {
|
|
@@ -16031,7 +15992,7 @@ function integer2(a, b) {
|
|
|
16031
15992
|
return new SQLiteIntegerBuilder(name);
|
|
16032
15993
|
}
|
|
16033
15994
|
|
|
16034
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
15995
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/columns/numeric.js
|
|
16035
15996
|
class SQLiteNumericBuilder extends SQLiteColumnBuilder {
|
|
16036
15997
|
static [entityKind] = "SQLiteNumericBuilder";
|
|
16037
15998
|
constructor(name) {
|
|
@@ -16101,7 +16062,7 @@ function numeric(a, b) {
|
|
|
16101
16062
|
return mode === "number" ? new SQLiteNumericNumberBuilder(name) : mode === "bigint" ? new SQLiteNumericBigIntBuilder(name) : new SQLiteNumericBuilder(name);
|
|
16102
16063
|
}
|
|
16103
16064
|
|
|
16104
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
16065
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/columns/real.js
|
|
16105
16066
|
class SQLiteRealBuilder extends SQLiteColumnBuilder {
|
|
16106
16067
|
static [entityKind] = "SQLiteRealBuilder";
|
|
16107
16068
|
constructor(name) {
|
|
@@ -16122,7 +16083,7 @@ function real(name) {
|
|
|
16122
16083
|
return new SQLiteRealBuilder(name ?? "");
|
|
16123
16084
|
}
|
|
16124
16085
|
|
|
16125
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
16086
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/columns/text.js
|
|
16126
16087
|
class SQLiteTextBuilder extends SQLiteColumnBuilder {
|
|
16127
16088
|
static [entityKind] = "SQLiteTextBuilder";
|
|
16128
16089
|
constructor(name, config2) {
|
|
@@ -16177,7 +16138,7 @@ function text(a, b = {}) {
|
|
|
16177
16138
|
return new SQLiteTextBuilder(name, config2);
|
|
16178
16139
|
}
|
|
16179
16140
|
|
|
16180
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
16141
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/columns/all.js
|
|
16181
16142
|
function getSQLiteColumnBuilders() {
|
|
16182
16143
|
return {
|
|
16183
16144
|
blob,
|
|
@@ -16189,7 +16150,7 @@ function getSQLiteColumnBuilders() {
|
|
|
16189
16150
|
};
|
|
16190
16151
|
}
|
|
16191
16152
|
|
|
16192
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
16153
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/table.js
|
|
16193
16154
|
var InlineForeignKeys = Symbol.for("drizzle:SQLiteInlineForeignKeys");
|
|
16194
16155
|
|
|
16195
16156
|
class SQLiteTable extends Table {
|
|
@@ -16223,7 +16184,7 @@ var sqliteTable = (name, columns, extraConfig) => {
|
|
|
16223
16184
|
return sqliteTableBase(name, columns, extraConfig);
|
|
16224
16185
|
};
|
|
16225
16186
|
|
|
16226
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
16187
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/indexes.js
|
|
16227
16188
|
class IndexBuilderOn {
|
|
16228
16189
|
constructor(name, unique2) {
|
|
16229
16190
|
this.name = name;
|
|
@@ -16266,7 +16227,7 @@ function index(name) {
|
|
|
16266
16227
|
return new IndexBuilderOn(name, false);
|
|
16267
16228
|
}
|
|
16268
16229
|
|
|
16269
|
-
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.
|
|
16230
|
+
// ../../node_modules/.pnpm/drizzle-orm@0.45.2_@cloudflare+workers-types@4.20260524.1_@opentelemetry+api@1.9.1_@typ_f775720d1395b789318c4e4a4fd2c362/node_modules/drizzle-orm/sqlite-core/primary-keys.js
|
|
16270
16231
|
function primaryKey(...config2) {
|
|
16271
16232
|
if (config2[0].columns) {
|
|
16272
16233
|
return new PrimaryKeyBuilder(config2[0].columns, config2[0].name);
|
|
@@ -16856,9 +16817,6 @@ var agentSkill = sqliteTable("agent_skill", {
|
|
|
16856
16817
|
// ../shared/src/db/queries/task.ts
|
|
16857
16818
|
var DEFAULT_STALE_SECONDS = Number(process.env.ALOOK_STALE_DISPATCH_TIMEOUT_S) || 20;
|
|
16858
16819
|
var DEFAULT_STALE_RUNNING_SECONDS = Number(process.env.ALOOK_STALE_RUNNING_TIMEOUT_S) || 3600;
|
|
16859
|
-
// ../shared/src/db/queries/task-message.ts
|
|
16860
|
-
var HIDDEN_STEP_TYPES = ["status", "log", "tool-result", "text"];
|
|
16861
|
-
var FIXED_PARAMS = 1 + HIDDEN_STEP_TYPES.length;
|
|
16862
16820
|
// ../shared/src/utils/email.ts
|
|
16863
16821
|
var DOMAIN = `@${process.env.ALOOK_DOMAIN || "alook.ai"}`;
|
|
16864
16822
|
var RESERVED_HANDLES = new Set([
|
|
@@ -16931,6 +16889,54 @@ function cmdPrefix() {
|
|
|
16931
16889
|
}));
|
|
16932
16890
|
}
|
|
16933
16891
|
|
|
16892
|
+
// lib/activate.ts
|
|
16893
|
+
import { hostname as hostname4 } from "os";
|
|
16894
|
+
|
|
16895
|
+
// lib/config.ts
|
|
16896
|
+
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
16897
|
+
import { join } from "path";
|
|
16898
|
+
import { homedir } from "os";
|
|
16899
|
+
function configDir() {
|
|
16900
|
+
return process.env.ALOOK_PROJECT_ROOT || join(homedir(), ".alook");
|
|
16901
|
+
}
|
|
16902
|
+
function configPath() {
|
|
16903
|
+
return join(configDir(), "config.json");
|
|
16904
|
+
}
|
|
16905
|
+
function loadCLIConfig() {
|
|
16906
|
+
try {
|
|
16907
|
+
return JSON.parse(readFileSync(configPath(), "utf-8"));
|
|
16908
|
+
} catch {
|
|
16909
|
+
return {};
|
|
16910
|
+
}
|
|
16911
|
+
}
|
|
16912
|
+
function loadCLIConfigForProfile(profile) {
|
|
16913
|
+
const cfg = loadCLIConfig();
|
|
16914
|
+
const profileName = profile || cfg.default_profile;
|
|
16915
|
+
if (profileName && cfg.profiles?.[profileName]) {
|
|
16916
|
+
return cfg.profiles[profileName];
|
|
16917
|
+
}
|
|
16918
|
+
return {
|
|
16919
|
+
server_url: cfg.server_url || "",
|
|
16920
|
+
watched_workspaces: cfg.watched_workspaces || []
|
|
16921
|
+
};
|
|
16922
|
+
}
|
|
16923
|
+
function saveCLIConfig(cfg) {
|
|
16924
|
+
mkdirSync(configDir(), { recursive: true, mode: 448 });
|
|
16925
|
+
writeFileSync(configPath(), JSON.stringify(cfg, null, 2), { mode: 384 });
|
|
16926
|
+
}
|
|
16927
|
+
function saveCLIConfigForProfile(profile, profileConfig) {
|
|
16928
|
+
const cfg = loadCLIConfig();
|
|
16929
|
+
if (profile) {
|
|
16930
|
+
if (!cfg.profiles)
|
|
16931
|
+
cfg.profiles = {};
|
|
16932
|
+
cfg.profiles[profile] = profileConfig;
|
|
16933
|
+
} else {
|
|
16934
|
+
cfg.server_url = profileConfig.server_url;
|
|
16935
|
+
cfg.watched_workspaces = profileConfig.watched_workspaces;
|
|
16936
|
+
}
|
|
16937
|
+
saveCLIConfig(cfg);
|
|
16938
|
+
}
|
|
16939
|
+
|
|
16934
16940
|
// daemon/pidfile.ts
|
|
16935
16941
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, unlinkSync, mkdirSync as mkdirSync2 } from "fs";
|
|
16936
16942
|
import { dirname as dirname2 } from "path";
|
|
@@ -17211,7 +17217,8 @@ function releaseDaemonPid(profile) {
|
|
|
17211
17217
|
removePidFileIfMatches(process.pid, profile);
|
|
17212
17218
|
}
|
|
17213
17219
|
|
|
17214
|
-
//
|
|
17220
|
+
// lib/runtimes.ts
|
|
17221
|
+
import { execSync } from "child_process";
|
|
17215
17222
|
function isCommandAvailable(cmd) {
|
|
17216
17223
|
try {
|
|
17217
17224
|
const check2 = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
|
|
@@ -17234,6 +17241,90 @@ function detectRuntimes() {
|
|
|
17234
17241
|
}
|
|
17235
17242
|
return found;
|
|
17236
17243
|
}
|
|
17244
|
+
|
|
17245
|
+
// lib/activate.ts
|
|
17246
|
+
async function activateAndSave(opts) {
|
|
17247
|
+
const { token, serverUrl, profile } = opts;
|
|
17248
|
+
console.log("Scanning for AI runtimes...");
|
|
17249
|
+
const runtimes = detectRuntimes();
|
|
17250
|
+
if (runtimes.length === 0) {
|
|
17251
|
+
console.error("Error: no runtimes found. Install claude, codex, or opencode first.");
|
|
17252
|
+
process.exit(1);
|
|
17253
|
+
}
|
|
17254
|
+
console.log(`Found: ${runtimes.map((r) => r.type).join(", ")}`);
|
|
17255
|
+
const host = hostname4();
|
|
17256
|
+
console.log("Registering runtime...");
|
|
17257
|
+
let activateResp;
|
|
17258
|
+
try {
|
|
17259
|
+
const res = await fetch(`${serverUrl}/api/machine-tokens/activate`, {
|
|
17260
|
+
method: "POST",
|
|
17261
|
+
headers: { "Content-Type": "application/json" },
|
|
17262
|
+
body: JSON.stringify({ token, hostname: host, runtimes })
|
|
17263
|
+
});
|
|
17264
|
+
if (!res.ok) {
|
|
17265
|
+
const text2 = await res.text();
|
|
17266
|
+
console.error(`Error: registration failed (${res.status}): ${text2}`);
|
|
17267
|
+
process.exit(1);
|
|
17268
|
+
}
|
|
17269
|
+
activateResp = await res.json();
|
|
17270
|
+
} catch (err) {
|
|
17271
|
+
console.error(`Error: failed to activate: ${err instanceof Error ? err.message : err}`);
|
|
17272
|
+
process.exit(1);
|
|
17273
|
+
}
|
|
17274
|
+
const client = new APIClient(serverUrl, token);
|
|
17275
|
+
let workspaces;
|
|
17276
|
+
try {
|
|
17277
|
+
workspaces = await client.getJSON("/api/workspaces");
|
|
17278
|
+
} catch (err) {
|
|
17279
|
+
console.error(`Error: failed to fetch workspaces: ${err instanceof Error ? err.message : err}`);
|
|
17280
|
+
process.exit(1);
|
|
17281
|
+
}
|
|
17282
|
+
if (!workspaces.length) {
|
|
17283
|
+
console.error("Error: no workspaces found for this user");
|
|
17284
|
+
process.exit(1);
|
|
17285
|
+
}
|
|
17286
|
+
const ws = workspaces.find((w) => w.id === activateResp.workspace_id) || workspaces[0];
|
|
17287
|
+
const wsClient = new APIClient(serverUrl, token, ws.id);
|
|
17288
|
+
let agentIds = [];
|
|
17289
|
+
try {
|
|
17290
|
+
const agents = await wsClient.getJSON(`/api/agents?workspace_id=${ws.id}`);
|
|
17291
|
+
agentIds = agents.map((a) => a.id);
|
|
17292
|
+
} catch {}
|
|
17293
|
+
const existing = loadCLIConfigForProfile(profile);
|
|
17294
|
+
const watched = existing.watched_workspaces || [];
|
|
17295
|
+
const idx = watched.findIndex((w) => w.id === ws.id);
|
|
17296
|
+
if (idx >= 0) {
|
|
17297
|
+
watched[idx] = { id: ws.id, name: ws.name, token, agent_ids: agentIds };
|
|
17298
|
+
} else {
|
|
17299
|
+
watched.push({ id: ws.id, name: ws.name, token, agent_ids: agentIds });
|
|
17300
|
+
}
|
|
17301
|
+
saveCLIConfigForProfile(profile, {
|
|
17302
|
+
server_url: serverUrl,
|
|
17303
|
+
watched_workspaces: watched
|
|
17304
|
+
});
|
|
17305
|
+
const daemonPid = readDaemonPid(profile);
|
|
17306
|
+
if (daemonPid && isProcessAlive(daemonPid)) {
|
|
17307
|
+
try {
|
|
17308
|
+
process.kill(daemonPid, "SIGHUP");
|
|
17309
|
+
console.log(`
|
|
17310
|
+
Daemon (pid ${daemonPid}) notified — workspace will be active shortly.`);
|
|
17311
|
+
} catch {
|
|
17312
|
+
console.log(`
|
|
17313
|
+
Daemon is running but could not be notified. Restart it to pick up the new workspace.`);
|
|
17314
|
+
}
|
|
17315
|
+
} else {
|
|
17316
|
+
const startCmd = isDev() ? `${cmdPrefix()} daemon start --foreground` : `${cmdPrefix()} daemon start`;
|
|
17317
|
+
console.log();
|
|
17318
|
+
console.log(`Run '${startCmd}' to start the daemon.`);
|
|
17319
|
+
}
|
|
17320
|
+
return {
|
|
17321
|
+
workspaceId: ws.id,
|
|
17322
|
+
workspaceName: ws.name,
|
|
17323
|
+
runtimeProviders: activateResp.runtimes.map((r) => r.provider)
|
|
17324
|
+
};
|
|
17325
|
+
}
|
|
17326
|
+
|
|
17327
|
+
// commands/register.ts
|
|
17237
17328
|
function registerCommand() {
|
|
17238
17329
|
const cmd = new Command("register").description("Register CLI with your Alook account").requiredOption("--token <token>", "API token (starts with al_)").option("--server <url>", "Server URL").option("--profile <name>", "Profile name").action(async (opts, command) => {
|
|
17239
17330
|
const token = opts.token;
|
|
@@ -17256,89 +17347,182 @@ Usage: ${cmdPrefix()} register --token <token>`);
|
|
|
17256
17347
|
console.error(`Error: failed to verify token: ${err instanceof Error ? err.message : err}`);
|
|
17257
17348
|
process.exit(1);
|
|
17258
17349
|
}
|
|
17259
|
-
|
|
17260
|
-
|
|
17261
|
-
|
|
17262
|
-
|
|
17263
|
-
|
|
17350
|
+
const result = await activateAndSave({ token, serverUrl, profile });
|
|
17351
|
+
console.log(`
|
|
17352
|
+
Registered as ${me.email}`);
|
|
17353
|
+
console.log(`Workspace: ${result.workspaceName} (${result.workspaceId})`);
|
|
17354
|
+
console.log(`Runtimes: ${result.runtimeProviders.join(", ")}`);
|
|
17355
|
+
});
|
|
17356
|
+
return cmd;
|
|
17357
|
+
}
|
|
17358
|
+
|
|
17359
|
+
// commands/login.ts
|
|
17360
|
+
import { Command as Command2 } from "commander";
|
|
17361
|
+
import { fork, spawn } from "child_process";
|
|
17362
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
17363
|
+
var DEVICE_CLIENT_ID = process.env.ALOOK_DEVICE_CLIENT_ID || "alook-cli";
|
|
17364
|
+
function openBrowser(url2) {
|
|
17365
|
+
try {
|
|
17366
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "linux" ? "xdg-open" : process.platform === "win32" ? "start" : null;
|
|
17367
|
+
if (cmd) {
|
|
17368
|
+
const args = process.platform === "win32" ? ["", url2] : [url2];
|
|
17369
|
+
spawn(cmd, args, { stdio: "ignore", detached: true }).unref();
|
|
17264
17370
|
}
|
|
17265
|
-
|
|
17266
|
-
|
|
17267
|
-
|
|
17268
|
-
|
|
17371
|
+
} catch {}
|
|
17372
|
+
}
|
|
17373
|
+
function sleep(ms) {
|
|
17374
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
17375
|
+
}
|
|
17376
|
+
async function pollAndActivate(opts) {
|
|
17377
|
+
const { deviceCode, expiresIn, serverUrl, profile } = opts;
|
|
17378
|
+
let interval = opts.interval;
|
|
17379
|
+
const expiresAt = Date.now() + expiresIn * 1000;
|
|
17380
|
+
let tokenResp;
|
|
17381
|
+
while (Date.now() < expiresAt) {
|
|
17382
|
+
await sleep(interval);
|
|
17269
17383
|
try {
|
|
17270
|
-
const res = await fetch(`${serverUrl}/api/
|
|
17384
|
+
const res = await fetch(`${serverUrl}/api/auth/device/token`, {
|
|
17271
17385
|
method: "POST",
|
|
17272
17386
|
headers: { "Content-Type": "application/json" },
|
|
17273
|
-
body: JSON.stringify({
|
|
17387
|
+
body: JSON.stringify({
|
|
17388
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
17389
|
+
device_code: deviceCode,
|
|
17390
|
+
client_id: DEVICE_CLIENT_ID
|
|
17391
|
+
})
|
|
17274
17392
|
});
|
|
17275
|
-
if (
|
|
17276
|
-
|
|
17277
|
-
|
|
17393
|
+
if (res.ok) {
|
|
17394
|
+
tokenResp = await res.json();
|
|
17395
|
+
break;
|
|
17396
|
+
}
|
|
17397
|
+
const errBody = await res.json();
|
|
17398
|
+
if (errBody.error === "slow_down") {
|
|
17399
|
+
interval += 5000;
|
|
17400
|
+
} else if (errBody.error === "authorization_pending") {} else if (errBody.error === "expired_token") {
|
|
17401
|
+
console.error("Error: device code expired. Please run login again.");
|
|
17402
|
+
process.exit(1);
|
|
17403
|
+
} else if (errBody.error === "access_denied") {
|
|
17404
|
+
console.error("Error: authorization was denied.");
|
|
17405
|
+
process.exit(1);
|
|
17406
|
+
} else {
|
|
17407
|
+
console.error(`Error: unexpected error: ${errBody.error_description || errBody.error}`);
|
|
17278
17408
|
process.exit(1);
|
|
17279
17409
|
}
|
|
17280
|
-
|
|
17281
|
-
|
|
17282
|
-
console.error(`Error: failed to activate: ${err instanceof Error ? err.message : err}`);
|
|
17410
|
+
} catch {
|
|
17411
|
+
console.error("Error: network request failed during polling.");
|
|
17283
17412
|
process.exit(1);
|
|
17284
17413
|
}
|
|
17285
|
-
|
|
17414
|
+
}
|
|
17415
|
+
if (!tokenResp) {
|
|
17416
|
+
console.error("Error: device code expired (timed out). Please run login again.");
|
|
17417
|
+
process.exit(1);
|
|
17418
|
+
}
|
|
17419
|
+
const sessionToken = tokenResp.access_token;
|
|
17420
|
+
const client = new APIClient(serverUrl, sessionToken);
|
|
17421
|
+
let email3 = "";
|
|
17422
|
+
try {
|
|
17423
|
+
const me = await client.getJSON("/api/me");
|
|
17424
|
+
email3 = me.email;
|
|
17425
|
+
} catch {}
|
|
17426
|
+
let existingWorkspaceId = "";
|
|
17427
|
+
try {
|
|
17428
|
+
const workspaces = await client.getJSON("/api/workspaces");
|
|
17429
|
+
if (workspaces.length > 0) {
|
|
17430
|
+
existingWorkspaceId = workspaces[0].id;
|
|
17431
|
+
}
|
|
17432
|
+
} catch {}
|
|
17433
|
+
const mtUrl = existingWorkspaceId ? `/api/machine-tokens?workspace_id=${existingWorkspaceId}` : "/api/machine-tokens";
|
|
17434
|
+
let machineToken2;
|
|
17435
|
+
try {
|
|
17436
|
+
const mtResp = await client.postJSON(mtUrl);
|
|
17437
|
+
machineToken2 = mtResp.token;
|
|
17438
|
+
} catch {
|
|
17439
|
+
process.exit(1);
|
|
17440
|
+
}
|
|
17441
|
+
const result = await activateAndSave({ token: machineToken2, serverUrl, profile });
|
|
17442
|
+
if (email3) {
|
|
17443
|
+
console.log(`
|
|
17444
|
+
Logged in as ${email3}`);
|
|
17445
|
+
}
|
|
17446
|
+
console.log(`Workspace: ${result.workspaceName} (${result.workspaceId})`);
|
|
17447
|
+
console.log(`Runtimes: ${result.runtimeProviders.join(", ")}`);
|
|
17448
|
+
}
|
|
17449
|
+
if (process.argv.includes("--__login-poll")) {
|
|
17450
|
+
const idx = process.argv.indexOf("--__login-poll");
|
|
17451
|
+
let data;
|
|
17452
|
+
try {
|
|
17453
|
+
data = JSON.parse(process.argv[idx + 1]);
|
|
17454
|
+
} catch {
|
|
17455
|
+
console.error("Error: invalid poll data");
|
|
17456
|
+
process.exit(1);
|
|
17457
|
+
}
|
|
17458
|
+
pollAndActivate(data).catch(() => process.exit(1));
|
|
17459
|
+
}
|
|
17460
|
+
function loginCommand() {
|
|
17461
|
+
const cmd = new Command2("login").description("Log in to Alook via browser (device code flow)").option("--server <url>", "Server URL").option("--profile <name>", "Profile name").action(async (opts, command) => {
|
|
17462
|
+
const profile = opts.profile || command.parent?.opts().profile;
|
|
17463
|
+
const serverUrl = opts.server || command.parent?.opts().server || process.env.ALOOK_SERVER_URL || "https://alook.ai";
|
|
17464
|
+
console.log("Requesting device code...");
|
|
17465
|
+
let deviceResp;
|
|
17286
17466
|
try {
|
|
17287
|
-
|
|
17467
|
+
const res = await fetch(`${serverUrl}/api/auth/device/code`, {
|
|
17468
|
+
method: "POST",
|
|
17469
|
+
headers: { "Content-Type": "application/json" },
|
|
17470
|
+
body: JSON.stringify({ client_id: DEVICE_CLIENT_ID })
|
|
17471
|
+
});
|
|
17472
|
+
if (!res.ok) {
|
|
17473
|
+
const text2 = await res.text();
|
|
17474
|
+
console.error(`Error: failed to get device code (${res.status}): ${text2}`);
|
|
17475
|
+
process.exit(1);
|
|
17476
|
+
}
|
|
17477
|
+
deviceResp = await res.json();
|
|
17288
17478
|
} catch (err) {
|
|
17289
|
-
console.error(`Error: failed to
|
|
17290
|
-
process.exit(1);
|
|
17291
|
-
}
|
|
17292
|
-
if (!workspaces.length) {
|
|
17293
|
-
console.error("Error: no workspaces found for this user");
|
|
17479
|
+
console.error(`Error: failed to request device code: ${err instanceof Error ? err.message : err}`);
|
|
17294
17480
|
process.exit(1);
|
|
17295
17481
|
}
|
|
17296
|
-
const
|
|
17297
|
-
|
|
17298
|
-
|
|
17299
|
-
|
|
17300
|
-
|
|
17301
|
-
|
|
17302
|
-
|
|
17303
|
-
|
|
17304
|
-
|
|
17305
|
-
|
|
17306
|
-
|
|
17307
|
-
|
|
17308
|
-
|
|
17309
|
-
|
|
17482
|
+
const verificationUrl = deviceResp.verification_uri_complete || deviceResp.verification_uri;
|
|
17483
|
+
console.log();
|
|
17484
|
+
console.log(` Open this URL in your browser:`);
|
|
17485
|
+
console.log(` ${verificationUrl}`);
|
|
17486
|
+
console.log();
|
|
17487
|
+
console.log(` Enter code: ${deviceResp.user_code}`);
|
|
17488
|
+
console.log();
|
|
17489
|
+
if (!process.stdout.isTTY) {
|
|
17490
|
+
const pollData = JSON.stringify({
|
|
17491
|
+
deviceCode: deviceResp.device_code,
|
|
17492
|
+
interval: (deviceResp.interval || 5) * 1000,
|
|
17493
|
+
expiresIn: deviceResp.expires_in,
|
|
17494
|
+
serverUrl,
|
|
17495
|
+
profile
|
|
17496
|
+
});
|
|
17497
|
+
const thisFile = fileURLToPath2(import.meta.url);
|
|
17498
|
+
const child = fork(thisFile, ["--__login-poll", pollData], {
|
|
17499
|
+
detached: true,
|
|
17500
|
+
stdio: "ignore"
|
|
17501
|
+
});
|
|
17502
|
+
child.unref();
|
|
17503
|
+
console.log(" Polling for authorization in the background (timeout: 5min).");
|
|
17504
|
+
console.log(" Once approved, run `npx @alook/cli status` to verify.");
|
|
17505
|
+
return;
|
|
17310
17506
|
}
|
|
17311
|
-
|
|
17312
|
-
|
|
17313
|
-
|
|
17507
|
+
openBrowser(verificationUrl);
|
|
17508
|
+
console.log(" (Browser opened automatically)");
|
|
17509
|
+
console.log();
|
|
17510
|
+
console.log("Waiting for authorization...");
|
|
17511
|
+
await pollAndActivate({
|
|
17512
|
+
deviceCode: deviceResp.device_code,
|
|
17513
|
+
interval: (deviceResp.interval || 5) * 1000,
|
|
17514
|
+
expiresIn: deviceResp.expires_in,
|
|
17515
|
+
serverUrl,
|
|
17516
|
+
profile
|
|
17314
17517
|
});
|
|
17315
|
-
console.log(`
|
|
17316
|
-
Registered as ${me.email}`);
|
|
17317
|
-
console.log(`Workspace: ${ws.name} (${ws.id})`);
|
|
17318
|
-
console.log(`Runtimes: ${activateResp.runtimes.map((r) => r.provider).join(", ")}`);
|
|
17319
|
-
const daemonPid = readDaemonPid(profile);
|
|
17320
|
-
if (daemonPid && isProcessAlive(daemonPid)) {
|
|
17321
|
-
try {
|
|
17322
|
-
process.kill(daemonPid, "SIGHUP");
|
|
17323
|
-
console.log(`
|
|
17324
|
-
Daemon (pid ${daemonPid}) notified — workspace will be active shortly.`);
|
|
17325
|
-
} catch {
|
|
17326
|
-
console.log(`
|
|
17327
|
-
Daemon is running but could not be notified. Restart it to pick up the new workspace.`);
|
|
17328
|
-
}
|
|
17329
|
-
} else {
|
|
17330
|
-
const startCmd = isDev() ? `${cmdPrefix()} daemon start --foreground` : `${cmdPrefix()} daemon start`;
|
|
17331
|
-
console.log();
|
|
17332
|
-
console.log(`Run '${startCmd}' to start the daemon.`);
|
|
17333
|
-
}
|
|
17334
17518
|
});
|
|
17335
17519
|
return cmd;
|
|
17336
17520
|
}
|
|
17337
17521
|
|
|
17338
17522
|
// commands/status.ts
|
|
17339
|
-
import { Command as
|
|
17523
|
+
import { Command as Command3 } from "commander";
|
|
17340
17524
|
function statusCommand() {
|
|
17341
|
-
const cmd = new
|
|
17525
|
+
const cmd = new Command3("status").description("Show registration status").action((_opts, command) => {
|
|
17342
17526
|
const profile = command.parent?.opts().profile;
|
|
17343
17527
|
const cfg = loadCLIConfigForProfile(profile);
|
|
17344
17528
|
const ws = cfg.watched_workspaces?.[0];
|
|
@@ -17355,8 +17539,8 @@ function statusCommand() {
|
|
|
17355
17539
|
}
|
|
17356
17540
|
|
|
17357
17541
|
// commands/daemon.ts
|
|
17358
|
-
import { Command as
|
|
17359
|
-
import { spawn as
|
|
17542
|
+
import { Command as Command4 } from "commander";
|
|
17543
|
+
import { spawn as spawn7 } from "child_process";
|
|
17360
17544
|
import { openSync as openSync2, closeSync as closeSync2, mkdirSync as mkdirSync9 } from "fs";
|
|
17361
17545
|
import { dirname as dirname4 } from "path";
|
|
17362
17546
|
|
|
@@ -17512,7 +17696,7 @@ function createHealthServer(port = DEFAULT_HEALTH_PORT) {
|
|
|
17512
17696
|
}
|
|
17513
17697
|
|
|
17514
17698
|
// daemon/agent/claude.ts
|
|
17515
|
-
import { spawn } from "child_process";
|
|
17699
|
+
import { spawn as spawn2 } from "child_process";
|
|
17516
17700
|
import { createInterface } from "readline";
|
|
17517
17701
|
|
|
17518
17702
|
class ClaudeBackend {
|
|
@@ -17540,7 +17724,7 @@ class ClaudeBackend {
|
|
|
17540
17724
|
if (options.resumeSessionId) {
|
|
17541
17725
|
args.push("--resume", options.resumeSessionId);
|
|
17542
17726
|
}
|
|
17543
|
-
const proc =
|
|
17727
|
+
const proc = spawn2(this.cliPath, args, {
|
|
17544
17728
|
cwd: options.cwd,
|
|
17545
17729
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17546
17730
|
env: { ...process.env, ...options.env },
|
|
@@ -17777,7 +17961,7 @@ function handleControlRequest(proc, event) {
|
|
|
17777
17961
|
}
|
|
17778
17962
|
|
|
17779
17963
|
// daemon/agent/codex.ts
|
|
17780
|
-
import { spawn as
|
|
17964
|
+
import { spawn as spawn3 } from "child_process";
|
|
17781
17965
|
import { createInterface as createInterface2 } from "readline";
|
|
17782
17966
|
var RAW_DETECTION_METHODS = new Set([
|
|
17783
17967
|
"turn/started",
|
|
@@ -17809,7 +17993,7 @@ class CodexBackend {
|
|
|
17809
17993
|
this.cliPath = cliPath;
|
|
17810
17994
|
}
|
|
17811
17995
|
execute(prompt, options) {
|
|
17812
|
-
const proc =
|
|
17996
|
+
const proc = spawn3(this.cliPath, ["app-server", "--listen", "stdio://", "--config", "sandbox_mode=danger-full-access"], {
|
|
17813
17997
|
cwd: options.cwd,
|
|
17814
17998
|
stdio: ["pipe", "pipe", "pipe"],
|
|
17815
17999
|
env: { ...process.env, ...options.env },
|
|
@@ -18281,7 +18465,7 @@ class CodexBackend {
|
|
|
18281
18465
|
}
|
|
18282
18466
|
|
|
18283
18467
|
// daemon/agent/opencode.ts
|
|
18284
|
-
import { spawn as
|
|
18468
|
+
import { spawn as spawn4 } from "child_process";
|
|
18285
18469
|
import { createInterface as createInterface3 } from "readline";
|
|
18286
18470
|
|
|
18287
18471
|
class OpenCodeBackend {
|
|
@@ -18299,7 +18483,7 @@ class OpenCodeBackend {
|
|
|
18299
18483
|
args.push("--session", options.resumeSessionId);
|
|
18300
18484
|
}
|
|
18301
18485
|
args.push(prompt);
|
|
18302
|
-
const proc =
|
|
18486
|
+
const proc = spawn4(this.cliPath, args, {
|
|
18303
18487
|
cwd: options.cwd,
|
|
18304
18488
|
stdio: ["ignore", "pipe", "pipe"],
|
|
18305
18489
|
env: { ...process.env, ...options.env, OPENCODE_PERMISSION: '{"*":"allow"}' },
|
|
@@ -18831,6 +19015,23 @@ Upload files for your owner to review in the app.
|
|
|
18831
19015
|
When your task includes attachments, their local paths are listed in the prompt JSON under "attachments".
|
|
18832
19016
|
Use your Read tool to open them. Images and PDFs are read visually.
|
|
18833
19017
|
---
|
|
19018
|
+
`;
|
|
19019
|
+
content += `
|
|
19020
|
+
### Agent Management
|
|
19021
|
+
Recruit new colleague agents directly from the CLI. The server auto-generates a name and email handle.
|
|
19022
|
+
- Run '${cmdPrefix()} agent recruit --instructions "<SYSTEM_PROMPT>" --relationship "<DELEGATION_CRITERIA>"'
|
|
19023
|
+
- '--instructions' — the new agent's system prompt (what it does, how it behaves)
|
|
19024
|
+
- '--relationship' — delegation criteria shown in both agents' COLLEAGUES section
|
|
19025
|
+
- '--name <name>' (optional) — preferred name; server generates one if omitted
|
|
19026
|
+
- '--description <text>' (optional) — agent description
|
|
19027
|
+
- '--model <model>' (optional) — model override
|
|
19028
|
+
- '--instructions-file <path>' — alternative: read instructions from a file (mutually exclusive with --instructions)
|
|
19029
|
+
- '--relationship-file <path>' — alternative: read relationship from a file (mutually exclusive with --relationship)
|
|
19030
|
+
- '--json' — output full JSON response
|
|
19031
|
+
- Example: '${cmdPrefix()} agent recruit --instructions "You are a QA engineer..." --relationship "DELEGATE when: code is ready for review"'
|
|
19032
|
+
- Output: 'Recruited Felix (felix@alook.ai) — ag_xK9mPq2z'
|
|
19033
|
+
- The new agent shares your runtime, is automatically linked as your colleague, and receives a welcome task.
|
|
19034
|
+
---
|
|
18834
19035
|
`;
|
|
18835
19036
|
content += `
|
|
18836
19037
|
### Calendar
|
|
@@ -19056,7 +19257,7 @@ function localISOString() {
|
|
|
19056
19257
|
function lockPathFor(timelineDir, filename) {
|
|
19057
19258
|
return join7(timelineDir, `.${filename}.lock`);
|
|
19058
19259
|
}
|
|
19059
|
-
function
|
|
19260
|
+
function sleep2(ms) {
|
|
19060
19261
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
19061
19262
|
}
|
|
19062
19263
|
async function initEntryAsync(timelineDir, entry) {
|
|
@@ -19066,7 +19267,7 @@ async function initEntryAsync(timelineDir, entry) {
|
|
|
19066
19267
|
try {
|
|
19067
19268
|
let acquired = acquireLock(lockPath);
|
|
19068
19269
|
if (!acquired) {
|
|
19069
|
-
await
|
|
19270
|
+
await sleep2(200);
|
|
19070
19271
|
acquired = acquireLock(lockPath);
|
|
19071
19272
|
}
|
|
19072
19273
|
if (!acquired) {
|
|
@@ -19868,7 +20069,7 @@ class DaemonWsClient {
|
|
|
19868
20069
|
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4 } from "fs";
|
|
19869
20070
|
|
|
19870
20071
|
// lib/update.ts
|
|
19871
|
-
import { spawn as
|
|
20072
|
+
import { spawn as spawn5 } from "child_process";
|
|
19872
20073
|
function fetchLatestVersion() {
|
|
19873
20074
|
return fetch("https://registry.npmjs.org/@alook/cli/latest").then((res) => {
|
|
19874
20075
|
if (!res.ok)
|
|
@@ -19879,7 +20080,7 @@ function fetchLatestVersion() {
|
|
|
19879
20080
|
function runNpmUpdate(targetVersion) {
|
|
19880
20081
|
return new Promise((resolve) => {
|
|
19881
20082
|
const chunks = [];
|
|
19882
|
-
const child =
|
|
20083
|
+
const child = spawn5("npm", ["install", "-g", `@alook/cli@${targetVersion}`], {
|
|
19883
20084
|
stdio: ["ignore", "pipe", "pipe"]
|
|
19884
20085
|
});
|
|
19885
20086
|
child.stdout?.on("data", (d) => chunks.push(d));
|
|
@@ -20432,11 +20633,11 @@ function resolveLoginShellEnv() {
|
|
|
20432
20633
|
// daemon/daemon.ts
|
|
20433
20634
|
import { existsSync as existsSync3, mkdirSync as mkdirSync8, openSync, closeSync, readdirSync as readdirSync3, statSync as statSync4, unlinkSync as unlinkSync5 } from "fs";
|
|
20434
20635
|
import { readdir as readdir2, readFile as readFile2, unlink, stat as fsStat } from "fs/promises";
|
|
20435
|
-
import { execSync as execSync4, spawn as
|
|
20436
|
-
import { fileURLToPath as
|
|
20636
|
+
import { execSync as execSync4, spawn as spawn6 } from "child_process";
|
|
20637
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
20437
20638
|
import { dirname as dirname3, join as join11 } from "path";
|
|
20438
20639
|
var log9 = createLogger2({ module: "daemon" });
|
|
20439
|
-
var _dir = dirname3(
|
|
20640
|
+
var _dir = dirname3(fileURLToPath3(import.meta.url));
|
|
20440
20641
|
var sessionRunnerPath = existsSync3(join11(_dir, "session-runner.js")) ? join11(_dir, "session-runner.js") : join11(_dir, "session-runner.ts");
|
|
20441
20642
|
var meetingRunnerPath = existsSync3(join11(_dir, "meeting-runner.js")) ? join11(_dir, "meeting-runner.js") : join11(_dir, "meeting-runner.ts");
|
|
20442
20643
|
function isCommandAvailable2(cmd) {
|
|
@@ -20888,17 +21089,17 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20888
21089
|
break;
|
|
20889
21090
|
case "daemon.kill": {
|
|
20890
21091
|
const ws = workspaceStates.find((w) => w.workspaceId === msg.workspaceId);
|
|
20891
|
-
if (ws) {
|
|
21092
|
+
if (ws && !activeTasks.has(msg.taskId)) {
|
|
20892
21093
|
const killTask = fromApiTask({
|
|
20893
21094
|
id: msg.taskId,
|
|
20894
|
-
agent_id:
|
|
21095
|
+
agent_id: msg.agentId,
|
|
20895
21096
|
runtime_id: "",
|
|
20896
21097
|
conversation_id: "",
|
|
20897
21098
|
workspace_id: ws.workspaceId,
|
|
20898
21099
|
prompt: "",
|
|
20899
|
-
status: "
|
|
21100
|
+
status: "dispatched",
|
|
20900
21101
|
priority: 0,
|
|
20901
|
-
dispatched_at:
|
|
21102
|
+
dispatched_at: new Date().toISOString(),
|
|
20902
21103
|
started_at: null,
|
|
20903
21104
|
completed_at: null,
|
|
20904
21105
|
result: null,
|
|
@@ -20997,7 +21198,7 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20997
21198
|
} catch (e) {
|
|
20998
21199
|
log9.error(`Failed to open daemon log file ${logPath}`, e);
|
|
20999
21200
|
}
|
|
21000
|
-
const child =
|
|
21201
|
+
const child = spawn6(process.execPath, args, {
|
|
21001
21202
|
detached: true,
|
|
21002
21203
|
stdio: logFd != null ? ["ignore", logFd, logFd] : ["ignore", "ignore", "ignore"],
|
|
21003
21204
|
env: resolveLoginShellEnv()
|
|
@@ -21072,7 +21273,7 @@ function spawnSessionRunner(input) {
|
|
|
21072
21273
|
} catch (e) {
|
|
21073
21274
|
log9.error(`Failed to open log file ${logFilePath}`, e);
|
|
21074
21275
|
}
|
|
21075
|
-
const child =
|
|
21276
|
+
const child = spawn6(process.execPath, [sessionRunnerPath, encoded], {
|
|
21076
21277
|
detached: true,
|
|
21077
21278
|
stdio: fd != null ? ["ignore", fd, fd] : ["ignore", "ignore", "ignore"]
|
|
21078
21279
|
});
|
|
@@ -21092,7 +21293,7 @@ function spawnMeetingRunner(input) {
|
|
|
21092
21293
|
} catch (e) {
|
|
21093
21294
|
log9.error(`Failed to open meeting log file ${logFilePath}`, e);
|
|
21094
21295
|
}
|
|
21095
|
-
const child =
|
|
21296
|
+
const child = spawn6(process.execPath, [meetingRunnerPath, encoded], {
|
|
21096
21297
|
detached: true,
|
|
21097
21298
|
stdio: fd != null ? ["ignore", fd, fd] : ["ignore", "ignore", "ignore"]
|
|
21098
21299
|
});
|
|
@@ -21258,9 +21459,16 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
21258
21459
|
child.on("close", async (code) => {
|
|
21259
21460
|
activeTasks.delete(task.id);
|
|
21260
21461
|
if (code !== 0) {
|
|
21462
|
+
const agentBaseDir = join11(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir");
|
|
21463
|
+
const killIntent = readKillIntent(agentBaseDir, task.id);
|
|
21464
|
+
if (killIntent) {
|
|
21465
|
+
log9.info(`Task ${task.id} exited due to kill intent — skipping failTask`);
|
|
21466
|
+
clearKillIntent(agentBaseDir, task.id);
|
|
21467
|
+
return;
|
|
21468
|
+
}
|
|
21261
21469
|
const msg = code === null ? `session-runner killed by signal (task ${task.id})` : `session-runner crashed (exit code ${code}, task ${task.id})`;
|
|
21262
21470
|
log9.warn(msg);
|
|
21263
|
-
const timelineDir = join11(
|
|
21471
|
+
const timelineDir = join11(agentBaseDir, ".context_timeline");
|
|
21264
21472
|
updateEntry(timelineDir, task.id, (entry) => {
|
|
21265
21473
|
entry.pid = null;
|
|
21266
21474
|
entry.status = "failed";
|
|
@@ -21294,7 +21502,7 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
21294
21502
|
var PID_POLL_INTERVAL_MS = 200;
|
|
21295
21503
|
var PID_POLL_TIMEOUT_MS = 2000;
|
|
21296
21504
|
var STOP_POLL_INTERVAL_MS = 200;
|
|
21297
|
-
function
|
|
21505
|
+
function sleep3(ms) {
|
|
21298
21506
|
return new Promise((r) => setTimeout(r, ms));
|
|
21299
21507
|
}
|
|
21300
21508
|
function buildChildArgs(profile, serverUrl) {
|
|
@@ -21313,7 +21521,7 @@ async function waitForPidFile(profile) {
|
|
|
21313
21521
|
const pid = readDaemonPid(profile);
|
|
21314
21522
|
if (pid != null && isProcessAlive(pid))
|
|
21315
21523
|
return pid;
|
|
21316
|
-
await
|
|
21524
|
+
await sleep3(PID_POLL_INTERVAL_MS);
|
|
21317
21525
|
}
|
|
21318
21526
|
return null;
|
|
21319
21527
|
}
|
|
@@ -21327,7 +21535,7 @@ async function startInBackground(profile, serverUrl) {
|
|
|
21327
21535
|
const logPath = daemonLogFilePath();
|
|
21328
21536
|
mkdirSync9(dirname4(logPath), { recursive: true, mode: 448 });
|
|
21329
21537
|
const logFd = openSync2(logPath, "a", 384);
|
|
21330
|
-
const child =
|
|
21538
|
+
const child = spawn7(process.execPath, buildChildArgs(profile, serverUrl), {
|
|
21331
21539
|
detached: true,
|
|
21332
21540
|
stdio: ["ignore", logFd, logFd],
|
|
21333
21541
|
env: resolveLoginShellEnv()
|
|
@@ -21381,7 +21589,7 @@ async function stopCommand(profile) {
|
|
|
21381
21589
|
console.log("Daemon stopped.");
|
|
21382
21590
|
return;
|
|
21383
21591
|
}
|
|
21384
|
-
await
|
|
21592
|
+
await sleep3(STOP_POLL_INTERVAL_MS);
|
|
21385
21593
|
}
|
|
21386
21594
|
console.warn(`Daemon did not exit within ${shutdownMs}ms — force killing.`);
|
|
21387
21595
|
if (!isWindows) {
|
|
@@ -21393,7 +21601,7 @@ async function stopCommand(profile) {
|
|
|
21393
21601
|
console.log("Daemon stopped.");
|
|
21394
21602
|
}
|
|
21395
21603
|
function daemonCommand2() {
|
|
21396
|
-
const cmd = new
|
|
21604
|
+
const cmd = new Command4("daemon").description("Manage the Alook daemon");
|
|
21397
21605
|
cmd.command("start").description("Start the daemon").option("--foreground", "Run in foreground").option("--server <url>", "Server URL override").action(async (opts, command) => {
|
|
21398
21606
|
const parentOpts = command.parent?.parent?.opts() || {};
|
|
21399
21607
|
const profile = parentOpts.profile;
|
|
@@ -21416,7 +21624,7 @@ function daemonCommand2() {
|
|
|
21416
21624
|
}
|
|
21417
21625
|
|
|
21418
21626
|
// commands/config.ts
|
|
21419
|
-
import { Command as
|
|
21627
|
+
import { Command as Command5 } from "commander";
|
|
21420
21628
|
|
|
21421
21629
|
// lib/output.ts
|
|
21422
21630
|
function printTable(headers, rows) {
|
|
@@ -21433,7 +21641,7 @@ function printJSON(data) {
|
|
|
21433
21641
|
|
|
21434
21642
|
// commands/config.ts
|
|
21435
21643
|
function configCommand() {
|
|
21436
|
-
const cmd = new
|
|
21644
|
+
const cmd = new Command5("config").description("Manage CLI configuration");
|
|
21437
21645
|
cmd.command("show").description("Show current configuration").action(() => {
|
|
21438
21646
|
const cfg = loadCLIConfig();
|
|
21439
21647
|
printJSON(cfg);
|
|
@@ -21445,7 +21653,7 @@ function configCommand() {
|
|
|
21445
21653
|
}
|
|
21446
21654
|
|
|
21447
21655
|
// commands/email.ts
|
|
21448
|
-
import { Command as
|
|
21656
|
+
import { Command as Command6 } from "commander";
|
|
21449
21657
|
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync10, readFileSync as readFileSync11 } from "fs";
|
|
21450
21658
|
import { join as join12 } from "path";
|
|
21451
21659
|
import PostalMime from "postal-mime";
|
|
@@ -21602,7 +21810,7 @@ var VALID_STATUSES = ["unread", "read", "archived", "sent"];
|
|
|
21602
21810
|
var VALID_FOLDERS = ["inbox", "sent", "untrust"];
|
|
21603
21811
|
var EMAIL_BASE = tempDir("alook-emails");
|
|
21604
21812
|
function emailCommand() {
|
|
21605
|
-
const cmd = new
|
|
21813
|
+
const cmd = new Command6("email").description("Manage agent emails");
|
|
21606
21814
|
cmd.command("pull").description("Download and parse emails to /tmp/alook-emails/{workspaceId}/{agentId}/").option("--agent_id <id>", "Agent ID").option("--email_id <id>", "Fetch a single email by ID (mutually exclusive with --status/--folder/--limit/--offset)").option("--status <status>", "Filter by status (unread, read, archived)").option("--folder <folder>", "Email folder (inbox, sent, untrust)").option("--limit <n>", "Maximum number of emails to download").option("--offset <n>", "Number of emails to skip").option("--workspace <id>", "Workspace ID").option("--json", "Output as JSON instead of files").action(async (opts, command) => {
|
|
21607
21815
|
const agentId = resolveAgentId(opts);
|
|
21608
21816
|
const { serverUrl, token, workspaceId } = resolveClientOpts(command, { workspace: opts.workspace, agentId });
|
|
@@ -21888,7 +22096,7 @@ function emailCommand() {
|
|
|
21888
22096
|
process.exit(1);
|
|
21889
22097
|
}
|
|
21890
22098
|
});
|
|
21891
|
-
const whitelistCmd = new
|
|
22099
|
+
const whitelistCmd = new Command6("whitelist").description("Manage email whitelist (allowed senders)");
|
|
21892
22100
|
whitelistCmd.command("list").description("List all whitelisted emails for an agent").option("--agent_id <id>", "Agent ID").option("--workspace <id>", "Workspace ID").option("--json", "Output as JSON").action(async (opts, command) => {
|
|
21893
22101
|
const agentId = resolveAgentId(opts);
|
|
21894
22102
|
const { serverUrl, token, workspaceId } = resolveClientOpts(command, {
|
|
@@ -21962,7 +22170,7 @@ function emailCommand() {
|
|
|
21962
22170
|
}
|
|
21963
22171
|
|
|
21964
22172
|
// commands/calendar.ts
|
|
21965
|
-
import { Command as
|
|
22173
|
+
import { Command as Command7 } from "commander";
|
|
21966
22174
|
function parseLocalDatetime(input) {
|
|
21967
22175
|
const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(?::(\d{2}))?$/.exec(input);
|
|
21968
22176
|
if (!match) {
|
|
@@ -21993,7 +22201,7 @@ function printEventDetail(ev) {
|
|
|
21993
22201
|
console.log(ev.description ?? "(no description)");
|
|
21994
22202
|
}
|
|
21995
22203
|
function calendarCommand() {
|
|
21996
|
-
const cmd = new
|
|
22204
|
+
const cmd = new Command7("calendar").description("Manage scheduled agent events");
|
|
21997
22205
|
cmd.command("set").description("Create a calendar event").option("--agent_id <id>", "Agent ID").requiredOption("--event_title <title>", "Event title (used as the task prompt)").requiredOption("--datetime <iso>", "Scheduled datetime (YYYY-MM-DDTHH:MM, local time)").option("--description <text>", "Optional longer-form notes for the event").option("--repeat <interval>", "Repeat interval, e.g. 1day, 2hour, 1month").option("--repeat_stop_date <date>", "Stop repeating on or after this date (YYYY-MM-DD, local time)").option("--json", "Output as JSON").action(async (opts, command) => {
|
|
21998
22206
|
const agentId = resolveAgentId(opts);
|
|
21999
22207
|
const { serverUrl, token, workspaceId } = resolveClientOpts(command, { agentId });
|
|
@@ -22165,7 +22373,7 @@ function calendarCommand() {
|
|
|
22165
22373
|
}
|
|
22166
22374
|
|
|
22167
22375
|
// commands/issue.ts
|
|
22168
|
-
import { Command as
|
|
22376
|
+
import { Command as Command8 } from "commander";
|
|
22169
22377
|
var VALID_STATUSES2 = ["todo", "in_progress", "review", "done", "closed", "canceled", "failed"];
|
|
22170
22378
|
function printIssue(issue3) {
|
|
22171
22379
|
console.log(`${issue3.id} ${issue3.status.padEnd(11)} ${issue3.title}`);
|
|
@@ -22197,7 +22405,7 @@ comments:`);
|
|
|
22197
22405
|
}
|
|
22198
22406
|
}
|
|
22199
22407
|
function issueCommand() {
|
|
22200
|
-
const cmd = new
|
|
22408
|
+
const cmd = new Command8("issue").description("Manage assigned issues");
|
|
22201
22409
|
cmd.command("create").description("Create and dispatch an issue to an agent").option("--agent_id <id>", "Agent ID").requiredOption("--title <title>", "Issue title").option("--description <text>", "Issue description").option("--body-file <path>", "Read issue description from a file").option("--json", "Output as JSON").action(async (opts, command) => {
|
|
22202
22410
|
const agentId = resolveAgentId(opts);
|
|
22203
22411
|
const { serverUrl, token, workspaceId } = resolveClientOpts(command, { agentId });
|
|
@@ -22315,19 +22523,70 @@ function issueCommand() {
|
|
|
22315
22523
|
return cmd;
|
|
22316
22524
|
}
|
|
22317
22525
|
|
|
22526
|
+
// commands/agent.ts
|
|
22527
|
+
import { Command as Command9 } from "commander";
|
|
22528
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
22529
|
+
function readField(opts, inlineName, fileName) {
|
|
22530
|
+
if (opts.inline && opts.file) {
|
|
22531
|
+
console.error(`Error: --${inlineName} and --${fileName} are mutually exclusive`);
|
|
22532
|
+
process.exit(1);
|
|
22533
|
+
}
|
|
22534
|
+
if (opts.file)
|
|
22535
|
+
return readFileSync12(opts.file, "utf-8");
|
|
22536
|
+
return opts.inline ?? null;
|
|
22537
|
+
}
|
|
22538
|
+
function agentCommand() {
|
|
22539
|
+
const cmd = new Command9("agent").description("Manage agents");
|
|
22540
|
+
cmd.command("recruit").description("Recruit a new colleague agent").option("--agent_id <id>", "Agent ID (or set ALOOK_AGENT_ID env var)").option("--instructions <text>", "Instructions for the new agent (system prompt)").option("--instructions-file <path>", "Read instructions from a file").option("--relationship <text>", "Relationship/delegation instruction for the link").option("--relationship-file <path>", "Read relationship from a file").option("--name <name>", "Preferred name for the new agent (auto-generated if omitted)").option("--description <text>", "Agent description").option("--model <model>", "Model override").option("--json", "Output as JSON").action(async (opts, command) => {
|
|
22541
|
+
const instructions = readField({ inline: opts.instructions, file: opts.instructionsFile }, "instructions", "instructions-file");
|
|
22542
|
+
if (!instructions) {
|
|
22543
|
+
console.error("Error: --instructions or --instructions-file is required");
|
|
22544
|
+
process.exit(1);
|
|
22545
|
+
}
|
|
22546
|
+
const relationship = readField({ inline: opts.relationship, file: opts.relationshipFile }, "relationship", "relationship-file");
|
|
22547
|
+
if (!relationship) {
|
|
22548
|
+
console.error("Error: --relationship or --relationship-file is required");
|
|
22549
|
+
process.exit(1);
|
|
22550
|
+
}
|
|
22551
|
+
const agentId = resolveAgentId(opts);
|
|
22552
|
+
const { serverUrl, token, workspaceId } = resolveClientOpts(command, { agentId });
|
|
22553
|
+
const client = new APIClient(serverUrl, token, workspaceId);
|
|
22554
|
+
const ctx = gatherContextEnvVars();
|
|
22555
|
+
const body = { instructions, relationship };
|
|
22556
|
+
if (opts.name)
|
|
22557
|
+
body.name = opts.name;
|
|
22558
|
+
if (opts.description)
|
|
22559
|
+
body.description = opts.description;
|
|
22560
|
+
if (opts.model)
|
|
22561
|
+
body.model = opts.model;
|
|
22562
|
+
if (ctx.conversationId)
|
|
22563
|
+
body.context_key = ctx.conversationId;
|
|
22564
|
+
try {
|
|
22565
|
+
const res = await client.postJSON(`/api/agents/recruit?agentId=${encodeURIComponent(agentId)}`, body);
|
|
22566
|
+
if (opts.json)
|
|
22567
|
+
return printJSON(res);
|
|
22568
|
+
console.log(`Recruited ${res.agent.name} (${res.agent.email}) — ${res.agent.id}`);
|
|
22569
|
+
} catch (err) {
|
|
22570
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
22571
|
+
process.exit(1);
|
|
22572
|
+
}
|
|
22573
|
+
});
|
|
22574
|
+
return cmd;
|
|
22575
|
+
}
|
|
22576
|
+
|
|
22318
22577
|
// commands/version.ts
|
|
22319
|
-
import { Command as
|
|
22578
|
+
import { Command as Command10 } from "commander";
|
|
22320
22579
|
function versionCommand() {
|
|
22321
|
-
const cmd = new
|
|
22580
|
+
const cmd = new Command10("version").description("Show CLI version").action(() => {
|
|
22322
22581
|
console.log(`alook version ${getCurrentVersion()}`);
|
|
22323
22582
|
});
|
|
22324
22583
|
return cmd;
|
|
22325
22584
|
}
|
|
22326
22585
|
|
|
22327
22586
|
// commands/update.ts
|
|
22328
|
-
import { Command as
|
|
22587
|
+
import { Command as Command11 } from "commander";
|
|
22329
22588
|
function updateCommand() {
|
|
22330
|
-
const cmd = new
|
|
22589
|
+
const cmd = new Command11("update").description("Update CLI to the latest version").action(async () => {
|
|
22331
22590
|
const current = getCurrentVersion();
|
|
22332
22591
|
console.log(`Current version: ${current}`);
|
|
22333
22592
|
const latest = await fetchLatestVersion();
|
|
@@ -22361,18 +22620,18 @@ ${result.output}`);
|
|
|
22361
22620
|
}
|
|
22362
22621
|
|
|
22363
22622
|
// commands/sync.ts
|
|
22364
|
-
import { Command as
|
|
22365
|
-
import { readFileSync as
|
|
22623
|
+
import { Command as Command12 } from "commander";
|
|
22624
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
22366
22625
|
import { basename as basename3 } from "path";
|
|
22367
22626
|
function syncCommand() {
|
|
22368
|
-
const cmd = new
|
|
22627
|
+
const cmd = new Command12("sync").description("File sync utilities");
|
|
22369
22628
|
cmd.command("upload-artifact").description("Upload a file artifact to a conversation").option("--agent_id <id>", "Agent ID").requiredOption("--conversation_id <id>", "Conversation ID").requiredOption("--file <path>", "Path to file to upload").action(async (opts, command) => {
|
|
22370
22629
|
const agentId = resolveAgentId(opts);
|
|
22371
22630
|
const { serverUrl, token, workspaceId } = resolveClientOpts(command, { agentId });
|
|
22372
22631
|
const client = new APIClient(serverUrl, token, workspaceId);
|
|
22373
22632
|
let bytes;
|
|
22374
22633
|
try {
|
|
22375
|
-
bytes =
|
|
22634
|
+
bytes = readFileSync13(opts.file);
|
|
22376
22635
|
} catch (err) {
|
|
22377
22636
|
console.error(`Error: cannot read file "${opts.file}": ${err.message}`);
|
|
22378
22637
|
process.exit(1);
|
|
@@ -22395,14 +22654,16 @@ function syncCommand() {
|
|
|
22395
22654
|
}
|
|
22396
22655
|
|
|
22397
22656
|
// src/index.ts
|
|
22398
|
-
var program = new
|
|
22657
|
+
var program = new Command13;
|
|
22399
22658
|
program.name("alook").description("Alook CLI").option("--server <url>", "Server URL").option("--profile <name>", "Profile name");
|
|
22400
22659
|
program.addCommand(registerCommand());
|
|
22660
|
+
program.addCommand(loginCommand());
|
|
22401
22661
|
program.addCommand(statusCommand());
|
|
22402
22662
|
program.addCommand(daemonCommand2());
|
|
22403
22663
|
program.addCommand(emailCommand());
|
|
22404
22664
|
program.addCommand(calendarCommand());
|
|
22405
22665
|
program.addCommand(issueCommand());
|
|
22666
|
+
program.addCommand(agentCommand());
|
|
22406
22667
|
program.addCommand(configCommand());
|
|
22407
22668
|
program.addCommand(versionCommand());
|
|
22408
22669
|
program.addCommand(updateCommand());
|