@lambdacurry/arbor 0.22.35 → 0.22.37

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.
Files changed (2) hide show
  1. package/dist/arbor.js +137 -8
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // package.json
3
3
  var package_default = {
4
4
  name: "@lambdacurry/arbor",
5
- version: "0.22.35",
5
+ version: "0.22.37",
6
6
  description: "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
7
7
  keywords: [
8
8
  "agents",
@@ -4933,6 +4933,41 @@ var CONTRIBUTION_TYPES = [
4933
4933
  "decision"
4934
4934
  ];
4935
4935
  var STAMP_FACETS = ["quality", "impact", "fit", "originality"];
4936
+ var ARTIFACT_TYPES = [
4937
+ "markdown",
4938
+ "concept",
4939
+ "decision",
4940
+ "research-brief",
4941
+ "summary",
4942
+ "plan",
4943
+ "json",
4944
+ "yaml",
4945
+ "schema",
4946
+ "table",
4947
+ "rubric",
4948
+ "profile-snapshot",
4949
+ "image",
4950
+ "diagram",
4951
+ "mockup",
4952
+ "canvas",
4953
+ "html-bundle",
4954
+ "dashboard",
4955
+ "prototype",
4956
+ "audio",
4957
+ "video",
4958
+ "transcript",
4959
+ "diff",
4960
+ "pr-reference",
4961
+ "script",
4962
+ "api-spec",
4963
+ "test-plan",
4964
+ "prompt",
4965
+ "tool-spec",
4966
+ "workflow",
4967
+ "routing-rule",
4968
+ "eval-rubric",
4969
+ "external-reference"
4970
+ ];
4936
4971
  // ../core/src/feedback/constants.ts
4937
4972
  var ARBOR_FEEDBACK_TYPES = [
4938
4973
  "comment",
@@ -6284,14 +6319,17 @@ var profiles = sqliteTable("profiles", {
6284
6319
  permissions: text("permissions", { mode: "json" }).$type().notNull().default([]),
6285
6320
  reputation: text("reputation", { mode: "json" }).$type().notNull().default({}),
6286
6321
  status: text("status").$type().notNull().default("active"),
6287
- betterAuthUserId: text("better_auth_user_id").unique(),
6322
+ betterAuthUserId: text("better_auth_user_id"),
6288
6323
  managedByProfileId: text("managed_by_profile_id"),
6289
6324
  color: text("color").$type(),
6290
6325
  emoji: text("emoji"),
6291
6326
  description: text("description"),
6292
6327
  notificationPrefs: text("notification_prefs", { mode: "json" }).$type(),
6293
6328
  createdAt: ts("created_at").notNull()
6294
- }, (t) => ({ orgIdx: index("profiles_org_idx").on(t.orgId) }));
6329
+ }, (t) => ({
6330
+ orgIdx: index("profiles_org_idx").on(t.orgId),
6331
+ baUserOrgUq: uniqueIndex("profiles_better_auth_user_org_unique").on(t.betterAuthUserId, t.orgId)
6332
+ }));
6295
6333
  var clients = sqliteTable("clients", {
6296
6334
  id: text("id").primaryKey(),
6297
6335
  kind: text("kind").$type().notNull(),
@@ -6360,6 +6398,17 @@ var invitations = sqliteTable("invitations", {
6360
6398
  emailIdx: index("invitations_email_idx").on(t.email, t.status),
6361
6399
  tokenIdx: uniqueIndex("invitations_token_idx").on(t.token)
6362
6400
  }));
6401
+ var humanSessionBindings = sqliteTable("human_session_bindings", {
6402
+ sessionId: text("session_id").primaryKey(),
6403
+ activeProfileId: text("active_profile_id").notNull(),
6404
+ updatedAt: ts("updated_at").notNull()
6405
+ }, (t) => ({ profileIdx: index("human_session_bindings_profile_idx").on(t.activeProfileId) }));
6406
+ var oauthClientBindings = sqliteTable("oauth_client_bindings", {
6407
+ userId: text("user_id").notNull(),
6408
+ clientId: text("client_id").notNull(),
6409
+ profileId: text("profile_id").notNull(),
6410
+ createdAt: ts("created_at").notNull()
6411
+ }, (t) => ({ pk: primaryKey({ columns: [t.userId, t.clientId] }) }));
6363
6412
  var agentPairings = sqliteTable("agent_pairings", {
6364
6413
  id: text("id").primaryKey(),
6365
6414
  orgId: text("org_id").notNull().references(() => orgs.id),
@@ -8637,9 +8686,30 @@ var MCP_OUTPUT_SCHEMAS = {
8637
8686
  profile: profile2,
8638
8687
  client: looseObject({ id, kind: string2() }),
8639
8688
  platform: looseObject({ level: string2() }).optional(),
8689
+ memberships: array(jsonObject).optional(),
8690
+ pendingInvites: array(jsonObject).optional(),
8640
8691
  spaceCharters: array(jsonObject).optional(),
8641
8692
  completeness: jsonObject.optional()
8642
8693
  }),
8694
+ org_switch: looseObject({
8695
+ profile: jsonObject,
8696
+ memberships: array(jsonObject)
8697
+ }),
8698
+ invitation_accept: looseObject({
8699
+ profileId: id,
8700
+ orgId: id,
8701
+ orgName: string2().nullable(),
8702
+ orgRole: string2()
8703
+ }),
8704
+ org_create: looseObject({
8705
+ orgId: id,
8706
+ profileId: id,
8707
+ name: string2()
8708
+ }),
8709
+ org_leave: looseObject({
8710
+ leftProfileId: id,
8711
+ locked: boolean2()
8712
+ }),
8643
8713
  introduce: profileMutation,
8644
8714
  thread_get: looseObject({
8645
8715
  threadId: id.optional(),
@@ -9807,6 +9877,10 @@ var MCP_TOOL_ANNOTATIONS = {
9807
9877
  inbox: readOnly,
9808
9878
  dismiss: destructive,
9809
9879
  whoami: readOnly,
9880
+ org_switch: idempotent,
9881
+ invitation_accept: additive,
9882
+ org_create: additive,
9883
+ org_leave: destructive,
9810
9884
  introduce: additive,
9811
9885
  thread_get: readOnly,
9812
9886
  tree: readOnly,
@@ -10123,6 +10197,7 @@ var TLDRAW_EXEC_OPERATIONS_SCHEMA = array(TLDRAW_EXEC_OPERATION_SCHEMA).min(1).m
10123
10197
  });
10124
10198
  }).describe("preferred declarative edits, applied in order; mutually exclusive with code");
10125
10199
  // ../actions/src/index.ts
10200
+ var ARTIFACT_TYPE_DESCRIPTION = `semantic type (one of: ${ARTIFACT_TYPES.join(", ")})`;
10126
10201
  var ARBOR_FEEDBACK_INPUT_TYPES = [...ARBOR_FEEDBACK_TYPES, "friction"];
10127
10202
  var CONTRIBUTION_ADD_LINK_RELS = [
10128
10203
  "cites",
@@ -11279,7 +11354,7 @@ var ACTION_DEFINITIONS = [
11279
11354
  title: "Create an artifact",
11280
11355
  description: "Promote durable output — a decision, summary, plan, or research brief — into a first-class artifact you own. Give it a concise summary of what the Artifact is or accomplishes; this is the skim and retrieval description, not a repeat of its title. Text kinds (doc/table/diagram/html) are living documents: pass `source` (born at v1, editable in place via edit_artifact); kind=file passes a contentRef instead. The artifact is AUTOMATICALLY listed on its source thread (no link post needed). When it came from a Thread Computer, pass its producing computerSessionId when available so the artifact cites the reproducible session. Reach for this when a thread has produced something worth retaining and citing beyond the conversation — especially a table or doc the team will UPDATE, which beats pasting it into a prose contribution.",
11281
11356
  inputSchema: {
11282
- type: string2().describe("semantic type, e.g. decision|summary|plan|markdown|table|research-brief"),
11357
+ type: _enum(ARTIFACT_TYPES).describe(ARTIFACT_TYPE_DESCRIPTION),
11283
11358
  kind: _enum(["doc", "table", "diagram", "html", "file"]).optional().describe("structural kind (default file). doc/table/diagram/html are editable, versioned text"),
11284
11359
  title: string2().min(1),
11285
11360
  source: string2().optional().describe("text kinds: the initial content (v1)"),
@@ -11544,7 +11619,7 @@ var ACTION_DEFINITIONS = [
11544
11619
  {
11545
11620
  name: "whoami",
11546
11621
  title: "Who am I",
11547
- description: "Return your own Arbor identity (profile + source client) as resolved from your credential. Reach for this to confirm which profile and org you're acting as before you write.",
11622
+ description: "Return your Arbor identity as resolved from your credential: which profile and org you're acting as, and which other orgs you can switch to on a human session.",
11548
11623
  inputSchema: {},
11549
11624
  surfaces: ["mcp", "cli"],
11550
11625
  toolset: "loop",
@@ -11872,6 +11947,50 @@ var ACTION_DEFINITIONS = [
11872
11947
  toolset: "admin",
11873
11948
  run: forward("service.register")
11874
11949
  },
11950
+ {
11951
+ name: "org_switch",
11952
+ title: "Switch workspace",
11953
+ description: "Act as your Profile in another org you already belong to (orgId from whoami's memberships). Session-only, not a PAT.",
11954
+ inputSchema: {
11955
+ orgId: string2().min(1).describe("the org to switch this session into")
11956
+ },
11957
+ surfaces: ["mcp", "cli"],
11958
+ toolset: "loop",
11959
+ run: forward("org.switch")
11960
+ },
11961
+ {
11962
+ name: "invitation_accept",
11963
+ title: "Accept an org invitation",
11964
+ description: "Join another org from a pending invitation while already signed in (invitationId from whoami's pendingInvites). Session-only, not a PAT.",
11965
+ inputSchema: {
11966
+ invitationId: string2().min(1).describe("the pending invitation id")
11967
+ },
11968
+ surfaces: ["mcp", "cli"],
11969
+ toolset: "loop",
11970
+ run: forward("invitation.accept")
11971
+ },
11972
+ {
11973
+ name: "org_create",
11974
+ title: "Create a workspace",
11975
+ description: "Create a new org you own (a personal workspace) and switch this session into it. Session-only, not a PAT.",
11976
+ inputSchema: {
11977
+ name: string2().min(1).optional().describe("workspace name; defaults to '{you}'s workspace'")
11978
+ },
11979
+ surfaces: ["mcp", "cli"],
11980
+ toolset: "loop",
11981
+ run: forward("org.create")
11982
+ },
11983
+ {
11984
+ name: "org_leave",
11985
+ title: "Leave a workspace",
11986
+ description: "Leave an org you belong to, disabling that Profile — keep at least one workspace, and appoint another owner before leaving a multi-person org. Session-only, not a PAT.",
11987
+ inputSchema: {
11988
+ orgId: string2().min(1).optional().describe("org to leave; defaults to the current org")
11989
+ },
11990
+ surfaces: ["cli"],
11991
+ toolset: "loop",
11992
+ run: forward("org.leave")
11993
+ },
11875
11994
  {
11876
11995
  name: "human_invite",
11877
11996
  title: "Invite a human",
@@ -12188,7 +12307,7 @@ var ACTION_DEFINITIONS = [
12188
12307
  verb: _enum(["create", "edit", "set_live_preview", "set_snapshot", "promote_attachment"]).describe("which artifact move"),
12189
12308
  title: string2().optional().describe("create: the artifact's title"),
12190
12309
  kind: _enum(["doc", "table", "diagram", "html", "file"]).optional().describe("create: structural kind (default file). doc/table/diagram/html are editable text"),
12191
- type: string2().optional().describe("create: semantic type, e.g. decision|summary|plan|markdown|table|research-brief"),
12310
+ type: _enum(ARTIFACT_TYPES).optional().describe(`create: ${ARTIFACT_TYPE_DESCRIPTION}`),
12192
12311
  source: string2().optional().describe("create (text kinds): the initial content · edit verb=replace: the full new content"),
12193
12312
  contentRef: string2().optional().describe("create (kind=file): where the content lives, e.g. inline://… or a URL"),
12194
12313
  editPolicy: _enum(["owner", "members", "anyone"]).optional().describe("create: who may edit (default members)"),
@@ -14481,10 +14600,20 @@ async function renderMe(ctx, action) {
14481
14600
  const setCharters = me.spaceCharters ?? [];
14482
14601
  const charterLines = setCharters.length > 0 ? ` space charters:
14483
14602
  ` + setCharters.map((s) => ` • ${s.spaceTitle} — ${clamp(s.charter)}
14603
+ `).join("") : "";
14604
+ const currentOrg = me.memberships?.find((m) => m.current);
14605
+ const otherOrgs = (me.memberships ?? []).filter((m) => !m.current);
14606
+ const orgLine = currentOrg ? ` org ${currentOrg.orgName} (${me.profile.orgId}) · resolved via ${me.client.kind}
14607
+ ` : ` org ${me.profile.orgId} · resolved via ${me.client.kind}
14608
+ `;
14609
+ const switchLines = otherOrgs.length > 0 ? ` other workspaces:
14610
+ ` + otherOrgs.map((m) => ` • ${m.orgName} — \`org_switch --org-id ${m.orgId}\`
14611
+ `).join("") : "";
14612
+ const inviteLines = (me.pendingInvites ?? []).length > 0 ? ` pending invites:
14613
+ ` + (me.pendingInvites ?? []).map((i) => ` • ${i.orgName} — \`invitation_accept --invitation-id ${i.invitationId}\`
14484
14614
  `).join("") : "";
14485
14615
  const human = `${me.profile.displayName} · ${me.profile.kind} · org-role ${me.profile.orgRole}
14486
- ` + ` org ${me.profile.orgId} · resolved via ${me.client.kind}
14487
- ` + setLines + charterLines + (gaps.length > 0 ? ` to be more legible to your team, set: ${gaps.join("; ")} (\`introduce\`)
14616
+ ` + orgLine + switchLines + inviteLines + setLines + charterLines + (gaps.length > 0 ? ` to be more legible to your team, set: ${gaps.join("; ")} (\`introduce\`)
14488
14617
  ` : "") + spaceLines;
14489
14618
  emitDual(me, human, action, ctx);
14490
14619
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.22.35",
3
+ "version": "0.22.37",
4
4
  "description": "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
5
5
  "keywords": [
6
6
  "agents",