crewly 1.20.29 → 1.20.31

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 (112) hide show
  1. package/config/skills/agent/core/canva-create/SKILL.md +53 -0
  2. package/config/skills/agent/core/canva-create/execute.sh +88 -0
  3. package/config/skills/agent/core/canva-create/execute.test.sh +54 -0
  4. package/config/skills/agent/core/canva-designs/SKILL.md +51 -0
  5. package/config/skills/agent/core/canva-designs/execute.sh +96 -0
  6. package/config/skills/agent/core/canva-designs/execute.test.sh +54 -0
  7. package/config/skills/agent/core/canva-export/SKILL.md +52 -0
  8. package/config/skills/agent/core/canva-export/execute.sh +111 -0
  9. package/config/skills/agent/core/canva-export/execute.test.sh +55 -0
  10. package/config/skills/agent/core/canva-upload/SKILL.md +49 -0
  11. package/config/skills/agent/core/canva-upload/execute.sh +72 -0
  12. package/config/skills/agent/core/canva-upload/execute.test.sh +54 -0
  13. package/config/skills/agent/core/docs-read/SKILL.md +50 -0
  14. package/config/skills/agent/core/docs-read/execute.sh +68 -0
  15. package/config/skills/agent/core/docs-read/execute.test.sh +52 -0
  16. package/config/skills/agent/core/docs-write/SKILL.md +55 -0
  17. package/config/skills/agent/core/docs-write/execute.sh +90 -0
  18. package/config/skills/agent/core/docs-write/execute.test.sh +54 -0
  19. package/config/skills/agent/core/drive-read/SKILL.md +53 -0
  20. package/config/skills/agent/core/drive-read/execute.sh +79 -0
  21. package/config/skills/agent/core/drive-read/execute.test.sh +55 -0
  22. package/config/skills/agent/core/drive-search/SKILL.md +55 -0
  23. package/config/skills/agent/core/drive-search/execute.sh +87 -0
  24. package/config/skills/agent/core/drive-search/execute.test.sh +54 -0
  25. package/config/skills/agent/core/drive-upload/SKILL.md +54 -0
  26. package/config/skills/agent/core/drive-upload/execute.sh +117 -0
  27. package/config/skills/agent/core/drive-upload/execute.test.sh +57 -0
  28. package/config/skills/agent/core/sheets-read/SKILL.md +53 -0
  29. package/config/skills/agent/core/sheets-read/execute.sh +81 -0
  30. package/config/skills/agent/core/sheets-read/execute.test.sh +52 -0
  31. package/config/skills/agent/core/sheets-write/SKILL.md +56 -0
  32. package/config/skills/agent/core/sheets-write/execute.sh +103 -0
  33. package/config/skills/agent/core/sheets-write/execute.test.sh +57 -0
  34. package/config/skills/agent/core/slides-create/SKILL.md +61 -0
  35. package/config/skills/agent/core/slides-create/execute.sh +92 -0
  36. package/config/skills/agent/core/slides-create/execute.test.sh +54 -0
  37. package/config/skills/agent/core/slides-read/SKILL.md +49 -0
  38. package/config/skills/agent/core/slides-read/execute.sh +67 -0
  39. package/config/skills/agent/core/slides-read/execute.test.sh +50 -0
  40. package/dist/backend/backend/src/constants.d.ts +69 -0
  41. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  42. package/dist/backend/backend/src/constants.js +73 -0
  43. package/dist/backend/backend/src/constants.js.map +1 -1
  44. package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts +48 -0
  45. package/dist/backend/backend/src/controllers/canva/canva.controller.d.ts.map +1 -0
  46. package/dist/backend/backend/src/controllers/canva/canva.controller.js +183 -0
  47. package/dist/backend/backend/src/controllers/canva/canva.controller.js.map +1 -0
  48. package/dist/backend/backend/src/controllers/canva/canva.routes.d.ts +22 -0
  49. package/dist/backend/backend/src/controllers/canva/canva.routes.d.ts.map +1 -0
  50. package/dist/backend/backend/src/controllers/canva/canva.routes.js +34 -0
  51. package/dist/backend/backend/src/controllers/canva/canva.routes.js.map +1 -0
  52. package/dist/backend/backend/src/controllers/google/google.controller.d.ts +100 -0
  53. package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
  54. package/dist/backend/backend/src/controllers/google/google.controller.js +237 -1
  55. package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
  56. package/dist/backend/backend/src/controllers/google/google.routes.d.ts +13 -0
  57. package/dist/backend/backend/src/controllers/google/google.routes.d.ts.map +1 -1
  58. package/dist/backend/backend/src/controllers/google/google.routes.js +27 -1
  59. package/dist/backend/backend/src/controllers/google/google.routes.js.map +1 -1
  60. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  61. package/dist/backend/backend/src/routes/api.routes.js +3 -0
  62. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  63. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  64. package/dist/backend/backend/src/services/agent/agent-registration.service.js +22 -4
  65. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  66. package/dist/backend/backend/src/services/canva/canva-token.service.d.ts +98 -0
  67. package/dist/backend/backend/src/services/canva/canva-token.service.d.ts.map +1 -0
  68. package/dist/backend/backend/src/services/canva/canva-token.service.js +198 -0
  69. package/dist/backend/backend/src/services/canva/canva-token.service.js.map +1 -0
  70. package/dist/backend/backend/src/services/canva/canva.service.d.ts +184 -0
  71. package/dist/backend/backend/src/services/canva/canva.service.d.ts.map +1 -0
  72. package/dist/backend/backend/src/services/canva/canva.service.js +274 -0
  73. package/dist/backend/backend/src/services/canva/canva.service.js.map +1 -0
  74. package/dist/backend/backend/src/services/google/docs.service.d.ts +117 -0
  75. package/dist/backend/backend/src/services/google/docs.service.d.ts.map +1 -0
  76. package/dist/backend/backend/src/services/google/docs.service.js +152 -0
  77. package/dist/backend/backend/src/services/google/docs.service.js.map +1 -0
  78. package/dist/backend/backend/src/services/google/drive.service.d.ts +157 -0
  79. package/dist/backend/backend/src/services/google/drive.service.d.ts.map +1 -0
  80. package/dist/backend/backend/src/services/google/drive.service.js +203 -0
  81. package/dist/backend/backend/src/services/google/drive.service.js.map +1 -0
  82. package/dist/backend/backend/src/services/google/google-api.client.d.ts +15 -7
  83. package/dist/backend/backend/src/services/google/google-api.client.d.ts.map +1 -1
  84. package/dist/backend/backend/src/services/google/google-api.client.js +13 -6
  85. package/dist/backend/backend/src/services/google/google-api.client.js.map +1 -1
  86. package/dist/backend/backend/src/services/google/sheets.service.d.ts +118 -0
  87. package/dist/backend/backend/src/services/google/sheets.service.d.ts.map +1 -0
  88. package/dist/backend/backend/src/services/google/sheets.service.js +158 -0
  89. package/dist/backend/backend/src/services/google/sheets.service.js.map +1 -0
  90. package/dist/backend/backend/src/services/google/slides.service.d.ts +136 -0
  91. package/dist/backend/backend/src/services/google/slides.service.d.ts.map +1 -0
  92. package/dist/backend/backend/src/services/google/slides.service.js +153 -0
  93. package/dist/backend/backend/src/services/google/slides.service.js.map +1 -0
  94. package/dist/backend/backend/src/utils/tool-call-markup.utils.d.ts +45 -0
  95. package/dist/backend/backend/src/utils/tool-call-markup.utils.d.ts.map +1 -0
  96. package/dist/backend/backend/src/utils/tool-call-markup.utils.js +83 -0
  97. package/dist/backend/backend/src/utils/tool-call-markup.utils.js.map +1 -0
  98. package/dist/backend/build-info.json +2 -2
  99. package/dist/cli/backend/src/constants.d.ts +69 -0
  100. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  101. package/dist/cli/backend/src/constants.js +73 -0
  102. package/dist/cli/backend/src/constants.js.map +1 -1
  103. package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  104. package/dist/cli/backend/src/services/agent/agent-registration.service.js +22 -4
  105. package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
  106. package/dist/cli/backend/src/utils/tool-call-markup.utils.d.ts +45 -0
  107. package/dist/cli/backend/src/utils/tool-call-markup.utils.d.ts.map +1 -0
  108. package/dist/cli/backend/src/utils/tool-call-markup.utils.js +83 -0
  109. package/dist/cli/backend/src/utils/tool-call-markup.utils.js.map +1 -0
  110. package/frontend/dist/assets/{index-d1bd0dec.js → index-96b51cd9.js} +243 -243
  111. package/frontend/dist/index.html +1 -1
  112. package/package.json +1 -1
