downcity 1.0.496 → 1.0.498
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoteClient.d.ts","sourceRoot":"","sources":["../../../../src/services/contact/runtime/RemoteClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"RemoteClient.d.ts","sourceRoot":"","sources":["../../../../src/services/contact/runtime/RemoteClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAwDxD;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,CAAC,CAAC,CAMb;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,CAAC,EAAE,MAAM,EAAE;IAClD,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;CACjB,GAAG,OAAO,CAAC,CAAC,CAAC,CAMb;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;CACjB,GAAG,OAAO,CAAC,CAAC,CAAC,CAOb;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,SAAS,CAAC;CACjB,GAAG,OAAO,CAAC,CAAC,CAAC,CAOb"}
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
* - contact 的 agent-to-agent 调用走独立轻量路由,不依赖用户 CLI auth。
|
|
6
6
|
* - 已建联后的敏感调用必须携带 contact token。
|
|
7
7
|
*/
|
|
8
|
+
function isRecord(value) {
|
|
9
|
+
return Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
10
|
+
}
|
|
8
11
|
function normalizeEndpoint(endpoint) {
|
|
9
12
|
const raw = String(endpoint || "").trim();
|
|
10
13
|
if (!raw)
|
|
@@ -16,6 +19,16 @@ function normalizeEndpoint(endpoint) {
|
|
|
16
19
|
url.hash = "";
|
|
17
20
|
return url.toString().replace(/\/$/, "");
|
|
18
21
|
}
|
|
22
|
+
function unwrapServiceActionEnvelope(value) {
|
|
23
|
+
if (!isRecord(value))
|
|
24
|
+
return value;
|
|
25
|
+
const inner = value.data;
|
|
26
|
+
if (typeof value.success === "boolean" && isRecord(inner)) {
|
|
27
|
+
// 关键点(中文):远端 contact API 挂在统一 service action route 下,HTTP 返回会包一层 { success, data }。
|
|
28
|
+
return inner;
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
19
32
|
async function postJson(params) {
|
|
20
33
|
const url = new URL(params.path, normalizeEndpoint(params.endpoint)).toString();
|
|
21
34
|
const headers = {
|
|
@@ -32,7 +45,7 @@ async function postJson(params) {
|
|
|
32
45
|
if (!response.ok) {
|
|
33
46
|
throw new Error(data?.error || data?.message || `HTTP ${response.status}`);
|
|
34
47
|
}
|
|
35
|
-
return data;
|
|
48
|
+
return unwrapServiceActionEnvelope(data);
|
|
36
49
|
}
|
|
37
50
|
/**
|
|
38
51
|
* 调用远端 ping。
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RemoteClient.js","sourceRoot":"","sources":["../../../../src/services/contact/runtime/RemoteClient.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"RemoteClient.js","sourceRoot":"","sources":["../../../../src/services/contact/runtime/RemoteClient.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
} from "../../bin/services/contact/runtime/InboxStore.js";
|
|
33
33
|
import {
|
|
34
34
|
listContacts,
|
|
35
|
+
saveContact,
|
|
35
36
|
} from "../../bin/services/contact/runtime/ContactStore.js";
|
|
36
37
|
import {
|
|
37
38
|
saveContactLinkRecord,
|
|
@@ -500,6 +501,62 @@ test("approve without endpoint creates an outbound-only local contact", async ()
|
|
|
500
501
|
}
|
|
501
502
|
});
|
|
502
503
|
|
|
504
|
+
test("approve unwraps remote service action envelope", async () => {
|
|
505
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-contact-approve-envelope-"));
|
|
506
|
+
const originalFetch = globalThis.fetch;
|
|
507
|
+
try {
|
|
508
|
+
const service = new ContactService(null);
|
|
509
|
+
const code = createContactLinkCode({
|
|
510
|
+
version: 1,
|
|
511
|
+
linkId: "link_server",
|
|
512
|
+
agentName: "server-agent",
|
|
513
|
+
endpoint: "https://agent-a.example.com",
|
|
514
|
+
secret: "secret-token",
|
|
515
|
+
createdAt: Date.now(),
|
|
516
|
+
expiresAt: Date.now() + 600_000,
|
|
517
|
+
});
|
|
518
|
+
globalThis.fetch = async () =>
|
|
519
|
+
new Response(JSON.stringify({
|
|
520
|
+
success: true,
|
|
521
|
+
data: {
|
|
522
|
+
success: true,
|
|
523
|
+
agentName: "server-agent",
|
|
524
|
+
endpoint: "https://agent-a.example.com",
|
|
525
|
+
tokenForOwner: "local-can-call-server",
|
|
526
|
+
},
|
|
527
|
+
}), {
|
|
528
|
+
status: 200,
|
|
529
|
+
headers: {
|
|
530
|
+
"Content-Type": "application/json",
|
|
531
|
+
},
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
const result = await service.actions.approve.execute({
|
|
535
|
+
context: {
|
|
536
|
+
rootPath: root,
|
|
537
|
+
config: {
|
|
538
|
+
name: "local-agent",
|
|
539
|
+
start: {
|
|
540
|
+
host: "127.0.0.1",
|
|
541
|
+
port: 5314,
|
|
542
|
+
},
|
|
543
|
+
},
|
|
544
|
+
},
|
|
545
|
+
payload: {
|
|
546
|
+
code,
|
|
547
|
+
},
|
|
548
|
+
});
|
|
549
|
+
|
|
550
|
+
assert.equal(result.success, true);
|
|
551
|
+
const contacts = await listContacts(root);
|
|
552
|
+
assert.equal(contacts.length, 1);
|
|
553
|
+
assert.equal(contacts[0].outboundToken, "local-can-call-server");
|
|
554
|
+
} finally {
|
|
555
|
+
globalThis.fetch = originalFetch;
|
|
556
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
|
|
503
560
|
test("approve sends requester endpoint from global public host", async () => {
|
|
504
561
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-contact-bidirectional-"));
|
|
505
562
|
const originalFetch = globalThis.fetch;
|
|
@@ -566,6 +623,61 @@ test("approve sends requester endpoint from global public host", async () => {
|
|
|
566
623
|
}
|
|
567
624
|
});
|
|
568
625
|
|
|
626
|
+
test("share unwraps remote service action envelope", async () => {
|
|
627
|
+
const root = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-contact-share-envelope-"));
|
|
628
|
+
const originalFetch = globalThis.fetch;
|
|
629
|
+
try {
|
|
630
|
+
const service = new ContactService(null);
|
|
631
|
+
await saveContact(root, {
|
|
632
|
+
id: "contact_server_agent",
|
|
633
|
+
name: "server-agent",
|
|
634
|
+
endpoint: "https://agent-a.example.com",
|
|
635
|
+
reachability: "outbound",
|
|
636
|
+
status: "trusted",
|
|
637
|
+
outboundToken: "local-can-call-server",
|
|
638
|
+
inboundTokenHash: null,
|
|
639
|
+
createdAt: Date.now(),
|
|
640
|
+
lastSeenAt: Date.now(),
|
|
641
|
+
});
|
|
642
|
+
globalThis.fetch = async () =>
|
|
643
|
+
new Response(JSON.stringify({
|
|
644
|
+
success: true,
|
|
645
|
+
data: {
|
|
646
|
+
success: true,
|
|
647
|
+
shareId: "remote_share_123",
|
|
648
|
+
},
|
|
649
|
+
}), {
|
|
650
|
+
status: 200,
|
|
651
|
+
headers: {
|
|
652
|
+
"Content-Type": "application/json",
|
|
653
|
+
},
|
|
654
|
+
});
|
|
655
|
+
|
|
656
|
+
const result = await service.actions.share.execute({
|
|
657
|
+
context: {
|
|
658
|
+
rootPath: root,
|
|
659
|
+
config: {
|
|
660
|
+
name: "local-agent",
|
|
661
|
+
start: {
|
|
662
|
+
host: "127.0.0.1",
|
|
663
|
+
port: 5314,
|
|
664
|
+
},
|
|
665
|
+
},
|
|
666
|
+
},
|
|
667
|
+
payload: {
|
|
668
|
+
to: "server-agent",
|
|
669
|
+
text: "hello",
|
|
670
|
+
},
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
assert.equal(result.success, true);
|
|
674
|
+
assert.equal(result.data.shareId, "remote_share_123");
|
|
675
|
+
} finally {
|
|
676
|
+
globalThis.fetch = originalFetch;
|
|
677
|
+
await fs.rm(root, { recursive: true, force: true });
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
|
|
569
681
|
test("inbox stores each share as a directory with lightweight meta and files", async () => {
|
|
570
682
|
const root = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-contact-inbox-"));
|
|
571
683
|
try {
|