@orlan-maker/cli 0.4.0 → 0.5.0
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/README.md +4 -1
- package/dist/commands.js +61 -38
- package/dist/http.js +2 -0
- package/package.json +1 -1
- package/skills/orlan/SKILL.md +45 -8
- package/skills/orlan-versions/SKILL.md +1 -1
package/README.md
CHANGED
|
@@ -102,7 +102,10 @@ output.
|
|
|
102
102
|
|
|
103
103
|
`orlan brief` is for the start of a session. It prints the topic, the open requests, the files with
|
|
104
104
|
their current versions, and one `next_step` line, in about 500 tokens for 6 files and 3 requests. The
|
|
105
|
-
topic is the one the
|
|
105
|
+
topic is the one the person has open in Orlan now ("You are in "startups" (open in Orlan now)"). When the
|
|
106
|
+
agent cannot reach that topic, the brief says so, gives the step that grants it, and names the topic it
|
|
107
|
+
works in instead: the newer of the one it used last and the one the person opened last, else its only
|
|
108
|
+
topic. Every command with no `--topic` uses the same topic. `orlan files add` posts a new file to the
|
|
106
109
|
topic and puts it on the board, in one request. Both are plain HTTP calls with the agent token.
|
|
107
110
|
|
|
108
111
|
`orlan board` prints the board of the topic. Each item shows its id, type, place and size in board
|
package/dist/commands.js
CHANGED
|
@@ -82,12 +82,16 @@ function finish(io, values, data, lines, next) {
|
|
|
82
82
|
const topicInput = (values) => (typeof values.topic === "string" ? { topicId: values.topic } : {});
|
|
83
83
|
/**
|
|
84
84
|
* The topic of a command that needs one: --topic (an id or a name), else the topic the brief names (the
|
|
85
|
-
* one the agent used last, else its only topic).
|
|
85
|
+
* one the person has open in Orlan now, else the one the agent used last, else its only topic). When the
|
|
86
|
+
* person's open topic is out of the agent's reach, the command says so first (F123), not with --json.
|
|
86
87
|
*/
|
|
87
|
-
async function topicOrDefault(api, values) {
|
|
88
|
+
async function topicOrDefault(api, values, io) {
|
|
88
89
|
if (typeof values.topic === "string")
|
|
89
90
|
return values.topic;
|
|
90
|
-
const { topic } = await api.get("/api/agent/brief", {}, "the brief");
|
|
91
|
+
const { topic, notice } = await api.get("/api/agent/brief", {}, "the brief");
|
|
92
|
+
if (notice && !values.json)
|
|
93
|
+
for (const line of notice)
|
|
94
|
+
io.out(line);
|
|
91
95
|
if (!topic) {
|
|
92
96
|
throw new OrlanError("The agent has several topics and used none yet. Add --topic <topic>.", "topic_missing");
|
|
93
97
|
}
|
|
@@ -251,6 +255,20 @@ async function confirmPrinted(server, token, io, deliveries) {
|
|
|
251
255
|
}
|
|
252
256
|
}
|
|
253
257
|
}
|
|
258
|
+
/**
|
|
259
|
+
* "all topics", the restricted topics it also reaches and the ones it leaves out (B058), or the topic
|
|
260
|
+
* names. An older server sends no leftOut.
|
|
261
|
+
*/
|
|
262
|
+
const reachText = (scope, all) => {
|
|
263
|
+
if (!scope.allTopics)
|
|
264
|
+
return scope.topics.map((topic) => quote(topic.name)).join(", ");
|
|
265
|
+
const named = (topics) => topics.map((topic) => `${quote(topic.name)} (restricted)`).join(", ");
|
|
266
|
+
const included = scope.topics.filter((topic) => topic.restricted);
|
|
267
|
+
const leftOut = scope.leftOut ?? [];
|
|
268
|
+
return (all +
|
|
269
|
+
(included.length > 0 ? `, and ${named(included)}` : "") +
|
|
270
|
+
(leftOut.length > 0 ? `, except ${named(leftOut)}` : ""));
|
|
271
|
+
};
|
|
254
272
|
/** Prints what planOldInstall removed, on one line, and the commands that remove the rest by hand. */
|
|
255
273
|
function printRemoved(io, { removed, byHand }) {
|
|
256
274
|
if (removed.length > 0)
|
|
@@ -285,7 +303,7 @@ async function connect(agent, values, io) {
|
|
|
285
303
|
await writeConfig(config);
|
|
286
304
|
const role = made.token.role[0]?.toUpperCase() + made.token.role.slice(1);
|
|
287
305
|
io.out(`Made an agent token for ${agentLabels[agent]}: ${made.token.prefix}..., ${role} on ` +
|
|
288
|
-
`${made.token
|
|
306
|
+
`${reachText(made.token, "all topics")}. It is in the ${where === "keychain" ? "keychain" : "credentials file"}.`);
|
|
289
307
|
await writeSkills(agent);
|
|
290
308
|
io.out(`Installed the Orlan skills orlan, orlan-review and orlan-versions in ${skillsDir(agent)}.`);
|
|
291
309
|
// The test is the person's, not a call of the agent: it names no agent session.
|
|
@@ -344,7 +362,7 @@ export const commands = {
|
|
|
344
362
|
details: [
|
|
345
363
|
"Shows a code and opens the Orlan page that approves it. Sign in there, check that the code is",
|
|
346
364
|
"the same, choose the organisation, and what your agents get: one topic, or all topics of the",
|
|
347
|
-
"organisation (also the topics made later; restricted topics only when you
|
|
365
|
+
"organisation (also the topics made later; restricted topics only when you include them there).",
|
|
348
366
|
"Details also has the agent role. The CLI token goes to the OS keychain, or to a file only you can",
|
|
349
367
|
"read when there is no keychain.",
|
|
350
368
|
"",
|
|
@@ -493,9 +511,7 @@ export const commands = {
|
|
|
493
511
|
io.out(`Server: ${config.server}`);
|
|
494
512
|
io.out(`Signed in as: ${quote(status.user.name)} (${status.user.email ?? "guest account"})`);
|
|
495
513
|
io.out(`Organisation: ${quote(status.org.name)} (${status.org.role})`);
|
|
496
|
-
io.out(`New agents get: ${status.agentDefaults.role} on ${status.agentDefaults
|
|
497
|
-
? "all topics, also new ones"
|
|
498
|
-
: status.agentDefaults.topics.map((topic) => quote(topic.name)).join(", ") || "no topics (use --topic)"}`);
|
|
514
|
+
io.out(`New agents get: ${status.agentDefaults.role} on ${reachText(status.agentDefaults, "all topics, also new ones") || "no topics (use --topic)"}`);
|
|
499
515
|
if (agents.length === 0)
|
|
500
516
|
io.out("Agents: none connected.");
|
|
501
517
|
for (const { agent, token: local, role, check } of agents) {
|
|
@@ -536,8 +552,9 @@ export const commands = {
|
|
|
536
552
|
"",
|
|
537
553
|
AGENT_HELP,
|
|
538
554
|
"--topic <id> A topic the agent can use. Repeat it for more. The agent then gets only these topics.",
|
|
539
|
-
"
|
|
540
|
-
"
|
|
555
|
+
" Each must be in what you approved at sign-in: a restricted topic only when you",
|
|
556
|
+
" included it. Default: what you chose at sign-in (one topic, the ticked topics, or all topics).",
|
|
557
|
+
"--role <role> editor, commenter or viewer, not above the role you approved. Default: that role.",
|
|
541
558
|
],
|
|
542
559
|
options: CONNECT_OPTIONS,
|
|
543
560
|
positionals: [0, 0],
|
|
@@ -574,14 +591,14 @@ export const commands = {
|
|
|
574
591
|
usage: "orlan files list [--topic <topic>] [--agent <id>] [--json]",
|
|
575
592
|
summary: "List the files of a topic with their current versions.",
|
|
576
593
|
details: [
|
|
577
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
594
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
578
595
|
AGENT_TOKEN_HELP,
|
|
579
596
|
JSON_HELP,
|
|
580
597
|
],
|
|
581
598
|
options: { ...agentOption, ...jsonOption, topic: { type: "string" } },
|
|
582
599
|
positionals: [0, 0],
|
|
583
600
|
run: (values, _positionals, io) => withAgent(values, async (api) => {
|
|
584
|
-
const topicId = await topicOrDefault(api, values);
|
|
601
|
+
const topicId = await topicOrDefault(api, values, io);
|
|
585
602
|
const { files } = await api.call("read_board", { topicId, view: "files" });
|
|
586
603
|
return finish(io, values, { files }, files.length === 0
|
|
587
604
|
? ["No files."]
|
|
@@ -601,7 +618,7 @@ export const commands = {
|
|
|
601
618
|
"",
|
|
602
619
|
"--at <x,y> Put it at this point of the board, in board coordinates, or at the nearest free",
|
|
603
620
|
" place. `orlan board` shows where the items are.",
|
|
604
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
621
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
605
622
|
AGENT_TOKEN_HELP,
|
|
606
623
|
JSON_HELP,
|
|
607
624
|
],
|
|
@@ -611,7 +628,7 @@ export const commands = {
|
|
|
611
628
|
const at = numbersOption(values, "at", 2);
|
|
612
629
|
if (at) {
|
|
613
630
|
// A place on the board: the file goes up first, then the post places it.
|
|
614
|
-
const topicId = await topicOrDefault(api, values);
|
|
631
|
+
const topicId = await topicOrDefault(api, values, io);
|
|
615
632
|
const uploadId = await api.upload(await readFile(filePath), { topic: topicId });
|
|
616
633
|
const posted = await api.call("post", { topicId, name: path.basename(filePath), uploadId, position: { x: at[0], y: at[1] } });
|
|
617
634
|
return finish(io, values, {
|
|
@@ -889,7 +906,7 @@ export const commands = {
|
|
|
889
906
|
"--page <n> The page, from 1.",
|
|
890
907
|
"--region <x,y,w,h> The rectangle on the page, as fractions (0 to 1). Default: the whole page.",
|
|
891
908
|
"--at <x,y> A new thread on this point of the board, in board coordinates.",
|
|
892
|
-
"--topic <topic> The topic of --at, of a #12 or of a file name. Default: the topic
|
|
909
|
+
"--topic <topic> The topic of --at, of a #12 or of a file name. Default: the topic open in Orlan now, else the one used last.",
|
|
893
910
|
AGENT_TOKEN_HELP,
|
|
894
911
|
JSON_HELP,
|
|
895
912
|
],
|
|
@@ -985,14 +1002,14 @@ export const commands = {
|
|
|
985
1002
|
'"in frame <id>". Each box is the box after it grew to fit its words. People vote; an agent reads',
|
|
986
1003
|
"the vote and its result, it does not vote.",
|
|
987
1004
|
"",
|
|
988
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
1005
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
989
1006
|
AGENT_TOKEN_HELP,
|
|
990
1007
|
JSON_HELP,
|
|
991
1008
|
],
|
|
992
1009
|
options: { ...agentOption, ...jsonOption, topic: { type: "string" } },
|
|
993
1010
|
positionals: [0, 0],
|
|
994
1011
|
run: (values, _positionals, io) => withAgent(values, async (api) => {
|
|
995
|
-
const topicId = await topicOrDefault(api, values);
|
|
1012
|
+
const topicId = await topicOrDefault(api, values, io);
|
|
996
1013
|
// Two requests at the same time: the board, and the names of its files.
|
|
997
1014
|
const [board, { files }] = await Promise.all([
|
|
998
1015
|
api.call("read_board", { topicId, view: "board" }),
|
|
@@ -1054,7 +1071,7 @@ export const commands = {
|
|
|
1054
1071
|
"",
|
|
1055
1072
|
"--out <file.png> Where to save the picture. A file that is there is replaced.",
|
|
1056
1073
|
"--frame <frame> Only this frame: its id, from `orlan board`.",
|
|
1057
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
1074
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
1058
1075
|
AGENT_TOKEN_HELP,
|
|
1059
1076
|
JSON_HELP,
|
|
1060
1077
|
],
|
|
@@ -1070,7 +1087,7 @@ export const commands = {
|
|
|
1070
1087
|
if (typeof values.out !== "string" || !values.out) {
|
|
1071
1088
|
throw new OrlanError("Add --out <file.png>: where to save the picture.", undefined, "orlan board view --out board.png");
|
|
1072
1089
|
}
|
|
1073
|
-
const topicId = await topicOrDefault(api, values);
|
|
1090
|
+
const topicId = await topicOrDefault(api, values, io);
|
|
1074
1091
|
const answer = await api.call("view_board", { topicId, ...(typeof values.frame === "string" ? { frameId: values.frame } : {}) });
|
|
1075
1092
|
const saved = path.resolve(values.out);
|
|
1076
1093
|
const png = Buffer.from(answer.png, "base64");
|
|
@@ -1130,7 +1147,7 @@ export const commands = {
|
|
|
1130
1147
|
"--frame <frame> The frame the item goes in, by its id. none: in no frame. Default: the frame that",
|
|
1131
1148
|
" holds more than half of it.",
|
|
1132
1149
|
'--text <text> The text, as the "<text>" word gives it. For an arrow: its label, for example "yes".',
|
|
1133
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
1150
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
1134
1151
|
AGENT_TOKEN_HELP,
|
|
1135
1152
|
JSON_HELP,
|
|
1136
1153
|
],
|
|
@@ -1198,7 +1215,7 @@ export const commands = {
|
|
|
1198
1215
|
// The server refuses a frame on an arrow, and says why.
|
|
1199
1216
|
Object.assign(edit, frameOption(values));
|
|
1200
1217
|
return withAgent(values, async (api) => {
|
|
1201
|
-
const { items, warnings } = await editBoard(api, values, [edit]);
|
|
1218
|
+
const { items, warnings } = await editBoard(api, values, io, [edit]);
|
|
1202
1219
|
const item = items[0];
|
|
1203
1220
|
const where = type === "arrow" ? `, from ${values.from} to ${values.to}` : "";
|
|
1204
1221
|
return finish(io, values, { ...item, warnings }, [`Added ${boxText(item)}${where}.`, ...warningLines(warnings)], afterWarnings(warnings, type === "arrow"
|
|
@@ -1233,7 +1250,7 @@ export const commands = {
|
|
|
1233
1250
|
"--to <item> The item the arrow points to, as --from.",
|
|
1234
1251
|
"--frame <frame> Put the item in this frame, by its id. none: take it out of its frame. The item",
|
|
1235
1252
|
" stays where it is. With --at and no --frame, the item goes in the frame it lands in.",
|
|
1236
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
1253
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
1237
1254
|
AGENT_TOKEN_HELP,
|
|
1238
1255
|
JSON_HELP,
|
|
1239
1256
|
],
|
|
@@ -1272,7 +1289,7 @@ export const commands = {
|
|
|
1272
1289
|
throw new OrlanError("Give --text, --at, --size, --text-color, --kind, --color, --from, --to or --frame.", undefined, `orlan board change ${id} --text "<text>"`);
|
|
1273
1290
|
}
|
|
1274
1291
|
return withAgent(values, async (api) => {
|
|
1275
|
-
const { items, warnings } = await editBoard(api, values, edits);
|
|
1292
|
+
const { items, warnings } = await editBoard(api, values, io, edits);
|
|
1276
1293
|
const item = items.find((each) => each.id === id);
|
|
1277
1294
|
return finish(io, values, { ...(item ?? { id }), warnings }, [item ? `Changed ${boxText(item)}.` : `Changed ${id}.`, ...warningLines(warnings)], afterWarnings(warnings, "orlan board (the board with the change)"));
|
|
1278
1295
|
});
|
|
@@ -1287,14 +1304,14 @@ export const commands = {
|
|
|
1287
1304
|
"of a deleted frame stay on the board, in the frame that frame was in.",
|
|
1288
1305
|
"",
|
|
1289
1306
|
"<item> The item id, from `orlan board`. Give several to delete several.",
|
|
1290
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
1307
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
1291
1308
|
AGENT_TOKEN_HELP,
|
|
1292
1309
|
JSON_HELP,
|
|
1293
1310
|
],
|
|
1294
1311
|
options: { ...agentOption, ...jsonOption, topic: { type: "string" } },
|
|
1295
1312
|
positionals: [1, 100],
|
|
1296
1313
|
run: (values, ids, io) => withAgent(values, async (api) => {
|
|
1297
|
-
const { warnings } = await editBoard(api, values, ids.map((id) => ({ op: "delete", id })));
|
|
1314
|
+
const { warnings } = await editBoard(api, values, io, ids.map((id) => ({ op: "delete", id })));
|
|
1298
1315
|
return finish(io, values, { deleted: ids, warnings }, [
|
|
1299
1316
|
`Deleted ${ids.length === 1 ? "1 item" : `${ids.length} items`}: ${ids.join(", ")}. A person can undo it.`,
|
|
1300
1317
|
...warningLines(warnings),
|
|
@@ -1335,7 +1352,7 @@ export const commands = {
|
|
|
1335
1352
|
"the error says what to change. The answer gives each item's id and its final place and size.",
|
|
1336
1353
|
...WARNINGS_HELP,
|
|
1337
1354
|
"",
|
|
1338
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
1355
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
1339
1356
|
AGENT_TOKEN_HELP,
|
|
1340
1357
|
JSON_HELP,
|
|
1341
1358
|
],
|
|
@@ -1353,7 +1370,7 @@ export const commands = {
|
|
|
1353
1370
|
throw new OrlanError('The edits are a JSON list, for example [{"op":"delete","id":"<item>"}].', undefined, "orlan board edit --help");
|
|
1354
1371
|
}
|
|
1355
1372
|
return withAgent(values, async (api) => {
|
|
1356
|
-
const { ids, items, warnings } = await editBoard(api, values, edits);
|
|
1373
|
+
const { ids, items, warnings } = await editBoard(api, values, io, edits);
|
|
1357
1374
|
return finish(io, values, { ids, items, warnings }, [
|
|
1358
1375
|
`Made ${ids.length} change${ids.length === 1 ? "" : "s"} in one step.`,
|
|
1359
1376
|
...items.map((item) => `- ${boxText(item)}`),
|
|
@@ -1401,7 +1418,7 @@ export const commands = {
|
|
|
1401
1418
|
"",
|
|
1402
1419
|
"<file.mmd> The Mermaid file.",
|
|
1403
1420
|
"--frame <frame> Draw the diagram in this frame, by its id, from `orlan board`.",
|
|
1404
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
1421
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
1405
1422
|
AGENT_TOKEN_HELP,
|
|
1406
1423
|
JSON_HELP,
|
|
1407
1424
|
],
|
|
@@ -1411,7 +1428,7 @@ export const commands = {
|
|
|
1411
1428
|
const source = await readFile(file, "utf8").catch((error) => {
|
|
1412
1429
|
throw new OrlanError(`Orlan cannot read ${quote(file)}: ${error.code ?? error.message}.`, undefined, "give the path of a Mermaid file, for example orlan board mermaid flow.mmd");
|
|
1413
1430
|
});
|
|
1414
|
-
const topicId = await topicOrDefault(api, values);
|
|
1431
|
+
const topicId = await topicOrDefault(api, values, io);
|
|
1415
1432
|
const answer = await api.call("import_mermaid", {
|
|
1416
1433
|
topicId,
|
|
1417
1434
|
mermaid: source,
|
|
@@ -1454,7 +1471,7 @@ export const commands = {
|
|
|
1454
1471
|
"--assignee <who> me (this agent), user:<id> or agent:<id>. Default: nobody.",
|
|
1455
1472
|
"--thread <t> The comment thread the task comes from: #12 or the thread id.",
|
|
1456
1473
|
"--done The task is done already.",
|
|
1457
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
1474
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
1458
1475
|
AGENT_TOKEN_HELP,
|
|
1459
1476
|
JSON_HELP,
|
|
1460
1477
|
],
|
|
@@ -1471,7 +1488,7 @@ export const commands = {
|
|
|
1471
1488
|
const assignee = assigneeOption(config, values);
|
|
1472
1489
|
const task = await api.call("record", {
|
|
1473
1490
|
kind: "task",
|
|
1474
|
-
topicId: await topicOrDefault(api, values),
|
|
1491
|
+
topicId: await topicOrDefault(api, values, io),
|
|
1475
1492
|
text,
|
|
1476
1493
|
...(assignee ? { assignee } : {}),
|
|
1477
1494
|
...(typeof values.thread === "string" ? { sourceThreadId: values.thread } : {}),
|
|
@@ -1525,7 +1542,7 @@ export const commands = {
|
|
|
1525
1542
|
"",
|
|
1526
1543
|
"--body <text> The decision in full: what, and why.",
|
|
1527
1544
|
"--thread <t> The comment thread the decision comes from: #12 or the thread id.",
|
|
1528
|
-
"--topic <topic> The topic id or its name. Default: the topic
|
|
1545
|
+
"--topic <topic> The topic id or its name. Default: the topic open in Orlan now, else the one used last.",
|
|
1529
1546
|
AGENT_TOKEN_HELP,
|
|
1530
1547
|
JSON_HELP,
|
|
1531
1548
|
],
|
|
@@ -1540,7 +1557,7 @@ export const commands = {
|
|
|
1540
1557
|
run: (values, [title], io) => withAgent(values, async (api) => {
|
|
1541
1558
|
const decision = await api.call("record", {
|
|
1542
1559
|
kind: "decision",
|
|
1543
|
-
topicId: await topicOrDefault(api, values),
|
|
1560
|
+
topicId: await topicOrDefault(api, values, io),
|
|
1544
1561
|
title,
|
|
1545
1562
|
...(typeof values.body === "string" ? { body: values.body } : {}),
|
|
1546
1563
|
...(typeof values.thread === "string" ? { sourceThreadId: values.thread } : {}),
|
|
@@ -1602,8 +1619,12 @@ export const commands = {
|
|
|
1602
1619
|
usage: "orlan brief [--topic <topic>] [--agent <id>] [--json]",
|
|
1603
1620
|
summary: "Print where the work stands: the topic, the open requests, the files, and the next step.",
|
|
1604
1621
|
details: [
|
|
1605
|
-
"For the start of a
|
|
1606
|
-
"
|
|
1622
|
+
"For the start of a task: one short answer, in one plain HTTP call. The topic is the one the person",
|
|
1623
|
+
"has open in Orlan now, and the first lines say so. When the agent cannot reach that topic, they say",
|
|
1624
|
+
"so, give the step that grants it, and name the topic the agent works in instead: the newer of the",
|
|
1625
|
+
"one it used last and the one the person opened last, else its only topic. Other commands with no",
|
|
1626
|
+
"--topic use the same topic; in one session they keep the topic of the last call for 5 minutes.",
|
|
1627
|
+
"It lists the open requests (`orlan inbox` prints them in full),",
|
|
1607
1628
|
"the files with their current versions, the open vote and the open tasks (one line each), and one",
|
|
1608
1629
|
"next_step line. People vote; an agent reads the vote, it does not vote.",
|
|
1609
1630
|
"",
|
|
@@ -1614,7 +1635,9 @@ export const commands = {
|
|
|
1614
1635
|
options: { ...agentOption, ...jsonOption, topic: { type: "string" } },
|
|
1615
1636
|
positionals: [0, 0],
|
|
1616
1637
|
run: (values, _positionals, io) => withAgent(values, async (api) => {
|
|
1617
|
-
const { lines, nextStep, ...answer } = await api.get("/api/agent/brief",
|
|
1638
|
+
const { lines, nextStep, ...answer } = await api.get("/api/agent/brief",
|
|
1639
|
+
// The start of a task: Orlan takes the topic the person has open now again (F123).
|
|
1640
|
+
{ topic: values.topic, start: "true" }, "the brief");
|
|
1618
1641
|
// The lines end with Orlan's next_step line.
|
|
1619
1642
|
io.out(values.json ? JSON.stringify({ ...answer, next_step: nextStep }) : lines.join("\n"));
|
|
1620
1643
|
return 0;
|
|
@@ -1771,9 +1794,9 @@ export const commands = {
|
|
|
1771
1794
|
},
|
|
1772
1795
|
};
|
|
1773
1796
|
/** Runs edit_board on the topic of --topic, else the default topic: one step, all edits or none. */
|
|
1774
|
-
async function editBoard(api, values, edits) {
|
|
1797
|
+
async function editBoard(api, values, io, edits) {
|
|
1775
1798
|
const answer = await api.call("edit_board", {
|
|
1776
|
-
topicId: await topicOrDefault(api, values),
|
|
1799
|
+
topicId: await topicOrDefault(api, values, io),
|
|
1777
1800
|
edits,
|
|
1778
1801
|
});
|
|
1779
1802
|
// A server before F096 gives no warnings.
|
package/dist/http.js
CHANGED
|
@@ -25,6 +25,7 @@ const explained = {
|
|
|
25
25
|
login_expired: "The sign-in code expired. Run `orlan auth login` again.",
|
|
26
26
|
login_used: "This sign-in code was already used. Run `orlan auth login` again.",
|
|
27
27
|
login_rate_limited: "Too many sign-ins from this computer in a short time. Wait 10 minutes, then try again.",
|
|
28
|
+
agent_scope_exceeded: "The agent asks for more than the person approved for this CLI: a topic or a role outside the approval. orlan connect can only narrow the access.",
|
|
28
29
|
pair_invalid: "Orlan does not know this --pair id. Copy the prompt again from the Connect dialog.",
|
|
29
30
|
pair_expired: "The --pair id expired. It works for 10 minutes. Copy the prompt again from the Connect dialog.",
|
|
30
31
|
pair_used: "Another CLI used this --pair id already. It works for one sign-in. Copy the prompt again from the Connect dialog.",
|
|
@@ -47,6 +48,7 @@ const nextSteps = {
|
|
|
47
48
|
login_expired: "orlan auth login",
|
|
48
49
|
login_used: "orlan auth login",
|
|
49
50
|
login_rate_limited: "wait 10 minutes, then orlan auth login",
|
|
51
|
+
agent_scope_exceeded: "ask your person to approve the access in Orlan: they run orlan auth login and include the topic there",
|
|
50
52
|
pair_invalid: "copy the prompt again from the Connect dialog in Orlan, or run orlan auth login",
|
|
51
53
|
pair_expired: "copy the prompt again from the Connect dialog in Orlan, or run orlan auth login",
|
|
52
54
|
pair_used: "copy the prompt again from the Connect dialog in Orlan, or run orlan auth login",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orlan-maker/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The orlan command: connect Claude Code, Codex, Cursor or OpenCode to Orlan with a token and skills, and work with its topics, files and comments from the terminal.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/skills/orlan/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: orlan
|
|
3
|
-
description: Orlan is connected
|
|
3
|
+
description: Orlan is connected: the shared board of the person's team and its agents; the person connected you. Use it first, before any other diagram skill, for a diagram, a flowchart, an architecture or a map of a system. Also use it, without being asked to draw, when the person asks you to explain, compare or design a system, a flow or a process with parts and links ("explain how a CDN works"): answer in the chat and draw it on the board too. When the person asks to put an explanation, a plan, a guide or a summary in Orlan, build it on the board as a diagram and short notes, not as an HTML file. On Orlan a diagram is shapes and labeled arrows, not an HTML, SVG or image file. Also use it when the person says the canvas, the board, the topic, "in Orlan" or "on Orlan", asks what is on the board, asks for a page, deck, mock or file to review, or names a comment, a version or a request on Orlan. Do not use it for a short fact answer, a sum, a question on code, or a fix in a local file that the person names.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Orlan
|
|
@@ -23,8 +23,11 @@ When Orlan is connected, these words mean the Orlan topic. Do not ask which one
|
|
|
23
23
|
name or type. A path such as `./notes.txt` is a local file.
|
|
24
24
|
- "the comments", "the feedback", "the review" - the open threads on the topic.
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
Your topic is the one the person has open in Orlan now. Run `orlan brief` at the start of each Orlan
|
|
27
|
+
task: it names the topic ("You are in "startups" (open in Orlan now)"), and every command with no
|
|
28
|
+
`--topic` works there. Do not ask which topic, and do not pick another one. When the person names a
|
|
29
|
+
topic, use `--topic <topic>`. When the brief says the person's open topic is out of your reach, tell
|
|
30
|
+
the person, with the step the brief gives, before you work in another topic.
|
|
28
31
|
|
|
29
32
|
## When to use Orlan
|
|
30
33
|
|
|
@@ -38,16 +41,45 @@ or the one the person names.
|
|
|
38
41
|
"design a payment flow"): answer in the chat, and also draw it on the board. Do not ask first, and do
|
|
39
42
|
not wait for the word "Orlan" or "board". End the answer with one line that says where the drawing
|
|
40
43
|
is: the topic and the frame. A short fact answer ("what port does HTTPS use") stays in the chat.
|
|
44
|
+
- The person asks you to put an explanation, a plan, a guide or a summary in Orlan ("put all of this in
|
|
45
|
+
Orlan", "put it on the board"): build it on the board. Follow "Put it in Orlan" below. No HTML file.
|
|
41
46
|
- The person asks for a note, a text, a shape, a frame or an arrow on the board: `orlan board add`.
|
|
42
47
|
Change one with `orlan board change <item>`, delete one with `orlan board delete <item>`.
|
|
43
|
-
- The person asks
|
|
44
|
-
|
|
48
|
+
- The person asks for a page, a document, a deck, a mock, a report or a chart as a file: make the file,
|
|
49
|
+
check it, then post it to the topic:
|
|
45
50
|
`orlan files add <path>`. When a local rule says to keep visuals as local files, keep the local file
|
|
46
|
-
and post it too. Tell the person that it is on the board, and give its name and version.
|
|
51
|
+
and post it too. Tell the person that it is on the board, and give its name and version. Make a
|
|
52
|
+
file only when the person asks for one, or for long prose that people read as a document.
|
|
47
53
|
- The person asks you to change a file that is on the topic: pull it with `--edit`, change it, and post
|
|
48
54
|
a new version: `orlan files push <file> <path> --changelog "<what changed>"`.
|
|
49
55
|
- A comment or a request names you: follow the `orlan-review` skill.
|
|
50
56
|
|
|
57
|
+
## Put it in Orlan
|
|
58
|
+
|
|
59
|
+
"Put all of this in Orlan" after an explanation, a plan, a guide or a summary means: build it on the
|
|
60
|
+
board, so that people get it at a glance. An HTML file is a tab that people must open; the board is
|
|
61
|
+
what they see.
|
|
62
|
+
|
|
63
|
+
1. `orlan brief` for the topic, and `orlan board` for a free place (right of or below the items).
|
|
64
|
+
2. Cut the content into 2 to 5 parts. Each part gets one frame, with the part's name as its title, in
|
|
65
|
+
one row from left to right.
|
|
66
|
+
3. The structure (steps, a flow, a decision, parts and their links) is a diagram in its own frame, drawn
|
|
67
|
+
as in "Draw a diagram".
|
|
68
|
+
4. The key points are short notes in the frame of their part: one point in each note, at most 20 words,
|
|
69
|
+
3 to 6 notes in a frame. Make a frame and its notes in one `orlan board edit` step. A frame of
|
|
70
|
+
`40 + 210 * columns` by `80 + 140 * rows`, and each note (190 x 120) at
|
|
71
|
+
`20 + 210 * column`, `60 + 140 * row` from the frame's corner, with `"frame"` set to the frame's id:
|
|
72
|
+
`[{"op":"create","type":"frame","id":"money","x":0,"y":0,"w":460,"h":220,"text":"Money"},`
|
|
73
|
+
`{"op":"create","type":"note","x":20,"y":60,"text":"Keep 6 months of costs in the bank","frame":"money"},`
|
|
74
|
+
`{"op":"create","type":"note","x":230,"y":60,"text":"Pay yourself last","frame":"money"}]`
|
|
75
|
+
5. Read the warnings and fix them. Look at it: `orlan board view --out <file.png>`, open the picture.
|
|
76
|
+
6. End your answer with one line that names the topic and the frames: "I put it on the board of
|
|
77
|
+
"startups", in the frames "Basics", "Money" and "First steps"."
|
|
78
|
+
|
|
79
|
+
Do not post an HTML file or a document for this. Post a file only when the person asks for a page, a
|
|
80
|
+
document, a deck or a mock, or when the content is long prose that people read as a document. Never
|
|
81
|
+
make both a board version and a file, unless the person asks for both.
|
|
82
|
+
|
|
51
83
|
## Draw a diagram
|
|
52
84
|
|
|
53
85
|
A diagram on Orlan is board shapes with words and labeled arrows. Do not post an HTML file or notes as a
|
|
@@ -162,8 +194,13 @@ Run `orlan <command> --help` for the options of a command.
|
|
|
162
194
|
the board. No HTML file, no notes.
|
|
163
195
|
- "explain how a CDN works" - explain it in the chat, draw the parts and their links in a frame as in
|
|
164
196
|
"Draw a diagram", and end with one line: "I drew it on the board of <topic>, in the frame <title>."
|
|
165
|
-
- "put
|
|
166
|
-
|
|
197
|
+
- "put all of this in Orlan", after you explained how to start a company - follow "Put it in Orlan":
|
|
198
|
+
a frame for each part, a diagram of the steps, short notes for the key points, in the topic the brief
|
|
199
|
+
names. No HTML file. End with the topic and the frames.
|
|
200
|
+
- "put the notes on the board" - add them as short notes in a frame, as in "Put it in Orlan", at a free
|
|
201
|
+
place that `orlan board` shows.
|
|
202
|
+
- "make a one-page HTML guide of this for the team" - the person asks for a page: make the file and
|
|
203
|
+
post it with `orlan files add <path>`. No board version.
|
|
167
204
|
- "what is 17*23?" - answer 391. No Orlan call.
|
|
168
205
|
- "fix the typo in ./notes.txt" - fix the local file. No Orlan call.
|
|
169
206
|
|
|
@@ -21,7 +21,7 @@ description: Get a file from Orlan and post a new version of it with a changelog
|
|
|
21
21
|
It ends your claim. When a version landed after the one you pulled, Orlan refuses it with
|
|
22
22
|
`stale_base` and that version's changelog: pull the newest version, make your change on it, push again.
|
|
23
23
|
- `orlan files add <path>` - posts a local file as a new file on your topic and puts it on the board.
|
|
24
|
-
`--topic <topic>` names the topic; the default is the topic
|
|
24
|
+
`--topic <topic>` names the topic; the default is the topic the person has open in Orlan. `--at <x,y>` puts it at
|
|
25
25
|
that point of the board (`orlan board` shows where the items are).
|
|
26
26
|
- `orlan files rollback <file> --version 3 --changelog "<why>"` - posts an older version again, as the
|
|
27
27
|
newest version. It waits for a person to make it current, as a push does.
|