@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.
- package/README.md +437 -0
- package/dist/cli/agent-comms.d.ts +55 -0
- package/dist/cli/agent-comms.d.ts.map +1 -0
- package/dist/cli/agent-comms.js +217 -0
- package/dist/cli/agent-comms.js.map +1 -0
- package/dist/cli/expose.d.ts +3 -0
- package/dist/cli/expose.d.ts.map +1 -0
- package/dist/cli/expose.js +104 -0
- package/dist/cli/expose.js.map +1 -0
- package/dist/cli/federation.d.ts +28 -0
- package/dist/cli/federation.d.ts.map +1 -0
- package/dist/cli/federation.js +409 -0
- package/dist/cli/federation.js.map +1 -0
- package/dist/cli/install.d.ts +3 -0
- package/dist/cli/install.d.ts.map +1 -0
- package/dist/cli/install.js +111 -0
- package/dist/cli/install.js.map +1 -0
- package/dist/cli/setup.d.ts +2 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +33 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +305 -0
- package/dist/cli.js.map +1 -0
- package/dist/daemon/agent-comms.d.ts +76 -0
- package/dist/daemon/agent-comms.d.ts.map +1 -0
- package/dist/daemon/agent-comms.js +188 -0
- package/dist/daemon/agent-comms.js.map +1 -0
- package/dist/daemon/doorman.d.ts +52 -0
- package/dist/daemon/doorman.d.ts.map +1 -0
- package/dist/daemon/doorman.js +203 -0
- package/dist/daemon/doorman.js.map +1 -0
- package/dist/daemon/intent-registry.d.ts +11 -0
- package/dist/daemon/intent-registry.d.ts.map +1 -0
- package/dist/daemon/intent-registry.js +101 -0
- package/dist/daemon/intent-registry.js.map +1 -0
- package/dist/daemon/keypair.d.ts +5 -0
- package/dist/daemon/keypair.d.ts.map +1 -0
- package/dist/daemon/keypair.js +25 -0
- package/dist/daemon/keypair.js.map +1 -0
- package/dist/daemon/message-handler.d.ts +20 -0
- package/dist/daemon/message-handler.d.ts.map +1 -0
- package/dist/daemon/message-handler.js +159 -0
- package/dist/daemon/message-handler.js.map +1 -0
- package/dist/daemon/notify.d.ts +7 -0
- package/dist/daemon/notify.d.ts.map +1 -0
- package/dist/daemon/notify.js +54 -0
- package/dist/daemon/notify.js.map +1 -0
- package/dist/daemon/peers.d.ts +66 -0
- package/dist/daemon/peers.d.ts.map +1 -0
- package/dist/daemon/peers.js +171 -0
- package/dist/daemon/peers.js.map +1 -0
- package/dist/daemon/reply-handler.d.ts +67 -0
- package/dist/daemon/reply-handler.d.ts.map +1 -0
- package/dist/daemon/reply-handler.js +176 -0
- package/dist/daemon/reply-handler.js.map +1 -0
- package/dist/daemon/scopes.d.ts +62 -0
- package/dist/daemon/scopes.d.ts.map +1 -0
- package/dist/daemon/scopes.js +113 -0
- package/dist/daemon/scopes.js.map +1 -0
- package/dist/daemon/server.d.ts +8 -0
- package/dist/daemon/server.d.ts.map +1 -0
- package/dist/daemon/server.js +286 -0
- package/dist/daemon/server.js.map +1 -0
- package/dist/shared/config.d.ts +42 -0
- package/dist/shared/config.d.ts.map +1 -0
- package/dist/shared/config.js +42 -0
- package/dist/shared/config.js.map +1 -0
- package/dist/shared/signing.d.ts +13 -0
- package/dist/shared/signing.d.ts.map +1 -0
- package/dist/shared/signing.js +46 -0
- package/dist/shared/signing.js.map +1 -0
- package/docs/agent-comms.md +277 -0
- package/docs/federation-flow.md +407 -0
- package/docs/quickstart.md +241 -0
- package/docs/scopes.md +198 -0
- package/package.json +57 -0
- package/scripts/install-skills.js +32 -0
- package/skills/ogp/SKILL.md +235 -0
- package/skills/ogp-agent-comms/SKILL.md +345 -0
- package/skills/ogp-expose/SKILL.md +281 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OGP v0.2.0 Scope Types
|
|
3
|
+
*
|
|
4
|
+
* Three-layer model:
|
|
5
|
+
* Layer 1: Gateway Capabilities - What I CAN support (advertised globally)
|
|
6
|
+
* Layer 2: Peer Negotiation - What I WILL grant YOU (per-peer, during approval)
|
|
7
|
+
* Layer 3: Runtime Enforcement - Is THIS request within YOUR granted scope (doorman)
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Default scopes granted to v0.1 peers (backward compatibility)
|
|
11
|
+
*/
|
|
12
|
+
export const DEFAULT_V1_SCOPES = {
|
|
13
|
+
version: "0.2.0",
|
|
14
|
+
grantedAt: new Date().toISOString(),
|
|
15
|
+
scopes: [
|
|
16
|
+
{
|
|
17
|
+
intent: "message",
|
|
18
|
+
enabled: true,
|
|
19
|
+
rateLimit: { requests: 100, windowSeconds: 3600 }
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
intent: "task-request",
|
|
23
|
+
enabled: true,
|
|
24
|
+
rateLimit: { requests: 100, windowSeconds: 3600 }
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
intent: "status-update",
|
|
28
|
+
enabled: true,
|
|
29
|
+
rateLimit: { requests: 100, windowSeconds: 3600 }
|
|
30
|
+
}
|
|
31
|
+
]
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Default rate limit for all intents
|
|
35
|
+
*/
|
|
36
|
+
export const DEFAULT_RATE_LIMIT = {
|
|
37
|
+
requests: 100,
|
|
38
|
+
windowSeconds: 3600
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Parse a rate limit string like "100/3600" or "10/60"
|
|
42
|
+
*/
|
|
43
|
+
export function parseRateLimit(rateStr) {
|
|
44
|
+
const match = rateStr.match(/^(\d+)\/(\d+)$/);
|
|
45
|
+
if (!match)
|
|
46
|
+
return null;
|
|
47
|
+
return {
|
|
48
|
+
requests: parseInt(match[1], 10),
|
|
49
|
+
windowSeconds: parseInt(match[2], 10)
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Format a rate limit as string like "100/3600"
|
|
54
|
+
*/
|
|
55
|
+
export function formatRateLimit(limit) {
|
|
56
|
+
return `${limit.requests}/${limit.windowSeconds}`;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Create a scope grant from CLI options
|
|
60
|
+
*/
|
|
61
|
+
export function createScopeGrant(intent, options = {}) {
|
|
62
|
+
return {
|
|
63
|
+
intent,
|
|
64
|
+
enabled: options.enabled ?? true,
|
|
65
|
+
...(options.rateLimit && { rateLimit: options.rateLimit }),
|
|
66
|
+
...(options.topics && { topics: options.topics }),
|
|
67
|
+
...(options.expiresAt && { expiresAt: options.expiresAt })
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create a scope bundle from an array of scope grants
|
|
72
|
+
*/
|
|
73
|
+
export function createScopeBundle(scopes) {
|
|
74
|
+
return {
|
|
75
|
+
version: "0.2.0",
|
|
76
|
+
grantedAt: new Date().toISOString(),
|
|
77
|
+
scopes
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Check if a scope grant covers a specific intent and topic
|
|
82
|
+
*/
|
|
83
|
+
export function scopeCoversIntent(grant, intent, topic) {
|
|
84
|
+
if (grant.intent !== intent)
|
|
85
|
+
return false;
|
|
86
|
+
if (!grant.enabled)
|
|
87
|
+
return false;
|
|
88
|
+
// Check expiration
|
|
89
|
+
if (grant.expiresAt) {
|
|
90
|
+
const expiry = new Date(grant.expiresAt);
|
|
91
|
+
if (expiry < new Date())
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
// For agent-comms, check topic restriction
|
|
95
|
+
if (intent === 'agent-comms' && grant.topics && grant.topics.length > 0) {
|
|
96
|
+
if (!topic)
|
|
97
|
+
return false;
|
|
98
|
+
// Check if topic matches any allowed prefix
|
|
99
|
+
const topicMatches = grant.topics.some(allowed => topic === allowed || topic.startsWith(allowed + '/'));
|
|
100
|
+
if (!topicMatches)
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Find a scope grant for a specific intent in a bundle
|
|
107
|
+
*/
|
|
108
|
+
export function findScopeGrant(bundle, intent) {
|
|
109
|
+
if (!bundle)
|
|
110
|
+
return null;
|
|
111
|
+
return bundle.scopes.find(s => s.intent === intent && s.enabled) || null;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=scopes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scopes.js","sourceRoot":"","sources":["../../src/daemon/scopes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type OGPConfig } from '../shared/config.js';
|
|
2
|
+
export declare function startServer(config?: OGPConfig, background?: boolean): void;
|
|
3
|
+
export declare function stopServer(): void;
|
|
4
|
+
export declare function getDaemonStatus(): {
|
|
5
|
+
running: boolean;
|
|
6
|
+
pid?: number;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAiB,KAAK,SAAS,EAAgB,MAAM,qBAAqB,CAAC;AAelF,wBAAgB,WAAW,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,UAAU,UAAQ,GAAG,IAAI,CAiPxE;AAED,wBAAgB,UAAU,IAAI,IAAI,CAqCjC;AAED,wBAAgB,eAAe,IAAI;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAyBpE"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import { spawn } from 'node:child_process';
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { requireConfig, getConfigDir } from '../shared/config.js';
|
|
6
|
+
import { getPublicKey } from './keypair.js';
|
|
7
|
+
import { addPeer, getPeer, approvePeer, listPeers, updatePeer } from './peers.js';
|
|
8
|
+
import { handleMessage } from './message-handler.js';
|
|
9
|
+
import { startDoormanCleanup, stopDoormanCleanup } from './doorman.js';
|
|
10
|
+
import { startReplyCleanup, stopReplyCleanup, getPendingReply, deletePendingReply, storePendingReply } from './reply-handler.js';
|
|
11
|
+
import { loadIntents } from './intent-registry.js';
|
|
12
|
+
let server = null;
|
|
13
|
+
const DAEMON_PID_FILE = path.join(getConfigDir(), 'daemon.pid');
|
|
14
|
+
const DAEMON_LOG_FILE = path.join(getConfigDir(), 'daemon.log');
|
|
15
|
+
export function startServer(config, background = false) {
|
|
16
|
+
const cfg = config || requireConfig();
|
|
17
|
+
// If background mode requested, fork and exit parent
|
|
18
|
+
if (background) {
|
|
19
|
+
const logStream = fs.openSync(DAEMON_LOG_FILE, 'a');
|
|
20
|
+
const child = spawn(process.execPath, [process.argv[1], 'start'], {
|
|
21
|
+
detached: true,
|
|
22
|
+
stdio: ['ignore', logStream, logStream]
|
|
23
|
+
});
|
|
24
|
+
child.unref();
|
|
25
|
+
fs.writeFileSync(DAEMON_PID_FILE, child.pid.toString(), 'utf-8');
|
|
26
|
+
console.log(`OGP daemon started (PID: ${child.pid})`);
|
|
27
|
+
console.log(`Logs: ${DAEMON_LOG_FILE}`);
|
|
28
|
+
process.exit(0);
|
|
29
|
+
}
|
|
30
|
+
const app = express();
|
|
31
|
+
app.use(express.json());
|
|
32
|
+
// /.well-known/ogp - Discovery endpoint
|
|
33
|
+
app.get('/.well-known/ogp', (req, res) => {
|
|
34
|
+
// Get supported intents from registry
|
|
35
|
+
const intents = loadIntents();
|
|
36
|
+
const intentNames = intents.map(i => i.name);
|
|
37
|
+
res.json({
|
|
38
|
+
version: '0.2.0',
|
|
39
|
+
displayName: cfg.displayName,
|
|
40
|
+
email: cfg.email,
|
|
41
|
+
gatewayUrl: cfg.gatewayUrl,
|
|
42
|
+
publicKey: getPublicKey(),
|
|
43
|
+
capabilities: {
|
|
44
|
+
intents: intentNames,
|
|
45
|
+
features: ['scope-negotiation', 'reply-callback']
|
|
46
|
+
},
|
|
47
|
+
endpoints: {
|
|
48
|
+
request: `${cfg.gatewayUrl}/federation/request`,
|
|
49
|
+
approve: `${cfg.gatewayUrl}/federation/approve`,
|
|
50
|
+
message: `${cfg.gatewayUrl}/federation/message`,
|
|
51
|
+
reply: `${cfg.gatewayUrl}/federation/reply/:nonce`
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
// POST /federation/request - Incoming federation request
|
|
56
|
+
app.post('/federation/request', async (req, res) => {
|
|
57
|
+
try {
|
|
58
|
+
const { peer, signature } = req.body;
|
|
59
|
+
if (!peer || !signature) {
|
|
60
|
+
return res.status(400).json({ error: 'Missing peer or signature' });
|
|
61
|
+
}
|
|
62
|
+
const peerData = {
|
|
63
|
+
id: peer.id,
|
|
64
|
+
displayName: peer.displayName,
|
|
65
|
+
email: peer.email,
|
|
66
|
+
gatewayUrl: peer.gatewayUrl,
|
|
67
|
+
publicKey: peer.publicKey,
|
|
68
|
+
status: 'pending',
|
|
69
|
+
requestedAt: new Date().toISOString()
|
|
70
|
+
};
|
|
71
|
+
addPeer(peerData);
|
|
72
|
+
console.log(`[OGP] Federation request from ${peer.displayName} (${peer.id})`);
|
|
73
|
+
res.json({
|
|
74
|
+
received: true,
|
|
75
|
+
status: 'pending',
|
|
76
|
+
message: 'Federation request received and pending approval'
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
console.error('[OGP] Error handling federation request:', error);
|
|
81
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
// POST /federation/approve - Peer approves our request
|
|
85
|
+
// Accepts both package format {peerId, approved} and fork format {fromGatewayId, fromGatewayUrl, ...}
|
|
86
|
+
// v0.2.0: Also accepts scopeGrants for scope negotiation
|
|
87
|
+
app.post('/federation/approve', async (req, res) => {
|
|
88
|
+
try {
|
|
89
|
+
const body = req.body || {};
|
|
90
|
+
// Fork format: full identity card sent as approval signal
|
|
91
|
+
const fromGatewayId = body.fromGatewayId;
|
|
92
|
+
const fromGatewayUrl = body.fromGatewayUrl;
|
|
93
|
+
const fromDisplayName = body.fromDisplayName;
|
|
94
|
+
const fromPublicKey = body.fromPublicKey;
|
|
95
|
+
const fromEmail = body.fromEmail;
|
|
96
|
+
// Package format: simple peerId + approved flag
|
|
97
|
+
const peerId = body.peerId;
|
|
98
|
+
// v0.2.0: Scope grants from the approving peer
|
|
99
|
+
const scopeGrants = body.scopeGrants;
|
|
100
|
+
const protocolVersion = body.protocolVersion || (scopeGrants ? '0.2.0' : '0.1.0');
|
|
101
|
+
// Find the peer to approve — try multiple strategies
|
|
102
|
+
let peer = null;
|
|
103
|
+
if (peerId)
|
|
104
|
+
peer = getPeer(peerId);
|
|
105
|
+
if (!peer && fromGatewayId)
|
|
106
|
+
peer = getPeer(fromGatewayId);
|
|
107
|
+
if (!peer && fromGatewayUrl) {
|
|
108
|
+
const allPeers = listPeers();
|
|
109
|
+
peer = allPeers.find((p) => p.gatewayUrl === fromGatewayUrl) || null;
|
|
110
|
+
}
|
|
111
|
+
// Last resort: approve any pending peer
|
|
112
|
+
if (!peer) {
|
|
113
|
+
const allPeers = listPeers();
|
|
114
|
+
peer = allPeers.find((p) => p.status === 'pending') || null;
|
|
115
|
+
}
|
|
116
|
+
if (!peer) {
|
|
117
|
+
return res.status(404).json({ error: 'No pending peer found' });
|
|
118
|
+
}
|
|
119
|
+
// Update peer info if fork sent richer data
|
|
120
|
+
const peerUpdates = {};
|
|
121
|
+
if (fromDisplayName)
|
|
122
|
+
peerUpdates.displayName = fromDisplayName;
|
|
123
|
+
if (fromPublicKey)
|
|
124
|
+
peerUpdates.publicKey = fromPublicKey;
|
|
125
|
+
if (fromEmail)
|
|
126
|
+
peerUpdates.email = fromEmail;
|
|
127
|
+
peerUpdates.protocolVersion = protocolVersion;
|
|
128
|
+
// Store received scopes (what this peer grants TO us)
|
|
129
|
+
if (scopeGrants) {
|
|
130
|
+
peerUpdates.receivedScopes = scopeGrants;
|
|
131
|
+
console.log(`[OGP] Received scope grants from ${peer.displayName}:`, scopeGrants.scopes.map(s => s.intent).join(', '));
|
|
132
|
+
}
|
|
133
|
+
// Update peer with new info
|
|
134
|
+
if (Object.keys(peerUpdates).length > 0) {
|
|
135
|
+
updatePeer(peer.id, peerUpdates);
|
|
136
|
+
}
|
|
137
|
+
approvePeer(peer.id);
|
|
138
|
+
console.log(`[OGP] Federation approved by ${peer.displayName} (v${protocolVersion})`);
|
|
139
|
+
res.json({ received: true });
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
console.error('[OGP] Error handling approval:', error);
|
|
143
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
// GET /federation/ping - Simple liveness + identity check (no auth required)
|
|
147
|
+
app.get('/federation/ping', (req, res) => {
|
|
148
|
+
res.json({
|
|
149
|
+
pong: true,
|
|
150
|
+
displayName: cfg.displayName,
|
|
151
|
+
gatewayUrl: cfg.gatewayUrl,
|
|
152
|
+
timestamp: new Date().toISOString()
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
// POST /federation/message - Receive federated message
|
|
156
|
+
app.post('/federation/message', async (req, res) => {
|
|
157
|
+
try {
|
|
158
|
+
const { message, signature } = req.body;
|
|
159
|
+
if (!message || !signature) {
|
|
160
|
+
return res.status(400).json({ error: 'Missing message or signature' });
|
|
161
|
+
}
|
|
162
|
+
const result = await handleMessage(message, signature);
|
|
163
|
+
if (result.success) {
|
|
164
|
+
res.json(result.response);
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
res.status(400).json({ error: result.error });
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
console.error('[OGP] Error handling message:', error);
|
|
172
|
+
res.status(500).json({ error: 'Internal server error' });
|
|
173
|
+
}
|
|
174
|
+
});
|
|
175
|
+
// GET /federation/reply/:nonce - Poll for reply to a message
|
|
176
|
+
app.get('/federation/reply/:nonce', (req, res) => {
|
|
177
|
+
const { nonce } = req.params;
|
|
178
|
+
const reply = getPendingReply(nonce);
|
|
179
|
+
if (!reply) {
|
|
180
|
+
return res.status(404).json({
|
|
181
|
+
nonce,
|
|
182
|
+
status: 'pending',
|
|
183
|
+
message: 'Reply not yet available'
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// Delete after retrieval
|
|
187
|
+
deletePendingReply(nonce);
|
|
188
|
+
res.json({
|
|
189
|
+
nonce,
|
|
190
|
+
status: 'complete',
|
|
191
|
+
reply: {
|
|
192
|
+
success: reply.success,
|
|
193
|
+
data: reply.data,
|
|
194
|
+
error: reply.error,
|
|
195
|
+
timestamp: reply.timestamp
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
// POST /federation/reply/:nonce - Receive reply callback from remote gateway
|
|
200
|
+
app.post('/federation/reply/:nonce', (req, res) => {
|
|
201
|
+
const { nonce } = req.params;
|
|
202
|
+
const body = req.body || {};
|
|
203
|
+
// The reply can come in different formats
|
|
204
|
+
const reply = body.reply || body;
|
|
205
|
+
const replyPayload = {
|
|
206
|
+
nonce,
|
|
207
|
+
success: reply.success ?? true,
|
|
208
|
+
data: reply.data,
|
|
209
|
+
error: reply.error,
|
|
210
|
+
timestamp: reply.timestamp || new Date().toISOString()
|
|
211
|
+
};
|
|
212
|
+
// Store for later retrieval
|
|
213
|
+
storePendingReply(nonce, replyPayload);
|
|
214
|
+
console.log(`[OGP] Received reply callback for nonce ${nonce}`);
|
|
215
|
+
res.json({ received: true });
|
|
216
|
+
});
|
|
217
|
+
server = app.listen(cfg.daemonPort, () => {
|
|
218
|
+
console.log(`[OGP] Daemon listening on port ${cfg.daemonPort}`);
|
|
219
|
+
console.log(`[OGP] Public key: ${getPublicKey()}`);
|
|
220
|
+
// Start cleanup timers
|
|
221
|
+
startDoormanCleanup();
|
|
222
|
+
startReplyCleanup();
|
|
223
|
+
console.log(`[OGP] Started doorman and reply cleanup timers`);
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
export function stopServer() {
|
|
227
|
+
// Stop cleanup timers
|
|
228
|
+
stopDoormanCleanup();
|
|
229
|
+
stopReplyCleanup();
|
|
230
|
+
// Check for PID file
|
|
231
|
+
if (!fs.existsSync(DAEMON_PID_FILE)) {
|
|
232
|
+
console.log('OGP daemon is not running');
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
try {
|
|
236
|
+
const pidStr = fs.readFileSync(DAEMON_PID_FILE, 'utf-8').trim();
|
|
237
|
+
const pid = parseInt(pidStr, 10);
|
|
238
|
+
if (isNaN(pid)) {
|
|
239
|
+
console.error('Invalid PID in daemon.pid file');
|
|
240
|
+
fs.unlinkSync(DAEMON_PID_FILE);
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
// Check if process is running
|
|
244
|
+
try {
|
|
245
|
+
process.kill(pid, 0); // Signal 0 checks if process exists
|
|
246
|
+
}
|
|
247
|
+
catch (error) {
|
|
248
|
+
console.log('OGP daemon is not running (stale PID file)');
|
|
249
|
+
fs.unlinkSync(DAEMON_PID_FILE);
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
// Send SIGTERM
|
|
253
|
+
process.kill(pid, 'SIGTERM');
|
|
254
|
+
fs.unlinkSync(DAEMON_PID_FILE);
|
|
255
|
+
console.log('OGP daemon stopped');
|
|
256
|
+
}
|
|
257
|
+
catch (error) {
|
|
258
|
+
console.error('Failed to stop daemon:', error);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
export function getDaemonStatus() {
|
|
262
|
+
if (!fs.existsSync(DAEMON_PID_FILE)) {
|
|
263
|
+
return { running: false };
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
const pidStr = fs.readFileSync(DAEMON_PID_FILE, 'utf-8').trim();
|
|
267
|
+
const pid = parseInt(pidStr, 10);
|
|
268
|
+
if (isNaN(pid)) {
|
|
269
|
+
fs.unlinkSync(DAEMON_PID_FILE);
|
|
270
|
+
return { running: false };
|
|
271
|
+
}
|
|
272
|
+
// Check if process is running
|
|
273
|
+
try {
|
|
274
|
+
process.kill(pid, 0);
|
|
275
|
+
return { running: true, pid };
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
fs.unlinkSync(DAEMON_PID_FILE);
|
|
279
|
+
return { running: false };
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
return { running: false };
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/daemon/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Response level for agent-comms
|
|
3
|
+
*/
|
|
4
|
+
export type ResponseLevel = 'full' | 'summary' | 'escalate' | 'deny';
|
|
5
|
+
/**
|
|
6
|
+
* Topic policy configuration
|
|
7
|
+
*/
|
|
8
|
+
export interface TopicPolicy {
|
|
9
|
+
level: ResponseLevel;
|
|
10
|
+
notes?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Response policy mapping topics to policies
|
|
14
|
+
*/
|
|
15
|
+
export interface ResponsePolicy {
|
|
16
|
+
[topic: string]: TopicPolicy;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Agent-comms configuration
|
|
20
|
+
*/
|
|
21
|
+
export interface AgentCommsConfig {
|
|
22
|
+
globalPolicy: ResponsePolicy;
|
|
23
|
+
defaultLevel: ResponseLevel;
|
|
24
|
+
activityLog: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface OGPConfig {
|
|
27
|
+
daemonPort: number;
|
|
28
|
+
openclawUrl: string;
|
|
29
|
+
openclawToken: string;
|
|
30
|
+
gatewayUrl: string;
|
|
31
|
+
displayName: string;
|
|
32
|
+
email: string;
|
|
33
|
+
stateDir: string;
|
|
34
|
+
agentComms?: AgentCommsConfig;
|
|
35
|
+
}
|
|
36
|
+
export declare function getConfigPath(): string;
|
|
37
|
+
export declare function getConfigDir(): string;
|
|
38
|
+
export declare function ensureConfigDir(): void;
|
|
39
|
+
export declare function loadConfig(): OGPConfig | null;
|
|
40
|
+
export declare function saveConfig(config: OGPConfig): void;
|
|
41
|
+
export declare function requireConfig(): OGPConfig;
|
|
42
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAErE;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,cAAc,CAAC;IAC7B,YAAY,EAAE,aAAa,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAKD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAItC;AAED,wBAAgB,UAAU,IAAI,SAAS,GAAG,IAAI,CAW7C;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAGlD;AAED,wBAAgB,aAAa,IAAI,SAAS,CAOzC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
const DEFAULT_CONFIG_DIR = path.join(os.homedir(), '.ogp');
|
|
5
|
+
const CONFIG_FILE = path.join(DEFAULT_CONFIG_DIR, 'config.json');
|
|
6
|
+
export function getConfigPath() {
|
|
7
|
+
return CONFIG_FILE;
|
|
8
|
+
}
|
|
9
|
+
export function getConfigDir() {
|
|
10
|
+
return DEFAULT_CONFIG_DIR;
|
|
11
|
+
}
|
|
12
|
+
export function ensureConfigDir() {
|
|
13
|
+
if (!fs.existsSync(DEFAULT_CONFIG_DIR)) {
|
|
14
|
+
fs.mkdirSync(DEFAULT_CONFIG_DIR, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function loadConfig() {
|
|
18
|
+
try {
|
|
19
|
+
if (!fs.existsSync(CONFIG_FILE)) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const data = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
23
|
+
return JSON.parse(data);
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.error('Failed to load config:', error);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function saveConfig(config) {
|
|
31
|
+
ensureConfigDir();
|
|
32
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), 'utf-8');
|
|
33
|
+
}
|
|
34
|
+
export function requireConfig() {
|
|
35
|
+
const config = loadConfig();
|
|
36
|
+
if (!config) {
|
|
37
|
+
console.error('No configuration found. Run "ogp setup" first.');
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
return config;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AA2CzB,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;AAC3D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;AAEjE,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;QACvC,EAAE,CAAC,SAAS,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAc,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;QAC/C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAiB;IAC1C,eAAe,EAAE,CAAC;IAClB,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AAC1E,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface KeyPair {
|
|
2
|
+
publicKey: string;
|
|
3
|
+
privateKey: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function generateKeyPair(): KeyPair;
|
|
6
|
+
export declare function sign(message: string, privateKeyHex: string): string;
|
|
7
|
+
export declare function verify(message: string, signatureHex: string, publicKeyHex: string): boolean;
|
|
8
|
+
export declare function signObject(obj: any, privateKeyHex: string): {
|
|
9
|
+
payload: any;
|
|
10
|
+
signature: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function verifyObject(payload: any, signature: string, publicKeyHex: string): boolean;
|
|
13
|
+
//# sourceMappingURL=signing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing.d.ts","sourceRoot":"","sources":["../../src/shared/signing.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,OAAO;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,eAAe,IAAI,OAAO,CAUzC;AAED,wBAAgB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAUnE;AAED,wBAAgB,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAc3F;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,GAAG,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAI/F;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAG3F"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
export function generateKeyPair() {
|
|
3
|
+
const { publicKey, privateKey } = crypto.generateKeyPairSync('ed25519', {
|
|
4
|
+
publicKeyEncoding: { type: 'spki', format: 'der' },
|
|
5
|
+
privateKeyEncoding: { type: 'pkcs8', format: 'der' }
|
|
6
|
+
});
|
|
7
|
+
return {
|
|
8
|
+
publicKey: publicKey.toString('hex'),
|
|
9
|
+
privateKey: privateKey.toString('hex')
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export function sign(message, privateKeyHex) {
|
|
13
|
+
const privateKeyDer = Buffer.from(privateKeyHex, 'hex');
|
|
14
|
+
const privateKey = crypto.createPrivateKey({
|
|
15
|
+
key: privateKeyDer,
|
|
16
|
+
format: 'der',
|
|
17
|
+
type: 'pkcs8'
|
|
18
|
+
});
|
|
19
|
+
const signature = crypto.sign(null, Buffer.from(message, 'utf-8'), privateKey);
|
|
20
|
+
return signature.toString('hex');
|
|
21
|
+
}
|
|
22
|
+
export function verify(message, signatureHex, publicKeyHex) {
|
|
23
|
+
try {
|
|
24
|
+
const publicKeyDer = Buffer.from(publicKeyHex, 'hex');
|
|
25
|
+
const publicKey = crypto.createPublicKey({
|
|
26
|
+
key: publicKeyDer,
|
|
27
|
+
format: 'der',
|
|
28
|
+
type: 'spki'
|
|
29
|
+
});
|
|
30
|
+
const signature = Buffer.from(signatureHex, 'hex');
|
|
31
|
+
return crypto.verify(null, Buffer.from(message, 'utf-8'), publicKey, signature);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function signObject(obj, privateKeyHex) {
|
|
38
|
+
const payload = JSON.stringify(obj);
|
|
39
|
+
const signature = sign(payload, privateKeyHex);
|
|
40
|
+
return { payload: obj, signature };
|
|
41
|
+
}
|
|
42
|
+
export function verifyObject(payload, signature, publicKeyHex) {
|
|
43
|
+
const message = JSON.stringify(payload);
|
|
44
|
+
return verify(message, signature, publicKeyHex);
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=signing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signing.js","sourceRoot":"","sources":["../../src/shared/signing.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,aAAa,CAAC;AAOjC,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,MAAM,CAAC,mBAAmB,CAAC,SAAS,EAAE;QACtE,iBAAiB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE;QAClD,kBAAkB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE;KACrD,CAAC,CAAC;IAEH,OAAO;QACL,SAAS,EAAE,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC;QACpC,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,OAAe,EAAE,aAAqB;IACzD,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;IACxD,MAAM,UAAU,GAAG,MAAM,CAAC,gBAAgB,CAAC;QACzC,GAAG,EAAE,aAAa;QAClB,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,OAAO;KACd,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,UAAU,CAAC,CAAC;IAC/E,OAAO,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,OAAe,EAAE,YAAoB,EAAE,YAAoB;IAChF,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACtD,MAAM,SAAS,GAAG,MAAM,CAAC,eAAe,CAAC;YACvC,GAAG,EAAE,YAAY;YACjB,MAAM,EAAE,KAAK;YACb,IAAI,EAAE,MAAM;SACb,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;QACnD,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAClF,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAQ,EAAE,aAAqB;IACxD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAC/C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AACrC,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,OAAY,EAAE,SAAiB,EAAE,YAAoB;IAChF,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC,OAAO,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AAClD,CAAC"}
|