crewly 1.4.61 → 1.4.63

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 (105) hide show
  1. package/config/skills/agent/content-calendar/execute.sh +2 -2
  2. package/config/skills/agent/marketing/brand-onboarding/SKILL.md +76 -0
  3. package/config/skills/agent/marketing/brand-onboarding/execute.sh +312 -0
  4. package/config/skills/agent/marketing/submit-for-approval/SKILL.md +73 -0
  5. package/config/skills/agent/marketing/submit-for-approval/execute.sh +138 -0
  6. package/config/skills/agent/marketing/weekly-content-planning/SKILL.md +52 -0
  7. package/config/skills/agent/marketing/weekly-content-planning/execute.sh +202 -0
  8. package/config/skills/agent/marketing/weekly-content-planning/execute.test.sh +151 -0
  9. package/config/skills/agent/marketing/weekly-marketing-report/SKILL.md +51 -0
  10. package/config/skills/agent/marketing/weekly-marketing-report/execute.sh +190 -0
  11. package/config/skills/agent/marketing/weekly-marketing-report/execute.test.sh +241 -0
  12. package/config/skills/orchestrator/send-to-remote/SKILL.md +51 -0
  13. package/config/skills/orchestrator/send-to-remote/execute.sh +114 -0
  14. package/config/templates/marketing-team/README.md +42 -0
  15. package/config/templates/marketing-team/goals.md +21 -0
  16. package/config/templates/marketing-team/knowledge/docs/brand-voice-guide.md +61 -0
  17. package/config/templates/marketing-team/knowledge/docs/content-best-practices.md +64 -0
  18. package/config/templates/marketing-team/knowledge/index.json +24 -0
  19. package/config/templates/marketing-team/learned-patterns.json +5 -0
  20. package/config/templates/marketing-team/norms/brand-consistency.md +40 -0
  21. package/config/templates/marketing-team/norms/content-quality-checklist.md +45 -0
  22. package/config/templates/marketing-team/quality-gates.yaml +47 -0
  23. package/config/templates/marketing-team/roles/analyst.md +63 -0
  24. package/config/templates/marketing-team/roles/strategist.md +26 -0
  25. package/config/templates/marketing-team/roles/writer.md +58 -0
  26. package/config/templates/marketing-team/template.json +90 -0
  27. package/config/templates/marketing-team/workflows/weekly-content-cycle.yaml +48 -0
  28. package/dist/backend/backend/src/constants.d.ts +9 -0
  29. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  30. package/dist/backend/backend/src/constants.js +9 -0
  31. package/dist/backend/backend/src/constants.js.map +1 -1
  32. package/dist/backend/backend/src/controllers/cross-machine/cross-machine.controller.d.ts +16 -0
  33. package/dist/backend/backend/src/controllers/cross-machine/cross-machine.controller.d.ts.map +1 -0
  34. package/dist/backend/backend/src/controllers/cross-machine/cross-machine.controller.js +140 -0
  35. package/dist/backend/backend/src/controllers/cross-machine/cross-machine.controller.js.map +1 -0
  36. package/dist/backend/backend/src/controllers/cross-machine/index.d.ts +7 -0
  37. package/dist/backend/backend/src/controllers/cross-machine/index.d.ts.map +1 -0
  38. package/dist/backend/backend/src/controllers/cross-machine/index.js +7 -0
  39. package/dist/backend/backend/src/controllers/cross-machine/index.js.map +1 -0
  40. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  41. package/dist/backend/backend/src/routes/api.routes.js +3 -0
  42. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  43. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  44. package/dist/backend/backend/src/services/agent/agent-registration.service.js +46 -6
  45. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  46. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts +13 -0
  47. package/dist/backend/backend/src/services/ai/prompt-builder.service.d.ts.map +1 -1
  48. package/dist/backend/backend/src/services/ai/prompt-builder.service.js +50 -5
  49. package/dist/backend/backend/src/services/ai/prompt-builder.service.js.map +1 -1
  50. package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.d.ts +8 -0
  51. package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.d.ts.map +1 -1
  52. package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.js +52 -3
  53. package/dist/backend/backend/src/services/cloud/device-auto-discovery.service.js.map +1 -1
  54. package/dist/backend/backend/src/services/cloud/relay-client.service.d.ts +5 -1
  55. package/dist/backend/backend/src/services/cloud/relay-client.service.d.ts.map +1 -1
  56. package/dist/backend/backend/src/services/cloud/relay-client.service.js +14 -2
  57. package/dist/backend/backend/src/services/cloud/relay-client.service.js.map +1 -1
  58. package/dist/backend/backend/src/services/index.d.ts +2 -0
  59. package/dist/backend/backend/src/services/index.d.ts.map +1 -1
  60. package/dist/backend/backend/src/services/index.js +2 -0
  61. package/dist/backend/backend/src/services/index.js.map +1 -1
  62. package/dist/backend/backend/src/services/onboarding/brand-onboarding.service.d.ts +155 -0
  63. package/dist/backend/backend/src/services/onboarding/brand-onboarding.service.d.ts.map +1 -0
  64. package/dist/backend/backend/src/services/onboarding/brand-onboarding.service.js +469 -0
  65. package/dist/backend/backend/src/services/onboarding/brand-onboarding.service.js.map +1 -0
  66. package/dist/backend/backend/src/services/onboarding/brand-onboarding.types.d.ts +107 -0
  67. package/dist/backend/backend/src/services/onboarding/brand-onboarding.types.d.ts.map +1 -0
  68. package/dist/backend/backend/src/services/onboarding/brand-onboarding.types.js +104 -0
  69. package/dist/backend/backend/src/services/onboarding/brand-onboarding.types.js.map +1 -0
  70. package/dist/backend/backend/src/services/onboarding/content-approval.service.d.ts +124 -0
  71. package/dist/backend/backend/src/services/onboarding/content-approval.service.d.ts.map +1 -0
  72. package/dist/backend/backend/src/services/onboarding/content-approval.service.js +256 -0
  73. package/dist/backend/backend/src/services/onboarding/content-approval.service.js.map +1 -0
  74. package/dist/backend/backend/src/services/onboarding/content-approval.types.d.ts +80 -0
  75. package/dist/backend/backend/src/services/onboarding/content-approval.types.d.ts.map +1 -0
  76. package/dist/backend/backend/src/services/onboarding/content-approval.types.js +16 -0
  77. package/dist/backend/backend/src/services/onboarding/content-approval.types.js.map +1 -0
  78. package/dist/backend/backend/src/services/onboarding/index.d.ts +12 -0
  79. package/dist/backend/backend/src/services/onboarding/index.d.ts.map +1 -0
  80. package/dist/backend/backend/src/services/onboarding/index.js +10 -0
  81. package/dist/backend/backend/src/services/onboarding/index.js.map +1 -0
  82. package/dist/backend/backend/src/services/slack/cross-machine-message.service.d.ts +147 -0
  83. package/dist/backend/backend/src/services/slack/cross-machine-message.service.d.ts.map +1 -0
  84. package/dist/backend/backend/src/services/slack/cross-machine-message.service.js +306 -0
  85. package/dist/backend/backend/src/services/slack/cross-machine-message.service.js.map +1 -0
  86. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +7 -0
  87. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  88. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +76 -0
  89. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  90. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  91. package/dist/backend/backend/src/services/slack/slack.service.js +8 -2
  92. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  93. package/dist/backend/backend/src/types/cross-machine.types.d.ts +103 -0
  94. package/dist/backend/backend/src/types/cross-machine.types.d.ts.map +1 -0
  95. package/dist/backend/backend/src/types/cross-machine.types.js +47 -0
  96. package/dist/backend/backend/src/types/cross-machine.types.js.map +1 -0
  97. package/dist/cli/backend/src/constants.d.ts +9 -0
  98. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  99. package/dist/cli/backend/src/constants.js +9 -0
  100. package/dist/cli/backend/src/constants.js.map +1 -1
  101. package/dist/cli/cli/src/commands/cloud.d.ts +18 -2
  102. package/dist/cli/cli/src/commands/cloud.d.ts.map +1 -1
  103. package/dist/cli/cli/src/commands/cloud.js +72 -16
  104. package/dist/cli/cli/src/commands/cloud.js.map +1 -1
  105. package/package.json +1 -1
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Type definitions for the Content Approval workflow.
3
+ *
4
+ * Used by marketing team agents to submit content for human review
5
+ * via Slack. The approval flow is: draft → submitted → approved/rejected.
6
+ *
7
+ * @module content-approval-types
8
+ */
9
+ /** Approval status for a content item. */
10
+ export type ContentApprovalStatus = 'pending' | 'approved' | 'rejected' | 'expired';
11
+ /** A content item submitted for approval. */
12
+ export interface ContentApprovalRequest {
13
+ /** Unique approval request ID */
14
+ id: string;
15
+ /** Team ID this approval belongs to */
16
+ teamId: string;
17
+ /** Agent session that submitted the content */
18
+ submittedBy: string;
19
+ /** Platform the content is for */
20
+ platform: string;
21
+ /** Content type (post, article, newsletter, etc.) */
22
+ contentType: string;
23
+ /** The actual content text */
24
+ content: string;
25
+ /** Suggested hashtags */
26
+ hashtags?: string[];
27
+ /** Suggested visual direction */
28
+ visualDirection?: string;
29
+ /** Suggested posting time */
30
+ scheduledTime?: string;
31
+ /** Current approval status */
32
+ status: ContentApprovalStatus;
33
+ /** Submission timestamp */
34
+ submittedAt: string;
35
+ /** Resolution timestamp */
36
+ resolvedAt?: string;
37
+ /** Who resolved (user ID or 'auto') */
38
+ resolvedBy?: string;
39
+ /** Rejection reason or edit notes */
40
+ feedback?: string;
41
+ /** Slack message timestamp for the approval message */
42
+ slackMessageTs?: string;
43
+ /** Slack channel ID where approval was posted */
44
+ slackChannelId?: string;
45
+ }
46
+ /** Options for submitting content for approval. */
47
+ export interface SubmitForApprovalOptions {
48
+ /** Team ID */
49
+ teamId: string;
50
+ /** Agent session name */
51
+ submittedBy: string;
52
+ /** Target platform */
53
+ platform: string;
54
+ /** Content type */
55
+ contentType: string;
56
+ /** Content text */
57
+ content: string;
58
+ /** Optional hashtags */
59
+ hashtags?: string[];
60
+ /** Optional visual direction */
61
+ visualDirection?: string;
62
+ /** Optional scheduled time */
63
+ scheduledTime?: string;
64
+ }
65
+ /** Result of resolving an approval request. */
66
+ export interface ApprovalResolution {
67
+ /** Approval ID that was resolved */
68
+ approvalId: string;
69
+ /** New status */
70
+ status: 'approved' | 'rejected';
71
+ /** Who resolved */
72
+ resolvedBy: string;
73
+ /** Optional feedback/notes */
74
+ feedback?: string;
75
+ }
76
+ /** How long an approval request stays active before expiring (ms). */
77
+ export declare const CONTENT_APPROVAL_TTL_MS: number;
78
+ /** Maximum pending approvals per team. */
79
+ export declare const MAX_PENDING_APPROVALS = 50;
80
+ //# sourceMappingURL=content-approval.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-approval.types.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/onboarding/content-approval.types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,0CAA0C;AAC1C,MAAM,MAAM,qBAAqB,GAC7B,SAAS,GACT,UAAU,GACV,UAAU,GACV,SAAS,CAAC;AAEd,6CAA6C;AAC7C,MAAM,WAAW,sBAAsB;IACrC,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,uCAAuC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;IACpB,8BAA8B;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,iCAAiC;IACjC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6BAA6B;IAC7B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,MAAM,EAAE,qBAAqB,CAAC;IAC9B,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,mDAAmD;AACnD,MAAM,WAAW,wBAAwB;IACvC,cAAc;IACd,MAAM,EAAE,MAAM,CAAC;IACf,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,sBAAsB;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,mBAAmB;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,wBAAwB;IACxB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,gCAAgC;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8BAA8B;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB;IACjB,MAAM,EAAE,UAAU,GAAG,UAAU,CAAC;IAChC,mBAAmB;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,QAAsB,CAAC;AAE3D,0CAA0C;AAC1C,eAAO,MAAM,qBAAqB,KAAK,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Type definitions for the Content Approval workflow.
3
+ *
4
+ * Used by marketing team agents to submit content for human review
5
+ * via Slack. The approval flow is: draft → submitted → approved/rejected.
6
+ *
7
+ * @module content-approval-types
8
+ */
9
+ // =============================================================================
10
+ // Constants
11
+ // =============================================================================
12
+ /** How long an approval request stays active before expiring (ms). */
13
+ export const CONTENT_APPROVAL_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
14
+ /** Maximum pending approvals per team. */
15
+ export const MAX_PENDING_APPROVALS = 50;
16
+ //# sourceMappingURL=content-approval.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-approval.types.js","sourceRoot":"","sources":["../../../../../../backend/src/services/onboarding/content-approval.types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAiFH,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF,sEAAsE;AACtE,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;AAEvE,0CAA0C;AAC1C,MAAM,CAAC,MAAM,qBAAqB,GAAG,EAAE,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Onboarding service exports.
3
+ *
4
+ * @module onboarding
5
+ */
6
+ export { BrandOnboardingService } from './brand-onboarding.service.js';
7
+ export { ONBOARDING_QUESTIONS, DEFAULT_CONTENT_MIX, } from './brand-onboarding.types.js';
8
+ export type { OnboardingQuestion, OnboardingAnswer, OnboardingSession, OnboardingStatus, BrandProfile, GenerateGuideOptions, } from './brand-onboarding.types.js';
9
+ export { ContentApprovalService } from './content-approval.service.js';
10
+ export { CONTENT_APPROVAL_TTL_MS, MAX_PENDING_APPROVALS, } from './content-approval.types.js';
11
+ export type { ContentApprovalRequest, ContentApprovalStatus, SubmitForApprovalOptions, ApprovalResolution, } from './content-approval.types.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/onboarding/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,sBAAsB,EACtB,qBAAqB,EACrB,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Onboarding service exports.
3
+ *
4
+ * @module onboarding
5
+ */
6
+ export { BrandOnboardingService } from './brand-onboarding.service.js';
7
+ export { ONBOARDING_QUESTIONS, DEFAULT_CONTENT_MIX, } from './brand-onboarding.types.js';
8
+ export { ContentApprovalService } from './content-approval.service.js';
9
+ export { CONTENT_APPROVAL_TTL_MS, MAX_PENDING_APPROVALS, } from './content-approval.types.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../backend/src/services/onboarding/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EACL,oBAAoB,EACpB,mBAAmB,GACpB,MAAM,6BAA6B,CAAC;AAUrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAC;AACvE,OAAO,EACL,uBAAuB,EACvB,qBAAqB,GACtB,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Cross-Machine Message Service
3
+ *
4
+ * Enables Crewly instances on different machines to communicate
5
+ * through a shared Slack channel. Uses Slack as the transport layer,
6
+ * replacing the Cloud Relay WebSocket approach with a simpler HTTP-based
7
+ * mechanism that leverages Slack's built-in auth, delivery, and persistence.
8
+ *
9
+ * @module services/slack/cross-machine-message
10
+ */
11
+ import { EventEmitter } from 'events';
12
+ import { type SlackService } from './slack.service.js';
13
+ import { DeviceIdentityService, type DeviceIdentity } from '../cloud/device-identity.service.js';
14
+ import type { SlackIncomingMessage } from '../../types/slack.types.js';
15
+ import { type CrossMachineMessage, type CrossMachineMessageType, type CrossMachineConfig, type CrossMachineSendResult } from '../../types/cross-machine.types.js';
16
+ /**
17
+ * Events emitted by CrossMachineMessageService.
18
+ */
19
+ export interface CrossMachineEvents {
20
+ /** Fired when a cross-machine message addressed to this machine is received */
21
+ message: (message: CrossMachineMessage) => void;
22
+ /** Fired when a broadcast message is received */
23
+ broadcast: (message: CrossMachineMessage) => void;
24
+ /** Fired on errors */
25
+ error: (error: Error) => void;
26
+ }
27
+ /**
28
+ * CrossMachineMessageService
29
+ *
30
+ * Singleton service managing cross-machine communication via Slack.
31
+ * On send: serializes a CrossMachineMessage with a recognizable prefix
32
+ * and posts it to the configured Slack channel.
33
+ * On receive: the SlackOrchestratorBridge detects the prefix and calls
34
+ * handleIncomingMessage(), which filters by target and emits events.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const service = getCrossMachineMessageService();
39
+ * await service.initialize();
40
+ *
41
+ * // Send a task to another machine
42
+ * await service.sendMessage('device-uuid-of-remote', 'delegate-task', {
43
+ * task: 'Run tests on feature branch',
44
+ * priority: 'high',
45
+ * });
46
+ *
47
+ * // Listen for incoming messages
48
+ * service.on('message', (msg) => {
49
+ * console.log(`Received ${msg.type} from ${msg.fromName}`);
50
+ * });
51
+ * ```
52
+ */
53
+ export declare class CrossMachineMessageService extends EventEmitter {
54
+ private readonly logger;
55
+ private slackService;
56
+ private deviceIdentity;
57
+ private config;
58
+ private identity;
59
+ private initialized;
60
+ /** Track processed message IDs to prevent duplicate handling */
61
+ private processedMessageIds;
62
+ /** Maximum number of tracked message IDs before pruning */
63
+ private readonly maxTrackedMessages;
64
+ /**
65
+ * Create a new CrossMachineMessageService.
66
+ *
67
+ * @param slackService - Optional SlackService override (for testing)
68
+ * @param deviceIdentity - Optional DeviceIdentityService override (for testing)
69
+ */
70
+ constructor(slackService?: SlackService, deviceIdentity?: DeviceIdentityService);
71
+ /**
72
+ * Initialize the service.
73
+ * Loads device identity and cross-machine config from disk.
74
+ *
75
+ * @returns Promise that resolves when initialized
76
+ */
77
+ initialize(): Promise<void>;
78
+ /**
79
+ * Check if the service is initialized and enabled.
80
+ *
81
+ * @returns True if ready to send/receive messages
82
+ */
83
+ isEnabled(): boolean;
84
+ /**
85
+ * Get the current configuration.
86
+ *
87
+ * @returns Cross-machine config or null
88
+ */
89
+ getConfig(): CrossMachineConfig | null;
90
+ /**
91
+ * Get the local device identity.
92
+ *
93
+ * @returns Device identity or null if not initialized
94
+ */
95
+ getIdentity(): DeviceIdentity | null;
96
+ /**
97
+ * Configure cross-machine messaging.
98
+ * Persists the config to ~/.crewly/cross-machine.json.
99
+ *
100
+ * @param config - Configuration with Slack channel ID
101
+ * @returns Promise that resolves when saved
102
+ */
103
+ configure(config: CrossMachineConfig): Promise<void>;
104
+ /**
105
+ * Send a cross-machine message via Slack.
106
+ *
107
+ * @param targetDeviceId - Target machine's device ID (or "*" for broadcast)
108
+ * @param type - Message type
109
+ * @param payload - Message payload
110
+ * @returns Send result with success status
111
+ */
112
+ sendMessage(targetDeviceId: string, type: CrossMachineMessageType, payload?: Record<string, unknown>): Promise<CrossMachineSendResult>;
113
+ /**
114
+ * Handle an incoming Slack message that has been identified as a
115
+ * cross-machine message by the SlackOrchestratorBridge.
116
+ *
117
+ * Checks if the message is addressed to this machine, deduplicates,
118
+ * and emits appropriate events.
119
+ *
120
+ * @param slackMessage - The raw Slack incoming message
121
+ * @returns True if the message was handled (addressed to us), false if ignored
122
+ */
123
+ handleIncomingMessage(slackMessage: SlackIncomingMessage): boolean;
124
+ /**
125
+ * Load cross-machine config from disk.
126
+ *
127
+ * @returns Config or null if not configured
128
+ */
129
+ private loadConfig;
130
+ /**
131
+ * Save cross-machine config to disk.
132
+ *
133
+ * @param config - Configuration to persist
134
+ */
135
+ private saveConfig;
136
+ /**
137
+ * Reset the singleton instance (for testing).
138
+ */
139
+ static resetInstance(): void;
140
+ }
141
+ /**
142
+ * Get the singleton CrossMachineMessageService instance.
143
+ *
144
+ * @returns The service instance
145
+ */
146
+ export declare function getCrossMachineMessageService(): CrossMachineMessageService;
147
+ //# sourceMappingURL=cross-machine-message.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-machine-message.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/cross-machine-message.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAMtC,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,KAAK,cAAc,EAAE,MAAM,qCAAqC,CAAC;AACjG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACvE,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAG5B,MAAM,oCAAoC,CAAC;AAI5C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,+EAA+E;IAC/E,OAAO,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAChD,iDAAiD;IACjD,SAAS,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAClD,sBAAsB;IACtB,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAC/B;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,qBAAa,0BAA2B,SAAQ,YAAY;IAC1D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,YAAY,CAAe;IACnC,OAAO,CAAC,cAAc,CAAwB;IAC9C,OAAO,CAAC,MAAM,CAAmC;IACjD,OAAO,CAAC,QAAQ,CAA+B;IAC/C,OAAO,CAAC,WAAW,CAAS;IAE5B,gEAAgE;IAChE,OAAO,CAAC,mBAAmB,CAAqB;IAChD,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAE5C;;;;;OAKG;gBACS,YAAY,CAAC,EAAE,YAAY,EAAE,cAAc,CAAC,EAAE,qBAAqB;IAQ/E;;;;;OAKG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAejC;;;;OAIG;IACH,SAAS,IAAI,OAAO;IAIpB;;;;OAIG;IACH,SAAS,IAAI,kBAAkB,GAAG,IAAI;IAItC;;;;OAIG;IACH,WAAW,IAAI,cAAc,GAAG,IAAI;IAIpC;;;;;;OAMG;IACG,SAAS,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1D;;;;;;;OAOG;IACG,WAAW,CACf,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,uBAAuB,EAC7B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACpC,OAAO,CAAC,sBAAsB,CAAC;IAgDlC;;;;;;;;;OASG;IACH,qBAAqB,CAAC,YAAY,EAAE,oBAAoB,GAAG,OAAO;IAqElE;;;;OAIG;YACW,UAAU;IAexB;;;;OAIG;YACW,UAAU;IAgBxB;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;CAG7B;AAED;;;;GAIG;AACH,wBAAgB,6BAA6B,IAAI,0BAA0B,CAK1E"}
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Cross-Machine Message Service
3
+ *
4
+ * Enables Crewly instances on different machines to communicate
5
+ * through a shared Slack channel. Uses Slack as the transport layer,
6
+ * replacing the Cloud Relay WebSocket approach with a simpler HTTP-based
7
+ * mechanism that leverages Slack's built-in auth, delivery, and persistence.
8
+ *
9
+ * @module services/slack/cross-machine-message
10
+ */
11
+ import { EventEmitter } from 'events';
12
+ import { v4 as uuidv4 } from 'uuid';
13
+ import { readFile, writeFile, mkdir } from 'fs/promises';
14
+ import { existsSync } from 'fs';
15
+ import { join } from 'path';
16
+ import { homedir } from 'os';
17
+ import { getSlackService } from './slack.service.js';
18
+ import { DeviceIdentityService } from '../cloud/device-identity.service.js';
19
+ import { parseCrossMachineMessage, serializeCrossMachineMessage, } from '../../types/cross-machine.types.js';
20
+ import { CROSS_MACHINE_CONSTANTS } from '../../constants.js';
21
+ import { LoggerService } from '../core/logger.service.js';
22
+ /** Config file path relative to ~/.crewly/ */
23
+ const CONFIG_FILE = 'cross-machine.json';
24
+ /** Singleton instance */
25
+ let serviceInstance = null;
26
+ /**
27
+ * CrossMachineMessageService
28
+ *
29
+ * Singleton service managing cross-machine communication via Slack.
30
+ * On send: serializes a CrossMachineMessage with a recognizable prefix
31
+ * and posts it to the configured Slack channel.
32
+ * On receive: the SlackOrchestratorBridge detects the prefix and calls
33
+ * handleIncomingMessage(), which filters by target and emits events.
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * const service = getCrossMachineMessageService();
38
+ * await service.initialize();
39
+ *
40
+ * // Send a task to another machine
41
+ * await service.sendMessage('device-uuid-of-remote', 'delegate-task', {
42
+ * task: 'Run tests on feature branch',
43
+ * priority: 'high',
44
+ * });
45
+ *
46
+ * // Listen for incoming messages
47
+ * service.on('message', (msg) => {
48
+ * console.log(`Received ${msg.type} from ${msg.fromName}`);
49
+ * });
50
+ * ```
51
+ */
52
+ export class CrossMachineMessageService extends EventEmitter {
53
+ logger;
54
+ slackService;
55
+ deviceIdentity;
56
+ config = null;
57
+ identity = null;
58
+ initialized = false;
59
+ /** Track processed message IDs to prevent duplicate handling */
60
+ processedMessageIds = new Set();
61
+ /** Maximum number of tracked message IDs before pruning */
62
+ maxTrackedMessages;
63
+ /**
64
+ * Create a new CrossMachineMessageService.
65
+ *
66
+ * @param slackService - Optional SlackService override (for testing)
67
+ * @param deviceIdentity - Optional DeviceIdentityService override (for testing)
68
+ */
69
+ constructor(slackService, deviceIdentity) {
70
+ super();
71
+ this.logger = LoggerService.getInstance().createComponentLogger('CrossMachineMsg');
72
+ this.slackService = slackService || getSlackService();
73
+ this.deviceIdentity = deviceIdentity || DeviceIdentityService.getInstance();
74
+ this.maxTrackedMessages = CROSS_MACHINE_CONSTANTS.MAX_TRACKED_MESSAGE_IDS;
75
+ }
76
+ /**
77
+ * Initialize the service.
78
+ * Loads device identity and cross-machine config from disk.
79
+ *
80
+ * @returns Promise that resolves when initialized
81
+ */
82
+ async initialize() {
83
+ if (this.initialized)
84
+ return;
85
+ this.identity = await this.deviceIdentity.getOrCreateIdentity();
86
+ this.config = await this.loadConfig();
87
+ this.initialized = true;
88
+ this.logger.info('Initialized', {
89
+ deviceId: this.identity.deviceId,
90
+ deviceName: this.identity.deviceName,
91
+ enabled: this.config?.enabled ?? false,
92
+ channelId: this.config?.channelId ?? 'not configured',
93
+ });
94
+ }
95
+ /**
96
+ * Check if the service is initialized and enabled.
97
+ *
98
+ * @returns True if ready to send/receive messages
99
+ */
100
+ isEnabled() {
101
+ return this.initialized && !!this.config?.enabled && !!this.config?.channelId;
102
+ }
103
+ /**
104
+ * Get the current configuration.
105
+ *
106
+ * @returns Cross-machine config or null
107
+ */
108
+ getConfig() {
109
+ return this.config ? { ...this.config } : null;
110
+ }
111
+ /**
112
+ * Get the local device identity.
113
+ *
114
+ * @returns Device identity or null if not initialized
115
+ */
116
+ getIdentity() {
117
+ return this.identity ? { ...this.identity } : null;
118
+ }
119
+ /**
120
+ * Configure cross-machine messaging.
121
+ * Persists the config to ~/.crewly/cross-machine.json.
122
+ *
123
+ * @param config - Configuration with Slack channel ID
124
+ * @returns Promise that resolves when saved
125
+ */
126
+ async configure(config) {
127
+ this.config = config;
128
+ await this.saveConfig(config);
129
+ this.logger.info('Configuration updated', { enabled: config.enabled, channelId: config.channelId });
130
+ }
131
+ /**
132
+ * Send a cross-machine message via Slack.
133
+ *
134
+ * @param targetDeviceId - Target machine's device ID (or "*" for broadcast)
135
+ * @param type - Message type
136
+ * @param payload - Message payload
137
+ * @returns Send result with success status
138
+ */
139
+ async sendMessage(targetDeviceId, type, payload = {}) {
140
+ if (!this.isEnabled()) {
141
+ return { success: false, error: 'Cross-machine messaging is not enabled or configured' };
142
+ }
143
+ if (!this.identity) {
144
+ return { success: false, error: 'Device identity not initialized' };
145
+ }
146
+ if (!this.slackService.isConnected()) {
147
+ return { success: false, error: 'Slack is not connected' };
148
+ }
149
+ const message = {
150
+ protocol: 'crewly-x-machine',
151
+ version: 1,
152
+ from: this.identity.deviceId,
153
+ fromName: this.identity.deviceName,
154
+ to: targetDeviceId,
155
+ type,
156
+ payload,
157
+ timestamp: new Date().toISOString(),
158
+ messageId: uuidv4(),
159
+ };
160
+ const serialized = serializeCrossMachineMessage(message);
161
+ try {
162
+ const ts = await this.slackService.sendMessage({
163
+ channelId: this.config.channelId,
164
+ text: serialized,
165
+ });
166
+ this.logger.info('Sent cross-machine message', {
167
+ to: targetDeviceId,
168
+ type,
169
+ messageId: message.messageId,
170
+ slackTs: ts,
171
+ });
172
+ return { success: true, slackTs: ts };
173
+ }
174
+ catch (error) {
175
+ const errorMsg = error instanceof Error ? error.message : String(error);
176
+ this.logger.error('Failed to send cross-machine message', { error: errorMsg, to: targetDeviceId, type });
177
+ return { success: false, error: errorMsg };
178
+ }
179
+ }
180
+ /**
181
+ * Handle an incoming Slack message that has been identified as a
182
+ * cross-machine message by the SlackOrchestratorBridge.
183
+ *
184
+ * Checks if the message is addressed to this machine, deduplicates,
185
+ * and emits appropriate events.
186
+ *
187
+ * @param slackMessage - The raw Slack incoming message
188
+ * @returns True if the message was handled (addressed to us), false if ignored
189
+ */
190
+ handleIncomingMessage(slackMessage) {
191
+ const parsed = parseCrossMachineMessage(slackMessage.text);
192
+ if (!parsed) {
193
+ return false;
194
+ }
195
+ // Ignore messages from ourselves
196
+ if (this.identity && parsed.from === this.identity.deviceId) {
197
+ this.logger.debug('Ignoring own message', { messageId: parsed.messageId });
198
+ return true; // Handled (by ignoring)
199
+ }
200
+ // Deduplicate
201
+ if (this.processedMessageIds.has(parsed.messageId)) {
202
+ this.logger.debug('Ignoring duplicate message', { messageId: parsed.messageId });
203
+ return true;
204
+ }
205
+ // Track message ID
206
+ this.processedMessageIds.add(parsed.messageId);
207
+ if (this.processedMessageIds.size > this.maxTrackedMessages) {
208
+ // Prune oldest entries (Set preserves insertion order)
209
+ const iterator = this.processedMessageIds.values();
210
+ const halfSize = Math.floor(this.maxTrackedMessages / 2);
211
+ for (let i = 0; i < halfSize; i++) {
212
+ const val = iterator.next().value;
213
+ if (val !== undefined) {
214
+ this.processedMessageIds.delete(val);
215
+ }
216
+ }
217
+ }
218
+ // Check if addressed to us or broadcast
219
+ const isForUs = this.identity && (parsed.to === this.identity.deviceId ||
220
+ parsed.to === '*');
221
+ if (!isForUs) {
222
+ this.logger.debug('Ignoring message addressed to another machine', {
223
+ to: parsed.to,
224
+ ourId: this.identity?.deviceId,
225
+ });
226
+ return true; // Handled (by ignoring — not for us)
227
+ }
228
+ this.logger.info('Received cross-machine message', {
229
+ from: parsed.fromName,
230
+ fromId: parsed.from,
231
+ type: parsed.type,
232
+ messageId: parsed.messageId,
233
+ });
234
+ // Handle ping/pong automatically
235
+ if (parsed.type === 'ping') {
236
+ this.sendMessage(parsed.from, 'pong', { inResponseTo: parsed.messageId }).catch(err => {
237
+ this.logger.warn('Failed to send pong', { error: err instanceof Error ? err.message : String(err) });
238
+ });
239
+ }
240
+ // Emit events
241
+ if (parsed.to === '*') {
242
+ this.emit('broadcast', parsed);
243
+ }
244
+ this.emit('message', parsed);
245
+ return true;
246
+ }
247
+ /**
248
+ * Load cross-machine config from disk.
249
+ *
250
+ * @returns Config or null if not configured
251
+ */
252
+ async loadConfig() {
253
+ const configPath = join(homedir(), '.crewly', CONFIG_FILE);
254
+ try {
255
+ if (existsSync(configPath)) {
256
+ const content = await readFile(configPath, 'utf-8');
257
+ return JSON.parse(content);
258
+ }
259
+ }
260
+ catch (error) {
261
+ this.logger.warn('Failed to load cross-machine config', {
262
+ error: error instanceof Error ? error.message : String(error),
263
+ });
264
+ }
265
+ return null;
266
+ }
267
+ /**
268
+ * Save cross-machine config to disk.
269
+ *
270
+ * @param config - Configuration to persist
271
+ */
272
+ async saveConfig(config) {
273
+ const crewlyHome = join(homedir(), '.crewly');
274
+ const configPath = join(crewlyHome, CONFIG_FILE);
275
+ try {
276
+ if (!existsSync(crewlyHome)) {
277
+ await mkdir(crewlyHome, { recursive: true });
278
+ }
279
+ await writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
280
+ }
281
+ catch (error) {
282
+ this.logger.error('Failed to save cross-machine config', {
283
+ error: error instanceof Error ? error.message : String(error),
284
+ });
285
+ throw error;
286
+ }
287
+ }
288
+ /**
289
+ * Reset the singleton instance (for testing).
290
+ */
291
+ static resetInstance() {
292
+ serviceInstance = null;
293
+ }
294
+ }
295
+ /**
296
+ * Get the singleton CrossMachineMessageService instance.
297
+ *
298
+ * @returns The service instance
299
+ */
300
+ export function getCrossMachineMessageService() {
301
+ if (!serviceInstance) {
302
+ serviceInstance = new CrossMachineMessageService();
303
+ }
304
+ return serviceInstance;
305
+ }
306
+ //# sourceMappingURL=cross-machine-message.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cross-machine-message.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/cross-machine-message.service.ts"],"names":[],"mappings":"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"}
@@ -111,6 +111,13 @@ export declare class SlackOrchestratorBridge extends EventEmitter {
111
111
  * @param message - Incoming Slack message
112
112
  */
113
113
  private handleSlackMessage;
114
+ /**
115
+ * Handle an incoming cross-machine message.
116
+ * Routes the message payload to the local orchestrator via the message queue.
117
+ *
118
+ * @param msg - Parsed cross-machine message
119
+ */
120
+ private handleCrossMachineMessage;
114
121
  /**
115
122
  * Parse command from message text
116
123
  *
@@ -1 +1 @@
1
- {"version":3,"file":"slack-orchestrator-bridge.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/slack-orchestrator-bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slack-orchestrator-bridge.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/slack-orchestrator-bridge.ts"],"names":[],"mappings":"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"}