@framers/agentos 0.1.52 → 0.1.54

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 (104) hide show
  1. package/dist/api/AgentOS.d.ts +10 -10
  2. package/dist/api/AgentOS.d.ts.map +1 -1
  3. package/dist/channels/index.d.ts +2 -1
  4. package/dist/channels/index.d.ts.map +1 -1
  5. package/dist/channels/index.js +2 -1
  6. package/dist/channels/index.js.map +1 -1
  7. package/dist/core/agency/index.d.ts +1 -2
  8. package/dist/core/agency/index.d.ts.map +1 -1
  9. package/dist/core/agency/index.js +1 -2
  10. package/dist/core/agency/index.js.map +1 -1
  11. package/dist/core/agents/AgentCore.d.ts +8 -19
  12. package/dist/core/agents/AgentCore.d.ts.map +1 -1
  13. package/dist/core/agents/AgentCore.js +7 -15
  14. package/dist/core/agents/AgentCore.js.map +1 -1
  15. package/dist/core/agents/AgentFactory.d.ts +9 -13
  16. package/dist/core/agents/AgentFactory.d.ts.map +1 -1
  17. package/dist/core/agents/AgentFactory.js +9 -13
  18. package/dist/core/agents/AgentFactory.js.map +1 -1
  19. package/dist/core/audio/SilenceDetector.d.ts +5 -5
  20. package/dist/core/audio/SilenceDetector.js +5 -5
  21. package/dist/core/evaluation/index.d.ts +2 -2
  22. package/dist/core/evaluation/index.js +2 -2
  23. package/dist/core/hitl/index.d.ts +1 -2
  24. package/dist/core/hitl/index.d.ts.map +1 -1
  25. package/dist/core/hitl/index.js +1 -2
  26. package/dist/core/hitl/index.js.map +1 -1
  27. package/dist/core/index.d.ts +1 -1
  28. package/dist/core/index.js +1 -1
  29. package/dist/core/llm/IPromptEngine.d.ts +13 -8
  30. package/dist/core/llm/IPromptEngine.d.ts.map +1 -1
  31. package/dist/core/llm/IPromptEngine.js.map +1 -1
  32. package/dist/core/marketplace/index.d.ts +2 -2
  33. package/dist/core/marketplace/index.js +2 -2
  34. package/dist/core/observability/index.d.ts +2 -2
  35. package/dist/core/observability/index.js +2 -2
  36. package/dist/core/planning/index.d.ts +1 -2
  37. package/dist/core/planning/index.d.ts.map +1 -1
  38. package/dist/core/planning/index.js +1 -2
  39. package/dist/core/planning/index.js.map +1 -1
  40. package/dist/core/provenance/index.d.ts +2 -2
  41. package/dist/core/provenance/index.js +2 -2
  42. package/dist/core/safety/index.d.ts +3 -2
  43. package/dist/core/safety/index.d.ts.map +1 -1
  44. package/dist/core/safety/index.js +3 -2
  45. package/dist/core/safety/index.js.map +1 -1
  46. package/dist/core/sandbox/index.d.ts +2 -2
  47. package/dist/core/sandbox/index.js +2 -2
  48. package/dist/core/structured/index.d.ts +1 -2
  49. package/dist/core/structured/index.d.ts.map +1 -1
  50. package/dist/core/structured/index.js +1 -2
  51. package/dist/core/structured/index.js.map +1 -1
  52. package/dist/core/tools/index.d.ts +2 -1
  53. package/dist/core/tools/index.d.ts.map +1 -1
  54. package/dist/core/tools/index.js +2 -1
  55. package/dist/core/tools/index.js.map +1 -1
  56. package/dist/discovery/index.d.ts +2 -1
  57. package/dist/discovery/index.d.ts.map +1 -1
  58. package/dist/discovery/index.js +2 -1
  59. package/dist/discovery/index.js.map +1 -1
  60. package/dist/memory/index.d.ts +2 -1
  61. package/dist/memory/index.d.ts.map +1 -1
  62. package/dist/memory/index.js +2 -1
  63. package/dist/memory/index.js.map +1 -1
  64. package/dist/rag/audit/index.d.ts +5 -2
  65. package/dist/rag/audit/index.d.ts.map +1 -1
  66. package/dist/rag/audit/index.js +5 -2
  67. package/dist/rag/audit/index.js.map +1 -1
  68. package/dist/rag/implementations/vector_stores/InMemoryVectorStore.d.ts +1 -2
  69. package/dist/rag/implementations/vector_stores/InMemoryVectorStore.d.ts.map +1 -1
  70. package/dist/rag/implementations/vector_stores/InMemoryVectorStore.js +1 -2
  71. package/dist/rag/implementations/vector_stores/InMemoryVectorStore.js.map +1 -1
  72. package/dist/rag/reranking/index.d.ts +2 -2
  73. package/dist/rag/reranking/index.js +2 -2
  74. package/dist/rag/reranking/providers/index.d.ts +3 -2
  75. package/dist/rag/reranking/providers/index.d.ts.map +1 -1
  76. package/dist/rag/reranking/providers/index.js +3 -2
  77. package/dist/rag/reranking/providers/index.js.map +1 -1
  78. package/dist/skills/SkillRegistry.js +1 -1
  79. package/dist/skills/SkillRegistry.js.map +1 -1
  80. package/dist/skills/index.d.ts +7 -1
  81. package/dist/skills/index.d.ts.map +1 -1
  82. package/dist/skills/index.js +7 -1
  83. package/dist/skills/index.js.map +1 -1
  84. package/dist/social-posting/ContentAdaptationEngine.d.ts +148 -0
  85. package/dist/social-posting/ContentAdaptationEngine.d.ts.map +1 -0
  86. package/dist/social-posting/ContentAdaptationEngine.js +445 -0
  87. package/dist/social-posting/ContentAdaptationEngine.js.map +1 -0
  88. package/dist/social-posting/SocialAbstractService.d.ts +52 -0
  89. package/dist/social-posting/SocialAbstractService.d.ts.map +1 -0
  90. package/dist/social-posting/SocialAbstractService.js +127 -0
  91. package/dist/social-posting/SocialAbstractService.js.map +1 -0
  92. package/dist/social-posting/SocialPostManager.d.ts +252 -0
  93. package/dist/social-posting/SocialPostManager.d.ts.map +1 -0
  94. package/dist/social-posting/SocialPostManager.js +344 -0
  95. package/dist/social-posting/SocialPostManager.js.map +1 -0
  96. package/dist/social-posting/index.d.ts +12 -0
  97. package/dist/social-posting/index.d.ts.map +1 -0
  98. package/dist/social-posting/index.js +15 -0
  99. package/dist/social-posting/index.js.map +1 -0
  100. package/dist/voice/index.d.ts +2 -1
  101. package/dist/voice/index.d.ts.map +1 -1
  102. package/dist/voice/index.js +2 -1
  103. package/dist/voice/index.js.map +1 -1
  104. package/package.json +6 -3
