@agent-team-foundation/first-tree-hub 0.6.1 → 0.6.3
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/{bootstrap-Dq_k_6ZD.mjs → bootstrap-DNL1cEwv.mjs} +54 -156
- package/dist/cli/index.mjs +400 -207
- package/dist/{core-Dt3yNBTm.mjs → core-B10jgThe.mjs} +4610 -3804
- package/dist/drizzle/0019_agent_configs.sql +30 -0
- package/dist/drizzle/0020_unified_user_token.sql +154 -0
- package/dist/drizzle/0021_drop_agents_profile.sql +10 -0
- package/dist/drizzle/meta/_journal.json +21 -0
- package/dist/feishu-BoMJHlOv.mjs +832 -0
- package/dist/index.mjs +4 -4
- package/dist/web/assets/index-CTl4pHIL.css +1 -0
- package/dist/web/assets/index-CnLpaSBg.js +308 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/feishu-Y4m2zFc3.mjs +0 -51
- package/dist/web/assets/index--kyp_ZHv.css +0 -1
- package/dist/web/assets/index-D7-5shxZ.js +0 -310
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-- M1 agent configuration: Hub-managed runtime config table.
|
|
2
|
+
-- Creates `agent_configs` and back-fills one row per non-deleted agent so
|
|
3
|
+
-- Step 6 can flip Claude Code handler over to read prompt from config without
|
|
4
|
+
-- silently dropping the existing `agents.profile` text.
|
|
5
|
+
|
|
6
|
+
CREATE TABLE IF NOT EXISTS "agent_configs" (
|
|
7
|
+
"agent_id" text PRIMARY KEY NOT NULL,
|
|
8
|
+
"version" integer NOT NULL DEFAULT 1,
|
|
9
|
+
"payload" jsonb NOT NULL,
|
|
10
|
+
"updated_by" text NOT NULL,
|
|
11
|
+
"updated_at" timestamp with time zone NOT NULL DEFAULT now()
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
--> statement-breakpoint
|
|
15
|
+
INSERT INTO "agent_configs" ("agent_id", "version", "payload", "updated_by", "updated_at")
|
|
16
|
+
SELECT
|
|
17
|
+
"uuid",
|
|
18
|
+
1,
|
|
19
|
+
jsonb_build_object(
|
|
20
|
+
'prompt', jsonb_build_object('append', COALESCE("profile", '')),
|
|
21
|
+
'model', '',
|
|
22
|
+
'mcpServers', '[]'::jsonb,
|
|
23
|
+
'env', '[]'::jsonb,
|
|
24
|
+
'gitRepos', '[]'::jsonb
|
|
25
|
+
),
|
|
26
|
+
'system',
|
|
27
|
+
now()
|
|
28
|
+
FROM "agents"
|
|
29
|
+
WHERE "status" != 'deleted'
|
|
30
|
+
ON CONFLICT ("agent_id") DO NOTHING;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
-- Unified user token milestone — retire agent tokens, authenticate every
|
|
2
|
+
-- caller as a user.
|
|
3
|
+
--
|
|
4
|
+
-- This migration collapses the two-track auth (member JWT + `aghub_*` agent
|
|
5
|
+
-- token) into a single member-JWT credential. Three structural changes:
|
|
6
|
+
-- 1. Drop `agent_tokens` (table + FK cascade).
|
|
7
|
+
-- 2. Add `clients.user_id` (nullable) — owning user of the physical client.
|
|
8
|
+
-- 3. Add `agents.client_id` (nullable FK) — pin an agent to the client that
|
|
9
|
+
-- runs it. `client_id` is backfilled from `agent_presence`. Rows that
|
|
10
|
+
-- cannot be backfilled stay NULL and bind on first WS connect (see
|
|
11
|
+
-- `api/agent/ws-client.ts` first-bind path). Originally this migration
|
|
12
|
+
-- raised an exception when any non-human agent was unbacked — that
|
|
13
|
+
-- gated startup on a data state the operator usually can't fix until
|
|
14
|
+
-- the server is up. Relaxed to NOTICE so the loop is broken; runtime
|
|
15
|
+
-- enforcement (Rule R-RUN in `services/agent.ts` + `agent-selector.ts`)
|
|
16
|
+
-- still rejects unclaimed agents on the request path.
|
|
17
|
+
-- 4. Make `agents.manager_id` NOT NULL after backfilling the first admin
|
|
18
|
+
-- member of each org onto the unmanaged rows.
|
|
19
|
+
--
|
|
20
|
+
-- There is no compatibility layer: operators stop SDK/CLI processes, run
|
|
21
|
+
-- `db:migrate`, then re-login via `first-tree-hub connect`. See the proposal
|
|
22
|
+
-- "unified-user-token.20260417" for the full upgrade runbook.
|
|
23
|
+
--
|
|
24
|
+
-- NOTE: Do NOT wrap this file in BEGIN;/COMMIT;. The Drizzle migrator already
|
|
25
|
+
-- runs every pending migration inside a single outer transaction, so a nested
|
|
26
|
+
-- BEGIN raises WARNING 25001 and the inner COMMIT prematurely closes the
|
|
27
|
+
-- outer transaction — which prevents the migration hash from being recorded
|
|
28
|
+
-- and causes the server to loop through the same failure on every restart.
|
|
29
|
+
|
|
30
|
+
DROP TABLE IF EXISTS "agent_tokens";
|
|
31
|
+
--> statement-breakpoint
|
|
32
|
+
|
|
33
|
+
-- ---------------------------------------------------------------------------
|
|
34
|
+
-- clients.user_id — nullable FK to users(id).
|
|
35
|
+
-- Nullable so legacy rows (created before handshake auth) keep existing;
|
|
36
|
+
-- the WS handshake claims them on first re-register under a JWT.
|
|
37
|
+
-- ---------------------------------------------------------------------------
|
|
38
|
+
ALTER TABLE "clients"
|
|
39
|
+
ADD COLUMN IF NOT EXISTS "user_id" text REFERENCES "users"("id") ON DELETE SET NULL;
|
|
40
|
+
--> statement-breakpoint
|
|
41
|
+
|
|
42
|
+
CREATE INDEX IF NOT EXISTS "idx_clients_user" ON "clients" ("user_id");
|
|
43
|
+
--> statement-breakpoint
|
|
44
|
+
|
|
45
|
+
-- ---------------------------------------------------------------------------
|
|
46
|
+
-- agents.client_id — pin an agent to the physical client that runs it.
|
|
47
|
+
-- ---------------------------------------------------------------------------
|
|
48
|
+
ALTER TABLE "agents"
|
|
49
|
+
ADD COLUMN IF NOT EXISTS "client_id" text REFERENCES "clients"("id") ON DELETE RESTRICT;
|
|
50
|
+
--> statement-breakpoint
|
|
51
|
+
|
|
52
|
+
-- Copy last-bound client from agent_presence.
|
|
53
|
+
UPDATE "agents" a
|
|
54
|
+
SET "client_id" = ap."client_id"
|
|
55
|
+
FROM "agent_presence" ap
|
|
56
|
+
WHERE ap."agent_id" = a."uuid"
|
|
57
|
+
AND ap."client_id" IS NOT NULL
|
|
58
|
+
AND a."client_id" IS NULL;
|
|
59
|
+
--> statement-breakpoint
|
|
60
|
+
|
|
61
|
+
-- Surface (do not block) any non-deleted non-human agent still missing a
|
|
62
|
+
-- client_id after the backfill. They will sit in an "unclaimed" state until
|
|
63
|
+
-- a client connects via WS and the first-bind path in
|
|
64
|
+
-- `api/agent/ws-client.ts` claims them. Runtime guards reject HTTP / WS
|
|
65
|
+
-- requests for those agents in the meantime.
|
|
66
|
+
DO $$
|
|
67
|
+
DECLARE
|
|
68
|
+
unpinned_count integer;
|
|
69
|
+
BEGIN
|
|
70
|
+
SELECT COUNT(*) INTO unpinned_count
|
|
71
|
+
FROM "agents"
|
|
72
|
+
WHERE "client_id" IS NULL
|
|
73
|
+
AND "type" <> 'human'
|
|
74
|
+
AND "status" <> 'deleted';
|
|
75
|
+
|
|
76
|
+
IF unpinned_count > 0 THEN
|
|
77
|
+
RAISE NOTICE
|
|
78
|
+
'unified-user-token migration: % non-human agents have no client_id after backfill; '
|
|
79
|
+
'they will be claimed on first WS bind (see ws-client.ts first-bind path)',
|
|
80
|
+
unpinned_count;
|
|
81
|
+
END IF;
|
|
82
|
+
END $$;
|
|
83
|
+
--> statement-breakpoint
|
|
84
|
+
|
|
85
|
+
CREATE INDEX IF NOT EXISTS "idx_agents_client" ON "agents" ("client_id");
|
|
86
|
+
--> statement-breakpoint
|
|
87
|
+
|
|
88
|
+
-- ---------------------------------------------------------------------------
|
|
89
|
+
-- agents.manager_id — backfill then enforce NOT NULL.
|
|
90
|
+
-- Human agents own their members row, so self-assign via members.
|
|
91
|
+
-- Non-human agents get the first admin member in their org.
|
|
92
|
+
-- ---------------------------------------------------------------------------
|
|
93
|
+
|
|
94
|
+
-- Human agents: self-assign to their own member row.
|
|
95
|
+
UPDATE "agents" a
|
|
96
|
+
SET "manager_id" = m."id"
|
|
97
|
+
FROM "members" m
|
|
98
|
+
WHERE m."agent_id" = a."uuid"
|
|
99
|
+
AND a."manager_id" IS NULL
|
|
100
|
+
AND a."type" = 'human';
|
|
101
|
+
--> statement-breakpoint
|
|
102
|
+
|
|
103
|
+
-- Non-human agents: first admin in org, ordered by created_at asc.
|
|
104
|
+
UPDATE "agents" a
|
|
105
|
+
SET "manager_id" = m."id"
|
|
106
|
+
FROM (
|
|
107
|
+
SELECT DISTINCT ON (m."organization_id")
|
|
108
|
+
m."id" AS id,
|
|
109
|
+
m."organization_id" AS organization_id
|
|
110
|
+
FROM "members" m
|
|
111
|
+
WHERE m."role" = 'admin'
|
|
112
|
+
ORDER BY m."organization_id", m."created_at" ASC
|
|
113
|
+
) m
|
|
114
|
+
WHERE a."organization_id" = m."organization_id"
|
|
115
|
+
AND a."manager_id" IS NULL;
|
|
116
|
+
--> statement-breakpoint
|
|
117
|
+
|
|
118
|
+
-- Fail loudly if any agent still lacks a manager.
|
|
119
|
+
DO $$
|
|
120
|
+
DECLARE
|
|
121
|
+
orphan_count integer;
|
|
122
|
+
BEGIN
|
|
123
|
+
SELECT COUNT(*) INTO orphan_count
|
|
124
|
+
FROM "agents"
|
|
125
|
+
WHERE "manager_id" IS NULL
|
|
126
|
+
AND "status" <> 'deleted';
|
|
127
|
+
|
|
128
|
+
IF orphan_count > 0 THEN
|
|
129
|
+
RAISE EXCEPTION
|
|
130
|
+
'unified-user-token migration: % non-deleted agents have no manager_id after backfill; '
|
|
131
|
+
'create at least one admin member per org, or set agents.manager_id manually, then retry',
|
|
132
|
+
orphan_count;
|
|
133
|
+
END IF;
|
|
134
|
+
END $$;
|
|
135
|
+
--> statement-breakpoint
|
|
136
|
+
|
|
137
|
+
ALTER TABLE "agents"
|
|
138
|
+
ALTER COLUMN "manager_id" SET NOT NULL;
|
|
139
|
+
--> statement-breakpoint
|
|
140
|
+
|
|
141
|
+
-- Recreate the manager_id FK as DEFERRABLE INITIALLY DEFERRED so the
|
|
142
|
+
-- bootstrap path for a new human agent + member row can run inside a
|
|
143
|
+
-- single transaction. The two rows reference each other (agents.manager_id
|
|
144
|
+
-- → members.id, members.agent_id → agents.uuid); without deferred FKs the
|
|
145
|
+
-- first INSERT always fails the sibling constraint.
|
|
146
|
+
ALTER TABLE "agents"
|
|
147
|
+
DROP CONSTRAINT IF EXISTS "agents_manager_id_fkey";
|
|
148
|
+
--> statement-breakpoint
|
|
149
|
+
|
|
150
|
+
ALTER TABLE "agents"
|
|
151
|
+
ADD CONSTRAINT "agents_manager_id_fkey"
|
|
152
|
+
FOREIGN KEY ("manager_id") REFERENCES "members"("id")
|
|
153
|
+
ON DELETE SET NULL
|
|
154
|
+
DEFERRABLE INITIALLY DEFERRED;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
-- PRD D7: remove `agents.profile` column and all dependent code paths.
|
|
2
|
+
-- The column was backfilled into `agent_configs.payload.prompt.append` by
|
|
3
|
+
-- migration 0018. After this migration, agent behavior instructions live
|
|
4
|
+
-- exclusively in `agent_configs`; the `profile` column is dead weight.
|
|
5
|
+
--
|
|
6
|
+
-- Callers that used to read/write `profile` have been updated in the same
|
|
7
|
+
-- release; operators must deploy this migration together with the matching
|
|
8
|
+
-- code change — no compatibility layer.
|
|
9
|
+
|
|
10
|
+
ALTER TABLE "agents" DROP COLUMN IF EXISTS "profile";
|
|
@@ -134,6 +134,27 @@
|
|
|
134
134
|
"when": 1776816000000,
|
|
135
135
|
"tag": "0018_agent_visibility",
|
|
136
136
|
"breakpoints": true
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"idx": 19,
|
|
140
|
+
"version": "7",
|
|
141
|
+
"when": 1776902400000,
|
|
142
|
+
"tag": "0019_agent_configs",
|
|
143
|
+
"breakpoints": true
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"idx": 20,
|
|
147
|
+
"version": "7",
|
|
148
|
+
"when": 1776988800000,
|
|
149
|
+
"tag": "0020_unified_user_token",
|
|
150
|
+
"breakpoints": true
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"idx": 21,
|
|
154
|
+
"version": "7",
|
|
155
|
+
"when": 1777075200000,
|
|
156
|
+
"tag": "0021_drop_agents_profile",
|
|
157
|
+
"breakpoints": true
|
|
137
158
|
}
|
|
138
159
|
]
|
|
139
160
|
}
|