@mcpher/gas-fakes 2.3.13 → 2.3.15

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 (54) hide show
  1. package/README.md +11 -5
  2. package/gf_agent/README.md +101 -0
  3. package/gf_agent/SKILL.md +396 -0
  4. package/gf_agent/documentation.md +105 -0
  5. package/gf_agent/gf-agent-contributor/SKILL.md +56 -0
  6. package/gf_agent/index.md +21 -0
  7. package/gf_agent/knowledge/00-execution-context.md +4 -0
  8. package/gf_agent/knowledge/01-drive.md +12 -0
  9. package/gf_agent/knowledge/02-syntax.md +13 -0
  10. package/gf_agent/knowledge/03-auth.md +15 -0
  11. package/gf_agent/knowledge/04-advanced.md +24 -0
  12. package/gf_agent/knowledge/05-sheets-forms.md +25 -0
  13. package/gf_agent/knowledge/06-jdbc-cloudsql.md +21 -0
  14. package/gf_agent/knowledge/07-jdbc-auth-details.md +30 -0
  15. package/gf_agent/knowledge/08-docs-limitations.md +4 -0
  16. package/gf_agent/knowledge/09-orchestrator-pattern.md +54 -0
  17. package/gf_agent/knowledge/10-sandbox-security.md +61 -0
  18. package/gf_agent/knowledge/11-chart-builder-limitations.md +15 -0
  19. package/gf_agent/knowledge/12-gmail-eventual-consistency.md +13 -0
  20. package/gf_agent/knowledge/README.md +16 -0
  21. package/gf_agent/scripts/SKILL.template.md +65 -0
  22. package/gf_agent/scripts/builder.js +78 -47
  23. package/gf_agent/skills/base.md +156 -0
  24. package/gf_agent/skills/cache.md +20 -0
  25. package/gf_agent/skills/calendar.md +780 -0
  26. package/gf_agent/skills/charts.md +127 -0
  27. package/gf_agent/skills/document.md +6626 -0
  28. package/gf_agent/skills/drive.md +423 -0
  29. package/gf_agent/skills/forms.md +4036 -0
  30. package/gf_agent/skills/gmail.md +576 -0
  31. package/gf_agent/skills/jdbc.md +3101 -0
  32. package/gf_agent/skills/lock.md +20 -0
  33. package/gf_agent/skills/properties.md +19 -0
  34. package/gf_agent/skills/script.md +50 -0
  35. package/gf_agent/skills/slides.md +5054 -0
  36. package/gf_agent/skills/spreadsheet.md +56075 -0
  37. package/gf_agent/skills/urlfetch.md +28 -0
  38. package/gf_agent/skills/utilities.md +33 -0
  39. package/gf_agent/skills/xml.md +270 -0
  40. package/package.json +1 -1
  41. package/src/cli/mcp.js +82 -67
  42. package/src/cli/setup.js +87 -9
  43. package/src/services/advgmail/fakeadvgmailmessages.js +85 -3
  44. package/src/services/driveapp/fakedrivemeta.js +1 -1
  45. package/src/services/gmailapp/fakegmailapp.js +217 -1
  46. package/src/services/gmailapp/fakegmailattachment.js +5 -0
  47. package/src/services/gmailapp/fakegmaildraft.js +32 -4
  48. package/src/services/gmailapp/fakegmaillabel.js +45 -0
  49. package/src/services/gmailapp/fakegmailmessage.js +212 -9
  50. package/src/services/gmailapp/fakegmailthread.js +151 -1
  51. package/src/services/spreadsheetapp/fakeembeddedchartbuilder.js +113 -28
  52. package/src/support/sxgmail.js +22 -2
  53. package/docs_discovery.json +0 -4939
  54. package/drive_tools.js +0 -20
@@ -167,7 +167,7 @@ class FakeGmailThread {
167
167
  }
168
168
 
169
169
  Gmail.Users.Threads.modify({ addLabelIds: [label.getId()] }, 'me', this.getId());
170
- return this;
170
+ return this.refresh();
171
171
  }
172
172
 
173
173
  removeLabel(label) {
@@ -215,6 +215,156 @@ class FakeGmailThread {
215
215
  }
216
216
  }
217
217
  Gmail.Users.Threads.modify({ removeLabelIds: [label.getId()] }, 'me', this.getId());