@@ -0,0 +1,274 @@
1
+ /**
2
+ * CanvaService — Canva Connect REST on the owner's grant.
3
+ *
4
+ * What agents can do: find designs, create a blank design (preset type or
5
+ * custom size, optionally from an uploaded asset), export a design
6
+ * (PDF / PNG / JPG / PPTX / GIF / MP4 — an async job, polled here to a
7
+ * download URL), and upload images / videos as assets. Video *generation*
8
+ * is not in the API: agents fill, duplicate and export, they do not render
9
+ * from scratch. Brand templates need Canva Enterprise and are not wired.
10
+ *
11
+ * @module services/canva/canva.service
12
+ */
13
+ import { CANVA_CONSTANTS } from '../../constants.js';
14
+ import { CanvaError } from './canva-token.service.js';
15
+ /**
16
+ * Trim a Canva design resource.
17
+ *
18
+ * @param d - Wire design
19
+ * @returns Trimmed
20
+ */
21
+ export function toDesign(d) {
22
+ return {
23
+ id: d.id ?? '',
24
+ title: d.title ?? '',
25
+ ...(d.urls?.edit_url ? { editUrl: d.urls.edit_url } : {}),
26
+ ...(d.urls?.view_url ? { viewUrl: d.urls.view_url } : {}),
27
+ ...(d.thumbnail?.url ? { thumbnailUrl: d.thumbnail.url } : {}),
28
+ ...(d.page_count !== undefined ? { pageCount: d.page_count } : {}),
29
+ ...(d.created_at ? { createdAt: new Date(d.created_at * 1000).toISOString() } : {}),
30
+ ...(d.updated_at ? { updatedAt: new Date(d.updated_at * 1000).toISOString() } : {}),
31
+ };
32
+ }
33
+ /**
34
+ * The `format` object for an export job.
35
+ *
36
+ * @param input - Export input
37
+ * @returns Canva format object
38
+ * @throws CanvaError(400, validation) for an unknown format / bad quality
39
+ */
40
+ export function buildExportFormat(input) {
41
+ const CODES = CANVA_CONSTANTS.ERROR_CODES;
42
+ const type = (input.format ?? '').trim().toLowerCase();
43
+ if (!CANVA_CONSTANTS.EXPORT_FORMATS.includes(type)) {
44
+ throw new CanvaError(400, CODES.VALIDATION, `format must be one of ${CANVA_CONSTANTS.EXPORT_FORMATS.join(', ')}`);
45
+ }
46
+ const pages = (input.pages ?? []).map((p) => Number(p)).filter((p) => Number.isInteger(p) && p > 0);
47
+ const format = { type, ...(pages.length ? { pages } : {}) };
48
+ if (type === 'jpg') {
49
+ const quality = input.quality ?? 80;
50
+ if (!Number.isInteger(quality) || quality < 1 || quality > 100)
51
+ throw new CanvaError(400, CODES.VALIDATION, 'quality must be 1–100');
52
+ format.quality = quality;
53
+ }
54
+ if (type === 'mp4')
55
+ format.quality = (input.videoQuality ?? '').trim() || 'horizontal_1080p';
56
+ return format;
57
+ }
58
+ /**
59
+ * Canva Connect calls.
60
+ */
61
+ export class CanvaService {
62
+ deps;
63
+ base = CANVA_CONSTANTS.API_BASE;
64
+ /**
65
+ * @param deps - Token provider, fetch, sleep
66
+ */
67
+ constructor(deps) {
68
+ this.deps = {
69
+ ...deps,
70
+ fetchImpl: deps.fetchImpl ?? fetch,
71
+ sleep: deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))),
72
+ now: deps.now ?? (() => Date.now()),
73
+ };
74
+ }
75
+ /**
76
+ * `GET /designs` — search / list.
77
+ *
78
+ * @param input - Query, ownership, sort, limit, continuation
79
+ * @returns Designs + continuation token
80
+ */
81
+ async listDesigns(input = {}) {
82
+ const limit = Math.min(Math.max(1, input.limit ?? CANVA_CONSTANTS.DESIGNS_DEFAULT_LIMIT), CANVA_CONSTANTS.DESIGNS_LIMIT_CEILING);
83
+ const url = new URL(`${this.base}/designs`);
84
+ url.searchParams.set('limit', String(limit));
85
+ if (input.query?.trim())
86
+ url.searchParams.set('query', input.query.trim());
87
+ if (input.ownership)
88
+ url.searchParams.set('ownership', input.ownership);
89
+ if (input.sortBy)
90
+ url.searchParams.set('sort_by', input.sortBy);
91
+ if (input.continuation)
92
+ url.searchParams.set('continuation', input.continuation);
93
+ const data = await this.request(url.toString());
94
+ return { designs: (data.items ?? []).map(toDesign), ...(data.continuation ? { continuation: data.continuation } : {}) };
95
+ }
96
+ /**
97
+ * `GET /designs/:id`.
98
+ *
99
+ * @param id - Design id
100
+ * @returns The design
101
+ */
102
+ async getDesign(id) {
103
+ const designId = (id ?? '').trim();
104
+ if (!designId)
105
+ throw new CanvaError(400, CANVA_CONSTANTS.ERROR_CODES.VALIDATION, '"id" is required');
106
+ const data = await this.request(`${this.base}/designs/${encodeURIComponent(designId)}`);
107
+ return toDesign(data.design ?? {});
108
+ }
109
+ /**
110
+ * `POST /designs` — a new design from a preset type, a custom size, or an asset.
111
+ *
112
+ * @param input - Title + type/size/asset
113
+ * @returns The new design (with editUrl)
114
+ * @throws CanvaError(400, validation) when neither a valid preset, size nor asset is given
115
+ */
116
+ async createDesign(input) {
117
+ const CODES = CANVA_CONSTANTS.ERROR_CODES;
118
+ const body = {};
119
+ const title = (input.title ?? '').trim();
120
+ if (title)
121
+ body.title = title.slice(0, 255);
122
+ const preset = (input.preset ?? '').trim().toLowerCase();
123
+ if (preset) {
124
+ if (!CANVA_CONSTANTS.PRESET_DESIGN_TYPES.includes(preset)) {
125
+ throw new CanvaError(400, CODES.VALIDATION, `preset must be one of ${CANVA_CONSTANTS.PRESET_DESIGN_TYPES.join(', ')} (or give width/height)`);
126
+ }
127
+ body.design_type = { type: 'preset', name: preset };
128
+ }
129
+ else if (input.width !== undefined || input.height !== undefined) {
130
+ const w = Number(input.width);
131
+ const h = Number(input.height);
132
+ if (![w, h].every((v) => Number.isInteger(v) && v >= 40 && v <= 8000)) {
133
+ throw new CanvaError(400, CODES.VALIDATION, 'width and height must be integers between 40 and 8000');
134
+ }
135
+ body.design_type = { type: 'custom', width: w, height: h };
136
+ }
137
+ if (input.assetId?.trim())
138
+ body.asset_id = input.assetId.trim();
139
+ if (!body.design_type && !body.asset_id) {
140
+ throw new CanvaError(400, CODES.VALIDATION, 'give a preset (doc|whiteboard|presentation), a width+height, or an assetId');
141
+ }
142
+ const data = await this.request(`${this.base}/designs`, { method: 'POST', body });
143
+ return toDesign(data.design ?? {});
144
+ }
145
+ /**
146
+ * `POST /exports` then poll `GET /exports/:id` until done.
147
+ *
148
+ * @param input - Design, format, options
149
+ * @returns Download URLs (or the failure)
150
+ */
151
+ async exportDesign(input) {
152
+ const designId = (input.designId ?? '').trim();
153
+ if (!designId)
154
+ throw new CanvaError(400, CANVA_CONSTANTS.ERROR_CODES.VALIDATION, '"designId" is required');
155
+ const format = buildExportFormat(input);
156
+ const started = await this.request(`${this.base}/exports`, { method: 'POST', body: { design_id: designId, format } });
157
+ const job = await this.pollJob(`${this.base}/exports/${encodeURIComponent(started.job?.id ?? '')}`, started.job);
158
+ return { jobId: job.id ?? '', status: job.status ?? 'failed', urls: job.urls ?? [], ...(job.error ? { error: job.error } : {}) };
159
+ }
160
+ /**
161
+ * `POST /asset-uploads` (binary body) then poll `GET /asset-uploads/:id`.
162
+ *
163
+ * @param name - Asset name (≤ 50 chars)
164
+ * @param bytes - File content
165
+ * @returns The asset
166
+ * @throws CanvaError(400, validation) for an empty/oversized file; 502 when the job fails
167
+ */
168
+ async uploadAsset(name, bytes) {
169
+ const CODES = CANVA_CONSTANTS.ERROR_CODES;
170
+ const assetName = (name ?? '').trim().slice(0, 50);
171
+ if (!assetName)
172
+ throw new CanvaError(400, CODES.VALIDATION, '"name" is required');
173
+ if (!bytes || bytes.length === 0)
174
+ throw new CanvaError(400, CODES.VALIDATION, 'file is empty');
175
+ if (bytes.length > CANVA_CONSTANTS.ASSET_MAX_BYTES)
176
+ throw new CanvaError(400, CODES.VALIDATION, `file exceeds ${CANVA_CONSTANTS.ASSET_MAX_BYTES} bytes`);
177
+ const started = await this.request(`${this.base}/asset-uploads`, {
178
+ method: 'POST',
179
+ rawBody: bytes,
180
+ headers: {
181
+ 'Content-Type': 'application/octet-stream',
182
+ 'Asset-Upload-Metadata': JSON.stringify({ name_base64: Buffer.from(assetName, 'utf8').toString('base64') }),
183
+ },
184
+ });
185
+ const job = await this.pollJob(`${this.base}/asset-uploads/${encodeURIComponent(started.job?.id ?? '')}`, started.job);
186
+ if (job.status !== 'success' || !job.asset) {
187
+ throw new CanvaError(502, CODES.CANVA_ERROR, `Asset upload failed: ${job.error?.message ?? job.error?.code ?? job.status}`);
188
+ }
189
+ return {
190
+ id: job.asset.id ?? '',
191
+ name: job.asset.name ?? assetName,
192
+ ...(job.asset.thumbnail?.url ? { thumbnailUrl: job.asset.thumbnail.url } : {}),
193
+ ...(job.asset.created_at ? { createdAt: new Date(job.asset.created_at * 1000).toISOString() } : {}),
194
+ };
195
+ }
196
+ // -------------------------------------------------------------------------
197
+ // Internals
198
+ // -------------------------------------------------------------------------
199
+ /**
200
+ * Poll a job until it leaves `in_progress` or the ceiling passes.
201
+ *
202
+ * @param url - Job URL
203
+ * @param first - The job as returned by the create call
204
+ * @returns The final job
205
+ */
206
+ async pollJob(url, first) {
207
+ let job = first ?? {};
208
+ const deadline = this.deps.now() + CANVA_CONSTANTS.JOB_POLL_TIMEOUT_MS;
209
+ while (job.status === 'in_progress' && this.deps.now() < deadline) {
210
+ await this.deps.sleep(CANVA_CONSTANTS.JOB_POLL_INTERVAL_MS);
211
+ job = (await this.request(url)).job ?? {};
212
+ }
213
+ if (job.status === 'in_progress') {
214
+ throw new CanvaError(504, CANVA_CONSTANTS.ERROR_CODES.CANVA_ERROR, `Canva job ${job.id ?? ''} is still running after ${CANVA_CONSTANTS.JOB_POLL_TIMEOUT_MS / 1000}s`);
215
+ }
216
+ return job;
217
+ }
218
+ /**
219
+ * Authenticated call; 401 drops the cached token, 403/404/429 pass
220
+ * through, other failures fold into 502.
221
+ *
222
+ * @param url - Absolute URL
223
+ * @param init - Method / body / headers
224
+ * @returns Parsed JSON
225
+ */
226
+ async request(url, init = {}) {
227
+ const CODES = CANVA_CONSTANTS.ERROR_CODES;
228
+ const token = await this.deps.tokens.getAccessToken();
229
+ let res;
230
+ try {
231
+ res = await this.deps.fetchImpl(url, {
232
+ method: init.method ?? 'GET',
233
+ headers: {
234
+ Authorization: `Bearer ${token}`,
235
+ Accept: 'application/json',
236
+ ...(init.body !== undefined ? { 'Content-Type': 'application/json' } : {}),
237
+ ...(init.headers ?? {}),
238
+ },
239
+ body: init.rawBody ?? (init.body !== undefined ? JSON.stringify(init.body) : undefined),
240
+ signal: AbortSignal.timeout(CANVA_CONSTANTS.REQUEST_TIMEOUT_MS),
241
+ });
242
+ }
243
+ catch (err) {
244
+ throw new CanvaError(502, CODES.NETWORK, `Canva unreachable: ${err instanceof Error ? err.message : String(err)}`);
245
+ }
246
+ const text = await res.text();
247
+ if (!res.ok) {
248
+ let message = `Canva request failed (${res.status})`;
249
+ try {
250
+ const parsed = JSON.parse(text);
251
+ message = parsed.message ?? parsed.code ?? message;
252
+ }
253
+ catch {
254
+ if (text)
255
+ message = text.slice(0, 200);
256
+ }
257
+ if (res.status === 401) {
258
+ this.deps.tokens.clearCache();
259
+ throw new CanvaError(401, CODES.CANVA_ERROR, `Canva rejected the access token: ${message}`);
260
+ }
261
+ const passthrough = res.status === 403 || res.status === 404 || res.status === 429;
262
+ throw new CanvaError(passthrough ? res.status : 502, CODES.CANVA_ERROR, message);
263
+ }
264
+ if (!text)
265
+ return {};
266
+ try {
267
+ return JSON.parse(text);
268
+ }
269
+ catch {
270
+ throw new CanvaError(502, CODES.CANVA_ERROR, 'Canva returned a non-JSON response.');
271
+ }
272
+ }
273
+ }
274
+ //# sourceMappingURL=canva.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canva.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/canva/canva.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * DocsService — Google Docs over the owner's Workspace grant.
3
+ *
4
+ * Reads any document the owner can see (`documents.readonly` /
5
+ * `drive.readonly`) and creates or appends to documents Crewly created
6
+ * (`drive.file`). Appending to a document the owner made elsewhere needs
7
+ * the `documents` scope, which the grant does not carry yet; Google then
8
+ * answers 403 and the error says so.
9
+ *
10
+ * @module services/google/docs.service
11
+ */
12
+ import { type GoogleApiDeps } from './google-api.client.js';
13
+ /** A document, flattened. */
14
+ export interface DocText {
15
+ id: string;
16
+ title: string;
17
+ /** Plain text: headings prefixed with `#`, table cells joined with ` | `. */
18
+ text: string;
19
+ webViewLink: string;
20
+ }
21
+ /** Create input. */
22
+ export interface DocCreateInput {
23
+ title: string;
24
+ /** Initial body (plain text; blank lines make paragraphs). */
25
+ text?: string;
26
+ }
27
+ interface WireTextRun {
28
+ content?: string;
29
+ }
30
+ interface WireParagraph {
31
+ elements?: Array<{
32
+ textRun?: WireTextRun;
33
+ endIndex?: number;
34
+ }>;
35
+ paragraphStyle?: {
36
+ namedStyleType?: string;
37
+ };
38
+ bullet?: unknown;
39
+ }
40
+ interface WireStructuralElement {
41
+ endIndex?: number;
42
+ paragraph?: WireParagraph;
43
+ table?: {
44
+ tableRows?: Array<{
45
+ tableCells?: Array<{
46
+ content?: WireStructuralElement[];
47
+ }>;
48
+ }>;
49
+ };
50
+ sectionBreak?: unknown;
51
+ }
52
+ interface WireDocument {
53
+ documentId?: string;
54
+ title?: string;
55
+ body?: {
56
+ content?: WireStructuralElement[];
57
+ };
58
+ }
59
+ /**
60
+ * Flatten a document body to plain text.
61
+ *
62
+ * @param content - `body.content`
63
+ * @returns Lines joined with `\n`
64
+ */
65
+ export declare function flattenDocBody(content: WireStructuralElement[] | undefined): string;
66
+ /**
67
+ * The document's end index (where `insertText` appends).
68
+ *
69
+ * @param doc - Document
70
+ * @returns Index just before the final newline (Docs refuses inserts after it)
71
+ */
72
+ export declare function docEndIndex(doc: WireDocument): number;
73
+ /**
74
+ * Docs: read, create, append.
75
+ */
76
+ export declare class DocsService {
77
+ private readonly deps;
78
+ private readonly base;
79
+ /**
80
+ * @param deps - Token provider and optional fetch override
81
+ */
82
+ constructor(deps: GoogleApiDeps);
83
+ /**
84
+ * `documents.get`, flattened to text.
85
+ *
86
+ * @param id - Document id
87
+ * @returns Title + text
88
+ */
89
+ read(id: string): Promise<DocText>;
90
+ /**
91
+ * `documents.create` + one `insertText` for the body.
92
+ *
93
+ * @param input - Title and optional body
94
+ * @returns The new document (text as written)
95
+ * @throws GoogleWorkspaceError(400, validation) without a title
96
+ */
97
+ create(input: DocCreateInput): Promise<DocText>;
98
+ /**
99
+ * Append text at the end of a document (`documents.get` for the end
100
+ * index, then `insertText`).
101
+ *
102
+ * @param id - Document id
103
+ * @param text - Text to append (a newline is prepended when the doc is not empty)
104
+ * @returns The updated document, flattened
105
+ * @throws GoogleWorkspaceError(400, validation) without text
106
+ */
107
+ append(id: string, text: string): Promise<DocText>;
108
+ }
109
+ /**
110
+ * Browser link for a document.
111
+ *
112
+ * @param id - Document id
113
+ * @returns URL
114
+ */
115
+ export declare function docLink(id: string): string;
116
+ export {};
117
+ //# sourceMappingURL=docs.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/google/docs.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG3E,6BAA6B;AAC7B,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,6EAA6E;IAC7E,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,oBAAoB;AACpB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,UAAU,WAAW;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,UAAU,aAAa;IACrB,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,CAAC,EAAE,WAAW,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/D,cAAc,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AACD,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,KAAK,CAAC;YAAE,UAAU,CAAC,EAAE,KAAK,CAAC;gBAAE,OAAO,CAAC,EAAE,qBAAqB,EAAE,CAAA;aAAE,CAAC,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;IAC7F,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AACD,UAAU,YAAY;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,qBAAqB,EAAE,CAAA;KAAE,CAAC;CAC9C;AAyBD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,EAAE,GAAG,SAAS,GAAG,MAAM,CAanF;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,CAKrD;AAED;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA4C;IAEjE;;OAEG;gBACS,IAAI,EAAE,aAAa;IAI/B;;;;;OAKG;IACG,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMxC;;;;;;OAMG;IACG,MAAM,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAerD;;;;;;;;OAQG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAazD;AAOD;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE1C"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * DocsService — Google Docs over the owner's Workspace grant.
3
+ *
4
+ * Reads any document the owner can see (`documents.readonly` /
5
+ * `drive.readonly`) and creates or appends to documents Crewly created
6
+ * (`drive.file`). Appending to a document the owner made elsewhere needs
7
+ * the `documents` scope, which the grant does not carry yet; Google then
8
+ * answers 403 and the error says so.
9
+ *
10
+ * @module services/google/docs.service
11
+ */
12
+ import { GOOGLE_WORKSPACE_CONSTANTS } from '../../constants.js';
13
+ import { GoogleWorkspaceError } from './google-workspace-token.service.js';
14
+ import { googleRequest } from './google-api.client.js';
15
+ import { requireId } from './drive.service.js';
16
+ const HEADING_PREFIX = {
17
+ TITLE: '# ',
18
+ HEADING_1: '# ',
19
+ HEADING_2: '## ',
20
+ HEADING_3: '### ',
21
+ HEADING_4: '#### ',
22
+ HEADING_5: '##### ',
23
+ HEADING_6: '###### ',
24
+ };
25
+ /**
26
+ * Flatten a paragraph to one line.
27
+ *
28
+ * @param p - Paragraph
29
+ * @returns Text without the trailing newline
30
+ */
31
+ function paragraphText(p) {
32
+ const raw = (p.elements ?? []).map((e) => e.textRun?.content ?? '').join('');
33
+ const line = raw.replace(/\n$/, '');
34
+ const prefix = HEADING_PREFIX[p.paragraphStyle?.namedStyleType ?? ''] ?? (p.bullet ? '- ' : '');
35
+ return `${prefix}${line}`;
36
+ }
37
+ /**
38
+ * Flatten a document body to plain text.
39
+ *
40
+ * @param content - `body.content`
41
+ * @returns Lines joined with `\n`
42
+ */
43
+ export function flattenDocBody(content) {
44
+ const lines = [];
45
+ for (const el of content ?? []) {
46
+ if (el.paragraph) {
47
+ lines.push(paragraphText(el.paragraph));
48
+ }
49
+ else if (el.table) {
50
+ for (const row of el.table.tableRows ?? []) {
51
+ const cells = (row.tableCells ?? []).map((cell) => flattenDocBody(cell.content).replace(/\n+/g, ' ').trim());
52
+ lines.push(cells.join(' | '));
53
+ }
54
+ }
55
+ }
56
+ return lines.join('\n').replace(/\n{3,}/g, '\n\n').trim();
57
+ }
58
+ /**
59
+ * The document's end index (where `insertText` appends).
60
+ *
61
+ * @param doc - Document
62
+ * @returns Index just before the final newline (Docs refuses inserts after it)
63
+ */
64
+ export function docEndIndex(doc) {
65
+ const content = doc.body?.content ?? [];
66
+ const last = content[content.length - 1];
67
+ const end = last?.endIndex ?? 1;
68
+ return Math.max(1, end - 1);
69
+ }
70
+ /**
71
+ * Docs: read, create, append.
72
+ */
73
+ export class DocsService {
74
+ deps;
75
+ base = GOOGLE_WORKSPACE_CONSTANTS.DOCS_API_BASE;
76
+ /**
77
+ * @param deps - Token provider and optional fetch override
78
+ */
79
+ constructor(deps) {
80
+ this.deps = deps;
81
+ }
82
+ /**
83
+ * `documents.get`, flattened to text.
84
+ *
85
+ * @param id - Document id
86
+ * @returns Title + text
87
+ */
88
+ async read(id) {
89
+ const documentId = requireId(id);
90
+ const doc = await googleRequest(this.deps, `${this.base}/documents/${encodeURIComponent(documentId)}`);
91
+ return toDocText(doc);
92
+ }
93
+ /**
94
+ * `documents.create` + one `insertText` for the body.
95
+ *
96
+ * @param input - Title and optional body
97
+ * @returns The new document (text as written)
98
+ * @throws GoogleWorkspaceError(400, validation) without a title
99
+ */
100
+ async create(input) {
101
+ const title = (input.title ?? '').trim();
102
+ if (!title)
103
+ throw new GoogleWorkspaceError(400, GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES.VALIDATION, '"title" is required');
104
+ const created = await googleRequest(this.deps, `${this.base}/documents`, { method: 'POST', body: { title } });
105
+ const documentId = created.documentId ?? '';
106
+ const text = (input.text ?? '').replace(/\r\n/g, '\n');
107
+ if (text.trim()) {
108
+ await googleRequest(this.deps, `${this.base}/documents/${encodeURIComponent(documentId)}:batchUpdate`, {
109
+ method: 'POST',
110
+ body: { requests: [{ insertText: { location: { index: 1 }, text } }] },
111
+ });
112
+ }
113
+ return { id: documentId, title: created.title ?? title, text, webViewLink: docLink(documentId) };
114
+ }
115
+ /**
116
+ * Append text at the end of a document (`documents.get` for the end
117
+ * index, then `insertText`).
118
+ *
119
+ * @param id - Document id
120
+ * @param text - Text to append (a newline is prepended when the doc is not empty)
121
+ * @returns The updated document, flattened
122
+ * @throws GoogleWorkspaceError(400, validation) without text
123
+ */
124
+ async append(id, text) {
125
+ const documentId = requireId(id);
126
+ const body = (text ?? '').replace(/\r\n/g, '\n');
127
+ if (!body.trim())
128
+ throw new GoogleWorkspaceError(400, GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES.VALIDATION, '"text" is required');
129
+ const doc = await googleRequest(this.deps, `${this.base}/documents/${encodeURIComponent(documentId)}`);
130
+ const index = docEndIndex(doc);
131
+ await googleRequest(this.deps, `${this.base}/documents/${encodeURIComponent(documentId)}:batchUpdate`, {
132
+ method: 'POST',
133
+ body: { requests: [{ insertText: { location: { index }, text: index > 1 ? `\n${body}` : body } }] },
134
+ });
135
+ const after = await googleRequest(this.deps, `${this.base}/documents/${encodeURIComponent(documentId)}`);
136
+ return toDocText(after);
137
+ }
138
+ }
139
+ function toDocText(doc) {
140
+ const id = doc.documentId ?? '';
141
+ return { id, title: doc.title ?? '', text: flattenDocBody(doc.body?.content), webViewLink: docLink(id) };
142
+ }
143
+ /**
144
+ * Browser link for a document.
145
+ *
146
+ * @param id - Document id
147
+ * @returns URL
148
+ */
149
+ export function docLink(id) {
150
+ return `https://docs.google.com/document/d/${id}/edit`;
151
+ }
152
+ //# sourceMappingURL=docs.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/google/docs.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qCAAqC,CAAC;AAC3E,OAAO,EAAE,aAAa,EAAsB,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAsC/C,MAAM,cAAc,GAA2B;IAC7C,KAAK,EAAE,IAAI;IACX,SAAS,EAAE,IAAI;IACf,SAAS,EAAE,KAAK;IAChB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,OAAO;IAClB,SAAS,EAAE,QAAQ;IACnB,SAAS,EAAE,SAAS;CACrB,CAAC;AAEF;;;;;GAKG;AACH,SAAS,aAAa,CAAC,CAAgB;IACrC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7E,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,cAAc,EAAE,cAAc,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAChG,OAAO,GAAG,MAAM,GAAG,IAAI,EAAE,CAAC;AAC5B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAA4C;IACzE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,EAAE,IAAI,OAAO,IAAI,EAAE,EAAE,CAAC;QAC/B,IAAI,EAAE,CAAC,SAAS,EAAE,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1C,CAAC;aAAM,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;YACpB,KAAK,MAAM,GAAG,IAAI,EAAE,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC7G,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,GAAiB;IAC3C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;IACxC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,EAAE,QAAQ,IAAI,CAAC,CAAC;IAChC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,WAAW;IACL,IAAI,CAAgB;IACpB,IAAI,GAAG,0BAA0B,CAAC,aAAa,CAAC;IAEjE;;OAEG;IACH,YAAY,IAAmB;QAC7B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,IAAI,CAAC,EAAU;QACnB,MAAM,UAAU,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,MAAM,aAAa,CAAe,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,cAAc,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACrH,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;IACxB,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,MAAM,CAAC,KAAqB;QAChC,MAAM,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACzC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,0BAA0B,CAAC,WAAW,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC;QAC1H,MAAM,OAAO,GAAG,MAAM,aAAa,CAAe,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,YAAY,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QAC5H,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACvD,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;YAChB,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,cAAc,kBAAkB,CAAC,UAAU,CAAC,cAAc,EAAE;gBACrG,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE;aACvE,CAAC,CAAC;QACL,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;IACnG,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,MAAM,CAAC,EAAU,EAAE,IAAY;QACnC,MAAM,UAAU,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,oBAAoB,CAAC,GAAG,EAAE,0BAA0B,CAAC,WAAW,CAAC,UAAU,EAAE,oBAAoB,CAAC,CAAC;QAC/H,MAAM,GAAG,GAAG,MAAM,aAAa,CAAe,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,cAAc,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACrH,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,cAAc,kBAAkB,CAAC,UAAU,CAAC,cAAc,EAAE;YACrG,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE;SACpG,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,aAAa,CAAe,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,IAAI,cAAc,kBAAkB,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACvH,OAAO,SAAS,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;CACF;AAED,SAAS,SAAS,CAAC,GAAiB;IAClC,MAAM,EAAE,GAAG,GAAG,CAAC,UAAU,IAAI,EAAE,CAAC;IAChC,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;AAC3G,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,sCAAsC,EAAE,OAAO,CAAC;AACzD,CAAC"}