@straiffi/archon 1.2.34 → 1.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.
- package/dist/client/assets/TestsDialog-DelI4dOJ.js +5 -0
- package/dist/client/assets/arc-4YfDy8uK.js +1 -0
- package/dist/client/assets/architecture-7EHR7CIX-B0ldQ5d_.js +1 -0
- package/dist/client/assets/architectureDiagram-3BPJPVTR-Cn7GlwQg.js +36 -0
- package/dist/client/assets/array-DOVTz2Mq.js +1 -0
- package/dist/client/assets/blockDiagram-GPEHLZMM-Dbt3i35a.js +132 -0
- package/dist/client/assets/c4Diagram-AAUBKEIU-BCNsqu0u.js +10 -0
- package/dist/client/assets/channel-BmkYY3c1.js +1 -0
- package/dist/client/assets/chunk-2J33WTMH-B9c8AzpT.js +1 -0
- package/dist/client/assets/chunk-3OPIFGDE-D-qpTyaE.js +62 -0
- package/dist/client/assets/chunk-4BX2VUAB-B3mVWXS4.js +1 -0
- package/dist/client/assets/chunk-4EGX6M5U-DTB6Um9X.js +1 -0
- package/dist/client/assets/chunk-55IACEB6-BB-0ajVZ.js +1 -0
- package/dist/client/assets/chunk-5DO6E6H7-DtX6GYFY.js +1 -0
- package/dist/client/assets/chunk-5ZQYHXKU-bBV3HPCk.js +2 -0
- package/dist/client/assets/chunk-727SXJPM-InkxsEhY.js +206 -0
- package/dist/client/assets/chunk-AQP2D5EJ-DZZL694W.js +231 -0
- package/dist/client/assets/chunk-BR22UD5L-CkJbcXZG.js +1 -0
- package/dist/client/assets/chunk-BSJP7CBP-X4eyoSqE.js +1 -0
- package/dist/client/assets/chunk-CSCIHK7Q-BuAgybUd.js +124 -0
- package/dist/client/assets/chunk-FHYWG6QK-Cb5GzaCb.js +1 -0
- package/dist/client/assets/chunk-FMBD7UC4-mGY2D2YB.js +15 -0
- package/dist/client/assets/chunk-KSCS5N6A-B9fgatSq.js +10 -0
- package/dist/client/assets/chunk-L5ZTLDWV-L-7z2xOe.js +1 -0
- package/dist/client/assets/chunk-LZXEDZCA-hrScZnrx.js +2 -0
- package/dist/client/assets/chunk-MPE355IW-WT7jTCZh.js +1 -0
- package/dist/client/assets/chunk-MZUSXYTE-CClXfOSj.js +1 -0
- package/dist/client/assets/chunk-N66VUXT2-Bpe4yprw.js +1 -0
- package/dist/client/assets/chunk-ND2GUHAM-d2HjiRzD.js +1 -0
- package/dist/client/assets/chunk-NNHCCRGN-C4ci-Gd6.js +159 -0
- package/dist/client/assets/chunk-NZK2D7GU-C6cn05ZM.js +1 -0
- package/dist/client/assets/chunk-O5CBEL6O-BAjbtmB_.js +70 -0
- package/dist/client/assets/chunk-PUPMXCY4-Dh45WL5s.js +1 -0
- package/dist/client/assets/chunk-QZHKN3VN-U_l6-b5-.js +1 -0
- package/dist/client/assets/chunk-UIBZB4QT-Cp2xSKlH.js +1 -0
- package/dist/client/assets/chunk-WCWK7LTN-BOt5FFIu.js +1 -0
- package/dist/client/assets/chunk-WU5MYG2G-By4sIjXN.js +1 -0
- package/dist/client/assets/chunk-XPW4576I-YiT9fJFY.js +32 -0
- package/dist/client/assets/classDiagram-4FO5ZUOK-B9B9lIAo.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-DXR72HYe.js +1 -0
- package/dist/client/assets/cose-bilkent-S5V4N54A-CtC2zeMr.js +1 -0
- package/dist/client/assets/cytoscape.esm-DnmRtSj9.js +321 -0
- package/dist/client/assets/dagre-5AiD43Uu.js +1 -0
- package/dist/client/assets/dagre-BM42HDAG-_iu0KXos.js +4 -0
- package/dist/client/assets/defaultLocale-Ck2Xxk-C.js +1 -0
- package/dist/client/assets/diagram-2AECGRRQ-DyBAakP6.js +43 -0
- package/dist/client/assets/diagram-5GNKFQAL-xD8YOWp-.js +10 -0
- package/dist/client/assets/diagram-KO2AKTUF-BQDiusQc.js +3 -0
- package/dist/client/assets/diagram-LMA3HP47-BRu1DXcK.js +24 -0
- package/dist/client/assets/diagram-OG6HWLK6-C3A1wt8S.js +24 -0
- package/dist/client/assets/dist-BQjeO--f.js +1 -0
- package/dist/client/assets/erDiagram-TEJ5UH35-C_fWil4q.js +85 -0
- package/dist/client/assets/eventmodeling-FCH6USID-BczyucFk.js +1 -0
- package/dist/client/assets/flowDiagram-I6XJVG4X-CKsgXWad.js +162 -0
- package/dist/client/assets/ganttDiagram-6RSMTGT7-DRhmLmdi.js +292 -0
- package/dist/client/assets/gitGraph-WXDBUCRP-x5mlGyzr.js +1 -0
- package/dist/client/assets/gitGraphDiagram-PVQCEYII-C34Vr5C1.js +106 -0
- package/dist/client/assets/graphlib-CMVU3iJd.js +1 -0
- package/dist/client/assets/index-DENrWubs.js +260 -0
- package/dist/client/assets/index-iElL-crz.css +2 -0
- package/dist/client/assets/info-J43DQDTF-BsM_Qb70.js +1 -0
- package/dist/client/assets/infoDiagram-5YYISTIA-Bkbr_hQH.js +2 -0
- package/dist/client/assets/init-Bft5Ffpj.js +1 -0
- package/dist/client/assets/ishikawaDiagram-YF4QCWOH-CEXsy2hU.js +70 -0
- package/dist/client/assets/journeyDiagram-JHISSGLW-RuKnL83f.js +139 -0
- package/dist/client/assets/kanban-definition-UN3LZRKU-DrlhCmkA.js +89 -0
- package/dist/client/assets/katex-Bpz5kWH9.js +257 -0
- package/dist/client/assets/line-CGdxyPh9.js +1 -0
- package/dist/client/assets/linear-BYVhmsFj.js +1 -0
- package/dist/client/assets/mermaid-parser.core-CbzywbCW.js +4 -0
- package/dist/client/assets/mermaid.core-09FBpi2R.js +9 -0
- package/dist/client/assets/mindmap-definition-RKZ34NQL-CXrsI5b1.js +96 -0
- package/dist/client/assets/ordinal-DIg8h6NI.js +1 -0
- package/dist/client/assets/packet-YPE3B663-DeVIMHV5.js +1 -0
- package/dist/client/assets/path-DfRbCp9y.js +1 -0
- package/dist/client/assets/pie-LRSECV5Y-ByRF4_cj.js +1 -0
- package/dist/client/assets/pieDiagram-4H26LBE5-HbOpep9N.js +30 -0
- package/dist/client/assets/quadrantDiagram-W4KKPZXB-BWw-ZWMn.js +7 -0
- package/dist/client/assets/radar-GUYGQ44K-XEreg8aR.js +1 -0
- package/dist/client/assets/requirementDiagram-4Y6WPE33-CpscsQdI.js +84 -0
- package/dist/client/assets/rough.esm-DCvqWubr.js +1 -0
- package/dist/client/assets/sankeyDiagram-5OEKKPKP-BoV5tyAf.js +40 -0
- package/dist/client/assets/sequenceDiagram-3UESZ5HK-CBcDRtjR.js +162 -0
- package/dist/client/assets/src-BcaL9nCM.js +1 -0
- package/dist/client/assets/stateDiagram-AJRCARHV-Df9lcs70.js +1 -0
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-FIWIctC4.js +1 -0
- package/dist/client/assets/timeline-definition-PNZ67QCA-BFv1VICg.js +120 -0
- package/dist/client/assets/treeView-BLDUP644-D85P2Ji3.js +1 -0
- package/dist/client/assets/treemap-LRROVOQU-BnXG5utQ.js +1 -0
- package/dist/client/assets/vennDiagram-CIIHVFJN-DPRtn-XH.js +34 -0
- package/dist/client/assets/wardley-L42UT6IY-Ct9qHtJP.js +1 -0
- package/dist/client/assets/wardleyDiagram-YWT4CUSO-CDiint0P.js +78 -0
- package/dist/client/assets/xychartDiagram-2RQKCTM6-ELyFdgmG.js +7 -0
- package/dist/client/index.html +3 -4
- package/dist/server/db.js +92 -0
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +396 -123
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/agent.js +462 -0
- package/dist/server/lib/agent.js.map +1 -1
- package/dist/server/lib/attachments.js +146 -0
- package/dist/server/lib/attachments.js.map +1 -1
- package/dist/server/lib/buildFlow.js +2 -1
- package/dist/server/lib/buildFlow.js.map +1 -1
- package/dist/server/lib/chatOperations.js +2 -0
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/chats.js +9 -4
- package/dist/server/lib/chats.js.map +1 -1
- package/dist/server/lib/externalSource.js +32 -0
- package/dist/server/lib/externalSource.js.map +1 -0
- package/dist/server/lib/httpError.js +9 -0
- package/dist/server/lib/httpError.js.map +1 -0
- package/dist/server/lib/mobileAccess.js +3 -0
- package/dist/server/lib/mobileAccess.js.map +1 -1
- package/dist/server/lib/specArtifact.js +353 -0
- package/dist/server/lib/specArtifact.js.map +1 -0
- package/dist/server/lib/specDraft.js +33 -0
- package/dist/server/lib/specDraft.js.map +1 -0
- package/dist/server/lib/specExport.js +70 -0
- package/dist/server/lib/specExport.js.map +1 -0
- package/dist/server/lib/specFormatting.js +26 -0
- package/dist/server/lib/specFormatting.js.map +1 -0
- package/dist/server/lib/specMessages.js +79 -0
- package/dist/server/lib/specMessages.js.map +1 -0
- package/dist/server/lib/specOperations.js +171 -0
- package/dist/server/lib/specOperations.js.map +1 -0
- package/dist/server/lib/specSections.js +82 -0
- package/dist/server/lib/specSections.js.map +1 -0
- package/dist/server/lib/specs.js +347 -0
- package/dist/server/lib/specs.js.map +1 -0
- package/dist/server/lib/thinkingState.js +26 -0
- package/dist/server/lib/thinkingState.js.map +1 -1
- package/dist/server/lib/ticketBatch.js +55 -0
- package/dist/server/lib/ticketBatch.js.map +1 -0
- package/dist/server/lib/ticketDescriptionContract.js +52 -0
- package/dist/server/lib/ticketDescriptionContract.js.map +1 -0
- package/dist/server/lib/tickets.js +7 -3
- package/dist/server/lib/tickets.js.map +1 -1
- package/dist/server/workers/build.js +10 -1
- package/dist/server/workers/build.js.map +1 -1
- package/dist/server/workers/chat.js +10 -1
- package/dist/server/workers/chat.js.map +1 -1
- package/dist/server/workers/followUp.js +10 -1
- package/dist/server/workers/followUp.js.map +1 -1
- package/dist/server/workers/plan.js +10 -32
- package/dist/server/workers/plan.js.map +1 -1
- package/dist/server/workers/planFollowUp.js +10 -0
- package/dist/server/workers/planFollowUp.js.map +1 -1
- package/dist/server/workers/review.js +10 -1
- package/dist/server/workers/review.js.map +1 -1
- package/dist/server/workers/specSession.js +520 -0
- package/dist/server/workers/specSession.js.map +1 -0
- package/package.json +1 -1
- package/dist/client/assets/TestsDialog-1JPVtcz7.js +0 -5
- package/dist/client/assets/dropdown-menu-BULYW006.js +0 -43
- package/dist/client/assets/index-DGoXllNX.js +0 -150
- package/dist/client/assets/index-DoNUd8CK.css +0 -2
- /package/dist/client/assets/{rolldown-runtime-BYbx6iT9.js → chunk-BNv3lrIs.js} +0 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
const SPEC_ARTIFACT_TAG = 'archon-spec-artifact';
|
|
2
|
+
const SPEC_GRILL_QUESTION_TAG = 'archon-grill-question';
|
|
3
|
+
const normalizeRequiredString = (value) => {
|
|
4
|
+
if (typeof value !== 'string') {
|
|
5
|
+
return null;
|
|
6
|
+
}
|
|
7
|
+
const trimmed = value.trim();
|
|
8
|
+
return trimmed ? trimmed : null;
|
|
9
|
+
};
|
|
10
|
+
const normalizeStringArray = (value) => {
|
|
11
|
+
if (!Array.isArray(value)) {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
14
|
+
return value
|
|
15
|
+
.filter((item) => typeof item === 'string')
|
|
16
|
+
.map(item => item.trim())
|
|
17
|
+
.filter(Boolean);
|
|
18
|
+
};
|
|
19
|
+
const normalizeLikelyFiles = (value) => {
|
|
20
|
+
if (!Array.isArray(value)) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
return value
|
|
24
|
+
.filter((item) => typeof item === 'object' &&
|
|
25
|
+
item !== null &&
|
|
26
|
+
typeof item.path === 'string' &&
|
|
27
|
+
typeof item.reason === 'string')
|
|
28
|
+
.map(item => ({
|
|
29
|
+
path: item.path.trim(),
|
|
30
|
+
reason: item.reason.trim(),
|
|
31
|
+
}))
|
|
32
|
+
.filter(item => item.path && item.reason);
|
|
33
|
+
};
|
|
34
|
+
const normalizeSnapshotTickets = (value) => {
|
|
35
|
+
if (!Array.isArray(value)) {
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return value
|
|
39
|
+
.filter((item) => typeof item === 'object' &&
|
|
40
|
+
item !== null &&
|
|
41
|
+
typeof item.key === 'string' &&
|
|
42
|
+
typeof item.title === 'string' &&
|
|
43
|
+
typeof item.description === 'string')
|
|
44
|
+
.map(item => ({
|
|
45
|
+
key: item.key.trim(),
|
|
46
|
+
title: item.title.trim(),
|
|
47
|
+
description: item.description.trim(),
|
|
48
|
+
}))
|
|
49
|
+
.filter(item => item.key && item.title && item.description);
|
|
50
|
+
};
|
|
51
|
+
const normalizeSnapshotDependencies = (value) => {
|
|
52
|
+
if (!Array.isArray(value)) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
return value
|
|
56
|
+
.filter((item) => typeof item === 'object' &&
|
|
57
|
+
item !== null &&
|
|
58
|
+
typeof item.blocker_key === 'string' &&
|
|
59
|
+
typeof item.dependent_key === 'string')
|
|
60
|
+
.map(item => ({
|
|
61
|
+
blocker_key: item.blocker_key.trim(),
|
|
62
|
+
dependent_key: item.dependent_key.trim(),
|
|
63
|
+
}))
|
|
64
|
+
.filter(item => item.blocker_key && item.dependent_key && item.blocker_key !== item.dependent_key);
|
|
65
|
+
};
|
|
66
|
+
const stripSpecArtifactBlock = (output) => {
|
|
67
|
+
return output
|
|
68
|
+
.replace(new RegExp(`<\\s*${SPEC_ARTIFACT_TAG}\\s*>[\\s\\S]*?<\\s*/\\s*${SPEC_ARTIFACT_TAG}\\s*>`, 'g'), '')
|
|
69
|
+
.trim();
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Escape literal control characters (newlines, tabs, carriage returns) that appear
|
|
73
|
+
* inside JSON string values. LLMs frequently emit literal newlines inside multi-line
|
|
74
|
+
* string fields (e.g. mermaid diagrams, ticket descriptions), which causes JSON.parse
|
|
75
|
+
* to throw. This sanitizer walks the raw text tracking whether we're inside a string
|
|
76
|
+
* value and escapes only the control characters found there, leaving structural
|
|
77
|
+
* whitespace untouched.
|
|
78
|
+
*/
|
|
79
|
+
const sanitizeJsonControlChars = (raw) => {
|
|
80
|
+
let result = '';
|
|
81
|
+
let insideString = false;
|
|
82
|
+
let escaped = false;
|
|
83
|
+
for (let i = 0; i < raw.length; i++) {
|
|
84
|
+
const char = raw[i];
|
|
85
|
+
if (insideString) {
|
|
86
|
+
if (escaped) {
|
|
87
|
+
result += char;
|
|
88
|
+
escaped = false;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (char === '\\') {
|
|
92
|
+
result += char;
|
|
93
|
+
escaped = true;
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (char === '"') {
|
|
97
|
+
result += char;
|
|
98
|
+
insideString = false;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (char === '\n') {
|
|
102
|
+
result += '\\n';
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (char === '\r') {
|
|
106
|
+
result += '\\r';
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (char === '\t') {
|
|
110
|
+
result += '\\t';
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
result += char;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
if (char === '"') {
|
|
117
|
+
insideString = true;
|
|
118
|
+
}
|
|
119
|
+
result += char;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return result;
|
|
123
|
+
};
|
|
124
|
+
export const extractSpecArtifactFromOutput = (output) => {
|
|
125
|
+
const match = output.match(new RegExp(`<\\s*${SPEC_ARTIFACT_TAG}\\s*>([\\s\\S]*?)<\\s*/\\s*${SPEC_ARTIFACT_TAG}\\s*>`));
|
|
126
|
+
if (!match) {
|
|
127
|
+
return {
|
|
128
|
+
cleanedOutput: output.trim(),
|
|
129
|
+
artifact: null,
|
|
130
|
+
presence: null,
|
|
131
|
+
error: 'No spec artifact block found in planner response',
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
let parsed;
|
|
135
|
+
try {
|
|
136
|
+
const sanitized = sanitizeJsonControlChars(match[1].trim());
|
|
137
|
+
parsed = JSON.parse(sanitized);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return {
|
|
141
|
+
cleanedOutput: stripSpecArtifactBlock(output),
|
|
142
|
+
artifact: null,
|
|
143
|
+
presence: null,
|
|
144
|
+
error: 'Spec artifact block contains invalid JSON',
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
148
|
+
return {
|
|
149
|
+
cleanedOutput: stripSpecArtifactBlock(output),
|
|
150
|
+
artifact: null,
|
|
151
|
+
presence: null,
|
|
152
|
+
error: 'Spec artifact block does not contain a valid JSON object',
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
const summary = normalizeRequiredString(parsed.summary);
|
|
156
|
+
if (!summary) {
|
|
157
|
+
return {
|
|
158
|
+
cleanedOutput: stripSpecArtifactBlock(output),
|
|
159
|
+
artifact: null,
|
|
160
|
+
presence: null,
|
|
161
|
+
error: 'Spec artifact is missing required "summary" field',
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
const tickets = normalizeSnapshotTickets(parsed.tickets);
|
|
165
|
+
if (!tickets.length) {
|
|
166
|
+
return {
|
|
167
|
+
cleanedOutput: stripSpecArtifactBlock(output),
|
|
168
|
+
artifact: null,
|
|
169
|
+
presence: null,
|
|
170
|
+
error: 'Spec artifact is missing required "tickets" field',
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
// Presence is derived from the raw parsed value, before normalization, so the
|
|
174
|
+
// resolver can tell "LLM omitted this field" (carry forward) apart from "LLM
|
|
175
|
+
// emitted an empty array" (deliberate clear). Only well-formed arrays count as
|
|
176
|
+
// present; malformed values fall back to carry-forward to protect information.
|
|
177
|
+
const presence = {
|
|
178
|
+
assumptions: Array.isArray(parsed.assumptions),
|
|
179
|
+
openQuestions: Array.isArray(parsed.open_questions),
|
|
180
|
+
likelyFiles: Array.isArray(parsed.likely_files),
|
|
181
|
+
dependencies: Array.isArray(parsed.dependencies),
|
|
182
|
+
};
|
|
183
|
+
const artifact = {
|
|
184
|
+
summary,
|
|
185
|
+
assumptions: normalizeStringArray(parsed.assumptions),
|
|
186
|
+
openQuestions: normalizeStringArray(parsed.open_questions),
|
|
187
|
+
likelyFiles: normalizeLikelyFiles(parsed.likely_files),
|
|
188
|
+
tickets,
|
|
189
|
+
dependencies: normalizeSnapshotDependencies(parsed.dependencies),
|
|
190
|
+
};
|
|
191
|
+
return {
|
|
192
|
+
cleanedOutput: stripSpecArtifactBlock(output),
|
|
193
|
+
artifact,
|
|
194
|
+
presence,
|
|
195
|
+
error: null,
|
|
196
|
+
};
|
|
197
|
+
};
|
|
198
|
+
export const extractLastMermaidBlock = (output) => {
|
|
199
|
+
const matches = [...output.matchAll(/```mermaid\s*\n([\s\S]*?)```/g)];
|
|
200
|
+
if (matches.length === 0) {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
const lastMatch = matches[matches.length - 1];
|
|
204
|
+
return lastMatch[1] ? lastMatch[1].trim() : null;
|
|
205
|
+
};
|
|
206
|
+
export const stripMermaidBlocks = (output) => {
|
|
207
|
+
return output
|
|
208
|
+
.replace(/```mermaid\s*\n[\s\S]*?```/g, '')
|
|
209
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
210
|
+
.trim();
|
|
211
|
+
};
|
|
212
|
+
export const extractLastMockupBlock = (output) => {
|
|
213
|
+
const matches = [...output.matchAll(/```archon-mockup\s*\n([\s\S]*?)```/g)];
|
|
214
|
+
if (matches.length === 0) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
const lastMatch = matches[matches.length - 1];
|
|
218
|
+
const content = lastMatch[1] ? lastMatch[1].trim() : '';
|
|
219
|
+
return content ? content : null;
|
|
220
|
+
};
|
|
221
|
+
export const stripMockupBlocks = (output) => {
|
|
222
|
+
return output
|
|
223
|
+
.replace(/```archon-mockup\s*\n[\s\S]*?```/g, '')
|
|
224
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
225
|
+
.trim();
|
|
226
|
+
};
|
|
227
|
+
/**
|
|
228
|
+
* Resolve the mermaid/mockup values to persist for a turn. A block emitted in the
|
|
229
|
+
* current response overrides the previous snapshot's value; an omitted block is
|
|
230
|
+
* carried forward so established side-channel artifacts don't disappear when a
|
|
231
|
+
* follow-up turn produces a new snapshot without re-emitting them.
|
|
232
|
+
*/
|
|
233
|
+
export const resolveCarriedForwardArtifacts = ({ rawResponse, previousMermaid, previousMockup, }) => {
|
|
234
|
+
return {
|
|
235
|
+
mermaid: extractLastMermaidBlock(rawResponse) ?? previousMermaid ?? null,
|
|
236
|
+
mockup: extractLastMockupBlock(rawResponse) ?? previousMockup ?? null,
|
|
237
|
+
};
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Resolve the optional structured array fields to persist for a turn. A field
|
|
241
|
+
* the LLM explicitly emitted (presence true) overrides the previous snapshot's
|
|
242
|
+
* value — including an explicit empty array, which means "clear this field". A
|
|
243
|
+
* field the LLM omitted (presence false) is carried forward unchanged so
|
|
244
|
+
* follow-up turns never silently drop information that is still part of the
|
|
245
|
+
* spec. Summary and tickets are not handled here: summary is always taken from
|
|
246
|
+
* the current artifact, and tickets are required on every artifact so they can
|
|
247
|
+
* never be omitted.
|
|
248
|
+
*/
|
|
249
|
+
export const resolveCarriedForwardStructuredFields = ({ artifact, presence, previous, }) => {
|
|
250
|
+
return {
|
|
251
|
+
assumptions: presence.assumptions ? artifact.assumptions : (previous?.assumptions ?? []),
|
|
252
|
+
openQuestions: presence.openQuestions ? artifact.openQuestions : (previous?.openQuestions ?? []),
|
|
253
|
+
likelyFiles: presence.likelyFiles ? artifact.likelyFiles : (previous?.likelyFiles ?? []),
|
|
254
|
+
dependencies: presence.dependencies ? artifact.dependencies : (previous?.dependencies ?? []),
|
|
255
|
+
};
|
|
256
|
+
};
|
|
257
|
+
const stripGrillQuestionBlock = (output) => {
|
|
258
|
+
return output
|
|
259
|
+
.replace(new RegExp(`<\\s*${SPEC_GRILL_QUESTION_TAG}\\s*>[\\s\\S]*?<\\s*/\\s*${SPEC_GRILL_QUESTION_TAG}\\s*>`, 'g'), '')
|
|
260
|
+
.trim();
|
|
261
|
+
};
|
|
262
|
+
const normalizeGrillSuggestion = (value, fallbackId) => {
|
|
263
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
const raw = value;
|
|
267
|
+
const label = typeof raw.label === 'string' ? raw.label.trim() : '';
|
|
268
|
+
const stringValue = typeof raw.value === 'string' ? raw.value.trim() : '';
|
|
269
|
+
if (!label && !stringValue) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
const id = typeof raw.id === 'string' && raw.id.trim()
|
|
273
|
+
? raw.id.trim()
|
|
274
|
+
: fallbackId;
|
|
275
|
+
return {
|
|
276
|
+
id,
|
|
277
|
+
label: label || stringValue,
|
|
278
|
+
value: stringValue || label,
|
|
279
|
+
...(raw.recommended === true ? { recommended: true } : {}),
|
|
280
|
+
};
|
|
281
|
+
};
|
|
282
|
+
const normalizeGrillSuggestions = (value) => {
|
|
283
|
+
if (!Array.isArray(value)) {
|
|
284
|
+
return [];
|
|
285
|
+
}
|
|
286
|
+
const suggestions = [];
|
|
287
|
+
value.forEach((item, index) => {
|
|
288
|
+
const normalized = normalizeGrillSuggestion(item, `suggestion-${index + 1}`);
|
|
289
|
+
if (normalized) {
|
|
290
|
+
suggestions.push(normalized);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
return suggestions;
|
|
294
|
+
};
|
|
295
|
+
export const extractGrillQuestionFromOutput = (output) => {
|
|
296
|
+
if (!output) {
|
|
297
|
+
return {
|
|
298
|
+
cleanedOutput: '',
|
|
299
|
+
grillQuestion: null,
|
|
300
|
+
error: 'Empty grill output',
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
const match = output.match(new RegExp(`<\\s*${SPEC_GRILL_QUESTION_TAG}\\s*>([\\s\\S]*?)<\\s*/\\s*${SPEC_GRILL_QUESTION_TAG}\\s*>`));
|
|
304
|
+
if (!match) {
|
|
305
|
+
return {
|
|
306
|
+
cleanedOutput: output.trim(),
|
|
307
|
+
grillQuestion: null,
|
|
308
|
+
error: 'No grill question block found in planner response',
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
let parsed;
|
|
312
|
+
try {
|
|
313
|
+
const sanitized = sanitizeJsonControlChars(match[1].trim());
|
|
314
|
+
parsed = JSON.parse(sanitized);
|
|
315
|
+
}
|
|
316
|
+
catch {
|
|
317
|
+
return {
|
|
318
|
+
cleanedOutput: stripGrillQuestionBlock(output),
|
|
319
|
+
grillQuestion: null,
|
|
320
|
+
error: 'Grill question block contains invalid JSON',
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
324
|
+
return {
|
|
325
|
+
cleanedOutput: stripGrillQuestionBlock(output),
|
|
326
|
+
grillQuestion: null,
|
|
327
|
+
error: 'Grill question block does not contain a valid JSON object',
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
const question = normalizeRequiredString(parsed.question);
|
|
331
|
+
if (!question) {
|
|
332
|
+
return {
|
|
333
|
+
cleanedOutput: stripGrillQuestionBlock(output),
|
|
334
|
+
grillQuestion: null,
|
|
335
|
+
error: 'Grill question is missing required "question" field',
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
const suggestions = normalizeGrillSuggestions(parsed.suggestions);
|
|
339
|
+
const rationale = typeof parsed.rationale === 'string' && parsed.rationale.trim()
|
|
340
|
+
? parsed.rationale.trim()
|
|
341
|
+
: undefined;
|
|
342
|
+
const grillQuestion = {
|
|
343
|
+
question,
|
|
344
|
+
...(rationale ? { rationale } : {}),
|
|
345
|
+
suggestions,
|
|
346
|
+
};
|
|
347
|
+
return {
|
|
348
|
+
cleanedOutput: stripGrillQuestionBlock(output),
|
|
349
|
+
grillQuestion,
|
|
350
|
+
error: null,
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
//# sourceMappingURL=specArtifact.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specArtifact.js","sourceRoot":"","sources":["../../../server/lib/specArtifact.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { formatSpecSections } from './specSections.js';
|
|
2
|
+
/**
|
|
3
|
+
* Build a deterministic, editable draft prompt that seeds a build-mode chat session
|
|
4
|
+
* created from a spec snapshot. Returned to the client which writes it into the
|
|
5
|
+
* composer's localStorage draft slot without auto-submitting.
|
|
6
|
+
*
|
|
7
|
+
* The draft targets the build-mode chat agent. It intentionally omits the spec's
|
|
8
|
+
* `plan_text` (planning context): that field is process narrative for the spec
|
|
9
|
+
* session and does not help the build agent act. Verification guidance is not
|
|
10
|
+
* emitted at the wrapper level either — it lives inside each work item's
|
|
11
|
+
* description, mirroring how the plan worker folds `test_scope` into each ticket.
|
|
12
|
+
*/
|
|
13
|
+
const DRAFT_SECTION_ORDER = [
|
|
14
|
+
'likelyFiles',
|
|
15
|
+
'assumptions',
|
|
16
|
+
'openQuestions',
|
|
17
|
+
'workBreakdown',
|
|
18
|
+
'dependencies',
|
|
19
|
+
'visualization',
|
|
20
|
+
'uiMockup',
|
|
21
|
+
];
|
|
22
|
+
export const buildSpecImplementationDraft = ({ snapshot, specSession, }) => {
|
|
23
|
+
const sections = [];
|
|
24
|
+
sections.push(`Implement the spec below in this repository, using the work breakdown provided here. Treat each work item's Acceptance Criteria as the done-gate for that item.`);
|
|
25
|
+
sections.push(`**Why:** ${snapshot.summary || '_No summary provided._'}`);
|
|
26
|
+
const renderedSections = formatSpecSections(snapshot, DRAFT_SECTION_ORDER);
|
|
27
|
+
for (const section of renderedSections) {
|
|
28
|
+
sections.push(`## ${section.heading}\n\n${section.body}`);
|
|
29
|
+
}
|
|
30
|
+
sections.push(`_Originates from spec session: ${specSession.title}_`);
|
|
31
|
+
return sections.join('\n\n');
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=specDraft.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specDraft.js","sourceRoot":"","sources":["../../../server/lib/specDraft.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAuB,MAAM,mBAAmB,CAAA;AAG3E;;;;;;;;;;GAUG;AACH,MAAM,mBAAmB,GAAkC;IACzD,aAAa;IACb,aAAa;IACb,eAAe;IACf,eAAe;IACf,cAAc;IACd,eAAe;IACf,UAAU;CACX,CAAA;AAED,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC,EAC3C,QAAQ,EACR,WAAW,GAIZ,EAAU,EAAE;IACX,MAAM,QAAQ,GAAa,EAAE,CAAA;IAE7B,QAAQ,CAAC,IAAI,CAAC,iKAAiK,CAAC,CAAA;IAEhL,QAAQ,CAAC,IAAI,CAAC,YAAY,QAAQ,CAAC,OAAO,IAAI,wBAAwB,EAAE,CAAC,CAAA;IAEzE,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAA;IAC1E,KAAK,MAAM,OAAO,IAAI,gBAAgB,EAAE,CAAC;QACvC,QAAQ,CAAC,IAAI,CAAC,MAAM,OAAO,CAAC,OAAO,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IAC3D,CAAC;IAED,QAAQ,CAAC,IAAI,CAAC,kCAAkC,WAAW,CAAC,KAAK,GAAG,CAAC,CAAA;IAErE,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAC9B,CAAC,CAAA"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { formatSpecSections } from './specSections.js';
|
|
4
|
+
/**
|
|
5
|
+
* Build a human-readable markdown export of a spec snapshot for the project's
|
|
6
|
+
* `docs/plans` directory. The audience is a person reading the file in a
|
|
7
|
+
* markdown viewer, so Goal, Visualization, and UI Mockup are retained for
|
|
8
|
+
* orientation. `plan_text` (planning context) is omitted: it is process
|
|
9
|
+
* narrative about the spec session, not content a doc reader needs.
|
|
10
|
+
*
|
|
11
|
+
* Verification guidance is not surfaced at the wrapper level — each work item's
|
|
12
|
+
* description carries its own per-project testing guidance.
|
|
13
|
+
*/
|
|
14
|
+
const EXPORT_SECTION_ORDER = [
|
|
15
|
+
'workBreakdown',
|
|
16
|
+
'likelyFiles',
|
|
17
|
+
'assumptions',
|
|
18
|
+
'openQuestions',
|
|
19
|
+
'dependencies',
|
|
20
|
+
'visualization',
|
|
21
|
+
'uiMockup',
|
|
22
|
+
];
|
|
23
|
+
const buildSpecExportMarkdown = ({ snapshot, specSession, }) => {
|
|
24
|
+
const sections = [];
|
|
25
|
+
sections.push(`# ${specSession.title}`);
|
|
26
|
+
sections.push('');
|
|
27
|
+
sections.push(`## Goal`);
|
|
28
|
+
sections.push('');
|
|
29
|
+
sections.push(snapshot.summary || '_No summary provided._');
|
|
30
|
+
sections.push('');
|
|
31
|
+
const renderedSections = formatSpecSections(snapshot, EXPORT_SECTION_ORDER);
|
|
32
|
+
for (const section of renderedSections) {
|
|
33
|
+
sections.push(`## ${section.heading}`);
|
|
34
|
+
sections.push('');
|
|
35
|
+
sections.push(section.body);
|
|
36
|
+
sections.push('');
|
|
37
|
+
}
|
|
38
|
+
sections.push('---');
|
|
39
|
+
sections.push('');
|
|
40
|
+
sections.push(`_Exported from spec session "${specSession.title}" on ${new Date().toISOString().split('T')[0]}_`);
|
|
41
|
+
return sections.join('\n') + '\n';
|
|
42
|
+
};
|
|
43
|
+
const slugify = (text) => {
|
|
44
|
+
return text
|
|
45
|
+
.toLowerCase()
|
|
46
|
+
.replace(/[^a-z0-9]+/g, '_')
|
|
47
|
+
.replace(/^_+|_+$/g, '')
|
|
48
|
+
.slice(0, 80);
|
|
49
|
+
};
|
|
50
|
+
export const exportSpecToDocs = ({ snapshot, specSession, repoPath, }) => {
|
|
51
|
+
const docsDir = path.join(repoPath, 'docs', 'plans');
|
|
52
|
+
const slug = slugify(specSession.title) || 'spec';
|
|
53
|
+
const filename = `${slug}_SPEC.md`;
|
|
54
|
+
const filePath = path.join(docsDir, filename);
|
|
55
|
+
fs.mkdirSync(docsDir, { recursive: true });
|
|
56
|
+
const content = buildSpecExportMarkdown({ snapshot, specSession });
|
|
57
|
+
fs.writeFileSync(filePath, content, 'utf-8');
|
|
58
|
+
return { content, filePath };
|
|
59
|
+
};
|
|
60
|
+
export const checkSpecExportCollision = ({ specSession, repoPath, }) => {
|
|
61
|
+
const docsDir = path.join(repoPath, 'docs', 'plans');
|
|
62
|
+
const slug = slugify(specSession.title) || 'spec';
|
|
63
|
+
const filename = `${slug}_SPEC.md`;
|
|
64
|
+
const filePath = path.join(docsDir, filename);
|
|
65
|
+
if (fs.existsSync(filePath)) {
|
|
66
|
+
return filePath;
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=specExport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specExport.js","sourceRoot":"","sources":["../../../server/lib/specExport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const NO_CONTENT = '_None_';
|
|
2
|
+
export const formatBulletList = (items) => {
|
|
3
|
+
if (items.length === 0) {
|
|
4
|
+
return NO_CONTENT;
|
|
5
|
+
}
|
|
6
|
+
return items.map(item => `- ${item}`).join('\n');
|
|
7
|
+
};
|
|
8
|
+
export const formatLikelyFiles = (files) => {
|
|
9
|
+
if (files.length === 0) {
|
|
10
|
+
return NO_CONTENT;
|
|
11
|
+
}
|
|
12
|
+
return files.map(file => `- \`${file.path}\` — ${file.reason || 'no reason provided'}`).join('\n');
|
|
13
|
+
};
|
|
14
|
+
export const formatWorkItems = (tickets) => {
|
|
15
|
+
if (tickets.length === 0) {
|
|
16
|
+
return NO_CONTENT;
|
|
17
|
+
}
|
|
18
|
+
return tickets.map(ticket => `### ${ticket.key} — ${ticket.title}\n\n${ticket.description}`).join('\n\n');
|
|
19
|
+
};
|
|
20
|
+
export const formatDependencies = (dependencies) => {
|
|
21
|
+
if (dependencies.length === 0) {
|
|
22
|
+
return NO_CONTENT;
|
|
23
|
+
}
|
|
24
|
+
return dependencies.map(dep => `- \`${dep.blocker_key}\` blocks \`${dep.dependent_key}\``).join('\n');
|
|
25
|
+
};
|
|
26
|
+
//# sourceMappingURL=specFormatting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specFormatting.js","sourceRoot":"","sources":["../../../server/lib/specFormatting.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG,QAAQ,CAAA;AAE3B,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAA4B,EAAU,EAAE;IACvE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AAClD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAmC,EAAU,EAAE;IAC/E,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,MAAM,IAAI,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACpG,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAgC,EAAU,EAAE;IAC1E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,KAAK,OAAO,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;AAC3G,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,YAA0C,EAAU,EAAE;IACvF,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,UAAU,CAAA;IACnB,CAAC;IAED,OAAO,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,GAAG,CAAC,WAAW,eAAe,GAAG,CAAC,aAAa,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACvG,CAAC,CAAA"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import db from '../db.js';
|
|
3
|
+
import { listSpecMessageAttachments } from './attachments.js';
|
|
4
|
+
const parseSpecMessageMetadata = (value) => {
|
|
5
|
+
if (!value) {
|
|
6
|
+
return undefined;
|
|
7
|
+
}
|
|
8
|
+
try {
|
|
9
|
+
const parsed = JSON.parse(value);
|
|
10
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
return parsed;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const listSpecMessagesStatement = db.prepare(`
|
|
20
|
+
SELECT id, spec_session_id, role, kind, content, metadata_json, created_at
|
|
21
|
+
FROM spec_messages
|
|
22
|
+
WHERE spec_session_id = ?
|
|
23
|
+
ORDER BY created_at ASC, rowid ASC
|
|
24
|
+
`);
|
|
25
|
+
const insertSpecMessageStatement = db.prepare(`
|
|
26
|
+
INSERT INTO spec_messages (id, spec_session_id, role, kind, content, metadata_json)
|
|
27
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
28
|
+
`);
|
|
29
|
+
const getSpecMessageStatement = db.prepare(`
|
|
30
|
+
SELECT id, spec_session_id, role, kind, content, metadata_json, created_at
|
|
31
|
+
FROM spec_messages
|
|
32
|
+
WHERE id = ?
|
|
33
|
+
`);
|
|
34
|
+
const touchSpecSessionStatement = db.prepare(`
|
|
35
|
+
UPDATE spec_sessions
|
|
36
|
+
SET updated_at = CURRENT_TIMESTAMP
|
|
37
|
+
WHERE id = ?
|
|
38
|
+
`);
|
|
39
|
+
export const listSpecMessages = (specSessionId, projectId) => {
|
|
40
|
+
const attachmentsByMessageId = listSpecMessageAttachments(specSessionId, projectId);
|
|
41
|
+
return listSpecMessagesStatement.all(specSessionId).map(row => {
|
|
42
|
+
const metadata = parseSpecMessageMetadata(row.metadata_json);
|
|
43
|
+
return {
|
|
44
|
+
id: row.id,
|
|
45
|
+
spec_session_id: row.spec_session_id,
|
|
46
|
+
role: row.role,
|
|
47
|
+
kind: row.kind,
|
|
48
|
+
content: row.content,
|
|
49
|
+
...(metadata ? { metadata } : {}),
|
|
50
|
+
attachments: attachmentsByMessageId.get(row.id) ?? [],
|
|
51
|
+
created_at: row.created_at,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
export const getSpecMessage = (specMessageId) => {
|
|
56
|
+
const row = getSpecMessageStatement.get(specMessageId);
|
|
57
|
+
if (!row) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const metadata = parseSpecMessageMetadata(row.metadata_json);
|
|
61
|
+
return {
|
|
62
|
+
id: row.id,
|
|
63
|
+
spec_session_id: row.spec_session_id,
|
|
64
|
+
role: row.role,
|
|
65
|
+
kind: row.kind,
|
|
66
|
+
content: row.content,
|
|
67
|
+
...(metadata ? { metadata } : {}),
|
|
68
|
+
attachments: [],
|
|
69
|
+
created_at: row.created_at,
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
export const createSpecMessage = ({ specSessionId, role, kind, content, metadata, }) => {
|
|
73
|
+
const id = randomUUID();
|
|
74
|
+
const metadataJson = metadata ? JSON.stringify(metadata) : null;
|
|
75
|
+
insertSpecMessageStatement.run(id, specSessionId, role, kind, content, metadataJson);
|
|
76
|
+
touchSpecSessionStatement.run(specSessionId);
|
|
77
|
+
return id;
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=specMessages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"specMessages.js","sourceRoot":"","sources":["../../../server/lib/specMessages.ts"],"names":[],"mappings":"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"}
|