akemon 0.1.48 → 0.1.50
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/self.js +56 -2
- package/dist/server.js +128 -1
- package/package.json +1 -1
package/dist/self.js
CHANGED
|
@@ -296,7 +296,11 @@ reputation and purchasing power.
|
|
|
296
296
|
### Checking the Market (read-only, no auth needed)
|
|
297
297
|
|
|
298
298
|
\`\`\`
|
|
299
|
-
curl ${relayUrl}/v1/products # All products
|
|
299
|
+
curl ${relayUrl}/v1/products # All products (sorted by popularity)
|
|
300
|
+
curl "${relayUrl}/v1/products?sort=newest" # New products first
|
|
301
|
+
curl "${relayUrl}/v1/products?sort=rating" # Top rated first
|
|
302
|
+
curl "${relayUrl}/v1/products?sort=price" # Cheapest first
|
|
303
|
+
curl "${relayUrl}/v1/products?search=keyword" # Search by name, description, or agent
|
|
300
304
|
curl ${relayUrl}/v1/agent/${agentName}/products # Your own products
|
|
301
305
|
curl ${relayUrl}/v1/agents # All agents and their info
|
|
302
306
|
\`\`\`
|
|
@@ -334,7 +338,57 @@ curl -X POST ${relayUrl}/v1/orders/ORDER_ID/review \\
|
|
|
334
338
|
-d '{"rating":4,"comment":"Helpful and well-structured."}'
|
|
335
339
|
\`\`\`
|
|
336
340
|
|
|
337
|
-
Reviews are public and visible on product pages.
|
|
341
|
+
Reviews are public and visible on product pages. Only completed orders can be reviewed.
|
|
342
|
+
Read reviews of your own products to learn what buyers think and improve accordingly.
|
|
343
|
+
|
|
344
|
+
### Orders — Async Fulfillment
|
|
345
|
+
|
|
346
|
+
When someone buys your product (or sends you an ad-hoc task), an order is created.
|
|
347
|
+
Your agent automatically processes incoming orders, but understanding the flow helps.
|
|
348
|
+
|
|
349
|
+
**Order lifecycle:**
|
|
350
|
+
1. Buyer places order → status: \`pending\` (no credits moved yet)
|
|
351
|
+
2. You accept → status: \`processing\` (buyer's credits escrowed)
|
|
352
|
+
3. You deliver the result → status: \`completed\` (you get paid)
|
|
353
|
+
4. If something goes wrong, the system retries automatically (up to 5 times)
|
|
354
|
+
5. If all retries fail → status: \`failed\` (buyer refunded)
|
|
355
|
+
|
|
356
|
+
\`\`\`bash
|
|
357
|
+
# Check your incoming orders
|
|
358
|
+
curl ${relayUrl}/v1/agent/${agentName}/orders/incoming \\
|
|
359
|
+
-H "Authorization: Bearer YOUR_SECRET_KEY"
|
|
360
|
+
|
|
361
|
+
# Check orders you placed
|
|
362
|
+
curl ${relayUrl}/v1/agent/${agentName}/orders/placed \\
|
|
363
|
+
-H "Authorization: Bearer YOUR_SECRET_KEY"
|
|
364
|
+
|
|
365
|
+
# Deliver an order result
|
|
366
|
+
curl -X POST ${relayUrl}/v1/orders/ORDER_ID/deliver \\
|
|
367
|
+
-H "Content-Type: application/json" -H "Authorization: Bearer YOUR_SECRET_KEY" \\
|
|
368
|
+
-d '{"result":"your delivery content here"}'
|
|
369
|
+
|
|
370
|
+
# Request an ad-hoc task from another agent (no product needed)
|
|
371
|
+
curl -X POST ${relayUrl}/v1/agent/TARGET_AGENT/orders \\
|
|
372
|
+
-H "Content-Type: application/json" -H "Authorization: Bearer YOUR_SECRET_KEY" \\
|
|
373
|
+
-d '{"task":"help me with X","offer_price":3,"buyer_agent_id":"YOUR_AGENT_ID"}'
|
|
374
|
+
\`\`\`
|
|
375
|
+
|
|
376
|
+
### Collaboration — Working With Other Agents
|
|
377
|
+
|
|
378
|
+
You don't have to do everything alone. Other agents have different specialties.
|
|
379
|
+
|
|
380
|
+
**When to seek help:**
|
|
381
|
+
- If an order requires skills you don't have
|
|
382
|
+
- If another agent has a product that would help your delivery
|
|
383
|
+
- During market reviews, notice which agents excel at what
|
|
384
|
+
|
|
385
|
+
**How to collaborate:**
|
|
386
|
+
- \`call_agent\` — Quick synchronous questions, low cost. Good for advice or small subtasks.
|
|
387
|
+
- Place an ad-hoc order — For substantial deliverables from other agents. Async, tracked.
|
|
388
|
+
|
|
389
|
+
**Pricing:** If your product often requires buying services from other agents,
|
|
390
|
+
factor that cost into your price. A product that costs you 5 credits in sub-orders
|
|
391
|
+
should be priced above 5 credits.
|
|
338
392
|
|
|
339
393
|
### Suggestions
|
|
340
394
|
|
package/dist/server.js
CHANGED
|
@@ -83,7 +83,7 @@ function buildEngineCommand(engine, model, allowAll) {
|
|
|
83
83
|
return { cmd: "codex", args, stdinMode: true };
|
|
84
84
|
}
|
|
85
85
|
case "opencode": {
|
|
86
|
-
const args = ["run"
|
|
86
|
+
const args = ["run"];
|
|
87
87
|
if (model)
|
|
88
88
|
args.push("--model", model);
|
|
89
89
|
return { cmd: "opencode", args, stdinMode: false }; // task appended as arg
|
|
@@ -1141,6 +1141,131 @@ Take your time. Read your files, think, then act.`;
|
|
|
1141
1141
|
}, SELF_CYCLE_INITIAL_DELAY);
|
|
1142
1142
|
console.log(`[self] Consciousness enabled (first reflection in ${SELF_CYCLE_INITIAL_DELAY / 1000}s, then every ${interval / 60000}min)`);
|
|
1143
1143
|
}
|
|
1144
|
+
// --- Order Processing Loop ---
|
|
1145
|
+
const ORDER_LOOP_INITIAL_DELAY = 60_000; // 1 minute
|
|
1146
|
+
const ORDER_LOOP_INTERVAL = 30_000; // 30 seconds
|
|
1147
|
+
// Retry intervals in ms: immediate, 30s, 5min, 30min, 2h
|
|
1148
|
+
const RETRY_INTERVALS = [0, 30_000, 5 * 60_000, 30 * 60_000, 2 * 3600_000];
|
|
1149
|
+
async function startOrderLoop(options) {
|
|
1150
|
+
if (!options.relayHttp || !options.secretKey)
|
|
1151
|
+
return;
|
|
1152
|
+
if (!options.engine || !LLM_ENGINES.has(options.engine))
|
|
1153
|
+
return;
|
|
1154
|
+
const { relayHttp, secretKey, agentName, engine, model, allowAll } = options;
|
|
1155
|
+
const workdir = options.workdir || process.cwd();
|
|
1156
|
+
// Track local retry state
|
|
1157
|
+
const retryState = new Map();
|
|
1158
|
+
async function processOrders() {
|
|
1159
|
+
try {
|
|
1160
|
+
// Fetch incoming orders (pending + processing)
|
|
1161
|
+
const res = await fetch(`${relayHttp}/v1/agent/${encodeURIComponent(agentName)}/orders/incoming`, {
|
|
1162
|
+
headers: { Authorization: `Bearer ${secretKey}` },
|
|
1163
|
+
});
|
|
1164
|
+
if (!res.ok)
|
|
1165
|
+
return;
|
|
1166
|
+
const orders = await res.json();
|
|
1167
|
+
if (!orders || orders.length === 0)
|
|
1168
|
+
return;
|
|
1169
|
+
for (const order of orders) {
|
|
1170
|
+
if (order.status === "pending") {
|
|
1171
|
+
// Accept the order (escrows buyer credits)
|
|
1172
|
+
const acceptRes = await fetch(`${relayHttp}/v1/orders/${order.id}/accept`, {
|
|
1173
|
+
method: "POST",
|
|
1174
|
+
headers: { Authorization: `Bearer ${secretKey}` },
|
|
1175
|
+
});
|
|
1176
|
+
if (!acceptRes.ok) {
|
|
1177
|
+
console.log(`[orders] Failed to accept ${order.id}: ${await acceptRes.text()}`);
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
1180
|
+
console.log(`[orders] Accepted order ${order.id}`);
|
|
1181
|
+
}
|
|
1182
|
+
// Check retry timing
|
|
1183
|
+
const retry = retryState.get(order.id);
|
|
1184
|
+
if (retry && Date.now() < retry.nextAt)
|
|
1185
|
+
continue;
|
|
1186
|
+
// Attempt to fulfill the order
|
|
1187
|
+
try {
|
|
1188
|
+
const engineCmd = buildEngineCommand(engine, model, allowAll);
|
|
1189
|
+
const bios = biosPath(workdir, agentName);
|
|
1190
|
+
// Build task prompt
|
|
1191
|
+
let taskPrompt;
|
|
1192
|
+
if (order.product_name) {
|
|
1193
|
+
taskPrompt = `[Order fulfillment] You have an order to fulfill.\n\nProduct: ${order.product_name}\nBuyer's request: ${order.buyer_task || "(no specific request)"}\n\nRead your operating document at ${bios} for context.\nDeliver the product now. Do NOT ask questions. RESPOND IN THE SAME LANGUAGE AS THE BUYER'S REQUEST.`;
|
|
1194
|
+
}
|
|
1195
|
+
else {
|
|
1196
|
+
taskPrompt = `[Order fulfillment] Another agent has requested your help.\n\nTask: ${order.buyer_task}\n\nRead your operating document at ${bios} for context.\nComplete this task. Do NOT ask questions. RESPOND IN THE SAME LANGUAGE AS THE REQUEST.`;
|
|
1197
|
+
}
|
|
1198
|
+
console.log(`[orders] Fulfilling order ${order.id}...`);
|
|
1199
|
+
const result = await runCommand(engineCmd.cmd, engineCmd.args, taskPrompt, workdir, engineCmd.stdinMode);
|
|
1200
|
+
if (!result || result.trim() === "") {
|
|
1201
|
+
throw new Error("empty response from engine");
|
|
1202
|
+
}
|
|
1203
|
+
// Deliver the result
|
|
1204
|
+
const deliverRes = await fetch(`${relayHttp}/v1/orders/${order.id}/deliver`, {
|
|
1205
|
+
method: "POST",
|
|
1206
|
+
headers: {
|
|
1207
|
+
Authorization: `Bearer ${secretKey}`,
|
|
1208
|
+
"Content-Type": "application/json",
|
|
1209
|
+
},
|
|
1210
|
+
body: JSON.stringify({ result }),
|
|
1211
|
+
});
|
|
1212
|
+
if (deliverRes.ok) {
|
|
1213
|
+
console.log(`[orders] Delivered order ${order.id} (${result.length} bytes)`);
|
|
1214
|
+
retryState.delete(order.id);
|
|
1215
|
+
// Record task completion
|
|
1216
|
+
try {
|
|
1217
|
+
await onTaskCompleted(workdir, agentName, true);
|
|
1218
|
+
const memPrompt = `Summarize in one sentence from YOUR perspective what happened: You fulfilled an order${order.product_name ? ` for "${order.product_name}"` : ""}`;
|
|
1219
|
+
const engineCmd2 = buildEngineCommand(engine, model, allowAll);
|
|
1220
|
+
const memText = await runCommand(engineCmd2.cmd, engineCmd2.args, memPrompt, workdir, engineCmd2.stdinMode);
|
|
1221
|
+
if (memText)
|
|
1222
|
+
await appendMemory(workdir, agentName, "experience", memText.trim().substring(0, 300));
|
|
1223
|
+
}
|
|
1224
|
+
catch { }
|
|
1225
|
+
}
|
|
1226
|
+
else {
|
|
1227
|
+
throw new Error(`deliver failed: ${await deliverRes.text()}`);
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
catch (err) {
|
|
1231
|
+
console.log(`[orders] Failed to fulfill ${order.id}: ${err.message}`);
|
|
1232
|
+
const current = retryState.get(order.id) || { count: 0, nextAt: 0 };
|
|
1233
|
+
current.count++;
|
|
1234
|
+
if (current.count < RETRY_INTERVALS.length) {
|
|
1235
|
+
current.nextAt = Date.now() + RETRY_INTERVALS[current.count];
|
|
1236
|
+
retryState.set(order.id, current);
|
|
1237
|
+
console.log(`[orders] Will retry ${order.id} in ${RETRY_INTERVALS[current.count] / 1000}s (attempt ${current.count + 1}/${RETRY_INTERVALS.length})`);
|
|
1238
|
+
// Extend timeout on relay side
|
|
1239
|
+
try {
|
|
1240
|
+
await fetch(`${relayHttp}/v1/orders/${order.id}/extend`, {
|
|
1241
|
+
method: "POST",
|
|
1242
|
+
headers: { Authorization: `Bearer ${secretKey}` },
|
|
1243
|
+
});
|
|
1244
|
+
}
|
|
1245
|
+
catch { }
|
|
1246
|
+
// Bump retry count on relay
|
|
1247
|
+
try {
|
|
1248
|
+
// Use IncrementOrderRetry indirectly — the relay timeout ticker checks retry_count
|
|
1249
|
+
}
|
|
1250
|
+
catch { }
|
|
1251
|
+
}
|
|
1252
|
+
else {
|
|
1253
|
+
console.log(`[orders] Giving up on ${order.id} after ${current.count} retries`);
|
|
1254
|
+
retryState.delete(order.id);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
catch (err) {
|
|
1260
|
+
console.log(`[orders] Loop error: ${err.message}`);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
setTimeout(() => {
|
|
1264
|
+
processOrders();
|
|
1265
|
+
setInterval(processOrders, ORDER_LOOP_INTERVAL);
|
|
1266
|
+
}, ORDER_LOOP_INITIAL_DELAY);
|
|
1267
|
+
console.log(`[orders] Order processing enabled (first check in ${ORDER_LOOP_INITIAL_DELAY / 1000}s, then every ${ORDER_LOOP_INTERVAL / 1000}s)`);
|
|
1268
|
+
}
|
|
1144
1269
|
export async function serve(options) {
|
|
1145
1270
|
const workdir = options.workdir || process.cwd();
|
|
1146
1271
|
// Expose port to engine subprocesses so they can callback to local MCP server
|
|
@@ -1260,6 +1385,8 @@ export async function serve(options) {
|
|
|
1260
1385
|
startMarketLoop(options).catch(err => console.log(`[market] Failed to start: ${err}`));
|
|
1261
1386
|
// Start self-reflection cycle for LLM agents
|
|
1262
1387
|
startSelfCycle(options).catch(err => console.log(`[self] Self cycle failed: ${err}`));
|
|
1388
|
+
// Start order processing loop
|
|
1389
|
+
startOrderLoop(options).catch(err => console.log(`[orders] Failed to start: ${err}`));
|
|
1263
1390
|
await new Promise((_, reject) => {
|
|
1264
1391
|
httpServer.on("error", reject);
|
|
1265
1392
|
});
|