team-chat 0.0.0-stage → 0.3.0
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/LICENSE +21 -0
- package/README.md +458 -2
- package/agents/rules.md +52 -0
- package/agents/runtimes/codex.md +14 -0
- package/bin/bridge +3 -0
- package/bin/runner +3 -0
- package/cli/lib/agents.js +97 -0
- package/cli/lib/docs.js +151 -0
- package/cli/lib/local.js +41 -0
- package/cli/lib/server.js +52 -0
- package/cli/lib/util.js +107 -0
- package/cli/team-chat.js +383 -0
- package/host/bridge/attempts.js +43 -0
- package/host/bridge/bridge.js +326 -0
- package/host/bridge/config.js +105 -0
- package/host/bridge/knowledge-outbox.js +96 -0
- package/host/bridge/launcher.js +126 -0
- package/host/bridge/main.js +87 -0
- package/host/bridge/progress.js +74 -0
- package/host/bridge/prompt.js +97 -0
- package/host/bridge/run-archive.js +200 -0
- package/host/bridge/thread.js +44 -0
- package/host/bridge/triage.js +97 -0
- package/host/bridge/workdir.js +41 -0
- package/host/knowledge/card.js +43 -0
- package/host/knowledge/errors.js +50 -0
- package/host/knowledge/lesson.js +153 -0
- package/host/knowledge/process.js +160 -0
- package/host/knowledge/scrub.js +29 -0
- package/host/knowledge/shell.js +74 -0
- package/host/knowledge/stack.js +229 -0
- package/host/knowledge/transcript.js +82 -0
- package/host/lib/chat-api.js +120 -0
- package/host/lib/log.js +6 -0
- package/host/lib/pid-lock.js +65 -0
- package/host/lib/shell-words.js +45 -0
- package/host/runner/bridge-process.js +82 -0
- package/host/runner/config.js +81 -0
- package/host/runner/main.js +69 -0
- package/host/runner/retention.js +40 -0
- package/host/runner/runner.js +161 -0
- package/package.json +67 -5
- package/server/dist/src/app.js +25 -0
- package/server/dist/src/app.module.js +50 -0
- package/server/dist/src/attachments/attachment-store.js +111 -0
- package/server/dist/src/attachments/attachments.controller.js +67 -0
- package/server/dist/src/attachments/mime.js +84 -0
- package/server/dist/src/attachments/uploads.interceptor.js +72 -0
- package/server/dist/src/auth/participant.guard.js +53 -0
- package/server/dist/src/bridges/bridge-restart.service.js +80 -0
- package/server/dist/src/bridges/bridges.controller.js +47 -0
- package/server/dist/src/chats/chats.controller.js +83 -0
- package/server/dist/src/chats/chats.service.js +128 -0
- package/server/dist/src/collector/collector.controller.js +71 -0
- package/server/dist/src/collector/collector.module.js +23 -0
- package/server/dist/src/collector/collector.service.js +111 -0
- package/server/dist/src/common/clock.js +20 -0
- package/server/dist/src/common/errors.js +37 -0
- package/server/dist/src/common/format.js +14 -0
- package/server/dist/src/common/http.js +17 -0
- package/server/dist/src/common/slug.js +28 -0
- package/server/dist/src/common/tokens.js +19 -0
- package/server/dist/src/common/validation.js +41 -0
- package/server/dist/src/config/config.js +39 -0
- package/server/dist/src/conversation.module.js +41 -0
- package/server/dist/src/db/database.js +73 -0
- package/server/dist/src/db/database.module.js +51 -0
- package/server/dist/src/db/schema.js +212 -0
- package/server/dist/src/decisions/decisions.controller.js +55 -0
- package/server/dist/src/decisions/decisions.service.js +109 -0
- package/server/dist/src/documents/documents.controller.js +87 -0
- package/server/dist/src/documents/documents.service.js +189 -0
- package/server/dist/src/health/health.controller.js +29 -0
- package/server/dist/src/knowledge/knowledge.controller.js +83 -0
- package/server/dist/src/knowledge/knowledge.module.js +25 -0
- package/server/dist/src/knowledge/knowledge.service.js +189 -0
- package/server/dist/src/local/docs-sync.service.js +97 -0
- package/server/dist/src/local/local.controller.js +197 -0
- package/server/dist/src/local/local.guard.js +55 -0
- package/server/dist/src/local/local.module.js +30 -0
- package/server/dist/src/local/setup.service.js +154 -0
- package/server/dist/src/local/transfer.service.js +151 -0
- package/server/dist/src/main.js +33 -0
- package/server/dist/src/mcp/chat-tools.js +282 -0
- package/server/dist/src/mcp/mcp.controller.js +58 -0
- package/server/dist/src/mcp/mcp.module.js +24 -0
- package/server/dist/src/mentions/mention-state.js +80 -0
- package/server/dist/src/mentions/mentions.controller.js +100 -0
- package/server/dist/src/mentions/mentions.service.js +203 -0
- package/server/dist/src/messages/message.presenter.js +102 -0
- package/server/dist/src/messages/messages.service.js +149 -0
- package/server/dist/src/messages/thread.controller.js +179 -0
- package/server/dist/src/participants/directory.service.js +68 -0
- package/server/dist/src/participants/participants.module.js +24 -0
- package/server/dist/src/participants/participants.service.js +84 -0
- package/server/dist/src/settings/settings.service.js +42 -0
- package/server/dist/src/sharing/consent.js +16 -0
- package/server/dist/src/sharing/sharing.module.js +22 -0
- package/server/dist/src/sharing/sharing.service.js +175 -0
- package/server/dist/src/team/runner.service.js +75 -0
- package/server/dist/src/team/team.controller.js +178 -0
- package/server/dist/src/team/team.module.js +25 -0
- package/server/dist/src/team/team.service.js +280 -0
- package/server/dist/src/web/template.js +57 -0
- package/server/dist/src/web/web-login.service.js +74 -0
- package/server/dist/src/web/web.controller.js +203 -0
- package/server/dist/src/web/web.module.js +25 -0
- package/server/drizzle/0000_init.sql +169 -0
- package/server/drizzle/0001_seed_roles.sql +25 -0
- package/server/drizzle/0002_knowledge.sql +17 -0
- package/server/drizzle/0003_sharing.sql +30 -0
- package/server/drizzle/meta/0000_snapshot.json +1224 -0
- package/server/drizzle/meta/0001_snapshot.json +1224 -0
- package/server/drizzle/meta/0002_snapshot.json +1359 -0
- package/server/drizzle/meta/0003_snapshot.json +1545 -0
- package/server/drizzle/meta/_journal.json +34 -0
- package/server/package.json +1 -0
- package/server/views/chat.html +865 -0
- package/server/views/documents.html +204 -0
- package/server/views/login.html +31 -0
- package/server/views/setup.html +60 -0
- 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;
|