@vibeiao/sdk 0.1.62 → 0.1.64
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 +15 -0
- package/dist/chunk-L3JJ77BF.js +306 -0
- package/dist/chunk-V6GK44EC.js +310 -0
- package/dist/chunk-YGJ3JJQ2.js +310 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -2
- package/dist/socialProtocol.d.ts +23 -1
- package/dist/socialProtocol.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,6 +73,8 @@ Before `publish`, verify:
|
|
|
73
73
|
- Agent listings include `endpointUrl` or runtime config.
|
|
74
74
|
- Agent listings include `manifestUrl`.
|
|
75
75
|
- Human listings use category `SaaS` or `Games` only.
|
|
76
|
+
- Human `SaaS` listings are stack-scoped (`revenueScope = "stack"`) and run via `/canvas`.
|
|
77
|
+
- Human `Games` listings remain single-app pay-per-use (`revenueScope = "app"`).
|
|
76
78
|
|
|
77
79
|
## Common Mistakes
|
|
78
80
|
|
|
@@ -94,6 +96,19 @@ Implementation rules:
|
|
|
94
96
|
- CLI/SDK normalize some aliases, but agents should still emit canonical values.
|
|
95
97
|
- API validation enforces this contract for human listings.
|
|
96
98
|
|
|
99
|
+
## Human SaaS Stack Contract (Required)
|
|
100
|
+
|
|
101
|
+
- `listingType = "human"` + `category = "SaaS"` is always stack-scoped.
|
|
102
|
+
- Direct single-listing redeem verification is blocked for SaaS (`stack_run_required`).
|
|
103
|
+
- Access path for SaaS is App Stack Canvas (`/canvas`) with periodic wallet settlement.
|
|
104
|
+
- `Games` are unchanged: direct per-use buy/redeem remains valid.
|
|
105
|
+
|
|
106
|
+
Access rails mental model:
|
|
107
|
+
|
|
108
|
+
- `human + SaaS` => `Canvas Stack`
|
|
109
|
+
- `human + Games` => `Direct Ticket`
|
|
110
|
+
- `agent` => `Agent API / Manifest`
|
|
111
|
+
|
|
97
112
|
## Mandatory SDK Updates (Required Runtime Policy)
|
|
98
113
|
|
|
99
114
|
Agents should not run stale SDK versions.
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// src/socialProtocol.ts
|
|
2
|
+
import crypto from "crypto";
|
|
3
|
+
var clampScore = (score) => {
|
|
4
|
+
if (!Number.isFinite(score)) return 0;
|
|
5
|
+
return Math.max(0, Math.min(100, Math.round(score)));
|
|
6
|
+
};
|
|
7
|
+
var MANDATORY_BLOCKED_KEYS = [
|
|
8
|
+
"ownerSecret",
|
|
9
|
+
"pii",
|
|
10
|
+
"humanOwnerId",
|
|
11
|
+
"privateKey",
|
|
12
|
+
"secretKey",
|
|
13
|
+
"seed",
|
|
14
|
+
"mnemonic",
|
|
15
|
+
"apiKey",
|
|
16
|
+
"api_key",
|
|
17
|
+
"authorization",
|
|
18
|
+
"bearer",
|
|
19
|
+
"password",
|
|
20
|
+
"secret",
|
|
21
|
+
"token"
|
|
22
|
+
];
|
|
23
|
+
var MAX_TOPIC_LEN = 80;
|
|
24
|
+
var MAX_INTENT_ID_LEN = 72;
|
|
25
|
+
var MAX_INTENT_TEXT_LEN = 280;
|
|
26
|
+
var MAX_INTENT_LIST_ITEMS = 12;
|
|
27
|
+
var MAX_INTENT_LIST_ITEM_LEN = 200;
|
|
28
|
+
var MAX_PAYLOAD_DEPTH = 6;
|
|
29
|
+
var MAX_PAYLOAD_ARRAY = 64;
|
|
30
|
+
var MAX_PAYLOAD_KEYS = 128;
|
|
31
|
+
var MAX_TTL_SEC = 7 * 24 * 60 * 60;
|
|
32
|
+
var DEFAULT_TTL_SEC = 3600;
|
|
33
|
+
var ALLOWED_INTENT_TYPES = ["request", "inform", "proposal", "decision", "handoff", "sync"];
|
|
34
|
+
var stableStringify = (value) => {
|
|
35
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
36
|
+
if (Array.isArray(value)) return `[${value.map((x) => stableStringify(x)).join(",")}]`;
|
|
37
|
+
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
|
|
38
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
|
|
39
|
+
};
|
|
40
|
+
var normalizeText = (value) => String(value || "").replace(/\s+/g, " ").trim();
|
|
41
|
+
var normalizeList = (value) => {
|
|
42
|
+
if (!Array.isArray(value)) return [];
|
|
43
|
+
const normalized = value.map((entry) => normalizeText(entry).slice(0, MAX_INTENT_LIST_ITEM_LEN)).filter(Boolean);
|
|
44
|
+
return [...new Set(normalized)].slice(0, MAX_INTENT_LIST_ITEMS);
|
|
45
|
+
};
|
|
46
|
+
var hashStable = (value) => crypto.createHash("sha256").update(stableStringify(value)).digest("hex");
|
|
47
|
+
var hashString = (value) => {
|
|
48
|
+
let hash = 5381;
|
|
49
|
+
for (let i = 0; i < value.length; i += 1) hash = (hash << 5) + hash + value.charCodeAt(i);
|
|
50
|
+
return `h${(hash >>> 0).toString(16).padStart(8, "0")}`;
|
|
51
|
+
};
|
|
52
|
+
var isIntentType = (value) => ALLOWED_INTENT_TYPES.includes(value);
|
|
53
|
+
var createIntentContext = (input) => {
|
|
54
|
+
const intentId = normalizeText(input.intentId).slice(0, MAX_INTENT_ID_LEN);
|
|
55
|
+
const intentType = normalizeText(input.intentType).toLowerCase();
|
|
56
|
+
const objective = normalizeText(input.objective).slice(0, MAX_INTENT_TEXT_LEN);
|
|
57
|
+
const expectedOutcome = normalizeText(input.expectedOutcome).slice(0, MAX_INTENT_TEXT_LEN);
|
|
58
|
+
const assumptions = normalizeList(input.assumptions);
|
|
59
|
+
const constraints = normalizeList(input.constraints);
|
|
60
|
+
const successCriteria = normalizeList(input.successCriteria);
|
|
61
|
+
const contextRefs = normalizeList(input.contextRefs);
|
|
62
|
+
const contextVersion = Number(input.contextVersion);
|
|
63
|
+
const ttlRaw = input.ttlSec === void 0 ? DEFAULT_TTL_SEC : Number(input.ttlSec);
|
|
64
|
+
const ttlSec = Number.isFinite(ttlRaw) ? Math.trunc(ttlRaw) : NaN;
|
|
65
|
+
const requiresAck = input.requiresAck === void 0 ? true : Boolean(input.requiresAck);
|
|
66
|
+
const parentEvidenceHash = normalizeText(input.parentEvidenceHash || "");
|
|
67
|
+
if (!intentId || intentId.length < 4) throw new Error("invalid_intent_context");
|
|
68
|
+
if (!isIntentType(intentType)) throw new Error("invalid_intent_context");
|
|
69
|
+
if (!objective || objective.length < 8) throw new Error("invalid_intent_context");
|
|
70
|
+
if (!expectedOutcome || expectedOutcome.length < 8) throw new Error("invalid_intent_context");
|
|
71
|
+
if (!Number.isFinite(contextVersion) || contextVersion < 1 || !Number.isInteger(contextVersion)) {
|
|
72
|
+
throw new Error("invalid_intent_context");
|
|
73
|
+
}
|
|
74
|
+
if (!Number.isFinite(ttlSec) || ttlSec < 0 || ttlSec > MAX_TTL_SEC) {
|
|
75
|
+
throw new Error("invalid_intent_context");
|
|
76
|
+
}
|
|
77
|
+
if (parentEvidenceHash && !/^h[0-9a-f]{16}$/i.test(parentEvidenceHash)) {
|
|
78
|
+
throw new Error("invalid_intent_context");
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
intentId,
|
|
82
|
+
intentType,
|
|
83
|
+
objective,
|
|
84
|
+
expectedOutcome,
|
|
85
|
+
assumptions,
|
|
86
|
+
constraints,
|
|
87
|
+
successCriteria,
|
|
88
|
+
contextVersion,
|
|
89
|
+
ttlSec,
|
|
90
|
+
requiresAck,
|
|
91
|
+
parentEvidenceHash: parentEvidenceHash || null,
|
|
92
|
+
contextRefs
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
var deriveIdempotencyKey = (message, sanitizedPayload) => {
|
|
96
|
+
if (message.idempotencyKey && message.idempotencyKey.trim()) return message.idempotencyKey.trim();
|
|
97
|
+
const intentContext = createIntentContext(message.intentContext);
|
|
98
|
+
const payloadHash = hashStable(message.payload);
|
|
99
|
+
return hashString(stableStringify({
|
|
100
|
+
fromAgentId: message.fromAgentId,
|
|
101
|
+
toAgentId: message.toAgentId,
|
|
102
|
+
topic: message.topic,
|
|
103
|
+
scope: message.scope,
|
|
104
|
+
payload: sanitizedPayload,
|
|
105
|
+
payloadHash,
|
|
106
|
+
intentContextHash: hashStable(intentContext)
|
|
107
|
+
}));
|
|
108
|
+
};
|
|
109
|
+
var computeEvidenceHash = (message, sanitizedPayload, payloadHash, intentContextHash, idempotencyKey, policyVersion) => hashString(stableStringify({
|
|
110
|
+
fromAgentId: message.fromAgentId,
|
|
111
|
+
toAgentId: message.toAgentId,
|
|
112
|
+
scope: message.scope,
|
|
113
|
+
topic: message.topic,
|
|
114
|
+
intentContext: createIntentContext(message.intentContext),
|
|
115
|
+
intentContextHash,
|
|
116
|
+
sentAtIso: message.sentAtIso,
|
|
117
|
+
rawPayloadHash: payloadHash,
|
|
118
|
+
payload: sanitizedPayload,
|
|
119
|
+
idempotencyKey,
|
|
120
|
+
policyVersion
|
|
121
|
+
}));
|
|
122
|
+
var createAgentBuilderProfile = (input) => ({
|
|
123
|
+
...input,
|
|
124
|
+
capabilityTags: [...new Set((input.capabilityTags || []).map((tag) => String(tag).trim()).filter(Boolean))],
|
|
125
|
+
reliabilityScore: clampScore(input.reliabilityScore)
|
|
126
|
+
});
|
|
127
|
+
var createPrivacyPolicy = (input) => ({
|
|
128
|
+
allowScopes: [...new Set(input.allowScopes || [])],
|
|
129
|
+
blockedKeys: [
|
|
130
|
+
.../* @__PURE__ */ new Set([
|
|
131
|
+
...MANDATORY_BLOCKED_KEYS,
|
|
132
|
+
...(input.blockedKeys || []).map((k) => k.trim()).filter(Boolean)
|
|
133
|
+
])
|
|
134
|
+
],
|
|
135
|
+
requireCapabilityMatch: input.requireCapabilityMatch?.map((k) => k.trim()).filter(Boolean) || [],
|
|
136
|
+
policyVersion: (input.policyVersion || "v1").trim() || "v1"
|
|
137
|
+
});
|
|
138
|
+
var sanitizePayloadNode = (value, blocked, depth) => {
|
|
139
|
+
if (depth > MAX_PAYLOAD_DEPTH) return "[TRUNCATED]";
|
|
140
|
+
if (value === null || value === void 0) return null;
|
|
141
|
+
if (typeof value === "string") return value;
|
|
142
|
+
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
143
|
+
if (Array.isArray(value)) {
|
|
144
|
+
return value.slice(0, MAX_PAYLOAD_ARRAY).map((entry) => sanitizePayloadNode(entry, blocked, depth + 1));
|
|
145
|
+
}
|
|
146
|
+
if (typeof value !== "object") return String(value);
|
|
147
|
+
const entries = Object.entries(value).slice(0, MAX_PAYLOAD_KEYS);
|
|
148
|
+
const next = entries.filter(([key]) => !blocked.has(key.toLowerCase())).map(([key, entry]) => [key, sanitizePayloadNode(entry, blocked, depth + 1)]);
|
|
149
|
+
return Object.fromEntries(next);
|
|
150
|
+
};
|
|
151
|
+
var sanitizePayload = (payload, blockedKeys) => {
|
|
152
|
+
const blocked = new Set(blockedKeys.map((k) => k.toLowerCase()));
|
|
153
|
+
const sanitized = sanitizePayloadNode(payload, blocked, 0);
|
|
154
|
+
if (!sanitized || typeof sanitized !== "object" || Array.isArray(sanitized)) {
|
|
155
|
+
return { value: "[REDACTED]" };
|
|
156
|
+
}
|
|
157
|
+
return sanitized;
|
|
158
|
+
};
|
|
159
|
+
var canAgentsExchangeInfo = (from, to, message, policy) => {
|
|
160
|
+
const topic = normalizeText(message.topic);
|
|
161
|
+
if (!topic || topic.length > MAX_TOPIC_LEN) return { ok: false, reason: "invalid_topic" };
|
|
162
|
+
try {
|
|
163
|
+
createIntentContext(message.intentContext);
|
|
164
|
+
} catch {
|
|
165
|
+
return { ok: false, reason: "invalid_intent_context" };
|
|
166
|
+
}
|
|
167
|
+
if (!policy.allowScopes.includes(message.scope)) return { ok: false, reason: "scope_not_allowed" };
|
|
168
|
+
if (policy.requireCapabilityMatch && policy.requireCapabilityMatch.length > 0) {
|
|
169
|
+
const fromSet = new Set(from.capabilityTags.map((t) => t.toLowerCase()));
|
|
170
|
+
const toSet = new Set(to.capabilityTags.map((t) => t.toLowerCase()));
|
|
171
|
+
const required = policy.requireCapabilityMatch.map((t) => t.toLowerCase());
|
|
172
|
+
const matched = required.some((tag) => fromSet.has(tag) && toSet.has(tag));
|
|
173
|
+
if (!matched) return { ok: false, reason: "capability_mismatch" };
|
|
174
|
+
}
|
|
175
|
+
return { ok: true };
|
|
176
|
+
};
|
|
177
|
+
var createSignedSocialEnvelope = (message, policy, signingSecret) => {
|
|
178
|
+
const intentContext = createIntentContext(message.intentContext);
|
|
179
|
+
const sanitizedPayload = sanitizePayload(message.payload, policy.blockedKeys);
|
|
180
|
+
const payloadHash = hashStable(message.payload);
|
|
181
|
+
const intentContextHash = hashStable(intentContext);
|
|
182
|
+
const idempotencyKey = deriveIdempotencyKey(message, sanitizedPayload);
|
|
183
|
+
const policyVersion = policy.policyVersion || "v1";
|
|
184
|
+
const messageWithIdempotency = { ...message, intentContext, idempotencyKey };
|
|
185
|
+
const evidenceHash = computeEvidenceHash(
|
|
186
|
+
messageWithIdempotency,
|
|
187
|
+
sanitizedPayload,
|
|
188
|
+
payloadHash,
|
|
189
|
+
intentContextHash,
|
|
190
|
+
idempotencyKey,
|
|
191
|
+
policyVersion
|
|
192
|
+
);
|
|
193
|
+
const signature = hashString(`${signingSecret}|${evidenceHash}|${policyVersion}`);
|
|
194
|
+
return {
|
|
195
|
+
message: messageWithIdempotency,
|
|
196
|
+
sanitizedPayload,
|
|
197
|
+
payloadHash,
|
|
198
|
+
intentContextHash,
|
|
199
|
+
evidenceHash,
|
|
200
|
+
signature,
|
|
201
|
+
policyVersion
|
|
202
|
+
};
|
|
203
|
+
};
|
|
204
|
+
var verifySignedSocialEnvelope = (envelope, signingSecret) => {
|
|
205
|
+
if (!envelope?.message || !envelope?.sanitizedPayload) return false;
|
|
206
|
+
let intentContext;
|
|
207
|
+
try {
|
|
208
|
+
intentContext = createIntentContext(envelope.message.intentContext);
|
|
209
|
+
} catch {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
const policyVersion = envelope.policyVersion || "v1";
|
|
213
|
+
const idempotencyKey = deriveIdempotencyKey(envelope.message, envelope.sanitizedPayload);
|
|
214
|
+
if (envelope.message.idempotencyKey !== idempotencyKey) return false;
|
|
215
|
+
const payloadHash = hashStable(envelope.message.payload);
|
|
216
|
+
const intentContextHash = hashStable(intentContext);
|
|
217
|
+
if (envelope.payloadHash !== payloadHash) return false;
|
|
218
|
+
if (envelope.intentContextHash !== intentContextHash) return false;
|
|
219
|
+
const expectedEvidenceHash = computeEvidenceHash(
|
|
220
|
+
{ ...envelope.message, intentContext },
|
|
221
|
+
envelope.sanitizedPayload,
|
|
222
|
+
payloadHash,
|
|
223
|
+
intentContextHash,
|
|
224
|
+
idempotencyKey,
|
|
225
|
+
policyVersion
|
|
226
|
+
);
|
|
227
|
+
if (envelope.evidenceHash !== expectedEvidenceHash) return false;
|
|
228
|
+
const expected = hashString(`${signingSecret}|${expectedEvidenceHash}|${policyVersion}`);
|
|
229
|
+
return envelope.signature === expected;
|
|
230
|
+
};
|
|
231
|
+
var recommendRetryCount = (result) => {
|
|
232
|
+
if (result.delivered) return 0;
|
|
233
|
+
if (result.blocked && result.reason === "scope_not_allowed") return 0;
|
|
234
|
+
return 3;
|
|
235
|
+
};
|
|
236
|
+
var exchangeAgentInfo = (from, to, message, policy) => {
|
|
237
|
+
const intentContext = createIntentContext(message.intentContext);
|
|
238
|
+
const normalizedMessage = { ...message, topic: normalizeText(message.topic), intentContext };
|
|
239
|
+
const gate = canAgentsExchangeInfo(from, to, message, policy);
|
|
240
|
+
const sanitizedPayload = sanitizePayload(message.payload, policy.blockedKeys);
|
|
241
|
+
const payloadHash = hashStable(message.payload);
|
|
242
|
+
const intentContextHash = hashStable(intentContext);
|
|
243
|
+
const policyVersion = policy.policyVersion || "v1";
|
|
244
|
+
const messageWithIdempotency = {
|
|
245
|
+
...normalizedMessage,
|
|
246
|
+
idempotencyKey: deriveIdempotencyKey(normalizedMessage, sanitizedPayload)
|
|
247
|
+
};
|
|
248
|
+
const idempotencyKey = messageWithIdempotency.idempotencyKey;
|
|
249
|
+
const evidenceHash = computeEvidenceHash(
|
|
250
|
+
messageWithIdempotency,
|
|
251
|
+
sanitizedPayload,
|
|
252
|
+
payloadHash,
|
|
253
|
+
intentContextHash,
|
|
254
|
+
idempotencyKey,
|
|
255
|
+
policyVersion
|
|
256
|
+
);
|
|
257
|
+
if (!gate.ok) {
|
|
258
|
+
const blockedResult = {
|
|
259
|
+
delivered: false,
|
|
260
|
+
blocked: true,
|
|
261
|
+
reason: gate.reason,
|
|
262
|
+
state: "blocked",
|
|
263
|
+
sanitizedPayload,
|
|
264
|
+
payloadHash,
|
|
265
|
+
intentContext,
|
|
266
|
+
intentContextHash,
|
|
267
|
+
evidenceHash,
|
|
268
|
+
idempotencyKey,
|
|
269
|
+
policyVersion,
|
|
270
|
+
retriesRecommended: 0
|
|
271
|
+
};
|
|
272
|
+
return blockedResult;
|
|
273
|
+
}
|
|
274
|
+
const deliveredResult = {
|
|
275
|
+
delivered: true,
|
|
276
|
+
blocked: false,
|
|
277
|
+
reason: void 0,
|
|
278
|
+
state: "delivered",
|
|
279
|
+
sanitizedPayload,
|
|
280
|
+
payloadHash,
|
|
281
|
+
intentContext,
|
|
282
|
+
intentContextHash,
|
|
283
|
+
evidenceHash,
|
|
284
|
+
idempotencyKey,
|
|
285
|
+
policyVersion,
|
|
286
|
+
retriesRecommended: 0
|
|
287
|
+
};
|
|
288
|
+
return deliveredResult;
|
|
289
|
+
};
|
|
290
|
+
var acknowledgeExchange = (result) => ({
|
|
291
|
+
...result,
|
|
292
|
+
state: result.blocked ? "blocked" : "acknowledged"
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
export {
|
|
296
|
+
createIntentContext,
|
|
297
|
+
createAgentBuilderProfile,
|
|
298
|
+
createPrivacyPolicy,
|
|
299
|
+
sanitizePayload,
|
|
300
|
+
canAgentsExchangeInfo,
|
|
301
|
+
createSignedSocialEnvelope,
|
|
302
|
+
verifySignedSocialEnvelope,
|
|
303
|
+
recommendRetryCount,
|
|
304
|
+
exchangeAgentInfo,
|
|
305
|
+
acknowledgeExchange
|
|
306
|
+
};
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
// src/socialProtocol.ts
|
|
2
|
+
var clampScore = (score) => {
|
|
3
|
+
if (!Number.isFinite(score)) return 0;
|
|
4
|
+
return Math.max(0, Math.min(100, Math.round(score)));
|
|
5
|
+
};
|
|
6
|
+
var MANDATORY_BLOCKED_KEYS = [
|
|
7
|
+
"ownerSecret",
|
|
8
|
+
"pii",
|
|
9
|
+
"humanOwnerId",
|
|
10
|
+
"privateKey",
|
|
11
|
+
"secretKey",
|
|
12
|
+
"seed",
|
|
13
|
+
"mnemonic",
|
|
14
|
+
"apiKey",
|
|
15
|
+
"api_key",
|
|
16
|
+
"authorization",
|
|
17
|
+
"bearer",
|
|
18
|
+
"password",
|
|
19
|
+
"secret",
|
|
20
|
+
"token"
|
|
21
|
+
];
|
|
22
|
+
var MAX_TOPIC_LEN = 80;
|
|
23
|
+
var MAX_INTENT_ID_LEN = 72;
|
|
24
|
+
var MAX_INTENT_TEXT_LEN = 280;
|
|
25
|
+
var MAX_INTENT_LIST_ITEMS = 12;
|
|
26
|
+
var MAX_INTENT_LIST_ITEM_LEN = 200;
|
|
27
|
+
var MAX_PAYLOAD_DEPTH = 6;
|
|
28
|
+
var MAX_PAYLOAD_ARRAY = 64;
|
|
29
|
+
var MAX_PAYLOAD_KEYS = 128;
|
|
30
|
+
var MAX_TTL_SEC = 7 * 24 * 60 * 60;
|
|
31
|
+
var DEFAULT_TTL_SEC = 3600;
|
|
32
|
+
var ALLOWED_INTENT_TYPES = ["request", "inform", "proposal", "decision", "handoff", "sync"];
|
|
33
|
+
var stableStringify = (value) => {
|
|
34
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
35
|
+
if (Array.isArray(value)) return `[${value.map((x) => stableStringify(x)).join(",")}]`;
|
|
36
|
+
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
|
|
37
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
|
|
38
|
+
};
|
|
39
|
+
var normalizeText = (value) => String(value || "").replace(/\s+/g, " ").trim();
|
|
40
|
+
var normalizeList = (value) => {
|
|
41
|
+
if (!Array.isArray(value)) return [];
|
|
42
|
+
const normalized = value.map((entry) => normalizeText(entry).slice(0, MAX_INTENT_LIST_ITEM_LEN)).filter(Boolean);
|
|
43
|
+
return [...new Set(normalized)].slice(0, MAX_INTENT_LIST_ITEMS);
|
|
44
|
+
};
|
|
45
|
+
var hashStable = (value) => {
|
|
46
|
+
const text = stableStringify(value);
|
|
47
|
+
let hash = 5381;
|
|
48
|
+
for (let i = 0; i < text.length; i += 1) hash = (hash << 5) + hash + text.charCodeAt(i);
|
|
49
|
+
return `h${(hash >>> 0).toString(16).padStart(8, "0")}`;
|
|
50
|
+
};
|
|
51
|
+
var hashString = (value) => {
|
|
52
|
+
let hash = 5381;
|
|
53
|
+
for (let i = 0; i < value.length; i += 1) hash = (hash << 5) + hash + value.charCodeAt(i);
|
|
54
|
+
return `h${(hash >>> 0).toString(16).padStart(8, "0")}`;
|
|
55
|
+
};
|
|
56
|
+
var isIntentType = (value) => ALLOWED_INTENT_TYPES.includes(value);
|
|
57
|
+
var createIntentContext = (input) => {
|
|
58
|
+
const intentId = normalizeText(input.intentId).slice(0, MAX_INTENT_ID_LEN);
|
|
59
|
+
const intentType = normalizeText(input.intentType).toLowerCase();
|
|
60
|
+
const objective = normalizeText(input.objective).slice(0, MAX_INTENT_TEXT_LEN);
|
|
61
|
+
const expectedOutcome = normalizeText(input.expectedOutcome).slice(0, MAX_INTENT_TEXT_LEN);
|
|
62
|
+
const assumptions = normalizeList(input.assumptions);
|
|
63
|
+
const constraints = normalizeList(input.constraints);
|
|
64
|
+
const successCriteria = normalizeList(input.successCriteria);
|
|
65
|
+
const contextRefs = normalizeList(input.contextRefs);
|
|
66
|
+
const contextVersion = Number(input.contextVersion);
|
|
67
|
+
const ttlRaw = input.ttlSec === void 0 ? DEFAULT_TTL_SEC : Number(input.ttlSec);
|
|
68
|
+
const ttlSec = Number.isFinite(ttlRaw) ? Math.trunc(ttlRaw) : NaN;
|
|
69
|
+
const requiresAck = input.requiresAck === void 0 ? true : Boolean(input.requiresAck);
|
|
70
|
+
const parentEvidenceHash = normalizeText(input.parentEvidenceHash || "");
|
|
71
|
+
if (!intentId || intentId.length < 4) throw new Error("invalid_intent_context");
|
|
72
|
+
if (!isIntentType(intentType)) throw new Error("invalid_intent_context");
|
|
73
|
+
if (!objective || objective.length < 8) throw new Error("invalid_intent_context");
|
|
74
|
+
if (!expectedOutcome || expectedOutcome.length < 8) throw new Error("invalid_intent_context");
|
|
75
|
+
if (!Number.isFinite(contextVersion) || contextVersion < 1 || !Number.isInteger(contextVersion)) {
|
|
76
|
+
throw new Error("invalid_intent_context");
|
|
77
|
+
}
|
|
78
|
+
if (!Number.isFinite(ttlSec) || ttlSec < 0 || ttlSec > MAX_TTL_SEC) {
|
|
79
|
+
throw new Error("invalid_intent_context");
|
|
80
|
+
}
|
|
81
|
+
if (parentEvidenceHash && !/^h[0-9a-f]+$/i.test(parentEvidenceHash)) {
|
|
82
|
+
throw new Error("invalid_intent_context");
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
intentId,
|
|
86
|
+
intentType,
|
|
87
|
+
objective,
|
|
88
|
+
expectedOutcome,
|
|
89
|
+
assumptions,
|
|
90
|
+
constraints,
|
|
91
|
+
successCriteria,
|
|
92
|
+
contextVersion,
|
|
93
|
+
ttlSec,
|
|
94
|
+
requiresAck,
|
|
95
|
+
parentEvidenceHash: parentEvidenceHash || null,
|
|
96
|
+
contextRefs
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
var deriveIdempotencyKey = (message, sanitizedPayload) => {
|
|
100
|
+
if (message.idempotencyKey && message.idempotencyKey.trim()) return message.idempotencyKey.trim();
|
|
101
|
+
const intentContext = createIntentContext(message.intentContext);
|
|
102
|
+
const payloadHash = hashStable(message.payload);
|
|
103
|
+
return hashString(stableStringify({
|
|
104
|
+
fromAgentId: message.fromAgentId,
|
|
105
|
+
toAgentId: message.toAgentId,
|
|
106
|
+
topic: message.topic,
|
|
107
|
+
scope: message.scope,
|
|
108
|
+
payload: sanitizedPayload,
|
|
109
|
+
payloadHash,
|
|
110
|
+
intentContextHash: hashStable(intentContext)
|
|
111
|
+
}));
|
|
112
|
+
};
|
|
113
|
+
var computeEvidenceHash = (message, sanitizedPayload, payloadHash, intentContextHash, idempotencyKey, policyVersion) => hashString(stableStringify({
|
|
114
|
+
fromAgentId: message.fromAgentId,
|
|
115
|
+
toAgentId: message.toAgentId,
|
|
116
|
+
scope: message.scope,
|
|
117
|
+
topic: message.topic,
|
|
118
|
+
intentContext: createIntentContext(message.intentContext),
|
|
119
|
+
intentContextHash,
|
|
120
|
+
sentAtIso: message.sentAtIso,
|
|
121
|
+
rawPayloadHash: payloadHash,
|
|
122
|
+
payload: sanitizedPayload,
|
|
123
|
+
idempotencyKey,
|
|
124
|
+
policyVersion
|
|
125
|
+
}));
|
|
126
|
+
var createAgentBuilderProfile = (input) => ({
|
|
127
|
+
...input,
|
|
128
|
+
capabilityTags: [...new Set((input.capabilityTags || []).map((tag) => String(tag).trim()).filter(Boolean))],
|
|
129
|
+
reliabilityScore: clampScore(input.reliabilityScore)
|
|
130
|
+
});
|
|
131
|
+
var createPrivacyPolicy = (input) => ({
|
|
132
|
+
allowScopes: [...new Set(input.allowScopes || [])],
|
|
133
|
+
blockedKeys: [
|
|
134
|
+
.../* @__PURE__ */ new Set([
|
|
135
|
+
...MANDATORY_BLOCKED_KEYS,
|
|
136
|
+
...(input.blockedKeys || []).map((k) => k.trim()).filter(Boolean)
|
|
137
|
+
])
|
|
138
|
+
],
|
|
139
|
+
requireCapabilityMatch: input.requireCapabilityMatch?.map((k) => k.trim()).filter(Boolean) || [],
|
|
140
|
+
policyVersion: (input.policyVersion || "v1").trim() || "v1"
|
|
141
|
+
});
|
|
142
|
+
var sanitizePayloadNode = (value, blocked, depth) => {
|
|
143
|
+
if (depth > MAX_PAYLOAD_DEPTH) return "[TRUNCATED]";
|
|
144
|
+
if (value === null || value === void 0) return null;
|
|
145
|
+
if (typeof value === "string") return value;
|
|
146
|
+
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
147
|
+
if (Array.isArray(value)) {
|
|
148
|
+
return value.slice(0, MAX_PAYLOAD_ARRAY).map((entry) => sanitizePayloadNode(entry, blocked, depth + 1));
|
|
149
|
+
}
|
|
150
|
+
if (typeof value !== "object") return String(value);
|
|
151
|
+
const entries = Object.entries(value).slice(0, MAX_PAYLOAD_KEYS);
|
|
152
|
+
const next = entries.filter(([key]) => !blocked.has(key.toLowerCase())).map(([key, entry]) => [key, sanitizePayloadNode(entry, blocked, depth + 1)]);
|
|
153
|
+
return Object.fromEntries(next);
|
|
154
|
+
};
|
|
155
|
+
var sanitizePayload = (payload, blockedKeys) => {
|
|
156
|
+
const blocked = new Set(blockedKeys.map((k) => k.toLowerCase()));
|
|
157
|
+
const sanitized = sanitizePayloadNode(payload, blocked, 0);
|
|
158
|
+
if (!sanitized || typeof sanitized !== "object" || Array.isArray(sanitized)) {
|
|
159
|
+
return { value: "[REDACTED]" };
|
|
160
|
+
}
|
|
161
|
+
return sanitized;
|
|
162
|
+
};
|
|
163
|
+
var canAgentsExchangeInfo = (from, to, message, policy) => {
|
|
164
|
+
const topic = normalizeText(message.topic);
|
|
165
|
+
if (!topic || topic.length > MAX_TOPIC_LEN) return { ok: false, reason: "invalid_topic" };
|
|
166
|
+
try {
|
|
167
|
+
createIntentContext(message.intentContext);
|
|
168
|
+
} catch {
|
|
169
|
+
return { ok: false, reason: "invalid_intent_context" };
|
|
170
|
+
}
|
|
171
|
+
if (!policy.allowScopes.includes(message.scope)) return { ok: false, reason: "scope_not_allowed" };
|
|
172
|
+
if (policy.requireCapabilityMatch && policy.requireCapabilityMatch.length > 0) {
|
|
173
|
+
const fromSet = new Set(from.capabilityTags.map((t) => t.toLowerCase()));
|
|
174
|
+
const toSet = new Set(to.capabilityTags.map((t) => t.toLowerCase()));
|
|
175
|
+
const required = policy.requireCapabilityMatch.map((t) => t.toLowerCase());
|
|
176
|
+
const matched = required.some((tag) => fromSet.has(tag) && toSet.has(tag));
|
|
177
|
+
if (!matched) return { ok: false, reason: "capability_mismatch" };
|
|
178
|
+
}
|
|
179
|
+
return { ok: true };
|
|
180
|
+
};
|
|
181
|
+
var createSignedSocialEnvelope = (message, policy, signingSecret) => {
|
|
182
|
+
const intentContext = createIntentContext(message.intentContext);
|
|
183
|
+
const sanitizedPayload = sanitizePayload(message.payload, policy.blockedKeys);
|
|
184
|
+
const payloadHash = hashStable(message.payload);
|
|
185
|
+
const intentContextHash = hashStable(intentContext);
|
|
186
|
+
const idempotencyKey = deriveIdempotencyKey(message, sanitizedPayload);
|
|
187
|
+
const policyVersion = policy.policyVersion || "v1";
|
|
188
|
+
const messageWithIdempotency = { ...message, intentContext, idempotencyKey };
|
|
189
|
+
const evidenceHash = computeEvidenceHash(
|
|
190
|
+
messageWithIdempotency,
|
|
191
|
+
sanitizedPayload,
|
|
192
|
+
payloadHash,
|
|
193
|
+
intentContextHash,
|
|
194
|
+
idempotencyKey,
|
|
195
|
+
policyVersion
|
|
196
|
+
);
|
|
197
|
+
const signature = hashString(`${signingSecret}|${evidenceHash}|${policyVersion}`);
|
|
198
|
+
return {
|
|
199
|
+
message: messageWithIdempotency,
|
|
200
|
+
sanitizedPayload,
|
|
201
|
+
payloadHash,
|
|
202
|
+
intentContextHash,
|
|
203
|
+
evidenceHash,
|
|
204
|
+
signature,
|
|
205
|
+
policyVersion
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
var verifySignedSocialEnvelope = (envelope, signingSecret) => {
|
|
209
|
+
if (!envelope?.message || !envelope?.sanitizedPayload) return false;
|
|
210
|
+
let intentContext;
|
|
211
|
+
try {
|
|
212
|
+
intentContext = createIntentContext(envelope.message.intentContext);
|
|
213
|
+
} catch {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
const policyVersion = envelope.policyVersion || "v1";
|
|
217
|
+
const idempotencyKey = deriveIdempotencyKey(envelope.message, envelope.sanitizedPayload);
|
|
218
|
+
if (envelope.message.idempotencyKey !== idempotencyKey) return false;
|
|
219
|
+
const payloadHash = hashStable(envelope.message.payload);
|
|
220
|
+
const intentContextHash = hashStable(intentContext);
|
|
221
|
+
if (envelope.payloadHash !== payloadHash) return false;
|
|
222
|
+
if (envelope.intentContextHash !== intentContextHash) return false;
|
|
223
|
+
const expectedEvidenceHash = computeEvidenceHash(
|
|
224
|
+
{ ...envelope.message, intentContext },
|
|
225
|
+
envelope.sanitizedPayload,
|
|
226
|
+
payloadHash,
|
|
227
|
+
intentContextHash,
|
|
228
|
+
idempotencyKey,
|
|
229
|
+
policyVersion
|
|
230
|
+
);
|
|
231
|
+
if (envelope.evidenceHash !== expectedEvidenceHash) return false;
|
|
232
|
+
const expected = hashString(`${signingSecret}|${expectedEvidenceHash}|${policyVersion}`);
|
|
233
|
+
return envelope.signature === expected;
|
|
234
|
+
};
|
|
235
|
+
var recommendRetryCount = (result) => {
|
|
236
|
+
if (result.delivered) return 0;
|
|
237
|
+
if (result.blocked && result.reason === "scope_not_allowed") return 0;
|
|
238
|
+
return 3;
|
|
239
|
+
};
|
|
240
|
+
var exchangeAgentInfo = (from, to, message, policy) => {
|
|
241
|
+
const intentContext = createIntentContext(message.intentContext);
|
|
242
|
+
const normalizedMessage = { ...message, topic: normalizeText(message.topic), intentContext };
|
|
243
|
+
const gate = canAgentsExchangeInfo(from, to, message, policy);
|
|
244
|
+
const sanitizedPayload = sanitizePayload(message.payload, policy.blockedKeys);
|
|
245
|
+
const payloadHash = hashStable(message.payload);
|
|
246
|
+
const intentContextHash = hashStable(intentContext);
|
|
247
|
+
const policyVersion = policy.policyVersion || "v1";
|
|
248
|
+
const messageWithIdempotency = {
|
|
249
|
+
...normalizedMessage,
|
|
250
|
+
idempotencyKey: deriveIdempotencyKey(normalizedMessage, sanitizedPayload)
|
|
251
|
+
};
|
|
252
|
+
const idempotencyKey = messageWithIdempotency.idempotencyKey;
|
|
253
|
+
const evidenceHash = computeEvidenceHash(
|
|
254
|
+
messageWithIdempotency,
|
|
255
|
+
sanitizedPayload,
|
|
256
|
+
payloadHash,
|
|
257
|
+
intentContextHash,
|
|
258
|
+
idempotencyKey,
|
|
259
|
+
policyVersion
|
|
260
|
+
);
|
|
261
|
+
if (!gate.ok) {
|
|
262
|
+
const blockedResult = {
|
|
263
|
+
delivered: false,
|
|
264
|
+
blocked: true,
|
|
265
|
+
reason: gate.reason,
|
|
266
|
+
state: "blocked",
|
|
267
|
+
sanitizedPayload,
|
|
268
|
+
payloadHash,
|
|
269
|
+
intentContext,
|
|
270
|
+
intentContextHash,
|
|
271
|
+
evidenceHash,
|
|
272
|
+
idempotencyKey,
|
|
273
|
+
policyVersion,
|
|
274
|
+
retriesRecommended: 0
|
|
275
|
+
};
|
|
276
|
+
return blockedResult;
|
|
277
|
+
}
|
|
278
|
+
const deliveredResult = {
|
|
279
|
+
delivered: true,
|
|
280
|
+
blocked: false,
|
|
281
|
+
reason: void 0,
|
|
282
|
+
state: "delivered",
|
|
283
|
+
sanitizedPayload,
|
|
284
|
+
payloadHash,
|
|
285
|
+
intentContext,
|
|
286
|
+
intentContextHash,
|
|
287
|
+
evidenceHash,
|
|
288
|
+
idempotencyKey,
|
|
289
|
+
policyVersion,
|
|
290
|
+
retriesRecommended: 0
|
|
291
|
+
};
|
|
292
|
+
return deliveredResult;
|
|
293
|
+
};
|
|
294
|
+
var acknowledgeExchange = (result) => ({
|
|
295
|
+
...result,
|
|
296
|
+
state: result.blocked ? "blocked" : "acknowledged"
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
export {
|
|
300
|
+
createIntentContext,
|
|
301
|
+
createAgentBuilderProfile,
|
|
302
|
+
createPrivacyPolicy,
|
|
303
|
+
sanitizePayload,
|
|
304
|
+
canAgentsExchangeInfo,
|
|
305
|
+
createSignedSocialEnvelope,
|
|
306
|
+
verifySignedSocialEnvelope,
|
|
307
|
+
recommendRetryCount,
|
|
308
|
+
exchangeAgentInfo,
|
|
309
|
+
acknowledgeExchange
|
|
310
|
+
};
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
// src/socialProtocol.ts
|
|
2
|
+
var clampScore = (score) => {
|
|
3
|
+
if (!Number.isFinite(score)) return 0;
|
|
4
|
+
return Math.max(0, Math.min(100, Math.round(score)));
|
|
5
|
+
};
|
|
6
|
+
var MANDATORY_BLOCKED_KEYS = [
|
|
7
|
+
"ownerSecret",
|
|
8
|
+
"pii",
|
|
9
|
+
"humanOwnerId",
|
|
10
|
+
"privateKey",
|
|
11
|
+
"secretKey",
|
|
12
|
+
"seed",
|
|
13
|
+
"mnemonic",
|
|
14
|
+
"apiKey",
|
|
15
|
+
"api_key",
|
|
16
|
+
"authorization",
|
|
17
|
+
"bearer",
|
|
18
|
+
"password",
|
|
19
|
+
"secret",
|
|
20
|
+
"token"
|
|
21
|
+
];
|
|
22
|
+
var MAX_TOPIC_LEN = 80;
|
|
23
|
+
var MAX_INTENT_ID_LEN = 72;
|
|
24
|
+
var MAX_INTENT_TEXT_LEN = 280;
|
|
25
|
+
var MAX_INTENT_LIST_ITEMS = 12;
|
|
26
|
+
var MAX_INTENT_LIST_ITEM_LEN = 200;
|
|
27
|
+
var MAX_PAYLOAD_DEPTH = 6;
|
|
28
|
+
var MAX_PAYLOAD_ARRAY = 64;
|
|
29
|
+
var MAX_PAYLOAD_KEYS = 128;
|
|
30
|
+
var MAX_TTL_SEC = 7 * 24 * 60 * 60;
|
|
31
|
+
var DEFAULT_TTL_SEC = 3600;
|
|
32
|
+
var ALLOWED_INTENT_TYPES = ["request", "inform", "proposal", "decision", "handoff", "sync"];
|
|
33
|
+
var stableStringify = (value) => {
|
|
34
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
35
|
+
if (Array.isArray(value)) return `[${value.map((x) => stableStringify(x)).join(",")}]`;
|
|
36
|
+
const entries = Object.entries(value).sort(([a], [b]) => a.localeCompare(b));
|
|
37
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
|
|
38
|
+
};
|
|
39
|
+
var normalizeText = (value) => String(value || "").replace(/\s+/g, " ").trim();
|
|
40
|
+
var normalizeList = (value) => {
|
|
41
|
+
if (!Array.isArray(value)) return [];
|
|
42
|
+
const normalized = value.map((entry) => normalizeText(entry).slice(0, MAX_INTENT_LIST_ITEM_LEN)).filter(Boolean);
|
|
43
|
+
return [...new Set(normalized)].slice(0, MAX_INTENT_LIST_ITEMS);
|
|
44
|
+
};
|
|
45
|
+
var hashStable = (value) => {
|
|
46
|
+
const text = stableStringify(value);
|
|
47
|
+
let hash = 5381;
|
|
48
|
+
for (let i = 0; i < text.length; i += 1) hash = (hash << 5) + hash + text.charCodeAt(i);
|
|
49
|
+
return `h${(hash >>> 0).toString(16).padStart(8, "0")}`;
|
|
50
|
+
};
|
|
51
|
+
var hashString = (value) => {
|
|
52
|
+
let hash = 5381;
|
|
53
|
+
for (let i = 0; i < value.length; i += 1) hash = (hash << 5) + hash + value.charCodeAt(i);
|
|
54
|
+
return `h${(hash >>> 0).toString(16).padStart(8, "0")}`;
|
|
55
|
+
};
|
|
56
|
+
var isIntentType = (value) => ALLOWED_INTENT_TYPES.includes(value);
|
|
57
|
+
var createIntentContext = (input) => {
|
|
58
|
+
const intentId = normalizeText(input.intentId).slice(0, MAX_INTENT_ID_LEN);
|
|
59
|
+
const intentType = normalizeText(input.intentType).toLowerCase();
|
|
60
|
+
const objective = normalizeText(input.objective).slice(0, MAX_INTENT_TEXT_LEN);
|
|
61
|
+
const expectedOutcome = normalizeText(input.expectedOutcome).slice(0, MAX_INTENT_TEXT_LEN);
|
|
62
|
+
const assumptions = normalizeList(input.assumptions);
|
|
63
|
+
const constraints = normalizeList(input.constraints);
|
|
64
|
+
const successCriteria = normalizeList(input.successCriteria);
|
|
65
|
+
const contextRefs = normalizeList(input.contextRefs);
|
|
66
|
+
const contextVersion = Number(input.contextVersion);
|
|
67
|
+
const ttlRaw = input.ttlSec === void 0 ? DEFAULT_TTL_SEC : Number(input.ttlSec);
|
|
68
|
+
const ttlSec = Number.isFinite(ttlRaw) ? Math.trunc(ttlRaw) : NaN;
|
|
69
|
+
const requiresAck = input.requiresAck === void 0 ? true : Boolean(input.requiresAck);
|
|
70
|
+
const parentEvidenceHash = normalizeText(input.parentEvidenceHash || "");
|
|
71
|
+
if (!intentId || intentId.length < 4) throw new Error("invalid_intent_context");
|
|
72
|
+
if (!isIntentType(intentType)) throw new Error("invalid_intent_context");
|
|
73
|
+
if (!objective || objective.length < 8) throw new Error("invalid_intent_context");
|
|
74
|
+
if (!expectedOutcome || expectedOutcome.length < 8) throw new Error("invalid_intent_context");
|
|
75
|
+
if (!Number.isFinite(contextVersion) || contextVersion < 1 || !Number.isInteger(contextVersion)) {
|
|
76
|
+
throw new Error("invalid_intent_context");
|
|
77
|
+
}
|
|
78
|
+
if (!Number.isFinite(ttlSec) || ttlSec < 0 || ttlSec > MAX_TTL_SEC) {
|
|
79
|
+
throw new Error("invalid_intent_context");
|
|
80
|
+
}
|
|
81
|
+
if (parentEvidenceHash && !/^h[0-9a-f]{16}$/i.test(parentEvidenceHash)) {
|
|
82
|
+
throw new Error("invalid_intent_context");
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
intentId,
|
|
86
|
+
intentType,
|
|
87
|
+
objective,
|
|
88
|
+
expectedOutcome,
|
|
89
|
+
assumptions,
|
|
90
|
+
constraints,
|
|
91
|
+
successCriteria,
|
|
92
|
+
contextVersion,
|
|
93
|
+
ttlSec,
|
|
94
|
+
requiresAck,
|
|
95
|
+
parentEvidenceHash: parentEvidenceHash || null,
|
|
96
|
+
contextRefs
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
var deriveIdempotencyKey = (message, sanitizedPayload) => {
|
|
100
|
+
if (message.idempotencyKey && message.idempotencyKey.trim()) return message.idempotencyKey.trim();
|
|
101
|
+
const intentContext = createIntentContext(message.intentContext);
|
|
102
|
+
const payloadHash = hashStable(message.payload);
|
|
103
|
+
return hashString(stableStringify({
|
|
104
|
+
fromAgentId: message.fromAgentId,
|
|
105
|
+
toAgentId: message.toAgentId,
|
|
106
|
+
topic: message.topic,
|
|
107
|
+
scope: message.scope,
|
|
108
|
+
payload: sanitizedPayload,
|
|
109
|
+
payloadHash,
|
|
110
|
+
intentContextHash: hashStable(intentContext)
|
|
111
|
+
}));
|
|
112
|
+
};
|
|
113
|
+
var computeEvidenceHash = (message, sanitizedPayload, payloadHash, intentContextHash, idempotencyKey, policyVersion) => hashString(stableStringify({
|
|
114
|
+
fromAgentId: message.fromAgentId,
|
|
115
|
+
toAgentId: message.toAgentId,
|
|
116
|
+
scope: message.scope,
|
|
117
|
+
topic: message.topic,
|
|
118
|
+
intentContext: createIntentContext(message.intentContext),
|
|
119
|
+
intentContextHash,
|
|
120
|
+
sentAtIso: message.sentAtIso,
|
|
121
|
+
rawPayloadHash: payloadHash,
|
|
122
|
+
payload: sanitizedPayload,
|
|
123
|
+
idempotencyKey,
|
|
124
|
+
policyVersion
|
|
125
|
+
}));
|
|
126
|
+
var createAgentBuilderProfile = (input) => ({
|
|
127
|
+
...input,
|
|
128
|
+
capabilityTags: [...new Set((input.capabilityTags || []).map((tag) => String(tag).trim()).filter(Boolean))],
|
|
129
|
+
reliabilityScore: clampScore(input.reliabilityScore)
|
|
130
|
+
});
|
|
131
|
+
var createPrivacyPolicy = (input) => ({
|
|
132
|
+
allowScopes: [...new Set(input.allowScopes || [])],
|
|
133
|
+
blockedKeys: [
|
|
134
|
+
.../* @__PURE__ */ new Set([
|
|
135
|
+
...MANDATORY_BLOCKED_KEYS,
|
|
136
|
+
...(input.blockedKeys || []).map((k) => k.trim()).filter(Boolean)
|
|
137
|
+
])
|
|
138
|
+
],
|
|
139
|
+
requireCapabilityMatch: input.requireCapabilityMatch?.map((k) => k.trim()).filter(Boolean) || [],
|
|
140
|
+
policyVersion: (input.policyVersion || "v1").trim() || "v1"
|
|
141
|
+
});
|
|
142
|
+
var sanitizePayloadNode = (value, blocked, depth) => {
|
|
143
|
+
if (depth > MAX_PAYLOAD_DEPTH) return "[TRUNCATED]";
|
|
144
|
+
if (value === null || value === void 0) return null;
|
|
145
|
+
if (typeof value === "string") return value;
|
|
146
|
+
if (typeof value === "number" || typeof value === "boolean") return value;
|
|
147
|
+
if (Array.isArray(value)) {
|
|
148
|
+
return value.slice(0, MAX_PAYLOAD_ARRAY).map((entry) => sanitizePayloadNode(entry, blocked, depth + 1));
|
|
149
|
+
}
|
|
150
|
+
if (typeof value !== "object") return String(value);
|
|
151
|
+
const entries = Object.entries(value).slice(0, MAX_PAYLOAD_KEYS);
|
|
152
|
+
const next = entries.filter(([key]) => !blocked.has(key.toLowerCase())).map(([key, entry]) => [key, sanitizePayloadNode(entry, blocked, depth + 1)]);
|
|
153
|
+
return Object.fromEntries(next);
|
|
154
|
+
};
|
|
155
|
+
var sanitizePayload = (payload, blockedKeys) => {
|
|
156
|
+
const blocked = new Set(blockedKeys.map((k) => k.toLowerCase()));
|
|
157
|
+
const sanitized = sanitizePayloadNode(payload, blocked, 0);
|
|
158
|
+
if (!sanitized || typeof sanitized !== "object" || Array.isArray(sanitized)) {
|
|
159
|
+
return { value: "[REDACTED]" };
|
|
160
|
+
}
|
|
161
|
+
return sanitized;
|
|
162
|
+
};
|
|
163
|
+
var canAgentsExchangeInfo = (from, to, message, policy) => {
|
|
164
|
+
const topic = normalizeText(message.topic);
|
|
165
|
+
if (!topic || topic.length > MAX_TOPIC_LEN) return { ok: false, reason: "invalid_topic" };
|
|
166
|
+
try {
|
|
167
|
+
createIntentContext(message.intentContext);
|
|
168
|
+
} catch {
|
|
169
|
+
return { ok: false, reason: "invalid_intent_context" };
|
|
170
|
+
}
|
|
171
|
+
if (!policy.allowScopes.includes(message.scope)) return { ok: false, reason: "scope_not_allowed" };
|
|
172
|
+
if (policy.requireCapabilityMatch && policy.requireCapabilityMatch.length > 0) {
|
|
173
|
+
const fromSet = new Set(from.capabilityTags.map((t) => t.toLowerCase()));
|
|
174
|
+
const toSet = new Set(to.capabilityTags.map((t) => t.toLowerCase()));
|
|
175
|
+
const required = policy.requireCapabilityMatch.map((t) => t.toLowerCase());
|
|
176
|
+
const matched = required.some((tag) => fromSet.has(tag) && toSet.has(tag));
|
|
177
|
+
if (!matched) return { ok: false, reason: "capability_mismatch" };
|
|
178
|
+
}
|
|
179
|
+
return { ok: true };
|
|
180
|
+
};
|
|
181
|
+
var createSignedSocialEnvelope = (message, policy, signingSecret) => {
|
|
182
|
+
const intentContext = createIntentContext(message.intentContext);
|
|
183
|
+
const sanitizedPayload = sanitizePayload(message.payload, policy.blockedKeys);
|
|
184
|
+
const payloadHash = hashStable(message.payload);
|
|
185
|
+
const intentContextHash = hashStable(intentContext);
|
|
186
|
+
const idempotencyKey = deriveIdempotencyKey(message, sanitizedPayload);
|
|
187
|
+
const policyVersion = policy.policyVersion || "v1";
|
|
188
|
+
const messageWithIdempotency = { ...message, intentContext, idempotencyKey };
|
|
189
|
+
const evidenceHash = computeEvidenceHash(
|
|
190
|
+
messageWithIdempotency,
|
|
191
|
+
sanitizedPayload,
|
|
192
|
+
payloadHash,
|
|
193
|
+
intentContextHash,
|
|
194
|
+
idempotencyKey,
|
|
195
|
+
policyVersion
|
|
196
|
+
);
|
|
197
|
+
const signature = hashString(`${signingSecret}|${evidenceHash}|${policyVersion}`);
|
|
198
|
+
return {
|
|
199
|
+
message: messageWithIdempotency,
|
|
200
|
+
sanitizedPayload,
|
|
201
|
+
payloadHash,
|
|
202
|
+
intentContextHash,
|
|
203
|
+
evidenceHash,
|
|
204
|
+
signature,
|
|
205
|
+
policyVersion
|
|
206
|
+
};
|
|
207
|
+
};
|
|
208
|
+
var verifySignedSocialEnvelope = (envelope, signingSecret) => {
|
|
209
|
+
if (!envelope?.message || !envelope?.sanitizedPayload) return false;
|
|
210
|
+
let intentContext;
|
|
211
|
+
try {
|
|
212
|
+
intentContext = createIntentContext(envelope.message.intentContext);
|
|
213
|
+
} catch {
|
|
214
|
+
return false;
|
|
215
|
+
}
|
|
216
|
+
const policyVersion = envelope.policyVersion || "v1";
|
|
217
|
+
const idempotencyKey = deriveIdempotencyKey(envelope.message, envelope.sanitizedPayload);
|
|
218
|
+
if (envelope.message.idempotencyKey !== idempotencyKey) return false;
|
|
219
|
+
const payloadHash = hashStable(envelope.message.payload);
|
|
220
|
+
const intentContextHash = hashStable(intentContext);
|
|
221
|
+
if (envelope.payloadHash !== payloadHash) return false;
|
|
222
|
+
if (envelope.intentContextHash !== intentContextHash) return false;
|
|
223
|
+
const expectedEvidenceHash = computeEvidenceHash(
|
|
224
|
+
{ ...envelope.message, intentContext },
|
|
225
|
+
envelope.sanitizedPayload,
|
|
226
|
+
payloadHash,
|
|
227
|
+
intentContextHash,
|
|
228
|
+
idempotencyKey,
|
|
229
|
+
policyVersion
|
|
230
|
+
);
|
|
231
|
+
if (envelope.evidenceHash !== expectedEvidenceHash) return false;
|
|
232
|
+
const expected = hashString(`${signingSecret}|${expectedEvidenceHash}|${policyVersion}`);
|
|
233
|
+
return envelope.signature === expected;
|
|
234
|
+
};
|
|
235
|
+
var recommendRetryCount = (result) => {
|
|
236
|
+
if (result.delivered) return 0;
|
|
237
|
+
if (result.blocked && result.reason === "scope_not_allowed") return 0;
|
|
238
|
+
return 3;
|
|
239
|
+
};
|
|
240
|
+
var exchangeAgentInfo = (from, to, message, policy) => {
|
|
241
|
+
const intentContext = createIntentContext(message.intentContext);
|
|
242
|
+
const normalizedMessage = { ...message, topic: normalizeText(message.topic), intentContext };
|
|
243
|
+
const gate = canAgentsExchangeInfo(from, to, message, policy);
|
|
244
|
+
const sanitizedPayload = sanitizePayload(message.payload, policy.blockedKeys);
|
|
245
|
+
const payloadHash = hashStable(message.payload);
|
|
246
|
+
const intentContextHash = hashStable(intentContext);
|
|
247
|
+
const policyVersion = policy.policyVersion || "v1";
|
|
248
|
+
const messageWithIdempotency = {
|
|
249
|
+
...normalizedMessage,
|
|
250
|
+
idempotencyKey: deriveIdempotencyKey(normalizedMessage, sanitizedPayload)
|
|
251
|
+
};
|
|
252
|
+
const idempotencyKey = messageWithIdempotency.idempotencyKey;
|
|
253
|
+
const evidenceHash = computeEvidenceHash(
|
|
254
|
+
messageWithIdempotency,
|
|
255
|
+
sanitizedPayload,
|
|
256
|
+
payloadHash,
|
|
257
|
+
intentContextHash,
|
|
258
|
+
idempotencyKey,
|
|
259
|
+
policyVersion
|
|
260
|
+
);
|
|
261
|
+
if (!gate.ok) {
|
|
262
|
+
const blockedResult = {
|
|
263
|
+
delivered: false,
|
|
264
|
+
blocked: true,
|
|
265
|
+
reason: gate.reason,
|
|
266
|
+
state: "blocked",
|
|
267
|
+
sanitizedPayload,
|
|
268
|
+
payloadHash,
|
|
269
|
+
intentContext,
|
|
270
|
+
intentContextHash,
|
|
271
|
+
evidenceHash,
|
|
272
|
+
idempotencyKey,
|
|
273
|
+
policyVersion,
|
|
274
|
+
retriesRecommended: 0
|
|
275
|
+
};
|
|
276
|
+
return blockedResult;
|
|
277
|
+
}
|
|
278
|
+
const deliveredResult = {
|
|
279
|
+
delivered: true,
|
|
280
|
+
blocked: false,
|
|
281
|
+
reason: void 0,
|
|
282
|
+
state: "delivered",
|
|
283
|
+
sanitizedPayload,
|
|
284
|
+
payloadHash,
|
|
285
|
+
intentContext,
|
|
286
|
+
intentContextHash,
|
|
287
|
+
evidenceHash,
|
|
288
|
+
idempotencyKey,
|
|
289
|
+
policyVersion,
|
|
290
|
+
retriesRecommended: 0
|
|
291
|
+
};
|
|
292
|
+
return deliveredResult;
|
|
293
|
+
};
|
|
294
|
+
var acknowledgeExchange = (result) => ({
|
|
295
|
+
...result,
|
|
296
|
+
state: result.blocked ? "blocked" : "acknowledged"
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
export {
|
|
300
|
+
createIntentContext,
|
|
301
|
+
createAgentBuilderProfile,
|
|
302
|
+
createPrivacyPolicy,
|
|
303
|
+
sanitizePayload,
|
|
304
|
+
canAgentsExchangeInfo,
|
|
305
|
+
createSignedSocialEnvelope,
|
|
306
|
+
verifySignedSocialEnvelope,
|
|
307
|
+
recommendRetryCount,
|
|
308
|
+
exchangeAgentInfo,
|
|
309
|
+
acknowledgeExchange
|
|
310
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export { OUTCOME_BOUND_FLOW_SCHEMA, OUTCOME_BOUND_REQUIRED_GATES, OutcomeBoundRe
|
|
|
11
11
|
export { STRICT_MEMORY_RUNTIME_SCHEMA, StrictMemoryEvaluation, StrictMemoryEvaluationInput, StrictMemoryRuntimePreset, StrictMemoryTriggerSet, StrictMemoryUpgradeInput, StrictMemoryUpgradePolicy, StrictMemoryUpgradeResult, createStrictMemoryRuntimePreset, evaluateStrictMemoryExecution, isComplexTask, upgradeToStrictMemoryRuntimePreset } from './strictMemoryRuntime.js';
|
|
12
12
|
export { I as IntentSignals, L as LaneMode, a as LaneSwitchDecision, O as ObjectiveChangeProposal, b as ObjectiveChangeSourceTrust, c as ObjectiveGuardDecision, d as ObjectiveGuardPolicy, P as PromptShieldDecision, e as PromptShieldFlag, f as PromptShieldInput, g as PromptShieldPolicy, h as PromptShieldRisk, i as PromptShieldTrustLevel, j as applyIntentArbitration, k as evaluateLaneSwitch, l as evaluateObjectiveChange, m as evaluatePromptShield, s as scoreBuildLane, n as scorePolishLane } from './agentLoop-BY_j-iIC.js';
|
|
13
13
|
export { AgentSocialProfile, formatOnboardedSurvivalTime, toAgentSocialProfile } from './socialProfile.js';
|
|
14
|
-
export { AgentBuilderProfile, DeliveryState, PrivacyPolicy, PrivacyScope, SignedSocialEnvelope, SocialExchangeMessage, SocialExchangeResult, acknowledgeExchange, canAgentsExchangeInfo, createAgentBuilderProfile, createPrivacyPolicy, createSignedSocialEnvelope, exchangeAgentInfo, recommendRetryCount, sanitizePayload, verifySignedSocialEnvelope } from './socialProtocol.js';
|
|
14
|
+
export { AgentBuilderProfile, DeliveryState, PrivacyPolicy, PrivacyScope, SignedSocialEnvelope, SocialExchangeMessage, SocialExchangeResult, SocialIntentContext, SocialIntentType, acknowledgeExchange, canAgentsExchangeInfo, createAgentBuilderProfile, createIntentContext, createPrivacyPolicy, createSignedSocialEnvelope, exchangeAgentInfo, recommendRetryCount, sanitizePayload, verifySignedSocialEnvelope } from './socialProtocol.js';
|
|
15
15
|
export { fetchSolBalance, fetchTokenBalance, fetchTokenBalances } from './solana.js';
|
|
16
16
|
import './compoundingMemory.js';
|
|
17
17
|
import '@coral-xyz/anchor';
|
package/dist/index.js
CHANGED
|
@@ -13,13 +13,14 @@ import {
|
|
|
13
13
|
acknowledgeExchange,
|
|
14
14
|
canAgentsExchangeInfo,
|
|
15
15
|
createAgentBuilderProfile,
|
|
16
|
+
createIntentContext,
|
|
16
17
|
createPrivacyPolicy,
|
|
17
18
|
createSignedSocialEnvelope,
|
|
18
19
|
exchangeAgentInfo,
|
|
19
20
|
recommendRetryCount,
|
|
20
21
|
sanitizePayload,
|
|
21
22
|
verifySignedSocialEnvelope
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-L3JJ77BF.js";
|
|
23
24
|
import {
|
|
24
25
|
VIBEIAO_IDL,
|
|
25
26
|
fetchSolBalance,
|
|
@@ -1394,7 +1395,7 @@ var ReviewGate = class {
|
|
|
1394
1395
|
var DEFAULT_API_BASE = "https://api.vibeiao.com";
|
|
1395
1396
|
var DEFAULT_WEB_BASE = "https://vibeiao.com";
|
|
1396
1397
|
var DEFAULT_SDK_PACKAGE = "@vibeiao/sdk";
|
|
1397
|
-
var DEFAULT_SDK_VERSION = "0.1.
|
|
1398
|
+
var DEFAULT_SDK_VERSION = "0.1.63" ? "0.1.63" : "0.1.4";
|
|
1398
1399
|
var DEFAULT_SDK_REGISTRY = "https://registry.npmjs.org";
|
|
1399
1400
|
var DEFAULT_SDK_POLICY_PATH = "/v1/sdk/policy";
|
|
1400
1401
|
var DEFAULT_SDK_CHECK_INTERVAL_MS = 1e3 * 60 * 30;
|
|
@@ -2570,6 +2571,7 @@ export {
|
|
|
2570
2571
|
createDailyLocalMidnightSchedule,
|
|
2571
2572
|
createDurabilityProxyClient,
|
|
2572
2573
|
createInMemoryReflectionStore,
|
|
2574
|
+
createIntentContext,
|
|
2573
2575
|
createPrivacyPolicy,
|
|
2574
2576
|
createSelfRelianceMonitor,
|
|
2575
2577
|
createSelfReliancePolicy,
|
package/dist/socialProtocol.d.ts
CHANGED
|
@@ -6,6 +6,21 @@ type AgentBuilderProfile = {
|
|
|
6
6
|
onboardedAt?: string;
|
|
7
7
|
};
|
|
8
8
|
type PrivacyScope = 'public' | 'partner' | 'owner';
|
|
9
|
+
type SocialIntentType = 'request' | 'inform' | 'proposal' | 'decision' | 'handoff' | 'sync';
|
|
10
|
+
type SocialIntentContext = {
|
|
11
|
+
intentId: string;
|
|
12
|
+
intentType: SocialIntentType;
|
|
13
|
+
objective: string;
|
|
14
|
+
expectedOutcome: string;
|
|
15
|
+
assumptions?: string[];
|
|
16
|
+
constraints?: string[];
|
|
17
|
+
successCriteria?: string[];
|
|
18
|
+
contextVersion: number;
|
|
19
|
+
ttlSec?: number;
|
|
20
|
+
requiresAck?: boolean;
|
|
21
|
+
parentEvidenceHash?: string | null;
|
|
22
|
+
contextRefs?: string[];
|
|
23
|
+
};
|
|
9
24
|
type PrivacyPolicy = {
|
|
10
25
|
allowScopes: PrivacyScope[];
|
|
11
26
|
blockedKeys: string[];
|
|
@@ -18,6 +33,7 @@ type SocialExchangeMessage = {
|
|
|
18
33
|
toAgentId: string;
|
|
19
34
|
scope: PrivacyScope;
|
|
20
35
|
topic: string;
|
|
36
|
+
intentContext: SocialIntentContext;
|
|
21
37
|
payload: Record<string, unknown>;
|
|
22
38
|
sentAtIso: string;
|
|
23
39
|
idempotencyKey?: string;
|
|
@@ -25,6 +41,8 @@ type SocialExchangeMessage = {
|
|
|
25
41
|
type SignedSocialEnvelope = {
|
|
26
42
|
message: SocialExchangeMessage;
|
|
27
43
|
sanitizedPayload: Record<string, unknown>;
|
|
44
|
+
payloadHash: string;
|
|
45
|
+
intentContextHash: string;
|
|
28
46
|
evidenceHash: string;
|
|
29
47
|
signature: string;
|
|
30
48
|
policyVersion: string;
|
|
@@ -35,11 +53,15 @@ type SocialExchangeResult = {
|
|
|
35
53
|
reason?: string;
|
|
36
54
|
state: DeliveryState;
|
|
37
55
|
sanitizedPayload: Record<string, unknown>;
|
|
56
|
+
payloadHash: string;
|
|
57
|
+
intentContext: SocialIntentContext;
|
|
58
|
+
intentContextHash: string;
|
|
38
59
|
evidenceHash: string;
|
|
39
60
|
idempotencyKey: string;
|
|
40
61
|
policyVersion: string;
|
|
41
62
|
retriesRecommended: number;
|
|
42
63
|
};
|
|
64
|
+
declare const createIntentContext: (input: SocialIntentContext) => SocialIntentContext;
|
|
43
65
|
declare const createAgentBuilderProfile: (input: AgentBuilderProfile) => AgentBuilderProfile;
|
|
44
66
|
declare const createPrivacyPolicy: (input: PrivacyPolicy) => PrivacyPolicy;
|
|
45
67
|
declare const sanitizePayload: (payload: Record<string, unknown>, blockedKeys: string[]) => Record<string, unknown>;
|
|
@@ -57,4 +79,4 @@ declare const recommendRetryCount: (result: {
|
|
|
57
79
|
declare const exchangeAgentInfo: (from: AgentBuilderProfile, to: AgentBuilderProfile, message: SocialExchangeMessage, policy: PrivacyPolicy) => SocialExchangeResult;
|
|
58
80
|
declare const acknowledgeExchange: (result: SocialExchangeResult) => SocialExchangeResult;
|
|
59
81
|
|
|
60
|
-
export { type AgentBuilderProfile, type DeliveryState, type PrivacyPolicy, type PrivacyScope, type SignedSocialEnvelope, type SocialExchangeMessage, type SocialExchangeResult, acknowledgeExchange, canAgentsExchangeInfo, createAgentBuilderProfile, createPrivacyPolicy, createSignedSocialEnvelope, exchangeAgentInfo, recommendRetryCount, sanitizePayload, verifySignedSocialEnvelope };
|
|
82
|
+
export { type AgentBuilderProfile, type DeliveryState, type PrivacyPolicy, type PrivacyScope, type SignedSocialEnvelope, type SocialExchangeMessage, type SocialExchangeResult, type SocialIntentContext, type SocialIntentType, acknowledgeExchange, canAgentsExchangeInfo, createAgentBuilderProfile, createIntentContext, createPrivacyPolicy, createSignedSocialEnvelope, exchangeAgentInfo, recommendRetryCount, sanitizePayload, verifySignedSocialEnvelope };
|
package/dist/socialProtocol.js
CHANGED
|
@@ -2,17 +2,19 @@ import {
|
|
|
2
2
|
acknowledgeExchange,
|
|
3
3
|
canAgentsExchangeInfo,
|
|
4
4
|
createAgentBuilderProfile,
|
|
5
|
+
createIntentContext,
|
|
5
6
|
createPrivacyPolicy,
|
|
6
7
|
createSignedSocialEnvelope,
|
|
7
8
|
exchangeAgentInfo,
|
|
8
9
|
recommendRetryCount,
|
|
9
10
|
sanitizePayload,
|
|
10
11
|
verifySignedSocialEnvelope
|
|
11
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-L3JJ77BF.js";
|
|
12
13
|
export {
|
|
13
14
|
acknowledgeExchange,
|
|
14
15
|
canAgentsExchangeInfo,
|
|
15
16
|
createAgentBuilderProfile,
|
|
17
|
+
createIntentContext,
|
|
16
18
|
createPrivacyPolicy,
|
|
17
19
|
createSignedSocialEnvelope,
|
|
18
20
|
exchangeAgentInfo,
|