@@ -0,0 +1,445 @@
1
+ /**
2
+ * @fileoverview Content Adaptation Engine — platform-specific content transformation.
3
+ * @module @framers/agentos/social-posting/ContentAdaptationEngine
4
+ *
5
+ * Applies static, deterministic rules to adapt a base content string for
6
+ * each target social media platform. The engine enforces character limits,
7
+ * hashtag placement, and generates platform-specific warnings.
8
+ *
9
+ * LLM-powered adaptation (tone rewriting, audience targeting, etc.) is
10
+ * intentionally left to the skill layer. This module provides the
11
+ * constraint-aware foundation that skills can build upon.
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * import { ContentAdaptationEngine } from '../social-posting/index.js';
16
+ *
17
+ * const engine = new ContentAdaptationEngine();
18
+ *
19
+ * const adapted = engine.adaptContent(
20
+ * 'Announcing our new feature! Check it out at https://example.com',
21
+ * ['twitter', 'linkedin', 'instagram'],
22
+ * ['announcement', 'product'],
23
+ * );
24
+ *
25
+ * console.log(adapted.twitter.text); // Truncated to 280 chars if needed
26
+ * console.log(adapted.instagram.hashtags); // ['#announcement', '#product']
27
+ * ```
28
+ */
29
+ // ============================================================================
30
+ // Platform Constraints Registry
31
+ // ============================================================================
32
+ /**
33
+ * Static constraint definitions for all supported social media platforms.
34
+ *
35
+ * Platforms are grouped by category:
36
+ * - Short-form: twitter, threads, bluesky, mastodon, farcaster
37
+ * - Visual-first: instagram, tiktok, pinterest, youtube
38
+ * - Professional/general: linkedin, facebook, reddit, lemmy
39
+ * - Long-form blogging: devto, hashnode, medium, wordpress
40
+ */
41
+ const PLATFORM_CONSTRAINTS = {
42
+ // --------------------------------------------------------------------------
43
+ // Short-form Micro-blogging
44
+ // --------------------------------------------------------------------------
45
+ twitter: {
46
+ maxLength: 280,
47
+ hashtagStyle: 'inline',
48
+ maxHashtags: 5,
49
+ supportsMedia: true,
50
+ supportsVideo: true,
51
+ supportsCarousel: false,
52
+ supportsPoll: true,
53
+ supportsThreading: true,
54
+ toneGuidance: 'Concise, punchy, conversational. Use threads for longer content.',
55
+ },
56
+ threads: {
57
+ maxLength: 500,
58
+ hashtagStyle: 'inline',
59
+ maxHashtags: 5,
60
+ supportsMedia: true,
61
+ supportsVideo: true,
62
+ supportsCarousel: true,
63
+ supportsPoll: false,
64
+ supportsThreading: true,
65
+ toneGuidance: 'Conversational, casual, community-oriented.',
66
+ },
67
+ bluesky: {
68
+ maxLength: 300,
69
+ hashtagStyle: 'none',
70
+ maxHashtags: 0,
71
+ supportsMedia: true,
72
+ supportsVideo: true,
73
+ supportsCarousel: false,
74
+ supportsPoll: false,
75
+ supportsThreading: true,
76
+ toneGuidance: 'Authentic, concise. Hashtags use facets (rich text), not inline text.',
77
+ },
78
+ mastodon: {
79
+ maxLength: 500,
80
+ hashtagStyle: 'inline',
81
+ maxHashtags: 10,
82
+ supportsMedia: true,
83
+ supportsVideo: true,
84
+ supportsCarousel: false,
85
+ supportsPoll: true,
86
+ supportsThreading: true,
87
+ toneGuidance: 'Community-conscious, CW (content warning) support encouraged.',
88
+ },
89
+ farcaster: {
90
+ maxLength: 320,
91
+ hashtagStyle: 'none',
92
+ maxHashtags: 0,
93
+ supportsMedia: true,
94
+ supportsVideo: false,
95
+ supportsCarousel: false,
96
+ supportsPoll: false,
97
+ supportsThreading: true,
98
+ toneGuidance: 'Crypto/web3 native, concise, authentic.',
99
+ },
100
+ // --------------------------------------------------------------------------
101
+ // Visual-First Platforms
102
+ // --------------------------------------------------------------------------
103
+ instagram: {
104
+ maxLength: 2200,
105
+ hashtagStyle: 'footer',
106
+ maxHashtags: 30,
107
+ supportsMedia: true,
108
+ supportsVideo: true,
109
+ supportsCarousel: true,
110
+ supportsPoll: false,
111
+ supportsThreading: false,
112
+ toneGuidance: 'Visual-first, storytelling, hashtags in footer block.',
113
+ },
114
+ tiktok: {
115
+ maxLength: 2200,
116
+ hashtagStyle: 'inline',
117
+ maxHashtags: 10,
118
+ supportsMedia: false,
119
+ supportsVideo: true,
120
+ supportsCarousel: false,
121
+ supportsPoll: false,
122
+ supportsThreading: false,
123
+ toneGuidance: 'Trendy, authentic, short-form video focused.',
124
+ },
125
+ pinterest: {
126
+ maxLength: 500,
127
+ hashtagStyle: 'none',
128
+ maxHashtags: 0,
129
+ supportsMedia: true,
130
+ supportsVideo: true,
131
+ supportsCarousel: true,
132
+ supportsPoll: false,
133
+ supportsThreading: false,
134
+ toneGuidance: 'Keyword-rich, descriptive, aspirational. Focus on discoverability.',
135
+ },
136
+ youtube: {
137
+ maxLength: 5000,
138
+ hashtagStyle: 'inline',
139
+ maxHashtags: 15,
140
+ supportsMedia: false,
141
+ supportsVideo: true,
142
+ supportsCarousel: false,
143
+ supportsPoll: true,
144
+ supportsThreading: false,
145
+ toneGuidance: 'Descriptive, SEO-aware. This is the video description field.',
146
+ },
147
+ // --------------------------------------------------------------------------
148
+ // Professional & General Social
149
+ // --------------------------------------------------------------------------
150
+ linkedin: {
151
+ maxLength: 3000,
152
+ hashtagStyle: 'footer',
153
+ maxHashtags: 5,
154
+ supportsMedia: true,
155
+ supportsVideo: true,
156
+ supportsCarousel: true,
157
+ supportsPoll: true,
158
+ supportsThreading: false,
159
+ toneGuidance: 'Professional, thought-leadership, industry insights.',
160
+ },
161
+ facebook: {
162
+ maxLength: 63206,
163
+ hashtagStyle: 'inline',
164
+ maxHashtags: 10,
165
+ supportsMedia: true,
166
+ supportsVideo: true,
167
+ supportsCarousel: true,
168
+ supportsPoll: true,
169
+ supportsThreading: false,
170
+ toneGuidance: 'Casual, community-driven, longer-form acceptable.',
171
+ },
172
+ reddit: {
173
+ maxLength: 40000,
174
+ hashtagStyle: 'none',
175
+ maxHashtags: 0,
176
+ supportsMedia: true,
177
+ supportsVideo: true,
178
+ supportsCarousel: false,
179
+ supportsPoll: true,
180
+ supportsThreading: false,
181
+ toneGuidance: 'Community-specific, informative, no hashtags. Markdown supported.',
182
+ },
183
+ lemmy: {
184
+ maxLength: 10000,
185
+ hashtagStyle: 'none',
186
+ maxHashtags: 0,
187
+ supportsMedia: true,
188
+ supportsVideo: false,
189
+ supportsCarousel: false,
190
+ supportsPoll: false,
191
+ supportsThreading: false,
192
+ toneGuidance: 'Community-focused, federated. Markdown supported.',
193
+ },
194
+ // --------------------------------------------------------------------------
195
+ // Long-Form Blogging
196
+ // --------------------------------------------------------------------------
197
+ devto: {
198
+ maxLength: 100000,
199
+ hashtagStyle: 'none',
200
+ maxHashtags: 0,
201
+ supportsMedia: true,
202
+ supportsVideo: false,
203
+ supportsCarousel: false,
204
+ supportsPoll: false,
205
+ supportsThreading: false,
206
+ toneGuidance: 'Developer-focused, technical, tutorial-style. Markdown/front-matter.',
207
+ },
208
+ hashnode: {
209
+ maxLength: 100000,
210
+ hashtagStyle: 'none',
211
+ maxHashtags: 0,
212
+ supportsMedia: true,
213
+ supportsVideo: false,
214
+ supportsCarousel: false,
215
+ supportsPoll: false,
216
+ supportsThreading: false,
217
+ toneGuidance: 'Developer blogging, technical depth, markdown.',
218
+ },
219
+ medium: {
220
+ maxLength: 100000,
221
+ hashtagStyle: 'none',
222
+ maxHashtags: 0,
223
+ supportsMedia: true,
224
+ supportsVideo: false,
225
+ supportsCarousel: false,
226
+ supportsPoll: false,
227
+ supportsThreading: false,
228
+ toneGuidance: 'Narrative, polished, long-form essays and thought pieces.',
229
+ },
230
+ wordpress: {
231
+ maxLength: 100000,
232
+ hashtagStyle: 'none',
233
+ maxHashtags: 0,
234
+ supportsMedia: true,
235
+ supportsVideo: true,
236
+ supportsCarousel: false,
237
+ supportsPoll: false,
238
+ supportsThreading: false,
239
+ toneGuidance: 'Flexible — depends on blog style. HTML and shortcodes supported.',
240
+ },
241
+ };
242
+ // ============================================================================
243
+ // ContentAdaptationEngine
244
+ // ============================================================================
245
+ /**
246
+ * Adapts base content for multiple social media platforms using static rules.
247
+ *
248
+ * The engine applies character limits, hashtag formatting, and generates
249
+ * warnings when content exceeds platform constraints. It does **not** perform
250
+ * LLM-based rewriting — that responsibility belongs to the skill layer which
251
+ * can call the engine's constraint methods to inform its prompts.
252
+ *
253
+ * @example
254
+ * ```typescript
255
+ * const engine = new ContentAdaptationEngine();
256
+ * const results = engine.adaptContent(
257
+ * 'We just shipped dark mode! Try it out.',
258
+ * ['twitter', 'linkedin'],
259
+ * ['darkmode', 'shipping'],
260
+ * );
261
+ *
262
+ * // results.twitter.text --> 'We just shipped dark mode! Try it out. #darkmode #shipping'
263
+ * // results.linkedin.text --> 'We just shipped dark mode! Try it out.\n\n#darkmode #shipping'
264
+ * ```
265
+ */
266
+ export class ContentAdaptationEngine {
267
+ // --------------------------------------------------------------------------
268
+ // Public API
269
+ // --------------------------------------------------------------------------
270
+ /**
271
+ * Adapt base content for one or more target platforms.
272
+ *
273
+ * For each platform, the engine:
274
+ * 1. Formats hashtags according to the platform's hashtagStyle
275
+ * 2. Truncates content if it exceeds the platform's maxLength
276
+ * 3. Generates warnings for any constraint violations
277
+ *
278
+ * @param baseContent - The original, platform-agnostic content
279
+ * @param platforms - Target platform identifiers
280
+ * @param hashtags - Optional hashtags (without '#' prefix)
281
+ * @returns A record mapping each platform to its adapted content
282
+ */
283
+ adaptContent(baseContent, platforms, hashtags) {
284
+ const results = {};
285
+ for (const platform of platforms) {
286
+ results[platform] = this.adaptForPlatform(baseContent, platform, hashtags);
287
+ }
288
+ return results;
289
+ }
290
+ /**
291
+ * Retrieve the constraint definition for a platform.
292
+ *
293
+ * Returns a default constraint set for unknown platforms (10000 chars,
294
+ * no hashtags, basic media support).
295
+ *
296
+ * @param platform - Platform identifier
297
+ * @returns The PlatformConstraints for the given platform
298
+ */
299
+ getConstraints(platform) {
300
+ return PLATFORM_CONSTRAINTS[platform] ?? this.getDefaultConstraints();
301
+ }
302
+ /**
303
+ * Truncate text to a maximum length, appending an ellipsis if truncated.
304
+ *
305
+ * Attempts to break at a word boundary to avoid cutting words mid-token.
306
+ * If no word boundary is found within the last 30 characters, truncates
307
+ * at the hard limit.
308
+ *
309
+ * @param text - The text to truncate
310
+ * @param maxLength - Maximum allowed length (including ellipsis)
311
+ * @returns The truncated text, or the original if within limits
312
+ */
313
+ truncateWithEllipsis(text, maxLength) {
314
+ if (text.length <= maxLength) {
315
+ return text;
316
+ }
317
+ const ellipsis = '...';
318
+ const targetLength = maxLength - ellipsis.length;
319
+ if (targetLength <= 0) {
320
+ return text.slice(0, maxLength);
321
+ }
322
+ // Try to break at a word boundary
323
+ const truncated = text.slice(0, targetLength);
324
+ const lastSpace = truncated.lastIndexOf(' ');
325
+ // Only break at word boundary if it's within 30 chars of the target
326
+ if (lastSpace > 0 && targetLength - lastSpace < 30) {
327
+ return truncated.slice(0, lastSpace) + ellipsis;
328
+ }
329
+ return truncated + ellipsis;
330
+ }
331
+ // --------------------------------------------------------------------------
332
+ // Internal Helpers
333
+ // --------------------------------------------------------------------------
334
+ /**
335
+ * Adapt content for a single platform.
336
+ */
337
+ adaptForPlatform(baseContent, platform, hashtags) {
338
+ const constraints = this.getConstraints(platform);
339
+ const warnings = [];
340
+ // Normalize and limit hashtags
341
+ const normalizedHashtags = this.normalizeHashtags(hashtags ?? [], constraints.maxHashtags);
342
+ if (hashtags && hashtags.length > constraints.maxHashtags) {
343
+ warnings.push(`Hashtag count (${hashtags.length}) exceeds platform maximum (${constraints.maxHashtags}). ` +
344
+ `Truncated to ${constraints.maxHashtags}.`);
345
+ }
346
+ // Build the full text with hashtags placed according to platform style
347
+ let fullText = this.formatWithHashtags(baseContent, normalizedHashtags, constraints.hashtagStyle);
348
+ // Check for truncation
349
+ let truncated = false;
350
+ if (fullText.length > constraints.maxLength) {
351
+ // If hashtags are in footer, try truncating just the content
352
+ if (constraints.hashtagStyle === 'footer' &&
353
+ normalizedHashtags.length > 0) {
354
+ const hashtagBlock = this.buildHashtagBlock(normalizedHashtags);
355
+ const contentBudget = constraints.maxLength - hashtagBlock.length - 2; // 2 for '\n\n'
356
+ if (contentBudget > 0) {
357
+ const truncatedContent = this.truncateWithEllipsis(baseContent, contentBudget);
358
+ fullText = truncatedContent + '\n\n' + hashtagBlock;
359
+ truncated = true;
360
+ }
361
+ else {
362
+ fullText = this.truncateWithEllipsis(fullText, constraints.maxLength);
363
+ truncated = true;
364
+ }
365
+ }
366
+ else {
367
+ fullText = this.truncateWithEllipsis(fullText, constraints.maxLength);
368
+ truncated = true;
369
+ }
370
+ warnings.push(`Content truncated from ${baseContent.length} to fit ${platform}'s ` +
371
+ `${constraints.maxLength} character limit.`);
372
+ }
373
+ // Platform-specific warnings
374
+ if (platform === 'bluesky' && hashtags && hashtags.length > 0) {
375
+ warnings.push('Bluesky uses facets (rich text) for hashtags, not inline text. ' +
376
+ 'Hashtags have been omitted from the text. Apply them via the AT Protocol facets API.');
377
+ }
378
+ if (platform === 'mastodon') {
379
+ warnings.push('Consider adding a Content Warning (CW) if the content is sensitive.');
380
+ }
381
+ return {
382
+ platform,
383
+ text: fullText,
384
+ hashtags: normalizedHashtags,
385
+ truncated,
386
+ mediaSupported: constraints.supportsMedia,
387
+ warnings,
388
+ };
389
+ }
390
+ /**
391
+ * Normalize hashtags: ensure '#' prefix, deduplicate, and limit count.
392
+ */
393
+ normalizeHashtags(hashtags, maxCount) {
394
+ if (maxCount === 0)
395
+ return [];
396
+ const seen = new Set();
397
+ const normalized = [];
398
+ for (const tag of hashtags) {
399
+ const cleaned = tag.startsWith('#') ? tag : `#${tag}`;
400
+ const lower = cleaned.toLowerCase();
401
+ if (!seen.has(lower) && normalized.length < maxCount) {
402
+ seen.add(lower);
403
+ normalized.push(cleaned);
404
+ }
405
+ }
406
+ return normalized;
407
+ }
408
+ /**
409
+ * Format content with hashtags according to the platform's style.
410
+ */
411
+ formatWithHashtags(content, hashtags, style) {
412
+ if (hashtags.length === 0 || style === 'none') {
413
+ return content;
414
+ }
415
+ if (style === 'footer') {
416
+ const hashtagBlock = this.buildHashtagBlock(hashtags);
417
+ return content + '\n\n' + hashtagBlock;
418
+ }
419
+ // Inline: append hashtags after the content with a space
420
+ return content + ' ' + hashtags.join(' ');
421
+ }
422
+ /**
423
+ * Build a hashtag block string for footer-style placement.
424
+ */
425
+ buildHashtagBlock(hashtags) {
426
+ return hashtags.join(' ');
427
+ }
428
+ /**
429
+ * Default constraints for unknown platforms.
430
+ */
431
+ getDefaultConstraints() {
432
+ return {
433
+ maxLength: 10000,
434
+ hashtagStyle: 'inline',
435
+ maxHashtags: 10,
436
+ supportsMedia: true,
437
+ supportsVideo: true,
438
+ supportsCarousel: false,
439
+ supportsPoll: false,
440
+ supportsThreading: false,
441
+ toneGuidance: 'General purpose. Adapt to the specific platform context.',
442
+ };
443
+ }
444
+ }
445
+ //# sourceMappingURL=ContentAdaptationEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContentAdaptationEngine.js","sourceRoot":"","sources":["../../src/social-posting/ContentAdaptationEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * @fileoverview Shared HTTP primitives for social channel services.
3
+ * @module @framers/agentos/social-posting/SocialAbstractService
4
+ */
5
+ export interface SocialRequestOptions {
6
+ /** Retry attempts after the initial request. */
7
+ maxRetries?: number;
8
+ /** Base delay for exponential backoff (ms). */
9
+ retryDelayMs?: number;
10
+ /** Max delay cap for backoff (ms). */
11
+ maxRetryDelayMs?: number;
12
+ /** Request timeout (ms). */
13
+ timeoutMs?: number;
14
+ /** Optional override for retryable HTTP status logic. */
15
+ shouldRetryStatus?: (status: number) => boolean;
16
+ }
17
+ export interface SocialServiceConfig {
18
+ /** Minimum spacing between outbound API requests. */
19
+ minRequestIntervalMs?: number;
20
+ /** Default retry attempts after initial request. */
21
+ defaultMaxRetries?: number;
22
+ /** Default base retry delay (ms). */
23
+ defaultRetryDelayMs?: number;
24
+ /** Default request timeout (ms). */
25
+ defaultTimeoutMs?: number;
26
+ }
27
+ /**
28
+ * Base class for social channel service layers.
29
+ *
30
+ * Adds:
31
+ * - request rate-limiting
32
+ * - retry with exponential backoff on retryable failures
33
+ * - JSON request/response helpers
34
+ * - OAuth scope assertion helper
35
+ */
36
+ export declare abstract class SocialAbstractService {
37
+ private readonly minRequestIntervalMs;
38
+ private readonly defaultMaxRetries;
39
+ private readonly defaultRetryDelayMs;
40
+ private readonly defaultTimeoutMs;
41
+ private lastRequestAt;
42
+ private rateLimiter;
43
+ protected constructor(config?: SocialServiceConfig);
44
+ protected fetchJson<T>(url: string, init?: RequestInit, options?: SocialRequestOptions): Promise<T>;
45
+ protected fetchText(url: string, init?: RequestInit, options?: SocialRequestOptions): Promise<string>;
46
+ protected fetchWithRetry(url: string, init?: RequestInit, options?: SocialRequestOptions): Promise<Response>;
47
+ protected assertScopes(requiredScopes: string[], grantedScopes?: string[]): void;
48
+ private fetchOnce;
49
+ private waitForRateLimit;
50
+ private computeBackoff;
51
+ }
52
+ //# sourceMappingURL=SocialAbstractService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SocialAbstractService.d.ts","sourceRoot":"","sources":["../../src/social-posting/SocialAbstractService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,oBAAoB;IACnC,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sCAAsC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,4BAA4B;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;CACjD;AAED,MAAM,WAAW,mBAAmB;IAClC,qDAAqD;IACrD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,oDAAoD;IACpD,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qCAAqC;IACrC,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAYD;;;;;;;;GAQG;AACH,8BAAsB,qBAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAS;IAC3C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,WAAW,CAAoC;IAEvD,SAAS,aAAa,MAAM,GAAE,mBAAwB;cAOtC,SAAS,CAAC,CAAC,EACzB,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,WAAgB,EACtB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,CAAC,CAAC;cAWG,SAAS,CACvB,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,WAAgB,EACtB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,MAAM,CAAC;cAKF,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,IAAI,GAAE,WAAgB,EACtB,OAAO,GAAE,oBAAyB,GACjC,OAAO,CAAC,QAAQ,CAAC;IAoCpB,SAAS,CAAC,YAAY,CAAC,cAAc,EAAE,MAAM,EAAE,EAAE,aAAa,GAAE,MAAM,EAAO,GAAG,IAAI;YAQtE,SAAS;YAgCT,gBAAgB;IAkB9B,OAAO,CAAC,cAAc;CAIvB"}
@@ -0,0 +1,127 @@
1
+ /**
2
+ * @fileoverview Shared HTTP primitives for social channel services.
3
+ * @module @framers/agentos/social-posting/SocialAbstractService
4
+ */
5
+ const DEFAULT_MAX_RETRIES = 2;
6
+ const DEFAULT_RETRY_DELAY_MS = 300;
7
+ const DEFAULT_MAX_RETRY_DELAY_MS = 5000;
8
+ const DEFAULT_TIMEOUT_MS = 15000;
9
+ const defaultRetryStatus = (status) => status === 429 || status >= 500;
10
+ const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
11
+ /**
12
+ * Base class for social channel service layers.
13
+ *
14
+ * Adds:
15
+ * - request rate-limiting
16
+ * - retry with exponential backoff on retryable failures
17
+ * - JSON request/response helpers
18
+ * - OAuth scope assertion helper
19
+ */
20
+ export class SocialAbstractService {
21
+ constructor(config = {}) {
22
+ this.lastRequestAt = 0;
23
+ this.rateLimiter = Promise.resolve();
24
+ this.minRequestIntervalMs = Math.max(0, config.minRequestIntervalMs ?? 0);
25
+ this.defaultMaxRetries = Math.max(0, config.defaultMaxRetries ?? DEFAULT_MAX_RETRIES);
26
+ this.defaultRetryDelayMs = Math.max(1, config.defaultRetryDelayMs ?? DEFAULT_RETRY_DELAY_MS);
27
+ this.defaultTimeoutMs = Math.max(1, config.defaultTimeoutMs ?? DEFAULT_TIMEOUT_MS);
28
+ }
29
+ async fetchJson(url, init = {}, options = {}) {
30
+ const res = await this.fetchWithRetry(url, init, options);
31
+ const contentType = (res.headers.get('content-type') ?? '').toLowerCase();
32
+ if (contentType.includes('application/json')) {
33
+ return (await res.json());
34
+ }
35
+ const text = await res.text();
36
+ return text;
37
+ }
38
+ async fetchText(url, init = {}, options = {}) {
39
+ const res = await this.fetchWithRetry(url, init, options);
40
+ return res.text();
41
+ }
42
+ async fetchWithRetry(url, init = {}, options = {}) {
43
+ const maxRetries = options.maxRetries ?? this.defaultMaxRetries;
44
+ const retryDelayMs = options.retryDelayMs ?? this.defaultRetryDelayMs;
45
+ const maxRetryDelayMs = options.maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
46
+ const timeoutMs = options.timeoutMs ?? this.defaultTimeoutMs;
47
+ const shouldRetryStatus = options.shouldRetryStatus ?? defaultRetryStatus;
48
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
49
+ let response = null;
50
+ try {
51
+ await this.waitForRateLimit();
52
+ response = await this.fetchOnce(url, init, timeoutMs);
53
+ }
54
+ catch (err) {
55
+ if (attempt >= maxRetries) {
56
+ throw err instanceof Error ? err : new Error(String(err));
57
+ }
58
+ await wait(this.computeBackoff(attempt, retryDelayMs, maxRetryDelayMs));
59
+ continue;
60
+ }
61
+ if (response.ok)
62
+ return response;
63
+ if (attempt < maxRetries && shouldRetryStatus(response.status)) {
64
+ await wait(this.computeBackoff(attempt, retryDelayMs, maxRetryDelayMs));
65
+ continue;
66
+ }
67
+ const body = await response.text().catch(() => '');
68
+ throw new Error(`HTTP ${response.status} ${response.statusText}${body ? `: ${body}` : ''}`);
69
+ }
70
+ throw new Error('Request failed after retry attempts were exhausted.');
71
+ }
72
+ assertScopes(requiredScopes, grantedScopes = []) {
73
+ const granted = new Set(grantedScopes);
74
+ const missing = requiredScopes.filter((scope) => !granted.has(scope));
75
+ if (missing.length === 0)
76
+ return;
77
+ throw new Error(`Missing required OAuth scopes: ${missing.join(', ')}`);
78
+ }
79
+ async fetchOnce(url, init, timeoutMs) {
80
+ const controller = new AbortController();
81
+ const timeout = setTimeout(() => controller.abort(), timeoutMs);
82
+ try {
83
+ const normalizedInit = {
84
+ ...init,
85
+ signal: controller.signal,
86
+ };
87
+ if (normalizedInit.body &&
88
+ typeof normalizedInit.body === 'object' &&
89
+ !(normalizedInit.body instanceof URLSearchParams) &&
90
+ !(normalizedInit.body instanceof FormData) &&
91
+ !(normalizedInit.body instanceof Blob) &&
92
+ !(normalizedInit.body instanceof ArrayBuffer)) {
93
+ normalizedInit.body = JSON.stringify(normalizedInit.body);
94
+ const headers = new Headers(normalizedInit.headers ?? {});
95
+ if (!headers.has('content-type')) {
96
+ headers.set('content-type', 'application/json');
97
+ }
98
+ normalizedInit.headers = headers;
99
+ }
100
+ return await fetch(url, normalizedInit);
101
+ }
102
+ finally {
103
+ clearTimeout(timeout);
104
+ }
105
+ }
106
+ async waitForRateLimit() {
107
+ this.rateLimiter = this.rateLimiter.then(async () => {
108
+ if (this.minRequestIntervalMs <= 0) {
109
+ this.lastRequestAt = Date.now();
110
+ return;
111
+ }
112
+ const now = Date.now();
113
+ const delta = now - this.lastRequestAt;
114
+ const waitMs = Math.max(0, this.minRequestIntervalMs - delta);
115
+ if (waitMs > 0) {
116
+ await wait(waitMs);
117
+ }
118
+ this.lastRequestAt = Date.now();
119
+ });
120
+ return this.rateLimiter;
121
+ }
122
+ computeBackoff(attempt, baseMs, capMs) {
123
+ const raw = baseMs * 2 ** attempt;
124
+ return Math.min(capMs, raw);
125
+ }
126
+ }
127
+ //# sourceMappingURL=SocialAbstractService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SocialAbstractService.js","sourceRoot":"","sources":["../../src/social-posting/SocialAbstractService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0BH,MAAM,mBAAmB,GAAG,CAAC,CAAC;AAC9B,MAAM,sBAAsB,GAAG,GAAG,CAAC;AACnC,MAAM,0BAA0B,GAAG,IAAI,CAAC;AACxC,MAAM,kBAAkB,GAAG,KAAK,CAAC;AAEjC,MAAM,kBAAkB,GAAG,CAAC,MAAc,EAAW,EAAE,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,CAAC;AAExF,MAAM,IAAI,GAAG,CAAC,EAAU,EAAiB,EAAE,CACzC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAEpD;;;;;;;;GAQG;AACH,MAAM,OAAgB,qBAAqB;IAQzC,YAAsB,SAA8B,EAAE;QAH9C,kBAAa,GAAG,CAAC,CAAC;QAClB,gBAAW,GAAkB,OAAO,CAAC,OAAO,EAAE,CAAC;QAGrD,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,oBAAoB,IAAI,CAAC,CAAC,CAAC;QAC1E,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,iBAAiB,IAAI,mBAAmB,CAAC,CAAC;QACtF,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,mBAAmB,IAAI,sBAAsB,CAAC,CAAC;QAC7F,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,gBAAgB,IAAI,kBAAkB,CAAC,CAAC;IACrF,CAAC;IAES,KAAK,CAAC,SAAS,CACvB,GAAW,EACX,OAAoB,EAAE,EACtB,UAAgC,EAAE;QAElC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1D,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1E,IAAI,WAAW,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC7C,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;QACjC,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,IAAoB,CAAC;IAC9B,CAAC;IAES,KAAK,CAAC,SAAS,CACvB,GAAW,EACX,OAAoB,EAAE,EACtB,UAAgC,EAAE;QAElC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QAC1D,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAES,KAAK,CAAC,cAAc,CAC5B,GAAW,EACX,OAAoB,EAAE,EACtB,UAAgC,EAAE;QAElC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC,iBAAiB,CAAC;QAChE,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,IAAI,CAAC,mBAAmB,CAAC;QACtE,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,0BAA0B,CAAC;QAC9E,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,gBAAgB,CAAC;QAC7D,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,IAAI,kBAAkB,CAAC;QAE1E,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,IAAI,CAAC,EAAE,CAAC;YAC1D,IAAI,QAAQ,GAAoB,IAAI,CAAC;YACrC,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC9B,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;YACxD,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,OAAO,IAAI,UAAU,EAAE,CAAC;oBAC1B,MAAM,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5D,CAAC;gBACD,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC;gBACxE,SAAS;YACX,CAAC;YAED,IAAI,QAAQ,CAAC,EAAE;gBAAE,OAAO,QAAQ,CAAC;YAEjC,IAAI,OAAO,GAAG,UAAU,IAAI,iBAAiB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/D,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC,CAAC;gBACxE,SAAS;YACX,CAAC;YAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YACnD,MAAM,IAAI,KAAK,CACb,QAAQ,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3E,CAAC;QACJ,CAAC;QAED,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAES,YAAY,CAAC,cAAwB,EAAE,gBAA0B,EAAE;QAC3E,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACtE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEjC,MAAM,IAAI,KAAK,CAAC,kCAAkC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,IAAiB,EAAE,SAAiB;QACvE,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,SAAS,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,cAAc,GAAgB;gBAClC,GAAG,IAAI;gBACP,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC;YAEF,IACE,cAAc,CAAC,IAAI;gBACnB,OAAO,cAAc,CAAC,IAAI,KAAK,QAAQ;gBACvC,CAAC,CAAC,cAAc,CAAC,IAAI,YAAY,eAAe,CAAC;gBACjD,CAAC,CAAC,cAAc,CAAC,IAAI,YAAY,QAAQ,CAAC;gBAC1C,CAAC,CAAC,cAAc,CAAC,IAAI,YAAY,IAAI,CAAC;gBACtC,CAAC,CAAC,cAAc,CAAC,IAAI,YAAY,WAAW,CAAC,EAC7C,CAAC;gBACD,cAAc,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;gBAC1D,MAAM,OAAO,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;gBAC1D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;oBACjC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;gBAClD,CAAC;gBACD,cAAc,CAAC,OAAO,GAAG,OAAO,CAAC;YACnC,CAAC;YAED,OAAO,MAAM,KAAK,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QAC1C,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,OAAO,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,gBAAgB;QAC5B,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;YAClD,IAAI,IAAI,CAAC,oBAAoB,IAAI,CAAC,EAAE,CAAC;gBACnC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAChC,OAAO;YACT,CAAC;YAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YACvB,MAAM,KAAK,GAAG,GAAG,GAAG,IAAI,CAAC,aAAa,CAAC;YACvC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,oBAAoB,GAAG,KAAK,CAAC,CAAC;YAC9D,IAAI,MAAM,GAAG,CAAC,EAAE,CAAC;gBACf,MAAM,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,CAAC;YACD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAEO,cAAc,CAAC,OAAe,EAAE,MAAc,EAAE,KAAa;QACnE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC;QAClC,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC9B,CAAC;CACF"}