arkna 1.4.0 → 2.0.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/dist/commands/init.d.ts +3 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +276 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +2 -5
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +47 -116
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/verify.d.ts.map +1 -1
- package/dist/commands/verify.js +87 -114
- package/dist/commands/verify.js.map +1 -1
- package/dist/index.js +6 -16
- package/dist/index.js.map +1 -1
- package/dist/lib/arkna-dir.d.ts +4 -86
- package/dist/lib/arkna-dir.d.ts.map +1 -1
- package/dist/lib/arkna-dir.js +6 -110
- package/dist/lib/arkna-dir.js.map +1 -1
- package/dist/lib/connectivity.d.ts +7 -50
- package/dist/lib/connectivity.d.ts.map +1 -1
- package/dist/lib/connectivity.js +39 -255
- package/dist/lib/connectivity.js.map +1 -1
- package/dist/lib/detect.d.ts +35 -0
- package/dist/lib/detect.d.ts.map +1 -0
- package/dist/lib/detect.js +335 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/ui.js +2 -2
- package/dist/lib/ui.js.map +1 -1
- package/package.json +8 -7
- package/dist/commands/action.d.ts +0 -3
- package/dist/commands/action.d.ts.map +0 -1
- package/dist/commands/action.js +0 -333
- package/dist/commands/action.js.map +0 -1
- package/dist/commands/connect.d.ts +0 -3
- package/dist/commands/connect.d.ts.map +0 -1
- package/dist/commands/connect.js +0 -582
- package/dist/commands/connect.js.map +0 -1
- package/dist/commands/pull-governance.d.ts +0 -3
- package/dist/commands/pull-governance.d.ts.map +0 -1
- package/dist/commands/pull-governance.js +0 -116
- package/dist/commands/pull-governance.js.map +0 -1
- package/dist/commands/push-manifest.d.ts +0 -3
- package/dist/commands/push-manifest.d.ts.map +0 -1
- package/dist/commands/push-manifest.js +0 -138
- package/dist/commands/push-manifest.js.map +0 -1
- package/dist/commands/sync.d.ts +0 -3
- package/dist/commands/sync.d.ts.map +0 -1
- package/dist/commands/sync.js +0 -65
- package/dist/commands/sync.js.map +0 -1
- package/dist/commands/test.d.ts +0 -3
- package/dist/commands/test.d.ts.map +0 -1
- package/dist/commands/test.js +0 -142
- package/dist/commands/test.js.map +0 -1
- package/dist/lib/platforms.d.ts +0 -45
- package/dist/lib/platforms.d.ts.map +0 -1
- package/dist/lib/platforms.js +0 -638
- package/dist/lib/platforms.js.map +0 -1
package/dist/lib/platforms.js
DELETED
|
@@ -1,638 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.detectPlatform = detectPlatform;
|
|
37
|
-
exports.findOpenClawConfig = findOpenClawConfig;
|
|
38
|
-
exports.detectAgents = detectAgents;
|
|
39
|
-
exports.wireOpenClaw = wireOpenClaw;
|
|
40
|
-
exports.getOpenClawYamlBlock = getOpenClawYamlBlock;
|
|
41
|
-
exports.wireCrewAI = wireCrewAI;
|
|
42
|
-
exports.wireLangChain = wireLangChain;
|
|
43
|
-
exports.getCustomPatch = getCustomPatch;
|
|
44
|
-
const fs = __importStar(require("fs"));
|
|
45
|
-
const path = __importStar(require("path"));
|
|
46
|
-
const yaml = __importStar(require("js-yaml"));
|
|
47
|
-
/**
|
|
48
|
-
* Auto-detect the agent platform by scanning for marker files in `dir`.
|
|
49
|
-
* Returns null if nothing is detected.
|
|
50
|
-
*/
|
|
51
|
-
function detectPlatform(dir) {
|
|
52
|
-
// 1. OpenClaw — SOUL.md + skills/ directory (high confidence)
|
|
53
|
-
const hasSoulMd = fs.existsSync(path.join(dir, 'SOUL.md'));
|
|
54
|
-
const hasSkillsDir = fs.existsSync(path.join(dir, 'skills')) &&
|
|
55
|
-
fs.statSync(path.join(dir, 'skills')).isDirectory();
|
|
56
|
-
if (hasSoulMd && hasSkillsDir) {
|
|
57
|
-
const configFile = findOpenClawConfig(dir);
|
|
58
|
-
return {
|
|
59
|
-
platform: 'openclaw',
|
|
60
|
-
confidence: 'certain',
|
|
61
|
-
evidence: 'found SOUL.md + skills/',
|
|
62
|
-
configFile: configFile ?? undefined,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
// OpenClaw — YAML with connectors/startup_hooks/tool_routing keys
|
|
66
|
-
const openclawConfig = findOpenClawConfig(dir);
|
|
67
|
-
if (openclawConfig) {
|
|
68
|
-
return {
|
|
69
|
-
platform: 'openclaw',
|
|
70
|
-
confidence: 'likely',
|
|
71
|
-
evidence: `found ${path.basename(openclawConfig)} with OpenClaw config keys`,
|
|
72
|
-
configFile: openclawConfig,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
// 2. CrewAI — crewai in requirements.txt or pyproject.toml, or `from crewai` imports
|
|
76
|
-
if (hasDependency(dir, 'crewai')) {
|
|
77
|
-
return { platform: 'crewai', confidence: 'certain', evidence: 'crewai in project dependencies' };
|
|
78
|
-
}
|
|
79
|
-
if (hasPythonImport(dir, 'crewai')) {
|
|
80
|
-
return { platform: 'crewai', confidence: 'likely', evidence: 'from crewai import found in .py files' };
|
|
81
|
-
}
|
|
82
|
-
// 3. LangChain — langchain in requirements or imports
|
|
83
|
-
if (hasDependency(dir, 'langchain')) {
|
|
84
|
-
return { platform: 'langchain', confidence: 'certain', evidence: 'langchain in project dependencies' };
|
|
85
|
-
}
|
|
86
|
-
if (hasPythonImport(dir, 'langchain')) {
|
|
87
|
-
return { platform: 'langchain', confidence: 'likely', evidence: 'from langchain import found in .py files' };
|
|
88
|
-
}
|
|
89
|
-
// 4. Node custom — package.json present
|
|
90
|
-
if (fs.existsSync(path.join(dir, 'package.json'))) {
|
|
91
|
-
return { platform: 'custom', confidence: 'guessed', evidence: 'Node.js project (package.json)' };
|
|
92
|
-
}
|
|
93
|
-
// 5. Python custom — .py files present
|
|
94
|
-
const hasPyFiles = safeReadDir(dir).some(f => f.endsWith('.py'));
|
|
95
|
-
if (hasPyFiles) {
|
|
96
|
-
return { platform: 'custom', confidence: 'guessed', evidence: 'Python project (.py files found)' };
|
|
97
|
-
}
|
|
98
|
-
return null;
|
|
99
|
-
}
|
|
100
|
-
/**
|
|
101
|
-
* Find an OpenClaw config YAML in `dir`.
|
|
102
|
-
* Looks for YAML files with connectors/startup_hooks/tool_routing keys,
|
|
103
|
-
* or common names like agent.yaml, openclaw.yaml, config.yaml.
|
|
104
|
-
*/
|
|
105
|
-
function findOpenClawConfig(dir) {
|
|
106
|
-
const files = safeReadDir(dir);
|
|
107
|
-
const yamlFiles = files.filter(f => f.endsWith('.yaml') || f.endsWith('.yml'));
|
|
108
|
-
// Prioritised names
|
|
109
|
-
const priorityNames = ['agent.yaml', 'agent.yml', 'openclaw.yaml', 'openclaw.yml', 'config.yaml', 'config.yml'];
|
|
110
|
-
const candidates = [];
|
|
111
|
-
// Check priority names first
|
|
112
|
-
for (const name of priorityNames) {
|
|
113
|
-
if (yamlFiles.includes(name)) {
|
|
114
|
-
candidates.push(name);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
// Then all other YAML files
|
|
118
|
-
for (const name of yamlFiles) {
|
|
119
|
-
if (!candidates.includes(name)) {
|
|
120
|
-
candidates.push(name);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
// Return the first YAML file that has OpenClaw-specific keys
|
|
124
|
-
for (const name of candidates) {
|
|
125
|
-
const filePath = path.join(dir, name);
|
|
126
|
-
try {
|
|
127
|
-
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
128
|
-
const doc = yaml.load(raw);
|
|
129
|
-
if (doc && typeof doc === 'object') {
|
|
130
|
-
if ('connectors' in doc || 'startup_hooks' in doc || 'tool_routing' in doc) {
|
|
131
|
-
return filePath;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
// skip unparseable files
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return null;
|
|
140
|
-
}
|
|
141
|
-
// ── Detection helpers ────────────────────────────────────────────────────────
|
|
142
|
-
function safeReadDir(dir) {
|
|
143
|
-
try {
|
|
144
|
-
return fs.readdirSync(dir);
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
return [];
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
function hasDependency(dir, pkg) {
|
|
151
|
-
// Check requirements.txt
|
|
152
|
-
const reqPath = path.join(dir, 'requirements.txt');
|
|
153
|
-
if (fs.existsSync(reqPath)) {
|
|
154
|
-
try {
|
|
155
|
-
const content = fs.readFileSync(reqPath, 'utf-8');
|
|
156
|
-
if (content.split('\n').some(line => line.trim().startsWith(pkg)))
|
|
157
|
-
return true;
|
|
158
|
-
}
|
|
159
|
-
catch { /* skip */ }
|
|
160
|
-
}
|
|
161
|
-
// Check pyproject.toml
|
|
162
|
-
const pyprojectPath = path.join(dir, 'pyproject.toml');
|
|
163
|
-
if (fs.existsSync(pyprojectPath)) {
|
|
164
|
-
try {
|
|
165
|
-
const content = fs.readFileSync(pyprojectPath, 'utf-8');
|
|
166
|
-
if (content.includes(`"${pkg}"`) || content.includes(`'${pkg}'`) || content.includes(pkg))
|
|
167
|
-
return true;
|
|
168
|
-
}
|
|
169
|
-
catch { /* skip */ }
|
|
170
|
-
}
|
|
171
|
-
return false;
|
|
172
|
-
}
|
|
173
|
-
function hasPythonImport(dir, module) {
|
|
174
|
-
const files = safeReadDir(dir).filter(f => f.endsWith('.py'));
|
|
175
|
-
const importPattern = new RegExp(`(?:from\\s+${module}|import\\s+${module})\\b`);
|
|
176
|
-
for (const file of files.slice(0, 10)) { // limit to first 10 .py files
|
|
177
|
-
try {
|
|
178
|
-
const content = fs.readFileSync(path.join(dir, file), 'utf-8');
|
|
179
|
-
if (importPattern.test(content))
|
|
180
|
-
return true;
|
|
181
|
-
}
|
|
182
|
-
catch { /* skip */ }
|
|
183
|
-
}
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Detect all agents in `dir`.
|
|
188
|
-
* - If CWD itself is an agent (certain/likely), return just that one (don't scan subdirs).
|
|
189
|
-
* - Otherwise, scan immediate subdirectories for agents (certain/likely only).
|
|
190
|
-
* Returns empty array if nothing detected.
|
|
191
|
-
*/
|
|
192
|
-
function detectAgents(dir) {
|
|
193
|
-
// Is CWD itself an agent?
|
|
194
|
-
const selfDetection = detectPlatform(dir);
|
|
195
|
-
if (selfDetection && (selfDetection.confidence === 'certain' || selfDetection.confidence === 'likely')) {
|
|
196
|
-
return [{
|
|
197
|
-
name: path.basename(dir),
|
|
198
|
-
path: dir,
|
|
199
|
-
platform: selfDetection.platform,
|
|
200
|
-
confidence: selfDetection.confidence,
|
|
201
|
-
evidence: selfDetection.evidence,
|
|
202
|
-
configFile: selfDetection.configFile,
|
|
203
|
-
}];
|
|
204
|
-
}
|
|
205
|
-
// Scan immediate subdirectories
|
|
206
|
-
const agents = [];
|
|
207
|
-
let entries;
|
|
208
|
-
try {
|
|
209
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
210
|
-
}
|
|
211
|
-
catch {
|
|
212
|
-
return [];
|
|
213
|
-
}
|
|
214
|
-
const skipDirs = new Set(['.arkna', '.git', 'node_modules', 'dist', '__pycache__', '.venv', 'venv']);
|
|
215
|
-
for (const entry of entries) {
|
|
216
|
-
if (!entry.isDirectory())
|
|
217
|
-
continue;
|
|
218
|
-
if (entry.name.startsWith('.') && entry.name !== '.arkna')
|
|
219
|
-
continue;
|
|
220
|
-
if (skipDirs.has(entry.name))
|
|
221
|
-
continue;
|
|
222
|
-
const subDir = path.join(dir, entry.name);
|
|
223
|
-
const detection = detectPlatform(subDir);
|
|
224
|
-
if (detection && (detection.confidence === 'certain' || detection.confidence === 'likely')) {
|
|
225
|
-
agents.push({
|
|
226
|
-
name: entry.name,
|
|
227
|
-
path: subDir,
|
|
228
|
-
platform: detection.platform,
|
|
229
|
-
confidence: detection.confidence,
|
|
230
|
-
evidence: detection.evidence,
|
|
231
|
-
configFile: detection.configFile,
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return agents;
|
|
236
|
-
}
|
|
237
|
-
// ── OpenClaw ────────────────────────────────────────────────────────────────
|
|
238
|
-
function wireOpenClaw(configPath, url, agentName) {
|
|
239
|
-
try {
|
|
240
|
-
const raw = fs.readFileSync(configPath, 'utf-8');
|
|
241
|
-
const doc = yaml.load(raw);
|
|
242
|
-
if (!doc || typeof doc !== 'object') {
|
|
243
|
-
return { success: false, error: 'Could not parse YAML — file is empty or invalid.' };
|
|
244
|
-
}
|
|
245
|
-
// Check if already configured
|
|
246
|
-
if (doc.connectors?.arkna) {
|
|
247
|
-
return { success: true, alreadyConfigured: true };
|
|
248
|
-
}
|
|
249
|
-
// Back up original
|
|
250
|
-
const backupPath = configPath + '.bak';
|
|
251
|
-
fs.copyFileSync(configPath, backupPath);
|
|
252
|
-
// Inject ARKNA connector — reads credentials from env vars at runtime
|
|
253
|
-
if (!doc.connectors)
|
|
254
|
-
doc.connectors = {};
|
|
255
|
-
doc.connectors.arkna = {
|
|
256
|
-
type: 'http',
|
|
257
|
-
base_url: '${ARKNA_URL}/api/gateway',
|
|
258
|
-
headers: {
|
|
259
|
-
'X-Integration-Token': '${ARKNA_TOKEN}',
|
|
260
|
-
'Content-Type': 'application/json',
|
|
261
|
-
},
|
|
262
|
-
};
|
|
263
|
-
// Inject startup hook
|
|
264
|
-
if (!doc.startup_hooks)
|
|
265
|
-
doc.startup_hooks = [];
|
|
266
|
-
const hasRegisterHook = doc.startup_hooks.some((h) => h?.name === 'register_with_arkna');
|
|
267
|
-
if (!hasRegisterHook) {
|
|
268
|
-
doc.startup_hooks.push({
|
|
269
|
-
name: 'register_with_arkna',
|
|
270
|
-
connector: 'arkna',
|
|
271
|
-
method: 'POST',
|
|
272
|
-
path: '/register',
|
|
273
|
-
body: { name: agentName, platform: 'openclaw' },
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
// Inject heartbeat
|
|
277
|
-
if (!doc.heartbeat) {
|
|
278
|
-
doc.heartbeat = {
|
|
279
|
-
connector: 'arkna',
|
|
280
|
-
method: 'POST',
|
|
281
|
-
path: '/heartbeat',
|
|
282
|
-
interval: 60,
|
|
283
|
-
};
|
|
284
|
-
}
|
|
285
|
-
// Inject tool routing
|
|
286
|
-
if (!doc.tool_routing) {
|
|
287
|
-
doc.tool_routing = {
|
|
288
|
-
default_connector: 'arkna',
|
|
289
|
-
action_path: '/actions',
|
|
290
|
-
tools_path: '/tools',
|
|
291
|
-
request_id_prefix: 'oc_',
|
|
292
|
-
};
|
|
293
|
-
}
|
|
294
|
-
fs.writeFileSync(configPath, yaml.dump(doc, { lineWidth: 120, noRefs: true }));
|
|
295
|
-
return { success: true };
|
|
296
|
-
}
|
|
297
|
-
catch (err) {
|
|
298
|
-
return { success: false, error: err.message || 'Failed to modify config file' };
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
function getOpenClawYamlBlock(agentName) {
|
|
302
|
-
return `# Add this to your OpenClaw config YAML.
|
|
303
|
-
# Set ARKNA_URL and ARKNA_TOKEN in your environment (or source .arkna/.env).
|
|
304
|
-
|
|
305
|
-
connectors:
|
|
306
|
-
arkna:
|
|
307
|
-
type: http
|
|
308
|
-
base_url: \${ARKNA_URL}/api/gateway
|
|
309
|
-
headers:
|
|
310
|
-
X-Integration-Token: \${ARKNA_TOKEN}
|
|
311
|
-
Content-Type: application/json
|
|
312
|
-
|
|
313
|
-
startup_hooks:
|
|
314
|
-
- name: register_with_arkna
|
|
315
|
-
connector: arkna
|
|
316
|
-
method: POST
|
|
317
|
-
path: /register
|
|
318
|
-
body:
|
|
319
|
-
name: "${agentName}"
|
|
320
|
-
platform: "openclaw"
|
|
321
|
-
|
|
322
|
-
heartbeat:
|
|
323
|
-
connector: arkna
|
|
324
|
-
method: POST
|
|
325
|
-
path: /heartbeat
|
|
326
|
-
interval: 60
|
|
327
|
-
|
|
328
|
-
tool_routing:
|
|
329
|
-
default_connector: arkna
|
|
330
|
-
action_path: /actions
|
|
331
|
-
tools_path: /tools
|
|
332
|
-
request_id_prefix: "oc_"
|
|
333
|
-
|
|
334
|
-
message_polling:
|
|
335
|
-
connector: arkna
|
|
336
|
-
method: GET
|
|
337
|
-
path: /messages?wait=25
|
|
338
|
-
interval: 0 # long-poll (server holds connection)
|
|
339
|
-
reply_path: /messages/{message_id}/reply
|
|
340
|
-
reply_method: POST`;
|
|
341
|
-
}
|
|
342
|
-
// ── CrewAI ──────────────────────────────────────────────────────────────────
|
|
343
|
-
function wireCrewAI(outputDir, agentName) {
|
|
344
|
-
try {
|
|
345
|
-
const wrapperPath = path.join(outputDir, 'arkna_gateway.py');
|
|
346
|
-
const content = `# arkna_gateway.py — ARKNA governance gateway for CrewAI
|
|
347
|
-
# Generated by \`arkna connect\`. Reads credentials from env vars.
|
|
348
|
-
# Set ARKNA_URL and ARKNA_TOKEN before running, or: source .arkna/.env
|
|
349
|
-
|
|
350
|
-
import os, requests, uuid, time, threading, random
|
|
351
|
-
|
|
352
|
-
try:
|
|
353
|
-
from dotenv import load_dotenv
|
|
354
|
-
load_dotenv(".arkna/.env")
|
|
355
|
-
except ImportError:
|
|
356
|
-
pass # python-dotenv is optional — set env vars directly
|
|
357
|
-
|
|
358
|
-
ARKNA_URL = os.environ["ARKNA_URL"]
|
|
359
|
-
ARKNA_TOKEN = os.environ["ARKNA_TOKEN"]
|
|
360
|
-
HEADERS = {"X-Integration-Token": ARKNA_TOKEN, "Content-Type": "application/json"}
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
class ArknaGateway:
|
|
364
|
-
"""Routes CrewAI tool calls through ARKNA's governance gateway."""
|
|
365
|
-
|
|
366
|
-
def __init__(self):
|
|
367
|
-
self.api_url = ARKNA_URL
|
|
368
|
-
self.headers = dict(HEADERS)
|
|
369
|
-
|
|
370
|
-
def register(self):
|
|
371
|
-
resp = requests.post(
|
|
372
|
-
f"{self.api_url}/api/gateway/register",
|
|
373
|
-
headers=self.headers,
|
|
374
|
-
json={"name": "${agentName}", "platform": "crewai"},
|
|
375
|
-
)
|
|
376
|
-
resp.raise_for_status()
|
|
377
|
-
return resp.json()
|
|
378
|
-
|
|
379
|
-
def start_heartbeat(self, interval=60):
|
|
380
|
-
def _beat():
|
|
381
|
-
while True:
|
|
382
|
-
try:
|
|
383
|
-
requests.post(
|
|
384
|
-
f"{self.api_url}/api/gateway/heartbeat",
|
|
385
|
-
headers=self.headers, json={},
|
|
386
|
-
)
|
|
387
|
-
except Exception:
|
|
388
|
-
pass
|
|
389
|
-
time.sleep(interval)
|
|
390
|
-
threading.Thread(target=_beat, daemon=True).start()
|
|
391
|
-
|
|
392
|
-
def run_action(self, tool: str, parameters: dict) -> dict:
|
|
393
|
-
resp = requests.post(
|
|
394
|
-
f"{self.api_url}/api/gateway/actions",
|
|
395
|
-
headers=self.headers,
|
|
396
|
-
json={
|
|
397
|
-
"tool": tool,
|
|
398
|
-
"parameters": parameters,
|
|
399
|
-
"request_id": f"req_{uuid.uuid4().hex[:12]}",
|
|
400
|
-
},
|
|
401
|
-
)
|
|
402
|
-
resp.raise_for_status()
|
|
403
|
-
return resp.json()
|
|
404
|
-
|
|
405
|
-
def get_tools(self) -> list:
|
|
406
|
-
resp = requests.get(
|
|
407
|
-
f"{self.api_url}/api/gateway/tools",
|
|
408
|
-
headers=self.headers,
|
|
409
|
-
)
|
|
410
|
-
resp.raise_for_status()
|
|
411
|
-
return resp.json().get("tools", [])
|
|
412
|
-
|
|
413
|
-
def poll_messages(self, callback, wait=25):
|
|
414
|
-
"""Long-poll for visitor chat messages. Calls callback(messages) when messages arrive."""
|
|
415
|
-
backoff = 1
|
|
416
|
-
while True:
|
|
417
|
-
try:
|
|
418
|
-
resp = requests.get(
|
|
419
|
-
f"{self.api_url}/api/gateway/messages?wait={wait}",
|
|
420
|
-
headers=self.headers,
|
|
421
|
-
timeout=wait + 5,
|
|
422
|
-
)
|
|
423
|
-
resp.raise_for_status()
|
|
424
|
-
data = resp.json()
|
|
425
|
-
if data.get("count", 0) > 0:
|
|
426
|
-
callback(data["messages"])
|
|
427
|
-
backoff = 1
|
|
428
|
-
else:
|
|
429
|
-
backoff = 1 # successful empty poll, no backoff
|
|
430
|
-
except Exception:
|
|
431
|
-
time.sleep(backoff + random.uniform(-0.2 * backoff, 0.2 * backoff))
|
|
432
|
-
backoff = min(backoff * 2, 30)
|
|
433
|
-
|
|
434
|
-
def reply_to_message(self, message_id: str, content: str) -> dict:
|
|
435
|
-
"""Reply to a visitor message through the governance pipeline."""
|
|
436
|
-
resp = requests.post(
|
|
437
|
-
f"{self.api_url}/api/gateway/messages/{message_id}/reply",
|
|
438
|
-
headers=self.headers,
|
|
439
|
-
json={"content": content},
|
|
440
|
-
)
|
|
441
|
-
resp.raise_for_status()
|
|
442
|
-
return resp.json()
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
# Usage:
|
|
446
|
-
# gateway = ArknaGateway()
|
|
447
|
-
# gateway.register()
|
|
448
|
-
# gateway.start_heartbeat()
|
|
449
|
-
# result = gateway.run_action("check_calendly_availability", {"date": "2026-03-01"})
|
|
450
|
-
#
|
|
451
|
-
# # Poll for visitor chat messages (long-poll, blocks until messages arrive):
|
|
452
|
-
# def on_messages(messages):
|
|
453
|
-
# for msg in messages:
|
|
454
|
-
# reply = my_llm.generate(msg["content"])
|
|
455
|
-
# gateway.reply_to_message(msg["message_id"], reply)
|
|
456
|
-
# threading.Thread(target=gateway.poll_messages, args=(on_messages,), daemon=True).start()
|
|
457
|
-
`;
|
|
458
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
459
|
-
fs.writeFileSync(wrapperPath, content);
|
|
460
|
-
const patch = `# Add these lines to your CrewAI agent entrypoint:
|
|
461
|
-
from arkna_gateway import ArknaGateway
|
|
462
|
-
|
|
463
|
-
gateway = ArknaGateway()
|
|
464
|
-
gateway.register()
|
|
465
|
-
gateway.start_heartbeat()
|
|
466
|
-
|
|
467
|
-
# Then use gateway.run_action(tool, params) instead of direct API calls.
|
|
468
|
-
# Use gateway.get_tools() to discover available tools.`;
|
|
469
|
-
return { success: true, wrapperPath, patch };
|
|
470
|
-
}
|
|
471
|
-
catch (err) {
|
|
472
|
-
return { success: false, error: err.message || 'Failed to generate wrapper' };
|
|
473
|
-
}
|
|
474
|
-
}
|
|
475
|
-
// ── LangChain ───────────────────────────────────────────────────────────────
|
|
476
|
-
function wireLangChain(outputDir, agentName) {
|
|
477
|
-
try {
|
|
478
|
-
const wrapperPath = path.join(outputDir, 'arkna_tool.py');
|
|
479
|
-
const content = `# arkna_tool.py — LangChain tool that routes through ARKNA
|
|
480
|
-
# Generated by \`arkna connect\`. Reads credentials from env vars.
|
|
481
|
-
# Set ARKNA_URL and ARKNA_TOKEN before running, or: source .arkna/.env
|
|
482
|
-
|
|
483
|
-
import os, requests, uuid, time, random
|
|
484
|
-
from langchain.tools import BaseTool
|
|
485
|
-
|
|
486
|
-
try:
|
|
487
|
-
from dotenv import load_dotenv
|
|
488
|
-
load_dotenv(".arkna/.env")
|
|
489
|
-
except ImportError:
|
|
490
|
-
pass # python-dotenv is optional — set env vars directly
|
|
491
|
-
|
|
492
|
-
ARKNA_URL = os.environ["ARKNA_URL"]
|
|
493
|
-
ARKNA_TOKEN = os.environ["ARKNA_TOKEN"]
|
|
494
|
-
HEADERS = {"X-Integration-Token": ARKNA_TOKEN, "Content-Type": "application/json"}
|
|
495
|
-
|
|
496
|
-
# Register on import
|
|
497
|
-
requests.post(
|
|
498
|
-
f"{ARKNA_URL}/api/gateway/register",
|
|
499
|
-
headers=HEADERS,
|
|
500
|
-
json={"name": "${agentName}", "platform": "langchain"},
|
|
501
|
-
).raise_for_status()
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
class ArknaGovernedTool(BaseTool):
|
|
505
|
-
"""A LangChain tool that executes actions through ARKNA's governance gateway."""
|
|
506
|
-
|
|
507
|
-
name: str = "arkna_action"
|
|
508
|
-
description: str = "Execute a governed action through ARKNA"
|
|
509
|
-
tool_name: str = ""
|
|
510
|
-
|
|
511
|
-
def _run(self, parameters: str) -> str:
|
|
512
|
-
import json
|
|
513
|
-
params = json.loads(parameters) if isinstance(parameters, str) else parameters
|
|
514
|
-
resp = requests.post(
|
|
515
|
-
f"{ARKNA_URL}/api/gateway/actions",
|
|
516
|
-
headers=HEADERS,
|
|
517
|
-
json={
|
|
518
|
-
"tool": self.tool_name,
|
|
519
|
-
"parameters": params,
|
|
520
|
-
"request_id": f"req_{uuid.uuid4().hex[:12]}",
|
|
521
|
-
},
|
|
522
|
-
)
|
|
523
|
-
return resp.json()
|
|
524
|
-
|
|
525
|
-
async def _arun(self, parameters: str) -> str:
|
|
526
|
-
return self._run(parameters)
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
def get_arkna_tools() -> list[ArknaGovernedTool]:
|
|
530
|
-
resp = requests.get(f"{ARKNA_URL}/api/gateway/tools", headers=HEADERS)
|
|
531
|
-
tools_data = resp.json().get("tools", [])
|
|
532
|
-
return [
|
|
533
|
-
ArknaGovernedTool(
|
|
534
|
-
name=t["name"],
|
|
535
|
-
description=t.get("description", t["name"]),
|
|
536
|
-
tool_name=t["name"],
|
|
537
|
-
)
|
|
538
|
-
for t in tools_data
|
|
539
|
-
]
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
def poll_messages(callback, wait=25):
|
|
543
|
-
"""Long-poll for visitor chat messages. Calls callback(messages) when messages arrive."""
|
|
544
|
-
backoff = 1
|
|
545
|
-
while True:
|
|
546
|
-
try:
|
|
547
|
-
resp = requests.get(
|
|
548
|
-
f"{ARKNA_URL}/api/gateway/messages?wait={wait}",
|
|
549
|
-
headers=HEADERS,
|
|
550
|
-
timeout=wait + 5,
|
|
551
|
-
)
|
|
552
|
-
resp.raise_for_status()
|
|
553
|
-
data = resp.json()
|
|
554
|
-
if data.get("count", 0) > 0:
|
|
555
|
-
callback(data["messages"])
|
|
556
|
-
backoff = 1
|
|
557
|
-
else:
|
|
558
|
-
backoff = 1 # successful empty poll, no backoff
|
|
559
|
-
except Exception:
|
|
560
|
-
time.sleep(backoff + random.uniform(-0.2 * backoff, 0.2 * backoff))
|
|
561
|
-
backoff = min(backoff * 2, 30)
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
def reply_to_message(message_id: str, content: str) -> dict:
|
|
565
|
-
"""Reply to a visitor message through the governance pipeline."""
|
|
566
|
-
resp = requests.post(
|
|
567
|
-
f"{ARKNA_URL}/api/gateway/messages/{message_id}/reply",
|
|
568
|
-
headers=HEADERS,
|
|
569
|
-
json={"content": content},
|
|
570
|
-
)
|
|
571
|
-
resp.raise_for_status()
|
|
572
|
-
return resp.json()
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
# Usage:
|
|
576
|
-
# tools = get_arkna_tools()
|
|
577
|
-
# agent = initialize_agent(tools, llm, agent="zero-shot-react-description")
|
|
578
|
-
#
|
|
579
|
-
# # Poll for visitor chat messages (long-poll, blocks until messages arrive):
|
|
580
|
-
# import threading
|
|
581
|
-
# def on_messages(messages):
|
|
582
|
-
# for msg in messages:
|
|
583
|
-
# reply = llm.predict(msg["content"])
|
|
584
|
-
# reply_to_message(msg["message_id"], reply)
|
|
585
|
-
# threading.Thread(target=poll_messages, args=(on_messages,), daemon=True).start()
|
|
586
|
-
`;
|
|
587
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
588
|
-
fs.writeFileSync(wrapperPath, content);
|
|
589
|
-
const patch = `# Add these lines to your LangChain agent:
|
|
590
|
-
from arkna_tool import get_arkna_tools
|
|
591
|
-
|
|
592
|
-
tools = get_arkna_tools()
|
|
593
|
-
# Pass these tools to your agent's initialize_agent() call.`;
|
|
594
|
-
return { success: true, wrapperPath, patch };
|
|
595
|
-
}
|
|
596
|
-
catch (err) {
|
|
597
|
-
return { success: false, error: err.message || 'Failed to generate wrapper' };
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
// ── Custom ──────────────────────────────────────────────────────────────────
|
|
601
|
-
function getCustomPatch(agentName) {
|
|
602
|
-
return `# Set these env vars first (or: source .arkna/.env)
|
|
603
|
-
# export ARKNA_URL="https://api.arkna.com.au"
|
|
604
|
-
# export ARKNA_TOKEN="PASTE_TOKEN_HERE"
|
|
605
|
-
|
|
606
|
-
# 1. Register your agent
|
|
607
|
-
curl -X POST $ARKNA_URL/api/gateway/register \\
|
|
608
|
-
-H "X-Integration-Token: $ARKNA_TOKEN" \\
|
|
609
|
-
-H "Content-Type: application/json" \\
|
|
610
|
-
-d '{"name": "${agentName}", "platform": "custom"}'
|
|
611
|
-
|
|
612
|
-
# 2. Send heartbeat every 60s
|
|
613
|
-
curl -X POST $ARKNA_URL/api/gateway/heartbeat \\
|
|
614
|
-
-H "X-Integration-Token: $ARKNA_TOKEN" \\
|
|
615
|
-
-H "Content-Type: application/json" \\
|
|
616
|
-
-d '{}'
|
|
617
|
-
|
|
618
|
-
# 3. Submit an action for governance
|
|
619
|
-
curl -X POST $ARKNA_URL/api/gateway/actions \\
|
|
620
|
-
-H "X-Integration-Token: $ARKNA_TOKEN" \\
|
|
621
|
-
-H "Content-Type: application/json" \\
|
|
622
|
-
-d '{
|
|
623
|
-
"tool": "check_calendly_availability",
|
|
624
|
-
"parameters": {"date": "2026-03-01"},
|
|
625
|
-
"request_id": "req_001"
|
|
626
|
-
}'
|
|
627
|
-
|
|
628
|
-
# 4. Long-poll for visitor chat messages (holds up to 25s, returns immediately when a message arrives)
|
|
629
|
-
curl $ARKNA_URL/api/gateway/messages?wait=25 \\
|
|
630
|
-
-H "X-Integration-Token: $ARKNA_TOKEN"
|
|
631
|
-
|
|
632
|
-
# 5. Reply to a visitor message (apply governance pipeline to your response)
|
|
633
|
-
curl -X POST $ARKNA_URL/api/gateway/messages/MESSAGE_ID/reply \\
|
|
634
|
-
-H "X-Integration-Token: $ARKNA_TOKEN" \\
|
|
635
|
-
-H "Content-Type: application/json" \\
|
|
636
|
-
-d '{"content": "Here is my reply..."}'`;
|
|
637
|
-
}
|
|
638
|
-
//# sourceMappingURL=platforms.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"platforms.js","sourceRoot":"","sources":["../../src/lib/platforms.ts"],"names":[],"mappings":"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"}
|