@cat-factory/integrations 0.25.2 → 0.26.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/documents/ClaudeDesignProvider.d.ts +32 -0
- package/dist/modules/documents/ClaudeDesignProvider.d.ts.map +1 -0
- package/dist/modules/documents/ClaudeDesignProvider.js +163 -0
- package/dist/modules/documents/ClaudeDesignProvider.js.map +1 -0
- package/dist/modules/documents/ConfluenceProvider.d.ts +2 -1
- package/dist/modules/documents/ConfluenceProvider.d.ts.map +1 -1
- package/dist/modules/documents/DocumentConnectionService.d.ts +28 -11
- package/dist/modules/documents/DocumentConnectionService.d.ts.map +1 -1
- package/dist/modules/documents/DocumentConnectionService.js +71 -12
- package/dist/modules/documents/DocumentConnectionService.js.map +1 -1
- package/dist/modules/documents/DocumentImportService.d.ts +9 -3
- package/dist/modules/documents/DocumentImportService.d.ts.map +1 -1
- package/dist/modules/documents/DocumentImportService.js +11 -5
- package/dist/modules/documents/DocumentImportService.js.map +1 -1
- package/dist/modules/documents/FigmaProvider.d.ts +42 -0
- package/dist/modules/documents/FigmaProvider.d.ts.map +1 -0
- package/dist/modules/documents/FigmaProvider.js +176 -0
- package/dist/modules/documents/FigmaProvider.js.map +1 -0
- package/dist/modules/documents/GitHubDocsProvider.d.ts +2 -1
- package/dist/modules/documents/GitHubDocsProvider.d.ts.map +1 -1
- package/dist/modules/documents/LinearDocumentProvider.d.ts +2 -1
- package/dist/modules/documents/LinearDocumentProvider.d.ts.map +1 -1
- package/dist/modules/documents/NotionProvider.d.ts +2 -1
- package/dist/modules/documents/NotionProvider.d.ts.map +1 -1
- package/dist/modules/documents/claudeDesign.logic.d.ts +88 -0
- package/dist/modules/documents/claudeDesign.logic.d.ts.map +1 -0
- package/dist/modules/documents/claudeDesign.logic.js +317 -0
- package/dist/modules/documents/claudeDesign.logic.js.map +1 -0
- package/dist/modules/documents/figma.logic.d.ts +98 -0
- package/dist/modules/documents/figma.logic.d.ts.map +1 -0
- package/dist/modules/documents/figma.logic.js +249 -0
- package/dist/modules/documents/figma.logic.js.map +1 -0
- package/dist/modules/documents/http.d.ts +35 -0
- package/dist/modules/documents/http.d.ts.map +1 -0
- package/dist/modules/documents/http.js +120 -0
- package/dist/modules/documents/http.js.map +1 -0
- package/package.json +3 -3
|
@@ -24,15 +24,21 @@ export class DocumentImportService {
|
|
|
24
24
|
throw new ValidationError(`Unknown or unconfigured document source '${source}'`);
|
|
25
25
|
return provider;
|
|
26
26
|
}
|
|
27
|
-
/**
|
|
28
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Fetch a page (by id or URL) and upsert its projection; returns the document.
|
|
29
|
+
* `ownerUserId` resolves the credential for a personal (`credentialScope: 'user'`)
|
|
30
|
+
* source — the acting user — and is ignored for workspace sources. The cached
|
|
31
|
+
* projection is always workspace-scoped, so a personal source's imported page is
|
|
32
|
+
* shared with the workspace once fetched (only the *credential* is personal).
|
|
33
|
+
*/
|
|
34
|
+
async import(workspaceId, source, ref, ownerUserId = '') {
|
|
29
35
|
await requireWorkspace(this.deps.workspaceRepository, workspaceId);
|
|
30
36
|
const provider = this.requireProvider(source);
|
|
31
37
|
const externalId = provider.parseRef(ref);
|
|
32
38
|
if (!externalId) {
|
|
33
39
|
throw new ValidationError(`Could not resolve a ${source} page id from '${ref}'`);
|
|
34
40
|
}
|
|
35
|
-
const connection = await this.deps.connectionService.requireConnection(workspaceId, source);
|
|
41
|
+
const connection = await this.deps.connectionService.requireConnection(workspaceId, source, ownerUserId);
|
|
36
42
|
const content = await provider.fetchDocument(connection.credentials, externalId);
|
|
37
43
|
// Preserve any existing block link across a re-import.
|
|
38
44
|
const existing = await this.deps.documentRepository.get(workspaceId, source, content.externalId);
|
|
@@ -70,13 +76,13 @@ export class DocumentImportService {
|
|
|
70
76
|
* and builds/parses the source-specific query. Throws if the source can't
|
|
71
77
|
* search (no provider `search`), so the controller can answer cleanly.
|
|
72
78
|
*/
|
|
73
|
-
async search(workspaceId, source, query) {
|
|
79
|
+
async search(workspaceId, source, query, ownerUserId = '') {
|
|
74
80
|
await requireWorkspace(this.deps.workspaceRepository, workspaceId);
|
|
75
81
|
const provider = this.requireProvider(source);
|
|
76
82
|
if (!provider.search) {
|
|
77
83
|
throw new ValidationError(`The ${source} source does not support search`);
|
|
78
84
|
}
|
|
79
|
-
const connection = await this.deps.connectionService.requireConnection(workspaceId, source);
|
|
85
|
+
const connection = await this.deps.connectionService.requireConnection(workspaceId, source, ownerUserId);
|
|
80
86
|
return provider.search(connection.credentials, query, workspaceId);
|
|
81
87
|
}
|
|
82
88
|
/** Every document imported into the workspace, across sources, as wire shapes. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentImportService.js","sourceRoot":"","sources":["../../../src/modules/documents/DocumentImportService.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAGtD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAgBnD,qFAAqF;AACrF,MAAM,UAAU,gBAAgB,CAAC,MAAsB;IACrD,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,MAAM,CAAC,aAAa;QACnC,QAAQ,EAAE,MAAM,CAAC,QAAQ;KAC1B,CAAA;AACH,CAAC;AAED,MAAM,OAAO,qBAAqB;IACH,IAAI;IAAjC,YAA6B,IAAuC;oBAAvC,IAAI;IAAsC,CAAC;IAEhE,eAAe,CAAC,MAA0B;QAChD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAC/C,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,eAAe,CAAC,4CAA4C,MAAM,GAAG,CAAC,CAAA;QAC/F,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"DocumentImportService.js","sourceRoot":"","sources":["../../../src/modules/documents/DocumentImportService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type DocumentContent, type DocumentCredentials, type DocumentSourceProvider, type NormalizedConnection } from '@cat-factory/kernel';
|
|
2
|
+
/** Carries the HTTP status so callers can surface a meaningful error. */
|
|
3
|
+
export declare class FigmaApiError extends Error {
|
|
4
|
+
readonly status: number;
|
|
5
|
+
constructor(status: number, message: string);
|
|
6
|
+
}
|
|
7
|
+
export declare class FigmaProvider implements DocumentSourceProvider {
|
|
8
|
+
readonly kind: 'figma';
|
|
9
|
+
readonly descriptor: {
|
|
10
|
+
source: "claude-design" | "confluence" | "figma" | "github" | "linear" | "notion";
|
|
11
|
+
label: string;
|
|
12
|
+
icon: string;
|
|
13
|
+
credentialFields: {
|
|
14
|
+
key: string;
|
|
15
|
+
label: string;
|
|
16
|
+
help?: string | undefined;
|
|
17
|
+
placeholder?: string | undefined;
|
|
18
|
+
secret?: boolean | undefined;
|
|
19
|
+
}[];
|
|
20
|
+
refLabel: string;
|
|
21
|
+
refPlaceholder: string;
|
|
22
|
+
searchable?: boolean | undefined;
|
|
23
|
+
credentialScope?: "user" | "workspace" | undefined;
|
|
24
|
+
};
|
|
25
|
+
normalizeConnection(input: DocumentCredentials): NormalizedConnection;
|
|
26
|
+
parseRef(input: string): string | null;
|
|
27
|
+
fetchDocument(credentials: DocumentCredentials, externalId: string): Promise<DocumentContent>;
|
|
28
|
+
/** Fetch a specific node's subtree, or the whole file's document, plus its components. */
|
|
29
|
+
private fetchNodes;
|
|
30
|
+
/**
|
|
31
|
+
* Fetch local variables (design tokens); null on the Enterprise-gating 403/404. Fully
|
|
32
|
+
* best-effort: any transport failure (incl. a blocked-redirect `DocumentHttpError`)
|
|
33
|
+
* drops the section rather than failing the whole import.
|
|
34
|
+
*/
|
|
35
|
+
private fetchVariables;
|
|
36
|
+
/** Best-effort short-lived PNG render URL for the node (or whole file); null on any failure. */
|
|
37
|
+
private fetchPreviewUrl;
|
|
38
|
+
private headers;
|
|
39
|
+
private parse;
|
|
40
|
+
private get;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=FigmaProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FigmaProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/FigmaProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAsB5B,yEAAyE;AACzE,qBAAa,aAAc,SAAQ,KAAK;IAEpC,QAAQ,CAAC,MAAM,EAAE,MAAM;IADzB,YACW,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAIhB;CACF;AAgCD,qBAAa,aAAc,YAAW,sBAAsB;IAC1D,QAAQ,CAAC,IAAI,EAAG,OAAO,CAAS;IAChC,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;;MAAmB;IAEtC,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CAMpE;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErC;IAEK,aAAa,CACjB,WAAW,EAAE,mBAAmB,EAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CA0B1B;IAED,0FAA0F;YAC5E,UAAU;IAyCxB;;;;OAIG;YACW,cAAc;IAmB5B,gGAAgG;YAClF,eAAe;IAqB7B,OAAO,CAAC,OAAO;IAQf,OAAO,CAAC,KAAK;YAQC,GAAG;CAqBlB"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { ValidationError, } from '@cat-factory/kernel';
|
|
2
|
+
import { FIGMA_API_HOST, FIGMA_DESCRIPTOR } from './figma.logic.js';
|
|
3
|
+
import * as figmaLogic from './figma.logic.js';
|
|
4
|
+
import { DocumentHttpError, createHostPinnedFetch, readCappedText } from './http.js';
|
|
5
|
+
// FigmaProvider: the document-source provider for Figma. It authenticates with a
|
|
6
|
+
// per-workspace personal access token (the `X-Figma-Token` header), fetches a
|
|
7
|
+
// file or a specific frame/node via the REST API, and renders the layout tree,
|
|
8
|
+
// text, components-used and (Enterprise-gated) design tokens to the Markdown the
|
|
9
|
+
// planner + `.cat-context/` materialisation consume. All Figma-specific *pure*
|
|
10
|
+
// logic (ref parsing, the fixed-host SSRF guard, JSON → Markdown) lives in
|
|
11
|
+
// `figma.logic.ts` so it is unit-testable; this class is the thin `fetch` shell.
|
|
12
|
+
// Because the API host is fixed (`api.figma.com`) and there is no per-site base
|
|
13
|
+
// URL, the only SSRF surface is a redirect off-host — guarded per hop below.
|
|
14
|
+
const API_BASE = 'https://api.figma.com/v1';
|
|
15
|
+
const USER_AGENT = 'cat-factory';
|
|
16
|
+
/** Depth fetched for a whole-file link (a node link fetches its own subtree). */
|
|
17
|
+
const FILE_DEPTH = 2;
|
|
18
|
+
/** Hard cap on the bytes read off any response body, to protect the isolate. */
|
|
19
|
+
const MAX_RESPONSE_BYTES = 5_000_000;
|
|
20
|
+
/** Carries the HTTP status so callers can surface a meaningful error. */
|
|
21
|
+
export class FigmaApiError extends Error {
|
|
22
|
+
status;
|
|
23
|
+
constructor(status, message) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.status = status;
|
|
26
|
+
this.name = 'FigmaApiError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* `fetch` pinned to `api.figma.com`, following redirects by hand so the SSRF host
|
|
31
|
+
* guard runs against every hop (a 302 can't chase the PAT off-host). The transport +
|
|
32
|
+
* capped-read are the shared documents `http` helpers; only the host/label differ.
|
|
33
|
+
*/
|
|
34
|
+
const safeFetch = createHostPinnedFetch({ host: FIGMA_API_HOST, label: 'Figma' });
|
|
35
|
+
export class FigmaProvider {
|
|
36
|
+
kind = 'figma';
|
|
37
|
+
descriptor = FIGMA_DESCRIPTOR;
|
|
38
|
+
normalizeConnection(input) {
|
|
39
|
+
const apiToken = input.apiToken?.trim();
|
|
40
|
+
if (!apiToken) {
|
|
41
|
+
throw new ValidationError('Figma requires a personal access token');
|
|
42
|
+
}
|
|
43
|
+
return { credentials: { apiToken }, label: 'Figma' };
|
|
44
|
+
}
|
|
45
|
+
parseRef(input) {
|
|
46
|
+
return figmaLogic.parseFigmaRef(input);
|
|
47
|
+
}
|
|
48
|
+
async fetchDocument(credentials, externalId) {
|
|
49
|
+
const { fileKey, nodeId } = figmaLogic.splitFigmaExternalId(externalId);
|
|
50
|
+
if (!fileKey) {
|
|
51
|
+
throw new FigmaApiError(400, `Figma ref is missing a file key: ${externalId}`);
|
|
52
|
+
}
|
|
53
|
+
const { roots, components, fileName } = await this.fetchNodes(credentials, fileKey, nodeId);
|
|
54
|
+
const sections = [figmaLogic.figmaNodesToMarkdown(roots, components)];
|
|
55
|
+
// Design tokens are Enterprise-gated; on 403/404 drop the section, don't fail.
|
|
56
|
+
const tokens = await this.fetchVariables(credentials, fileKey);
|
|
57
|
+
if (tokens)
|
|
58
|
+
sections.push(tokens);
|
|
59
|
+
// A rendered preview rides along as a reference line (no download). Best-effort:
|
|
60
|
+
// a non-multimodal agent ignores it and the short-lived URL may expire.
|
|
61
|
+
const preview = await this.fetchPreviewUrl(credentials, fileKey, nodeId);
|
|
62
|
+
if (preview)
|
|
63
|
+
sections.push(`### Rendered preview\nRendered preview: ${preview}`);
|
|
64
|
+
const title = nodeId ? `${fileName} — ${roots[0]?.name?.trim() || nodeId}` : fileName || fileKey;
|
|
65
|
+
return {
|
|
66
|
+
externalId,
|
|
67
|
+
title,
|
|
68
|
+
url: figmaLogic.figmaUrlFor(externalId),
|
|
69
|
+
body: sections.filter(Boolean).join('\n\n').trim(),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
/** Fetch a specific node's subtree, or the whole file's document, plus its components. */
|
|
73
|
+
async fetchNodes(credentials, fileKey, nodeId) {
|
|
74
|
+
if (nodeId) {
|
|
75
|
+
const res = await this.get(credentials, `/files/${encodeURIComponent(fileKey)}/nodes?ids=${encodeURIComponent(nodeId)}`);
|
|
76
|
+
const entry = res.nodes?.[nodeId];
|
|
77
|
+
if (!entry?.document) {
|
|
78
|
+
throw new FigmaApiError(404, `Figma node ${nodeId} not found in file ${fileKey}`);
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
roots: [entry.document],
|
|
82
|
+
components: entry.components ?? {},
|
|
83
|
+
fileName: res.name ?? fileKey,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
const res = await this.get(credentials, `/files/${encodeURIComponent(fileKey)}?depth=${FILE_DEPTH}`);
|
|
87
|
+
if (!res.document) {
|
|
88
|
+
throw new FigmaApiError(502, `Figma returned no document for file ${fileKey}`);
|
|
89
|
+
}
|
|
90
|
+
// For a whole-file link the document's children are the pages/canvases; render
|
|
91
|
+
// each top-level frame under them as a section root.
|
|
92
|
+
const roots = (res.document.children ?? []).flatMap((page) => page.children ?? []);
|
|
93
|
+
return {
|
|
94
|
+
roots: roots.length ? roots : [res.document],
|
|
95
|
+
components: res.components ?? {},
|
|
96
|
+
fileName: res.name ?? fileKey,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Fetch local variables (design tokens); null on the Enterprise-gating 403/404. Fully
|
|
101
|
+
* best-effort: any transport failure (incl. a blocked-redirect `DocumentHttpError`)
|
|
102
|
+
* drops the section rather than failing the whole import.
|
|
103
|
+
*/
|
|
104
|
+
async fetchVariables(credentials, fileKey) {
|
|
105
|
+
try {
|
|
106
|
+
const res = await safeFetch(`${API_BASE}/files/${encodeURIComponent(fileKey)}/variables/local`, { method: 'GET', headers: this.headers(credentials) });
|
|
107
|
+
if (res.status === 403 || res.status === 404)
|
|
108
|
+
return null;
|
|
109
|
+
if (!res.ok)
|
|
110
|
+
return null;
|
|
111
|
+
const json = this.parse(await readCappedText(res, MAX_RESPONSE_BYTES));
|
|
112
|
+
const markdown = figmaLogic.figmaVariablesToMarkdown(json?.meta);
|
|
113
|
+
return markdown || null;
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/** Best-effort short-lived PNG render URL for the node (or whole file); null on any failure. */
|
|
120
|
+
async fetchPreviewUrl(credentials, fileKey, nodeId) {
|
|
121
|
+
if (!nodeId)
|
|
122
|
+
return null;
|
|
123
|
+
try {
|
|
124
|
+
const res = await safeFetch(`${API_BASE}/images/${encodeURIComponent(fileKey)}?ids=${encodeURIComponent(nodeId)}&format=png`, { method: 'GET', headers: this.headers(credentials) });
|
|
125
|
+
if (!res.ok)
|
|
126
|
+
return null;
|
|
127
|
+
const json = this.parse(await readCappedText(res, MAX_RESPONSE_BYTES));
|
|
128
|
+
if (!json || json.err)
|
|
129
|
+
return null;
|
|
130
|
+
const url = json.images?.[nodeId];
|
|
131
|
+
return typeof url === 'string' ? url : null;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
headers(credentials) {
|
|
138
|
+
return {
|
|
139
|
+
'x-figma-token': credentials.apiToken ?? '',
|
|
140
|
+
accept: 'application/json',
|
|
141
|
+
'user-agent': USER_AGENT,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
parse(text) {
|
|
145
|
+
try {
|
|
146
|
+
return JSON.parse(text);
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async get(credentials, path) {
|
|
153
|
+
const url = `${API_BASE}${path}`;
|
|
154
|
+
let res;
|
|
155
|
+
try {
|
|
156
|
+
res = await safeFetch(url, { method: 'GET', headers: this.headers(credentials) });
|
|
157
|
+
}
|
|
158
|
+
catch (err) {
|
|
159
|
+
// The shared transport raises DocumentHttpError on a blocked/off-host redirect;
|
|
160
|
+
// surface it as the provider's own error type so callers see one shape.
|
|
161
|
+
if (err instanceof DocumentHttpError)
|
|
162
|
+
throw new FigmaApiError(err.status, err.message);
|
|
163
|
+
throw err;
|
|
164
|
+
}
|
|
165
|
+
if (!res.ok) {
|
|
166
|
+
const text = await readCappedText(res, MAX_RESPONSE_BYTES).catch(() => '');
|
|
167
|
+
throw new FigmaApiError(res.status, `Figma GET ${url} → ${res.status}: ${text.slice(0, 300)}`);
|
|
168
|
+
}
|
|
169
|
+
const json = this.parse(await readCappedText(res, MAX_RESPONSE_BYTES));
|
|
170
|
+
if (json === null) {
|
|
171
|
+
throw new FigmaApiError(502, `Figma returned an unparseable body for ${path}`);
|
|
172
|
+
}
|
|
173
|
+
return json;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=FigmaProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FigmaProvider.js","sourceRoot":"","sources":["../../../src/modules/documents/FigmaProvider.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,7 +8,7 @@ export declare class GitHubDocsProvider implements DocumentSourceProvider {
|
|
|
8
8
|
private readonly deps;
|
|
9
9
|
readonly kind: 'github';
|
|
10
10
|
readonly descriptor: {
|
|
11
|
-
source: "confluence" | "github" | "linear" | "notion";
|
|
11
|
+
source: "claude-design" | "confluence" | "figma" | "github" | "linear" | "notion";
|
|
12
12
|
label: string;
|
|
13
13
|
icon: string;
|
|
14
14
|
credentialFields: {
|
|
@@ -21,6 +21,7 @@ export declare class GitHubDocsProvider implements DocumentSourceProvider {
|
|
|
21
21
|
refLabel: string;
|
|
22
22
|
refPlaceholder: string;
|
|
23
23
|
searchable?: boolean | undefined;
|
|
24
|
+
credentialScope?: "user" | "workspace" | undefined;
|
|
24
25
|
};
|
|
25
26
|
constructor(deps: GitHubDocsProviderDependencies);
|
|
26
27
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GitHubDocsProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/GitHubDocsProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,KAAK,4BAA4B,EACjC,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAe5B,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,YAAY,CAAA;IAC1B,8EAA8E;IAC9E,aAAa,EAAE,4BAA4B,CAAA;CAC5C;AAED,qBAAa,kBAAmB,YAAW,sBAAsB;IAInD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAS;IACjC,QAAQ,CAAC,UAAU
|
|
1
|
+
{"version":3,"file":"GitHubDocsProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/GitHubDocsProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,YAAY,EACjB,KAAK,4BAA4B,EACjC,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAe5B,MAAM,WAAW,8BAA8B;IAC7C,YAAY,EAAE,YAAY,CAAA;IAC1B,8EAA8E;IAC9E,aAAa,EAAE,4BAA4B,CAAA;CAC5C;AAED,qBAAa,kBAAmB,YAAW,sBAAsB;IAInD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAHjC,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAS;IACjC,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;;MAAyB;IAE5C,YAA6B,IAAI,EAAE,8BAA8B,EAAI;IAErE;;;;OAIG;IACH,mBAAmB,CAAC,MAAM,EAAE,mBAAmB,GAAG,oBAAoB,CAErE;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErC;IAEK,aAAa,CACjB,YAAY,EAAE,mBAAmB,EACjC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAoB1B;IAEK,MAAM,CACV,YAAY,EAAE,mBAAmB,EACjC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAkCjC;IAED;;;;OAIG;YACW,qBAAqB;CAUpC"}
|
|
@@ -2,7 +2,7 @@ import { type DocumentContent, type DocumentCredentials, type DocumentSearchResu
|
|
|
2
2
|
export declare class LinearDocumentProvider implements DocumentSourceProvider {
|
|
3
3
|
readonly kind: 'linear';
|
|
4
4
|
readonly descriptor: {
|
|
5
|
-
source: "confluence" | "github" | "linear" | "notion";
|
|
5
|
+
source: "claude-design" | "confluence" | "figma" | "github" | "linear" | "notion";
|
|
6
6
|
label: string;
|
|
7
7
|
icon: string;
|
|
8
8
|
credentialFields: {
|
|
@@ -15,6 +15,7 @@ export declare class LinearDocumentProvider implements DocumentSourceProvider {
|
|
|
15
15
|
refLabel: string;
|
|
16
16
|
refPlaceholder: string;
|
|
17
17
|
searchable?: boolean | undefined;
|
|
18
|
+
credentialScope?: "user" | "workspace" | undefined;
|
|
18
19
|
};
|
|
19
20
|
normalizeConnection(input: DocumentCredentials): NormalizedConnection;
|
|
20
21
|
parseRef(input: string): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LinearDocumentProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/LinearDocumentProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAsB5B,qBAAa,sBAAuB,YAAW,sBAAsB;IACnE,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAS;IACjC,QAAQ,CAAC,UAAU
|
|
1
|
+
{"version":3,"file":"LinearDocumentProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/LinearDocumentProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAsB5B,qBAAa,sBAAuB,YAAW,sBAAsB;IACnE,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAS;IACjC,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;;MAAyB;IAE5C,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CAMpE;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErC;IAEK,aAAa,CACjB,WAAW,EAAE,mBAAmB,EAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAM1B;IAEK,MAAM,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAO7F;CACF"}
|
|
@@ -7,7 +7,7 @@ export declare class NotionApiError extends Error {
|
|
|
7
7
|
export declare class NotionProvider implements DocumentSourceProvider {
|
|
8
8
|
readonly kind: 'notion';
|
|
9
9
|
readonly descriptor: {
|
|
10
|
-
source: "confluence" | "github" | "linear" | "notion";
|
|
10
|
+
source: "claude-design" | "confluence" | "figma" | "github" | "linear" | "notion";
|
|
11
11
|
label: string;
|
|
12
12
|
icon: string;
|
|
13
13
|
credentialFields: {
|
|
@@ -20,6 +20,7 @@ export declare class NotionProvider implements DocumentSourceProvider {
|
|
|
20
20
|
refLabel: string;
|
|
21
21
|
refPlaceholder: string;
|
|
22
22
|
searchable?: boolean | undefined;
|
|
23
|
+
credentialScope?: "user" | "workspace" | undefined;
|
|
23
24
|
};
|
|
24
25
|
normalizeConnection(input: DocumentCredentials): NormalizedConnection;
|
|
25
26
|
parseRef(input: string): string | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NotionProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/NotionProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAuB5B,yEAAyE;AACzE,qBAAa,cAAe,SAAQ,KAAK;IAErC,QAAQ,CAAC,MAAM,EAAE,MAAM;IADzB,YACW,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAIhB;CACF;AAkGD,qBAAa,cAAe,YAAW,sBAAsB;IAC3D,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAS;IACjC,QAAQ,CAAC,UAAU
|
|
1
|
+
{"version":3,"file":"NotionProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/NotionProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AAuB5B,yEAAyE;AACzE,qBAAa,cAAe,SAAQ,KAAK;IAErC,QAAQ,CAAC,MAAM,EAAE,MAAM;IADzB,YACW,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EAIhB;CACF;AAkGD,qBAAa,cAAe,YAAW,sBAAsB;IAC3D,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAS;IACjC,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;;MAAoB;IAEvC,mBAAmB,CAAC,KAAK,EAAE,mBAAmB,GAAG,oBAAoB,CAMpE;IAED,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErC;IAEK,aAAa,CACjB,WAAW,EAAE,mBAAmB,EAChC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,eAAe,CAAC,CAe1B;IAEK,MAAM,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CA6B7F;IAED,iFAAiF;YACnE,WAAW;YAqBX,GAAG;CA+BlB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { DocumentSourceDescriptor } from '@cat-factory/kernel';
|
|
2
|
+
/**
|
|
3
|
+
* Claude Design's programmatic-read host. PROVISIONAL: today the design-system read is
|
|
4
|
+
* bound to a claude.ai login; this provider targets the per-user-PAT API shape the
|
|
5
|
+
* product is moving toward. The host is pinned (see {@link assertSafeClaudeDesignUrl})
|
|
6
|
+
* and the exact endpoints in `ClaudeDesignProvider` should be re-verified against the
|
|
7
|
+
* current API when the credentialed read ships — treat them as the intended shape, not a
|
|
8
|
+
* frozen contract.
|
|
9
|
+
*/
|
|
10
|
+
export declare const CLAUDE_DESIGN_API_HOST = "api.claude.com";
|
|
11
|
+
/** Where a human opens the project (the canonical URL stored on imported documents). */
|
|
12
|
+
export declare const CLAUDE_DESIGN_APP_HOST = "claude.ai";
|
|
13
|
+
/** What the connect UI renders, and which credentials the provider needs. */
|
|
14
|
+
export declare const CLAUDE_DESIGN_DESCRIPTOR: DocumentSourceDescriptor;
|
|
15
|
+
/**
|
|
16
|
+
* The Claude Design read host is fixed, so any request/redirect must stay on it over
|
|
17
|
+
* https. A redirect off-host (e.g. to a link-local metadata address) is rejected as an
|
|
18
|
+
* SSRF attempt. Delegates to the shared host-pin guard; throws a plain `Error` the
|
|
19
|
+
* provider maps to a `DocumentHttpError`. Kept pure so it is unit-testable without a
|
|
20
|
+
* network.
|
|
21
|
+
*/
|
|
22
|
+
export declare function assertSafeClaudeDesignUrl(url: string): void;
|
|
23
|
+
/**
|
|
24
|
+
* Resolve a Claude Design reference from raw user input into the stable composite
|
|
25
|
+
* external id this provider stores: `"<projectId>"` for a whole project, or
|
|
26
|
+
* `"<projectId>::<filePath>"` for a single component/file. Accepts a
|
|
27
|
+
* `claude.ai/design/<projectId>` URL (optionally `…/files/<path>` or `?file=<path>`), a
|
|
28
|
+
* bare project id, or the composite form. Returns null when no project id is found.
|
|
29
|
+
*
|
|
30
|
+
* Deterministic (same input → same external id), which the
|
|
31
|
+
* `(workspace, source, externalId)` document key relies on for de-duplication.
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseClaudeDesignRef(input: string): string | null;
|
|
34
|
+
/** Split a composite external id back into its project id and optional file path. */
|
|
35
|
+
export declare function splitClaudeDesignExternalId(externalId: string): {
|
|
36
|
+
projectId: string;
|
|
37
|
+
filePath?: string;
|
|
38
|
+
};
|
|
39
|
+
/** Build the canonical web URL stored on the imported document (matched by `getByUrl`). */
|
|
40
|
+
export declare function claudeDesignUrlFor(externalId: string): string;
|
|
41
|
+
/** A single component card, as recorded by Claude Design's `@dsCard` markers/manifest. */
|
|
42
|
+
export interface DsCard {
|
|
43
|
+
name?: string;
|
|
44
|
+
group?: string;
|
|
45
|
+
subtitle?: string;
|
|
46
|
+
path?: string;
|
|
47
|
+
}
|
|
48
|
+
/** One fetched project file (path + raw textual content). */
|
|
49
|
+
export interface ClaudeDesignFile {
|
|
50
|
+
path: string;
|
|
51
|
+
content: string;
|
|
52
|
+
}
|
|
53
|
+
/** The manifest file name Claude Design compiles its card index into. */
|
|
54
|
+
export declare const DS_MANIFEST_PATH = "_ds_manifest.json";
|
|
55
|
+
/**
|
|
56
|
+
* Parse a `_ds_manifest.json` payload (a bare array of cards, or `{ cards: [...] }`)
|
|
57
|
+
* into a lenient {@link DsCard} list. Unknown shapes yield `[]` so the caller falls
|
|
58
|
+
* back to per-file HTML extraction.
|
|
59
|
+
*/
|
|
60
|
+
export declare function parseDsManifest(json: unknown): DsCard[];
|
|
61
|
+
/**
|
|
62
|
+
* Read the first-line `<!-- @dsCard group="…" name="…" subtitle="…" -->` marker Claude
|
|
63
|
+
* Design writes at the top of each component-preview HTML. Returns null when absent.
|
|
64
|
+
*/
|
|
65
|
+
export declare function parseDsCardComment(html: string): DsCard | null;
|
|
66
|
+
/**
|
|
67
|
+
* Extract CSS custom properties (`--token: value`) from a stylesheet/HTML blob as design
|
|
68
|
+
* tokens, deduped (last value wins) and sorted. These are Claude Design's design tokens —
|
|
69
|
+
* the analogue of Figma variables.
|
|
70
|
+
*/
|
|
71
|
+
export declare function extractCssTokens(content: string): string[];
|
|
72
|
+
/** Strip `<script>`/`<style>` blocks and all tags, returning collapsed visible text. */
|
|
73
|
+
export declare function htmlToText(html: string): string;
|
|
74
|
+
/** Render a grouped component inventory from a card list (`### <group>` → `- <name>`). */
|
|
75
|
+
export declare function dsCardsToMarkdown(cards: DsCard[]): string;
|
|
76
|
+
/**
|
|
77
|
+
* Normalize a whole Claude Design project's fetched files into the lightweight Markdown a
|
|
78
|
+
* frontend agent consumes. Strategy:
|
|
79
|
+
* 1. If a `_ds_manifest.json` is present, it is the authoritative component index →
|
|
80
|
+
* `### Components` grouped inventory.
|
|
81
|
+
* 2. Otherwise, recover the inventory from each preview HTML's `@dsCard` marker.
|
|
82
|
+
* 3. Design tokens are unioned from the CSS custom properties across all files.
|
|
83
|
+
* 4. A bounded slice of visible text gives the agent a sense of the content.
|
|
84
|
+
*
|
|
85
|
+
* `projectName` titles the document. Pure: no network, fully unit-testable.
|
|
86
|
+
*/
|
|
87
|
+
export declare function renderClaudeDesignProject(projectName: string, files: ClaudeDesignFile[]): string;
|
|
88
|
+
//# sourceMappingURL=claudeDesign.logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claudeDesign.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/claudeDesign.logic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAmBnE;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,mBAAmB,CAAA;AAEtD,wFAAwF;AACxF,eAAO,MAAM,sBAAsB,cAAc,CAAA;AAEjD,6EAA6E;AAC7E,eAAO,MAAM,wBAAwB,EAAE,wBAmBtC,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAE3D;AASD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkCjE;AAWD,qFAAqF;AACrF,wBAAgB,2BAA2B,CAAC,UAAU,EAAE,MAAM,GAAG;IAC/D,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAKA;AAED,2FAA2F;AAC3F,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAI7D;AAID,0FAA0F;AAC1F,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,6DAA6D;AAC7D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,yEAAyE;AACzE,eAAO,MAAM,gBAAgB,sBAAsB,CAAA;AAMnD;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CAmBvD;AAKD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY9D;AAID;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAW1D;AAED,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAc/C;AAED,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAsBzD;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,MAAM,CA+ChG"}
|