@cat-factory/integrations 0.32.0 → 0.33.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.
Files changed (48) hide show
  1. package/dist/index.d.ts +4 -3
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +4 -3
  4. package/dist/index.js.map +1 -1
  5. package/dist/modules/documents/ConfluenceProvider.d.ts +1 -2
  6. package/dist/modules/documents/ConfluenceProvider.d.ts.map +1 -1
  7. package/dist/modules/documents/DocumentConnectionService.d.ts +11 -28
  8. package/dist/modules/documents/DocumentConnectionService.d.ts.map +1 -1
  9. package/dist/modules/documents/DocumentConnectionService.js +12 -71
  10. package/dist/modules/documents/DocumentConnectionService.js.map +1 -1
  11. package/dist/modules/documents/DocumentImportService.d.ts +4 -7
  12. package/dist/modules/documents/DocumentImportService.d.ts.map +1 -1
  13. package/dist/modules/documents/DocumentImportService.js +6 -9
  14. package/dist/modules/documents/DocumentImportService.js.map +1 -1
  15. package/dist/modules/documents/FigmaProvider.d.ts +4 -5
  16. package/dist/modules/documents/FigmaProvider.d.ts.map +1 -1
  17. package/dist/modules/documents/FigmaProvider.js +22 -21
  18. package/dist/modules/documents/FigmaProvider.js.map +1 -1
  19. package/dist/modules/documents/GitHubDocsProvider.d.ts +1 -2
  20. package/dist/modules/documents/GitHubDocsProvider.d.ts.map +1 -1
  21. package/dist/modules/documents/LinearDocumentProvider.d.ts +1 -2
  22. package/dist/modules/documents/LinearDocumentProvider.d.ts.map +1 -1
  23. package/dist/modules/documents/NotionProvider.d.ts +1 -2
  24. package/dist/modules/documents/NotionProvider.d.ts.map +1 -1
  25. package/dist/modules/documents/{ClaudeDesignProvider.d.ts → ZeplinProvider.d.ts} +12 -11
  26. package/dist/modules/documents/ZeplinProvider.d.ts.map +1 -0
  27. package/dist/modules/documents/ZeplinProvider.js +126 -0
  28. package/dist/modules/documents/ZeplinProvider.js.map +1 -0
  29. package/dist/modules/documents/design.logic.d.ts +60 -0
  30. package/dist/modules/documents/design.logic.d.ts.map +1 -0
  31. package/dist/modules/documents/design.logic.js +0 -0
  32. package/dist/modules/documents/design.logic.js.map +1 -0
  33. package/dist/modules/documents/figma.logic.d.ts +30 -9
  34. package/dist/modules/documents/figma.logic.d.ts.map +1 -1
  35. package/dist/modules/documents/figma.logic.js +51 -36
  36. package/dist/modules/documents/figma.logic.js.map +1 -1
  37. package/dist/modules/documents/zeplin.logic.d.ts +102 -0
  38. package/dist/modules/documents/zeplin.logic.d.ts.map +1 -0
  39. package/dist/modules/documents/zeplin.logic.js +193 -0
  40. package/dist/modules/documents/zeplin.logic.js.map +1 -0
  41. package/package.json +3 -3
  42. package/dist/modules/documents/ClaudeDesignProvider.d.ts.map +0 -1
  43. package/dist/modules/documents/ClaudeDesignProvider.js +0 -163
  44. package/dist/modules/documents/ClaudeDesignProvider.js.map +0 -1
  45. package/dist/modules/documents/claudeDesign.logic.d.ts +0 -88
  46. package/dist/modules/documents/claudeDesign.logic.d.ts.map +0 -1
  47. package/dist/modules/documents/claudeDesign.logic.js +0 -317
  48. package/dist/modules/documents/claudeDesign.logic.js.map +0 -1