218
+ return this.refresh();
219
+ }
220
+
221
+ __hasLabel(label) {
222
+ if (!this.__threadResource.messages) return false;
223
+ for (const m of this.__threadResource.messages) {
224
+ if (m.labelIds && m.labelIds.includes(label)) return true;
225
+ }
226
+ return false;
227
+ }
228
+
229
+ hasStarredMessages() {
230
+ ScriptApp.__behavior.checkMethod('GmailThread', 'hasStarredMessages');
231
+ return this.__hasLabel('STARRED');
232
+ }
233
+
234
+ isImportant() {
235
+ ScriptApp.__behavior.checkMethod('GmailThread', 'isImportant');
236
+ return this.__hasLabel('IMPORTANT');
237
+ }
238
+
239
+ isInChats() {
240
+ ScriptApp.__behavior.checkMethod('GmailThread', 'isInChats');
241
+ return this.__hasLabel('CHAT');
242
+ }
243
+
244
+ isInInbox() {
245
+ ScriptApp.__behavior.checkMethod('GmailThread', 'isInInbox');
246
+ return this.__hasLabel('INBOX');
247
+ }
248
+
249
+ isInPriorityInbox() {
250
+ ScriptApp.__behavior.checkMethod('GmailThread', 'isInPriorityInbox');
251
+ return this.__hasLabel('INBOX') && this.__hasLabel('IMPORTANT');
252
+ }
253
+
254
+ isInSpam() {
255
+ ScriptApp.__behavior.checkMethod('GmailThread', 'isInSpam');
256
+ return this.__hasLabel('SPAM');
257
+ }
258
+
259
+ isInTrash() {
260
+ ScriptApp.__behavior.checkMethod('GmailThread', 'isInTrash');
261
+ return this.__hasLabel('TRASH');
262
+ }
263
+
264
+ isUnread() {
265
+ ScriptApp.__behavior.checkMethod('GmailThread', 'isUnread');
266
+ return this.__hasLabel('UNREAD');
267
+ }
268
+
269
+ getFirstMessageSubject() {
270
+ ScriptApp.__behavior.checkMethod('GmailThread', 'getFirstMessageSubject');
271
+ const msgs = this.getMessages();
272
+ return msgs.length > 0 ? msgs[0].getSubject() : '';
273
+ }
274
+
275
+ getLastMessageDate() {
276
+ ScriptApp.__behavior.checkMethod('GmailThread', 'getLastMessageDate');
277
+ const msgs = this.getMessages();
278
+ return msgs.length > 0 ? msgs[msgs.length - 1].getDate() : new Date();
279
+ }
280
+
281
+ getMessageCount() {
282
+ ScriptApp.__behavior.checkMethod('GmailThread', 'getMessageCount');
283
+ return this.getMessages().length;
284
+ }
285
+
286
+ getPermalink() {
287
+ ScriptApp.__behavior.checkMethod('GmailThread', 'getPermalink');
288
+ return `https://mail.google.com/mail/u/0/#inbox/${this.getId()}`;
289
+ }
290
+
291
+ refresh() {
292
+ ScriptApp.__behavior.checkMethod('GmailThread', 'refresh');
293
+ this.__threadResource = Gmail.Users.Threads.get('me', this.getId());
294
+ return this;
295
+ }
296
+
297
+ markImportant() {
298
+ ScriptApp.__behavior.checkMethod('GmailThread', 'markImportant');
299
+ Gmail.Users.Threads.modify({ addLabelIds: ['IMPORTANT'] }, 'me', this.getId());
300
+ return this.refresh();
301
+ }
302
+
303
+ markRead() {
304
+ ScriptApp.__behavior.checkMethod('GmailThread', 'markRead');
305
+ Gmail.Users.Threads.modify({ removeLabelIds: ['UNREAD'] }, 'me', this.getId());
306
+ return this.refresh();
307
+ }
308
+
309
+ markUnimportant() {
310
+ ScriptApp.__behavior.checkMethod('GmailThread', 'markUnimportant');
311
+ Gmail.Users.Threads.modify({ removeLabelIds: ['IMPORTANT'] }, 'me', this.getId());
312
+ return this.refresh();
313
+ }
314
+
315
+ markUnread() {
316
+ ScriptApp.__behavior.checkMethod('GmailThread', 'markUnread');
317
+ Gmail.Users.Threads.modify({ addLabelIds: ['UNREAD'] }, 'me', this.getId());
318
+ return this.refresh();
319
+ }
320
+
321
+ moveToArchive() {
322
+ ScriptApp.__behavior.checkMethod('GmailThread', 'moveToArchive');
323
+ Gmail.Users.Threads.modify({ removeLabelIds: ['INBOX'] }, 'me', this.getId());
324
+ return this.refresh();
325
+ }
326
+
327
+ moveToInbox() {
328
+ ScriptApp.__behavior.checkMethod('GmailThread', 'moveToInbox');
329
+ Gmail.Users.Threads.modify({ addLabelIds: ['INBOX'] }, 'me', this.getId());
330
+ return this.refresh();
331
+ }
332
+
333
+ moveToSpam() {
334
+ ScriptApp.__behavior.checkMethod('GmailThread', 'moveToSpam');
335
+ Gmail.Users.Threads.modify({ addLabelIds: ['SPAM'] }, 'me', this.getId());
336
+ return this.refresh();
337
+ }
338
+
339
+ moveToTrash() {
340
+ ScriptApp.__behavior.checkMethod('GmailThread', 'moveToTrash');
341
+ Gmail.Users.Threads.trash('me', this.getId());
342
+ return this.refresh();
343
+ }
344
+
345
+ createDraftReply(body, options) {
346
+ ScriptApp.__behavior.checkMethod('GmailThread', 'createDraftReply');
347
+ const msgs = this.getMessages();
348
+ return msgs.length > 0 ? msgs[msgs.length - 1].createDraftReply(body, options) : null;
349
+ }
350
+
351
+ createDraftReplyAll(body, options) {
352
+ ScriptApp.__behavior.checkMethod('GmailThread', 'createDraftReplyAll');
353
+ const msgs = this.getMessages();
354
+ return msgs.length > 0 ? msgs[msgs.length - 1].createDraftReplyAll(body, options) : null;
355
+ }
356
+
357
+ reply(body, options) {
358
+ ScriptApp.__behavior.checkMethod('GmailThread', 'reply');
359
+ const msgs = this.getMessages();
360
+ if (msgs.length > 0) msgs[msgs.length - 1].reply(body, options);
361
+ return this;
362
+ }
363
+
364
+ replyAll(body, options) {
365
+ ScriptApp.__behavior.checkMethod('GmailThread', 'replyAll');
366
+ const msgs = this.getMessages();
367
+ if (msgs.length > 0) msgs[msgs.length - 1].replyAll(body, options);
218
368
  return this;
219
369
  }
