team-chat 0.0.0-stage → 0.3.1

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 (122) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +458 -2
  3. package/agents/rules.md +52 -0
  4. package/agents/runtimes/codex.md +14 -0
  5. package/bin/bridge +3 -0
  6. package/bin/runner +3 -0
  7. package/cli/lib/agents.js +97 -0
  8. package/cli/lib/docs.js +151 -0
  9. package/cli/lib/local.js +41 -0
  10. package/cli/lib/server.js +52 -0
  11. package/cli/lib/util.js +107 -0
  12. package/cli/team-chat.js +383 -0
  13. package/host/bridge/attempts.js +43 -0
  14. package/host/bridge/bridge.js +326 -0
  15. package/host/bridge/config.js +105 -0
  16. package/host/bridge/knowledge-outbox.js +96 -0
  17. package/host/bridge/launcher.js +126 -0
  18. package/host/bridge/main.js +87 -0
  19. package/host/bridge/progress.js +74 -0
  20. package/host/bridge/prompt.js +97 -0
  21. package/host/bridge/run-archive.js +200 -0
  22. package/host/bridge/thread.js +44 -0
  23. package/host/bridge/triage.js +97 -0
  24. package/host/bridge/workdir.js +41 -0
  25. package/host/knowledge/card.js +43 -0
  26. package/host/knowledge/errors.js +50 -0
  27. package/host/knowledge/lesson.js +153 -0
  28. package/host/knowledge/process.js +160 -0
  29. package/host/knowledge/scrub.js +29 -0
  30. package/host/knowledge/shell.js +74 -0
  31. package/host/knowledge/stack.js +229 -0
  32. package/host/knowledge/transcript.js +82 -0
  33. package/host/lib/chat-api.js +120 -0
  34. package/host/lib/log.js +6 -0
  35. package/host/lib/pid-lock.js +65 -0
  36. package/host/lib/shell-words.js +45 -0
  37. package/host/runner/bridge-process.js +82 -0
  38. package/host/runner/config.js +81 -0
  39. package/host/runner/main.js +69 -0
  40. package/host/runner/retention.js +40 -0
  41. package/host/runner/runner.js +161 -0
  42. package/package.json +61 -5
  43. package/server/dist/src/app.js +25 -0
  44. package/server/dist/src/app.module.js +50 -0
  45. package/server/dist/src/attachments/attachment-store.js +111 -0
  46. package/server/dist/src/attachments/attachments.controller.js +67 -0
  47. package/server/dist/src/attachments/mime.js +84 -0
  48. package/server/dist/src/attachments/uploads.interceptor.js +72 -0
  49. package/server/dist/src/auth/participant.guard.js +53 -0
  50. package/server/dist/src/bridges/bridge-restart.service.js +80 -0
  51. package/server/dist/src/bridges/bridges.controller.js +47 -0
  52. package/server/dist/src/chats/chats.controller.js +83 -0
  53. package/server/dist/src/chats/chats.service.js +128 -0
  54. package/server/dist/src/collector/collector.controller.js +71 -0
  55. package/server/dist/src/collector/collector.module.js +23 -0
  56. package/server/dist/src/collector/collector.service.js +111 -0
  57. package/server/dist/src/common/clock.js +20 -0
  58. package/server/dist/src/common/errors.js +37 -0
  59. package/server/dist/src/common/format.js +14 -0
  60. package/server/dist/src/common/http.js +17 -0
  61. package/server/dist/src/common/slug.js +28 -0
  62. package/server/dist/src/common/tokens.js +19 -0
  63. package/server/dist/src/common/validation.js +41 -0
  64. package/server/dist/src/config/config.js +39 -0
  65. package/server/dist/src/conversation.module.js +41 -0
  66. package/server/dist/src/db/database.js +73 -0
  67. package/server/dist/src/db/database.module.js +51 -0
  68. package/server/dist/src/db/schema.js +212 -0
  69. package/server/dist/src/decisions/decisions.controller.js +55 -0
  70. package/server/dist/src/decisions/decisions.service.js +109 -0
  71. package/server/dist/src/documents/documents.controller.js +87 -0
  72. package/server/dist/src/documents/documents.service.js +189 -0
  73. package/server/dist/src/health/health.controller.js +29 -0
  74. package/server/dist/src/knowledge/knowledge.controller.js +83 -0
  75. package/server/dist/src/knowledge/knowledge.module.js +25 -0
  76. package/server/dist/src/knowledge/knowledge.service.js +189 -0
  77. package/server/dist/src/local/docs-sync.service.js +97 -0
  78. package/server/dist/src/local/local.controller.js +197 -0
  79. package/server/dist/src/local/local.guard.js +55 -0
  80. package/server/dist/src/local/local.module.js +30 -0
  81. package/server/dist/src/local/setup.service.js +154 -0
  82. package/server/dist/src/local/transfer.service.js +151 -0
  83. package/server/dist/src/main.js +33 -0
  84. package/server/dist/src/mcp/chat-tools.js +282 -0
  85. package/server/dist/src/mcp/mcp.controller.js +58 -0
  86. package/server/dist/src/mcp/mcp.module.js +24 -0
  87. package/server/dist/src/mentions/mention-state.js +80 -0
  88. package/server/dist/src/mentions/mentions.controller.js +100 -0
  89. package/server/dist/src/mentions/mentions.service.js +203 -0
  90. package/server/dist/src/messages/message.presenter.js +102 -0
  91. package/server/dist/src/messages/messages.service.js +149 -0
  92. package/server/dist/src/messages/thread.controller.js +179 -0
  93. package/server/dist/src/participants/directory.service.js +68 -0
  94. package/server/dist/src/participants/participants.module.js +24 -0
  95. package/server/dist/src/participants/participants.service.js +84 -0
  96. package/server/dist/src/settings/settings.service.js +42 -0
  97. package/server/dist/src/sharing/consent.js +16 -0
  98. package/server/dist/src/sharing/sharing.module.js +22 -0
  99. package/server/dist/src/sharing/sharing.service.js +175 -0
  100. package/server/dist/src/team/runner.service.js +75 -0
  101. package/server/dist/src/team/team.controller.js +178 -0
  102. package/server/dist/src/team/team.module.js +25 -0
  103. package/server/dist/src/team/team.service.js +280 -0
  104. package/server/dist/src/web/template.js +57 -0
  105. package/server/dist/src/web/web-login.service.js +74 -0
  106. package/server/dist/src/web/web.controller.js +203 -0
  107. package/server/dist/src/web/web.module.js +25 -0
  108. package/server/drizzle/0000_init.sql +169 -0
  109. package/server/drizzle/0001_seed_roles.sql +25 -0
  110. package/server/drizzle/0002_knowledge.sql +17 -0
  111. package/server/drizzle/0003_sharing.sql +30 -0
  112. package/server/drizzle/meta/0000_snapshot.json +1224 -0
  113. package/server/drizzle/meta/0001_snapshot.json +1224 -0
  114. package/server/drizzle/meta/0002_snapshot.json +1359 -0
  115. package/server/drizzle/meta/0003_snapshot.json +1545 -0
  116. package/server/drizzle/meta/_journal.json +34 -0
  117. package/server/package.json +1 -0
  118. package/server/views/chat.html +865 -0
  119. package/server/views/documents.html +204 -0
  120. package/server/views/login.html +31 -0
  121. package/server/views/setup.html +60 -0
  122. package/server/views/team.html +369 -0