@@ -0,0 +1,102 @@
1
+ import type { DocumentSourceDescriptor } from '@cat-factory/kernel';
2
+ import { type DesignBlock, type DesignComponent, type DesignContext, type DesignToken } from './design.logic.js';
3
+ /** Zeplin's REST API host. The PAT is sent to this host only — see {@link assertSafeZeplinUrl}. */
4
+ export declare const ZEPLIN_API_HOST = "api.zeplin.dev";
5
+ /** What the connect UI renders, and which credentials the provider needs. */
6
+ export declare const ZEPLIN_DESCRIPTOR: DocumentSourceDescriptor;
7
+ /**
8
+ * The Zeplin REST host is fixed, so any request/redirect must stay on `api.zeplin.dev`
9
+ * over https; a redirect off-host is treated as an SSRF attempt and rejected. Mirrors the
10
+ * per-hop guard the other host-pinned providers run. Kept pure so it is unit-testable
11
+ * without a network.
12
+ */
13
+ export declare function assertSafeZeplinUrl(url: string): void;
14
+ /**
15
+ * Resolve a Zeplin reference from raw user input into the stable composite external id
16
+ * this provider stores: `"<projectId>"` for a whole-project link, or
17
+ * `"<projectId>:<screenId>"` for a specific screen. Accepts an `app.zeplin.io`
18
+ * project/screen URL, a bare project id, or a `projectId:screenId` string. Returns null
19
+ * when no project id is found.
20
+ */
21
+ export declare function parseZeplinRef(input: string): string | null;
22
+ /** Split a composite external id back into its project id and optional screen id. */
23
+ export declare function splitZeplinExternalId(externalId: string): {
24
+ projectId: string;
25
+ screenId?: string;
26
+ };
27
+ /** Build the canonical web URL stored on the imported document. */
28
+ export declare function zeplinUrlFor(externalId: string): string;
29
+ /** Accept either a bare array or a `{ <key>: [...] }` envelope, else an empty array. */
30
+ export declare function unwrapArray<T>(value: unknown, key: string): T[];
31
+ /** Accept either a bare object or a `{ <key>: {...} }` envelope, else null. */
32
+ export declare function unwrapObject<T>(value: unknown, key: string): T | null;
33
+ export interface ZeplinScreen {
34
+ id?: string;
35
+ name?: string;
36
+ description?: string;
37
+ image?: {
38
+ width?: number;
39
+ height?: number;
40
+ } | null;
41
+ }
42
+ export interface ZeplinComponent {
43
+ id?: string;
44
+ name?: string;
45
+ description?: string;
46
+ section?: {
47
+ name?: string;
48
+ } | null;
49
+ }
50
+ /** A Zeplin colour token: 0–255 channels + 0–1 alpha (Zeplin's representation). */
51
+ interface ZeplinColor {
52
+ name?: string;
53
+ r?: number;
54
+ g?: number;
55
+ b?: number;
56
+ a?: number;
57
+ }
58
+ interface ZeplinTextStyle {
59
+ name?: string;
60
+ font_family?: string;
61
+ font_size?: number;
62
+ }
63
+ interface ZeplinSpacing {
64
+ name?: string;
65
+ value?: number;
66
+ }
67
+ /** The `/projects/:id/design_tokens` payload we read (lenient — verify-at-build). */
68
+ export interface ZeplinDesignTokens {
69
+ colors?: ZeplinColor[];
70
+ text_styles?: ZeplinTextStyle[];
71
+ spacing?: ZeplinSpacing[];
72
+ measurements?: ZeplinSpacing[];
73
+ }
74
+ /**
75
+ * The single source of truth for how many screens a whole-project import pulls and
76
+ * renders: {@link ZeplinProvider} builds its `?limit=` query from this, and
77
+ * {@link zeplinScreensToBlocks} bounds the rendered blocks by it, so the fetch and the
78
+ * render can't drift.
79
+ */
80
+ export declare const MAX_SCREENS = 40;
81
+ /** Map Zeplin screens into source-neutral blocks (name + an optional description line). */
82
+ export declare function zeplinScreensToBlocks(screens: ZeplinScreen[]): DesignBlock[];
83
+ /** Map Zeplin components into source-neutral components (grouped by their section). */
84
+ export declare function zeplinComponentsToDesign(components: ZeplinComponent[]): DesignComponent[];
85
+ /** Map Zeplin design tokens (colours / typography / spacing) into source-neutral tokens. */
86
+ export declare function zeplinTokens(tokens: ZeplinDesignTokens | undefined | null): DesignToken[];
87
+ export interface ZeplinContextInput {
88
+ /** The composite external id (`<projectId>` or `<projectId>:<screenId>`). */
89
+ externalId: string;
90
+ /** The Zeplin project's name (from the API), used for the document title. */
91
+ projectName: string;
92
+ /** The fetched screens (the whole project, or just the one referenced). */
93
+ screens: ZeplinScreen[];
94
+ /** The project's design-system components. */
95
+ components: ZeplinComponent[];
96
+ /** The project's design tokens, or null when unavailable. */
97
+ designTokens?: ZeplinDesignTokens | null;
98
+ }
99
+ /** Assemble the fetched Zeplin pieces into the shared {@link DesignContext}. */
100
+ export declare function buildZeplinDesignContext(input: ZeplinContextInput): DesignContext;
101
+ export {};
102
+ //# sourceMappingURL=zeplin.logic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zeplin.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/zeplin.logic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ import { dimensionMeta, } from './design.logic.js';
2
+ import { assertHostPinned } from './http.js';
3
+ // Zeplin-specific pure logic, kept out of the provider shell so it is unit-testable
4
+ // without a live workspace: parsing/canonicalising a project+screen ref out of user input,
5
+ // the fixed-host SSRF guard, and mapping Zeplin's screens / components / design-tokens JSON
6
+ // into the source-neutral `DesignContext` the shared `renderDesignContext` emits. The
7
+ // `fetch` itself (the `Authorization: Bearer` REST client) lives in `ZeplinProvider`.
8
+ //
9
+ // Zeplin is the design→dev *handoff* tool, so its content model is screens + a
10
+ // design-system (components + tokens), NOT Figma's node tree — which is exactly why it
11
+ // rides the shared `DesignContext` rather than a Figma-shaped renderer.
12
+ /** Zeplin's REST API host. The PAT is sent to this host only — see {@link assertSafeZeplinUrl}. */
13
+ export const ZEPLIN_API_HOST = 'api.zeplin.dev';
14
+ /** What the connect UI renders, and which credentials the provider needs. */
15
+ export const ZEPLIN_DESCRIPTOR = {
16
+ source: 'zeplin',
17
+ label: 'Zeplin',
18
+ icon: 'i-lucide-layout-template',
19
+ credentialFields: [
20
+ {
21
+ key: 'apiToken',
22
+ label: 'Personal access token',
23
+ secret: true,
24
+ placeholder: 'zeplin PAT',
25
+ help: 'Create a personal access token in Zeplin → Profile → Developer → Personal access tokens. It is stored sealed and shared by the workspace.',
26
+ },
27
+ ],
28
+ refLabel: 'Zeplin project or screen URL',
29
+ refPlaceholder: 'https://app.zeplin.io/project/<projectId>/screen/<screenId>',
30
+ // No catalogue search exposed here — import a specific project/screen by URL.
31
+ searchable: false,
32
+ };
33
+ /**
34
+ * The Zeplin REST host is fixed, so any request/redirect must stay on `api.zeplin.dev`
35
+ * over https; a redirect off-host is treated as an SSRF attempt and rejected. Mirrors the
36
+ * per-hop guard the other host-pinned providers run. Kept pure so it is unit-testable
37
+ * without a network.
38
+ */
39
+ export function assertSafeZeplinUrl(url) {
40
+ assertHostPinned(url, ZEPLIN_API_HOST, 'Zeplin');
41
+ }
42
+ // ---- Ref parsing + canonical URL ------------------------------------------
43
+ const ID = /^[A-Za-z0-9]+$/;
44
+ /**
45
+ * Resolve a Zeplin reference from raw user input into the stable composite external id
46
+ * this provider stores: `"<projectId>"` for a whole-project link, or
47
+ * `"<projectId>:<screenId>"` for a specific screen. Accepts an `app.zeplin.io`
48
+ * project/screen URL, a bare project id, or a `projectId:screenId` string. Returns null
49
+ * when no project id is found.
50
+ */
51
+ export function parseZeplinRef(input) {
52
+ const trimmed = input.trim();
53
+ if (!trimmed)
54
+ return null;
55
+ // Bare ref: a project id, optionally `:`-suffixed with a screen id.
56
+ if (!trimmed.includes('/') && !/zeplin\.io/i.test(trimmed)) {
57
+ const [project, screen, ...rest] = trimmed.split(':');
58
+ if (!project || !ID.test(project) || rest.length)
59
+ return null;
60
+ if (!screen)
61
+ return project;
62
+ return ID.test(screen) ? `${project}:${screen}` : project;
63
+ }
64
+ let url;
65
+ try {
66
+ url = new URL(trimmed);
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ if (!/(^|\.)zeplin\.io$/i.test(url.hostname))
72
+ return null;
73
+ const project = url.pathname.match(/\/project\/([A-Za-z0-9]+)/)?.[1];
74
+ if (!project)
75
+ return null;
76
+ const screen = url.pathname.match(/\/screen\/([A-Za-z0-9]+)/)?.[1];
77
+ return screen ? `${project}:${screen}` : project;
78
+ }
79
+ /** Split a composite external id back into its project id and optional screen id. */
80
+ export function splitZeplinExternalId(externalId) {
81
+ const idx = externalId.indexOf(':');
82
+ if (idx === -1)
83
+ return { projectId: externalId };
84
+ return { projectId: externalId.slice(0, idx), screenId: externalId.slice(idx + 1) };
85
+ }
86
+ /** Build the canonical web URL stored on the imported document. */
87
+ export function zeplinUrlFor(externalId) {
88
+ const { projectId, screenId } = splitZeplinExternalId(externalId);
89
+ const base = `https://app.zeplin.io/project/${projectId}`;
90
+ return screenId ? `${base}/screen/${screenId}` : base;
91
+ }
92
+ // ---- Response envelope unwrapping -----------------------------------------
93
+ // Zeplin's REST responses are inconsistent about wrapping collections/objects in a named
94
+ // envelope (`{ screens: [...] }` / `{ screen: {...} }`) vs returning them bare, so every
95
+ // read normalises through these. Pure + exported so the provider shell stays a thin fetch
96
+ // layer and the unwrap is unit-testable without a network.
97
+ /** Accept either a bare array or a `{ <key>: [...] }` envelope, else an empty array. */
98
+ export function unwrapArray(value, key) {
99
+ if (Array.isArray(value))
100
+ return value;
101
+ if (value && typeof value === 'object') {
102
+ const inner = value[key];
103
+ if (Array.isArray(inner))
104
+ return inner;
105
+ }
106
+ return [];
107
+ }
108
+ /** Accept either a bare object or a `{ <key>: {...} }` envelope, else null. */
109
+ export function unwrapObject(value, key) {
110
+ if (!value || typeof value !== 'object')
111
+ return null;
112
+ const inner = value[key];
113
+ if (inner && typeof inner === 'object')
114
+ return inner;
115
+ return value;
116
+ }
117
+ /**
118
+ * The single source of truth for how many screens a whole-project import pulls and
119
+ * renders: {@link ZeplinProvider} builds its `?limit=` query from this, and
120
+ * {@link zeplinScreensToBlocks} bounds the rendered blocks by it, so the fetch and the
121
+ * render can't drift.
122
+ */
123
+ export const MAX_SCREENS = 40;
124
+ function screenMeta(screen) {
125
+ return dimensionMeta(screen.image?.width, screen.image?.height);
126
+ }
127
+ /** Map Zeplin screens into source-neutral blocks (name + an optional description line). */
128
+ export function zeplinScreensToBlocks(screens) {
129
+ return screens.slice(0, MAX_SCREENS).map((screen) => ({
130
+ title: screen.name?.trim() || '(unnamed screen)',
131
+ meta: screenMeta(screen),
132
+ sections: screen.description?.trim()
133
+ ? [{ heading: 'Description', lines: [screen.description.trim()] }]
134
+ : [],
135
+ }));
136
+ }
137
+ /** Map Zeplin components into source-neutral components (grouped by their section). */
138
+ export function zeplinComponentsToDesign(components) {
139
+ return components
140
+ .filter((c) => c.name?.trim())
141
+ .map((c) => ({
142
+ name: c.name.trim(),
143
+ group: c.section?.name?.trim() || undefined,
144
+ note: c.description?.trim() || undefined,
145
+ }));
146
+ }
147
+ function colorHex(c) {
148
+ const to2 = (n) => Math.max(0, Math.min(255, Math.round(n ?? 0)))
149
+ .toString(16)
150
+ .padStart(2, '0');
151
+ const hex = `#${to2(c.r)}${to2(c.g)}${to2(c.b)}`;
152
+ return c.a != null && c.a < 1 ? `${hex} (a=${c.a.toFixed(2)})` : hex;
153
+ }
154
+ /** Map Zeplin design tokens (colours / typography / spacing) into source-neutral tokens. */
155
+ export function zeplinTokens(tokens) {
156
+ if (!tokens)
157
+ return [];
158
+ const out = [];
159
+ for (const c of tokens.colors ?? []) {
160
+ if (c.name?.trim())
161
+ out.push({ collection: 'Colors', name: c.name.trim(), value: colorHex(c) });
162
+ }
163
+ for (const t of tokens.text_styles ?? []) {
164
+ if (!t.name?.trim())
165
+ continue;
166
+ const value = [t.font_family, t.font_size != null ? `${t.font_size}px` : null]
167
+ .filter(Boolean)
168
+ .join(' ');
169
+ out.push({ collection: 'Typography', name: t.name.trim(), value: value || '—' });
170
+ }
171
+ for (const s of [...(tokens.spacing ?? []), ...(tokens.measurements ?? [])]) {
172
+ if (s.name?.trim()) {
173
+ out.push({ collection: 'Spacing', name: s.name.trim(), value: String(s.value ?? '') });
174
+ }
175
+ }
176
+ return out;
177
+ }
178
+ /** Assemble the fetched Zeplin pieces into the shared {@link DesignContext}. */
179
+ export function buildZeplinDesignContext(input) {
180
+ const { projectId, screenId } = splitZeplinExternalId(input.externalId);
181
+ const title = screenId && input.screens[0]?.name?.trim()
182
+ ? `${input.projectName || projectId} — ${input.screens[0].name.trim()}`
183
+ : input.projectName || projectId;
184
+ return {
185
+ title,
186
+ url: zeplinUrlFor(input.externalId),
187
+ blocks: zeplinScreensToBlocks(input.screens),
188
+ components: zeplinComponentsToDesign(input.components),
189
+ tokens: zeplinTokens(input.designTokens),
190
+ references: [],
191
+ };
192
+ }
193
+ //# sourceMappingURL=zeplin.logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zeplin.logic.js","sourceRoot":"","sources":["../../../src/modules/documents/zeplin.logic.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,GAKd,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAE5C,oFAAoF;AACpF,2FAA2F;AAC3F,4FAA4F;AAC5F,sFAAsF;AACtF,sFAAsF;AACtF,EAAE;AACF,+EAA+E;AAC/E,uFAAuF;AACvF,wEAAwE;AAExE,mGAAmG;AACnG,MAAM,CAAC,MAAM,eAAe,GAAG,gBAAgB,CAAA;AAE/C,6EAA6E;AAC7E,MAAM,CAAC,MAAM,iBAAiB,GAA6B;IACzD,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,QAAQ;IACf,IAAI,EAAE,0BAA0B;IAChC,gBAAgB,EAAE;QAChB;YACE,GAAG,EAAE,UAAU;YACf,KAAK,EAAE,uBAAuB;YAC9B,MAAM,EAAE,IAAI;YACZ,WAAW,EAAE,YAAY;YACzB,IAAI,EAAE,2IAA2I;SAClJ;KACF;IACD,QAAQ,EAAE,8BAA8B;IACxC,cAAc,EAAE,6DAA6D;IAC7E,8EAA8E;IAC9E,UAAU,EAAE,KAAK;CAClB,CAAA;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,gBAAgB,CAAC,GAAG,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAA;AAClD,CAAC;AAED,8EAA8E;AAE9E,MAAM,EAAE,GAAG,gBAAgB,CAAA;AAE3B;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IAEzB,oEAAoE;IACpE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3D,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACrD,IAAI,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAA;QAC7D,IAAI,CAAC,MAAM;YAAE,OAAO,OAAO,CAAA;QAC3B,OAAO,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;IAC3D,CAAC;IAED,IAAI,GAAQ,CAAA;IACZ,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAA;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAA;IACzD,MAAM,OAAO,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,2BAA2B,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IACpE,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAA;IACzB,MAAM,MAAM,GAAG,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC,CAAC,CAAA;IAClE,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,OAAO,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,OAAO,CAAA;AAClD,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IAItD,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IACnC,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,CAAA;IAChD,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,QAAQ,EAAE,UAAU,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,CAAA;AACrF,CAAC;AAED,mEAAmE;AACnE,MAAM,UAAU,YAAY,CAAC,UAAkB;IAC7C,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAA;IACjE,MAAM,IAAI,GAAG,iCAAiC,SAAS,EAAE,CAAA;IACzD,OAAO,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,WAAW,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;AACvD,CAAC;AAED,8EAA8E;AAE9E,yFAAyF;AACzF,yFAAyF;AACzF,0FAA0F;AAC1F,2DAA2D;AAE3D,wFAAwF;AACxF,MAAM,UAAU,WAAW,CAAI,KAAc,EAAE,GAAW;IACxD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAY,CAAA;IAC7C,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,KAAK,GAAI,KAAiC,CAAC,GAAG,CAAC,CAAA;QACrD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAAE,OAAO,KAAY,CAAA;IAC/C,CAAC;IACD,OAAO,EAAE,CAAA;AACX,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,YAAY,CAAI,KAAc,EAAE,GAAW;IACzD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACpD,MAAM,KAAK,GAAI,KAAiC,CAAC,GAAG,CAAC,CAAA;IACrD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAU,CAAA;IACzD,OAAO,KAAU,CAAA;AACnB,CAAC;AA8CD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,EAAE,CAAA;AAE7B,SAAS,UAAU,CAAC,MAAoB;IACtC,OAAO,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;AACjE,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,qBAAqB,CAAC,OAAuB;IAC3D,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACpD,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,kBAAkB;QAChD,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC;QACxB,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,EAAE;YAClC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAClE,CAAC,CAAC,EAAE;KACP,CAAC,CAAC,CAAA;AACL,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,wBAAwB,CAAC,UAA6B;IACpE,OAAO,UAAU;SACd,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;SAC7B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACX,IAAI,EAAE,CAAC,CAAC,IAAK,CAAC,IAAI,EAAE;QACpB,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,SAAS;QAC3C,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,SAAS;KACzC,CAAC,CAAC,CAAA;AACP,CAAC;AAED,SAAS,QAAQ,CAAC,CAAc;IAC9B,MAAM,GAAG,GAAG,CAAC,CAAqB,EAAE,EAAE,CACpC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;SAC3C,QAAQ,CAAC,EAAE,CAAC;SACZ,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;IACrB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAChD,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAA;AACtE,CAAC;AAED,4FAA4F;AAC5F,MAAM,UAAU,YAAY,CAAC,MAA6C;IACxE,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAA;IACtB,MAAM,GAAG,GAAkB,EAAE,CAAA;IAC7B,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QACpC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACjG,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;QACzC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE;YAAE,SAAQ;QAC7B,MAAM,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;aAC3E,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,GAAG,CAAC,CAAA;QACZ,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,IAAI,GAAG,EAAE,CAAC,CAAA;IAClF,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAC5E,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;YACnB,GAAG,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;QACxF,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAeD,gFAAgF;AAChF,MAAM,UAAU,wBAAwB,CAAC,KAAyB;IAChE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,qBAAqB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IACvE,MAAM,KAAK,GACT,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE;QACxC,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,IAAI,SAAS,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,IAAK,CAAC,IAAI,EAAE,EAAE;QACzE,CAAC,CAAC,KAAK,CAAC,WAAW,IAAI,SAAS,CAAA;IACpC,OAAO;QACL,KAAK;QACL,GAAG,EAAE,YAAY,CAAC,KAAK,CAAC,UAAU,CAAC;QACnC,MAAM,EAAE,qBAAqB,CAAC,KAAK,CAAC,OAAO,CAAC;QAC5C,UAAU,EAAE,wBAAwB,CAAC,KAAK,CAAC,UAAU,CAAC;QACtD,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC;QACxC,UAAU,EAAE,EAAE;KACf,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/integrations",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "External-system integration domain logic for the Agent Architecture Board (GitHub, documents, tasks, environments, runners).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,8 +25,8 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "ai": "^6.0.209",
28
- "@cat-factory/contracts": "0.48.0",
29
- "@cat-factory/kernel": "0.49.0"
28
+ "@cat-factory/contracts": "0.49.0",
29
+ "@cat-factory/kernel": "0.50.0"
30
30
  },
