@dp-pcs/ogp 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +437 -0
  2. package/dist/cli/agent-comms.d.ts +55 -0
  3. package/dist/cli/agent-comms.d.ts.map +1 -0
  4. package/dist/cli/agent-comms.js +217 -0
  5. package/dist/cli/agent-comms.js.map +1 -0
  6. package/dist/cli/expose.d.ts +3 -0
  7. package/dist/cli/expose.d.ts.map +1 -0
  8. package/dist/cli/expose.js +104 -0
  9. package/dist/cli/expose.js.map +1 -0
  10. package/dist/cli/federation.d.ts +28 -0
  11. package/dist/cli/federation.d.ts.map +1 -0
  12. package/dist/cli/federation.js +409 -0
  13. package/dist/cli/federation.js.map +1 -0
  14. package/dist/cli/install.d.ts +3 -0
  15. package/dist/cli/install.d.ts.map +1 -0
  16. package/dist/cli/install.js +111 -0
  17. package/dist/cli/install.js.map +1 -0
  18. package/dist/cli/setup.d.ts +2 -0
  19. package/dist/cli/setup.d.ts.map +1 -0
  20. package/dist/cli/setup.js +33 -0
  21. package/dist/cli/setup.js.map +1 -0
  22. package/dist/cli.d.ts +3 -0
  23. package/dist/cli.d.ts.map +1 -0
  24. package/dist/cli.js +305 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/daemon/agent-comms.d.ts +76 -0
  27. package/dist/daemon/agent-comms.d.ts.map +1 -0
  28. package/dist/daemon/agent-comms.js +188 -0
  29. package/dist/daemon/agent-comms.js.map +1 -0
  30. package/dist/daemon/doorman.d.ts +52 -0
  31. package/dist/daemon/doorman.d.ts.map +1 -0
  32. package/dist/daemon/doorman.js +203 -0
  33. package/dist/daemon/doorman.js.map +1 -0
  34. package/dist/daemon/intent-registry.d.ts +11 -0
  35. package/dist/daemon/intent-registry.d.ts.map +1 -0
  36. package/dist/daemon/intent-registry.js +101 -0
  37. package/dist/daemon/intent-registry.js.map +1 -0
  38. package/dist/daemon/keypair.d.ts +5 -0
  39. package/dist/daemon/keypair.d.ts.map +1 -0
  40. package/dist/daemon/keypair.js +25 -0
  41. package/dist/daemon/keypair.js.map +1 -0
  42. package/dist/daemon/message-handler.d.ts +20 -0
  43. package/dist/daemon/message-handler.d.ts.map +1 -0
  44. package/dist/daemon/message-handler.js +159 -0
  45. package/dist/daemon/message-handler.js.map +1 -0
  46. package/dist/daemon/notify.d.ts +7 -0
  47. package/dist/daemon/notify.d.ts.map +1 -0
  48. package/dist/daemon/notify.js +54 -0
  49. package/dist/daemon/notify.js.map +1 -0
  50. package/dist/daemon/peers.d.ts +66 -0
  51. package/dist/daemon/peers.d.ts.map +1 -0
  52. package/dist/daemon/peers.js +171 -0
  53. package/dist/daemon/peers.js.map +1 -0
  54. package/dist/daemon/reply-handler.d.ts +67 -0
  55. package/dist/daemon/reply-handler.d.ts.map +1 -0
  56. package/dist/daemon/reply-handler.js +176 -0
  57. package/dist/daemon/reply-handler.js.map +1 -0
  58. package/dist/daemon/scopes.d.ts +62 -0
  59. package/dist/daemon/scopes.d.ts.map +1 -0
  60. package/dist/daemon/scopes.js +113 -0
  61. package/dist/daemon/scopes.js.map +1 -0
  62. package/dist/daemon/server.d.ts +8 -0
  63. package/dist/daemon/server.d.ts.map +1 -0
  64. package/dist/daemon/server.js +286 -0
  65. package/dist/daemon/server.js.map +1 -0
  66. package/dist/shared/config.d.ts +42 -0
  67. package/dist/shared/config.d.ts.map +1 -0
  68. package/dist/shared/config.js +42 -0
  69. package/dist/shared/config.js.map +1 -0
  70. package/dist/shared/signing.d.ts +13 -0
  71. package/dist/shared/signing.d.ts.map +1 -0
  72. package/dist/shared/signing.js +46 -0
  73. package/dist/shared/signing.js.map +1 -0
  74. package/docs/agent-comms.md +277 -0
  75. package/docs/federation-flow.md +407 -0
  76. package/docs/quickstart.md +241 -0
  77. package/docs/scopes.md +198 -0
  78. package/package.json +57 -0
  79. package/scripts/install-skills.js +32 -0
  80. package/skills/ogp/SKILL.md +235 -0
  81. package/skills/ogp-agent-comms/SKILL.md +345 -0
  82. package/skills/ogp-expose/SKILL.md +281 -0
