@straiffi/archon 1.4.6 → 1.4.8
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/GitHubActionsDialog-ln1X9xDf.js +1 -0
- package/dist/client/assets/TestsDialog-Cp3Da2W0.js +5 -0
- package/dist/client/assets/{arc-4YfDy8uK.js → arc-CnuHRbeq.js} +1 -1
- package/dist/client/assets/architecture-7EHR7CIX-tSrokdFP.js +1 -0
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-B0ybRTUn.js → architectureDiagram-3BPJPVTR-CFEtd9pl.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DrrQouTh.js → blockDiagram-GPEHLZMM-9UsBOlSn.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BJdqjAbL.js → c4Diagram-AAUBKEIU--TsvWn6X.js} +1 -1
- package/dist/client/assets/channel-BjRPoR7Z.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-Dh6TqsDY.js → chunk-2J33WTMH-B3FphDWz.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-BI6L9trS.js → chunk-3OPIFGDE-CLbUIPKK.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-B3mVWXS4.js → chunk-4BX2VUAB-_WBpCe0m.js} +1 -1
- package/dist/client/assets/{chunk-4EGX6M5U-DTB6Um9X.js → chunk-4EGX6M5U-BBQHxMeA.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-BB-0ajVZ.js → chunk-55IACEB6-B-d-YzxI.js} +1 -1
- package/dist/client/assets/{chunk-5DO6E6H7-DtX6GYFY.js → chunk-5DO6E6H7-BA-oSVa-.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-mt5W2CGF.js → chunk-5ZQYHXKU-CUHKY5eH.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-D7IvpFAq.js → chunk-727SXJPM-DfKJ4Ud0.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CjusndWN.js → chunk-AQP2D5EJ-B0oLVoZs.js} +1 -1
- package/dist/client/assets/{chunk-BR22UD5L-CkJbcXZG.js → chunk-BR22UD5L-prWX503j.js} +1 -1
- package/dist/client/assets/{chunk-BSJP7CBP-X4eyoSqE.js → chunk-BSJP7CBP-CNtf2uaW.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-BmXd8_5X.js → chunk-CSCIHK7Q-Czl8GWBW.js} +2 -2
- package/dist/client/assets/{chunk-FHYWG6QK-Cb5GzaCb.js → chunk-FHYWG6QK-BQ8n0J0S.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-mGY2D2YB.js → chunk-FMBD7UC4-CWQN4V4s.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-DJIqk8ji.js → chunk-KSCS5N6A-pOOnuun_.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-CRVFCsvJ.js → chunk-L5ZTLDWV-DzRVeTqf.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-CRla8IXQ.js → chunk-LZXEDZCA-MVhzvLVp.js} +2 -2
- package/dist/client/assets/{chunk-MPE355IW-WT7jTCZh.js → chunk-MPE355IW-gHN8AuU_.js} +1 -1
- package/dist/client/assets/{chunk-MZUSXYTE-CClXfOSj.js → chunk-MZUSXYTE-Clzaz1kK.js} +1 -1
- package/dist/client/assets/{chunk-N66VUXT2-Bpe4yprw.js → chunk-N66VUXT2-CkkAOkdt.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-BYAb7NsA.js → chunk-ND2GUHAM-BeNiy3nE.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-DUI0mwZm.js → chunk-NZK2D7GU-CnENvQ9d.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-BX5VWTmZ.js → chunk-O5CBEL6O-CkqDMX_f.js} +1 -1
- package/dist/client/assets/{chunk-PUPMXCY4-Dh45WL5s.js → chunk-PUPMXCY4-DAdQFv8j.js} +1 -1
- package/dist/client/assets/chunk-QZHKN3VN-biOr9EeQ.js +1 -0
- package/dist/client/assets/{chunk-UIBZB4QT-Cp2xSKlH.js → chunk-UIBZB4QT-BRR84OYN.js} +1 -1
- package/dist/client/assets/{chunk-WCWK7LTN-BOt5FFIu.js → chunk-WCWK7LTN-CQU7Fs_W.js} +1 -1
- package/dist/client/assets/chunk-WU5MYG2G-sJ18xVVM.js +1 -0
- package/dist/client/assets/{chunk-XPW4576I-YiT9fJFY.js → chunk-XPW4576I-DafcxlUi.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BjzBLL5f.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BDLW6NLv.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-CtC2zeMr.js → cose-bilkent-S5V4N54A-DhJHP9hr.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-CqGwgHpm.js → dagre-BM42HDAG-BWnmF2aL.js} +1 -1
- package/dist/client/assets/{dagre-5AiD43Uu.js → dagre-CdwzCXQr.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-W2M_p8Yv.js → diagram-2AECGRRQ-CASRQI5Y.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-Cl9Hh0jb.js → diagram-5GNKFQAL-CY8fXRrV.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-Cn0-x5HI.js → diagram-KO2AKTUF-vtm-gqIm.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-BH2_JbrM.js → diagram-LMA3HP47-Ck-iA5q1.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-DuSmDdz3.js → diagram-OG6HWLK6-ALBEY2Nn.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-DMHLFeQs.js → erDiagram-TEJ5UH35-BAHPzYR7.js} +1 -1
- package/dist/client/assets/eventmodeling-FCH6USID-DapHLQIh.js +1 -0
- package/dist/client/assets/{flowDiagram-I6XJVG4X-G6q9UKR3.js → flowDiagram-I6XJVG4X-pUYj1KCo.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-hhWmmnFi.js → ganttDiagram-6RSMTGT7-zw-EKZcX.js} +1 -1
- package/dist/client/assets/gitGraph-WXDBUCRP-BTBN_hfb.js +1 -0
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CvmZJ3zf.js → gitGraphDiagram-PVQCEYII-DmPxQKXO.js} +1 -1
- package/dist/client/assets/index-BokL1E46.css +2 -0
- package/dist/client/assets/index-WeECH1eZ.js +260 -0
- package/dist/client/assets/info-J43DQDTF-CgiMJYKF.js +1 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-BIes94lQ.js → infoDiagram-5YYISTIA-D0zuFK8l.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-1sUDbjPm.js → ishikawaDiagram-YF4QCWOH-BoNe_Ie6.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-BEEP6Na-.js → journeyDiagram-JHISSGLW-ByAP1uL0.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-CPFego8B.js → kanban-definition-UN3LZRKU-CGXOqdl0.js} +1 -1
- package/dist/client/assets/{line-BdjuNfVr.js → line-BZ3JWBtG.js} +1 -1
- package/dist/client/assets/{linear-BYVhmsFj.js → linear-DFIW-KnM.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-ep6OPAQm.js → mermaid-parser.core-DuHIifHL.js} +2 -2
- package/dist/client/assets/{mermaid.core-CgiGEZhy.js → mermaid.core-Co8EqKSU.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-0hOE50-8.js → mindmap-definition-RKZ34NQL-Cv3-5Q_b.js} +1 -1
- package/dist/client/assets/{ordinal-DIg8h6NI.js → ordinal-C1FS1Sfe.js} +1 -1
- package/dist/client/assets/packet-YPE3B663-Bnwqjena.js +1 -0
- package/dist/client/assets/pie-LRSECV5Y-Ctj0ef-4.js +1 -0
- package/dist/client/assets/{pieDiagram-4H26LBE5-BEgccEEE.js → pieDiagram-4H26LBE5-DziVyTJT.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CvDyAdJI.js → quadrantDiagram-W4KKPZXB-DjNtV4An.js} +1 -1
- package/dist/client/assets/radar-GUYGQ44K-DE0H_saz.js +1 -0
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-DSmztQBO.js → requirementDiagram-4Y6WPE33-Cs3npD-z.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-DgDUHUAw.js → sankeyDiagram-5OEKKPKP-DxepDJwc.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BYaYgN0W.js → sequenceDiagram-3UESZ5HK-DIPg-NEj.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CqU_4LpV.js → stateDiagram-AJRCARHV-DUA-Ko9b.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-D6OlcyEp.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-BTYLNo8J.js → timeline-definition-PNZ67QCA-wvi8pREg.js} +1 -1
- package/dist/client/assets/treeView-BLDUP644-CSAZL2OH.js +1 -0
- package/dist/client/assets/treemap-LRROVOQU-tYm4XKfP.js +1 -0
- package/dist/client/assets/{vennDiagram-CIIHVFJN-C-MV8-cy.js → vennDiagram-CIIHVFJN-CabtIweB.js} +1 -1
- package/dist/client/assets/wardley-L42UT6IY-DdiEFppm.js +1 -0
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BOZ5g5Fn.js → wardleyDiagram-YWT4CUSO-BiOWydTY.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-6wYwr3vn.js → xychartDiagram-2RQKCTM6-sWfRgDRl.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/server/db.js +114 -9
- package/dist/server/db.js.map +1 -1
- package/dist/server/index.js +409 -5
- package/dist/server/index.js.map +1 -1
- package/dist/server/lib/attachments.js +36 -26
- package/dist/server/lib/attachments.js.map +1 -1
- package/dist/server/lib/chatOperations.js +6 -0
- package/dist/server/lib/chatOperations.js.map +1 -1
- package/dist/server/lib/chats.js +2 -2
- package/dist/server/lib/chats.js.map +1 -1
- package/dist/server/lib/integrations/assignedIssues.js +21 -9
- package/dist/server/lib/integrations/assignedIssues.js.map +1 -1
- package/dist/server/lib/integrations/github-issues.js +107 -12
- package/dist/server/lib/integrations/github-issues.js.map +1 -1
- package/dist/server/lib/integrations/github.js +10 -0
- package/dist/server/lib/integrations/github.js.map +1 -1
- package/dist/server/lib/integrations/githubActions.js +266 -0
- package/dist/server/lib/integrations/githubActions.js.map +1 -0
- package/dist/server/lib/integrations/githubActionsSessions.js +168 -0
- package/dist/server/lib/integrations/githubActionsSessions.js.map +1 -0
- package/dist/server/lib/integrations/importedIssueImages.js +210 -0
- package/dist/server/lib/integrations/importedIssueImages.js.map +1 -0
- package/dist/server/lib/integrations/jira.js +132 -21
- package/dist/server/lib/integrations/jira.js.map +1 -1
- package/dist/server/lib/specOperations.js +11 -0
- package/dist/server/lib/specOperations.js.map +1 -1
- package/dist/server/lib/specs.js +2 -7
- package/dist/server/lib/specs.js.map +1 -1
- package/dist/server/lib/ticketWorkflowOperations.js +6 -0
- package/dist/server/lib/ticketWorkflowOperations.js.map +1 -1
- package/dist/server/lib/trackedExternalIssues.js +33 -0
- package/dist/server/lib/trackedExternalIssues.js.map +1 -0
- package/package.json +2 -1
- package/dist/client/assets/TestsDialog-Vy9cdwzA.js +0 -5
- package/dist/client/assets/architecture-7EHR7CIX-B0ldQ5d_.js +0 -1
- package/dist/client/assets/channel-B3iXJSit.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-U_l6-b5-.js +0 -1
- package/dist/client/assets/chunk-WU5MYG2G-xHcJhj1C.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-BvskNpH1.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B1-Afdak.js +0 -1
- package/dist/client/assets/eventmodeling-FCH6USID-BczyucFk.js +0 -1
- package/dist/client/assets/gitGraph-WXDBUCRP-x5mlGyzr.js +0 -1
- package/dist/client/assets/index-CT3aYWb0.js +0 -260
- package/dist/client/assets/index-D6gWjd6J.css +0 -2
- package/dist/client/assets/info-J43DQDTF-BsM_Qb70.js +0 -1
- package/dist/client/assets/packet-YPE3B663-DeVIMHV5.js +0 -1
- package/dist/client/assets/pie-LRSECV5Y-ByRF4_cj.js +0 -1
- package/dist/client/assets/radar-GUYGQ44K-XEreg8aR.js +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-C_J0aecM.js +0 -1
- package/dist/client/assets/treeView-BLDUP644-D85P2Ji3.js +0 -1
- package/dist/client/assets/treemap-LRROVOQU-BnXG5utQ.js +0 -1
- package/dist/client/assets/wardley-L42UT6IY-Ct9qHtJP.js +0 -1
- /package/dist/client/assets/{array-DOVTz2Mq.js → array-B57E4cSs.js} +0 -0
- /package/dist/client/assets/{chunk-NNHCCRGN-C4ci-Gd6.js → chunk-NNHCCRGN-DRSAMe5H.js} +0 -0
- /package/dist/client/assets/{cytoscape.esm-DnmRtSj9.js → cytoscape.esm-CVYSm6AJ.js} +0 -0
- /package/dist/client/assets/{defaultLocale-Ck2Xxk-C.js → defaultLocale-6WHJ3B09.js} +0 -0
- /package/dist/client/assets/{dist-BQjeO--f.js → dist-By2zKKTF.js} +0 -0
- /package/dist/client/assets/{graphlib-CMVU3iJd.js → graphlib-B0DVs0bw.js} +0 -0
- /package/dist/client/assets/{init-Bft5Ffpj.js → init-DiYCGS1R.js} +0 -0
- /package/dist/client/assets/{katex-Bpz5kWH9.js → katex-bgJu_0Fy.js} +0 -0
- /package/dist/client/assets/{path-DfRbCp9y.js → path-DL_QDy2X.js} +0 -0
- /package/dist/client/assets/{rough.esm-DCvqWubr.js → rough.esm-Bbn_-PMU.js} +0 -0
- /package/dist/client/assets/{src-BcaL9nCM.js → src-Bi_byJUe.js} +0 -0
package/dist/server/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { adjectives, animals, uniqueNamesGenerator } from 'unique-names-generato
|
|
|
10
10
|
import db from './db.js';
|
|
11
11
|
import { deleteChatSession, getChatSession, listChatSessions, updateChatSessionMode } from './lib/chats.js';
|
|
12
12
|
import { deleteSpecSession, getCreatedTicketIdsForSnapshot, getSpecSession, getSpecSnapshot, listSpecSessions } from './lib/specs.js';
|
|
13
|
-
import { createChatAttachment, createSpecAttachment, deleteChatAttachment, deleteSpecSessionAttachment,
|
|
13
|
+
import { createChatAttachment, createSpecAttachment, getAttachmentById, deleteChatAttachment, deleteSpecSessionAttachment, getChatAttachmentForSession, getChatAttachmentLinkedMessageId, getSpecAttachmentForSession, getSpecAttachmentLinkedMessageId, MAX_CHAT_ATTACHMENTS_PER_TURN, MAX_CHAT_ATTACHMENT_SIZE_BYTES, MAX_SPEC_ATTACHMENTS_PER_TURN, MAX_SPEC_ATTACHMENT_SIZE_BYTES, readChatAttachmentContent, readSpecAttachmentContent, validateImageAttachment, } from './lib/attachments.js';
|
|
14
14
|
import { createProjectChatSession, resolveChatMode, resolveChatTool, stopProjectChatSessionResponse, submitProjectChatSessionMessage, } from './lib/chatOperations.js';
|
|
15
15
|
import { createProjectSpecSession, deleteProjectSpecSession, stopProjectSpecSessionResponse, submitProjectSpecSessionMessage, updateProjectSpecSessionMode, } from './lib/specOperations.js';
|
|
16
16
|
import { buildProjectSpecReviewRevisionDraft, getProjectSpecReviewFindings, startProjectSpecReview, stopProjectSpecReview, } from './lib/specReviewOperations.js';
|
|
@@ -49,8 +49,11 @@ import { shutdownRealtimeServer } from './lib/shutdown.js';
|
|
|
49
49
|
import { resolveClientBuildPaths, shouldServeClientApp, STATIC_CLIENT_DIRECTORY_OPTIONS, STATIC_CLIENT_INDEX_OPTIONS, } from './lib/staticClient.js';
|
|
50
50
|
import { deleteIntegrationConnection, getGitHubConnectionConfig, getJiraConnectionConfig, listIntegrationConnections, upsertIntegrationConnection, } from './lib/integrations/index.js';
|
|
51
51
|
import { createGitHubPullRequest, createOrFindGitHubPullRequest, findOpenGitHubPullRequest, findOpenGitHubPullRequestByHeadBranch, getGitHubPullRequestComments, getGitHubPullRequestReviews, getGitHubPullRequest, GitHubApiError, hasGitHubRemoteBranch, resolveGitHubRepository, validateGitHubConnection, } from './lib/integrations/github.js';
|
|
52
|
-
import { importJiraIssue, JiraApiError, validateJiraConnection } from './lib/integrations/jira.js';
|
|
53
|
-
import { importGitHubIssue } from './lib/integrations/github-issues.js';
|
|
52
|
+
import { importJiraIssue, JiraApiError, prepareJiraIssueImport, validateJiraConnection } from './lib/integrations/jira.js';
|
|
53
|
+
import { importGitHubIssue, prepareGitHubIssueImport } from './lib/integrations/github-issues.js';
|
|
54
|
+
import { buildImportedIssueSessionTitle, importProviderHostedIssueImages } from './lib/integrations/importedIssueImages.js';
|
|
55
|
+
import { dispatchGitHubWorkflow, getGitHubWorkflowDispatchConfig, getGitHubWorkflowRun, getGitHubWorkflowRunJobs, listGitHubWorkflows, listGitHubWorkflowRuns, } from './lib/integrations/githubActions.js';
|
|
56
|
+
import { clearAllGitHubActionsSessions, getActiveTrackedRunCount, getTrackedGitHubActionsRuns, trackGitHubActionsRun, } from './lib/integrations/githubActionsSessions.js';
|
|
54
57
|
import { PlanningReferenceError, resolveExternalPlanningDescription } from './lib/integrations/planning.js';
|
|
55
58
|
import { refreshIfNeeded as refreshAssignedIssues, clearCachedAssignedIssues } from './lib/integrations/assignedIssuesCache.js';
|
|
56
59
|
import { buildCommitMessagePrompt, normalizeGeneratedCommitMessage } from './lib/commitMessage.js';
|
|
@@ -2066,7 +2069,7 @@ app.post('/projects/:id/chat-sessions/:sessionId/attachments', (req, res) => {
|
|
|
2066
2069
|
}
|
|
2067
2070
|
catch (uploadError) {
|
|
2068
2071
|
for (const attachmentId of createdAttachmentIds) {
|
|
2069
|
-
const attachment =
|
|
2072
|
+
const attachment = getAttachmentById(attachmentId);
|
|
2070
2073
|
if (!attachment) {
|
|
2071
2074
|
continue;
|
|
2072
2075
|
}
|
|
@@ -2351,7 +2354,7 @@ app.post('/projects/:id/spec-sessions/:sessionId/attachments', (req, res) => {
|
|
|
2351
2354
|
}
|
|
2352
2355
|
catch (uploadError) {
|
|
2353
2356
|
for (const attachmentId of createdAttachmentIds) {
|
|
2354
|
-
const attachment =
|
|
2357
|
+
const attachment = getAttachmentById(attachmentId);
|
|
2355
2358
|
if (!attachment) {
|
|
2356
2359
|
continue;
|
|
2357
2360
|
}
|
|
@@ -3578,6 +3581,76 @@ app.get('/integrations', (req, res) => {
|
|
|
3578
3581
|
}
|
|
3579
3582
|
return res.json({ connections: listIntegrationConnections(result.project.id) });
|
|
3580
3583
|
});
|
|
3584
|
+
const NOOP_BROADCASTER = {
|
|
3585
|
+
emit: () => undefined,
|
|
3586
|
+
};
|
|
3587
|
+
const buildSpecImportSessionPayload = (payload, draft) => {
|
|
3588
|
+
return {
|
|
3589
|
+
tool: payload?.tool,
|
|
3590
|
+
mode: payload?.mode,
|
|
3591
|
+
model: payload?.model,
|
|
3592
|
+
variant: payload?.variant,
|
|
3593
|
+
skills: payload?.skills,
|
|
3594
|
+
title: buildImportedIssueSessionTitle(draft),
|
|
3595
|
+
external_source: draft.external_source,
|
|
3596
|
+
};
|
|
3597
|
+
};
|
|
3598
|
+
const prepareSpecImportResponse = async ({ projectId, payload, preparedDraft, importOptions, broadcaster, }) => {
|
|
3599
|
+
const draft = {
|
|
3600
|
+
title: preparedDraft.title,
|
|
3601
|
+
description: preparedDraft.description,
|
|
3602
|
+
external_source: preparedDraft.external_source,
|
|
3603
|
+
};
|
|
3604
|
+
const imported = await importProviderHostedIssueImages({
|
|
3605
|
+
...importOptions,
|
|
3606
|
+
draft,
|
|
3607
|
+
imageCandidates: preparedDraft.image_candidates,
|
|
3608
|
+
});
|
|
3609
|
+
if (imported.importedImages.length === 0) {
|
|
3610
|
+
return {
|
|
3611
|
+
draft,
|
|
3612
|
+
prompt_text: imported.promptText,
|
|
3613
|
+
external_source: draft.external_source,
|
|
3614
|
+
spec_session: null,
|
|
3615
|
+
imported_attachments: [],
|
|
3616
|
+
import_notice: imported.notice,
|
|
3617
|
+
};
|
|
3618
|
+
}
|
|
3619
|
+
const createResult = createProjectSpecSession({
|
|
3620
|
+
projectId,
|
|
3621
|
+
payload: buildSpecImportSessionPayload(payload, draft),
|
|
3622
|
+
broadcaster: NOOP_BROADCASTER,
|
|
3623
|
+
});
|
|
3624
|
+
if (!createResult.ok) {
|
|
3625
|
+
throw new HttpError(createResult.status, createResult.error);
|
|
3626
|
+
}
|
|
3627
|
+
if (!createResult.value) {
|
|
3628
|
+
throw new Error('Unable to create the imported spec session.');
|
|
3629
|
+
}
|
|
3630
|
+
const specSession = createResult.value;
|
|
3631
|
+
try {
|
|
3632
|
+
const importedAttachments = imported.importedImages.map(image => createSpecAttachment({
|
|
3633
|
+
specSessionId: specSession.id,
|
|
3634
|
+
originalName: image.originalName,
|
|
3635
|
+
mimeType: image.mimeType,
|
|
3636
|
+
buffer: image.buffer,
|
|
3637
|
+
projectId,
|
|
3638
|
+
}));
|
|
3639
|
+
broadcaster.emit('spec-session:created', specSession);
|
|
3640
|
+
return {
|
|
3641
|
+
draft,
|
|
3642
|
+
prompt_text: imported.promptText,
|
|
3643
|
+
external_source: draft.external_source,
|
|
3644
|
+
spec_session: specSession,
|
|
3645
|
+
imported_attachments: importedAttachments,
|
|
3646
|
+
import_notice: imported.notice,
|
|
3647
|
+
};
|
|
3648
|
+
}
|
|
3649
|
+
catch (error) {
|
|
3650
|
+
deleteSpecSession(specSession.id);
|
|
3651
|
+
throw error;
|
|
3652
|
+
}
|
|
3653
|
+
};
|
|
3581
3654
|
app.post('/integrations/github/connect', async (req, res) => {
|
|
3582
3655
|
const result = getRequiredProject(req);
|
|
3583
3656
|
if ('error' in result) {
|
|
@@ -3749,6 +3822,77 @@ app.post('/integrations/jira/resolve/issue', async (req, res) => {
|
|
|
3749
3822
|
return res.status(500).json({ error: getErrorMessage(error) || 'Unable to import the Jira issue.' });
|
|
3750
3823
|
}
|
|
3751
3824
|
});
|
|
3825
|
+
app.post('/integrations/jira/prepare-spec-import', async (req, res) => {
|
|
3826
|
+
const result = getRequiredProject(req);
|
|
3827
|
+
if ('error' in result) {
|
|
3828
|
+
return res.status(400).json({ error: result.error });
|
|
3829
|
+
}
|
|
3830
|
+
const jiraConfig = getJiraConnectionConfig(result.project.id);
|
|
3831
|
+
if (!jiraConfig) {
|
|
3832
|
+
return res.status(400).json({ error: 'Jira is not connected for this project.' });
|
|
3833
|
+
}
|
|
3834
|
+
const issue = asTrimmedString(req.body?.issue);
|
|
3835
|
+
if (!issue) {
|
|
3836
|
+
return res.status(400).json({ error: 'issue is required' });
|
|
3837
|
+
}
|
|
3838
|
+
try {
|
|
3839
|
+
const prepared = await prepareJiraIssueImport(jiraConfig, issue);
|
|
3840
|
+
const response = await prepareSpecImportResponse({
|
|
3841
|
+
projectId: result.project.id,
|
|
3842
|
+
payload: req.body,
|
|
3843
|
+
preparedDraft: prepared,
|
|
3844
|
+
importOptions: { provider: 'jira', config: jiraConfig },
|
|
3845
|
+
broadcaster: io,
|
|
3846
|
+
});
|
|
3847
|
+
return res.json(response);
|
|
3848
|
+
}
|
|
3849
|
+
catch (error) {
|
|
3850
|
+
console.warn(`[integrations] jira spec import failed project=${result.project.id} issue=${issue}`, error);
|
|
3851
|
+
if (error instanceof JiraApiError) {
|
|
3852
|
+
return res.status(error.status).json({ error: error.publicMessage });
|
|
3853
|
+
}
|
|
3854
|
+
if (error instanceof HttpError) {
|
|
3855
|
+
return res.status(error.status).json({ error: error.message });
|
|
3856
|
+
}
|
|
3857
|
+
return res.status(500).json({ error: getErrorMessage(error) || 'Unable to prepare the Jira issue for spec import.' });
|
|
3858
|
+
}
|
|
3859
|
+
});
|
|
3860
|
+
app.post('/integrations/jira/prepare/spec-import', async (req, res) => {
|
|
3861
|
+
const result = getRequiredProject(req);
|
|
3862
|
+
if ('error' in result) {
|
|
3863
|
+
return res.status(400).json({ error: result.error });
|
|
3864
|
+
}
|
|
3865
|
+
const jiraConfig = getJiraConnectionConfig(result.project.id);
|
|
3866
|
+
if (!jiraConfig) {
|
|
3867
|
+
return res.status(400).json({ error: 'Jira is not connected for this project.' });
|
|
3868
|
+
}
|
|
3869
|
+
const issue = asTrimmedString(req.body?.issue);
|
|
3870
|
+
if (!issue) {
|
|
3871
|
+
return res.status(400).json({ error: 'issue is required' });
|
|
3872
|
+
}
|
|
3873
|
+
console.info(`[integrations] jira prepare spec import project=${result.project.id} issue=${issue}`);
|
|
3874
|
+
try {
|
|
3875
|
+
const prepared = await prepareJiraIssueImport(jiraConfig, issue);
|
|
3876
|
+
const response = await prepareSpecImportResponse({
|
|
3877
|
+
projectId: result.project.id,
|
|
3878
|
+
payload: req.body,
|
|
3879
|
+
preparedDraft: prepared,
|
|
3880
|
+
importOptions: { provider: 'jira', config: jiraConfig },
|
|
3881
|
+
broadcaster: io,
|
|
3882
|
+
});
|
|
3883
|
+
return res.json(response);
|
|
3884
|
+
}
|
|
3885
|
+
catch (error) {
|
|
3886
|
+
console.warn(`[integrations] jira prepare spec import failed project=${result.project.id} issue=${issue}`, error);
|
|
3887
|
+
if (error instanceof JiraApiError) {
|
|
3888
|
+
return res.status(error.status).json({ error: error.publicMessage });
|
|
3889
|
+
}
|
|
3890
|
+
if (error instanceof HttpError) {
|
|
3891
|
+
return res.status(error.status).json({ error: error.message });
|
|
3892
|
+
}
|
|
3893
|
+
return res.status(500).json({ error: getErrorMessage(error) || 'Unable to prepare the Jira issue for spec import.' });
|
|
3894
|
+
}
|
|
3895
|
+
});
|
|
3752
3896
|
app.post('/integrations/github/resolve/issue', async (req, res) => {
|
|
3753
3897
|
const result = getRequiredProject(req);
|
|
3754
3898
|
if ('error' in result) {
|
|
@@ -3778,6 +3922,265 @@ app.post('/integrations/github/resolve/issue', async (req, res) => {
|
|
|
3778
3922
|
return res.status(500).json({ error: getErrorMessage(error) || 'Unable to import the GitHub issue.' });
|
|
3779
3923
|
}
|
|
3780
3924
|
});
|
|
3925
|
+
app.post('/integrations/github/prepare-spec-import', async (req, res) => {
|
|
3926
|
+
const result = getRequiredProject(req);
|
|
3927
|
+
if ('error' in result) {
|
|
3928
|
+
return res.status(400).json({ error: result.error });
|
|
3929
|
+
}
|
|
3930
|
+
const githubConfig = getGitHubConnectionConfig(result.project.id);
|
|
3931
|
+
if (!githubConfig) {
|
|
3932
|
+
return res.status(400).json({ error: 'GitHub is not connected for this project.' });
|
|
3933
|
+
}
|
|
3934
|
+
const issue = asTrimmedString(req.body?.issue);
|
|
3935
|
+
if (!issue) {
|
|
3936
|
+
return res.status(400).json({ error: 'issue is required' });
|
|
3937
|
+
}
|
|
3938
|
+
try {
|
|
3939
|
+
const prepared = await prepareGitHubIssueImport(githubConfig, issue);
|
|
3940
|
+
const response = await prepareSpecImportResponse({
|
|
3941
|
+
projectId: result.project.id,
|
|
3942
|
+
payload: req.body,
|
|
3943
|
+
preparedDraft: prepared,
|
|
3944
|
+
importOptions: { provider: 'github', config: githubConfig },
|
|
3945
|
+
broadcaster: io,
|
|
3946
|
+
});
|
|
3947
|
+
return res.json(response);
|
|
3948
|
+
}
|
|
3949
|
+
catch (error) {
|
|
3950
|
+
console.warn(`[integrations] github spec import failed project=${result.project.id} issue=${issue}`, error);
|
|
3951
|
+
if (error instanceof GitHubApiError) {
|
|
3952
|
+
return res.status(error.status).json({ error: error.publicMessage });
|
|
3953
|
+
}
|
|
3954
|
+
if (error instanceof HttpError) {
|
|
3955
|
+
return res.status(error.status).json({ error: error.message });
|
|
3956
|
+
}
|
|
3957
|
+
return res.status(500).json({ error: getErrorMessage(error) || 'Unable to prepare the GitHub issue for spec import.' });
|
|
3958
|
+
}
|
|
3959
|
+
});
|
|
3960
|
+
app.post('/integrations/github/prepare/spec-import', async (req, res) => {
|
|
3961
|
+
const result = getRequiredProject(req);
|
|
3962
|
+
if ('error' in result) {
|
|
3963
|
+
return res.status(400).json({ error: result.error });
|
|
3964
|
+
}
|
|
3965
|
+
const githubConfig = getGitHubConnectionConfig(result.project.id);
|
|
3966
|
+
if (!githubConfig) {
|
|
3967
|
+
return res.status(400).json({ error: 'GitHub is not connected for this project.' });
|
|
3968
|
+
}
|
|
3969
|
+
const issue = asTrimmedString(req.body?.issue);
|
|
3970
|
+
if (!issue) {
|
|
3971
|
+
return res.status(400).json({ error: 'issue is required' });
|
|
3972
|
+
}
|
|
3973
|
+
console.info(`[integrations] github prepare spec import project=${result.project.id} issue=${issue}`);
|
|
3974
|
+
try {
|
|
3975
|
+
const prepared = await prepareGitHubIssueImport(githubConfig, issue);
|
|
3976
|
+
const response = await prepareSpecImportResponse({
|
|
3977
|
+
projectId: result.project.id,
|
|
3978
|
+
payload: req.body,
|
|
3979
|
+
preparedDraft: prepared,
|
|
3980
|
+
importOptions: { provider: 'github', config: githubConfig },
|
|
3981
|
+
broadcaster: io,
|
|
3982
|
+
});
|
|
3983
|
+
return res.json(response);
|
|
3984
|
+
}
|
|
3985
|
+
catch (error) {
|
|
3986
|
+
console.warn(`[integrations] github prepare spec import failed project=${result.project.id} issue=${issue}`, error);
|
|
3987
|
+
if (error instanceof GitHubApiError) {
|
|
3988
|
+
return res.status(error.status).json({ error: error.publicMessage });
|
|
3989
|
+
}
|
|
3990
|
+
if (error instanceof HttpError) {
|
|
3991
|
+
return res.status(error.status).json({ error: error.message });
|
|
3992
|
+
}
|
|
3993
|
+
return res.status(500).json({ error: getErrorMessage(error) || 'Unable to prepare the GitHub issue for spec import.' });
|
|
3994
|
+
}
|
|
3995
|
+
});
|
|
3996
|
+
app.get('/integrations/github/actions/workflows', async (req, res) => {
|
|
3997
|
+
const result = getRequiredProject(req);
|
|
3998
|
+
if ('error' in result) {
|
|
3999
|
+
return res.status(400).json({ error: result.error });
|
|
4000
|
+
}
|
|
4001
|
+
const githubConfig = getGitHubConnectionConfig(result.project.id);
|
|
4002
|
+
if (!githubConfig) {
|
|
4003
|
+
return res.status(400).json({ error: 'GitHub is not connected for this project.' });
|
|
4004
|
+
}
|
|
4005
|
+
try {
|
|
4006
|
+
const workflows = await listGitHubWorkflows(githubConfig);
|
|
4007
|
+
return res.json({ workflows });
|
|
4008
|
+
}
|
|
4009
|
+
catch (error) {
|
|
4010
|
+
console.warn(`[integrations] github actions workflows failed project=${result.project.id}`, error);
|
|
4011
|
+
if (error instanceof GitHubApiError) {
|
|
4012
|
+
return res.status(error.status).json({ error: error.publicMessage });
|
|
4013
|
+
}
|
|
4014
|
+
return res.status(502).json({ error: 'Unable to load GitHub Actions workflows right now.' });
|
|
4015
|
+
}
|
|
4016
|
+
});
|
|
4017
|
+
app.get('/integrations/github/actions/workflows/:id/inputs', async (req, res) => {
|
|
4018
|
+
const result = getRequiredProject(req);
|
|
4019
|
+
if ('error' in result) {
|
|
4020
|
+
return res.status(400).json({ error: result.error });
|
|
4021
|
+
}
|
|
4022
|
+
const githubConfig = getGitHubConnectionConfig(result.project.id);
|
|
4023
|
+
if (!githubConfig) {
|
|
4024
|
+
return res.status(400).json({ error: 'GitHub is not connected for this project.' });
|
|
4025
|
+
}
|
|
4026
|
+
const workflowIdParam = asTrimmedString(req.params.id);
|
|
4027
|
+
const workflowPath = asTrimmedString(req.query.path);
|
|
4028
|
+
if (!workflowPath) {
|
|
4029
|
+
return res.status(400).json({ error: 'path query parameter is required' });
|
|
4030
|
+
}
|
|
4031
|
+
try {
|
|
4032
|
+
const workflows = await listGitHubWorkflows(githubConfig);
|
|
4033
|
+
const workflow = workflows.find(candidate => String(candidate.id) === workflowIdParam);
|
|
4034
|
+
if (!workflow) {
|
|
4035
|
+
return res.status(404).json({ error: 'GitHub Actions workflow not found.' });
|
|
4036
|
+
}
|
|
4037
|
+
const dispatchConfig = await getGitHubWorkflowDispatchConfig(githubConfig, workflowPath);
|
|
4038
|
+
return res.json({ inputs: dispatchConfig.inputs, dispatchable: dispatchConfig.dispatchable });
|
|
4039
|
+
}
|
|
4040
|
+
catch (error) {
|
|
4041
|
+
console.warn(`[integrations] github actions inputs failed project=${result.project.id} workflow=${workflowIdParam}`, error);
|
|
4042
|
+
if (error instanceof GitHubApiError) {
|
|
4043
|
+
return res.status(error.status).json({ error: error.publicMessage });
|
|
4044
|
+
}
|
|
4045
|
+
return res.status(502).json({ error: 'Unable to load the workflow inputs right now.' });
|
|
4046
|
+
}
|
|
4047
|
+
});
|
|
4048
|
+
app.post('/integrations/github/actions/workflows/:id/dispatch', async (req, res) => {
|
|
4049
|
+
const result = getRequiredProject(req);
|
|
4050
|
+
if ('error' in result) {
|
|
4051
|
+
return res.status(400).json({ error: result.error });
|
|
4052
|
+
}
|
|
4053
|
+
const githubConfig = getGitHubConnectionConfig(result.project.id);
|
|
4054
|
+
if (!githubConfig) {
|
|
4055
|
+
return res.status(400).json({ error: 'GitHub is not connected for this project.' });
|
|
4056
|
+
}
|
|
4057
|
+
const workflowIdParam = asTrimmedString(req.params.id);
|
|
4058
|
+
const workflowId = Number(workflowIdParam);
|
|
4059
|
+
if (!workflowId || !Number.isFinite(workflowId)) {
|
|
4060
|
+
return res.status(400).json({ error: 'workflow id must be a number' });
|
|
4061
|
+
}
|
|
4062
|
+
const ref = asTrimmedString(req.body?.ref);
|
|
4063
|
+
if (!ref) {
|
|
4064
|
+
return res.status(400).json({ error: 'ref is required' });
|
|
4065
|
+
}
|
|
4066
|
+
const rawInputs = req.body?.inputs;
|
|
4067
|
+
const inputs = {};
|
|
4068
|
+
if (rawInputs && typeof rawInputs === 'object' && !Array.isArray(rawInputs)) {
|
|
4069
|
+
for (const [key, value] of Object.entries(rawInputs)) {
|
|
4070
|
+
if (typeof value === 'string' || typeof value === 'boolean') {
|
|
4071
|
+
inputs[key] = value;
|
|
4072
|
+
}
|
|
4073
|
+
else if (typeof value === 'number') {
|
|
4074
|
+
inputs[key] = String(value);
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
}
|
|
4078
|
+
console.info(`[integrations] github actions dispatch project=${result.project.id} workflow=${workflowId} ref=${ref}`);
|
|
4079
|
+
try {
|
|
4080
|
+
const dispatchedAt = Date.now();
|
|
4081
|
+
await dispatchGitHubWorkflow(githubConfig, workflowId, { ref, inputs });
|
|
4082
|
+
const trackedRun = trackGitHubActionsRun({
|
|
4083
|
+
io,
|
|
4084
|
+
projectId: result.project.id,
|
|
4085
|
+
workflowId,
|
|
4086
|
+
config: githubConfig,
|
|
4087
|
+
dispatchedAt,
|
|
4088
|
+
});
|
|
4089
|
+
return res.status(202).json({ tracking_key: trackedRun.tracking_key, dispatched: true });
|
|
4090
|
+
}
|
|
4091
|
+
catch (error) {
|
|
4092
|
+
console.warn(`[integrations] github actions dispatch failed project=${result.project.id} workflow=${workflowId}`, error);
|
|
4093
|
+
if (error instanceof GitHubApiError) {
|
|
4094
|
+
return res.status(error.status).json({ error: error.publicMessage });
|
|
4095
|
+
}
|
|
4096
|
+
return res.status(502).json({ error: 'Unable to dispatch the workflow right now.' });
|
|
4097
|
+
}
|
|
4098
|
+
});
|
|
4099
|
+
app.get('/integrations/github/actions/runs', async (req, res) => {
|
|
4100
|
+
const result = getRequiredProject(req);
|
|
4101
|
+
if ('error' in result) {
|
|
4102
|
+
return res.status(400).json({ error: result.error });
|
|
4103
|
+
}
|
|
4104
|
+
const githubConfig = getGitHubConnectionConfig(result.project.id);
|
|
4105
|
+
if (!githubConfig) {
|
|
4106
|
+
return res.status(400).json({ error: 'GitHub is not connected for this project.' });
|
|
4107
|
+
}
|
|
4108
|
+
try {
|
|
4109
|
+
const [recentRuns, trackedRuns] = await Promise.all([
|
|
4110
|
+
listGitHubWorkflowRuns(githubConfig).catch(error => {
|
|
4111
|
+
console.warn(`[integrations] github actions runs list failed project=${result.project.id}`, error);
|
|
4112
|
+
return [];
|
|
4113
|
+
}),
|
|
4114
|
+
Promise.resolve(getTrackedGitHubActionsRuns(result.project.id)),
|
|
4115
|
+
]);
|
|
4116
|
+
const trackedByRunId = new Map();
|
|
4117
|
+
for (const tracked of trackedRuns) {
|
|
4118
|
+
if (tracked.run) {
|
|
4119
|
+
trackedByRunId.set(tracked.run.id, tracked);
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
4122
|
+
const recentById = new Map(recentRuns.map(run => [run.id, run]));
|
|
4123
|
+
const mergedRecent = recentRuns.map(run => trackedByRunId.get(run.id)?.run ?? run);
|
|
4124
|
+
const trackedOnly = trackedRuns
|
|
4125
|
+
.map(tracked => tracked.run)
|
|
4126
|
+
.filter((run) => Boolean(run) && !recentById.has(run.id));
|
|
4127
|
+
const seenRunIds = new Set();
|
|
4128
|
+
const runs = [...trackedOnly, ...mergedRecent].filter(run => {
|
|
4129
|
+
if (seenRunIds.has(run.id)) {
|
|
4130
|
+
return false;
|
|
4131
|
+
}
|
|
4132
|
+
seenRunIds.add(run.id);
|
|
4133
|
+
return true;
|
|
4134
|
+
});
|
|
4135
|
+
return res.json({ runs, tracked_runs: trackedRuns });
|
|
4136
|
+
}
|
|
4137
|
+
catch (error) {
|
|
4138
|
+
console.warn(`[integrations] github actions runs failed project=${result.project.id}`, error);
|
|
4139
|
+
if (error instanceof GitHubApiError) {
|
|
4140
|
+
return res.status(error.status).json({ error: error.publicMessage });
|
|
4141
|
+
}
|
|
4142
|
+
return res.status(502).json({ error: 'Unable to load GitHub Actions runs right now.' });
|
|
4143
|
+
}
|
|
4144
|
+
});
|
|
4145
|
+
app.get('/integrations/github/actions/active-count', (req, res) => {
|
|
4146
|
+
const result = getRequiredProject(req);
|
|
4147
|
+
if ('error' in result) {
|
|
4148
|
+
return res.status(400).json({ error: result.error });
|
|
4149
|
+
}
|
|
4150
|
+
const githubConfig = getGitHubConnectionConfig(result.project.id);
|
|
4151
|
+
if (!githubConfig) {
|
|
4152
|
+
return res.status(400).json({ error: 'GitHub is not connected for this project.' });
|
|
4153
|
+
}
|
|
4154
|
+
return res.json({ activeCount: getActiveTrackedRunCount(result.project.id) });
|
|
4155
|
+
});
|
|
4156
|
+
app.get('/integrations/github/actions/runs/:id', async (req, res) => {
|
|
4157
|
+
const result = getRequiredProject(req);
|
|
4158
|
+
if ('error' in result) {
|
|
4159
|
+
return res.status(400).json({ error: result.error });
|
|
4160
|
+
}
|
|
4161
|
+
const githubConfig = getGitHubConnectionConfig(result.project.id);
|
|
4162
|
+
if (!githubConfig) {
|
|
4163
|
+
return res.status(400).json({ error: 'GitHub is not connected for this project.' });
|
|
4164
|
+
}
|
|
4165
|
+
const runId = Number(asTrimmedString(req.params.id));
|
|
4166
|
+
if (!runId || !Number.isFinite(runId)) {
|
|
4167
|
+
return res.status(400).json({ error: 'run id must be a number' });
|
|
4168
|
+
}
|
|
4169
|
+
try {
|
|
4170
|
+
const [run, jobs] = await Promise.all([
|
|
4171
|
+
getGitHubWorkflowRun(githubConfig, runId),
|
|
4172
|
+
getGitHubWorkflowRunJobs(githubConfig, runId),
|
|
4173
|
+
]);
|
|
4174
|
+
return res.json({ run: { ...run, jobs } });
|
|
4175
|
+
}
|
|
4176
|
+
catch (error) {
|
|
4177
|
+
console.warn(`[integrations] github actions run failed project=${result.project.id} run=${runId}`, error);
|
|
4178
|
+
if (error instanceof GitHubApiError) {
|
|
4179
|
+
return res.status(error.status).json({ error: error.publicMessage });
|
|
4180
|
+
}
|
|
4181
|
+
return res.status(502).json({ error: 'Unable to load the GitHub Actions run right now.' });
|
|
4182
|
+
}
|
|
4183
|
+
});
|
|
3781
4184
|
const ASSIGNED_ISSUES_CACHE_TTL_MS = 60 * 1000;
|
|
3782
4185
|
app.get('/integrations/assigned', async (req, res) => {
|
|
3783
4186
|
const result = getRequiredProject(req);
|
|
@@ -6052,6 +6455,7 @@ export const startServer = ({ port = DEFAULT_PORT, host } = {}) => {
|
|
|
6052
6455
|
export const shutdownServer = async (signal) => {
|
|
6053
6456
|
await stopMobileAccess();
|
|
6054
6457
|
await clearAllTestSessions(io);
|
|
6458
|
+
await clearAllGitHubActionsSessions();
|
|
6055
6459
|
await shutdownRealtimeServer({
|
|
6056
6460
|
signal,
|
|
6057
6461
|
io,
|