forge-openclaw-plugin 0.3.16 → 0.3.17
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/assets/{action-bar-DgrmzFrI.js → action-bar-D3CEYlj4.js} +1 -1
- package/dist/assets/{activity-page-CF451ueg.js → activity-page-Ce1pHIu5.js} +1 -1
- package/dist/assets/{ai-surface-workspace-DtwybxJB.js → ai-surface-workspace-DEliwOjF.js} +1 -1
- package/dist/assets/artifacts-page-BgyFVIVM.js +2 -0
- package/dist/assets/{atlas-panel-CB3uYk_K.js → atlas-panel-VZOnJa1c.js} +1 -1
- package/dist/assets/{board-CuxQRKPJ.js → board-DprRipIG.js} +1 -1
- package/dist/assets/{calendar-page-BYsDuLnh.js → calendar-page-Zstsn4uG.js} +1 -1
- package/dist/assets/{calendar-rules-DXuOv2J-.js → calendar-rules-BGIBuEDk.js} +1 -1
- package/dist/assets/{calendar-week-toolbar-8PJmiUE_.js → calendar-week-toolbar-DXFkMkbq.js} +1 -1
- package/dist/assets/{charts-BzT4pUPg.js → charts-C5S0-BL7.js} +1 -1
- package/dist/assets/{companion-sync-lab-page-DzWNOaBh.js → companion-sync-lab-page-DIPPLFKt.js} +1 -1
- package/dist/assets/{daily-metrics-dashboard-CHcYxDhs.js → daily-metrics-dashboard-CG-OOCJz.js} +1 -1
- package/dist/assets/{define-workbench-box-DcI0_QKW.js → define-workbench-box-BEEdtBkQ.js} +1 -1
- package/dist/assets/{entity-link-multiselect-C--AiCMb.js → entity-link-multiselect-BfDAROHB.js} +1 -1
- package/dist/assets/{entity-note-count-link-xne6mshj.js → entity-note-count-link-BGOiaash.js} +1 -1
- package/dist/assets/{entity-notes-surface-jy6Psist.js → entity-notes-surface-DPsJwqQa.js} +1 -1
- package/dist/assets/execution-board-Dg-2GSKv.js +1 -0
- package/dist/assets/{faceted-token-search-BMQ1Wwzt.js → faceted-token-search-DV7MSVYb.js} +1 -1
- package/dist/assets/{flagship-signal-deck-DjcskRwF.js → flagship-signal-deck-D3wVL3bC.js} +1 -1
- package/dist/assets/{floating-action-menu-cGhbJ2tc.js → floating-action-menu-BUs382px.js} +1 -1
- package/dist/assets/{forms-D1qJ3oOP.js → forms-ByKjodjN.js} +1 -1
- package/dist/assets/{generic-node-view-DNVwfqqq.js → generic-node-view-BY5dbPXJ.js} +1 -1
- package/dist/assets/{goal-detail-page-dAbyCilO.js → goal-detail-page-MYr6j2B4.js} +1 -1
- package/dist/assets/{goal-dialog-DH50D0tP.js → goal-dialog-nkdME5Uy.js} +1 -1
- package/dist/assets/goals-page-BsFeBzU1.js +1 -0
- package/dist/assets/{graph-BF4IsheG.js → graph-CHVj0Z7n.js} +1 -1
- package/dist/assets/habits-page-wO461EVU.js +1 -0
- package/dist/assets/{health-boxes-BPTgGM6G.js → health-boxes-BphMeSJj.js} +1 -1
- package/dist/assets/index-CSd8ylsy.css +1 -0
- package/dist/assets/index-gmPaoLN-.js +2 -0
- package/dist/assets/{inline-note-fields-D4mCM1gO.js → inline-note-fields-BvQwmMAv.js} +1 -1
- package/dist/assets/{insight-flow-dialog-Btp6bkbV.js → insight-flow-dialog-H_eaOmst.js} +1 -1
- package/dist/assets/{insights-page-1qM4mxjS.js → insights-page-DINYe3cB.js} +3 -3
- package/dist/assets/{kanban-boxes-u_A-UJG-.js → kanban-boxes-oACOTDYG.js} +1 -1
- package/dist/assets/{kanban-page-CKCa_3Qb.js → kanban-page-BGLXH91f.js} +1 -1
- package/dist/assets/knowledge-graph-page-VfMvw5jL.js +1 -0
- package/dist/assets/{life-force-page-BZlyA144.js → life-force-page-DQPb6UL-.js} +1 -1
- package/dist/assets/{life-force-workspace-CtAWZXNw.js → life-force-workspace-BJ1aI3JE.js} +1 -1
- package/dist/assets/{maps-BTVHALP8.js → maps-CvEHVkBk.js} +1 -1
- package/dist/assets/{metric-tile-Bkx2btO2.js → metric-tile-CbEe19Gd.js} +1 -1
- package/dist/assets/{motion-DcgUnXhY.js → motion-BibSzp57.js} +1 -1
- package/dist/assets/{movement-boxes-QZ2EIS9q.js → movement-boxes-dtDYhw5c.js} +1 -1
- package/dist/assets/{movement-page-B-3ihggI.js → movement-page-BhmwCHjs.js} +1 -1
- package/dist/assets/{note-markdown-BWedRE3c.js → note-markdown-CG8u2d6p.js} +1 -1
- package/dist/assets/{note-tags-input-DZkCqI1w.js → note-tags-input-D_conqDO.js} +1 -1
- package/dist/assets/{notes-boxes-DGFmt7Dp.js → notes-boxes-BLKucFqW.js} +1 -1
- package/dist/assets/notes-page-CafVxWjb.js +1 -0
- package/dist/assets/{open-in-graph-button-CjvkEj1P.js → open-in-graph-button-DFQ4r6SN.js} +1 -1
- package/dist/assets/{orbit-map-CRHSPenk.js → orbit-map-DsEl3ori.js} +1 -1
- package/dist/assets/overview-page-BffcX-pM.js +1 -0
- package/dist/assets/page-hero-U603l9rQ.js +1 -0
- package/dist/assets/pill-cluster-BYVFNppV.js +1 -0
- package/dist/assets/{preference-entity-handoff-button-CfCQl3cW.js → preference-entity-handoff-button-cPrTpHsV.js} +1 -1
- package/dist/assets/{preferences-page-OltGdsQ2.js → preferences-page-DQjFIOmt.js} +1 -1
- package/dist/assets/{project-collections-FfBIVwXu.js → project-collections-B9OGHGqm.js} +1 -1
- package/dist/assets/project-detail-page-r1Sw2kcO.js +1 -0
- package/dist/assets/{project-dialog-B_J1ESMk.js → project-dialog-B2_PcXAf.js} +1 -1
- package/dist/assets/project-management-hierarchy-page-qLNG8hsh.js +1 -0
- package/dist/assets/{project-management-section-nav-DBNHt9p5.js → project-management-section-nav-DFUlmMEB.js} +1 -1
- package/dist/assets/{projects-boxes-BvlVsO5q.js → projects-boxes-BA7_XaqX.js} +1 -1
- package/dist/assets/projects-page-B6ggXWFw.js +1 -0
- package/dist/assets/psyche-behaviors-page-ByWpXlLq.js +5 -0
- package/dist/assets/{psyche-flashcards-page-05606-97.js → psyche-flashcards-page-B9nSc0mk.js} +1 -1
- package/dist/assets/{psyche-goal-map-page-Cw-aqS3Y.js → psyche-goal-map-page-BQU7qI88.js} +1 -1
- package/dist/assets/{psyche-graph-0E22QHPe.js → psyche-graph-DCeP7r2b.js} +1 -1
- package/dist/assets/{psyche-metrics-page-DBFVPeMa.js → psyche-metrics-page-DD2lOP-J.js} +1 -1
- package/dist/assets/psyche-mode-guide-page-DbtZgnjr.js +1 -0
- package/dist/assets/psyche-modes-page-3zFJWFQf.js +1 -0
- package/dist/assets/psyche-page-D5vXYkfB.js +1 -0
- package/dist/assets/psyche-patterns-page-BneAAeKS.js +5 -0
- package/dist/assets/{psyche-questionnaire-builder-page-DEt0UDsz.js → psyche-questionnaire-builder-page-BH1la5C9.js} +1 -1
- package/dist/assets/{psyche-questionnaire-detail-page-BXQbOE6A.js → psyche-questionnaire-detail-page-DYav634P.js} +1 -1
- package/dist/assets/psyche-questionnaire-run-detail-page-9VaijhJm.js +1 -0
- package/dist/assets/{psyche-questionnaire-run-page-D_EokOQm.js → psyche-questionnaire-run-page-e1T6k_dS.js} +1 -1
- package/dist/assets/{psyche-questionnaires-page-D1Ov2L4n.js → psyche-questionnaires-page-Dyv367z9.js} +1 -1
- package/dist/assets/{psyche-report-detail-page-9HyPr8BJ.js → psyche-report-detail-page-hqxHIXw2.js} +3 -3
- package/dist/assets/psyche-reports-page-DhIfcGbt.js +1 -0
- package/dist/assets/{psyche-schemas-DDol0j-g.js → psyche-schemas-Cg51Ztxz.js} +1 -1
- package/dist/assets/psyche-schemas-beliefs-page-Dgb5o9vx.js +9 -0
- package/dist/assets/{psyche-screen-time-page-DJMDR5oo.js → psyche-screen-time-page-D6MnJGNa.js} +1 -1
- package/dist/assets/{psyche-self-observation-page-DFKXG1Yv.js → psyche-self-observation-page-C1Vyezbv.js} +1 -1
- package/dist/assets/{psyche-values-page-TWKth89J.js → psyche-values-page-B_JWVw1Q.js} +2 -2
- package/dist/assets/{question-flow-dialog-D-_EvoAt.js → question-flow-dialog-yMYVk998.js} +2 -2
- package/dist/assets/{report-chain-fields-Dy-jBQDn.js → report-chain-fields-D4NM9a6I.js} +1 -1
- package/dist/assets/rewards-page-B5-bcL4R.js +1 -0
- package/dist/assets/{scheduling-rules-editor-CAd290IE.js → scheduling-rules-editor-De72IUax.js} +1 -1
- package/dist/assets/{schema-badge-BLaVI1D7.js → schema-badge-jX28kUa6.js} +1 -1
- package/dist/assets/{schemas-B0Pa-V-A.js → schemas-BlFy-uPR.js} +1 -1
- package/dist/assets/{select-menu-DcS4Ukjf.js → select-menu-BXv1rsVc.js} +1 -1
- package/dist/assets/{settings-agents-page-Bt38HhEJ.js → settings-agents-page-DN_np10S.js} +1 -1
- package/dist/assets/settings-bin-page-BM5BpK_i.js +1 -0
- package/dist/assets/{settings-calendar-page-DPSSZV3s.js → settings-calendar-page-Cg0gSSFs.js} +3 -3
- package/dist/assets/{settings-data-page-BdHsD1C_.js → settings-data-page-Dwmp2rLy.js} +1 -1
- package/dist/assets/{settings-logs-page-D9OnWoFq.js → settings-logs-page-DQNM21Re.js} +1 -1
- package/dist/assets/{settings-mobile-page-DFpsXA4M.js → settings-mobile-page-DQdiRa-a.js} +1 -1
- package/dist/assets/settings-models-page-CAEPpuHF.js +1 -0
- package/dist/assets/{settings-page-m_3iYPwU.js → settings-page-Cl2KiCFg.js} +1 -1
- package/dist/assets/{settings-rewards-page-B2aBm-dA.js → settings-rewards-page-DoIUumhe.js} +1 -1
- package/dist/assets/{settings-section-nav-CMeU19Rx.js → settings-section-nav-D_N87IG0.js} +1 -1
- package/dist/assets/{settings-users-page-D8jyewJl.js → settings-users-page-CPesR62N.js} +1 -1
- package/dist/assets/{settings-wiki-page-DjOgQJAh.js → settings-wiki-page-BxMQM5Vi.js} +1 -1
- package/dist/assets/{sleep-page-D8-dA4bE.js → sleep-page-DUYmQKrg.js} +1 -1
- package/dist/assets/{sports-page-CK3PgPKB.js → sports-page-Bzi5TF9T.js} +1 -1
- package/dist/assets/{state-Bpe5dF3T.js → state-BFyKSULP.js} +1 -1
- package/dist/assets/{strategies-page-aFpJath-.js → strategies-page-C-T2MZx4.js} +1 -1
- package/dist/assets/{strategy-detail-page-CobF5qLv.js → strategy-detail-page-3tYuSZu-.js} +1 -1
- package/dist/assets/{strategy-dialog-Fgoaoob5.js → strategy-dialog-BWm4slo4.js} +1 -1
- package/dist/assets/{surface-D0dqgX-k.js → surface-BJObZeRw.js} +1 -1
- package/dist/assets/{table-U7otr5go.js → table-CTLroJKN.js} +1 -1
- package/dist/assets/task-detail-page-ZZOXSpSF.js +1 -0
- package/dist/assets/{task-dialog-eCDTF8xe.js → task-dialog-2wy0xI7f.js} +5 -5
- package/dist/assets/timebox-planning-dialog-C6h0Hp71.js +1 -0
- package/dist/assets/{today-boxes-CYfskVrM.js → today-boxes-B_TdgSDz.js} +1 -1
- package/dist/assets/today-page-Dipns9tl.js +1 -0
- package/dist/assets/training-load-page-B78e1-o-.js +1 -0
- package/dist/assets/{ui-B9TWEtCx.js → ui-uo_bNP7c.js} +1 -1
- package/dist/assets/{use-anchored-overlay-position-BY4kNzPj.js → use-anchored-overlay-position-BSxFX6Hi.js} +1 -1
- package/dist/assets/{use-psyche-focus-target-BhNedCZB.js → use-psyche-focus-target-1GLkhYiv.js} +1 -1
- package/dist/assets/{user-badge-MEZuJiir.js → user-badge-C4eZu1e_.js} +1 -1
- package/dist/assets/{user-select-field-fx129Uh6.js → user-select-field-CmKwcbZt.js} +1 -1
- package/dist/assets/{utility-widgets-h5eG2jvc.js → utility-widgets-B06wQFrd.js} +2 -2
- package/dist/assets/{vendor-BwL6m4SE.js → vendor-B7FKSwHK.js} +222 -212
- package/dist/assets/{vitals-page-eoFnQ3XL.js → vitals-page-BC7QFsm2.js} +1 -1
- package/dist/assets/{weekly-review-page-C7BU1gkK.js → weekly-review-page-BjNsNoWj.js} +1 -1
- package/dist/assets/{weight-loss-page-Cc7Do3XY.js → weight-loss-page-BOahGY9r.js} +1 -1
- package/dist/assets/{wiki-article-markdown-CCKoSptz.js → wiki-article-markdown-DO47HnZf.js} +2 -2
- package/dist/assets/{wiki-editor-page-BpbxZrgz.js → wiki-editor-page-OWRUHl4O.js} +5 -5
- package/dist/assets/{wiki-ingest-history-page-D5Wfr8pc.js → wiki-ingest-history-page-CuHpg2lZ.js} +1 -1
- package/dist/assets/{wiki-ingest-modal-DhRVsEwC.js → wiki-ingest-modal-EZ3kX-vA.js} +1 -1
- package/dist/assets/wiki-page-BPV3HIgu.js +1 -0
- package/dist/assets/{workbench-flow-page-y9FxDbKO.js → workbench-flow-page-C53KueEz.js} +3 -3
- package/dist/assets/{workbench-page-Da16AZvN.js → workbench-page-DJ7nT2JQ.js} +1 -1
- package/dist/assets/workout-detail-page-Dhyu0q7o.js +2 -0
- package/dist/index.html +8 -8
- package/dist/openclaw/parity.d.ts +1 -1
- package/dist/openclaw/parity.js +10 -0
- package/dist/openclaw/routes.js +78 -0
- package/dist/openclaw/tools.js +42 -0
- package/dist/server/apps/api/migrations/072_artifact_store.sql +106 -0
- package/dist/server/apps/api/src/app.js +364 -3
- package/dist/server/apps/api/src/openapi.js +570 -1
- package/dist/server/apps/api/src/repositories/entity-links.js +66 -0
- package/dist/server/apps/api/src/services/artifacts.js +1059 -0
- package/dist/server/apps/api/src/services/entity-crud.js +22 -0
- package/dist/server/apps/api/src/services/knowledge-graph.js +45 -0
- package/dist/server/apps/api/src/services/psyche-observation-calendar.js +1 -0
- package/dist/server/apps/api/src/types.js +2 -0
- package/dist/server/apps/web/src/lib/api.js +69 -0
- package/dist/server/apps/web/src/lib/entity-visuals.js +10 -1
- package/dist/server/apps/web/src/lib/knowledge-graph-types.js +9 -0
- package/openclaw.plugin.json +2 -1
- package/package.json +1 -1
- package/server/migrations/072_artifact_store.sql +106 -0
- package/skills/forge-openclaw/SKILL.md +57 -4
- package/skills/forge-openclaw/entity_conversation_playbooks.md +212 -14
- package/skills/forge-openclaw/psyche_entity_playbooks.md +20 -0
- package/dist/assets/execution-board-BSUZCIIx.js +0 -1
- package/dist/assets/goals-page-DkMy9mPD.js +0 -1
- package/dist/assets/habits-page-CCQR8rg6.js +0 -1
- package/dist/assets/index-VzCGTBS_.css +0 -1
- package/dist/assets/index-izRKx6JK.js +0 -2
- package/dist/assets/knowledge-graph-page-BZOxRv19.js +0 -1
- package/dist/assets/notes-page-DYkn04tz.js +0 -1
- package/dist/assets/overview-page-D6LsjPWe.js +0 -1
- package/dist/assets/page-hero-BLhM8FF3.js +0 -1
- package/dist/assets/pill-cluster-B5bYs_e2.js +0 -1
- package/dist/assets/project-detail-page-CCm3iZPQ.js +0 -1
- package/dist/assets/project-management-hierarchy-page-BNzvtNZj.js +0 -1
- package/dist/assets/projects-page-BUf7KV-_.js +0 -1
- package/dist/assets/psyche-behaviors-page-jtyhdpJ1.js +0 -5
- package/dist/assets/psyche-mode-guide-page-DI-LNEDT.js +0 -1
- package/dist/assets/psyche-modes-page-CaMupyfi.js +0 -1
- package/dist/assets/psyche-page-CFBq0YKf.js +0 -1
- package/dist/assets/psyche-patterns-page-sp4ikoef.js +0 -5
- package/dist/assets/psyche-questionnaire-run-detail-page-Cd3ClsSK.js +0 -1
- package/dist/assets/psyche-reports-page-BeyJg5fb.js +0 -1
- package/dist/assets/psyche-schemas-beliefs-page-DNmf-Vma.js +0 -9
- package/dist/assets/rewards-page-D3ymEd2X.js +0 -1
- package/dist/assets/settings-bin-page-DqyVI1i1.js +0 -1
- package/dist/assets/settings-models-page-DaFXLp-O.js +0 -1
- package/dist/assets/task-detail-page-CDK79bzk.js +0 -1
- package/dist/assets/timebox-planning-dialog-CNZIGSpd.js +0 -1
- package/dist/assets/today-page-Bnh8wopq.js +0 -1
- package/dist/assets/training-load-page-C7lq-jqy.js +0 -1
- package/dist/assets/wiki-page-1vf-HErs.js +0 -1
- package/dist/assets/workout-detail-page-Cq0YamXF.js +0 -2
|
@@ -165,6 +165,10 @@ const API_TAGS = [
|
|
|
165
165
|
name: "Wiki",
|
|
166
166
|
description: "SQLite-backed wiki settings, pages, ingest, sync, health, and search."
|
|
167
167
|
},
|
|
168
|
+
{
|
|
169
|
+
name: "Artifacts",
|
|
170
|
+
description: "Trusted file artifact storage, metadata, static safety scans, human-only downloads, links, versions, and audit events."
|
|
171
|
+
},
|
|
168
172
|
{
|
|
169
173
|
name: "Preferences",
|
|
170
174
|
description: "Preference profiles, comparisons, concepts, contexts, and learned scores."
|
|
@@ -232,7 +236,7 @@ const API_TAG_GROUPS = [
|
|
|
232
236
|
},
|
|
233
237
|
{
|
|
234
238
|
name: "Knowledge And Reflection",
|
|
235
|
-
tags: ["Wiki", "Preferences", "Psyche", "Questionnaires"]
|
|
239
|
+
tags: ["Wiki", "Artifacts", "Preferences", "Psyche", "Questionnaires"]
|
|
236
240
|
},
|
|
237
241
|
{
|
|
238
242
|
name: "Platform And Agents",
|
|
@@ -289,6 +293,9 @@ function resolveTagsForPath(path) {
|
|
|
289
293
|
if (path.startsWith("/api/v1/wiki")) {
|
|
290
294
|
return ["Wiki"];
|
|
291
295
|
}
|
|
296
|
+
if (path.startsWith("/api/v1/artifacts")) {
|
|
297
|
+
return ["Artifacts"];
|
|
298
|
+
}
|
|
292
299
|
if (path.startsWith("/api/v1/preferences")) {
|
|
293
300
|
return ["Preferences"];
|
|
294
301
|
}
|
|
@@ -5503,6 +5510,265 @@ export function buildOpenApiDocument() {
|
|
|
5503
5510
|
dataQuality: { type: "object", additionalProperties: true }
|
|
5504
5511
|
}
|
|
5505
5512
|
};
|
|
5513
|
+
const entityLink = {
|
|
5514
|
+
type: "object",
|
|
5515
|
+
required: [
|
|
5516
|
+
"sourceEntityType",
|
|
5517
|
+
"sourceEntityId",
|
|
5518
|
+
"targetEntityType",
|
|
5519
|
+
"targetEntityId",
|
|
5520
|
+
"anchorKey",
|
|
5521
|
+
"relationship",
|
|
5522
|
+
"createdByActor",
|
|
5523
|
+
"createdAt"
|
|
5524
|
+
],
|
|
5525
|
+
properties: {
|
|
5526
|
+
sourceEntityType: { type: "string" },
|
|
5527
|
+
sourceEntityId: { type: "string" },
|
|
5528
|
+
targetEntityType: { type: "string" },
|
|
5529
|
+
targetEntityId: { type: "string" },
|
|
5530
|
+
anchorKey: nullable({ type: "string" }),
|
|
5531
|
+
relationship: { type: "string" },
|
|
5532
|
+
createdByActor: nullable({ type: "string" }),
|
|
5533
|
+
createdAt: { type: "string", format: "date-time" }
|
|
5534
|
+
}
|
|
5535
|
+
};
|
|
5536
|
+
const entityLinkInput = {
|
|
5537
|
+
type: "object",
|
|
5538
|
+
required: ["entityType", "entityId"],
|
|
5539
|
+
properties: {
|
|
5540
|
+
entityType: { type: "string" },
|
|
5541
|
+
entityId: { type: "string" },
|
|
5542
|
+
anchorKey: { type: "string" },
|
|
5543
|
+
relationship: { type: "string", default: "related" }
|
|
5544
|
+
}
|
|
5545
|
+
};
|
|
5546
|
+
const artifactScanFinding = {
|
|
5547
|
+
type: "object",
|
|
5548
|
+
required: ["code", "severity", "message"],
|
|
5549
|
+
properties: {
|
|
5550
|
+
code: { type: "string" },
|
|
5551
|
+
severity: {
|
|
5552
|
+
type: "string",
|
|
5553
|
+
enum: ["info", "low", "moderate", "high", "blocked"]
|
|
5554
|
+
},
|
|
5555
|
+
message: { type: "string" }
|
|
5556
|
+
}
|
|
5557
|
+
};
|
|
5558
|
+
const artifactScanResult = {
|
|
5559
|
+
type: "object",
|
|
5560
|
+
required: [
|
|
5561
|
+
"scannedAt",
|
|
5562
|
+
"scannerVersion",
|
|
5563
|
+
"declaredExtension",
|
|
5564
|
+
"detectedMimeType",
|
|
5565
|
+
"extensionAllowed",
|
|
5566
|
+
"byteSize",
|
|
5567
|
+
"findings",
|
|
5568
|
+
"extractedTextSample",
|
|
5569
|
+
"extractedTextTruncated"
|
|
5570
|
+
],
|
|
5571
|
+
properties: {
|
|
5572
|
+
scannedAt: { type: "string", format: "date-time" },
|
|
5573
|
+
scannerVersion: { type: "string" },
|
|
5574
|
+
declaredExtension: { type: "string" },
|
|
5575
|
+
detectedMimeType: { type: "string" },
|
|
5576
|
+
extensionAllowed: { type: "boolean" },
|
|
5577
|
+
byteSize: { type: "integer" },
|
|
5578
|
+
findings: arrayOf(artifactScanFinding),
|
|
5579
|
+
extractedTextSample: { type: "string" },
|
|
5580
|
+
extractedTextTruncated: { type: "boolean" }
|
|
5581
|
+
}
|
|
5582
|
+
};
|
|
5583
|
+
const artifact = {
|
|
5584
|
+
type: "object",
|
|
5585
|
+
required: [
|
|
5586
|
+
"id",
|
|
5587
|
+
"title",
|
|
5588
|
+
"shortDescription",
|
|
5589
|
+
"description",
|
|
5590
|
+
"originalFileName",
|
|
5591
|
+
"storageKey",
|
|
5592
|
+
"storagePath",
|
|
5593
|
+
"contentSha256",
|
|
5594
|
+
"byteSize",
|
|
5595
|
+
"detectedExtension",
|
|
5596
|
+
"declaredMimeType",
|
|
5597
|
+
"detectedMimeType",
|
|
5598
|
+
"formatFamily",
|
|
5599
|
+
"sourceKind",
|
|
5600
|
+
"sourceLabel",
|
|
5601
|
+
"uploadedByUserId",
|
|
5602
|
+
"uploadedByAgentId",
|
|
5603
|
+
"actingForUserId",
|
|
5604
|
+
"artifactState",
|
|
5605
|
+
"dangerScore",
|
|
5606
|
+
"dangerLevel",
|
|
5607
|
+
"downloadPolicy",
|
|
5608
|
+
"scanResults",
|
|
5609
|
+
"enrichmentResults",
|
|
5610
|
+
"metadata",
|
|
5611
|
+
"links",
|
|
5612
|
+
"createdAt",
|
|
5613
|
+
"updatedAt"
|
|
5614
|
+
],
|
|
5615
|
+
properties: {
|
|
5616
|
+
id: { type: "string" },
|
|
5617
|
+
title: { type: "string" },
|
|
5618
|
+
shortDescription: { type: "string" },
|
|
5619
|
+
description: { type: "string" },
|
|
5620
|
+
originalFileName: { type: "string" },
|
|
5621
|
+
storageKey: { type: "string" },
|
|
5622
|
+
storagePath: { type: "string" },
|
|
5623
|
+
contentSha256: { type: "string" },
|
|
5624
|
+
byteSize: { type: "integer" },
|
|
5625
|
+
detectedExtension: { type: "string" },
|
|
5626
|
+
declaredMimeType: { type: "string" },
|
|
5627
|
+
detectedMimeType: { type: "string" },
|
|
5628
|
+
formatFamily: {
|
|
5629
|
+
type: "string",
|
|
5630
|
+
enum: [
|
|
5631
|
+
"spreadsheet",
|
|
5632
|
+
"document",
|
|
5633
|
+
"presentation",
|
|
5634
|
+
"pdf",
|
|
5635
|
+
"text",
|
|
5636
|
+
"structured_text",
|
|
5637
|
+
"image"
|
|
5638
|
+
]
|
|
5639
|
+
},
|
|
5640
|
+
sourceKind: {
|
|
5641
|
+
type: "string",
|
|
5642
|
+
enum: ["upload", "agent_upload", "wiki_ingest", "external_reference", "manual"]
|
|
5643
|
+
},
|
|
5644
|
+
sourceLabel: { type: "string" },
|
|
5645
|
+
uploadedByUserId: nullable({ type: "string" }),
|
|
5646
|
+
uploadedByAgentId: nullable({ type: "string" }),
|
|
5647
|
+
actingForUserId: nullable({ type: "string" }),
|
|
5648
|
+
artifactState: {
|
|
5649
|
+
type: "string",
|
|
5650
|
+
enum: ["active", "quarantined", "blocked", "archived", "metadata_only"]
|
|
5651
|
+
},
|
|
5652
|
+
dangerScore: { type: "integer", minimum: 0, maximum: 100 },
|
|
5653
|
+
dangerLevel: { type: "string", enum: ["low", "moderate", "high", "blocked"] },
|
|
5654
|
+
downloadPolicy: { type: "string", enum: ["human_only", "disabled"] },
|
|
5655
|
+
scanResults: artifactScanResult,
|
|
5656
|
+
enrichmentResults: { type: "object", additionalProperties: true },
|
|
5657
|
+
metadata: { type: "object", additionalProperties: true },
|
|
5658
|
+
links: arrayOf(entityLink),
|
|
5659
|
+
createdAt: { type: "string", format: "date-time" },
|
|
5660
|
+
updatedAt: { type: "string", format: "date-time" }
|
|
5661
|
+
}
|
|
5662
|
+
};
|
|
5663
|
+
const artifactUploadInput = {
|
|
5664
|
+
type: "object",
|
|
5665
|
+
required: ["originalFileName", "contentBase64"],
|
|
5666
|
+
properties: {
|
|
5667
|
+
title: { type: "string" },
|
|
5668
|
+
shortDescription: { type: "string" },
|
|
5669
|
+
description: { type: "string" },
|
|
5670
|
+
originalFileName: { type: "string" },
|
|
5671
|
+
declaredMimeType: { type: "string" },
|
|
5672
|
+
contentBase64: {
|
|
5673
|
+
type: "string",
|
|
5674
|
+
description: "Base64 file bytes. Forge stores and statically scans bytes; agents must not execute or open file contents."
|
|
5675
|
+
},
|
|
5676
|
+
sourceKind: {
|
|
5677
|
+
type: "string",
|
|
5678
|
+
enum: ["upload", "agent_upload", "wiki_ingest", "external_reference", "manual"]
|
|
5679
|
+
},
|
|
5680
|
+
sourceLabel: { type: "string" },
|
|
5681
|
+
uploadedByUserId: nullable({ type: "string" }),
|
|
5682
|
+
uploadedByAgentId: nullable({ type: "string" }),
|
|
5683
|
+
actingForUserId: nullable({ type: "string" }),
|
|
5684
|
+
downloadPolicy: { type: "string", enum: ["human_only", "disabled"] },
|
|
5685
|
+
links: arrayOf(entityLinkInput),
|
|
5686
|
+
metadata: { type: "object", additionalProperties: true },
|
|
5687
|
+
useLlmEnrichment: { type: "boolean" },
|
|
5688
|
+
llmProfileId: { type: "string" }
|
|
5689
|
+
}
|
|
5690
|
+
};
|
|
5691
|
+
const artifactMetadataPatchInput = {
|
|
5692
|
+
type: "object",
|
|
5693
|
+
properties: {
|
|
5694
|
+
title: { type: "string" },
|
|
5695
|
+
shortDescription: { type: "string" },
|
|
5696
|
+
description: { type: "string" },
|
|
5697
|
+
sourceLabel: { type: "string" },
|
|
5698
|
+
artifactState: {
|
|
5699
|
+
type: "string",
|
|
5700
|
+
enum: ["active", "quarantined", "blocked", "archived", "metadata_only"]
|
|
5701
|
+
},
|
|
5702
|
+
downloadPolicy: { type: "string", enum: ["human_only", "disabled"] },
|
|
5703
|
+
links: arrayOf(entityLinkInput),
|
|
5704
|
+
metadata: { type: "object", additionalProperties: true }
|
|
5705
|
+
}
|
|
5706
|
+
};
|
|
5707
|
+
const artifactTrustPatchInput = {
|
|
5708
|
+
type: "object",
|
|
5709
|
+
required: ["artifactState", "reason"],
|
|
5710
|
+
properties: {
|
|
5711
|
+
artifactState: {
|
|
5712
|
+
type: "string",
|
|
5713
|
+
enum: ["active", "quarantined", "blocked", "archived", "metadata_only"]
|
|
5714
|
+
},
|
|
5715
|
+
reason: { type: "string" },
|
|
5716
|
+
downloadPolicy: { type: "string", enum: ["human_only", "disabled"] }
|
|
5717
|
+
}
|
|
5718
|
+
};
|
|
5719
|
+
const artifactEnrichmentInput = {
|
|
5720
|
+
type: "object",
|
|
5721
|
+
properties: {
|
|
5722
|
+
llmProfileId: { type: "string" },
|
|
5723
|
+
fillMissingOnly: { type: "boolean", default: true },
|
|
5724
|
+
explicitApiKey: {
|
|
5725
|
+
type: "string",
|
|
5726
|
+
description: "Optional transient key for the selected LLM provider. It is not persisted by Forge."
|
|
5727
|
+
}
|
|
5728
|
+
}
|
|
5729
|
+
};
|
|
5730
|
+
const artifactVersion = {
|
|
5731
|
+
type: "object",
|
|
5732
|
+
required: [
|
|
5733
|
+
"id",
|
|
5734
|
+
"artifactId",
|
|
5735
|
+
"versionNumber",
|
|
5736
|
+
"contentSha256",
|
|
5737
|
+
"storageKey",
|
|
5738
|
+
"byteSize",
|
|
5739
|
+
"originalFileName",
|
|
5740
|
+
"scanResults",
|
|
5741
|
+
"enrichmentResults",
|
|
5742
|
+
"createdByActor",
|
|
5743
|
+
"createdAt"
|
|
5744
|
+
],
|
|
5745
|
+
properties: {
|
|
5746
|
+
id: { type: "string" },
|
|
5747
|
+
artifactId: { type: "string" },
|
|
5748
|
+
versionNumber: { type: "integer" },
|
|
5749
|
+
contentSha256: { type: "string" },
|
|
5750
|
+
storageKey: { type: "string" },
|
|
5751
|
+
byteSize: { type: "integer" },
|
|
5752
|
+
originalFileName: { type: "string" },
|
|
5753
|
+
scanResults: { type: "object", additionalProperties: true },
|
|
5754
|
+
enrichmentResults: { type: "object", additionalProperties: true },
|
|
5755
|
+
createdByActor: nullable({ type: "string" }),
|
|
5756
|
+
createdAt: { type: "string", format: "date-time" }
|
|
5757
|
+
}
|
|
5758
|
+
};
|
|
5759
|
+
const artifactAuditEvent = {
|
|
5760
|
+
type: "object",
|
|
5761
|
+
required: ["id", "artifactId", "eventType", "actor", "source", "metadata", "createdAt"],
|
|
5762
|
+
properties: {
|
|
5763
|
+
id: { type: "string" },
|
|
5764
|
+
artifactId: { type: "string" },
|
|
5765
|
+
eventType: { type: "string" },
|
|
5766
|
+
actor: nullable({ type: "string" }),
|
|
5767
|
+
source: { type: "string", enum: ["ui", "openclaw", "agent", "system"] },
|
|
5768
|
+
metadata: { type: "object", additionalProperties: true },
|
|
5769
|
+
createdAt: { type: "string", format: "date-time" }
|
|
5770
|
+
}
|
|
5771
|
+
};
|
|
5506
5772
|
const document = {
|
|
5507
5773
|
openapi: "3.1.0",
|
|
5508
5774
|
info: {
|
|
@@ -5609,6 +5875,17 @@ export function buildOpenApiDocument() {
|
|
|
5609
5875
|
Note: note,
|
|
5610
5876
|
NoteSummary: noteSummary,
|
|
5611
5877
|
NotesSummaryByEntity: notesSummaryByEntity,
|
|
5878
|
+
EntityLink: entityLink,
|
|
5879
|
+
EntityLinkInput: entityLinkInput,
|
|
5880
|
+
ArtifactScanFinding: artifactScanFinding,
|
|
5881
|
+
ArtifactScanResult: artifactScanResult,
|
|
5882
|
+
Artifact: artifact,
|
|
5883
|
+
ArtifactUploadInput: artifactUploadInput,
|
|
5884
|
+
ArtifactMetadataPatchInput: artifactMetadataPatchInput,
|
|
5885
|
+
ArtifactTrustPatchInput: artifactTrustPatchInput,
|
|
5886
|
+
ArtifactEnrichmentInput: artifactEnrichmentInput,
|
|
5887
|
+
ArtifactVersion: artifactVersion,
|
|
5888
|
+
ArtifactAuditEvent: artifactAuditEvent,
|
|
5612
5889
|
HealthLink: healthLink,
|
|
5613
5890
|
SleepSession: sleepSession,
|
|
5614
5891
|
WorkoutSession: workoutSession,
|
|
@@ -5645,6 +5922,298 @@ export function buildOpenApiDocument() {
|
|
|
5645
5922
|
}
|
|
5646
5923
|
},
|
|
5647
5924
|
paths: {
|
|
5925
|
+
"/api/v1/artifacts": {
|
|
5926
|
+
get: {
|
|
5927
|
+
summary: "List artifact metadata",
|
|
5928
|
+
description: "Lists stored file artifacts and their metadata, scan state, danger score, and generic entity links. This route does not return file bytes.",
|
|
5929
|
+
parameters: [
|
|
5930
|
+
{ name: "query", in: "query", schema: { type: "string" } },
|
|
5931
|
+
{
|
|
5932
|
+
name: "artifactState",
|
|
5933
|
+
in: "query",
|
|
5934
|
+
schema: {
|
|
5935
|
+
type: "string",
|
|
5936
|
+
enum: ["active", "quarantined", "blocked", "archived", "metadata_only"]
|
|
5937
|
+
}
|
|
5938
|
+
},
|
|
5939
|
+
{
|
|
5940
|
+
name: "dangerLevel",
|
|
5941
|
+
in: "query",
|
|
5942
|
+
schema: { type: "string", enum: ["low", "moderate", "high", "blocked"] }
|
|
5943
|
+
},
|
|
5944
|
+
{
|
|
5945
|
+
name: "formatFamily",
|
|
5946
|
+
in: "query",
|
|
5947
|
+
schema: {
|
|
5948
|
+
type: "string",
|
|
5949
|
+
enum: [
|
|
5950
|
+
"spreadsheet",
|
|
5951
|
+
"document",
|
|
5952
|
+
"presentation",
|
|
5953
|
+
"pdf",
|
|
5954
|
+
"text",
|
|
5955
|
+
"structured_text",
|
|
5956
|
+
"image"
|
|
5957
|
+
]
|
|
5958
|
+
}
|
|
5959
|
+
},
|
|
5960
|
+
{ name: "linkedEntityType", in: "query", schema: { type: "string" } },
|
|
5961
|
+
{ name: "linkedEntityId", in: "query", schema: { type: "string" } },
|
|
5962
|
+
{ name: "limit", in: "query", schema: { type: "integer", minimum: 1, maximum: 500 } }
|
|
5963
|
+
],
|
|
5964
|
+
responses: {
|
|
5965
|
+
"200": jsonResponse({
|
|
5966
|
+
type: "object",
|
|
5967
|
+
required: ["artifacts"],
|
|
5968
|
+
properties: { artifacts: arrayOf({ $ref: "#/components/schemas/Artifact" }) }
|
|
5969
|
+
}, "Artifact list"),
|
|
5970
|
+
default: { $ref: "#/components/responses/Error" }
|
|
5971
|
+
}
|
|
5972
|
+
},
|
|
5973
|
+
post: {
|
|
5974
|
+
summary: "Upload a trusted file artifact",
|
|
5975
|
+
description: "Stores base64 file bytes only for trusted human sessions or trusted/autonomous agent tokens with artifact upload scopes. Forge statically scans and stores the file for human download; it does not execute or autonomously open the file.",
|
|
5976
|
+
requestBody: {
|
|
5977
|
+
required: true,
|
|
5978
|
+
content: {
|
|
5979
|
+
"application/json": {
|
|
5980
|
+
schema: { $ref: "#/components/schemas/ArtifactUploadInput" }
|
|
5981
|
+
}
|
|
5982
|
+
}
|
|
5983
|
+
},
|
|
5984
|
+
responses: {
|
|
5985
|
+
"201": jsonResponse({
|
|
5986
|
+
type: "object",
|
|
5987
|
+
required: ["artifact"],
|
|
5988
|
+
properties: { artifact: { $ref: "#/components/schemas/Artifact" } }
|
|
5989
|
+
}, "Created artifact"),
|
|
5990
|
+
default: { $ref: "#/components/responses/Error" }
|
|
5991
|
+
}
|
|
5992
|
+
}
|
|
5993
|
+
},
|
|
5994
|
+
"/api/v1/artifacts/{id}": {
|
|
5995
|
+
parameters: [
|
|
5996
|
+
{
|
|
5997
|
+
name: "id",
|
|
5998
|
+
in: "path",
|
|
5999
|
+
required: true,
|
|
6000
|
+
schema: { type: "string" }
|
|
6001
|
+
}
|
|
6002
|
+
],
|
|
6003
|
+
get: {
|
|
6004
|
+
summary: "Get artifact metadata",
|
|
6005
|
+
responses: {
|
|
6006
|
+
"200": jsonResponse({
|
|
6007
|
+
type: "object",
|
|
6008
|
+
required: ["artifact"],
|
|
6009
|
+
properties: { artifact: { $ref: "#/components/schemas/Artifact" } }
|
|
6010
|
+
}, "Artifact metadata"),
|
|
6011
|
+
default: { $ref: "#/components/responses/Error" }
|
|
6012
|
+
}
|
|
6013
|
+
},
|
|
6014
|
+
patch: {
|
|
6015
|
+
summary: "Patch artifact metadata",
|
|
6016
|
+
requestBody: {
|
|
6017
|
+
required: true,
|
|
6018
|
+
content: {
|
|
6019
|
+
"application/json": {
|
|
6020
|
+
schema: { $ref: "#/components/schemas/ArtifactMetadataPatchInput" }
|
|
6021
|
+
}
|
|
6022
|
+
}
|
|
6023
|
+
},
|
|
6024
|
+
responses: {
|
|
6025
|
+
"200": jsonResponse({
|
|
6026
|
+
type: "object",
|
|
6027
|
+
required: ["artifact"],
|
|
6028
|
+
properties: { artifact: { $ref: "#/components/schemas/Artifact" } }
|
|
6029
|
+
}, "Updated artifact"),
|
|
6030
|
+
default: { $ref: "#/components/responses/Error" }
|
|
6031
|
+
}
|
|
6032
|
+
}
|
|
6033
|
+
},
|
|
6034
|
+
"/api/v1/artifacts/{id}/download": {
|
|
6035
|
+
parameters: [
|
|
6036
|
+
{
|
|
6037
|
+
name: "id",
|
|
6038
|
+
in: "path",
|
|
6039
|
+
required: true,
|
|
6040
|
+
schema: { type: "string" }
|
|
6041
|
+
}
|
|
6042
|
+
],
|
|
6043
|
+
get: {
|
|
6044
|
+
summary: "Download artifact bytes for a human operator",
|
|
6045
|
+
description: "Returns the stored file bytes only to an authenticated human/operator session. Agent tokens are not allowed to download artifacts.",
|
|
6046
|
+
responses: {
|
|
6047
|
+
"200": {
|
|
6048
|
+
description: "Artifact file bytes",
|
|
6049
|
+
content: {
|
|
6050
|
+
"application/octet-stream": {
|
|
6051
|
+
schema: { type: "string", format: "binary" }
|
|
6052
|
+
}
|
|
6053
|
+
}
|
|
6054
|
+
},
|
|
6055
|
+
default: { $ref: "#/components/responses/Error" }
|
|
6056
|
+
}
|
|
6057
|
+
}
|
|
6058
|
+
},
|
|
6059
|
+
"/api/v1/artifacts/{id}/scan": {
|
|
6060
|
+
parameters: [
|
|
6061
|
+
{
|
|
6062
|
+
name: "id",
|
|
6063
|
+
in: "path",
|
|
6064
|
+
required: true,
|
|
6065
|
+
schema: { type: "string" }
|
|
6066
|
+
}
|
|
6067
|
+
],
|
|
6068
|
+
post: {
|
|
6069
|
+
summary: "Rescan an artifact with the static safety scanner",
|
|
6070
|
+
responses: {
|
|
6071
|
+
"200": jsonResponse({
|
|
6072
|
+
type: "object",
|
|
6073
|
+
required: ["artifact"],
|
|
6074
|
+
properties: { artifact: { $ref: "#/components/schemas/Artifact" } }
|
|
6075
|
+
}, "Rescanned artifact"),
|
|
6076
|
+
default: { $ref: "#/components/responses/Error" }
|
|
6077
|
+
}
|
|
6078
|
+
}
|
|
6079
|
+
},
|
|
6080
|
+
"/api/v1/artifacts/{id}/enrich": {
|
|
6081
|
+
parameters: [
|
|
6082
|
+
{
|
|
6083
|
+
name: "id",
|
|
6084
|
+
in: "path",
|
|
6085
|
+
required: true,
|
|
6086
|
+
schema: { type: "string" }
|
|
6087
|
+
}
|
|
6088
|
+
],
|
|
6089
|
+
post: {
|
|
6090
|
+
summary: "Use a configured LLM to fill missing artifact metadata",
|
|
6091
|
+
description: "LLM enrichment receives only safe metadata, scan findings, and static text samples. It may propose title, short description, description, tags, and a danger score, but Forge never lowers the deterministic scanner danger score.",
|
|
6092
|
+
requestBody: {
|
|
6093
|
+
required: false,
|
|
6094
|
+
content: {
|
|
6095
|
+
"application/json": {
|
|
6096
|
+
schema: { $ref: "#/components/schemas/ArtifactEnrichmentInput" }
|
|
6097
|
+
}
|
|
6098
|
+
}
|
|
6099
|
+
},
|
|
6100
|
+
responses: {
|
|
6101
|
+
"200": jsonResponse({
|
|
6102
|
+
type: "object",
|
|
6103
|
+
required: ["artifact"],
|
|
6104
|
+
properties: { artifact: { $ref: "#/components/schemas/Artifact" } }
|
|
6105
|
+
}, "Enriched artifact"),
|
|
6106
|
+
default: { $ref: "#/components/responses/Error" }
|
|
6107
|
+
}
|
|
6108
|
+
}
|
|
6109
|
+
},
|
|
6110
|
+
"/api/v1/artifacts/{id}/links": {
|
|
6111
|
+
parameters: [
|
|
6112
|
+
{
|
|
6113
|
+
name: "id",
|
|
6114
|
+
in: "path",
|
|
6115
|
+
required: true,
|
|
6116
|
+
schema: { type: "string" }
|
|
6117
|
+
}
|
|
6118
|
+
],
|
|
6119
|
+
post: {
|
|
6120
|
+
summary: "Replace generic entity links for an artifact",
|
|
6121
|
+
description: "Stores artifact relationships through Forge's reusable entity_links model. Use this to connect artifacts to goals, projects, tasks, wiki-backed notes, Psyche records, calendar entities, and other supported Forge entities.",
|
|
6122
|
+
requestBody: {
|
|
6123
|
+
required: true,
|
|
6124
|
+
content: {
|
|
6125
|
+
"application/json": {
|
|
6126
|
+
schema: {
|
|
6127
|
+
type: "object",
|
|
6128
|
+
required: ["links"],
|
|
6129
|
+
properties: {
|
|
6130
|
+
links: arrayOf({ $ref: "#/components/schemas/EntityLinkInput" })
|
|
6131
|
+
}
|
|
6132
|
+
}
|
|
6133
|
+
}
|
|
6134
|
+
}
|
|
6135
|
+
},
|
|
6136
|
+
responses: {
|
|
6137
|
+
"200": jsonResponse({
|
|
6138
|
+
type: "object",
|
|
6139
|
+
required: ["artifact"],
|
|
6140
|
+
properties: { artifact: { $ref: "#/components/schemas/Artifact" } }
|
|
6141
|
+
}, "Relinked artifact"),
|
|
6142
|
+
default: { $ref: "#/components/responses/Error" }
|
|
6143
|
+
}
|
|
6144
|
+
}
|
|
6145
|
+
},
|
|
6146
|
+
"/api/v1/artifacts/{id}/trust": {
|
|
6147
|
+
parameters: [
|
|
6148
|
+
{
|
|
6149
|
+
name: "id",
|
|
6150
|
+
in: "path",
|
|
6151
|
+
required: true,
|
|
6152
|
+
schema: { type: "string" }
|
|
6153
|
+
}
|
|
6154
|
+
],
|
|
6155
|
+
post: {
|
|
6156
|
+
summary: "Apply a trusted artifact state override",
|
|
6157
|
+
requestBody: {
|
|
6158
|
+
required: true,
|
|
6159
|
+
content: {
|
|
6160
|
+
"application/json": {
|
|
6161
|
+
schema: { $ref: "#/components/schemas/ArtifactTrustPatchInput" }
|
|
6162
|
+
}
|
|
6163
|
+
}
|
|
6164
|
+
},
|
|
6165
|
+
responses: {
|
|
6166
|
+
"200": jsonResponse({
|
|
6167
|
+
type: "object",
|
|
6168
|
+
required: ["artifact"],
|
|
6169
|
+
properties: { artifact: { $ref: "#/components/schemas/Artifact" } }
|
|
6170
|
+
}, "Trust-updated artifact"),
|
|
6171
|
+
default: { $ref: "#/components/responses/Error" }
|
|
6172
|
+
}
|
|
6173
|
+
}
|
|
6174
|
+
},
|
|
6175
|
+
"/api/v1/artifacts/{id}/versions": {
|
|
6176
|
+
parameters: [
|
|
6177
|
+
{
|
|
6178
|
+
name: "id",
|
|
6179
|
+
in: "path",
|
|
6180
|
+
required: true,
|
|
6181
|
+
schema: { type: "string" }
|
|
6182
|
+
}
|
|
6183
|
+
],
|
|
6184
|
+
get: {
|
|
6185
|
+
summary: "List artifact versions",
|
|
6186
|
+
responses: {
|
|
6187
|
+
"200": jsonResponse({
|
|
6188
|
+
type: "object",
|
|
6189
|
+
required: ["versions"],
|
|
6190
|
+
properties: { versions: arrayOf({ $ref: "#/components/schemas/ArtifactVersion" }) }
|
|
6191
|
+
}, "Artifact versions"),
|
|
6192
|
+
default: { $ref: "#/components/responses/Error" }
|
|
6193
|
+
}
|
|
6194
|
+
}
|
|
6195
|
+
},
|
|
6196
|
+
"/api/v1/artifacts/{id}/audit": {
|
|
6197
|
+
parameters: [
|
|
6198
|
+
{
|
|
6199
|
+
name: "id",
|
|
6200
|
+
in: "path",
|
|
6201
|
+
required: true,
|
|
6202
|
+
schema: { type: "string" }
|
|
6203
|
+
}
|
|
6204
|
+
],
|
|
6205
|
+
get: {
|
|
6206
|
+
summary: "List artifact audit events",
|
|
6207
|
+
responses: {
|
|
6208
|
+
"200": jsonResponse({
|
|
6209
|
+
type: "object",
|
|
6210
|
+
required: ["events"],
|
|
6211
|
+
properties: { events: arrayOf({ $ref: "#/components/schemas/ArtifactAuditEvent" }) }
|
|
6212
|
+
}, "Artifact audit events"),
|
|
6213
|
+
default: { $ref: "#/components/responses/Error" }
|
|
6214
|
+
}
|
|
6215
|
+
}
|
|
6216
|
+
},
|
|
5648
6217
|
"/api/v1/health": {
|
|
5649
6218
|
get: {
|
|
5650
6219
|
summary: "Get Forge API health and watchdog status",
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { getDatabase } from "../db.js";
|
|
2
|
+
function mapRow(row) {
|
|
3
|
+
return {
|
|
4
|
+
sourceEntityType: row.source_entity_type,
|
|
5
|
+
sourceEntityId: row.source_entity_id,
|
|
6
|
+
targetEntityType: row.target_entity_type,
|
|
7
|
+
targetEntityId: row.target_entity_id,
|
|
8
|
+
anchorKey: row.anchor_key.trim() || null,
|
|
9
|
+
relationship: row.relationship,
|
|
10
|
+
createdByActor: row.created_by_actor,
|
|
11
|
+
createdAt: row.created_at
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function normalizeLink(link) {
|
|
15
|
+
return {
|
|
16
|
+
entityType: link.entityType.trim(),
|
|
17
|
+
entityId: link.entityId.trim(),
|
|
18
|
+
anchorKey: link.anchorKey?.trim() ?? "",
|
|
19
|
+
relationship: link.relationship?.trim() || "related"
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function normalizeEntityLinks(links) {
|
|
23
|
+
const seen = new Set();
|
|
24
|
+
return links
|
|
25
|
+
.map(normalizeLink)
|
|
26
|
+
.filter((link) => link.entityType.length > 0 && link.entityId.length > 0)
|
|
27
|
+
.filter((link) => {
|
|
28
|
+
const key = `${link.entityType}:${link.entityId}:${link.anchorKey}:${link.relationship}`;
|
|
29
|
+
if (seen.has(key)) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
seen.add(key);
|
|
33
|
+
return true;
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
export function listEntityLinksForSources(sourceEntityType, sourceEntityIds) {
|
|
37
|
+
if (sourceEntityIds.length === 0) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const placeholders = sourceEntityIds.map(() => "?").join(", ");
|
|
41
|
+
const rows = getDatabase()
|
|
42
|
+
.prepare(`SELECT source_entity_type, source_entity_id, target_entity_type, target_entity_id,
|
|
43
|
+
anchor_key, relationship, created_by_actor, created_at
|
|
44
|
+
FROM entity_links
|
|
45
|
+
WHERE source_entity_type = ?
|
|
46
|
+
AND source_entity_id IN (${placeholders})
|
|
47
|
+
ORDER BY created_at ASC`)
|
|
48
|
+
.all(sourceEntityType, ...sourceEntityIds);
|
|
49
|
+
return rows.map(mapRow);
|
|
50
|
+
}
|
|
51
|
+
export function replaceEntityLinksForSource(input) {
|
|
52
|
+
const createdAt = (input.now ?? new Date()).toISOString();
|
|
53
|
+
const normalized = normalizeEntityLinks(input.links);
|
|
54
|
+
getDatabase()
|
|
55
|
+
.prepare(`DELETE FROM entity_links
|
|
56
|
+
WHERE source_entity_type = ?
|
|
57
|
+
AND source_entity_id = ?`)
|
|
58
|
+
.run(input.sourceEntityType, input.sourceEntityId);
|
|
59
|
+
const statement = getDatabase().prepare(`INSERT OR IGNORE INTO entity_links (
|
|
60
|
+
source_entity_type, source_entity_id, target_entity_type, target_entity_id,
|
|
61
|
+
anchor_key, relationship, created_by_actor, created_at
|
|
62
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`);
|
|
63
|
+
for (const link of normalized) {
|
|
64
|
+
statement.run(input.sourceEntityType, input.sourceEntityId, link.entityType, link.entityId, link.anchorKey, link.relationship, input.actor ?? null, createdAt);
|
|
65
|
+
}
|
|
66
|
+
}
|