@@ -0,0 +1,203 @@
1
+ /**
2
+ * OGP Doorman - Runtime scope enforcement and rate limiting
3
+ *
4
+ * The doorman sits at Layer 3 of the scope model:
5
+ * Layer 1: Gateway Capabilities - What I CAN support
6
+ * Layer 2: Peer Negotiation - What I WILL grant YOU
7
+ * Layer 3: Runtime Enforcement - Is THIS request within YOUR granted scope (doorman)
8
+ */
9
+ import { getPeer } from './peers.js';
10
+ import { DEFAULT_V1_SCOPES, DEFAULT_RATE_LIMIT, findScopeGrant, scopeCoversIntent } from './scopes.js';
11
+ // In-memory rate limit tracking
12
+ // Key format: "peerId:intent"
13
+ const rateLimitStore = new Map();
14
+ // Cleanup interval (5 minutes)
15
+ const CLEANUP_INTERVAL_MS = 5 * 60 * 1000;
16
+ let cleanupTimer = null;
17
+ /**
18
+ * Start the periodic cleanup of expired rate limit entries
19
+ */
20
+ export function startDoormanCleanup() {
21
+ if (cleanupTimer)
22
+ return;
23
+ cleanupTimer = setInterval(cleanupExpiredEntries, CLEANUP_INTERVAL_MS);
24
+ }
25
+ /**
26
+ * Stop the periodic cleanup
27
+ */
28
+ export function stopDoormanCleanup() {
29
+ if (cleanupTimer) {
30
+ clearInterval(cleanupTimer);
31
+ cleanupTimer = null;
32
+ }
33
+ }
34
+ /**
35
+ * Clean up expired rate limit entries
36
+ */
37
+ function cleanupExpiredEntries() {
38
+ const now = Date.now();
39
+ for (const [key, entry] of rateLimitStore.entries()) {
40
+ // Remove entries with no recent activity (> 1 hour old)
41
+ if (now - entry.windowStart > 3600 * 1000) {
42
+ rateLimitStore.delete(key);
43
+ }
44
+ }
45
+ }
46
+ /**
47
+ * Check if a request from a peer is allowed
48
+ *
49
+ * @param peerId - The peer making the request
50
+ * @param intent - The intent being requested
51
+ * @param payload - Optional payload with topic for agent-comms
52
+ * @returns DoormanResult indicating if request is allowed
53
+ */
54
+ export function checkAccess(peerId, intent, payload) {
55
+ // 1. Get peer and verify approved
56
+ const peer = getPeer(peerId);
57
+ if (!peer) {
58
+ return {
59
+ allowed: false,
60
+ reason: 'Unknown peer',
61
+ statusCode: 403
62
+ };
63
+ }
64
+ if (peer.status !== 'approved') {
65
+ return {
66
+ allowed: false,
67
+ reason: 'Peer not approved',
68
+ statusCode: 403
69
+ };
70
+ }
71
+ // 2. Determine scope bundle to use
72
+ // Priority: grantedScopes takes precedence over protocolVersion
73
+ let scopeBundle;
74
+ let isV1Peer = false;
75
+ if (peer.grantedScopes) {
76
+ // Use negotiated scopes if they exist
77
+ scopeBundle = peer.grantedScopes;
78
+ isV1Peer = !peer.protocolVersion || peer.protocolVersion === '0.1.0';
79
+ }
80
+ else {
81
+ // No scope negotiation done - fall back to v0.1 defaults
82
+ isV1Peer = true;
83
+ scopeBundle = DEFAULT_V1_SCOPES;
84
+ }
85
+ // 3. Find scope grant for this intent
86
+ const grant = findScopeGrant(scopeBundle, intent);
87
+ if (!grant) {
88
+ return {
89
+ allowed: false,
90
+ reason: `Intent '${intent}' not in granted scope`,
91
+ statusCode: 403,
92
+ isV1Peer
93
+ };
94
+ }
95
+ // 4. Check if scope covers this specific request (including topic)
96
+ const topic = payload?.topic;
97
+ if (!scopeCoversIntent(grant, intent, topic)) {
98
+ if (topic && grant.topics && grant.topics.length > 0) {
99
+ return {
100
+ allowed: false,
101
+ reason: `Topic '${topic}' not allowed for intent '${intent}'`,
102
+ statusCode: 403,
103
+ isV1Peer
104
+ };
105
+ }
106
+ return {
107
+ allowed: false,
108
+ reason: `Intent '${intent}' scope check failed`,
109
+ statusCode: 403,
110
+ isV1Peer
111
+ };
112
+ }
113
+ // 5. Check rate limit
114
+ const rateLimit = grant.rateLimit || DEFAULT_RATE_LIMIT;
115
+ const rateLimitResult = checkRateLimit(peerId, intent, rateLimit);
116
+ if (!rateLimitResult.allowed) {
117
+ return {
118
+ allowed: false,
119
+ reason: `Rate limit exceeded for intent '${intent}'`,
120
+ statusCode: 429,
121
+ retryAfter: rateLimitResult.retryAfter,
122
+ isV1Peer
123
+ };
124
+ }
125
+ // 6. All checks passed
126
+ return {
127
+ allowed: true,
128
+ isV1Peer
129
+ };
130
+ }
131
+ /**
132
+ * Check and update rate limit for a peer+intent combination
133
+ */
134
+ function checkRateLimit(peerId, intent, limit) {
135
+ const key = `${peerId}:${intent}`;
136
+ const now = Date.now();
137
+ const windowMs = limit.windowSeconds * 1000;
138
+ let entry = rateLimitStore.get(key);
139
+ if (!entry) {
140
+ // First request - create entry
141
+ entry = {
142
+ timestamps: [now],
143
+ windowStart: now
144
+ };
145
+ rateLimitStore.set(key, entry);
146
+ return { allowed: true };
147
+ }
148
+ // Filter out timestamps outside the sliding window
149
+ const windowStart = now - windowMs;
150
+ entry.timestamps = entry.timestamps.filter(ts => ts > windowStart);
151
+ entry.windowStart = windowStart;
152
+ // Check if we're at the limit
153
+ if (entry.timestamps.length >= limit.requests) {
154
+ // Calculate when the oldest request will expire
155
+ const oldestInWindow = Math.min(...entry.timestamps);
156
+ const retryAfter = Math.ceil((oldestInWindow + windowMs - now) / 1000);
157
+ return {
158
+ allowed: false,
159
+ retryAfter: Math.max(1, retryAfter)
160
+ };
161
+ }
162
+ // Record this request
163
+ entry.timestamps.push(now);
164
+ return { allowed: true };
165
+ }
166
+ /**
167
+ * Get current rate limit status for a peer+intent
168
+ */
169
+ export function getRateLimitStatus(peerId, intent, limit) {
170
+ const key = `${peerId}:${intent}`;
171
+ const now = Date.now();
172
+ const windowMs = limit.windowSeconds * 1000;
173
+ const entry = rateLimitStore.get(key);
174
+ if (!entry) {
175
+ return {
176
+ used: 0,
177
+ remaining: limit.requests,
178
+ windowSeconds: limit.windowSeconds
179
+ };
180
+ }
181
+ // Filter to current window
182
+ const windowStart = now - windowMs;
183
+ const recentTimestamps = entry.timestamps.filter(ts => ts > windowStart);
184
+ return {
185
+ used: recentTimestamps.length,
186
+ remaining: Math.max(0, limit.requests - recentTimestamps.length),
187
+ windowSeconds: limit.windowSeconds
188
+ };
189
+ }
190
+ /**
191
+ * Reset rate limit for a specific peer+intent (for testing)
192
+ */
193
+ export function resetRateLimit(peerId, intent) {
194
+ const key = `${peerId}:${intent}`;
195
+ rateLimitStore.delete(key);
196
+ }
197
+ /**
198
+ * Reset all rate limits (for testing)
199
+ */
200
+ export function resetAllRateLimits() {
201
+ rateLimitStore.clear();
202
+ }
203
+ //# sourceMappingURL=doorman.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doorman.js","sourceRoot":"","sources":["../../src/daemon/doorman.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface Intent {
2
+ name: string;
3
+ description: string;
4
+ schema?: Record<string, any>;
5
+ handler?: string;
6
+ }
7
+ export declare function loadIntents(): Intent[];
8
+ export declare function saveIntents(intents: Intent[]): void;
9
+ export declare function registerIntent(intent: Intent): void;
10
+ export declare function getIntent(name: string): Intent | null;
11
+ //# sourceMappingURL=intent-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-registry.d.ts","sourceRoot":"","sources":["../../src/daemon/intent-registry.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA0DD,wBAAgB,WAAW,IAAI,MAAM,EAAE,CA2BtC;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAGnD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CASnD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGrD"}
@@ -0,0 +1,101 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { getConfigDir, ensureConfigDir } from '../shared/config.js';
4
+ const INTENTS_FILE = path.join(getConfigDir(), 'intents.json');
5
+ const DEFAULT_INTENTS = [
6
+ {
7
+ name: 'message',
8
+ description: 'Simple text message',
9
+ schema: {
10
+ type: 'object',
11
+ properties: {
12
+ text: { type: 'string' }
13
+ },
14
+ required: ['text']
15
+ }
16
+ },
17
+ {
18
+ name: 'task-request',
19
+ description: 'Request a peer to perform a task',
20
+ schema: {
21
+ type: 'object',
22
+ properties: {
23
+ taskType: { type: 'string' },
24
+ description: { type: 'string' },
25
+ parameters: { type: 'object' }
26
+ },
27
+ required: ['taskType', 'description']
28
+ }
29
+ },
30
+ {
31
+ name: 'status-update',
32
+ description: 'Status update from a peer',
33
+ schema: {
34
+ type: 'object',
35
+ properties: {
36
+ status: { type: 'string' },
37
+ message: { type: 'string' }
38
+ },
39
+ required: ['status']
40
+ }
41
+ },
42
+ {
43
+ name: 'agent-comms',
44
+ description: 'Agent-to-agent communication with topic routing',
45
+ schema: {
46
+ type: 'object',
47
+ properties: {
48
+ topic: { type: 'string', description: 'Topic category for routing (e.g., "memory-management")' },
49
+ message: { type: 'string', description: 'The message content' },
50
+ replyTo: { type: 'string', format: 'uri', description: 'Callback URL for async reply' },
51
+ conversationId: { type: 'string', description: 'Thread identifier for multi-turn conversations' },
52
+ priority: { type: 'string', enum: ['low', 'normal', 'high'], description: 'Message priority level' }
53
+ },
54
+ required: ['topic', 'message']
55
+ }
56
+ }
57
+ ];
58
+ export function loadIntents() {
59
+ ensureConfigDir();
60
+ if (!fs.existsSync(INTENTS_FILE)) {
61
+ saveIntents(DEFAULT_INTENTS);
62
+ return DEFAULT_INTENTS;
63
+ }
64
+ const data = fs.readFileSync(INTENTS_FILE, 'utf-8');
65
+ const existingIntents = JSON.parse(data);
66
+ // Merge new default intents that don't exist in the file (upgrade path)
67
+ let updated = false;
68
+ for (const defaultIntent of DEFAULT_INTENTS) {
69
+ const exists = existingIntents.some(i => i.name === defaultIntent.name);
70
+ if (!exists) {
71
+ existingIntents.push(defaultIntent);
72
+ updated = true;
73
+ console.log(`[OGP] Added new default intent: ${defaultIntent.name}`);
74
+ }
75
+ }
76
+ // Save if we added new intents
77
+ if (updated) {
78
+ saveIntents(existingIntents);
79
+ }
80
+ return existingIntents;
81
+ }
82
+ export function saveIntents(intents) {
83
+ ensureConfigDir();
84
+ fs.writeFileSync(INTENTS_FILE, JSON.stringify(intents, null, 2), 'utf-8');
85
+ }
86
+ export function registerIntent(intent) {
87
+ const intents = loadIntents();
88
+ const existing = intents.findIndex(i => i.name === intent.name);
89
+ if (existing >= 0) {
90
+ intents[existing] = intent;
91
+ }
92
+ else {
93
+ intents.push(intent);
94
+ }
95
+ saveIntents(intents);
96
+ }
97
+ export function getIntent(name) {
98
+ const intents = loadIntents();
99
+ return intents.find(i => i.name === name) || null;
100
+ }
101
+ //# sourceMappingURL=intent-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intent-registry.js","sourceRoot":"","sources":["../../src/daemon/intent-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { type KeyPair } from '../shared/signing.js';
2
+ export declare function loadOrGenerateKeyPair(): KeyPair;
3
+ export declare function getPublicKey(): string;
4
+ export declare function getPrivateKey(): string;
5
+ //# sourceMappingURL=keypair.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keypair.d.ts","sourceRoot":"","sources":["../../src/daemon/keypair.ts"],"names":[],"mappings":"AAEA,OAAO,EAAmB,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAKrE,wBAAgB,qBAAqB,IAAI,OAAO,CAY/C;AAED,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAGtC"}
@@ -0,0 +1,25 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { generateKeyPair } from '../shared/signing.js';
4
+ import { getConfigDir, ensureConfigDir } from '../shared/config.js';
5
+ const KEYPAIR_FILE = path.join(getConfigDir(), 'keypair.json');
6
+ export function loadOrGenerateKeyPair() {
7
+ ensureConfigDir();
8
+ if (fs.existsSync(KEYPAIR_FILE)) {
9
+ const data = fs.readFileSync(KEYPAIR_FILE, 'utf-8');
10
+ return JSON.parse(data);
11
+ }
12
+ const keypair = generateKeyPair();
13
+ fs.writeFileSync(KEYPAIR_FILE, JSON.stringify(keypair, null, 2), 'utf-8');
14
+ console.log('[OGP] Generated new Ed25519 keypair');
15
+ return keypair;
16
+ }
17
+ export function getPublicKey() {
18
+ const keypair = loadOrGenerateKeyPair();
19
+ return keypair.publicKey;
20
+ }
21
+ export function getPrivateKey() {
22
+ const keypair = loadOrGenerateKeyPair();
23
+ return keypair.privateKey;
24
+ }
25
+ //# sourceMappingURL=keypair.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keypair.js","sourceRoot":"","sources":["../../src/daemon/keypair.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAgB,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEpE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,cAAc,CAAC,CAAC;AAE/D,MAAM,UAAU,qBAAqB;IACnC,eAAe,EAAE,CAAC;IAElB,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;IACrC,CAAC;IAED,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;IAClC,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;IACnD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;IACxC,OAAO,OAAO,CAAC,SAAS,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,qBAAqB,EAAE,CAAC;IACxC,OAAO,OAAO,CAAC,UAAU,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,20 @@
1
+ export interface FederationMessage {
2
+ intent: string;
3
+ from: string;
4
+ to: string;
5
+ nonce: string;
6
+ timestamp: string;
7
+ payload: any;
8
+ replyTo?: string;
9
+ conversationId?: string;
10
+ }
11
+ export interface MessageResponse {
12
+ success: boolean;
13
+ nonce: string;
14
+ response?: any;
15
+ error?: string;
16
+ statusCode?: number;
17
+ retryAfter?: number;
18
+ }
19
+ export declare function handleMessage(message: FederationMessage, signature: string): Promise<MessageResponse>;
20
+ //# sourceMappingURL=message-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-handler.d.ts","sourceRoot":"","sources":["../../src/daemon/message-handler.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,GAAG,CAAC;IAEb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,aAAa,CACjC,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAyF1B"}
@@ -0,0 +1,159 @@
1
+ import { verifyObject } from '../shared/signing.js';
2
+ import { getPeer } from './peers.js';
3
+ import { getIntent } from './intent-registry.js';
4
+ import { notifyOpenClaw } from './notify.js';
5
+ import { checkAccess } from './doorman.js';
6
+ import { logActivity, getEffectivePolicy } from './agent-comms.js';
7
+ export async function handleMessage(message, signature) {
8
+ // 1. Verify sender exists and is approved
9
+ const peer = getPeer(message.from);
10
+ if (!peer) {
11
+ return {
12
+ success: false,
13
+ nonce: message.nonce,
14
+ error: 'Unknown peer',
15
+ statusCode: 403
16
+ };
17
+ }
18
+ if (peer.status !== 'approved') {
19
+ return {
20
+ success: false,
21
+ nonce: message.nonce,
22
+ error: 'Peer not approved',
23
+ statusCode: 403
24
+ };
25
+ }
26
+ // 2. Verify signature
27
+ if (!verifyObject(message, signature, peer.publicKey)) {
28
+ return {
29
+ success: false,
30
+ nonce: message.nonce,
31
+ error: 'Invalid signature',
32
+ statusCode: 401
33
+ };
34
+ }
35
+ // 3. Doorman scope check (v0.2.0)
36
+ const accessResult = checkAccess(message.from, message.intent, message.payload);
37
+ if (!accessResult.allowed) {
38
+ console.log(`[OGP] Access denied for ${message.from}: ${accessResult.reason}`);
39
+ return {
40
+ success: false,
41
+ nonce: message.nonce,
42
+ error: accessResult.reason,
43
+ statusCode: accessResult.statusCode,
44
+ retryAfter: accessResult.retryAfter
45
+ };
46
+ }
47
+ if (accessResult.isV1Peer) {
48
+ console.log(`[OGP] Processing message from v0.1 peer ${message.from} (legacy mode)`);
49
+ }
50
+ // 4. Check intent exists
51
+ const intent = getIntent(message.intent);
52
+ if (!intent) {
53
+ return {
54
+ success: false,
55
+ nonce: message.nonce,
56
+ error: `Unknown intent: ${message.intent}`,
57
+ statusCode: 400
58
+ };
59
+ }
60
+ // 5. Handle agent-comms specially (includes replyTo support)
61
+ if (message.intent === 'agent-comms') {
62
+ return handleAgentComms(message, peer.displayName);
63
+ }
64
+ // 6. Standard intent handling: Notify OpenClaw
65
+ const notificationText = formatNotification(message, peer.displayName);
66
+ await notifyOpenClaw({
67
+ text: notificationText,
68
+ metadata: {
69
+ ogp: {
70
+ from: message.from,
71
+ intent: message.intent,
72
+ nonce: message.nonce,
73
+ payload: message.payload,
74
+ replyTo: message.replyTo,
75
+ conversationId: message.conversationId
76
+ }
77
+ }
78
+ });
79
+ // 7. Return success
80
+ return {
81
+ success: true,
82
+ nonce: message.nonce,
83
+ response: {
84
+ received: true,
85
+ timestamp: new Date().toISOString()
86
+ }
87
+ };
88
+ }
89
+ /**
90
+ * Handle agent-comms intent with topic routing and reply support
91
+ */
92
+ async function handleAgentComms(message, displayName) {
93
+ const payload = message.payload || {};
94
+ const topic = payload.topic || 'general';
95
+ const messageText = payload.message || '';
96
+ const priority = payload.priority || 'normal';
97
+ // Get effective response policy for this peer and topic
98
+ const policy = getEffectivePolicy(message.from, topic);
99
+ // Log incoming activity
100
+ logActivity({
101
+ direction: 'in',
102
+ peerId: message.from,
103
+ peerName: displayName,
104
+ topic,
105
+ message: messageText,
106
+ level: policy.level
107
+ });
108
+ // Build enhanced notification with policy info
109
+ const priorityIndicator = priority === 'high' ? '[HIGH] ' : priority === 'low' ? '[low] ' : '';
110
+ const policyTag = `[${policy.level.toUpperCase()}]`;
111
+ const notificationText = `[OGP Agent-Comms] ${priorityIndicator}${displayName} → ${topic} ${policyTag}: ${messageText}`;
112
+ await notifyOpenClaw({
113
+ text: notificationText,
114
+ metadata: {
115
+ ogp: {
116
+ from: message.from,
117
+ intent: 'agent-comms',
118
+ nonce: message.nonce,
119
+ topic,
120
+ message: messageText,
121
+ priority,
122
+ replyTo: message.replyTo,
123
+ conversationId: message.conversationId,
124
+ payload: message.payload,
125
+ // Include policy info for agent to use
126
+ responsePolicy: {
127
+ level: policy.level,
128
+ notes: policy.notes
129
+ }
130
+ }
131
+ }
132
+ });
133
+ return {
134
+ success: true,
135
+ nonce: message.nonce,
136
+ response: {
137
+ received: true,
138
+ topic,
139
+ timestamp: new Date().toISOString(),
140
+ // Tell sender how to get replies if they didn't provide callback
141
+ replyEndpoint: message.replyTo ? undefined : `/federation/reply/${message.nonce}`
142
+ }
143
+ };
144
+ }
145
+ function formatNotification(message, displayName) {
146
+ const intent = message.intent;
147
+ const payload = message.payload;
148
+ switch (intent) {
149
+ case 'message':
150
+ return `[OGP] Message from ${displayName}: ${payload.text}`;
151
+ case 'task-request':
152
+ return `[OGP] Task request from ${displayName}: ${payload.description}`;
153
+ case 'status-update':
154
+ return `[OGP] Status update from ${displayName}: ${payload.message || payload.status}`;
155
+ default:
156
+ return `[OGP] ${intent} from ${displayName}`;
157
+ }
158
+ }
159
+ //# sourceMappingURL=message-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"message-handler.js","sourceRoot":"","sources":["../../src/daemon/message-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface NotificationPayload {
2
+ text: string;
3
+ sessionKey?: string;
4
+ metadata?: Record<string, any>;
5
+ }
6
+ export declare function notifyOpenClaw(payload: NotificationPayload): Promise<boolean>;
7
+ //# sourceMappingURL=notify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../src/daemon/notify.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED,wBAAsB,cAAc,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuDnF"}
@@ -0,0 +1,54 @@
1
+ import { requireConfig } from '../shared/config.js';
2
+ import { execSync } from 'node:child_process';
3
+ export async function notifyOpenClaw(payload) {
4
+ const config = requireConfig();
5
+ // Method 1: Use openclaw CLI if available (most reliable, handles TLS)
6
+ try {
7
+ const escaped = payload.text.replace(/'/g, "'\\''");
8
+ execSync(`openclaw system event --text '${escaped}' --mode now 2>/dev/null`, {
9
+ timeout: 5000,
10
+ env: { ...process.env }
11
+ });
12
+ console.log('[OGP] Notified OpenClaw via CLI:', payload.text);
13
+ return true;
14
+ }
15
+ catch {
16
+ // CLI not available or failed — try HTTP
17
+ }
18
+ // Method 2: HTTP with token (for non-localhost or when CLI unavailable)
19
+ if (!config.openclawToken) {
20
+ console.log('[OGP] No OpenClaw token configured — skipping notification');
21
+ return false;
22
+ }
23
+ const openclawUrl = config.openclawUrl.replace(/\/$/, '');
24
+ try {
25
+ // Disable TLS verification for localhost
26
+ const env = { ...process.env };
27
+ if (openclawUrl.includes('localhost') || openclawUrl.includes('127.0.0.1')) {
28
+ env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
29
+ }
30
+ const response = await fetch(`${openclawUrl}/tools/invoke`, {
31
+ method: 'POST',
32
+ headers: {
33
+ 'Content-Type': 'application/json',
34
+ 'Authorization': `Bearer ${config.openclawToken}`
35
+ },
36
+ body: JSON.stringify({
37
+ tool: 'sessions_send',
38
+ args: {
39
+ sessionKey: payload.sessionKey || 'agent:main:main',
40
+ message: payload.text
41
+ }
42
+ })
43
+ });
44
+ if (response.ok) {
45
+ console.log('[OGP] Notified OpenClaw via HTTP:', payload.text);
46
+ return true;
47
+ }
48
+ }
49
+ catch (error) {
50
+ console.error('[OGP] Error notifying OpenClaw:', error);
51
+ }
52
+ return false;
53
+ }
54
+ //# sourceMappingURL=notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../src/daemon/notify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAQ9C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAA4B;IAC/D,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,uEAAuE;IACvE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACpD,QAAQ,CAAC,iCAAiC,OAAO,0BAA0B,EAAE;YAC3E,OAAO,EAAE,IAAI;YACb,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE;SACxB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,kCAAkC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9D,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,yCAAyC;IAC3C,CAAC;IAED,wEAAwE;IACxE,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;QAC1E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IAE1D,IAAI,CAAC;QACH,yCAAyC;QACzC,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC/B,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC3E,GAAG,CAAC,4BAA4B,GAAG,GAAG,CAAC;QACzC,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,WAAW,eAAe,EAAE;YAC1D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,eAAe,EAAE,UAAU,MAAM,CAAC,aAAa,EAAE;aAClD;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,IAAI,EAAE,eAAe;gBACrB,IAAI,EAAE;oBACJ,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,iBAAiB;oBACnD,OAAO,EAAE,OAAO,CAAC,IAAI;iBACtB;aACF,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;YAC/D,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}