@twinsearth/agent-universe 2.5.9 → 2.6.1
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 +3 -1
- package/js/index.js +1 -1
- package/js/lib/aca.js +1 -1
- package/js/lib/market.js +32 -2
- package/js/lib/mcp.js +1 -1
- package/js/lib/models.js +27 -2
- package/js/package-lock.json +2 -2
- package/js/package.json +1 -1
- package/js/test/test.js +67 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -273,7 +273,7 @@ npm config set @twinsearth:registry https://npm.pkg.github.com
|
|
|
273
273
|
npm install @twinsearth/agent-universe
|
|
274
274
|
```
|
|
275
275
|
|
|
276
|
-
已发布版本:1.0.0 / 2.0.0 / 2.2.0 / 2.3.0 / 2.3.1 / 2.3.4 / 2.3.5 / 2.3.6 / 2.4.0 ~ 2.
|
|
276
|
+
已发布版本:1.0.0 / 2.0.0 / 2.2.0 / 2.3.0 / 2.3.1 / 2.3.4 / 2.3.5 / 2.3.6 / 2.4.0 ~ 2.6.1,详见 [Releases](https://github.com/TwinsEarth/agent-universe/releases)。
|
|
277
277
|
|
|
278
278
|
## 版本谱系
|
|
279
279
|
|
|
@@ -310,6 +310,8 @@ npm install @twinsearth/agent-universe
|
|
|
310
310
|
| v2.5.7 | **Identity** | **跨实现身份一致性:统一 DID 派生口径 + conformance 签名向量逐字节命中上游 + 客户端构建链路根治(file: 依赖)** |
|
|
311
311
|
| v2.5.8 | **Ledger** | **精确整数账本 Money(i64):守恒精确相等无容差 + 发布即托管 __escrow__ 防铸币 + 三端共享金额向量逐值一致** |
|
|
312
312
|
| v2.5.9 | **Auth QA** | **认证式 BFT(固定委员集 Ed25519 签名票,替代调用方合成)+ 可失败独立审计(只信任流水独立重放)+ nonce/时间窗重放保护 + 只追加结算流水** |
|
|
313
|
+
| v2.6.0 | **State Machine** | **状态机恢复边(no_quorum→open、rework→running,消除 NoQuorum 吸收态)+ 证据分级作为结算强制闸门(is_trustworthy 此前零调用点)+ policy=None 提交即验收** |
|
|
314
|
+
| v2.6.1 | **Ledger Persistence** | **账本落盘 + 重启从只追加流水重放恢复(ledger_entries,根治只写不读/重启丢账)+ MCP 单一来源参数校验(缺必填/类型错误返回 -32602,杜绝静默降级)** |
|
|
313
315
|
|
|
314
316
|
详见 [RELEASES.md](RELEASES.md) 和 [releases/](releases/) 目录。
|
|
315
317
|
|
package/js/index.js
CHANGED
|
@@ -9,7 +9,7 @@ const { AgentMarket, Bid, Reputation, MIN_STAKE } = require('./lib/market');
|
|
|
9
9
|
const { McpHttpClient, McpError, MCP_PROTOCOL_VERSION } = require('./lib/mcp');
|
|
10
10
|
const aca = require('./lib/aca');
|
|
11
11
|
|
|
12
|
-
const version = '2.
|
|
12
|
+
const version = '2.6.1';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* AgentUniverse 门面:聚合身份、网络、市场能力
|
package/js/lib/aca.js
CHANGED
|
@@ -129,7 +129,7 @@ function buildManifest(identity, name, capabilities, opts = {}) {
|
|
|
129
129
|
const manifest = {
|
|
130
130
|
did: identity.did,
|
|
131
131
|
name,
|
|
132
|
-
version: opts.version || '2.
|
|
132
|
+
version: opts.version || '2.6.1',
|
|
133
133
|
capabilities: [...capabilities],
|
|
134
134
|
endpoints: opts.endpoints || [],
|
|
135
135
|
hardware: {
|
package/js/lib/market.js
CHANGED
|
@@ -175,11 +175,33 @@ class AgentMarket {
|
|
|
175
175
|
}
|
|
176
176
|
|
|
177
177
|
/** 执行 → 完成 → 验证 */
|
|
178
|
-
completeTask(taskId, passed = true) {
|
|
178
|
+
completeTask(taskId, passed = true, evidenceGrade = 'CpuProto') {
|
|
179
179
|
const task = this.tasks.get(taskId);
|
|
180
180
|
task.start();
|
|
181
181
|
task.complete();
|
|
182
|
-
task.
|
|
182
|
+
task.evidenceGrade = evidenceGrade;
|
|
183
|
+
if (task.verificationPolicy === 'None') {
|
|
184
|
+
// 无需 QA:提交结果即验收(证据门禁亦豁免)
|
|
185
|
+
task.transition(TaskStatus.VERIFIED);
|
|
186
|
+
} else {
|
|
187
|
+
task.verify(passed);
|
|
188
|
+
}
|
|
189
|
+
return task;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** 恢复边:返工任务回到执行中(v2.6.0) */
|
|
193
|
+
resumeAfterRework(taskId) {
|
|
194
|
+
const task = this.tasks.get(taskId);
|
|
195
|
+
if (!task) throw new Error('任务不存在');
|
|
196
|
+
task.resumeAfterRework();
|
|
197
|
+
return task;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** 恢复边:无共识任务重新开放(v2.6.0,消除吸收态) */
|
|
201
|
+
reopenTask(taskId) {
|
|
202
|
+
const task = this.tasks.get(taskId);
|
|
203
|
+
if (!task) throw new Error('任务不存在');
|
|
204
|
+
task.reopenAfterNoQuorum();
|
|
183
205
|
return task;
|
|
184
206
|
}
|
|
185
207
|
|
|
@@ -195,6 +217,14 @@ class AgentMarket {
|
|
|
195
217
|
return { paid: 0, reason: 'rejected' };
|
|
196
218
|
}
|
|
197
219
|
|
|
220
|
+
// 证据分级强制闸门(v2.6.0):需要验证的任务,结果证据必须可信;
|
|
221
|
+
// policy='None' 时豁免。
|
|
222
|
+
if (task.verificationPolicy !== 'None') {
|
|
223
|
+
if (task.evidenceGrade !== 'Verified' && task.evidenceGrade !== 'CpuProto') {
|
|
224
|
+
return { paid: 0, reason: 'untrusted_evidence' };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
198
228
|
const price = task.winnerPrice || task.budget;
|
|
199
229
|
const pay = Math.min(price, task.budget);
|
|
200
230
|
|
package/js/lib/mcp.js
CHANGED
|
@@ -60,7 +60,7 @@ class McpHttpClient {
|
|
|
60
60
|
method: 'initialize',
|
|
61
61
|
params: {
|
|
62
62
|
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
63
|
-
clientInfo: { name: 'agent-universe-js', version: '2.
|
|
63
|
+
clientInfo: { name: 'agent-universe-js', version: '2.6.1' },
|
|
64
64
|
capabilities: {},
|
|
65
65
|
},
|
|
66
66
|
});
|
package/js/lib/models.js
CHANGED
|
@@ -13,6 +13,7 @@ const TaskStatus = {
|
|
|
13
13
|
VERIFIED: 'verified',
|
|
14
14
|
SETTLED: 'settled',
|
|
15
15
|
REWORK: 'rework',
|
|
16
|
+
NO_QUORUM: 'no_quorum',
|
|
16
17
|
DISPUTED: 'disputed',
|
|
17
18
|
REJECTED: 'rejected',
|
|
18
19
|
};
|
|
@@ -24,9 +25,10 @@ const TRANSITIONS = {
|
|
|
24
25
|
[TaskStatus.MATCHED]: [TaskStatus.ASSIGNED],
|
|
25
26
|
[TaskStatus.ASSIGNED]: [TaskStatus.RUNNING],
|
|
26
27
|
[TaskStatus.RUNNING]: [TaskStatus.COMPLETED, TaskStatus.REWORK],
|
|
27
|
-
[TaskStatus.COMPLETED]: [TaskStatus.VERIFIED, TaskStatus.DISPUTED, TaskStatus.REWORK],
|
|
28
|
+
[TaskStatus.COMPLETED]: [TaskStatus.VERIFIED, TaskStatus.DISPUTED, TaskStatus.REWORK, TaskStatus.NO_QUORUM],
|
|
28
29
|
[TaskStatus.VERIFIED]: [TaskStatus.SETTLED],
|
|
29
|
-
[TaskStatus.REWORK]: [TaskStatus.RUNNING],
|
|
30
|
+
[TaskStatus.REWORK]: [TaskStatus.RUNNING], // 恢复边:返工 → 继续执行
|
|
31
|
+
[TaskStatus.NO_QUORUM]: [TaskStatus.OPEN], // 恢复边:无共识 → 重新开放
|
|
30
32
|
[TaskStatus.DISPUTED]: [TaskStatus.SETTLED, TaskStatus.REJECTED],
|
|
31
33
|
[TaskStatus.SETTLED]: [],
|
|
32
34
|
[TaskStatus.REJECTED]: [],
|
|
@@ -78,6 +80,8 @@ class Task {
|
|
|
78
80
|
this.goal = goal;
|
|
79
81
|
this.status = TaskStatus.PENDING;
|
|
80
82
|
this.assignee = null;
|
|
83
|
+
this.verificationPolicy = 'BftLite'; // 验证策略;'None' 时提交即验收、豁免证据门禁
|
|
84
|
+
this.evidenceGrade = null; // 结果信封证据等级
|
|
81
85
|
this.history = [TaskStatus.PENDING];
|
|
82
86
|
}
|
|
83
87
|
|
|
@@ -116,6 +120,27 @@ class Task {
|
|
|
116
120
|
throw new Error('只有验证通过的任务才能结算');
|
|
117
121
|
}
|
|
118
122
|
|
|
123
|
+
/** 本轮验收无共识(v2.6.0) */
|
|
124
|
+
markNoQuorum() {
|
|
125
|
+
return this.transition(TaskStatus.NO_QUORUM);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** 恢复边:无共识任务重新开放(v2.6.0,消除吸收态) */
|
|
129
|
+
reopenAfterNoQuorum() {
|
|
130
|
+
if (this.status !== TaskStatus.NO_QUORUM) {
|
|
131
|
+
throw new Error(`只有 NO_QUORUM 状态才能重新开放,当前 ${this.status}`);
|
|
132
|
+
}
|
|
133
|
+
return this.transition(TaskStatus.OPEN);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** 恢复边:返工任务回到执行中(v2.6.0) */
|
|
137
|
+
resumeAfterRework() {
|
|
138
|
+
if (this.status !== TaskStatus.REWORK) {
|
|
139
|
+
throw new Error(`只有 REWORK 状态才能恢复执行,当前 ${this.status}`);
|
|
140
|
+
}
|
|
141
|
+
return this.transition(TaskStatus.RUNNING);
|
|
142
|
+
}
|
|
143
|
+
|
|
119
144
|
get isTerminal() {
|
|
120
145
|
return this.status === TaskStatus.SETTLED || this.status === TaskStatus.REJECTED;
|
|
121
146
|
}
|
package/js/package-lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@twinsearth/agent-universe",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.1",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@twinsearth/agent-universe",
|
|
9
|
-
"version": "2.
|
|
9
|
+
"version": "2.6.1",
|
|
10
10
|
"license": "MIT",
|
|
11
11
|
"engines": {
|
|
12
12
|
"node": ">=18"
|
package/js/package.json
CHANGED
package/js/test/test.js
CHANGED
|
@@ -43,8 +43,8 @@ function test(name, fn) {
|
|
|
43
43
|
console.log('Agent Universe JS SDK 测试\n');
|
|
44
44
|
|
|
45
45
|
// 1. 版本号
|
|
46
|
-
test('版本号为 2.
|
|
47
|
-
assert.strictEqual(version, '2.
|
|
46
|
+
test('版本号为 2.6.1', () => {
|
|
47
|
+
assert.strictEqual(version, '2.6.1');
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
// 2. 密钥对 + DID + 签名验证
|
|
@@ -352,6 +352,71 @@ test('ACA receipt 签名、结果哈希正反例', () => {
|
|
|
352
352
|
assert.ok(!verifyReceiptResult(receipt, Buffer.from('other')));
|
|
353
353
|
});
|
|
354
354
|
|
|
355
|
+
// 13. v2.6.0 状态机恢复边:rework→running、no_quorum→open
|
|
356
|
+
test('v2.6.0 状态机恢复边', () => {
|
|
357
|
+
const market = new AgentMarket();
|
|
358
|
+
market.deposit('did:au:req', 50);
|
|
359
|
+
market.publishTask('task-1', 'goal', 50, 'did:au:req');
|
|
360
|
+
const t = market.tasks.get('task-1');
|
|
361
|
+
t.assign('did:au:worker'); // OPEN→MATCHED→ASSIGNED
|
|
362
|
+
t.start(); // ASSIGNED→RUNNING
|
|
363
|
+
t.complete(); // RUNNING→COMPLETED
|
|
364
|
+
|
|
365
|
+
// 返工 → 恢复执行
|
|
366
|
+
t.transition(TaskStatus.REWORK);
|
|
367
|
+
assert.strictEqual(t.status, TaskStatus.REWORK);
|
|
368
|
+
market.resumeAfterRework('task-1');
|
|
369
|
+
assert.strictEqual(t.status, TaskStatus.RUNNING);
|
|
370
|
+
// 非 REWORK 不能恢复
|
|
371
|
+
assert.throws(() => market.resumeAfterRework('task-1'), /REWORK/);
|
|
372
|
+
|
|
373
|
+
// 无共识 → 重新开放
|
|
374
|
+
t.complete(); // RUNNING→COMPLETED
|
|
375
|
+
t.markNoQuorum(); // COMPLETED→NO_QUORUM
|
|
376
|
+
assert.strictEqual(t.status, TaskStatus.NO_QUORUM);
|
|
377
|
+
market.reopenTask('task-1'); // NO_QUORUM→OPEN
|
|
378
|
+
assert.strictEqual(t.status, TaskStatus.OPEN);
|
|
379
|
+
// 非 NO_QUORUM 不能 reopen
|
|
380
|
+
assert.throws(() => market.reopenTask('task-1'), /NO_QUORUM/);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
// 14. v2.6.0 Unverified 证据拒绝结算
|
|
384
|
+
test('v2.6.0 Unverified 证据拒绝结算', () => {
|
|
385
|
+
const market = new AgentMarket();
|
|
386
|
+
const owner = 'did:au:owner';
|
|
387
|
+
market.deposit(owner, 100);
|
|
388
|
+
market.deposit('did:au:req', 50);
|
|
389
|
+
market.registerAgent(AgentCard.new({ did: owner, name: 'w' }), MIN_STAKE);
|
|
390
|
+
market.publishTask('task-1', 'goal', 50, 'did:au:req');
|
|
391
|
+
market.submitBid('task-1', owner, 40);
|
|
392
|
+
market.matchTask('task-1');
|
|
393
|
+
// 验收通过但证据 Unverified
|
|
394
|
+
market.completeTask('task-1', true, 'Unverified');
|
|
395
|
+
assert.strictEqual(market.tasks.get('task-1').status, TaskStatus.VERIFIED);
|
|
396
|
+
const r = market.settle('task-1');
|
|
397
|
+
assert.strictEqual(r.reason, 'untrusted_evidence');
|
|
398
|
+
assert.strictEqual(r.paid, 0);
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
// 15. v2.6.0 policy=None 提交即验收、豁免证据门禁
|
|
402
|
+
test('v2.6.0 policy=None 提交即验收并豁免证据', () => {
|
|
403
|
+
const market = new AgentMarket();
|
|
404
|
+
const owner = 'did:au:owner';
|
|
405
|
+
market.deposit(owner, 100);
|
|
406
|
+
market.deposit('did:au:req', 50);
|
|
407
|
+
market.registerAgent(AgentCard.new({ did: owner, name: 'w' }), MIN_STAKE);
|
|
408
|
+
const t = market.publishTask('task-1', 'goal', 50, 'did:au:req');
|
|
409
|
+
t.verificationPolicy = 'None';
|
|
410
|
+
market.submitBid('task-1', owner, 40);
|
|
411
|
+
market.matchTask('task-1');
|
|
412
|
+
// 无 QA 投票,提交(证据 Unverified)即验收
|
|
413
|
+
market.completeTask('task-1', true, 'Unverified');
|
|
414
|
+
assert.strictEqual(t.status, TaskStatus.VERIFIED);
|
|
415
|
+
const r = market.settle('task-1');
|
|
416
|
+
assert.strictEqual(r.reason, 'settled');
|
|
417
|
+
assert.strictEqual(r.paid, 40);
|
|
418
|
+
});
|
|
419
|
+
|
|
355
420
|
console.log(`\n${passed} 项测试通过`);
|
|
356
421
|
if (process.exitCode === 1) {
|
|
357
422
|
console.error('存在失败测试');
|