31
31
  "devDependencies": {
32
32
  "typescript": "7.0.1-rc",
@@ -1 +0,0 @@
1
- {"version":3,"file":"ClaudeDesignProvider.d.ts","sourceRoot":"","sources":["../../../src/modules/documents/ClaudeDesignProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,eAAe,EACpB,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,EAC3B,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAA;AA8C5B,qBAAa,oBAAqB,YAAW,sBAAsB;IACjE,QAAQ,CAAC,IAAI,EAAG,eAAe,CAAS;IACxC,QAAQ,CAAC,UAAU;;;;;;;;;;;;;;;MAA2B;IAE9C,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,CAmB1B;IAED,0FAA0F;YAC5E,iBAAiB;IAoC/B,2FAA2F;YAC7E,SAAS;IA+BvB,yFAAyF;IACzF,OAAO,CAAC,UAAU;IAkBlB,OAAO,CAAC,OAAO;YAQD,GAAG;CAiBlB"}
@@ -1,163 +0,0 @@
1
- import { ValidationError, } from '@cat-factory/kernel';
2
- import { CLAUDE_DESIGN_API_HOST, CLAUDE_DESIGN_DESCRIPTOR, DS_MANIFEST_PATH, claudeDesignUrlFor, parseClaudeDesignRef, renderClaudeDesignProject, splitClaudeDesignExternalId, } from './claudeDesign.logic.js';
3
- import { DocumentHttpError, createHostPinnedFetch, readCappedText } from './http.js';
4
- // ClaudeDesignProvider: the document-source provider for Anthropic's Claude Design. It
5
- // authenticates with a **per-user** personal access token (the credential is stored
6
- // keyed by user id, not shared across the workspace — see the descriptor's
7
- // `credentialScope: 'user'`), reads a design-system project's files over the REST API,
8
- // and renders the component inventory + design tokens to the Markdown the planner +
9
- // `.cat-context/` materialisation consume. All Claude-Design-specific *pure* logic (ref
10
- // parsing, the host-pin guard, the HTML/manifest → Markdown normalizer) lives in
11
- // `claudeDesign.logic.ts`; this class is the thin `fetch` shell.
12
- //
13
- // PROVISIONAL API SHAPE: the endpoint paths/headers below target the per-user-PAT read
14
- // the product is moving toward (today the design-system read is claude.ai-login-bound).
15
- // The host is pinned; re-verify the exact endpoints against the current API when the
16
- // credentialed read ships — they are the intended shape, not a frozen contract. The
17
- // normalizer they feed is solid and fully unit-tested regardless.
18
- const API_BASE = `https://${CLAUDE_DESIGN_API_HOST}/v1`;
19
- const USER_AGENT = 'cat-factory';
20
- /** Hard cap on the bytes read off any response body, to protect the isolate. */
21
- const MAX_RESPONSE_BYTES = 5_000_000;
22
- /** Bound how many project files we pull for a whole-project import. */
23
- const MAX_PROJECT_FILES = 12;
24
- /**
25
- * `fetch` pinned to the Claude Design host, following redirects by hand so the SSRF host
26
- * guard runs against every hop (a 302 can't chase the PAT off-host). Shared transport.
27
- */
28
- const safeFetch = createHostPinnedFetch({ host: CLAUDE_DESIGN_API_HOST, label: 'Claude Design' });
29
- export class ClaudeDesignProvider {
30
- kind = 'claude-design';
31
- descriptor = CLAUDE_DESIGN_DESCRIPTOR;
32
- normalizeConnection(input) {
33
- const apiToken = input.apiToken?.trim();
34
- if (!apiToken) {
35
- throw new ValidationError('Claude Design requires a personal access token');
36
- }
37
- return { credentials: { apiToken }, label: 'Claude Design' };
38
- }
39
- parseRef(input) {
40
- return parseClaudeDesignRef(input);
41
- }
42
- async fetchDocument(credentials, externalId) {
43
- const { projectId, filePath } = splitClaudeDesignExternalId(externalId);
44
- if (!projectId) {
45
- throw new DocumentHttpError(400, `Claude Design ref is missing a project id: ${externalId}`);
46
- }
47
- const files = filePath
48
- ? [{ path: filePath, content: await this.fetchFile(credentials, projectId, filePath) }]
49
- : await this.fetchProjectFiles(credentials, projectId);
50
- const projectName = this.deriveName(projectId, filePath, files);
51
- const body = renderClaudeDesignProject(projectName, files);
52
- return {
53
- externalId,
54
- title: projectName,
55
- url: claudeDesignUrlFor(externalId),
56
- body,
57
- };
58
- }
59
- /** List a project's files, then fetch the manifest + a bounded slice of HTML previews. */
60
- async fetchProjectFiles(credentials, projectId) {
61
- const listed = await this.get(credentials, `/design/projects/${encodeURIComponent(projectId)}/files`);
62
- const paths = normalizePaths(listed);
63
- if (paths.length === 0) {
64
- throw new DocumentHttpError(404, `Claude Design project ${projectId} has no readable files`);
65
- }
66
- // The manifest is the authoritative index; then prefer component-preview HTML and any
67
- // stylesheet (for tokens), bounded so a huge project can't stall the import.
68
- const manifest = paths.filter((p) => p.endsWith(DS_MANIFEST_PATH));
69
- const styles = paths.filter((p) => /\.css$/i.test(p));
70
- const html = paths.filter((p) => /\.html?$/i.test(p));
71
- const chosen = [...manifest, ...styles, ...html].slice(0, MAX_PROJECT_FILES);
72
- const out = [];
73
- for (const path of chosen) {
74
- try {
75
- out.push({ path, content: await this.fetchFile(credentials, projectId, path) });
76
- }
77
- catch {
78
- // A single unreadable file shouldn't fail the whole import — skip it.
79
- }
80
- }
81
- if (out.length === 0) {
82
- throw new DocumentHttpError(502, `Claude Design project ${projectId} returned no file content`);
83
- }
84
- return out;
85
- }
86
- /** Fetch one file's textual content (raw, or unwrapped from a `{ content }` JSON body). */
87
- async fetchFile(credentials, projectId, path) {
88
- const url = `${API_BASE}/design/projects/${encodeURIComponent(projectId)}/files/${path
89
- .split('/')
90
- .map(encodeURIComponent)
91
- .join('/')}`;
92
- const res = await safeFetch(url, { method: 'GET', headers: this.headers(credentials) });
93
- if (!res.ok) {
94
- const text = await readCappedText(res, MAX_RESPONSE_BYTES, 'Claude Design').catch(() => '');
95
- throw new DocumentHttpError(res.status, `Claude Design GET ${url} → ${res.status}: ${text.slice(0, 300)}`);
96
- }
97
- const text = await readCappedText(res, MAX_RESPONSE_BYTES, 'Claude Design');
98
- // The files endpoint may return raw file bytes or a `{ content }` JSON envelope.
99
- const contentType = res.headers.get('content-type') ?? '';
100
- if (contentType.includes('application/json')) {
101
- try {
102
- const json = JSON.parse(text);
103
- if (typeof json.content === 'string')
104
- return json.content;
105
- }
106
- catch {
107
- // Not a JSON envelope after all — fall through and use the raw text.
108
- }
109
- }
110
- return text;
111
- }
112
- /** Name the document: the manifest's `name`, else the file path, else the project id. */
113
- deriveName(projectId, filePath, files) {
114
- const manifest = files.find((f) => f.path.endsWith(DS_MANIFEST_PATH));
115
- if (manifest) {
116
- try {
117
- const json = JSON.parse(manifest.content);
118
- if (typeof json.name === 'string' && json.name.trim())
119
- return json.name.trim();
120
- }
121
- catch {
122
- // ignore — fall through
123
- }
124
- }
125
- if (filePath)
126
- return `${projectId} — ${filePath}`;
127
- return projectId;
128
- }
129
- headers(credentials) {
130
- return {
131
- authorization: `Bearer ${credentials.apiToken ?? ''}`,
132
- accept: 'application/json',
133
- 'user-agent': USER_AGENT,
134
- };
135
- }
136
- async get(credentials, path) {
137
- const url = `${API_BASE}${path}`;
138
- const res = await safeFetch(url, { method: 'GET', headers: this.headers(credentials) });
139
- if (!res.ok) {
140
- const text = await readCappedText(res, MAX_RESPONSE_BYTES, 'Claude Design').catch(() => '');
141
- throw new DocumentHttpError(res.status, `Claude Design GET ${url} → ${res.status}: ${text.slice(0, 300)}`);
142
- }
143
- const text = await readCappedText(res, MAX_RESPONSE_BYTES, 'Claude Design');
144
- try {
145
- return JSON.parse(text);
146
- }
147
- catch {
148
- throw new DocumentHttpError(502, `Claude Design returned an unparseable body for ${path}`);
149
- }
150
- }
151
- }
152
- /** Flatten the file-list response into a clean string[] of paths. */
153
- function normalizePaths(listed) {
154
- const raw = listed.files ?? listed.paths ?? [];
155
- const out = [];
156
- for (const entry of raw) {
157
- const path = typeof entry === 'string' ? entry : entry?.path;
158
- if (typeof path === 'string' && path.trim())
159
- out.push(path.trim());
160
- }
161
- return out;
162
- }
163
- //# sourceMappingURL=ClaudeDesignProvider.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ClaudeDesignProvider.js","sourceRoot":"","sources":["../../../src/modules/documents/ClaudeDesignProvider.ts"],"names":[],"mappings":"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"}
@@ -1,88 +0,0 @@
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
@@ -1 +0,0 @@
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"}