@lambdacurry/arbor 0.4.24 → 0.4.26
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/arbor.js +65 -32
- package/package.json +1 -1
package/dist/arbor.js
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
+
var __returnValue = (v) => v;
|
|
4
|
+
function __exportSetter(name, newValue) {
|
|
5
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
+
}
|
|
3
7
|
var __export = (target, all) => {
|
|
4
8
|
for (var name in all)
|
|
5
9
|
__defProp(target, name, {
|
|
6
10
|
get: all[name],
|
|
7
11
|
enumerable: true,
|
|
8
12
|
configurable: true,
|
|
9
|
-
set: (
|
|
13
|
+
set: __exportSetter.bind(all, name)
|
|
10
14
|
});
|
|
11
15
|
};
|
|
12
16
|
|
|
@@ -1397,8 +1401,15 @@ var invitations = sqliteTable("invitations", {
|
|
|
1397
1401
|
email: text("email").notNull(),
|
|
1398
1402
|
profileId: text("profile_id").notNull().references(() => profiles.id),
|
|
1399
1403
|
status: text("status").$type().notNull().default("pending"),
|
|
1404
|
+
token: text("token"),
|
|
1405
|
+
expiresAt: ts("expires_at"),
|
|
1406
|
+
invitedByProfileId: text("invited_by_profile_id").references(() => profiles.id),
|
|
1407
|
+
spaceIds: text("space_ids", { mode: "json" }).$type(),
|
|
1400
1408
|
createdAt: ts("created_at").notNull()
|
|
1401
|
-
}, (t) => ({
|
|
1409
|
+
}, (t) => ({
|
|
1410
|
+
emailIdx: index("invitations_email_idx").on(t.email, t.status),
|
|
1411
|
+
tokenIdx: uniqueIndex("invitations_token_idx").on(t.token)
|
|
1412
|
+
}));
|
|
1402
1413
|
var agentPairings = sqliteTable("agent_pairings", {
|
|
1403
1414
|
id: text("id").primaryKey(),
|
|
1404
1415
|
orgId: text("org_id").notNull().references(() => orgs.id),
|
|
@@ -1614,6 +1625,7 @@ var notificationCursors = sqliteTable("notification_cursors", {
|
|
|
1614
1625
|
lastSeenAt: ts("last_seen_at").notNull()
|
|
1615
1626
|
});
|
|
1616
1627
|
// ../core/src/ops/onboarding.ts
|
|
1628
|
+
var INVITE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
1617
1629
|
var EMOJI_RE = new RegExp("^\\p{RGI_Emoji}$", "v");
|
|
1618
1630
|
// ../core/src/ops/agent-pairing.ts
|
|
1619
1631
|
var PAIRING_TTL_MS = 15 * 60 * 1000;
|
|
@@ -13174,7 +13186,7 @@ function finalize(ctx, schema) {
|
|
|
13174
13186
|
result.$schema = "http://json-schema.org/draft-07/schema#";
|
|
13175
13187
|
} else if (ctx.target === "draft-04") {
|
|
13176
13188
|
result.$schema = "http://json-schema.org/draft-04/schema#";
|
|
13177
|
-
} else if (ctx.target === "openapi-3.0") {}
|
|
13189
|
+
} else if (ctx.target === "openapi-3.0") {}
|
|
13178
13190
|
if (ctx.external?.uri) {
|
|
13179
13191
|
const id = ctx.external.registry.get(schema)?.id;
|
|
13180
13192
|
if (!id)
|
|
@@ -13418,7 +13430,7 @@ var literalProcessor = (schema, ctx, json, _params) => {
|
|
|
13418
13430
|
if (val === undefined) {
|
|
13419
13431
|
if (ctx.unrepresentable === "throw") {
|
|
13420
13432
|
throw new Error("Literal `undefined` cannot be represented in JSON Schema");
|
|
13421
|
-
}
|
|
13433
|
+
}
|
|
13422
13434
|
} else if (typeof val === "bigint") {
|
|
13423
13435
|
if (ctx.unrepresentable === "throw") {
|
|
13424
13436
|
throw new Error("BigInt literals cannot be represented in JSON Schema");
|
|
@@ -15989,7 +16001,7 @@ config(en_default());
|
|
|
15989
16001
|
// ../actions/src/index.ts
|
|
15990
16002
|
var ORIENTATION = `Arbor is your team's deliberation room and shared memory — people and agents settle typed work here, and Arbor remembers what's decided. To work well:
|
|
15991
16003
|
|
|
15992
|
-
1. RECALL FIRST. Run \`recall\` before re-deriving or restating anything — it may already be settled; cite prior work ([label](#con_…)) and build on it. Empty recall is itself worth noting. WHY: a room where everyone re-derives is just a chat log.
|
|
16004
|
+
1. RECALL FIRST. Run \`recall\` before re-deriving or restating anything — it may already be settled; cite prior work ([label](#con_…)) and build on it. Phrase the query in PROBLEM-LANGUAGE (a natural-language question — "how do agents handle X"), not extracted keywords; it ranks better. Empty recall is itself worth noting. WHY: a room where everyone re-derives is just a chat log.
|
|
15993
16005
|
2. CONTRIBUTE typed points — ONE point per contribution, with the type that names your move (proposal / critique / question / evidence / risk / correction / assertion / decision). Markdown welcome; put references IN your prose (a URL or [label](#con_…) becomes a navigable reference — there's no separate links field). WHY: one typed point is reviewable on its own.
|
|
15994
16006
|
3. ANSWER through asks. When \`inbox\` or a thread shows an open request you can meet, answer THROUGH it — \`respond\` to it, or \`stamp\` the contribution a review-ask is about — so it completes and the requester is notified. WHY: a plain reply that merely happens to answer leaves their ask hanging (the most common failure).
|
|
15995
16007
|
4. REVIEW honestly; promote the standout, sparingly. \`stamp\` to vouch or push back with a one-line why (you can't stamp your own work — ask via \`request\`). PROMOTE a contribution/artifact only when it's the standout the org should find FIRST (the \uD83C\uDF96️). WHY: promotion is curation, not applause — and it's about an OUTPUT, never a whole thread (a thread RESOLVES; it is never "promoted").
|
|
@@ -16331,11 +16343,11 @@ var ACTIONS = [
|
|
|
16331
16343
|
{
|
|
16332
16344
|
name: "tree",
|
|
16333
16345
|
title: "Navigate the workspace tree",
|
|
16334
|
-
description: "Map the workspace
|
|
16346
|
+
description: "Map the workspace — a GLANCEABLE structure map, not a full dump. By default (depth `topics`) you get your accessible spaces (purpose, governance stage) → their topics, plus a LIGHT roster (who's in each space by name/kind/role). Go DEEPER with the targeted reads, not by inflating the tree: `space_get` for a space's full roster + capabilities + charters, `topic_get` for a topic's threads, `thread_get` for a thread's contributions. Depths: `spaces` (just the spaces — lightest), `topics` (default — spaces + topics + light roster), `threads` (also expands each topic's threads with contribution counts). Scope with space or topic to map just that subtree.",
|
|
16335
16347
|
inputSchema: {
|
|
16336
16348
|
space: exports_external.string().optional().describe("scope to one space id (spc_…)"),
|
|
16337
16349
|
topic: exports_external.string().optional().describe("scope to one topic id (top_…)"),
|
|
16338
|
-
depth: exports_external.enum(["topics", "threads"]).optional().describe("how deep to expand: topics | threads (
|
|
16350
|
+
depth: exports_external.enum(["spaces", "topics", "threads"]).optional().describe("how deep to expand: spaces (just spaces) | topics (default: + topics + light roster) | threads (+ each topic's threads). For one topic's threads or one thread's contributions, prefer topic_get / thread_get.")
|
|
16339
16351
|
},
|
|
16340
16352
|
surfaces: ["mcp", "cli"],
|
|
16341
16353
|
run: forward("navigation.tree")
|
|
@@ -16725,24 +16737,29 @@ var httpExecutor = {
|
|
|
16725
16737
|
|
|
16726
16738
|
// src/output.ts
|
|
16727
16739
|
import { randomUUID } from "node:crypto";
|
|
16740
|
+
function lastValue(value) {
|
|
16741
|
+
return Array.isArray(value) ? value[value.length - 1] : value;
|
|
16742
|
+
}
|
|
16728
16743
|
var GLOBAL_BOOLEAN_FLAGS = new Set(["json", "quiet", "no-quiet", "version", "help"]);
|
|
16729
16744
|
var RESERVED_FLAGS = new Set([...GLOBAL_BOOLEAN_FLAGS, "url", "fields"]);
|
|
16730
16745
|
var TRUTHY = new Set(["true", "1", "yes", "on"]);
|
|
16731
16746
|
function truthyFlag(value) {
|
|
16732
|
-
|
|
16747
|
+
const v = lastValue(value);
|
|
16748
|
+
return v === true || typeof v === "string" && TRUTHY.has(v.toLowerCase());
|
|
16733
16749
|
}
|
|
16734
16750
|
function stringFlag(value, name) {
|
|
16735
|
-
|
|
16751
|
+
const v = lastValue(value);
|
|
16752
|
+
if (v === undefined)
|
|
16736
16753
|
return;
|
|
16737
|
-
if (
|
|
16754
|
+
if (v === true)
|
|
16738
16755
|
throw new UsageError(`--${name} expects a value`);
|
|
16739
|
-
return String(
|
|
16756
|
+
return String(v);
|
|
16740
16757
|
}
|
|
16741
16758
|
function resolveOutput(flags, opts) {
|
|
16742
16759
|
const json2 = truthyFlag(flags.json);
|
|
16743
16760
|
const isTTY = opts?.isTTY ?? Boolean(process.stdout.isTTY);
|
|
16744
16761
|
const quiet = truthyFlag(flags["no-quiet"]) ? false : truthyFlag(flags.quiet) || json2 || !isTTY;
|
|
16745
|
-
const fieldsRaw = flags.fields;
|
|
16762
|
+
const fieldsRaw = lastValue(flags.fields);
|
|
16746
16763
|
const fields = typeof fieldsRaw === "string" && fieldsRaw.trim() ? fieldsRaw.split(",").map((f) => f.trim()).filter(Boolean) : undefined;
|
|
16747
16764
|
return { json: json2, quiet, fields };
|
|
16748
16765
|
}
|
|
@@ -16875,7 +16892,7 @@ function buildInput(inputSchema, flags) {
|
|
|
16875
16892
|
const input = {};
|
|
16876
16893
|
for (const spec of flagsForSchema(inputSchema)) {
|
|
16877
16894
|
if (spec.kind === "string") {
|
|
16878
|
-
const fileSrc = flags[`${spec.flag}-file`];
|
|
16895
|
+
const fileSrc = lastValue(flags[`${spec.flag}-file`]);
|
|
16879
16896
|
if (fileSrc !== undefined) {
|
|
16880
16897
|
if (flags[spec.flag] !== undefined) {
|
|
16881
16898
|
throw new UsageError(`pass either --${spec.flag} or --${spec.flag}-file, not both`);
|
|
@@ -16897,33 +16914,41 @@ function buildInput(inputSchema, flags) {
|
|
|
16897
16914
|
}
|
|
16898
16915
|
switch (spec.kind) {
|
|
16899
16916
|
case "number": {
|
|
16900
|
-
const n = Number(raw);
|
|
16917
|
+
const n = Number(lastValue(raw));
|
|
16901
16918
|
if (Number.isNaN(n))
|
|
16902
|
-
throw new UsageError(`--${spec.flag} expects a number, got: ${String(raw)}`);
|
|
16919
|
+
throw new UsageError(`--${spec.flag} expects a number, got: ${String(lastValue(raw))}`);
|
|
16903
16920
|
input[spec.field] = n;
|
|
16904
16921
|
break;
|
|
16905
16922
|
}
|
|
16906
16923
|
case "array": {
|
|
16907
|
-
const
|
|
16908
|
-
|
|
16909
|
-
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16924
|
+
const tokens = Array.isArray(raw) ? raw : [String(raw)];
|
|
16925
|
+
const out = [];
|
|
16926
|
+
for (const token of tokens) {
|
|
16927
|
+
const text3 = String(token).trim();
|
|
16928
|
+
if (text3.startsWith("[")) {
|
|
16929
|
+
try {
|
|
16930
|
+
const parsed = JSON.parse(text3);
|
|
16931
|
+
if (Array.isArray(parsed)) {
|
|
16932
|
+
out.push(...parsed);
|
|
16933
|
+
continue;
|
|
16934
|
+
}
|
|
16935
|
+
} catch {
|
|
16936
|
+
throw new UsageError(`--${spec.flag} looks like JSON but failed to parse — check the quoting`);
|
|
16914
16937
|
}
|
|
16915
|
-
} catch {
|
|
16916
|
-
throw new UsageError(`--${spec.flag} looks like JSON but failed to parse — check the quoting`);
|
|
16917
16938
|
}
|
|
16939
|
+
for (const part of text3.split(",").map((s) => s.trim()).filter(Boolean))
|
|
16940
|
+
out.push(part);
|
|
16918
16941
|
}
|
|
16919
|
-
input[spec.field] =
|
|
16942
|
+
input[spec.field] = out;
|
|
16920
16943
|
break;
|
|
16921
16944
|
}
|
|
16922
|
-
case "boolean":
|
|
16923
|
-
|
|
16945
|
+
case "boolean": {
|
|
16946
|
+
const v = lastValue(raw);
|
|
16947
|
+
input[spec.field] = v === true ? true : v !== "false";
|
|
16924
16948
|
break;
|
|
16949
|
+
}
|
|
16925
16950
|
default:
|
|
16926
|
-
input[spec.field] = String(raw);
|
|
16951
|
+
input[spec.field] = String(lastValue(raw));
|
|
16927
16952
|
}
|
|
16928
16953
|
}
|
|
16929
16954
|
return input;
|
|
@@ -17085,6 +17110,14 @@ async function login(opts) {
|
|
|
17085
17110
|
}
|
|
17086
17111
|
|
|
17087
17112
|
// src/index.ts
|
|
17113
|
+
function setFlag(flags, key, value) {
|
|
17114
|
+
const prev = flags[key];
|
|
17115
|
+
if (prev === undefined || typeof value === "boolean" || typeof prev === "boolean") {
|
|
17116
|
+
flags[key] = value;
|
|
17117
|
+
return;
|
|
17118
|
+
}
|
|
17119
|
+
flags[key] = Array.isArray(prev) ? [...prev, value] : [prev, value];
|
|
17120
|
+
}
|
|
17088
17121
|
function parseArgs(argv) {
|
|
17089
17122
|
const positionals = [];
|
|
17090
17123
|
const flags = {};
|
|
@@ -17094,11 +17127,11 @@ function parseArgs(argv) {
|
|
|
17094
17127
|
const body = arg.slice(2);
|
|
17095
17128
|
const eq = body.indexOf("=");
|
|
17096
17129
|
if (eq !== -1) {
|
|
17097
|
-
flags
|
|
17130
|
+
setFlag(flags, body.slice(0, eq), body.slice(eq + 1));
|
|
17098
17131
|
} else if (!GLOBAL_BOOLEAN_FLAGS.has(body) && i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
|
|
17099
|
-
flags
|
|
17132
|
+
setFlag(flags, body, argv[++i]);
|
|
17100
17133
|
} else {
|
|
17101
|
-
flags
|
|
17134
|
+
setFlag(flags, body, true);
|
|
17102
17135
|
}
|
|
17103
17136
|
} else {
|
|
17104
17137
|
positionals.push(arg);
|
|
@@ -17128,7 +17161,7 @@ async function renderMe(ctx, action) {
|
|
|
17128
17161
|
` : "") + spaceLines;
|
|
17129
17162
|
emitDual(me, human, action, ctx);
|
|
17130
17163
|
}
|
|
17131
|
-
var CLI_NOTE = `On this CLI, before your first write:
|
|
17164
|
+
var CLI_NOTE = `On this CLI, before your first write: commands are NOUN-VERB (\`thread get\`, \`space get\`, not \`get thread\`). Flag names are kebab-derived from the inputs (\`--thread-id\`, \`--request-id\`, \`--contribution-id\` — not \`--thread\`/\`--request\`), so check \`arbor help\` or \`arbor <command> --help\` for a command's exact flags instead of guessing. Pass long/markdown bodies via \`--body-file -\` (stdin), never shell-quoted; a one-line \`--summary\` (≤300 chars) on a long contribution becomes its recall snippet. List inputs (e.g. \`--capabilities\`) accept EITHER a comma list (\`--capabilities a,b,c\`) OR a repeated flag (\`--capabilities a --capabilities b\`) — both build the array. \`tree\` is a glanceable map (default depth \`topics\`); drill down with \`space get\`/\`topic get\`/\`thread get\` rather than expanding the whole tree. If \`inbox\` is empty, that's "nothing needs you" — but if you're unsure your auth resolved, \`whoami\` confirms it.`;
|
|
17132
17165
|
function renderOrient(ctx) {
|
|
17133
17166
|
emitDual({ orientation: ORIENTATION, cliNote: CLI_NOTE }, `${ORIENTATION}
|
|
17134
17167
|
|
package/package.json
CHANGED