220
370
 
@@ -1,5 +1,5 @@
1
1
  import { Proxies } from "../../support/proxies.js";
2
- import { signatureArgs } from "../../support/helpers.js";
2
+ import { signatureArgs, notYetImplemented } from "../../support/helpers.js";
3
3
  import { Utils } from "../../support/utils.js";
4
4
  import { makeSheetsGridRange } from "./sheetrangehelpers.js";
5
5
  import { newFakeEmbeddedChart } from "./fakeembeddedchart.js";
@@ -155,6 +155,25 @@ export class FakeEmbeddedChartBuilder {
155
155
  }
156
156
  }
157
157
 
158
+ // Apply colors to series
159
+ if (this.__colors && basic && basic.series) {
160
+ basic.series.forEach((s, i) => {
161
+ if (this.__colors[i]) {
162
+ const hex = this.__colors[i];
163
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
164
+ if (result) {
165
+ s.colorStyle = {
166
+ rgbColor: {
167
+ red: parseInt(result[1], 16) / 255,
168
+ green: parseInt(result[2], 16) / 255,
169
+ blue: parseInt(result[3], 16) / 255
170
+ }
171
+ };
172
+ }
173
+ }
174
+ });
175
+ }
176
+
158
177
  // 2. Handle Specialized Spec Blocks
