@lambdacurry/arbor 0.22.35 → 0.22.36

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 +99 -6
  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.36",
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",
@@ -6284,14 +6284,17 @@ var profiles = sqliteTable("profiles", {
6284
6284
  permissions: text("permissions", { mode: "json" }).$type().notNull().default([]),
6285
6285
  reputation: text("reputation", { mode: "json" }).$type().notNull().default({}),
6286
6286
  status: text("status").$type().notNull().default("active"),
6287
- betterAuthUserId: text("better_auth_user_id").unique(),
6287
+ betterAuthUserId: text("better_auth_user_id"),
6288
6288
  managedByProfileId: text("managed_by_profile_id"),
6289
6289
  color: text("color").$type(),
6290
6290
  emoji: text("emoji"),
6291
6291
  description: text("description"),
6292
6292
  notificationPrefs: text("notification_prefs", { mode: "json" }).$type(),
6293
6293
  createdAt: ts("created_at").notNull()
6294
- }, (t) => ({ orgIdx: index("profiles_org_idx").on(t.orgId) }));
6294
+ }, (t) => ({
6295
+ orgIdx: index("profiles_org_idx").on(t.orgId),
6296
+ baUserOrgUq: uniqueIndex("profiles_better_auth_user_org_unique").on(t.betterAuthUserId, t.orgId)
6297
+ }));
6295
6298
  var clients = sqliteTable("clients", {
6296
6299
  id: text("id").primaryKey(),
6297
6300
  kind: text("kind").$type().notNull(),
@@ -6360,6 +6363,17 @@ var invitations = sqliteTable("invitations", {
6360
6363
  emailIdx: index("invitations_email_idx").on(t.email, t.status),
6361
6364
  tokenIdx: uniqueIndex("invitations_token_idx").on(t.token)
6362
6365
  }));
6366
+ var humanSessionBindings = sqliteTable("human_session_bindings", {
6367
+ sessionId: text("session_id").primaryKey(),
6368
+ activeProfileId: text("active_profile_id").notNull(),
6369
+ updatedAt: ts("updated_at").notNull()
6370
+ }, (t) => ({ profileIdx: index("human_session_bindings_profile_idx").on(t.activeProfileId) }));
6371
+ var oauthClientBindings = sqliteTable("oauth_client_bindings", {
6372
+ userId: text("user_id").notNull(),
6373
+ clientId: text("client_id").notNull(),
6374
+ profileId: text("profile_id").notNull(),
6375
+ createdAt: ts("created_at").notNull()
6376
+ }, (t) => ({ pk: primaryKey({ columns: [t.userId, t.clientId] }) }));
6363
6377
  var agentPairings = sqliteTable("agent_pairings", {
6364
6378
  id: text("id").primaryKey(),
6365
6379
  orgId: text("org_id").notNull().references(() => orgs.id),
@@ -8637,9 +8651,30 @@ var MCP_OUTPUT_SCHEMAS = {
8637
8651
  profile: profile2,
8638
8652
  client: looseObject({ id, kind: string2() }),
8639
8653
  platform: looseObject({ level: string2() }).optional(),
8654
+ memberships: array(jsonObject).optional(),
8655
+ pendingInvites: array(jsonObject).optional(),
8640
8656
  spaceCharters: array(jsonObject).optional(),
8641
8657
  completeness: jsonObject.optional()
8642
8658
  }),
8659
+ org_switch: looseObject({
8660
+ profile: jsonObject,
8661
+ memberships: array(jsonObject)
8662
+ }),
8663
+ invitation_accept: looseObject({
8664
+ profileId: id,
8665
+ orgId: id,
8666
+ orgName: string2().nullable(),
8667
+ orgRole: string2()
8668
+ }),
8669
+ org_create: looseObject({
8670
+ orgId: id,
8671
+ profileId: id,
8672
+ name: string2()
8673
+ }),
8674
+ org_leave: looseObject({
8675
+ leftProfileId: id,
8676
+ locked: boolean2()
8677
+ }),
8643
8678
  introduce: profileMutation,
8644
8679
  thread_get: looseObject({
8645
8680
  threadId: id.optional(),
@@ -9807,6 +9842,10 @@ var MCP_TOOL_ANNOTATIONS = {
9807
9842
  inbox: readOnly,
9808
9843
  dismiss: destructive,
9809
9844
  whoami: readOnly,
9845
+ org_switch: idempotent,
9846
+ invitation_accept: additive,
9847
+ org_create: additive,
9848
+ org_leave: destructive,
9810
9849
  introduce: additive,
9811
9850
  thread_get: readOnly,
9812
9851
  tree: readOnly,
@@ -11544,7 +11583,7 @@ var ACTION_DEFINITIONS = [
11544
11583
  {
11545
11584
  name: "whoami",
11546
11585
  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.",
11586
+ 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
11587
  inputSchema: {},
11549
11588
  surfaces: ["mcp", "cli"],
11550
11589
  toolset: "loop",
@@ -11872,6 +11911,50 @@ var ACTION_DEFINITIONS = [
11872
11911
  toolset: "admin",
11873
11912
  run: forward("service.register")
11874
11913
  },
11914
+ {
11915
+ name: "org_switch",
11916
+ title: "Switch workspace",
11917
+ description: "Act as your Profile in another org you already belong to (orgId from whoami's memberships). Session-only, not a PAT.",
11918
+ inputSchema: {
11919
+ orgId: string2().min(1).describe("the org to switch this session into")
11920
+ },
11921
+ surfaces: ["mcp", "cli"],
11922
+ toolset: "loop",
11923
+ run: forward("org.switch")
11924
+ },
11925
+ {
11926
+ name: "invitation_accept",
11927
+ title: "Accept an org invitation",
11928
+ description: "Join another org from a pending invitation while already signed in (invitationId from whoami's pendingInvites). Session-only, not a PAT.",
11929
+ inputSchema: {
11930
+ invitationId: string2().min(1).describe("the pending invitation id")
11931
+ },
11932
+ surfaces: ["mcp", "cli"],
11933
+ toolset: "loop",
11934
+ run: forward("invitation.accept")
11935
+ },
11936
+ {
11937
+ name: "org_create",
11938
+ title: "Create a workspace",
11939
+ description: "Create a new org you own (a personal workspace) and switch this session into it. Session-only, not a PAT.",
11940
+ inputSchema: {
11941
+ name: string2().min(1).optional().describe("workspace name; defaults to '{you}'s workspace'")
11942
+ },
11943
+ surfaces: ["mcp", "cli"],
11944
+ toolset: "loop",
11945
+ run: forward("org.create")
11946
+ },
11947
+ {
11948
+ name: "org_leave",
11949
+ title: "Leave a workspace",
11950
+ 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.",
11951
+ inputSchema: {
11952
+ orgId: string2().min(1).optional().describe("org to leave; defaults to the current org")
11953
+ },
11954
+ surfaces: ["cli"],
11955
+ toolset: "loop",
11956
+ run: forward("org.leave")
11957
+ },
11875
11958
  {
11876
11959
  name: "human_invite",
11877
11960
  title: "Invite a human",
@@ -14481,10 +14564,20 @@ async function renderMe(ctx, action) {
14481
14564
  const setCharters = me.spaceCharters ?? [];
14482
14565
  const charterLines = setCharters.length > 0 ? ` space charters:
14483
14566
  ` + setCharters.map((s) => ` • ${s.spaceTitle} — ${clamp(s.charter)}
14567
+ `).join("") : "";
14568
+ const currentOrg = me.memberships?.find((m) => m.current);
14569
+ const otherOrgs = (me.memberships ?? []).filter((m) => !m.current);
14570
+ const orgLine = currentOrg ? ` org ${currentOrg.orgName} (${me.profile.orgId}) · resolved via ${me.client.kind}
14571
+ ` : ` org ${me.profile.orgId} · resolved via ${me.client.kind}
14572
+ `;
14573
+ const switchLines = otherOrgs.length > 0 ? ` other workspaces:
14574
+ ` + otherOrgs.map((m) => ` • ${m.orgName} — \`org_switch --org-id ${m.orgId}\`
14575
+ `).join("") : "";
14576
+ const inviteLines = (me.pendingInvites ?? []).length > 0 ? ` pending invites:
14577
+ ` + (me.pendingInvites ?? []).map((i) => ` • ${i.orgName} — \`invitation_accept --invitation-id ${i.invitationId}\`
14484
14578
  `).join("") : "";
14485
14579
  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\`)
14580
+ ` + orgLine + switchLines + inviteLines + setLines + charterLines + (gaps.length > 0 ? ` to be more legible to your team, set: ${gaps.join("; ")} (\`introduce\`)
14488
14581
  ` : "") + spaceLines;
14489
14582
  emitDual(me, human, action, ctx);
14490
14583
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.22.35",
3
+ "version": "0.22.36",
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",