@@ -0,0 +1,203 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.WebController = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const drizzle_orm_1 = require("drizzle-orm");
18
+ const attachment_store_1 = require("../attachments/attachment-store");
19
+ const chats_service_1 = require("../chats/chats.service");
20
+ const database_module_1 = require("../db/database.module");
21
+ const schema_1 = require("../db/schema");
22
+ const participants_service_1 = require("../participants/participants.service");
23
+ const template_1 = require("./template");
24
+ const web_login_service_1 = require("./web-login.service");
25
+ /**
26
+ * Страницы чата. Открываются только тем, кто вошёл по ссылке; токен из cookie страница
27
+ * отдаёт в свой JS — в API она ходит тем же Bearer-токеном, что и агенты.
28
+ */
29
+ let WebController = class WebController {
30
+ db;
31
+ chats;
32
+ participants;
33
+ login;
34
+ constructor(db, chats, participants, login) {
35
+ this.db = db;
36
+ this.chats = chats;
37
+ this.participants = participants;
38
+ this.login = login;
39
+ }
40
+ async enter(code, res) {
41
+ const entered = await this.login.consume(code);
42
+ if (!entered)
43
+ return page(res, 401, 'login', { expired: false, used: true });
44
+ res.cookie(web_login_service_1.COOKIE, entered.token, { httpOnly: true, sameSite: 'lax', maxAge: web_login_service_1.COOKIE_MAX_AGE_MS });
45
+ res.redirect('/');
46
+ }
47
+ async leave(req, res) {
48
+ const token = cookie(req, web_login_service_1.COOKIE);
49
+ if (token)
50
+ await this.login.logout(token);
51
+ res.clearCookie(web_login_service_1.COOKIE);
52
+ res.redirect('/');
53
+ }
54
+ /** Без адреса — в первый чат; чатов нет — на первый запуск. */
55
+ async home(req, res) {
56
+ if (!(await this.me(req, res)))
57
+ return;
58
+ res.redirect(await this.firstChatOr('/setup'));
59
+ }
60
+ async documentsHome(req, res) {
61
+ if (!(await this.me(req, res)))
62
+ return;
63
+ res.redirect(await this.firstChatOr('/setup', '/documents'));
64
+ }
65
+ async setup(req, res) {
66
+ const me = await this.me(req, res);
67
+ if (!me)
68
+ return;
69
+ if ((await this.chats.all()).length > 0)
70
+ return res.redirect('/');
71
+ page(res, 200, 'setup', { owner: (0, participants_service_1.isOwner)(me), token: me.token });
72
+ }
73
+ async chat(slug, req, res) {
74
+ const me = await this.me(req, res);
75
+ if (!me)
76
+ return;
77
+ const chat = await this.chats.bySlug(slug);
78
+ page(res, 200, 'chat', {
79
+ chat: (0, chats_service_1.chatApi)(chat), me, owner: (0, participants_service_1.isOwner)(me), token: me.token,
80
+ maxFiles: attachment_store_1.MAX_FILES, maxKb: attachment_store_1.MAX_BYTES / 1024,
81
+ });
82
+ }
83
+ async documents(slug, req, res) {
84
+ const me = await this.me(req, res);
85
+ if (!me)
86
+ return;
87
+ page(res, 200, 'documents', { chat: (0, chats_service_1.chatApi)(await this.chats.bySlug(slug)), me, owner: (0, participants_service_1.isOwner)(me), token: me.token });
88
+ }
89
+ /** Команда — общая на все чаты; «назад» ведёт в чат, из которого пришли. */
90
+ async team(from, req, res) {
91
+ const me = await this.me(req, res);
92
+ if (!me)
93
+ return;
94
+ const all = await this.chats.all();
95
+ const back = all.find(c => c.slug === from) ?? all[0];
96
+ page(res, 200, 'team', { me, owner: (0, participants_service_1.isOwner)(me), token: me.token, back: back ? `/c/${back.slug}` : '/setup' });
97
+ }
98
+ /**
99
+ * Кто вошёл в этом браузере. Не вошёл (или зашёл токеном агента) — страница входа и 401;
100
+ * агенты и раннеры ходят в API, а не на страницы.
101
+ */
102
+ async me(req, res) {
103
+ const token = cookie(req, web_login_service_1.COOKIE);
104
+ const participant = token ? await this.participants.byToken(token) : null;
105
+ if (!participant || participant.kind !== 'human') {
106
+ page(res, 401, 'login', { expired: Boolean(token), used: false });
107
+ return null;
108
+ }
109
+ await this.participants.touchSeen(participant.id);
110
+ return { ...participant, token: token };
111
+ }
112
+ async firstChatOr(fallback, suffix = '') {
113
+ const [first] = await this.db.select({ slug: schema_1.chats.slug }).from(schema_1.chats).orderBy((0, drizzle_orm_1.asc)(schema_1.chats.id)).limit(1);
114
+ return first ? `/c/${first.slug}${suffix}` : fallback;
115
+ }
116
+ };
117
+ exports.WebController = WebController;
118
+ __decorate([
119
+ (0, common_1.Get)('login/:code'),
120
+ __param(0, (0, common_1.Param)('code')),
121
+ __param(1, (0, common_1.Res)()),
122
+ __metadata("design:type", Function),
123
+ __metadata("design:paramtypes", [String, Object]),
124
+ __metadata("design:returntype", Promise)
125
+ ], WebController.prototype, "enter", null);
126
+ __decorate([
127
+ (0, common_1.Get)('logout'),
128
+ __param(0, (0, common_1.Req)()),
129
+ __param(1, (0, common_1.Res)()),
130
+ __metadata("design:type", Function),
131
+ __metadata("design:paramtypes", [Object, Object]),
132
+ __metadata("design:returntype", Promise)
133
+ ], WebController.prototype, "leave", null);
134
+ __decorate([
135
+ (0, common_1.Get)(),
136
+ __param(0, (0, common_1.Req)()),
137
+ __param(1, (0, common_1.Res)()),
138
+ __metadata("design:type", Function),
139
+ __metadata("design:paramtypes", [Object, Object]),
140
+ __metadata("design:returntype", Promise)
141
+ ], WebController.prototype, "home", null);
142
+ __decorate([
143
+ (0, common_1.Get)('documents'),
144
+ __param(0, (0, common_1.Req)()),
145
+ __param(1, (0, common_1.Res)()),
146
+ __metadata("design:type", Function),
147
+ __metadata("design:paramtypes", [Object, Object]),
148
+ __metadata("design:returntype", Promise)
149
+ ], WebController.prototype, "documentsHome", null);
150
+ __decorate([
151
+ (0, common_1.Get)('setup'),
152
+ __param(0, (0, common_1.Req)()),
153
+ __param(1, (0, common_1.Res)()),
154
+ __metadata("design:type", Function),
155
+ __metadata("design:paramtypes", [Object, Object]),
156
+ __metadata("design:returntype", Promise)
157
+ ], WebController.prototype, "setup", null);
158
+ __decorate([
159
+ (0, common_1.Get)('c/:chat'),
160
+ __param(0, (0, common_1.Param)('chat')),
161
+ __param(1, (0, common_1.Req)()),
162
+ __param(2, (0, common_1.Res)()),
163
+ __metadata("design:type", Function),
164
+ __metadata("design:paramtypes", [String, Object, Object]),
165
+ __metadata("design:returntype", Promise)
166
+ ], WebController.prototype, "chat", null);
167
+ __decorate([
168
+ (0, common_1.Get)('c/:chat/documents'),
169
+ __param(0, (0, common_1.Param)('chat')),
170
+ __param(1, (0, common_1.Req)()),
171
+ __param(2, (0, common_1.Res)()),
172
+ __metadata("design:type", Function),
173
+ __metadata("design:paramtypes", [String, Object, Object]),
174
+ __metadata("design:returntype", Promise)
175
+ ], WebController.prototype, "documents", null);
176
+ __decorate([
177
+ (0, common_1.Get)('team'),
178
+ __param(0, (0, common_1.Query)('from')),
179
+ __param(1, (0, common_1.Req)()),
180
+ __param(2, (0, common_1.Res)()),
181
+ __metadata("design:type", Function),
182
+ __metadata("design:paramtypes", [Object, Object, Object]),
183
+ __metadata("design:returntype", Promise)
184
+ ], WebController.prototype, "team", null);
185
+ exports.WebController = WebController = __decorate([
186
+ (0, common_1.Controller)(),
187
+ __param(0, (0, common_1.Inject)(database_module_1.DATABASE)),
188
+ __metadata("design:paramtypes", [Object, chats_service_1.ChatsService,
189
+ participants_service_1.ParticipantsService,
190
+ web_login_service_1.WebLoginService])
191
+ ], WebController);
192
+ function page(res, status, view, vars) {
193
+ res.status(status).type('html').send((0, template_1.render)(view, vars));
194
+ }
195
+ /** Cookie из заголовка — без cookie-parser: нужна одна. */
196
+ function cookie(req, name) {
197
+ for (const part of (req.headers.cookie ?? '').split(';')) {
198
+ const [key, ...rest] = part.trim().split('=');
199
+ if (key === name)
200
+ return decodeURIComponent(rest.join('='));
201
+ }
202
+ return null;
203
+ }
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.WebModule = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ const conversation_module_1 = require("../conversation.module");
12
+ const web_controller_1 = require("./web.controller");
13
+ const web_login_service_1 = require("./web-login.service");
14
+ /** Страницы и вход в них по одноразовой ссылке. */
15
+ let WebModule = class WebModule {
16
+ };
17
+ exports.WebModule = WebModule;
18
+ exports.WebModule = WebModule = __decorate([
19
+ (0, common_1.Module)({
20
+ imports: [conversation_module_1.ConversationModule],
21
+ providers: [web_login_service_1.WebLoginService],
22
+ controllers: [web_controller_1.WebController],
23
+ exports: [web_login_service_1.WebLoginService],
24
+ })
25
+ ], WebModule);
@@ -0,0 +1,169 @@
1
+ CREATE TABLE "attachments" (
2
+ "id" serial PRIMARY KEY NOT NULL,
3
+ "message_id" integer NOT NULL,
4
+ "name" text NOT NULL,
5
+ "mime" varchar(191) NOT NULL,
6
+ "size" bigint NOT NULL,
7
+ "path" text NOT NULL,
8
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
9
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
10
+ );
11
+ --> statement-breakpoint
12
+ CREATE TABLE "chat_agent_roles" (
13
+ "id" serial PRIMARY KEY NOT NULL,
14
+ "chat_id" integer NOT NULL,
15
+ "participant_id" integer NOT NULL,
16
+ "role" text NOT NULL,
17
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
18
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
19
+ CONSTRAINT "chat_agent_roles_chat_id_participant_id_unique" UNIQUE("chat_id","participant_id")
20
+ );
21
+ --> statement-breakpoint
22
+ CREATE TABLE "chats" (
23
+ "id" serial PRIMARY KEY NOT NULL,
24
+ "slug" text NOT NULL,
25
+ "name" text NOT NULL,
26
+ "description" text,
27
+ "workdir" text,
28
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
29
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
30
+ CONSTRAINT "chats_slug_unique" UNIQUE("slug")
31
+ );
32
+ --> statement-breakpoint
33
+ CREATE TABLE "decisions" (
34
+ "id" serial PRIMARY KEY NOT NULL,
35
+ "chat_id" integer NOT NULL,
36
+ "number" integer NOT NULL,
37
+ "participant_id" integer NOT NULL,
38
+ "title" text NOT NULL,
39
+ "body" text,
40
+ "message_id" integer,
41
+ "supersedes_id" integer,
42
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
43
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
44
+ CONSTRAINT "decisions_chat_id_number_unique" UNIQUE("chat_id","number")
45
+ );
46
+ --> statement-breakpoint
47
+ CREATE TABLE "document_versions" (
48
+ "id" serial PRIMARY KEY NOT NULL,
49
+ "document_id" integer NOT NULL,
50
+ "revision" integer NOT NULL,
51
+ "body" text NOT NULL,
52
+ "participant_id" integer,
53
+ "note" text,
54
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
55
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
56
+ CONSTRAINT "document_versions_document_id_revision_unique" UNIQUE("document_id","revision")
57
+ );
58
+ --> statement-breakpoint
59
+ CREATE TABLE "documents" (
60
+ "id" serial PRIMARY KEY NOT NULL,
61
+ "chat_id" integer NOT NULL,
62
+ "slug" text NOT NULL,
63
+ "title" text NOT NULL,
64
+ "kind" text NOT NULL,
65
+ "status" text DEFAULT 'draft' NOT NULL,
66
+ "origin" text,
67
+ "participant_id" integer,
68
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
69
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
70
+ CONSTRAINT "documents_chat_id_slug_unique" UNIQUE("chat_id","slug")
71
+ );
72
+ --> statement-breakpoint
73
+ CREATE TABLE "login_codes" (
74
+ "code_hash" varchar(64) PRIMARY KEY NOT NULL,
75
+ "participant_id" integer NOT NULL,
76
+ "expires_at" timestamp with time zone NOT NULL,
77
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL
78
+ );
79
+ --> statement-breakpoint
80
+ CREATE TABLE "mentions" (
81
+ "id" serial PRIMARY KEY NOT NULL,
82
+ "message_id" integer NOT NULL,
83
+ "participant_id" integer NOT NULL,
84
+ "handled_at" timestamp with time zone,
85
+ "run_started_at" timestamp with time zone,
86
+ "beat_at" timestamp with time zone,
87
+ "beat_ttl" integer,
88
+ "outcome" varchar(16),
89
+ "outcome_at" timestamp with time zone,
90
+ "note" text,
91
+ "attempts" integer DEFAULT 0 NOT NULL,
92
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
93
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
94
+ CONSTRAINT "mentions_message_id_participant_id_unique" UNIQUE("message_id","participant_id")
95
+ );
96
+ --> statement-breakpoint
97
+ CREATE TABLE "messages" (
98
+ "id" serial PRIMARY KEY NOT NULL,
99
+ "chat_id" integer NOT NULL,
100
+ "participant_id" integer NOT NULL,
101
+ "body" text NOT NULL,
102
+ "reply_to_id" integer,
103
+ "asks_owner" boolean DEFAULT false NOT NULL,
104
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
105
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
106
+ );
107
+ --> statement-breakpoint
108
+ CREATE TABLE "participant_tokens" (
109
+ "id" serial PRIMARY KEY NOT NULL,
110
+ "participant_id" integer NOT NULL,
111
+ "token_hash" varchar(64) NOT NULL,
112
+ "label" text NOT NULL,
113
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
114
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
115
+ CONSTRAINT "participant_tokens_token_hash_unique" UNIQUE("token_hash")
116
+ );
117
+ --> statement-breakpoint
118
+ CREATE TABLE "participants" (
119
+ "id" serial PRIMARY KEY NOT NULL,
120
+ "name" text NOT NULL,
121
+ "handle" text NOT NULL,
122
+ "kind" text NOT NULL,
123
+ "role" text NOT NULL,
124
+ "accent" varchar(16) DEFAULT '#0057c2' NOT NULL,
125
+ "token_hash" varchar(64),
126
+ "last_seen_at" timestamp with time zone,
127
+ "runtime" varchar(40),
128
+ "disabled_at" timestamp with time zone,
129
+ "host_id" integer,
130
+ "runtimes" jsonb,
131
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
132
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
133
+ CONSTRAINT "participants_handle_unique" UNIQUE("handle"),
134
+ CONSTRAINT "participants_token_hash_unique" UNIQUE("token_hash")
135
+ );
136
+ --> statement-breakpoint
137
+ CREATE TABLE "roles" (
138
+ "id" serial PRIMARY KEY NOT NULL,
139
+ "slug" text NOT NULL,
140
+ "name" text NOT NULL,
141
+ "instructions" text NOT NULL,
142
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
143
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
144
+ CONSTRAINT "roles_slug_unique" UNIQUE("slug")
145
+ );
146
+ --> statement-breakpoint
147
+ ALTER TABLE "attachments" ADD CONSTRAINT "attachments_message_id_messages_id_fk" FOREIGN KEY ("message_id") REFERENCES "public"."messages"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
148
+ ALTER TABLE "chat_agent_roles" ADD CONSTRAINT "chat_agent_roles_chat_id_chats_id_fk" FOREIGN KEY ("chat_id") REFERENCES "public"."chats"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
149
+ ALTER TABLE "chat_agent_roles" ADD CONSTRAINT "chat_agent_roles_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
150
+ ALTER TABLE "decisions" ADD CONSTRAINT "decisions_chat_id_chats_id_fk" FOREIGN KEY ("chat_id") REFERENCES "public"."chats"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
151
+ ALTER TABLE "decisions" ADD CONSTRAINT "decisions_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
152
+ ALTER TABLE "decisions" ADD CONSTRAINT "decisions_message_id_messages_id_fk" FOREIGN KEY ("message_id") REFERENCES "public"."messages"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
153
+ ALTER TABLE "decisions" ADD CONSTRAINT "decisions_supersedes_id_decisions_id_fk" FOREIGN KEY ("supersedes_id") REFERENCES "public"."decisions"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
154
+ ALTER TABLE "document_versions" ADD CONSTRAINT "document_versions_document_id_documents_id_fk" FOREIGN KEY ("document_id") REFERENCES "public"."documents"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
155
+ ALTER TABLE "document_versions" ADD CONSTRAINT "document_versions_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
156
+ ALTER TABLE "documents" ADD CONSTRAINT "documents_chat_id_chats_id_fk" FOREIGN KEY ("chat_id") REFERENCES "public"."chats"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
157
+ ALTER TABLE "documents" ADD CONSTRAINT "documents_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
158
+ ALTER TABLE "login_codes" ADD CONSTRAINT "login_codes_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
159
+ ALTER TABLE "mentions" ADD CONSTRAINT "mentions_message_id_messages_id_fk" FOREIGN KEY ("message_id") REFERENCES "public"."messages"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
160
+ ALTER TABLE "mentions" ADD CONSTRAINT "mentions_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
161
+ ALTER TABLE "messages" ADD CONSTRAINT "messages_chat_id_chats_id_fk" FOREIGN KEY ("chat_id") REFERENCES "public"."chats"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
162
+ ALTER TABLE "messages" ADD CONSTRAINT "messages_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
163
+ ALTER TABLE "messages" ADD CONSTRAINT "messages_reply_to_id_messages_id_fk" FOREIGN KEY ("reply_to_id") REFERENCES "public"."messages"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
164
+ ALTER TABLE "participant_tokens" ADD CONSTRAINT "participant_tokens_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
165
+ ALTER TABLE "participants" ADD CONSTRAINT "participants_host_id_participants_id_fk" FOREIGN KEY ("host_id") REFERENCES "public"."participants"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
166
+ CREATE INDEX "documents_status_kind_index" ON "documents" USING btree ("status","kind");--> statement-breakpoint
167
+ CREATE INDEX "mentions_participant_id_handled_at_index" ON "mentions" USING btree ("participant_id","handled_at");--> statement-breakpoint
168
+ CREATE INDEX "messages_chat_id_id_index" ON "messages" USING btree ("chat_id","id");--> statement-breakpoint
169
+ CREATE INDEX "messages_created_at_index" ON "messages" USING btree ("created_at");
@@ -0,0 +1,25 @@
1
+ -- Роли по умолчанию: их назначает агентам первый запуск (team-chat start → setup).
2
+ -- Тексты — те же, что заводила PHP-миграция 2026_10_24_000000_create_roles_and_agents.
3
+ -- Уже есть (перенос базы) — не трогаем: роли мог переписать владелец.
4
+ INSERT INTO "roles" ("slug", "name", "instructions") VALUES
5
+ ('developer', 'Разработчик', $md$Отвечаешь за **последствия, стоимость и риски реализации**. Бизнес-модель и
6
+ требования — зона аналитика, решения принимает владелец.
7
+
8
+ - Проверяй факты в коде, а не вспоминай. У тебя есть доступ к репозиториям — если
9
+ вопрос о том, как что-то устроено, посмотри, прежде чем отвечать.
10
+ - Говори прямо, если предложение технически дорого или ломает работающее.
11
+ Соглашаться с плохой идеей — не помощь.
12
+ - Не переписывай задним числом уже принятое решение. Не согласен — скажи и предложи
13
+ выпустить новое решение взамен старого.$md$),
14
+ ('analyst', 'Бизнес-аналитик', $md$Отвечаешь за **бизнес-модель, экономику и требования**. Техническая реализация,
15
+ её стоимость и риски — зона разработчика, решения принимает владелец.
16
+
17
+ - **Не пиши код.** Это не твоя роль, и смешение ролей обходится дорого: реализация,
18
+ написанная мимо разработчика, чаще ломает тесты и конвенции репозитория. Нужна
19
+ реализация — ставь задачу разработчику.
20
+ - Требования формулируй проверяемо: что должно быть верно, чтобы решение считалось рабочим.
21
+ - Если предложение противоречит уже принятому решению — скажи прямо и предложи
22
+ выпустить новое решение взамен старого, а не переписывать прошлое.
23
+ - Проверяй факты в коде и во внешних источниках сам: утверждать что-либо о
24
+ содержимом репозиториев или о рынке по памяти нет причин — сходи и посмотри.$md$)
25
+ ON CONFLICT ("slug") DO NOTHING;
@@ -0,0 +1,17 @@
1
+ CREATE TABLE "knowledge_cards" (
2
+ "id" serial PRIMARY KEY NOT NULL,
3
+ "chat_id" integer NOT NULL,
4
+ "participant_id" integer,
5
+ "key" text NOT NULL,
6
+ "format" integer NOT NULL,
7
+ "card" jsonb NOT NULL,
8
+ "search" text,
9
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
10
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
11
+ CONSTRAINT "knowledge_cards_key_unique" UNIQUE("key")
12
+ );
13
+ --> statement-breakpoint
14
+ ALTER TABLE "knowledge_cards" ADD CONSTRAINT "knowledge_cards_chat_id_chats_id_fk" FOREIGN KEY ("chat_id") REFERENCES "public"."chats"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
15
+ ALTER TABLE "knowledge_cards" ADD CONSTRAINT "knowledge_cards_participant_id_participants_id_fk" FOREIGN KEY ("participant_id") REFERENCES "public"."participants"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
16
+ CREATE INDEX "knowledge_cards_search_idx" ON "knowledge_cards" USING gin (to_tsvector('russian', "search"));--> statement-breakpoint
17
+ CREATE INDEX "knowledge_cards_chat_id_index" ON "knowledge_cards" USING btree ("chat_id");
@@ -0,0 +1,30 @@
1
+ CREATE TABLE "collected_cards" (
2
+ "id" serial PRIMARY KEY NOT NULL,
3
+ "installation_id" integer NOT NULL,
4
+ "ref" varchar(64) NOT NULL,
5
+ "format" integer NOT NULL,
6
+ "card" jsonb NOT NULL,
7
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
8
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
9
+ CONSTRAINT "collected_cards_installation_id_ref_unique" UNIQUE("installation_id","ref")
10
+ );
11
+ --> statement-breakpoint
12
+ CREATE TABLE "collector_installations" (
13
+ "id" serial PRIMARY KEY NOT NULL,
14
+ "token_hash" varchar(64) NOT NULL,
15
+ "last_seen_at" timestamp with time zone,
16
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
17
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL,
18
+ CONSTRAINT "collector_installations_token_hash_unique" UNIQUE("token_hash")
19
+ );
20
+ --> statement-breakpoint
21
+ CREATE TABLE "settings" (
22
+ "key" text PRIMARY KEY NOT NULL,
23
+ "value" jsonb NOT NULL,
24
+ "created_at" timestamp with time zone DEFAULT now() NOT NULL,
25
+ "updated_at" timestamp with time zone DEFAULT now() NOT NULL
26
+ );
27
+ --> statement-breakpoint
28
+ ALTER TABLE "knowledge_cards" ADD COLUMN "revision" integer DEFAULT 1 NOT NULL;--> statement-breakpoint
29
+ ALTER TABLE "knowledge_cards" ADD COLUMN "shared_revision" integer DEFAULT 0 NOT NULL;--> statement-breakpoint
30
+ ALTER TABLE "collected_cards" ADD CONSTRAINT "collected_cards_installation_id_collector_installations_id_fk" FOREIGN KEY ("installation_id") REFERENCES "public"."collector_installations"("id") ON DELETE cascade ON UPDATE no action;