hanoman 0.1.9 → 0.1.11
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/build-info.json +3 -3
- package/dist/cli.js +210 -4
- package/dist/server.js +2215 -174
- package/package.json +1 -1
- package/prisma/migrations/20260801170000_github_issue/migration.sql +31 -0
- package/prisma/migrations/20260801180000_telegram_gateway/migration.sql +112 -0
- package/prisma/schema.prisma +143 -0
- package/web/assets/{index-D5MU9hT6.js → index-D8IVSqJP.js} +1551 -1551
- package/web/index.html +1 -1
package/package.json
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
-- SPEC-471 · ADR-0095 · cermin issue GitHub sebagai record lokal (pola Ticket, ADR-0062).
|
|
2
|
+
--
|
|
3
|
+
-- Tabel baru → `CREATE TABLE` polos; tak ada redefinisi tabel.
|
|
4
|
+
-- `id` deterministik "<projectId>:<owner>/<repo>#<number>" ditulis aplikasi, bukan default DB —
|
|
5
|
+
-- itulah yang mencegah dua mesin melahirkan dua baris untuk issue yang sama.
|
|
6
|
+
-- `specId` sengaja TANPA FOREIGN KEY, cermin Ticket.specId: changefeed bisa memancarkan
|
|
7
|
+
-- GithubIssue sebelum Spec-nya mendarat (kelas SPEC-382), dan FK akan menolaknya.
|
|
8
|
+
CREATE TABLE "GithubIssue" (
|
|
9
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
10
|
+
"projectId" TEXT NOT NULL,
|
|
11
|
+
"repoSlug" TEXT NOT NULL,
|
|
12
|
+
"number" INTEGER NOT NULL,
|
|
13
|
+
"title" TEXT NOT NULL,
|
|
14
|
+
"body" TEXT NOT NULL,
|
|
15
|
+
"authorLogin" TEXT NOT NULL,
|
|
16
|
+
"labels" JSONB NOT NULL,
|
|
17
|
+
"url" TEXT NOT NULL,
|
|
18
|
+
"issueState" TEXT NOT NULL,
|
|
19
|
+
"status" TEXT NOT NULL DEFAULT 'new',
|
|
20
|
+
"specId" TEXT,
|
|
21
|
+
"issueCreatedAt" DATETIME NOT NULL,
|
|
22
|
+
"issueUpdatedAt" DATETIME NOT NULL,
|
|
23
|
+
"pulledAt" DATETIME NOT NULL,
|
|
24
|
+
"version" INTEGER NOT NULL DEFAULT 0,
|
|
25
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
26
|
+
"updatedAt" DATETIME NOT NULL,
|
|
27
|
+
CONSTRAINT "GithubIssue_projectId_fkey" FOREIGN KEY ("projectId")
|
|
28
|
+
REFERENCES "Project" ("id") ON DELETE CASCADE ON UPDATE CASCADE
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
CREATE INDEX "GithubIssue_projectId_status_idx" ON "GithubIssue" ("projectId", "status");
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
-- SPEC-476 · ADR-0096 · durable, local-only Telegram gateway state.
|
|
2
|
+
-- Deliberately no foreign keys: project/session references may disappear while dedupe/audit remains.
|
|
3
|
+
-- Deliberately no credentials or inbound message body.
|
|
4
|
+
CREATE TABLE "TelegramGatewayState" (
|
|
5
|
+
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT DEFAULT 1,
|
|
6
|
+
"offset" INTEGER NOT NULL DEFAULT 0,
|
|
7
|
+
"botUsername" TEXT,
|
|
8
|
+
"lastUpdateAt" DATETIME,
|
|
9
|
+
"lastError" TEXT,
|
|
10
|
+
"updatedAt" DATETIME NOT NULL
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
CREATE TABLE "TelegramChat" (
|
|
14
|
+
"chatId" TEXT NOT NULL PRIMARY KEY,
|
|
15
|
+
"userId" TEXT NOT NULL,
|
|
16
|
+
"sessionId" TEXT,
|
|
17
|
+
"activeProjectId" TEXT,
|
|
18
|
+
"activeSessionId" TEXT,
|
|
19
|
+
"personalityAgentId" TEXT,
|
|
20
|
+
"summary" TEXT,
|
|
21
|
+
"agent" TEXT NOT NULL,
|
|
22
|
+
"model" TEXT NOT NULL,
|
|
23
|
+
"effort" TEXT NOT NULL,
|
|
24
|
+
"lastProgressKey" TEXT,
|
|
25
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
26
|
+
"updatedAt" DATETIME NOT NULL
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE UNIQUE INDEX "TelegramChat_userId_key" ON "TelegramChat"("userId");
|
|
30
|
+
|
|
31
|
+
CREATE TABLE "TelegramUpdate" (
|
|
32
|
+
"updateId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
33
|
+
"chatId" TEXT,
|
|
34
|
+
"userId" TEXT,
|
|
35
|
+
"kind" TEXT NOT NULL,
|
|
36
|
+
"digest" TEXT NOT NULL,
|
|
37
|
+
"state" TEXT NOT NULL DEFAULT 'received',
|
|
38
|
+
"rejectReason" TEXT,
|
|
39
|
+
"receivedAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
40
|
+
"claimedAt" DATETIME,
|
|
41
|
+
"dispatchedAt" DATETIME
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE INDEX "TelegramUpdate_userId_receivedAt_idx" ON "TelegramUpdate"("userId", "receivedAt");
|
|
45
|
+
CREATE INDEX "TelegramUpdate_state_idx" ON "TelegramUpdate"("state");
|
|
46
|
+
|
|
47
|
+
CREATE TABLE "TelegramMemory" (
|
|
48
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
49
|
+
"chatId" TEXT NOT NULL,
|
|
50
|
+
"content" TEXT NOT NULL,
|
|
51
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
52
|
+
"updatedAt" DATETIME NOT NULL
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
CREATE INDEX "TelegramMemory_chatId_createdAt_idx" ON "TelegramMemory"("chatId", "createdAt");
|
|
56
|
+
|
|
57
|
+
CREATE TABLE "TelegramOutbox" (
|
|
58
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
59
|
+
"chatId" TEXT NOT NULL,
|
|
60
|
+
"updateId" INTEGER NOT NULL,
|
|
61
|
+
"kind" TEXT NOT NULL,
|
|
62
|
+
"dedupeKey" TEXT NOT NULL,
|
|
63
|
+
"text" TEXT NOT NULL,
|
|
64
|
+
"state" TEXT NOT NULL DEFAULT 'pending',
|
|
65
|
+
"confirmationId" TEXT,
|
|
66
|
+
"telegramMessageId" INTEGER,
|
|
67
|
+
"error" TEXT,
|
|
68
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
69
|
+
"claimedAt" DATETIME,
|
|
70
|
+
"sentAt" DATETIME
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
CREATE UNIQUE INDEX "TelegramOutbox_dedupeKey_key" ON "TelegramOutbox"("dedupeKey");
|
|
74
|
+
CREATE INDEX "TelegramOutbox_state_createdAt_idx" ON "TelegramOutbox"("state", "createdAt");
|
|
75
|
+
CREATE INDEX "TelegramOutbox_chatId_createdAt_idx" ON "TelegramOutbox"("chatId", "createdAt");
|
|
76
|
+
|
|
77
|
+
CREATE TABLE "TelegramConfirmation" (
|
|
78
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
79
|
+
"callbackToken" TEXT NOT NULL,
|
|
80
|
+
"chatId" TEXT NOT NULL,
|
|
81
|
+
"userId" TEXT NOT NULL,
|
|
82
|
+
"updateId" INTEGER NOT NULL,
|
|
83
|
+
"description" TEXT NOT NULL,
|
|
84
|
+
"method" TEXT NOT NULL,
|
|
85
|
+
"path" TEXT NOT NULL,
|
|
86
|
+
"state" TEXT NOT NULL DEFAULT 'pending',
|
|
87
|
+
"expiresAt" DATETIME NOT NULL,
|
|
88
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
89
|
+
"approvedAt" DATETIME,
|
|
90
|
+
"usedAt" DATETIME
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
CREATE UNIQUE INDEX "TelegramConfirmation_callbackToken_key" ON "TelegramConfirmation"("callbackToken");
|
|
94
|
+
CREATE INDEX "TelegramConfirmation_chatId_state_idx" ON "TelegramConfirmation"("chatId", "state");
|
|
95
|
+
CREATE INDEX "TelegramConfirmation_expiresAt_idx" ON "TelegramConfirmation"("expiresAt");
|
|
96
|
+
|
|
97
|
+
CREATE TABLE "TelegramAudit" (
|
|
98
|
+
"id" TEXT NOT NULL PRIMARY KEY,
|
|
99
|
+
"chatId" TEXT,
|
|
100
|
+
"userId" TEXT,
|
|
101
|
+
"updateId" INTEGER,
|
|
102
|
+
"action" TEXT NOT NULL,
|
|
103
|
+
"outcome" TEXT NOT NULL,
|
|
104
|
+
"correlationId" TEXT,
|
|
105
|
+
"method" TEXT,
|
|
106
|
+
"path" TEXT,
|
|
107
|
+
"statusCode" INTEGER,
|
|
108
|
+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
CREATE INDEX "TelegramAudit_chatId_createdAt_idx" ON "TelegramAudit"("chatId", "createdAt");
|
|
112
|
+
CREATE INDEX "TelegramAudit_updateId_idx" ON "TelegramAudit"("updateId");
|
package/prisma/schema.prisma
CHANGED
|
@@ -24,6 +24,7 @@ model Project {
|
|
|
24
24
|
specs Spec[]
|
|
25
25
|
tickets Ticket[]
|
|
26
26
|
customAgents CustomAgent[] // SPEC-450 · ADR-0094 · custom agent milik project ini
|
|
27
|
+
githubIssues GithubIssue[] // SPEC-471 · ADR-0095 · cermin issue repo GitHub project ini
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
model Spec {
|
|
@@ -91,6 +92,38 @@ model CustomAgent {
|
|
|
91
92
|
@@index([projectId])
|
|
92
93
|
}
|
|
93
94
|
|
|
95
|
+
// SPEC-471 · ADR-0095 · cermin issue GitHub sebagai record lokal, pola Ticket (ADR-0062).
|
|
96
|
+
// `id` DETERMINISTIK "<projectId>:<owner>/<repo>#<number>" ditulis aplikasi, bukan default DB —
|
|
97
|
+
// alasan yang sama dengan CustomAgent (ADR-0094): dua mesin yang menarik repo yang sama harus
|
|
98
|
+
// bertemu sebagai SATU baris di changefeed, bukan dua yang saling menelan. `projectId` ikut di
|
|
99
|
+
// dalam id karena dua project hanoman boleh menunjuk repo yang sama.
|
|
100
|
+
//
|
|
101
|
+
// `specId` sengaja TANPA FK (cermin Ticket.specId): changefeed bisa memancarkan GithubIssue
|
|
102
|
+
// sebelum Spec-nya mendarat (kelas SPEC-382) dan FK akan menolaknya.
|
|
103
|
+
model GithubIssue {
|
|
104
|
+
id String @id
|
|
105
|
+
projectId String
|
|
106
|
+
repoSlug String // "owner/repo"
|
|
107
|
+
number Int
|
|
108
|
+
title String
|
|
109
|
+
body String
|
|
110
|
+
authorLogin String
|
|
111
|
+
labels Json // string[]
|
|
112
|
+
url String
|
|
113
|
+
issueState String // open | closed — keadaan DI GITHUB saat ditarik
|
|
114
|
+
status String @default("new") // new | accepted | rejected (zGithubIssueStatus)
|
|
115
|
+
specId String? // soft-link Spec hasil promosi
|
|
116
|
+
issueCreatedAt DateTime
|
|
117
|
+
issueUpdatedAt DateTime
|
|
118
|
+
pulledAt DateTime
|
|
119
|
+
version Int @default(0) // SPEC-471 · version-stamp sync (ADR-0045)
|
|
120
|
+
createdAt DateTime @default(now())
|
|
121
|
+
updatedAt DateTime @updatedAt
|
|
122
|
+
project Project @relation(fields: [projectId], references: [id], onDelete: Cascade)
|
|
123
|
+
|
|
124
|
+
@@index([projectId, status])
|
|
125
|
+
}
|
|
126
|
+
|
|
94
127
|
model Setting {
|
|
95
128
|
id Int @id @default(1)
|
|
96
129
|
data Json
|
|
@@ -378,6 +411,116 @@ model RuntimeConfig {
|
|
|
378
411
|
updatedAt DateTime @updatedAt
|
|
379
412
|
}
|
|
380
413
|
|
|
414
|
+
// SPEC-476 · ADR-0096 · seluruh state gateway Telegram bersifat LOCAL-only. Telegram adalah kanal
|
|
415
|
+
// menuju tmux di mesin ini, jadi offset/binding/memory/outbox tidak punya arti untuk sync antar-node.
|
|
416
|
+
// Tujuh model ini sengaja tanpa FK: referensi project/spec/session dapat hilang sementara audit dan
|
|
417
|
+
// dedupe harus tetap bertahan. Tidak ada token, credential, atau body inbound di schema ini.
|
|
418
|
+
model TelegramGatewayState {
|
|
419
|
+
id Int @id @default(1)
|
|
420
|
+
offset Int @default(0)
|
|
421
|
+
botUsername String?
|
|
422
|
+
lastUpdateAt DateTime?
|
|
423
|
+
lastError String?
|
|
424
|
+
updatedAt DateTime @updatedAt
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
model TelegramChat {
|
|
428
|
+
chatId String @id
|
|
429
|
+
userId String @unique
|
|
430
|
+
sessionId String?
|
|
431
|
+
activeProjectId String?
|
|
432
|
+
activeSessionId String?
|
|
433
|
+
personalityAgentId String?
|
|
434
|
+
summary String?
|
|
435
|
+
agent String
|
|
436
|
+
model String
|
|
437
|
+
effort String
|
|
438
|
+
lastProgressKey String?
|
|
439
|
+
createdAt DateTime @default(now())
|
|
440
|
+
updatedAt DateTime @updatedAt
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
model TelegramUpdate {
|
|
444
|
+
updateId Int @id
|
|
445
|
+
chatId String?
|
|
446
|
+
userId String?
|
|
447
|
+
kind String
|
|
448
|
+
digest String
|
|
449
|
+
state String @default("received") // received | rejected | dispatching | dispatched | uncertain
|
|
450
|
+
rejectReason String?
|
|
451
|
+
receivedAt DateTime @default(now())
|
|
452
|
+
claimedAt DateTime?
|
|
453
|
+
dispatchedAt DateTime?
|
|
454
|
+
|
|
455
|
+
@@index([userId, receivedAt])
|
|
456
|
+
@@index([state])
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
model TelegramMemory {
|
|
460
|
+
id String @id @default(cuid())
|
|
461
|
+
chatId String
|
|
462
|
+
content String
|
|
463
|
+
createdAt DateTime @default(now())
|
|
464
|
+
updatedAt DateTime @updatedAt
|
|
465
|
+
|
|
466
|
+
@@index([chatId, createdAt])
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
model TelegramOutbox {
|
|
470
|
+
id String @id @default(cuid())
|
|
471
|
+
chatId String
|
|
472
|
+
updateId Int
|
|
473
|
+
kind String
|
|
474
|
+
dedupeKey String @unique
|
|
475
|
+
text String
|
|
476
|
+
state String @default("pending") // pending | sending | sent | failed | uncertain
|
|
477
|
+
confirmationId String?
|
|
478
|
+
telegramMessageId Int?
|
|
479
|
+
error String?
|
|
480
|
+
createdAt DateTime @default(now())
|
|
481
|
+
claimedAt DateTime?
|
|
482
|
+
sentAt DateTime?
|
|
483
|
+
|
|
484
|
+
@@index([state, createdAt])
|
|
485
|
+
@@index([chatId, createdAt])
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
model TelegramConfirmation {
|
|
489
|
+
id String @id @default(cuid())
|
|
490
|
+
callbackToken String @unique
|
|
491
|
+
chatId String
|
|
492
|
+
userId String
|
|
493
|
+
updateId Int
|
|
494
|
+
description String
|
|
495
|
+
method String
|
|
496
|
+
path String
|
|
497
|
+
state String @default("pending") // pending | approved | denied | used | expired
|
|
498
|
+
expiresAt DateTime
|
|
499
|
+
createdAt DateTime @default(now())
|
|
500
|
+
approvedAt DateTime?
|
|
501
|
+
usedAt DateTime?
|
|
502
|
+
|
|
503
|
+
@@index([chatId, state])
|
|
504
|
+
@@index([expiresAt])
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
model TelegramAudit {
|
|
508
|
+
id String @id @default(cuid())
|
|
509
|
+
chatId String?
|
|
510
|
+
userId String?
|
|
511
|
+
updateId Int?
|
|
512
|
+
action String
|
|
513
|
+
outcome String
|
|
514
|
+
correlationId String?
|
|
515
|
+
method String?
|
|
516
|
+
path String?
|
|
517
|
+
statusCode Int?
|
|
518
|
+
createdAt DateTime @default(now())
|
|
519
|
+
|
|
520
|
+
@@index([chatId, createdAt])
|
|
521
|
+
@@index([updateId])
|
|
522
|
+
}
|
|
523
|
+
|
|
381
524
|
|
|
382
525
|
|
|
383
526
|
|