159
178
  if (basic && basic.chartType === "PIE") {
160
179
  spec.pieChart = {
@@ -233,43 +252,109 @@ export class FakeEmbeddedChartBuilder {
233
252
  setTransposeRowsAndColumns(transpose) { return this; }
234
253
 
235
254
  // --- Chart Specific Builder Methods ---
236
- reverseCategories() { return this; }
255
+ __getAxis(position) {
256
+ if (!this.__apiChart.spec.basicChart) {
257
+ this.__apiChart.spec.basicChart = { axis: [], domains: [], series: [] };
258
+ }
259
+ if (!this.__apiChart.spec.basicChart.axis) {
260
+ this.__apiChart.spec.basicChart.axis = [];
261
+ }
262
+ let axis = this.__apiChart.spec.basicChart.axis.find(a => a.position === position);
263
+ if (!axis) {
264
+ axis = { position };
265
+ this.__apiChart.spec.basicChart.axis.push(axis);
266
+ }
267
+ return axis;
268
+ }
269
+
270
+ reverseCategories() { notYetImplemented('reverseCategories'); return this; }
237
271
  setBackgroundColor(color) { return this.setOption("backgroundColor", color); }
238
- setColors(colors) { return this; }
272
+
273
+ setColors(colors) {
274
+ ScriptApp.__behavior.checkMethod("EmbeddedChartBuilder", "setColors");
275
+ this.__colors = Array.isArray(colors) ? colors : [colors];
276
+ return this;
277
+ }
278
+
239
279
  setLegendPosition(position) {
240
280
  this.__apiChart.spec.basicChart.legendPosition = position ? position.toString() : "RIGHT_LEGEND";
241
281
  return this;
242
282
  }
243
- setLegendTextStyle(textStyle) { return this; }
244
- setPointStyle(pointStyle) { return this; }
245
- setRange(min, max) { return this; }
246
- setStacked() { return this; }
283
+
284
+ setLegendTextStyle(textStyle) { notYetImplemented('setLegendTextStyle'); return this; }
285
+ setPointStyle(pointStyle) { notYetImplemented('setPointStyle'); return this; }
286
+
287
+ setRange(min, max) {
288
+ ScriptApp.__behavior.checkMethod("EmbeddedChartBuilder", "setRange");
289
+ const chartType = this.__apiChart.spec.basicChart ? this.__apiChart.spec.basicChart.chartType : null;
290
+ if (chartType === "BAR") {
291
+ return this.setXAxisRange(min, max);
292
+ }
293
+ return this.setYAxisRange(min, max);
294
+ }
295
+
296
+ setStacked() {
297
+ ScriptApp.__behavior.checkMethod("EmbeddedChartBuilder", "setStacked");
298
+ if (this.__apiChart.spec.basicChart) {
299
+ this.__apiChart.spec.basicChart.stackedType = "STACKED";
300
+ }
301
+ return this;
302
+ }
303
+
247
304
  setTitle(title) {
305
+ ScriptApp.__behavior.checkMethod("EmbeddedChartBuilder", "setTitle");
248
306
  this.__apiChart.spec.title = title;
249
307
  return this;
250
308
  }
251
- setTitleTextStyle(textStyle) { return this; }
252
- setXAxisTextStyle(textStyle) { return this; }
253
- setXAxisTitle(title) { return this; }
254
- setXAxisTitleTextStyle(textStyle) { return this; }
255
- setYAxisTextStyle(textStyle) { return this; }
256
- setYAxisTitle(title) { return this; }
257
- setYAxisTitleTextStyle(textStyle) { return this; }
258
- useLogScale() { return this; }
309
+
310
+ setTitleTextStyle(textStyle) { notYetImplemented('setTitleTextStyle'); return this; }
311
+ setXAxisTextStyle(textStyle) { notYetImplemented('setXAxisTextStyle'); return this; }
312
+
313
+ setXAxisTitle(title) {
314
+ ScriptApp.__behavior.checkMethod("EmbeddedChartBuilder", "setXAxisTitle");
315
+ this.__getAxis("BOTTOM_AXIS").title = title;
316
+ return this;
317
+ }
318
+
319
+ setXAxisTitleTextStyle(textStyle) { notYetImplemented('setXAxisTitleTextStyle'); return this; }
320
+ setYAxisTextStyle(textStyle) { notYetImplemented('setYAxisTextStyle'); return this; }
321
+
322
+ setYAxisTitle(title) {
323
+ ScriptApp.__behavior.checkMethod("EmbeddedChartBuilder", "setYAxisTitle");
324
+ this.__getAxis("LEFT_AXIS").title = title;
325
+ return this;
326
+ }
327
+
328
+ setYAxisTitleTextStyle(textStyle) { notYetImplemented('setYAxisTitleTextStyle'); return this; }
329
+ useLogScale() { notYetImplemented('useLogScale'); return this; }
259
330
  set3D() { return this.setOption("is3D", true); }
260
- enablePaging(enable, pageSize) { return this; }
261
- enableRtlTable(enable) { return this; }
262
- enableSorting(enable) { return this; }
263
- setFirstRowNumber(number) { return this; }
264
- setInitialSortingAscending(column) { return this; }
265
- setInitialSortingDescending(column) { return this; }
266
- showRowNumberColumn(show) { return this; }
267
- useAlternatingRowStyle(use) { return this; }
268
- setXAxisLogScale() { return this; }
269
- setXAxisRange(min, max) { return this; }
270
- setYAxisLogScale() { return this; }
271
- setYAxisRange(min, max) { return this; }
272
- reverseDirection() { return this; }
331
+ enablePaging(enable, pageSize) { notYetImplemented('enablePaging'); return this; }
332
+ enableRtlTable(enable) { notYetImplemented('enableRtlTable'); return this; }
333
+ enableSorting(enable) { notYetImplemented('enableSorting'); return this; }
334
+ setFirstRowNumber(number) { notYetImplemented('setFirstRowNumber'); return this; }
335
+ setInitialSortingAscending(column) { notYetImplemented('setInitialSortingAscending'); return this; }
336
+ setInitialSortingDescending(column) { notYetImplemented('setInitialSortingDescending'); return this; }
337
+ showRowNumberColumn(show) { notYetImplemented('showRowNumberColumn'); return this; }
338
+ useAlternatingRowStyle(use) { notYetImplemented('useAlternatingRowStyle'); return this; }
339
+ setXAxisLogScale() { notYetImplemented('setXAxisLogScale'); return this; }
340
+
341
+ setXAxisRange(min, max) {
342
+ ScriptApp.__behavior.checkMethod("EmbeddedChartBuilder", "setXAxisRange");
343
+ const axis = this.__getAxis("BOTTOM_AXIS");
344
+ axis.viewWindowOptions = { viewWindowMin: min, viewWindowMax: max };
345
+ return this;
346
+ }
347
+
348
+ setYAxisLogScale() { notYetImplemented('setYAxisLogScale'); return this; }
349
+
350
+ setYAxisRange(min, max) {
351
+ ScriptApp.__behavior.checkMethod("EmbeddedChartBuilder", "setYAxisRange");
352
+ const axis = this.__getAxis("LEFT_AXIS");
353
+ axis.viewWindowOptions = { viewWindowMin: min, viewWindowMax: max };
354
+ return this;
355
+ }
356
+
357
+ reverseDirection() { notYetImplemented('reverseDirection'); return this; }
273
358
 
274
359
  toString() {
275
360
  const type = this.__apiChart.spec.basicChart?.chartType;
@@ -16,8 +16,28 @@ export const sxGmail = async (Auth, { subProp, prop, method, params, options })
16
16
  const tag = `sxGmail for ${methodName}`;
17
17
 
18
18
  return sxRetry(Auth, tag, async () => {
19
- const callish = subProp ? apiClient[prop][subProp] : apiClient[prop];
20
- return callish[method](params, options);
19
+ let context = subProp ? apiClient[prop][subProp] : apiClient[prop];
20
+ let methodFunc = context[method];
21
+
22
+ if (!methodFunc && method.includes('.')) {
23
+ const parts = method.split('.');
24
+ for (const part of parts) {
25
+ if (!context[part]) {
26
+ methodFunc = undefined;
27
+ break;
28
+ }
29
+ methodFunc = context[part];
30
+ if (part !== parts[parts.length - 1]) {
31
+ context = methodFunc;
32
+ }
33
+ }
34
+ }
35
+
36
+ if (typeof methodFunc !== 'function') {
37
+ throw new Error(`Method ${methodName} not found on Gmail API client`);
38
+ }
39
+
40
+ return methodFunc.call(context, params, options);
21
41
  }, {
22
42
  skipLog: (error, response) => {
23
43
  // Don't log 404, 409, or 400 as an error.