@seasonkoh/webaz 0.1.21 → 0.1.22
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/layer0-foundation/L0-2-state-machine/engine.js +83 -90
- package/dist/layer1-agent/L1-1-mcp-server/server.js +13 -0
- package/dist/layer3-trust/L3-1-dispute-engine/dispute-engine.js +138 -168
- package/dist/layer4-economics/L4-4-skill-market/skill-engine.js +6 -4
- package/dist/layer4-economics/L4-4-skill-market/skill-listing-engine.js +12 -8
- package/dist/ledger.js +58 -0
- package/dist/money.js +106 -0
- package/dist/pwa/acp-feed.js +103 -0
- package/dist/pwa/public/app.js +8 -7
- package/dist/pwa/public/index.html +26 -1
- package/dist/pwa/routes/auction.js +9 -6
- package/dist/pwa/routes/disputes-write.js +12 -11
- package/dist/pwa/routes/orders-create.js +24 -13
- package/dist/pwa/routes/public-utils.js +11 -0
- package/dist/pwa/server.js +57 -39
- package/dist/settlement-math.js +27 -0
- package/package.json +1 -1
|
@@ -12,6 +12,21 @@
|
|
|
12
12
|
import { generateId } from '../L0-1-database/schema.js';
|
|
13
13
|
import { appendOrderEvent } from './order-chain.js';
|
|
14
14
|
import { VALID_TRANSITIONS, CURRENT_RESPONSIBLE, CURRENT_RESPONSIBLE_SELF_FULFILL } from './transitions.js';
|
|
15
|
+
// RFC-014 PR2 — 资金算术统一走整数 base-units;分配用 allocate 保证精确守恒。
|
|
16
|
+
import { toUnits, toDecimal, mulRate, allocate } from '../../money.js';
|
|
17
|
+
// RFC-014 PR3 — 钱包落库 helper 抽到共享 ledger 模块(原私有于此),防多份漂移。
|
|
18
|
+
import { walletUnits, applyWalletDelta } from '../../ledger.js';
|
|
19
|
+
// ─── RFC-014 公池入金 helper ───────────────────────────────────
|
|
20
|
+
function creditReserveUnits(db, fromUserId, amountUnits, orderId, note) {
|
|
21
|
+
if (amountUnits <= 0)
|
|
22
|
+
return;
|
|
23
|
+
const cur = db.prepare("SELECT COALESCE(balance,0) balance, COALESCE(total_orphan_sponsor,0) tos FROM commission_reserve WHERE id='main'").get();
|
|
24
|
+
const newBal = toDecimal(toUnits(cur?.balance ?? 0) + amountUnits);
|
|
25
|
+
const newTos = toDecimal(toUnits(cur?.tos ?? 0) + amountUnits);
|
|
26
|
+
db.prepare(`UPDATE commission_reserve SET balance = ?, total_orphan_sponsor = ?, updated_at = datetime('now') WHERE id = 'main'`).run(newBal, newTos);
|
|
27
|
+
db.prepare(`INSERT INTO commission_reserve_txns (id, kind, from_user_id, amount, related_order_id, note) VALUES (?,?,?,?,?,?)`)
|
|
28
|
+
.run(generateId('crt'), 'redirect_orphan_sponsor', fromUserId, toDecimal(amountUnits), orderId, note);
|
|
29
|
+
}
|
|
15
30
|
// ─── 核心函数 ────────────────────────────────────────────────
|
|
16
31
|
/**
|
|
17
32
|
* 执行状态转移
|
|
@@ -236,8 +251,10 @@ export function settleFault(db, orderId, faultState) {
|
|
|
236
251
|
const v = Number(row?.value);
|
|
237
252
|
return Number.isFinite(v) && v >= 0 ? v : 0.30;
|
|
238
253
|
};
|
|
239
|
-
|
|
240
|
-
const
|
|
254
|
+
// RFC-014:金额一律转整数 base-units 后再算/分配。
|
|
255
|
+
const totalU = toUnits(total);
|
|
256
|
+
const penaltyU = isSecondhand ? 0 : mulRate(totalU, faultPenaltyRate());
|
|
257
|
+
const orderStakeBackingU = Math.max(0, toUnits(Number(order.stake_backing || 0)));
|
|
241
258
|
// RFC-007 stage 4:没收后的【守恒 + 不牟利】再分配(取代旧的 buyer 50% / protocol 50%)。
|
|
242
259
|
// 旧分配漏掉推广人(违反 §谁责任谁承担:推广人承担了真实推广成本却零补偿)。
|
|
243
260
|
// 新规则(全部用订单快照,可复算,绝不印钱):
|
|
@@ -248,92 +265,81 @@ export function settleFault(db, orderId, faultState) {
|
|
|
248
265
|
// 4. 推广半残值(超封顶 / 无推广人)→ commission_reserve 三级公池(与正常单未归属佣金同去向,不给买家=不过补)。
|
|
249
266
|
// 守恒:protocolTake + buyerComp + promotersPaid + reserveResidual ≡ F(按构造,残值兜底)。
|
|
250
267
|
const FORFEIT_LEVEL_RATES = { 1: 0.70, 2: 0.20, 3: 0.10 };
|
|
251
|
-
const round2 = (n) => Math.round(n * 100) / 100;
|
|
252
|
-
const reserveResidual = (amount, note) => {
|
|
253
|
-
const a = round2(amount);
|
|
254
|
-
if (a <= 0)
|
|
255
|
-
return;
|
|
256
|
-
// 复制 redirectToCommissionReserve 的两笔写入(L0 不依赖 server.ts;kind 用既有 orphan_sponsor 桶)
|
|
257
|
-
db.prepare(`UPDATE commission_reserve SET balance = balance + ?, total_orphan_sponsor = total_orphan_sponsor + ?, updated_at = datetime('now') WHERE id = 'main'`).run(a, a);
|
|
258
|
-
db.prepare(`INSERT INTO commission_reserve_txns (id, kind, from_user_id, amount, related_order_id, note) VALUES (?,?,?,?,?,?)`)
|
|
259
|
-
.run(generateId('crt'), 'redirect_orphan_sponsor', sellerId, a, orderId, note);
|
|
260
|
-
};
|
|
261
268
|
const protocolFeeRate = () => {
|
|
262
269
|
const key = isSecondhand ? 'protocol_fee_rate_secondhand' : 'protocol_fee_rate_shop';
|
|
263
270
|
const row = db.prepare('SELECT value FROM protocol_params WHERE key = ?').get(key);
|
|
264
271
|
const v = Number(row?.value);
|
|
265
272
|
return Number.isFinite(v) && v >= 0 ? v : (isSecondhand ? 0.01 : 0.02);
|
|
266
273
|
};
|
|
267
|
-
// 罚没【收取 + RFC-007
|
|
274
|
+
// 罚没【收取 + RFC-007 守恒分配】(整数 base-units;allocate 保证精确守恒),返回实扣额 units(0=起步免赔付)
|
|
268
275
|
const forfeitAndDistribute = (penalty) => {
|
|
269
276
|
// 起步免赔付:无背书订单(stake_backing=0)绝不没收、绝不碰新商家自由余额
|
|
270
|
-
if (
|
|
277
|
+
if (orderStakeBackingU <= 0)
|
|
271
278
|
return 0;
|
|
272
|
-
//
|
|
273
|
-
const fromStaked = Math.min(penalty,
|
|
274
|
-
const remainder =
|
|
275
|
-
const
|
|
276
|
-
const fromBalance =
|
|
277
|
-
const F =
|
|
279
|
+
// 收取:先扣 staked(封顶背书额),不足再扣卖家自由 balance(责任自负;封顶其真实余额→不转负)
|
|
280
|
+
const fromStaked = Math.min(penalty, orderStakeBackingU);
|
|
281
|
+
const remainder = penalty - fromStaked;
|
|
282
|
+
const sellerBalU = Math.max(0, walletUnits(db, sellerId).balance);
|
|
283
|
+
const fromBalance = Math.min(remainder, sellerBalU);
|
|
284
|
+
const F = fromStaked + fromBalance;
|
|
278
285
|
if (F <= 0)
|
|
279
286
|
return 0;
|
|
280
|
-
|
|
281
|
-
db.prepare('UPDATE wallets SET staked = staked - ? WHERE user_id = ?').run(fromStaked, sellerId);
|
|
282
|
-
if (fromBalance > 0)
|
|
283
|
-
db.prepare('UPDATE wallets SET balance = balance - ? WHERE user_id = ?').run(fromBalance, sellerId);
|
|
287
|
+
applyWalletDelta(db, sellerId, { staked: -fromStaked, balance: -fromBalance });
|
|
284
288
|
// 1. 协议回收原始平台费(封顶 F,不牟利)
|
|
285
|
-
const protocolTake =
|
|
289
|
+
const protocolTake = Math.min(F, mulRate(totalU, protocolFeeRate()));
|
|
286
290
|
if (protocolTake > 0)
|
|
287
|
-
db
|
|
288
|
-
// 2. R 与买家补偿
|
|
289
|
-
const R =
|
|
290
|
-
const buyerComp =
|
|
291
|
+
applyWalletDelta(db, sysUserId, { balance: protocolTake });
|
|
292
|
+
// 2. R 与买家补偿(精确平分:allocate 两桶求和 ≡ R)
|
|
293
|
+
const R = F - protocolTake;
|
|
294
|
+
const [buyerComp, promoterHalf] = allocate(R, [1, 1]);
|
|
291
295
|
if (buyerComp > 0)
|
|
292
|
-
db
|
|
293
|
-
// 3. 推广半 → l1/l2/l3
|
|
294
|
-
const promoterHalf = round2(R - buyerComp);
|
|
296
|
+
applyWalletDelta(db, buyerId, { balance: buyerComp });
|
|
297
|
+
// 3. 推广半 → l1/l2/l3 按原始佣金比例分,封顶原始佣金总额(allocate 求和 ≡ payable)
|
|
295
298
|
const commissionRate = Number(order.snapshot_commission_rate ?? 0);
|
|
296
|
-
const
|
|
299
|
+
const poolU = mulRate(totalU, Number.isFinite(commissionRate) && commissionRate > 0 ? commissionRate : 0);
|
|
297
300
|
const levels = [
|
|
298
|
-
{ uid: order.l1_uid, orig:
|
|
299
|
-
{ uid: order.l2_uid, orig:
|
|
300
|
-
{ uid: order.l3_uid, orig:
|
|
301
|
+
{ uid: order.l1_uid, orig: mulRate(poolU, FORFEIT_LEVEL_RATES[1]) },
|
|
302
|
+
{ uid: order.l2_uid, orig: mulRate(poolU, FORFEIT_LEVEL_RATES[2]) },
|
|
303
|
+
{ uid: order.l3_uid, orig: mulRate(poolU, FORFEIT_LEVEL_RATES[3]) },
|
|
301
304
|
].filter(l => l.uid); // 仅【真实存在的推广人】参与
|
|
302
|
-
const originalCommissionTotal =
|
|
305
|
+
const originalCommissionTotal = levels.reduce((s, l) => s + l.orig, 0);
|
|
303
306
|
let promotersPaid = 0;
|
|
304
307
|
if (promoterHalf > 0 && originalCommissionTotal > 0) {
|
|
305
308
|
const payable = Math.min(promoterHalf, originalCommissionTotal); // 封顶原始佣金总额
|
|
306
|
-
|
|
307
|
-
|
|
309
|
+
const shares = allocate(payable, levels.map(l => l.orig));
|
|
310
|
+
levels.forEach((l, i) => {
|
|
311
|
+
const share = shares[i];
|
|
308
312
|
if (share <= 0)
|
|
309
|
-
|
|
310
|
-
db.
|
|
311
|
-
promotersPaid
|
|
312
|
-
}
|
|
313
|
+
return;
|
|
314
|
+
applyWalletDelta(db, l.uid, { balance: share, earned: share });
|
|
315
|
+
promotersPaid += share;
|
|
316
|
+
});
|
|
313
317
|
}
|
|
314
318
|
// 4. 推广半残值(超封顶 / 无推广人 / 取整余数)→ 三级公池;绝不给买家、绝不印钱
|
|
315
|
-
|
|
319
|
+
creditReserveUnits(db, sellerId, promoterHalf - promotersPaid, orderId, `RFC-007 fault forfeit residual order=${orderId}`);
|
|
316
320
|
return F;
|
|
317
321
|
};
|
|
318
322
|
// P0.1:RFQ 路径的 bid_stake_held — fault 时由各分支按规则处理
|
|
319
|
-
const
|
|
323
|
+
const bidStakeHeldU = toUnits(Number(order.bid_stake_held || 0));
|
|
324
|
+
// bid_stake_held 没收 50/50 的公用逻辑(中标后弃单的额外惩罚)
|
|
325
|
+
const forfeitBidStake5050 = () => {
|
|
326
|
+
if (bidStakeHeldU <= 0)
|
|
327
|
+
return;
|
|
328
|
+
applyWalletDelta(db, sellerId, { staked: -bidStakeHeldU });
|
|
329
|
+
const [compBuyer, compSys] = allocate(bidStakeHeldU, [1, 1]);
|
|
330
|
+
if (compBuyer > 0)
|
|
331
|
+
applyWalletDelta(db, buyerId, { balance: compBuyer });
|
|
332
|
+
if (compSys > 0)
|
|
333
|
+
applyWalletDelta(db, sysUserId, { balance: compSys });
|
|
334
|
+
};
|
|
320
335
|
if (faultState === 'fault_seller') {
|
|
321
336
|
// 1. buyer escrow 全额退回
|
|
322
|
-
db
|
|
323
|
-
.run(total, total, buyerId);
|
|
337
|
+
applyWalletDelta(db, buyerId, { escrowed: -totalU, balance: totalU });
|
|
324
338
|
// P0.1:bid_stake_held 没收 50/50(中标后弃单的额外惩罚)
|
|
325
|
-
|
|
326
|
-
db.prepare('UPDATE wallets SET staked = staked - ? WHERE user_id = ?').run(bidStakeHeld, sellerId);
|
|
327
|
-
const compToBuyer = Math.round(bidStakeHeld * 0.5 * 100) / 100;
|
|
328
|
-
const compToSys = Math.round((bidStakeHeld - compToBuyer) * 100) / 100;
|
|
329
|
-
if (compToBuyer > 0)
|
|
330
|
-
db.prepare('UPDATE wallets SET balance = balance + ? WHERE user_id = ?').run(compToBuyer, buyerId);
|
|
331
|
-
if (compToSys > 0)
|
|
332
|
-
db.prepare('UPDATE wallets SET balance = balance + ? WHERE user_id = ?').run(compToSys, sysUserId);
|
|
333
|
-
}
|
|
339
|
+
forfeitBidStake5050();
|
|
334
340
|
// 2. 罚没(fault_penalty_rate×total,staked 不足扣自由 balance,绝不印钱)→ RFC-007 守恒分配
|
|
335
|
-
if (
|
|
336
|
-
forfeitAndDistribute(
|
|
341
|
+
if (penaltyU > 0)
|
|
342
|
+
forfeitAndDistribute(penaltyU);
|
|
337
343
|
// 3. 库存回退(非二手)
|
|
338
344
|
if (!isSecondhand)
|
|
339
345
|
db.prepare('UPDATE products SET stock = stock + 1 WHERE id = ?').run(order.product_id);
|
|
@@ -353,21 +359,12 @@ export function settleFault(db, orderId, faultState) {
|
|
|
353
359
|
const isSelfFulfill = !order.logistics_id;
|
|
354
360
|
if (isSelfFulfill) {
|
|
355
361
|
// 1. buyer escrow 全额退回
|
|
356
|
-
db
|
|
357
|
-
.run(total, total, buyerId);
|
|
362
|
+
applyWalletDelta(db, buyerId, { escrowed: -totalU, balance: totalU });
|
|
358
363
|
// 2. bid_stake_held 没收 50/50(同 fault_seller 逻辑)
|
|
359
|
-
|
|
360
|
-
db.prepare('UPDATE wallets SET staked = staked - ? WHERE user_id = ?').run(bidStakeHeld, sellerId);
|
|
361
|
-
const compToBuyer = Math.round(bidStakeHeld * 0.5 * 100) / 100;
|
|
362
|
-
const compToSys = Math.round((bidStakeHeld - compToBuyer) * 100) / 100;
|
|
363
|
-
if (compToBuyer > 0)
|
|
364
|
-
db.prepare('UPDATE wallets SET balance = balance + ? WHERE user_id = ?').run(compToBuyer, buyerId);
|
|
365
|
-
if (compToSys > 0)
|
|
366
|
-
db.prepare('UPDATE wallets SET balance = balance + ? WHERE user_id = ?').run(compToSys, sysUserId);
|
|
367
|
-
}
|
|
364
|
+
forfeitBidStake5050();
|
|
368
365
|
// 3. 罚没(self-fulfill seller 违约;fault_penalty_rate×total,staked 不足扣自由 balance)→ RFC-007 守恒分配
|
|
369
|
-
if (
|
|
370
|
-
forfeitAndDistribute(
|
|
366
|
+
if (penaltyU > 0)
|
|
367
|
+
forfeitAndDistribute(penaltyU);
|
|
371
368
|
// 4. 库存回退
|
|
372
369
|
if (!isSecondhand)
|
|
373
370
|
db.prepare('UPDATE products SET stock = stock + 1 WHERE id = ?').run(order.product_id);
|
|
@@ -381,17 +378,13 @@ export function settleFault(db, orderId, faultState) {
|
|
|
381
378
|
else {
|
|
382
379
|
// Phase 2 logistics 市场:真正的 logistics 接单后违约
|
|
383
380
|
// 1. buyer escrow 全额退回
|
|
384
|
-
db
|
|
385
|
-
.run(total, total, buyerId);
|
|
381
|
+
applyWalletDelta(db, buyerId, { escrowed: -totalU, balance: totalU });
|
|
386
382
|
// 2. seller 无责 → bid_stake_held / stake 全额返还
|
|
387
|
-
if (
|
|
388
|
-
db
|
|
389
|
-
}
|
|
383
|
+
if (bidStakeHeldU > 0)
|
|
384
|
+
applyWalletDelta(db, sellerId, { balance: bidStakeHeldU, staked: -bidStakeHeldU });
|
|
390
385
|
// seller 无责 → 退还其【该单实际背书的 stake】(= stake_backing;起步阶段=0,无可退)
|
|
391
|
-
if (
|
|
392
|
-
db
|
|
393
|
-
.run(orderStakeBacking, orderStakeBacking, sellerId);
|
|
394
|
-
}
|
|
386
|
+
if (orderStakeBackingU > 0)
|
|
387
|
+
applyWalletDelta(db, sellerId, { staked: -orderStakeBackingU, balance: orderStakeBackingU });
|
|
395
388
|
// 3. 库存回退
|
|
396
389
|
if (!isSecondhand)
|
|
397
390
|
db.prepare('UPDATE products SET stock = stock + 1 WHERE id = ?').run(order.product_id);
|
|
@@ -415,9 +408,8 @@ export function settleFault(db, orderId, faultState) {
|
|
|
415
408
|
catch { }
|
|
416
409
|
}
|
|
417
410
|
// P0.1:买家违约 → bid_stake_held 全额返还卖家(卖家未失责)
|
|
418
|
-
if (
|
|
419
|
-
db
|
|
420
|
-
}
|
|
411
|
+
if (bidStakeHeldU > 0)
|
|
412
|
+
applyWalletDelta(db, sellerId, { balance: bidStakeHeldU, staked: -bidStakeHeldU });
|
|
421
413
|
}
|
|
422
414
|
// 标记已结算(防止重复处置)
|
|
423
415
|
db.prepare("UPDATE orders SET settled_fault_at = datetime('now') WHERE id = ?").run(orderId);
|
|
@@ -434,19 +426,20 @@ export function settleDeclinedNoFault(db, orderId) {
|
|
|
434
426
|
return;
|
|
435
427
|
if (order.settled_fault_at)
|
|
436
428
|
return; // 幂等(复用 settled_fault_at 标记)
|
|
437
|
-
const total = Number(order.total_amount);
|
|
438
429
|
const buyerId = order.buyer_id;
|
|
439
430
|
const sellerId = order.seller_id;
|
|
440
431
|
const isSecondhand = order.source === 'secondhand';
|
|
441
|
-
|
|
442
|
-
const
|
|
432
|
+
// RFC-014:整数 base-units
|
|
433
|
+
const totalU = toUnits(Number(order.total_amount));
|
|
434
|
+
const orderStakeBackingU = Math.max(0, toUnits(Number(order.stake_backing || 0)));
|
|
435
|
+
const bidStakeHeldU = toUnits(Number(order.bid_stake_held || 0));
|
|
443
436
|
// 1. 买家 escrow 全额退回
|
|
444
|
-
db
|
|
437
|
+
applyWalletDelta(db, buyerId, { escrowed: -totalU, balance: totalU });
|
|
445
438
|
// 2. 卖家质押全退(封顶其实际 staked,绝不转负)—— 无责零成本
|
|
446
|
-
const
|
|
447
|
-
const returnStake = Math.min(
|
|
439
|
+
const sellerStakedU = Math.max(0, walletUnits(db, sellerId).staked);
|
|
440
|
+
const returnStake = Math.min(orderStakeBackingU + bidStakeHeldU, sellerStakedU);
|
|
448
441
|
if (returnStake > 0)
|
|
449
|
-
db
|
|
442
|
+
applyWalletDelta(db, sellerId, { staked: -returnStake, balance: returnStake });
|
|
450
443
|
// 3. 库存 / 二手状态恢复
|
|
451
444
|
if (!isSecondhand)
|
|
452
445
|
db.prepare('UPDATE products SET stock = stock + 1 WHERE id = ?').run(order.product_id);
|
|
@@ -1529,6 +1529,19 @@ function handleInfo() {
|
|
|
1529
1529
|
disclaimer: '本协议尚未公开上线,prod 真实用户≈0,无真实经济流转。下方 live_stats / 工具示例所有计数均来自**本机 MCP 服务器的本地 SQLite**(~/.webaz/webaz.db),仅供 dev / demo,不代表协议全网真实状态。请勿据此评估市场规模、做投资决策、或替终端用户承诺任何经济关系。',
|
|
1530
1530
|
},
|
|
1531
1531
|
description: 'WebAZ is a decentralized commerce protocol. Every transaction flows through a state machine; each state transition needs proof-of-action from the responsible party. Any timeout-without-action: protocol auto-rules default + executes remedy. / WebAZ 是去中心化商业协议;每笔交易通过状态机流转,每次状态转移需对应责任方的操作证明;超时未操作则协议自动判违约并执行处置。',
|
|
1532
|
+
// 给【终端用户/买家】的价值主张 —— 陌生 agent / 普通买家先要知道"对我有什么用",而非只读抽象 tagline + 技术 description。
|
|
1533
|
+
for_end_user: {
|
|
1534
|
+
note: 'What WebAZ does FOR a buyer (why use it): / 这个协议对买家有什么用(为什么用它):',
|
|
1535
|
+
value: [
|
|
1536
|
+
'Escrow on every order — your money is held by the protocol and only released to the seller after you confirm receipt (or an auto-confirm window). / 每笔订单托管:钱由协议托管,你确认收货(或到自动确认期)才放款给卖家。',
|
|
1537
|
+
'Automatic fault ruling — if the seller does not accept / ship / deliver in time, the protocol auto-refunds you, no haggling. / 自动判责:卖家不接单/不发货/不送达超时,协议自动退款给你,无需扯皮。',
|
|
1538
|
+
'Disputes with evidence + arbitration — open a dispute with proof; a neutral process decides. / 争议可凭证据发起 + 中立仲裁裁决。',
|
|
1539
|
+
'Decision-ready transparency — price history, seller reputation, win/loss record and arbitration precedents are public before you buy. / 知情决策:价格历史、卖家信誉、胜诉/败诉记录、仲裁判例,下单前都公开可查。',
|
|
1540
|
+
'Agent-native — your AI agent can compare prices, place orders, and track fulfillment for you via the MCP tools. / agent 原生:你的 AI 可经 MCP 工具替你比价、下单、跟踪履约。',
|
|
1541
|
+
],
|
|
1542
|
+
honesty: 'Pre-launch: WAZ is a simulated test currency, no real money settles yet. Don\'t treat balances as real value. / 尚未上线:WAZ 是模拟测试币,暂无真实资金结算,余额勿当真实价值。',
|
|
1543
|
+
try_it: 'Browse without an account at https://webaz.xyz/#discover ; the protocol state is public at https://webaz.xyz/.well-known/webaz-protocol.json',
|
|
1544
|
+
},
|
|
1532
1545
|
// 连接两个场景:用协议(本工具) ↔ 改协议(开发协作)。想改 WebAZ 本身的 agent 从这里进。
|
|
1533
1546
|
for_contributors: {
|
|
1534
1547
|
note: 'Want to change WebAZ itself (not just use it)? This is an open, agent-native protocol — AI-authored PRs are welcome, with accountability. / 想改 WebAZ 本身(不只是用)?这是开放的 agent 原生协议,欢迎 AI 提 PR,但需问责。',
|