@dxos/edge-client 0.9.1-main.c7dcc2e112 → 0.10.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/lib/neutral/index.mjs +29 -28
- package/dist/lib/neutral/index.mjs.map +3 -3
- package/dist/lib/neutral/meta.json +1 -1
- package/dist/lib/neutral/testing/index.mjs +1 -1
- package/dist/lib/neutral/testing/index.mjs.map +2 -2
- package/dist/types/src/auth.d.ts.map +1 -1
- package/dist/types/src/browser-rendering.d.ts +28 -0
- package/dist/types/src/browser-rendering.d.ts.map +1 -0
- package/dist/types/src/edge-client.d.ts +3 -2
- package/dist/types/src/edge-client.d.ts.map +1 -1
- package/dist/types/src/edge-http-client.d.ts +2 -2
- package/dist/types/src/edge-http-client.d.ts.map +1 -1
- package/dist/types/src/edge-identity.d.ts +5 -1
- package/dist/types/src/edge-identity.d.ts.map +1 -1
- package/dist/types/src/hub-http-client.d.ts +1 -1
- package/dist/types/src/hub-http-client.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/auth.ts +6 -6
- package/src/base-http-client.ts +1 -1
- package/src/browser-rendering.ts +39 -0
- package/src/edge-client.test.ts +1 -1
- package/src/edge-client.ts +9 -7
- package/src/edge-http-client.ts +7 -4
- package/src/edge-identity.ts +5 -1
- package/src/edge-ws-connection.ts +1 -1
- package/src/edge-ws-muxer.test.ts +1 -1
- package/src/hub-http-client.ts +1 -1
- package/src/testing/test-utils.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/edge-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "EDGE Client",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -46,29 +46,29 @@
|
|
|
46
46
|
"README.md"
|
|
47
47
|
],
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@effect/platform": "0.96.
|
|
49
|
+
"@effect/platform": "0.96.2",
|
|
50
50
|
"@opentelemetry/api": "^1.9.1",
|
|
51
51
|
"isomorphic-ws": "^5.0.0",
|
|
52
52
|
"ws": "^8.17.1",
|
|
53
|
-
"@dxos/
|
|
54
|
-
"@dxos/
|
|
55
|
-
"@dxos/
|
|
56
|
-
"@dxos/errors": "0.
|
|
57
|
-
"@dxos/
|
|
58
|
-
"@dxos/invariant": "0.
|
|
59
|
-
"@dxos/keyring": "0.
|
|
60
|
-
"@dxos/keys": "0.
|
|
61
|
-
"@dxos/node-std": "0.
|
|
62
|
-
"@dxos/
|
|
63
|
-
"@dxos/
|
|
64
|
-
"@dxos/
|
|
65
|
-
"@dxos/
|
|
53
|
+
"@dxos/async": "0.10.0",
|
|
54
|
+
"@dxos/effect": "0.10.0",
|
|
55
|
+
"@dxos/context": "0.10.0",
|
|
56
|
+
"@dxos/errors": "0.10.0",
|
|
57
|
+
"@dxos/crypto": "0.10.0",
|
|
58
|
+
"@dxos/invariant": "0.10.0",
|
|
59
|
+
"@dxos/keyring": "0.10.0",
|
|
60
|
+
"@dxos/keys": "0.10.0",
|
|
61
|
+
"@dxos/node-std": "0.10.0",
|
|
62
|
+
"@dxos/protocols": "0.10.0",
|
|
63
|
+
"@dxos/log": "0.10.0",
|
|
64
|
+
"@dxos/util": "0.10.0",
|
|
65
|
+
"@dxos/credentials": "0.10.0"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@dxos/test-utils": "0.
|
|
68
|
+
"@dxos/test-utils": "0.10.0"
|
|
69
69
|
},
|
|
70
70
|
"peerDependencies": {
|
|
71
|
-
"effect": "3.21.
|
|
71
|
+
"effect": "3.21.4"
|
|
72
72
|
},
|
|
73
73
|
"publishConfig": {
|
|
74
74
|
"access": "public"
|
package/src/auth.ts
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { createCredential, signPresentation } from '@dxos/credentials';
|
|
5
|
+
import { createCredential, createDidFromIdentityKey, signPresentation } from '@dxos/credentials';
|
|
6
6
|
import { type Signer } from '@dxos/crypto';
|
|
7
7
|
import { invariant } from '@dxos/invariant';
|
|
8
8
|
import { Keyring } from '@dxos/keyring';
|
|
9
|
-
import { PublicKey } from '@dxos/keys';
|
|
9
|
+
import { IdentityDid, PublicKey } from '@dxos/keys';
|
|
10
10
|
import { type Chain, type Credential } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
11
11
|
|
|
12
12
|
import type { EdgeIdentity } from './edge-identity';
|
|
@@ -16,7 +16,7 @@ import type { EdgeIdentity } from './edge-identity';
|
|
|
16
16
|
*/
|
|
17
17
|
export const createDeviceEdgeIdentity = async (signer: Signer, key: PublicKey): Promise<EdgeIdentity> => {
|
|
18
18
|
return {
|
|
19
|
-
|
|
19
|
+
identityDid: await createDidFromIdentityKey(key),
|
|
20
20
|
peerKey: key.toHex(),
|
|
21
21
|
presentCredentials: async ({ challenge }) => {
|
|
22
22
|
return signPresentation({
|
|
@@ -68,7 +68,7 @@ export const createChainEdgeIdentity = async (
|
|
|
68
68
|
];
|
|
69
69
|
|
|
70
70
|
return {
|
|
71
|
-
|
|
71
|
+
identityDid: await createDidFromIdentityKey(identityKey),
|
|
72
72
|
peerKey: peerKey.toHex(),
|
|
73
73
|
presentCredentials: async ({ challenge }) => {
|
|
74
74
|
// TODO: make chain required after device invitation flow update release
|
|
@@ -126,10 +126,10 @@ export const createTestHaloEdgeIdentity = async (
|
|
|
126
126
|
};
|
|
127
127
|
|
|
128
128
|
export const createStubEdgeIdentity = (): EdgeIdentity => {
|
|
129
|
-
const identityKey = PublicKey.random();
|
|
130
129
|
const deviceKey = PublicKey.random();
|
|
131
130
|
return {
|
|
132
|
-
|
|
131
|
+
// Random placeholder DID — the stub never authenticates or connects; a real identity replaces it.
|
|
132
|
+
identityDid: IdentityDid.random(),
|
|
133
133
|
peerKey: deviceKey.toHex(),
|
|
134
134
|
presentCredentials: async () => {
|
|
135
135
|
throw new Error('Stub identity does not support authentication.');
|
package/src/base-http-client.ts
CHANGED
|
@@ -71,7 +71,7 @@ export abstract class BaseHttpClient {
|
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
setIdentity(identity: EdgeIdentity): void {
|
|
74
|
-
if (this._edgeIdentity?.
|
|
74
|
+
if (this._edgeIdentity?.identityDid !== identity.identityDid || this._edgeIdentity?.peerKey !== identity.peerKey) {
|
|
75
75
|
this._edgeIdentity = identity;
|
|
76
76
|
this._authHeader = undefined;
|
|
77
77
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import * as Context from 'effect/Context';
|
|
6
|
+
import * as Schema from 'effect/Schema';
|
|
7
|
+
|
|
8
|
+
import { type EdgeHttpClient } from './edge-http-client';
|
|
9
|
+
|
|
10
|
+
/** Request body for EDGE `/ai/browser-rendering/markdown` (ai-service Browser Run markdown quick action). */
|
|
11
|
+
export const MarkdownRequest = Schema.Struct({
|
|
12
|
+
url: Schema.optional(Schema.String),
|
|
13
|
+
html: Schema.optional(Schema.String),
|
|
14
|
+
gotoOptions: Schema.optional(
|
|
15
|
+
Schema.Struct({
|
|
16
|
+
waitUntil: Schema.optional(Schema.Literal('load', 'domcontentloaded', 'networkidle0', 'networkidle2')),
|
|
17
|
+
timeout: Schema.optional(Schema.Number),
|
|
18
|
+
}),
|
|
19
|
+
),
|
|
20
|
+
rejectRequestPattern: Schema.optional(Schema.Array(Schema.String)),
|
|
21
|
+
userAgent: Schema.optional(Schema.String),
|
|
22
|
+
waitForSelector: Schema.optional(Schema.String),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export type MarkdownRequest = Schema.Schema.Type<typeof MarkdownRequest>;
|
|
26
|
+
|
|
27
|
+
/** JSON body returned by Cloudflare Browser Run markdown quick action. */
|
|
28
|
+
export const MarkdownResponse = Schema.Struct({
|
|
29
|
+
success: Schema.Boolean,
|
|
30
|
+
result: Schema.String,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export type MarkdownResponse = Schema.Schema.Type<typeof MarkdownResponse>;
|
|
34
|
+
|
|
35
|
+
/** Authenticated EDGE HTTP client for operation handlers (e.g. browser markdown fetch). */
|
|
36
|
+
export class EdgeHttpClientService extends Context.Tag('@dxos/edge-client/EdgeHttpClientService')<
|
|
37
|
+
EdgeHttpClientService,
|
|
38
|
+
EdgeHttpClient
|
|
39
|
+
>() {}
|
package/src/edge-client.test.ts
CHANGED
|
@@ -158,7 +158,7 @@ describe('EdgeClient', () => {
|
|
|
158
158
|
|
|
159
159
|
const textMessage = (message: string, source?: EdgeIdentity) =>
|
|
160
160
|
protocol.createMessage(TextMessageSchema, {
|
|
161
|
-
source: source && { peerKey: source.peerKey,
|
|
161
|
+
source: source && { peerKey: source.peerKey, identityDid: source.identityDid },
|
|
162
162
|
payload: { message },
|
|
163
163
|
});
|
|
164
164
|
|
package/src/edge-client.ts
CHANGED
|
@@ -43,7 +43,8 @@ export type MessengerConfig = {
|
|
|
43
43
|
export interface EdgeConnection extends Required<Lifecycle> {
|
|
44
44
|
statusChanged: Event<EdgeStatus>;
|
|
45
45
|
get info(): any;
|
|
46
|
-
|
|
46
|
+
/** Identity DID (`did:halo:…`) of the connected identity. */
|
|
47
|
+
get identityDid(): string;
|
|
47
48
|
get peerKey(): string;
|
|
48
49
|
get isOpen(): boolean;
|
|
49
50
|
get status(): EdgeStatus;
|
|
@@ -88,7 +89,7 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
88
89
|
return {
|
|
89
90
|
open: this.isOpen,
|
|
90
91
|
status: this.status,
|
|
91
|
-
identity: this._identity.
|
|
92
|
+
identity: this._identity.identityDid,
|
|
92
93
|
device: this._identity.peerKey,
|
|
93
94
|
};
|
|
94
95
|
}
|
|
@@ -108,8 +109,8 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
108
109
|
};
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
get
|
|
112
|
-
return this._identity.
|
|
112
|
+
get identityDid() {
|
|
113
|
+
return this._identity.identityDid;
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
get peerKey() {
|
|
@@ -117,7 +118,7 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
117
118
|
}
|
|
118
119
|
|
|
119
120
|
setIdentity(identity: EdgeIdentity) {
|
|
120
|
-
if (identity.
|
|
121
|
+
if (identity.identityDid !== this._identity.identityDid || identity.peerKey !== this._identity.peerKey) {
|
|
121
122
|
log('Edge identity changed', { identity, oldIdentity: this._identity });
|
|
122
123
|
this._identity = identity;
|
|
123
124
|
this._closeCurrentConnection(new EdgeIdentityChangedError());
|
|
@@ -139,9 +140,10 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
139
140
|
throw new EdgeConnectionClosedError();
|
|
140
141
|
}
|
|
141
142
|
|
|
143
|
+
// DX-1059: sources are DID-only; validate against identityDid.
|
|
142
144
|
if (
|
|
143
145
|
message.source &&
|
|
144
|
-
(message.source.peerKey !== this._identity.peerKey || message.source.
|
|
146
|
+
(message.source.peerKey !== this._identity.peerKey || message.source.identityDid !== this.identityDid)
|
|
145
147
|
) {
|
|
146
148
|
throw new EdgeIdentityChangedError();
|
|
147
149
|
}
|
|
@@ -219,7 +221,7 @@ export class EdgeClient extends Resource implements EdgeConnection {
|
|
|
219
221
|
}
|
|
220
222
|
|
|
221
223
|
const identity = this._identity;
|
|
222
|
-
const path = `/ws/${identity.
|
|
224
|
+
const path = `/ws/${identity.identityDid}/${identity.peerKey}`;
|
|
223
225
|
const protocolHeader = this._config.disableAuth ? undefined : await this._createAuthHeader(path);
|
|
224
226
|
if (this._identity !== identity) {
|
|
225
227
|
log('identity changed during auth header request');
|
package/src/edge-http-client.ts
CHANGED
|
@@ -11,7 +11,7 @@ import * as Function from 'effect/Function';
|
|
|
11
11
|
import { type Context } from '@dxos/context';
|
|
12
12
|
import { EffectEx } from '@dxos/effect';
|
|
13
13
|
import { invariant } from '@dxos/invariant';
|
|
14
|
-
import { type
|
|
14
|
+
import { type SpaceId } from '@dxos/keys';
|
|
15
15
|
import { log } from '@dxos/log';
|
|
16
16
|
import {
|
|
17
17
|
type CompleteOAuthRegistrationRequest,
|
|
@@ -117,10 +117,10 @@ export class EdgeHttpClient extends BaseHttpClient {
|
|
|
117
117
|
|
|
118
118
|
public getAgentStatus(
|
|
119
119
|
ctx: Context,
|
|
120
|
-
request: {
|
|
120
|
+
request: { ownerIdentityDid: string },
|
|
121
121
|
args?: EdgeHttpCallArgs,
|
|
122
122
|
): Promise<GetAgentStatusResponseBody> {
|
|
123
|
-
return this._call(ctx, new URL(`/users/${request.
|
|
123
|
+
return this._call(ctx, new URL(`/users/${request.ownerIdentityDid}/agent/status`, this.baseUrl), {
|
|
124
124
|
...args,
|
|
125
125
|
method: 'GET',
|
|
126
126
|
});
|
|
@@ -271,7 +271,10 @@ export class EdgeHttpClient extends BaseHttpClient {
|
|
|
271
271
|
const formData = new FormData();
|
|
272
272
|
formData.append('name', body.name ?? '');
|
|
273
273
|
formData.append('version', body.version);
|
|
274
|
-
|
|
274
|
+
// The function owner is the authenticated identity (edge requires ownerUri === presenter DID).
|
|
275
|
+
// Prefer the connected identity's DID; otherwise use the DID supplied on the request body.
|
|
276
|
+
const ownerUri = this._edgeIdentity?.identityDid ?? body.ownerUri;
|
|
277
|
+
formData.append('ownerUri', ownerUri);
|
|
275
278
|
formData.append('entryPoint', body.entryPoint);
|
|
276
279
|
body.runtime && formData.append('runtime', body.runtime);
|
|
277
280
|
for (const [filename, content] of Object.entries(body.assets)) {
|
package/src/edge-identity.ts
CHANGED
|
@@ -8,7 +8,11 @@ import { type Presentation } from '@dxos/protocols/proto/dxos/halo/credentials';
|
|
|
8
8
|
|
|
9
9
|
export interface EdgeIdentity {
|
|
10
10
|
peerKey: string;
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Identity DID (`did:halo:…`) — the public identity segment of the edge WebSocket path.
|
|
13
|
+
* The router keys connections by the DID.
|
|
14
|
+
*/
|
|
15
|
+
identityDid: string;
|
|
12
16
|
/**
|
|
13
17
|
* Returns credential presentation issued by the identity key.
|
|
14
18
|
* Presentation must have the provided challenge.
|
|
@@ -35,7 +35,7 @@ describe('WebSocketMuxerTest', () => {
|
|
|
35
35
|
|
|
36
36
|
const textMessage = (message: string, source?: EdgeIdentity) =>
|
|
37
37
|
protocol.createMessage(TextMessageSchema, {
|
|
38
|
-
source: source && { peerKey: source.peerKey,
|
|
38
|
+
source: source && { peerKey: source.peerKey, identityDid: source.identityDid },
|
|
39
39
|
serviceId: 'test-service',
|
|
40
40
|
payload: { message },
|
|
41
41
|
});
|
package/src/hub-http-client.ts
CHANGED
|
@@ -6,6 +6,7 @@ import { type Context } from '@dxos/context';
|
|
|
6
6
|
import {
|
|
7
7
|
type CheckEmailExistsResponse,
|
|
8
8
|
type GetAccountResponse,
|
|
9
|
+
type GetProfileUsageResponse,
|
|
9
10
|
type IssueInvitationResponse,
|
|
10
11
|
type ListAccountInvitationsResponse,
|
|
11
12
|
type LoginRequest,
|
|
@@ -14,7 +15,6 @@ import {
|
|
|
14
15
|
type RedeemInvitationCodeResponse,
|
|
15
16
|
type RequestAccessRequest,
|
|
16
17
|
type RequestAccessResponse,
|
|
17
|
-
type GetProfileUsageResponse,
|
|
18
18
|
type ResendVerificationEmailResponse,
|
|
19
19
|
type ValidateInvitationCodeResponse,
|
|
20
20
|
} from '@dxos/protocols';
|
|
@@ -106,7 +106,7 @@ const createResponseSender = (connection: () => WebSocketMuxer) => {
|
|
|
106
106
|
void connection().send(
|
|
107
107
|
buf.create(MessageSchema, {
|
|
108
108
|
source: {
|
|
109
|
-
|
|
109
|
+
identityDid: recipient.identityDid,
|
|
110
110
|
peerKey: recipient.peerKey,
|
|
111
111
|
},
|
|
112
112
|
serviceId: request.serviceId!,
|