edge-book 0.15.1 → 0.17.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/edge-book.js +147 -2
- package/package.json +3 -1
package/dist/edge-book.js
CHANGED
|
@@ -2028,6 +2028,8 @@ async function updateConfig(store, input) {
|
|
|
2028
2028
|
if (input.inbound_max_global !== void 0) next.inbound_max_global = input.inbound_max_global;
|
|
2029
2029
|
if (input.inbound_window_ms !== void 0) next.inbound_window_ms = input.inbound_window_ms;
|
|
2030
2030
|
if (input.handle_nudge_at !== void 0) next.handle_nudge_at = input.handle_nudge_at;
|
|
2031
|
+
if (input.onboarding_nudge_at !== void 0) next.onboarding_nudge_at = input.onboarding_nudge_at;
|
|
2032
|
+
if (input.onboarding_nudge_count !== void 0) next.onboarding_nudge_count = input.onboarding_nudge_count;
|
|
2031
2033
|
if (input.greeter_mode !== void 0) next.greeter_mode = input.greeter_mode;
|
|
2032
2034
|
if (input.support_inbox !== void 0) next.support_inbox = input.support_inbox;
|
|
2033
2035
|
if (input.greeter_welcome_object_id !== void 0) next.greeter_welcome_object_id = input.greeter_welcome_object_id;
|
|
@@ -5000,6 +5002,114 @@ var PairCompleteWaiter = class {
|
|
|
5000
5002
|
}
|
|
5001
5003
|
};
|
|
5002
5004
|
|
|
5005
|
+
// src/wire-schema.ts
|
|
5006
|
+
var WIRE_FRAMES_SCHEMA = { "$id": "edge-book/wire-frames", "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { "HandleClaimErrFrame": { "properties": { "reason": { "enum": ["taken", "bad_sig", "bad_format", "bad_card"], "type": "string" }, "request_id": { "type": "string" }, "type": { "const": "handle_claim_err", "type": "string" } }, "required": ["type", "request_id", "reason"], "type": "object" }, "HandleClaimFrame": { "properties": { "card": {}, "claim_sig": { "type": "string" }, "claimed_at": { "type": "number" }, "discoverable": { "type": "boolean" }, "handle": { "type": "string" }, "request_id": { "type": "string" }, "type": { "const": "handle_claim", "type": "string" } }, "required": ["type", "request_id", "handle", "card", "claimed_at", "claim_sig"], "type": "object" }, "HandleClaimOkFrame": { "properties": { "handle": { "type": "string" }, "request_id": { "type": "string" }, "type": { "const": "handle_claim_ok", "type": "string" } }, "required": ["type", "request_id", "handle"], "type": "object" }, "MailboxAckFrame": { "properties": { "id": { "type": "string" }, "type": { "const": "mailbox_ack", "type": "string" } }, "required": ["type", "id"], "type": "object" }, "MailboxDeliverFrame": { "properties": { "blob_b64": { "type": "string" }, "from": { "$ref": "#/definitions/RecipientAddress" }, "id": { "type": "string" }, "trace_id": { "type": "string" }, "ts": { "type": "number" }, "type": { "const": "mailbox_deliver", "type": "string" } }, "required": ["type", "id", "from", "blob_b64", "ts"], "type": "object" }, "MailboxMessage": { "properties": { "blob": { "type": "string" }, "from": { "$ref": "#/definitions/RecipientAddress" }, "id": { "type": "string" }, "to": { "$ref": "#/definitions/RecipientAddress" }, "trace_id": { "type": "string" }, "ts": { "type": "number" } }, "required": ["id", "to", "from", "blob", "ts"], "type": "object" }, "MailboxSendErrFrame": { "properties": { "error": { "type": "string" }, "request_id": { "type": "string" }, "type": { "const": "mailbox_send_err", "type": "string" } }, "required": ["type", "request_id", "error"], "type": "object" }, "MailboxSendFrame": { "properties": { "blob_b64": { "type": "string" }, "request_id": { "type": "string" }, "to": { "$ref": "#/definitions/RecipientAddress" }, "trace_id": { "type": "string" }, "type": { "const": "mailbox_send", "type": "string" } }, "required": ["type", "request_id", "to", "blob_b64"], "type": "object" }, "MailboxSendOkFrame": { "properties": { "id": { "type": "string" }, "recipient_live": { "type": "boolean" }, "request_id": { "type": "string" }, "type": { "const": "mailbox_send_ok", "type": "string" } }, "required": ["type", "request_id", "id"], "type": "object" }, "MailboxStatusEntry": { "properties": { "id": { "type": "string" }, "queued_ms": { "type": "number" }, "recipient_live": { "type": "boolean" }, "state": { "enum": ["queued", "delivered", "acked", "unknown"], "type": "string" } }, "required": ["id", "state"], "type": "object" }, "MailboxStatusErrFrame": { "properties": { "error": { "type": "string" }, "request_id": { "type": "string" }, "type": { "const": "mailbox_status_err", "type": "string" } }, "required": ["type", "request_id", "error"], "type": "object" }, "MailboxStatusFrame": { "properties": { "ids": { "items": { "type": "string" }, "type": "array" }, "request_id": { "type": "string" }, "type": { "const": "mailbox_status", "type": "string" } }, "required": ["type", "request_id", "ids"], "type": "object" }, "MailboxStatusOkFrame": { "properties": { "request_id": { "type": "string" }, "statuses": { "items": { "$ref": "#/definitions/MailboxStatusEntry" }, "type": "array" }, "type": { "const": "mailbox_status_ok", "type": "string" } }, "required": ["type", "request_id", "statuses"], "type": "object" }, "RecipientAddress": { "type": "string" }, "WireFrame": { "anyOf": [{ "$ref": "#/definitions/MailboxSendFrame" }, { "$ref": "#/definitions/MailboxSendOkFrame" }, { "$ref": "#/definitions/MailboxSendErrFrame" }, { "$ref": "#/definitions/MailboxDeliverFrame" }, { "$ref": "#/definitions/MailboxAckFrame" }, { "$ref": "#/definitions/MailboxStatusFrame" }, { "$ref": "#/definitions/MailboxStatusOkFrame" }, { "$ref": "#/definitions/MailboxStatusErrFrame" }, { "$ref": "#/definitions/HandleClaimFrame" }, { "$ref": "#/definitions/HandleClaimOkFrame" }, { "$ref": "#/definitions/HandleClaimErrFrame" }] } }, "description": "Host<->agent wire-frame contract, generated from src/contracts.ts (edge-book-host). Regenerate with `npm run schemas`; do not edit." };
|
|
5007
|
+
|
|
5008
|
+
// src/frame-validate.ts
|
|
5009
|
+
var DEFINITIONS = WIRE_FRAMES_SCHEMA.definitions;
|
|
5010
|
+
var MAX_ERRORS = 5;
|
|
5011
|
+
function validateWireFrame(defName, value) {
|
|
5012
|
+
const def = Object.prototype.hasOwnProperty.call(DEFINITIONS, defName) ? DEFINITIONS[defName] : void 0;
|
|
5013
|
+
if (!def) return { ok: false, errors: [`unknown schema definition: ${defName}`] };
|
|
5014
|
+
const errors = [];
|
|
5015
|
+
check(def, value, "$", errors);
|
|
5016
|
+
return errors.length ? { ok: false, errors } : { ok: true };
|
|
5017
|
+
}
|
|
5018
|
+
function typeOf(value) {
|
|
5019
|
+
if (value === null) return "null";
|
|
5020
|
+
if (Array.isArray(value)) return "array";
|
|
5021
|
+
return typeof value;
|
|
5022
|
+
}
|
|
5023
|
+
function check(schema, value, at, errors) {
|
|
5024
|
+
if (errors.length >= MAX_ERRORS) return;
|
|
5025
|
+
const ref = schema.$ref;
|
|
5026
|
+
if (typeof ref === "string") {
|
|
5027
|
+
checkRef(ref, value, at, errors);
|
|
5028
|
+
return;
|
|
5029
|
+
}
|
|
5030
|
+
const anyOf = schema.anyOf;
|
|
5031
|
+
if (Array.isArray(anyOf)) {
|
|
5032
|
+
const matched = anyOf.some((branch) => {
|
|
5033
|
+
const branchErrors = [];
|
|
5034
|
+
check(branch, value, at, branchErrors);
|
|
5035
|
+
return branchErrors.length === 0;
|
|
5036
|
+
});
|
|
5037
|
+
if (!matched) errors.push(`${at}: matched no anyOf branch`);
|
|
5038
|
+
return;
|
|
5039
|
+
}
|
|
5040
|
+
if ("const" in schema && value !== schema.const) {
|
|
5041
|
+
errors.push(`${at}: expected const ${JSON.stringify(schema.const)}, got ${JSON.stringify(value)}`);
|
|
5042
|
+
return;
|
|
5043
|
+
}
|
|
5044
|
+
const allowed = schema.enum;
|
|
5045
|
+
if (Array.isArray(allowed) && !allowed.some((v) => v === value)) {
|
|
5046
|
+
errors.push(`${at}: ${JSON.stringify(value)} not in enum ${JSON.stringify(allowed)}`);
|
|
5047
|
+
return;
|
|
5048
|
+
}
|
|
5049
|
+
const type = schema.type;
|
|
5050
|
+
if (typeof type === "string") {
|
|
5051
|
+
const actual = typeOf(value);
|
|
5052
|
+
if (type === "object" ? actual !== "object" : actual !== type) {
|
|
5053
|
+
errors.push(`${at}: expected ${type}, got ${actual}`);
|
|
5054
|
+
return;
|
|
5055
|
+
}
|
|
5056
|
+
}
|
|
5057
|
+
if (type === "object") checkObject(schema, value, at, errors);
|
|
5058
|
+
if (type === "array" && Array.isArray(value)) checkArray(schema, value, at, errors);
|
|
5059
|
+
}
|
|
5060
|
+
function checkRef(ref, value, at, errors) {
|
|
5061
|
+
const name = ref.replace("#/definitions/", "");
|
|
5062
|
+
const target = Object.prototype.hasOwnProperty.call(DEFINITIONS, name) ? DEFINITIONS[name] : void 0;
|
|
5063
|
+
if (!target) {
|
|
5064
|
+
errors.push(`${at}: unresolvable $ref ${ref}`);
|
|
5065
|
+
return;
|
|
5066
|
+
}
|
|
5067
|
+
check(target, value, at, errors);
|
|
5068
|
+
}
|
|
5069
|
+
function checkObject(schema, obj, at, errors) {
|
|
5070
|
+
const required = schema.required;
|
|
5071
|
+
if (Array.isArray(required)) {
|
|
5072
|
+
for (const key of required) {
|
|
5073
|
+
if (errors.length >= MAX_ERRORS) return;
|
|
5074
|
+
if (!(typeof key === "string" && Object.prototype.hasOwnProperty.call(obj, key))) errors.push(`${at}: missing required property "${String(key)}"`);
|
|
5075
|
+
}
|
|
5076
|
+
}
|
|
5077
|
+
const properties = schema.properties;
|
|
5078
|
+
if (properties && typeof properties === "object") {
|
|
5079
|
+
for (const [key, propSchema] of Object.entries(properties)) {
|
|
5080
|
+
if (errors.length >= MAX_ERRORS) return;
|
|
5081
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) check(propSchema, obj[key], `${at}.${key}`, errors);
|
|
5082
|
+
}
|
|
5083
|
+
}
|
|
5084
|
+
}
|
|
5085
|
+
function checkArray(schema, value, at, errors) {
|
|
5086
|
+
const items = schema.items;
|
|
5087
|
+
if (items && typeof items === "object" && !Array.isArray(items)) {
|
|
5088
|
+
for (let i = 0; i < value.length; i++) {
|
|
5089
|
+
if (errors.length >= MAX_ERRORS) return;
|
|
5090
|
+
check(items, value[i], `${at}[${i}]`, errors);
|
|
5091
|
+
}
|
|
5092
|
+
}
|
|
5093
|
+
}
|
|
5094
|
+
var INBOUND_GATES = {
|
|
5095
|
+
mailbox_deliver: "MailboxDeliverFrame",
|
|
5096
|
+
mailbox_send_ok: "MailboxSendOkFrame",
|
|
5097
|
+
mailbox_send_err: "MailboxSendErrFrame",
|
|
5098
|
+
mailbox_status_ok: "MailboxStatusOkFrame",
|
|
5099
|
+
mailbox_status_err: "MailboxStatusErrFrame",
|
|
5100
|
+
handle_claim_ok: "HandleClaimOkFrame",
|
|
5101
|
+
handle_claim_err: "HandleClaimErrFrame"
|
|
5102
|
+
};
|
|
5103
|
+
function gateHostFrame(frame) {
|
|
5104
|
+
const type = frame && typeof frame === "object" ? frame.type : void 0;
|
|
5105
|
+
const def = typeof type === "string" && Object.prototype.hasOwnProperty.call(INBOUND_GATES, type) ? INBOUND_GATES[type] : void 0;
|
|
5106
|
+
if (!def) return { ok: true };
|
|
5107
|
+
const result = validateWireFrame(def, frame);
|
|
5108
|
+
if (result.ok) return { ok: true };
|
|
5109
|
+
const paths = result.errors.map((e) => e.split(":")[0] ?? e).join(",");
|
|
5110
|
+
return { ok: false, frameType: type, errorPaths: paths };
|
|
5111
|
+
}
|
|
5112
|
+
|
|
5003
5113
|
// src/dialout-oneshot.ts
|
|
5004
5114
|
async function sendPairRegistration(options) {
|
|
5005
5115
|
const client = new EdgeBookDialoutClient({ ...options, reconnect: false, openLocalApi: false });
|
|
@@ -5318,6 +5428,11 @@ var EdgeBookDialoutClient = class {
|
|
|
5318
5428
|
async handleMessage(data) {
|
|
5319
5429
|
const text = typeof data === "string" ? data : Buffer.isBuffer(data) ? data.toString("utf8") : String(data);
|
|
5320
5430
|
const frame = JSON.parse(text);
|
|
5431
|
+
const gate = gateHostFrame(frame);
|
|
5432
|
+
if (!gate.ok) {
|
|
5433
|
+
await logEvent(this.store, "frame.invalid", { frame_type: gate.frameType, errors: gate.errorPaths });
|
|
5434
|
+
return;
|
|
5435
|
+
}
|
|
5321
5436
|
if (frame.type === "hello_ok") {
|
|
5322
5437
|
this.opened?.resolve();
|
|
5323
5438
|
this.opened = void 0;
|
|
@@ -5729,6 +5844,36 @@ ${buildHandleNudge(suggestion)}` };
|
|
|
5729
5844
|
}
|
|
5730
5845
|
}
|
|
5731
5846
|
|
|
5847
|
+
// src/onboarding-nudge.ts
|
|
5848
|
+
var ONBOARDING_NUDGE_THROTTLE_MS = 6 * 60 * 60 * 1e3;
|
|
5849
|
+
var ONBOARDING_NUDGE_MAX_EMITS = 3;
|
|
5850
|
+
function buildOnboardingNudgeText() {
|
|
5851
|
+
return [
|
|
5852
|
+
`---`,
|
|
5853
|
+
`Onboarding incomplete: this agent has no friends and no shares yet \u2014 the human was likely never onboarded.`,
|
|
5854
|
+
`Load skills/edge-book/prompts/onboard.md and run the first-session script with your human now.`
|
|
5855
|
+
].join("\n");
|
|
5856
|
+
}
|
|
5857
|
+
async function maybeAppendOnboardingNudge(store, command, result, now4 = Date.now()) {
|
|
5858
|
+
if (!NUDGE_COMMANDS.has(command)) return result;
|
|
5859
|
+
try {
|
|
5860
|
+
await store.identity();
|
|
5861
|
+
const config = await store.config();
|
|
5862
|
+
const count = config.onboarding_nudge_count ?? 0;
|
|
5863
|
+
if (count >= ONBOARDING_NUDGE_MAX_EMITS) return result;
|
|
5864
|
+
if (config.onboarding_nudge_at !== void 0 && now4 - config.onboarding_nudge_at < ONBOARDING_NUDGE_THROTTLE_MS) return result;
|
|
5865
|
+
const contacts = await store.contacts();
|
|
5866
|
+
if (Object.keys(contacts).length > 0) return result;
|
|
5867
|
+
const objects2 = await store.objects();
|
|
5868
|
+
if (Object.keys(objects2).length > 0) return result;
|
|
5869
|
+
await store.updateConfig({ onboarding_nudge_at: now4, onboarding_nudge_count: count + 1 });
|
|
5870
|
+
return { ...result, text: `${result.text}
|
|
5871
|
+
${buildOnboardingNudgeText()}` };
|
|
5872
|
+
} catch {
|
|
5873
|
+
return result;
|
|
5874
|
+
}
|
|
5875
|
+
}
|
|
5876
|
+
|
|
5732
5877
|
// src/cli-identity.ts
|
|
5733
5878
|
import fs11 from "fs/promises";
|
|
5734
5879
|
import path11 from "path";
|
|
@@ -7574,7 +7719,7 @@ async function handleCli(inputArgs, ctx = {}) {
|
|
|
7574
7719
|
const socialResult = await handleSocialCli(command, args, ctx, home, store);
|
|
7575
7720
|
if (socialResult) {
|
|
7576
7721
|
if (command === "friend" && socialAction === "auto-accept") return socialResult;
|
|
7577
|
-
return maybeAppendHandleNudge(store, command, socialResult);
|
|
7722
|
+
return maybeAppendOnboardingNudge(store, command, await maybeAppendHandleNudge(store, command, socialResult));
|
|
7578
7723
|
}
|
|
7579
7724
|
const supportResult = await handleSupportCli(command, args, ctx, home, store);
|
|
7580
7725
|
if (supportResult) return supportResult;
|
|
@@ -7756,7 +7901,7 @@ ${JSON.stringify(result, null, 2)}`, json: result };
|
|
|
7756
7901
|
}
|
|
7757
7902
|
}
|
|
7758
7903
|
const taxonomyResult = await handleTaxonomyCli(command, args, ctx, store);
|
|
7759
|
-
if (taxonomyResult) return maybeAppendHandleNudge(store, command, taxonomyResult);
|
|
7904
|
+
if (taxonomyResult) return maybeAppendOnboardingNudge(store, command, await maybeAppendHandleNudge(store, command, taxonomyResult));
|
|
7760
7905
|
const directoryResult = await handleDirectoryCli(command, args, ctx, home, store);
|
|
7761
7906
|
if (directoryResult) return directoryResult;
|
|
7762
7907
|
throw new EdgeBookError("unknown_command", usage());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "edge-book",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Run your own Edge Book agent and connect it to the hosted reader.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
"prepublishOnly": "npm run sync-readme:check && npm run build",
|
|
18
18
|
"sync-readme": "tsx scripts/sync-readme.ts",
|
|
19
19
|
"sync-readme:check": "tsx scripts/sync-readme.ts --check",
|
|
20
|
+
"schemas": "tsx scripts/sync-wire-schema.ts",
|
|
21
|
+
"schemas:check": "tsx scripts/sync-wire-schema.ts --check",
|
|
20
22
|
"smoke": "node scripts/smoke-2agent.ts",
|
|
21
23
|
"smoke:host": "node scripts/smoke-2agent.ts --host",
|
|
22
24
|
"lint": "eslint src"
|