@alook/cli 0.0.101 → 0.0.103
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 +104 -23
- package/dist/session-runner.js +31 -6
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var __export = (target, all) => {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
// src/index.ts
|
|
18
|
-
import { Command as
|
|
18
|
+
import { Command as Command12 } from "commander";
|
|
19
19
|
|
|
20
20
|
// commands/register.ts
|
|
21
21
|
import { Command } from "commander";
|
|
@@ -14605,7 +14605,7 @@ var DaemonPushMessageSchema = exports_external.discriminatedUnion("type", [
|
|
|
14605
14605
|
exports_external.object({ type: exports_external.literal("daemon.evict"), workspaceId: exports_external.string() }),
|
|
14606
14606
|
exports_external.object({ type: exports_external.literal("daemon.update"), version: exports_external.string() }),
|
|
14607
14607
|
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() })
|
|
14608
|
+
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
14609
|
]);
|
|
14610
14610
|
var RegisterResponseSchema = exports_external.object({
|
|
14611
14611
|
runtimes: exports_external.array(exports_external.object({ id: exports_external.string() }))
|
|
@@ -14947,13 +14947,24 @@ var StudioMemberSchema = exports_external.object({
|
|
|
14947
14947
|
description: exports_external.string().optional().default(""),
|
|
14948
14948
|
instructions: exports_external.string().optional().default(""),
|
|
14949
14949
|
avatar_url: exports_external.string().max(2000).nullable().optional(),
|
|
14950
|
-
email_handle: exports_external.string().max(30).optional()
|
|
14950
|
+
email_handle: exports_external.string().max(30).optional(),
|
|
14951
|
+
relationship: exports_external.object({
|
|
14952
|
+
leaderSees: exports_external.string(),
|
|
14953
|
+
memberSees: exports_external.string()
|
|
14954
|
+
}).optional()
|
|
14951
14955
|
});
|
|
14952
14956
|
var CreateStudioRequestSchema = exports_external.object({
|
|
14953
14957
|
name: exports_external.string().max(100).optional(),
|
|
14954
14958
|
scenario: exports_external.string().max(50).optional(),
|
|
14955
14959
|
members: exports_external.array(StudioMemberSchema).min(1).max(4)
|
|
14956
14960
|
}).refine((v) => v.members.some((m) => m.role === "leader"), { message: "at least one member must have the leader role" });
|
|
14961
|
+
var RecruitAgentRequestSchema = exports_external.object({
|
|
14962
|
+
instructions: exports_external.string().min(1, "instructions is required"),
|
|
14963
|
+
relationship: exports_external.string().min(1, "relationship is required"),
|
|
14964
|
+
name: exports_external.string().optional(),
|
|
14965
|
+
description: exports_external.string().optional().default(""),
|
|
14966
|
+
model: exports_external.string().max(100).optional()
|
|
14967
|
+
});
|
|
14957
14968
|
// ../../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
|
|
14958
14969
|
var entityKind = Symbol.for("drizzle:entityKind");
|
|
14959
14970
|
var hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
|
|
@@ -16852,9 +16863,6 @@ var agentSkill = sqliteTable("agent_skill", {
|
|
|
16852
16863
|
// ../shared/src/db/queries/task.ts
|
|
16853
16864
|
var DEFAULT_STALE_SECONDS = Number(process.env.ALOOK_STALE_DISPATCH_TIMEOUT_S) || 20;
|
|
16854
16865
|
var DEFAULT_STALE_RUNNING_SECONDS = Number(process.env.ALOOK_STALE_RUNNING_TIMEOUT_S) || 3600;
|
|
16855
|
-
// ../shared/src/db/queries/task-message.ts
|
|
16856
|
-
var HIDDEN_STEP_TYPES = ["status", "log", "tool-result", "text"];
|
|
16857
|
-
var FIXED_PARAMS = 1 + HIDDEN_STEP_TYPES.length;
|
|
16858
16866
|
// ../shared/src/utils/email.ts
|
|
16859
16867
|
var DOMAIN = `@${process.env.ALOOK_DOMAIN || "alook.ai"}`;
|
|
16860
16868
|
var RESERVED_HANDLES = new Set([
|
|
@@ -18827,6 +18835,23 @@ Upload files for your owner to review in the app.
|
|
|
18827
18835
|
When your task includes attachments, their local paths are listed in the prompt JSON under "attachments".
|
|
18828
18836
|
Use your Read tool to open them. Images and PDFs are read visually.
|
|
18829
18837
|
---
|
|
18838
|
+
`;
|
|
18839
|
+
content += `
|
|
18840
|
+
### Agent Management
|
|
18841
|
+
Recruit new colleague agents directly from the CLI. The server auto-generates a name and email handle.
|
|
18842
|
+
- Run '${cmdPrefix()} agent recruit --instructions "<SYSTEM_PROMPT>" --relationship "<DELEGATION_CRITERIA>"'
|
|
18843
|
+
- '--instructions' — the new agent's system prompt (what it does, how it behaves)
|
|
18844
|
+
- '--relationship' — delegation criteria shown in both agents' COLLEAGUES section
|
|
18845
|
+
- '--name <name>' (optional) — preferred name; server generates one if omitted
|
|
18846
|
+
- '--description <text>' (optional) — agent description
|
|
18847
|
+
- '--model <model>' (optional) — model override
|
|
18848
|
+
- '--instructions-file <path>' — alternative: read instructions from a file (mutually exclusive with --instructions)
|
|
18849
|
+
- '--relationship-file <path>' — alternative: read relationship from a file (mutually exclusive with --relationship)
|
|
18850
|
+
- '--json' — output full JSON response
|
|
18851
|
+
- Example: '${cmdPrefix()} agent recruit --instructions "You are a QA engineer..." --relationship "DELEGATE when: code is ready for review"'
|
|
18852
|
+
- Output: 'Recruited Felix (felix@alook.ai) — ag_xK9mPq2z'
|
|
18853
|
+
- The new agent shares your runtime, is automatically linked as your colleague, and receives a welcome task.
|
|
18854
|
+
---
|
|
18830
18855
|
`;
|
|
18831
18856
|
content += `
|
|
18832
18857
|
### Calendar
|
|
@@ -18916,7 +18941,7 @@ function ensureSymlinks(workDir) {
|
|
|
18916
18941
|
symlinkSync(CANONICAL_FILE, aliasPath);
|
|
18917
18942
|
} catch (err) {
|
|
18918
18943
|
const code = err?.code;
|
|
18919
|
-
if (code === "EPERM" || code === "EACCES") {
|
|
18944
|
+
if (code === "EEXIST") {} else if (code === "EPERM" || code === "EACCES") {
|
|
18920
18945
|
copyFileSync(canonicalPath, aliasPath);
|
|
18921
18946
|
} else {
|
|
18922
18947
|
throw err;
|
|
@@ -20338,7 +20363,7 @@ function runScan() {
|
|
|
20338
20363
|
const prevHash = readCacheHash(globalCachePath(scannerConfig.daemonId, runtime));
|
|
20339
20364
|
if (prevHash !== hash2) {
|
|
20340
20365
|
const skillItems = skills.map((s) => ({ name: s.name, description: s.description }));
|
|
20341
|
-
log8.
|
|
20366
|
+
log8.debug(`Syncing global ${runtime} — ${skills.length} skills`);
|
|
20342
20367
|
const daemonId = scannerConfig.daemonId;
|
|
20343
20368
|
const syncPromises = scannerConfig.workspaces.map((ws) => clientRef.syncSkills(ws.token, {
|
|
20344
20369
|
scope: "global",
|
|
@@ -20364,7 +20389,7 @@ function runScan() {
|
|
|
20364
20389
|
const prevHash = readCacheHash(agentCachePath(target.agentId, target.runtime));
|
|
20365
20390
|
if (prevHash !== hash2) {
|
|
20366
20391
|
const skillItems = skills.map((s) => ({ name: s.name, description: s.description }));
|
|
20367
|
-
log8.
|
|
20392
|
+
log8.debug(`Syncing ${target.agentId}:${target.runtime} — ${skills.length} agent skills`);
|
|
20368
20393
|
clientRef.syncSkills(target.token, {
|
|
20369
20394
|
scope: "agent",
|
|
20370
20395
|
agent_id: target.agentId,
|
|
@@ -20884,17 +20909,17 @@ async function startDaemon(profile, serverUrl) {
|
|
|
20884
20909
|
break;
|
|
20885
20910
|
case "daemon.kill": {
|
|
20886
20911
|
const ws = workspaceStates.find((w) => w.workspaceId === msg.workspaceId);
|
|
20887
|
-
if (ws) {
|
|
20912
|
+
if (ws && !activeTasks.has(msg.taskId)) {
|
|
20888
20913
|
const killTask = fromApiTask({
|
|
20889
20914
|
id: msg.taskId,
|
|
20890
|
-
agent_id:
|
|
20915
|
+
agent_id: msg.agentId,
|
|
20891
20916
|
runtime_id: "",
|
|
20892
20917
|
conversation_id: "",
|
|
20893
20918
|
workspace_id: ws.workspaceId,
|
|
20894
20919
|
prompt: "",
|
|
20895
|
-
status: "
|
|
20920
|
+
status: "dispatched",
|
|
20896
20921
|
priority: 0,
|
|
20897
|
-
dispatched_at:
|
|
20922
|
+
dispatched_at: new Date().toISOString(),
|
|
20898
20923
|
started_at: null,
|
|
20899
20924
|
completed_at: null,
|
|
20900
20925
|
result: null,
|
|
@@ -21254,9 +21279,16 @@ async function handleTask(client, config2, runtimeIndex, task, token, activeTask
|
|
|
21254
21279
|
child.on("close", async (code) => {
|
|
21255
21280
|
activeTasks.delete(task.id);
|
|
21256
21281
|
if (code !== 0) {
|
|
21282
|
+
const agentBaseDir = join11(config2.workspacesRoot, task.workspaceId, task.agentId, "workdir");
|
|
21283
|
+
const killIntent = readKillIntent(agentBaseDir, task.id);
|
|
21284
|
+
if (killIntent) {
|
|
21285
|
+
log9.info(`Task ${task.id} exited due to kill intent — skipping failTask`);
|
|
21286
|
+
clearKillIntent(agentBaseDir, task.id);
|
|
21287
|
+
return;
|
|
21288
|
+
}
|
|
21257
21289
|
const msg = code === null ? `session-runner killed by signal (task ${task.id})` : `session-runner crashed (exit code ${code}, task ${task.id})`;
|
|
21258
21290
|
log9.warn(msg);
|
|
21259
|
-
const timelineDir = join11(
|
|
21291
|
+
const timelineDir = join11(agentBaseDir, ".context_timeline");
|
|
21260
21292
|
updateEntry(timelineDir, task.id, (entry) => {
|
|
21261
21293
|
entry.pid = null;
|
|
21262
21294
|
entry.status = "failed";
|
|
@@ -22311,19 +22343,67 @@ function issueCommand() {
|
|
|
22311
22343
|
return cmd;
|
|
22312
22344
|
}
|
|
22313
22345
|
|
|
22314
|
-
// commands/
|
|
22346
|
+
// commands/agent.ts
|
|
22315
22347
|
import { Command as Command8 } from "commander";
|
|
22348
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
22349
|
+
function readField(opts, inlineName, fileName) {
|
|
22350
|
+
if (opts.inline && opts.file) {
|
|
22351
|
+
console.error(`Error: --${inlineName} and --${fileName} are mutually exclusive`);
|
|
22352
|
+
process.exit(1);
|
|
22353
|
+
}
|
|
22354
|
+
if (opts.file)
|
|
22355
|
+
return readFileSync12(opts.file, "utf-8");
|
|
22356
|
+
return opts.inline ?? null;
|
|
22357
|
+
}
|
|
22358
|
+
function agentCommand() {
|
|
22359
|
+
const cmd = new Command8("agent").description("Manage agents");
|
|
22360
|
+
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) => {
|
|
22361
|
+
const instructions = readField({ inline: opts.instructions, file: opts.instructionsFile }, "instructions", "instructions-file");
|
|
22362
|
+
if (!instructions) {
|
|
22363
|
+
console.error("Error: --instructions or --instructions-file is required");
|
|
22364
|
+
process.exit(1);
|
|
22365
|
+
}
|
|
22366
|
+
const relationship = readField({ inline: opts.relationship, file: opts.relationshipFile }, "relationship", "relationship-file");
|
|
22367
|
+
if (!relationship) {
|
|
22368
|
+
console.error("Error: --relationship or --relationship-file is required");
|
|
22369
|
+
process.exit(1);
|
|
22370
|
+
}
|
|
22371
|
+
const agentId = resolveAgentId(opts);
|
|
22372
|
+
const { serverUrl, token, workspaceId } = resolveClientOpts(command, { agentId });
|
|
22373
|
+
const client = new APIClient(serverUrl, token, workspaceId);
|
|
22374
|
+
const body = { instructions, relationship };
|
|
22375
|
+
if (opts.name)
|
|
22376
|
+
body.name = opts.name;
|
|
22377
|
+
if (opts.description)
|
|
22378
|
+
body.description = opts.description;
|
|
22379
|
+
if (opts.model)
|
|
22380
|
+
body.model = opts.model;
|
|
22381
|
+
try {
|
|
22382
|
+
const res = await client.postJSON(`/api/agents/recruit?agentId=${encodeURIComponent(agentId)}`, body);
|
|
22383
|
+
if (opts.json)
|
|
22384
|
+
return printJSON(res);
|
|
22385
|
+
console.log(`Recruited ${res.agent.name} (${res.agent.email}) — ${res.agent.id}`);
|
|
22386
|
+
} catch (err) {
|
|
22387
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
22388
|
+
process.exit(1);
|
|
22389
|
+
}
|
|
22390
|
+
});
|
|
22391
|
+
return cmd;
|
|
22392
|
+
}
|
|
22393
|
+
|
|
22394
|
+
// commands/version.ts
|
|
22395
|
+
import { Command as Command9 } from "commander";
|
|
22316
22396
|
function versionCommand() {
|
|
22317
|
-
const cmd = new
|
|
22397
|
+
const cmd = new Command9("version").description("Show CLI version").action(() => {
|
|
22318
22398
|
console.log(`alook version ${getCurrentVersion()}`);
|
|
22319
22399
|
});
|
|
22320
22400
|
return cmd;
|
|
22321
22401
|
}
|
|
22322
22402
|
|
|
22323
22403
|
// commands/update.ts
|
|
22324
|
-
import { Command as
|
|
22404
|
+
import { Command as Command10 } from "commander";
|
|
22325
22405
|
function updateCommand() {
|
|
22326
|
-
const cmd = new
|
|
22406
|
+
const cmd = new Command10("update").description("Update CLI to the latest version").action(async () => {
|
|
22327
22407
|
const current = getCurrentVersion();
|
|
22328
22408
|
console.log(`Current version: ${current}`);
|
|
22329
22409
|
const latest = await fetchLatestVersion();
|
|
@@ -22357,18 +22437,18 @@ ${result.output}`);
|
|
|
22357
22437
|
}
|
|
22358
22438
|
|
|
22359
22439
|
// commands/sync.ts
|
|
22360
|
-
import { Command as
|
|
22361
|
-
import { readFileSync as
|
|
22440
|
+
import { Command as Command11 } from "commander";
|
|
22441
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
22362
22442
|
import { basename as basename3 } from "path";
|
|
22363
22443
|
function syncCommand() {
|
|
22364
|
-
const cmd = new
|
|
22444
|
+
const cmd = new Command11("sync").description("File sync utilities");
|
|
22365
22445
|
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) => {
|
|
22366
22446
|
const agentId = resolveAgentId(opts);
|
|
22367
22447
|
const { serverUrl, token, workspaceId } = resolveClientOpts(command, { agentId });
|
|
22368
22448
|
const client = new APIClient(serverUrl, token, workspaceId);
|
|
22369
22449
|
let bytes;
|
|
22370
22450
|
try {
|
|
22371
|
-
bytes =
|
|
22451
|
+
bytes = readFileSync13(opts.file);
|
|
22372
22452
|
} catch (err) {
|
|
22373
22453
|
console.error(`Error: cannot read file "${opts.file}": ${err.message}`);
|
|
22374
22454
|
process.exit(1);
|
|
@@ -22391,7 +22471,7 @@ function syncCommand() {
|
|
|
22391
22471
|
}
|
|
22392
22472
|
|
|
22393
22473
|
// src/index.ts
|
|
22394
|
-
var program = new
|
|
22474
|
+
var program = new Command12;
|
|
22395
22475
|
program.name("alook").description("Alook CLI").option("--server <url>", "Server URL").option("--profile <name>", "Profile name");
|
|
22396
22476
|
program.addCommand(registerCommand());
|
|
22397
22477
|
program.addCommand(statusCommand());
|
|
@@ -22399,6 +22479,7 @@ program.addCommand(daemonCommand2());
|
|
|
22399
22479
|
program.addCommand(emailCommand());
|
|
22400
22480
|
program.addCommand(calendarCommand());
|
|
22401
22481
|
program.addCommand(issueCommand());
|
|
22482
|
+
program.addCommand(agentCommand());
|
|
22402
22483
|
program.addCommand(configCommand());
|
|
22403
22484
|
program.addCommand(versionCommand());
|
|
22404
22485
|
program.addCommand(updateCommand());
|
package/dist/session-runner.js
CHANGED
|
@@ -14472,7 +14472,7 @@ var DaemonPushMessageSchema = exports_external.discriminatedUnion("type", [
|
|
|
14472
14472
|
exports_external.object({ type: exports_external.literal("daemon.evict"), workspaceId: exports_external.string() }),
|
|
14473
14473
|
exports_external.object({ type: exports_external.literal("daemon.update"), version: exports_external.string() }),
|
|
14474
14474
|
exports_external.object({ type: exports_external.literal("daemon.rescan") }),
|
|
14475
|
-
exports_external.object({ type: exports_external.literal("daemon.kill"), workspaceId: exports_external.string(), taskId: exports_external.string(), targetTaskId: exports_external.string() })
|
|
14475
|
+
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() })
|
|
14476
14476
|
]);
|
|
14477
14477
|
var RegisterResponseSchema = exports_external.object({
|
|
14478
14478
|
runtimes: exports_external.array(exports_external.object({ id: exports_external.string() }))
|
|
@@ -14814,13 +14814,24 @@ var StudioMemberSchema = exports_external.object({
|
|
|
14814
14814
|
description: exports_external.string().optional().default(""),
|
|
14815
14815
|
instructions: exports_external.string().optional().default(""),
|
|
14816
14816
|
avatar_url: exports_external.string().max(2000).nullable().optional(),
|
|
14817
|
-
email_handle: exports_external.string().max(30).optional()
|
|
14817
|
+
email_handle: exports_external.string().max(30).optional(),
|
|
14818
|
+
relationship: exports_external.object({
|
|
14819
|
+
leaderSees: exports_external.string(),
|
|
14820
|
+
memberSees: exports_external.string()
|
|
14821
|
+
}).optional()
|
|
14818
14822
|
});
|
|
14819
14823
|
var CreateStudioRequestSchema = exports_external.object({
|
|
14820
14824
|
name: exports_external.string().max(100).optional(),
|
|
14821
14825
|
scenario: exports_external.string().max(50).optional(),
|
|
14822
14826
|
members: exports_external.array(StudioMemberSchema).min(1).max(4)
|
|
14823
14827
|
}).refine((v) => v.members.some((m) => m.role === "leader"), { message: "at least one member must have the leader role" });
|
|
14828
|
+
var RecruitAgentRequestSchema = exports_external.object({
|
|
14829
|
+
instructions: exports_external.string().min(1, "instructions is required"),
|
|
14830
|
+
relationship: exports_external.string().min(1, "relationship is required"),
|
|
14831
|
+
name: exports_external.string().optional(),
|
|
14832
|
+
description: exports_external.string().optional().default(""),
|
|
14833
|
+
model: exports_external.string().max(100).optional()
|
|
14834
|
+
});
|
|
14824
14835
|
// ../../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
|
|
14825
14836
|
var entityKind = Symbol.for("drizzle:entityKind");
|
|
14826
14837
|
var hasOwnEntityKind = Symbol.for("drizzle:hasOwnEntityKind");
|
|
@@ -16719,9 +16730,6 @@ var agentSkill = sqliteTable("agent_skill", {
|
|
|
16719
16730
|
// ../shared/src/db/queries/task.ts
|
|
16720
16731
|
var DEFAULT_STALE_SECONDS = Number(process.env.ALOOK_STALE_DISPATCH_TIMEOUT_S) || 20;
|
|
16721
16732
|
var DEFAULT_STALE_RUNNING_SECONDS = Number(process.env.ALOOK_STALE_RUNNING_TIMEOUT_S) || 3600;
|
|
16722
|
-
// ../shared/src/db/queries/task-message.ts
|
|
16723
|
-
var HIDDEN_STEP_TYPES = ["status", "log", "tool-result", "text"];
|
|
16724
|
-
var FIXED_PARAMS = 1 + HIDDEN_STEP_TYPES.length;
|
|
16725
16733
|
// ../shared/src/utils/email.ts
|
|
16726
16734
|
var DOMAIN = `@${process.env.ALOOK_DOMAIN || "alook.ai"}`;
|
|
16727
16735
|
var RESERVED_HANDLES = new Set([
|
|
@@ -18165,6 +18173,23 @@ Upload files for your owner to review in the app.
|
|
|
18165
18173
|
When your task includes attachments, their local paths are listed in the prompt JSON under "attachments".
|
|
18166
18174
|
Use your Read tool to open them. Images and PDFs are read visually.
|
|
18167
18175
|
---
|
|
18176
|
+
`;
|
|
18177
|
+
content += `
|
|
18178
|
+
### Agent Management
|
|
18179
|
+
Recruit new colleague agents directly from the CLI. The server auto-generates a name and email handle.
|
|
18180
|
+
- Run '${cmdPrefix()} agent recruit --instructions "<SYSTEM_PROMPT>" --relationship "<DELEGATION_CRITERIA>"'
|
|
18181
|
+
- '--instructions' — the new agent's system prompt (what it does, how it behaves)
|
|
18182
|
+
- '--relationship' — delegation criteria shown in both agents' COLLEAGUES section
|
|
18183
|
+
- '--name <name>' (optional) — preferred name; server generates one if omitted
|
|
18184
|
+
- '--description <text>' (optional) — agent description
|
|
18185
|
+
- '--model <model>' (optional) — model override
|
|
18186
|
+
- '--instructions-file <path>' — alternative: read instructions from a file (mutually exclusive with --instructions)
|
|
18187
|
+
- '--relationship-file <path>' — alternative: read relationship from a file (mutually exclusive with --relationship)
|
|
18188
|
+
- '--json' — output full JSON response
|
|
18189
|
+
- Example: '${cmdPrefix()} agent recruit --instructions "You are a QA engineer..." --relationship "DELEGATE when: code is ready for review"'
|
|
18190
|
+
- Output: 'Recruited Felix (felix@alook.ai) — ag_xK9mPq2z'
|
|
18191
|
+
- The new agent shares your runtime, is automatically linked as your colleague, and receives a welcome task.
|
|
18192
|
+
---
|
|
18168
18193
|
`;
|
|
18169
18194
|
content += `
|
|
18170
18195
|
### Calendar
|
|
@@ -18254,7 +18279,7 @@ function ensureSymlinks(workDir) {
|
|
|
18254
18279
|
symlinkSync(CANONICAL_FILE, aliasPath);
|
|
18255
18280
|
} catch (err) {
|
|
18256
18281
|
const code = err?.code;
|
|
18257
|
-
if (code === "EPERM" || code === "EACCES") {
|
|
18282
|
+
if (code === "EEXIST") {} else if (code === "EPERM" || code === "EACCES") {
|
|
18258
18283
|
copyFileSync(canonicalPath, aliasPath);
|
|
18259
18284
|
} else {
|
|
18260
18285
|
throw err;
|