dsh-deeppilot 0.8.1 → 0.8.2
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/COMPATIBILITY.md +20 -145
- package/README.md +9 -29
- package/README.zh-CN.md +7 -25
- package/lib/client.js +21 -59
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +21 -27
- package/lib/index.js +41 -136
- package/lib/index.js.map +1 -1
- package/package.json +20 -20
package/lib/index.d.ts
CHANGED
|
@@ -264,8 +264,8 @@ interface SessionsApiLike {
|
|
|
264
264
|
};
|
|
265
265
|
data: string;
|
|
266
266
|
}>>;
|
|
267
|
-
/**
|
|
268
|
-
projections
|
|
267
|
+
/** Complete projection baseline for one session; null when it is gone. */
|
|
268
|
+
projections(req: RpcRequestLike<{
|
|
269
269
|
sessionId: string;
|
|
270
270
|
}>): Promise<RpcResponseLike<{
|
|
271
271
|
asOfSeq: number;
|
|
@@ -446,12 +446,6 @@ interface ApiProxyLike {
|
|
|
446
446
|
sessions: SessionsApiLike;
|
|
447
447
|
workspace?: WorkspaceApiLike;
|
|
448
448
|
host?: HostApiLike;
|
|
449
|
-
/**
|
|
450
|
-
* DSH 0.1.7 added `session.projections`. Absent/false keeps the bridge on
|
|
451
|
-
* its existing list-row projection hints — the call is gated on this flag so
|
|
452
|
-
* older hosts never see a failing RPC.
|
|
453
|
-
*/
|
|
454
|
-
supportsProjections?: boolean;
|
|
455
449
|
respond(message: {
|
|
456
450
|
type: 'client-response';
|
|
457
451
|
rpcId: string;
|
|
@@ -639,7 +633,7 @@ declare class HostBridge {
|
|
|
639
633
|
/** Tail history for an opened session; pushes s2c.session.tail to the sink. */
|
|
640
634
|
openSession(sink: BridgeSink, sessionId: string, tailCount: number): Promise<boolean>;
|
|
641
635
|
/**
|
|
642
|
-
* Pull one session's projection baseline
|
|
636
|
+
* Pull one session's projection baseline and fold every key
|
|
643
637
|
* through applyProjection — unknown keys are ignored there, `null` means the
|
|
644
638
|
* session no longer exists, and any failure degrades to a diagnostic: opening
|
|
645
639
|
* a session must never fail because a baseline could not be read.
|
|
@@ -744,18 +738,18 @@ interface Config {
|
|
|
744
738
|
};
|
|
745
739
|
}
|
|
746
740
|
declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
747
|
-
enabled: z<boolean, boolean, "defined">;
|
|
741
|
+
enabled: z<boolean, boolean, "volatile-defined">;
|
|
748
742
|
devicesPath: z<string, string, "defined">;
|
|
749
743
|
historyBufferMax: z<number, number, "defined">;
|
|
750
|
-
debug: z<boolean, boolean, "defined">;
|
|
751
|
-
local: z<Schemastery.ObjectS<NoInfer<{
|
|
744
|
+
debug: z<boolean, boolean, "volatile-defined">;
|
|
745
|
+
local: z<NoInfer<Schemastery.ObjectS<NoInfer<{
|
|
752
746
|
enabled: z<boolean, boolean, "defined">;
|
|
753
747
|
port: z<number, number, "defined">;
|
|
754
|
-
}
|
|
748
|
+
}>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
|
|
755
749
|
enabled: z<boolean, boolean, "defined">;
|
|
756
750
|
port: z<number, number, "defined">;
|
|
757
|
-
}
|
|
758
|
-
remote: z<Schemastery.ObjectS<NoInfer<{
|
|
751
|
+
}>>>, "volatile-defined">;
|
|
752
|
+
remote: z<NoInfer<Schemastery.ObjectS<NoInfer<{
|
|
759
753
|
enabled: z<boolean, boolean, "defined">;
|
|
760
754
|
provider: z<"tailscale-funnel", "tailscale-funnel", "defined">;
|
|
761
755
|
hostname: z<string, string, "defined">;
|
|
@@ -763,7 +757,7 @@ declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
|
763
757
|
helperPath: z<string, string, "defined">;
|
|
764
758
|
funnelPort: z<443 | 8443 | 10000, 443 | 8443 | 10000, "defined">;
|
|
765
759
|
maxConnectionsPerSource: z<number, number, "defined">;
|
|
766
|
-
}
|
|
760
|
+
}>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
|
|
767
761
|
enabled: z<boolean, boolean, "defined">;
|
|
768
762
|
provider: z<"tailscale-funnel", "tailscale-funnel", "defined">;
|
|
769
763
|
hostname: z<string, string, "defined">;
|
|
@@ -771,7 +765,7 @@ declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
|
771
765
|
helperPath: z<string, string, "defined">;
|
|
772
766
|
funnelPort: z<443 | 8443 | 10000, 443 | 8443 | 10000, "defined">;
|
|
773
767
|
maxConnectionsPerSource: z<number, number, "defined">;
|
|
774
|
-
}
|
|
768
|
+
}>>>, "volatile-defined">;
|
|
775
769
|
push: z<Schemastery.ObjectS<NoInfer<{
|
|
776
770
|
provider: z<"apns" | "none" | "relay", "apns" | "none" | "relay", "defined">;
|
|
777
771
|
contentMode: z<"generic" | "preview", "generic" | "preview", "defined">;
|
|
@@ -792,18 +786,18 @@ declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
|
792
786
|
relayToken: z<string, string, "defined">;
|
|
793
787
|
}>>, "defined">;
|
|
794
788
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
795
|
-
enabled: z<boolean, boolean, "defined">;
|
|
789
|
+
enabled: z<boolean, boolean, "volatile-defined">;
|
|
796
790
|
devicesPath: z<string, string, "defined">;
|
|
797
791
|
historyBufferMax: z<number, number, "defined">;
|
|
798
|
-
debug: z<boolean, boolean, "defined">;
|
|
799
|
-
local: z<Schemastery.ObjectS<NoInfer<{
|
|
792
|
+
debug: z<boolean, boolean, "volatile-defined">;
|
|
793
|
+
local: z<NoInfer<Schemastery.ObjectS<NoInfer<{
|
|
800
794
|
enabled: z<boolean, boolean, "defined">;
|
|
801
795
|
port: z<number, number, "defined">;
|
|
802
|
-
}
|
|
796
|
+
}>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
|
|
803
797
|
enabled: z<boolean, boolean, "defined">;
|
|
804
798
|
port: z<number, number, "defined">;
|
|
805
|
-
}
|
|
806
|
-
remote: z<Schemastery.ObjectS<NoInfer<{
|
|
799
|
+
}>>>, "volatile-defined">;
|
|
800
|
+
remote: z<NoInfer<Schemastery.ObjectS<NoInfer<{
|
|
807
801
|
enabled: z<boolean, boolean, "defined">;
|
|
808
802
|
provider: z<"tailscale-funnel", "tailscale-funnel", "defined">;
|
|
809
803
|
hostname: z<string, string, "defined">;
|
|
@@ -811,7 +805,7 @@ declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
|
811
805
|
helperPath: z<string, string, "defined">;
|
|
812
806
|
funnelPort: z<443 | 8443 | 10000, 443 | 8443 | 10000, "defined">;
|
|
813
807
|
maxConnectionsPerSource: z<number, number, "defined">;
|
|
814
|
-
}
|
|
808
|
+
}>>>, NoInfer<Schemastery.ObjectT<NoInfer<{
|
|
815
809
|
enabled: z<boolean, boolean, "defined">;
|
|
816
810
|
provider: z<"tailscale-funnel", "tailscale-funnel", "defined">;
|
|
817
811
|
hostname: z<string, string, "defined">;
|
|
@@ -819,7 +813,7 @@ declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
|
819
813
|
helperPath: z<string, string, "defined">;
|
|
820
814
|
funnelPort: z<443 | 8443 | 10000, 443 | 8443 | 10000, "defined">;
|
|
821
815
|
maxConnectionsPerSource: z<number, number, "defined">;
|
|
822
|
-
}
|
|
816
|
+
}>>>, "volatile-defined">;
|
|
823
817
|
push: z<Schemastery.ObjectS<NoInfer<{
|
|
824
818
|
provider: z<"apns" | "none" | "relay", "apns" | "none" | "relay", "defined">;
|
|
825
819
|
contentMode: z<"generic" | "preview", "generic" | "preview", "defined">;
|
|
@@ -867,8 +861,8 @@ declare function shouldReEnrollRelayToken(transport: 'apns' | 'relay', outcome:
|
|
|
867
861
|
* devices) and loopback Funnel-origin listeners. The web UI and the rest of
|
|
868
862
|
* DSH's API are never exposed by these listeners.
|
|
869
863
|
*
|
|
870
|
-
* Data plane: an in-process HostBridge consumes a local
|
|
871
|
-
*
|
|
864
|
+
* Data plane: an in-process HostBridge consumes a local adapter over DSH
|
|
865
|
+
* Session/Workspace controllers, mirrors session summaries,
|
|
872
866
|
* tracks pending approvals/questions, and fans projected protocol-v2 pushes
|
|
873
867
|
* out to every connected device.
|
|
874
868
|
*
|
package/lib/index.js
CHANGED
|
@@ -2479,26 +2479,26 @@ var HostBridge = class {
|
|
|
2479
2479
|
hasMore: Boolean(result.hasMore) || page.dropped > 0
|
|
2480
2480
|
});
|
|
2481
2481
|
this.deriveTitleFallback(sessionId, messages);
|
|
2482
|
-
|
|
2482
|
+
this.refreshProjections(sessionId);
|
|
2483
2483
|
return true;
|
|
2484
2484
|
} catch {
|
|
2485
2485
|
return false;
|
|
2486
2486
|
}
|
|
2487
2487
|
}
|
|
2488
2488
|
/**
|
|
2489
|
-
* Pull one session's projection baseline
|
|
2489
|
+
* Pull one session's projection baseline and fold every key
|
|
2490
2490
|
* through applyProjection — unknown keys are ignored there, `null` means the
|
|
2491
2491
|
* session no longer exists, and any failure degrades to a diagnostic: opening
|
|
2492
2492
|
* a session must never fail because a baseline could not be read.
|
|
2493
2493
|
*/
|
|
2494
2494
|
async refreshProjections(sessionId) {
|
|
2495
2495
|
try {
|
|
2496
|
-
const response = await this.apiProxy.sessions.projections
|
|
2496
|
+
const response = await this.apiProxy.sessions.projections({
|
|
2497
2497
|
rpcId: randomUUID(),
|
|
2498
2498
|
payload: { sessionId }
|
|
2499
2499
|
});
|
|
2500
2500
|
if (this.disposed) return;
|
|
2501
|
-
const result = response
|
|
2501
|
+
const result = response.result;
|
|
2502
2502
|
if (!result) return;
|
|
2503
2503
|
if (!result.ok) {
|
|
2504
2504
|
this.diagnostic("sessions.projections failed: " + result.error.code);
|
|
@@ -3303,9 +3303,9 @@ function projectSessionModels(value) {
|
|
|
3303
3303
|
}
|
|
3304
3304
|
/** Project a history page (raw events) into MessageProjection rows. */
|
|
3305
3305
|
//#endregion
|
|
3306
|
-
//#region src/
|
|
3306
|
+
//#region src/dsh-remote-interactions.ts
|
|
3307
3307
|
/**
|
|
3308
|
-
* Resident DSH
|
|
3308
|
+
* Resident DSH Remote Events client for phone interactions.
|
|
3309
3309
|
*
|
|
3310
3310
|
* The Host-side `approval/request` and `user-questions/request` events are
|
|
3311
3311
|
* owned once by DSH API Remotes. API Gateway then fans each pending waterfall
|
|
@@ -3313,6 +3313,10 @@ function projectSessionModels(value) {
|
|
|
3313
3313
|
* that official Client plane in-process instead of registering a competing
|
|
3314
3314
|
* Host waterfall listener or replacing the official Web composer.
|
|
3315
3315
|
*/
|
|
3316
|
+
/** The rc.1 Client sends relative RPC paths to its in-process carrier. */
|
|
3317
|
+
function inProcessRemoteRequest(input, init) {
|
|
3318
|
+
return new Request(new URL(input, "http://localhost/"), init);
|
|
3319
|
+
}
|
|
3316
3320
|
let clientFaces;
|
|
3317
3321
|
/**
|
|
3318
3322
|
* Load DSH's browser-distributed Client faces into a tiny Host-side module
|
|
@@ -3369,32 +3373,9 @@ function createAgentScope(ctx, identity) {
|
|
|
3369
3373
|
}
|
|
3370
3374
|
});
|
|
3371
3375
|
}
|
|
3372
|
-
/**
|
|
3373
|
-
* Arity of the Host's published `wireStream.open`. 0.1.7-alpha.1 declares
|
|
3374
|
-
* `(endpoint, payload, uplink, peer, signal)`; every earlier generation
|
|
3375
|
-
* declares `(endpoint, payload, signal)`. Both are plain arrow functions with
|
|
3376
|
-
* no default or rest parameters, so `length` is a reliable contract selector —
|
|
3377
|
-
* unlike a capability probe, it opens no trial stream. A future signature that
|
|
3378
|
-
* rest-parameterizes (reporting `0`) falls back to the 3-argument call, which
|
|
3379
|
-
* every generation through `0.1.6-*` accepts.
|
|
3380
|
-
*/
|
|
3381
|
-
function hostWireStreamArity(open) {
|
|
3382
|
-
return open.length;
|
|
3383
|
-
}
|
|
3384
|
-
/**
|
|
3385
|
-
* Open one Host logical stream on whichever `wireStream.open` contract the
|
|
3386
|
-
* running Host publishes. DeepPilot's carrier owns the Host in process and has
|
|
3387
|
-
* no Client-to-Host uplink, so the 5-argument form sends `undefined` for both
|
|
3388
|
-
* `uplink` and `peer` — the documented "operator's in-process carrier" case.
|
|
3389
|
-
*/
|
|
3390
|
-
function openHostStream(gateway, endpoint, payload, signal) {
|
|
3391
|
-
const open = gateway.wireStream.open;
|
|
3392
|
-
if (hostWireStreamArity(open) >= 5) return open(endpoint, payload, void 0, void 0, signal);
|
|
3393
|
-
return open(endpoint, payload, signal);
|
|
3394
|
-
}
|
|
3395
3376
|
function inProcessStream(gateway, endpoint, payload, signal) {
|
|
3396
3377
|
return (async function* () {
|
|
3397
|
-
yield* await
|
|
3378
|
+
yield* await gateway.wireStream.open(endpoint, payload, void 0, void 0, signal);
|
|
3398
3379
|
})();
|
|
3399
3380
|
}
|
|
3400
3381
|
/**
|
|
@@ -3404,16 +3385,16 @@ function inProcessStream(gateway, endpoint, payload, signal) {
|
|
|
3404
3385
|
* The returned disposer tears down the Remote Events generation, all pending
|
|
3405
3386
|
* listeners, and every lazily minted Agent scope.
|
|
3406
3387
|
*/
|
|
3407
|
-
async function
|
|
3388
|
+
async function startDshRemoteInteractions(hostCtx, handlers) {
|
|
3408
3389
|
const connection = hostCtx.get("connection");
|
|
3409
3390
|
const gateway = hostCtx.get("typertGateway");
|
|
3410
|
-
if (connection === void 0) throw new Error("
|
|
3411
|
-
if (gateway === void 0) throw new Error("
|
|
3391
|
+
if (connection === void 0) throw new Error("DSH Host connection is unavailable");
|
|
3392
|
+
if (gateway === void 0) throw new Error("DSH typertGateway is unavailable");
|
|
3412
3393
|
const faces = await loadClientFaces();
|
|
3413
3394
|
const client = new Context();
|
|
3414
3395
|
const fetchHandler = connection.createSharedFetchHandler("/api");
|
|
3415
3396
|
const transport = {
|
|
3416
|
-
fetch: (input, init) => fetchHandler.fetch(
|
|
3397
|
+
fetch: (input, init) => fetchHandler.fetch(inProcessRemoteRequest(input, init)),
|
|
3417
3398
|
openStream: (endpoint, payload, signal) => inProcessStream(gateway, endpoint, payload, signal),
|
|
3418
3399
|
ownsHost: true
|
|
3419
3400
|
};
|
|
@@ -3460,19 +3441,17 @@ async function startDsh012RemoteInteractions(hostCtx, handlers) {
|
|
|
3460
3441
|
}
|
|
3461
3442
|
}
|
|
3462
3443
|
//#endregion
|
|
3463
|
-
//#region src/
|
|
3444
|
+
//#region src/dsh-api-proxy.ts
|
|
3464
3445
|
/**
|
|
3465
|
-
*
|
|
3446
|
+
* Adapter for the DSH rc.1 controller API.
|
|
3466
3447
|
*
|
|
3467
3448
|
* DeepPilot's phone protocol deliberately speaks one stable in-process
|
|
3468
|
-
* `apiProxy` vocabulary.
|
|
3469
|
-
*
|
|
3470
|
-
*
|
|
3471
|
-
* controllers and joins the official Client interaction plane in-process,
|
|
3472
|
-
* keeping the phone protocol isolated from the Host API migration.
|
|
3449
|
+
* `apiProxy` vocabulary. This adapter maps it to the current public
|
|
3450
|
+
* Session/Workspace controllers and Gateway-backed Remote Events, keeping
|
|
3451
|
+
* the phone protocol isolated from the Host API.
|
|
3473
3452
|
*/
|
|
3474
|
-
/** Direct-controller
|
|
3475
|
-
var
|
|
3453
|
+
/** Direct-controller adapter with the shape HostBridge consumes. */
|
|
3454
|
+
var DshApiProxy = class {
|
|
3476
3455
|
ctx;
|
|
3477
3456
|
session;
|
|
3478
3457
|
workspaceController;
|
|
@@ -3482,22 +3461,14 @@ var Dsh012ApiProxy = class {
|
|
|
3482
3461
|
constructor(ctx, options = {}) {
|
|
3483
3462
|
this.ctx = ctx;
|
|
3484
3463
|
const session = ctx.get("sessionController");
|
|
3485
|
-
if (session === void 0) throw new Error("
|
|
3464
|
+
if (session === void 0) throw new Error("DSH sessionController is unavailable");
|
|
3486
3465
|
this.session = session;
|
|
3487
3466
|
this.workspaceController = ctx.get("workspaceController");
|
|
3488
|
-
if (
|
|
3467
|
+
if (this.workspaceController === void 0) delete this.workspace?.unarchiveSession;
|
|
3489
3468
|
this.directoryPicker = ctx.get("directoryPickerController");
|
|
3490
3469
|
this.shouldSurfaceInteraction = options.shouldSurfaceInteraction ?? (() => true);
|
|
3491
3470
|
}
|
|
3492
3471
|
/**
|
|
3493
|
-
* Whether the host controller implements `session.projections` (added in
|
|
3494
|
-
* DSH 0.1.7). HostBridge gates its open-time baseline refresh on this so
|
|
3495
|
-
* older hosts keep their current list-row-hint behaviour with no RPC noise.
|
|
3496
|
-
*/
|
|
3497
|
-
get supportsProjections() {
|
|
3498
|
-
return typeof this.session.projections === "function";
|
|
3499
|
-
}
|
|
3500
|
-
/**
|
|
3501
3472
|
* Decide whether this Gateway Client can surface a phone card. The decision
|
|
3502
3473
|
* fails open to false so a broken device registry delegates this delivery
|
|
3503
3474
|
* while the official Web Client remains able to answer.
|
|
@@ -3552,11 +3523,7 @@ var Dsh012ApiProxy = class {
|
|
|
3552
3523
|
rename: async (request) => this.call(() => this.session.rename(request.payload)),
|
|
3553
3524
|
cancel: async (request) => this.call(() => this.session.cancel(request.payload)),
|
|
3554
3525
|
attachment: async (request) => this.call(() => this.session.attachment(request.payload)),
|
|
3555
|
-
projections: async (request) => this.call(() =>
|
|
3556
|
-
const read = this.session.projections;
|
|
3557
|
-
if (typeof read !== "function") throw unavailable("session projections unavailable");
|
|
3558
|
-
return read.call(this.session, request.payload);
|
|
3559
|
-
})
|
|
3526
|
+
projections: async (request) => this.call(() => this.session.projections(request.payload))
|
|
3560
3527
|
};
|
|
3561
3528
|
workspace = {
|
|
3562
3529
|
list: async () => this.call(async () => {
|
|
@@ -3581,9 +3548,7 @@ var Dsh012ApiProxy = class {
|
|
|
3581
3548
|
}),
|
|
3582
3549
|
unarchiveSession: async (request) => this.call(async () => {
|
|
3583
3550
|
if (this.workspaceController === void 0) throw unavailable("workspace controller unavailable");
|
|
3584
|
-
|
|
3585
|
-
if (typeof unarchive !== "function") throw unavailable("session restore unavailable on this host version");
|
|
3586
|
-
return { archivedSessionIds: [...(await unarchive.call(this.workspaceController, request.payload)).archivedSessionIds] };
|
|
3551
|
+
return { archivedSessionIds: [...(await this.workspaceController.unarchiveSession(request.payload)).archivedSessionIds] };
|
|
3587
3552
|
})
|
|
3588
3553
|
};
|
|
3589
3554
|
host = {
|
|
@@ -3634,7 +3599,7 @@ var Dsh012ApiProxy = class {
|
|
|
3634
3599
|
});
|
|
3635
3600
|
let disposeInteractions;
|
|
3636
3601
|
try {
|
|
3637
|
-
disposeInteractions = await
|
|
3602
|
+
disposeInteractions = await startDshRemoteInteractions(this.ctx, {
|
|
3638
3603
|
approval: (sessionId, request, next) => this.answerApproval(queue, sessionId, request, next),
|
|
3639
3604
|
question: (sessionId, request, next) => this.answerQuestion(queue, sessionId, request, next)
|
|
3640
3605
|
});
|
|
@@ -4134,28 +4099,11 @@ const booleanSchema = { parse(value) {
|
|
|
4134
4099
|
if (typeof value !== "boolean") reject("boolean");
|
|
4135
4100
|
return value;
|
|
4136
4101
|
} };
|
|
4137
|
-
/**
|
|
4138
|
-
* One strict boundary codec carrying both generation shapes of the supported
|
|
4139
|
-
* `0.1.x` host family.
|
|
4140
|
-
*
|
|
4141
|
-
* Through `0.1.6-alpha.1` a descriptor published the schema value itself and
|
|
4142
|
-
* every consumer parsed through `codec.schema.parse(value)`. `0.1.6-alpha.2`
|
|
4143
|
-
* switched to a lazily materialized process-realm factory: `TypertRegistry`
|
|
4144
|
-
* now rejects a strict codec without `create()`, and the Gateway parses
|
|
4145
|
-
* through `codec.create().parse(value)`.
|
|
4146
|
-
*
|
|
4147
|
-
* Publishing both keys — `create()` returning the same hand-written,
|
|
4148
|
-
* dependency-free codec — keeps one package valid across the entire declared
|
|
4149
|
-
* peer range instead of forking the wire contract per host generation. The
|
|
4150
|
-
* cast is required because each generation's `TypertCodec` declares only its
|
|
4151
|
-
* own key, so a fresh object literal carrying both fails excess-property
|
|
4152
|
-
* checking against either one.
|
|
4153
|
-
*/
|
|
4102
|
+
/** The rc.1 Gateway materializes each strict codec through `create()`. */
|
|
4154
4103
|
function strictCodec(typeSymbol, schema) {
|
|
4155
4104
|
return {
|
|
4156
4105
|
mode: "strict",
|
|
4157
4106
|
typeSymbol,
|
|
4158
|
-
schema,
|
|
4159
4107
|
create: () => schema
|
|
4160
4108
|
};
|
|
4161
4109
|
}
|
|
@@ -5391,18 +5339,18 @@ function localListenError(error, port) {
|
|
|
5391
5339
|
/** Operator-run relay used by distributed builds; overridable via config. */
|
|
5392
5340
|
const DEFAULT_RELAY_URL = "https://pilot.hailab.dev";
|
|
5393
5341
|
const Config = z.object({
|
|
5394
|
-
enabled:
|
|
5342
|
+
enabled: z.boolean().default(true).volatile(),
|
|
5395
5343
|
devicesPath: z.string().default(join(bridgeDataDir(), "devices-v2.json")),
|
|
5396
5344
|
historyBufferMax: z.natural().min(100).default(2e3),
|
|
5397
|
-
debug:
|
|
5398
|
-
local:
|
|
5345
|
+
debug: z.boolean().default(false).volatile(),
|
|
5346
|
+
local: z.object({
|
|
5399
5347
|
enabled: z.boolean().default(true),
|
|
5400
5348
|
port: z.natural().min(MIN_LOCAL_PORT).max(MAX_LOCAL_PORT).default(DEFAULT_LOCAL_PORT).description("DeepPilot 局域网独立端口(仅 TLS;默认 3098,修改后本地连接会短暂重连)")
|
|
5401
5349
|
}).default({
|
|
5402
5350
|
enabled: true,
|
|
5403
5351
|
port: DEFAULT_LOCAL_PORT
|
|
5404
|
-
})),
|
|
5405
|
-
remote:
|
|
5352
|
+
}).volatile(),
|
|
5353
|
+
remote: z.object({
|
|
5406
5354
|
enabled: z.boolean().default(false),
|
|
5407
5355
|
provider: z.union(["tailscale-funnel"]).default("tailscale-funnel"),
|
|
5408
5356
|
hostname: z.string().default(DEFAULT_REMOTE_HOSTNAME),
|
|
@@ -5422,7 +5370,7 @@ const Config = z.object({
|
|
|
5422
5370
|
helperPath: "",
|
|
5423
5371
|
funnelPort: 443,
|
|
5424
5372
|
maxConnectionsPerSource: 8
|
|
5425
|
-
})),
|
|
5373
|
+
}).volatile(),
|
|
5426
5374
|
push: z.object({
|
|
5427
5375
|
provider: z.union([
|
|
5428
5376
|
"none",
|
|
@@ -5448,21 +5396,6 @@ const Config = z.object({
|
|
|
5448
5396
|
})
|
|
5449
5397
|
});
|
|
5450
5398
|
/**
|
|
5451
|
-
* Declare one live-update (volatile) config node when the host supports it.
|
|
5452
|
-
*
|
|
5453
|
-
* DSH 0.1.7's schemastery adds `Schema#volatile()`; the schemas this package
|
|
5454
|
-
* typechecks against (3.18.x line) do not have the method, so the call goes
|
|
5455
|
-
* through a structural check instead of a direct chain — a direct
|
|
5456
|
-
* `.volatile()` would both fail typecheck today and throw at import on an
|
|
5457
|
-
* older host, killing plugin activation.
|
|
5458
|
-
*/
|
|
5459
|
-
function live(node) {
|
|
5460
|
-
const schema = node;
|
|
5461
|
-
if (typeof schema.volatile === "function") return schema.volatile();
|
|
5462
|
-
if (typeof schema.extra === "function") return schema.extra("volatile", true);
|
|
5463
|
-
return node;
|
|
5464
|
-
}
|
|
5465
|
-
/**
|
|
5466
5399
|
* Deep-unwrap live-update (volatile) references to plain values.
|
|
5467
5400
|
*
|
|
5468
5401
|
* On a 0.1.7 host, `apply()`'s options — and even a direct `Config(raw)` call
|
|
@@ -5470,8 +5403,7 @@ function live(node) {
|
|
|
5470
5403
|
* `currentConfig()` compares plain values (`=== true`, numeric bounds, object
|
|
5471
5404
|
* fields), and schemastery refuses to re-parse a reference, so normalization
|
|
5472
5405
|
* unwraps on the way in and on the way out. A JSON-shaped config value cannot
|
|
5473
|
-
* carry a function, so the `get` check cannot false-positive
|
|
5474
|
-
* passes through unchanged, keeping older-host behavior identical.
|
|
5406
|
+
* carry a function, so the `get` check cannot false-positive.
|
|
5475
5407
|
*/
|
|
5476
5408
|
function plainConfig(value) {
|
|
5477
5409
|
if (value === null || typeof value !== "object") return value;
|
|
@@ -5485,8 +5417,7 @@ function plainConfig(value) {
|
|
|
5485
5417
|
* Cordis hands the second argument in different shapes depending on host
|
|
5486
5418
|
* composition: a reactive options getter, the resolved config value, or
|
|
5487
5419
|
* nothing when the patch row omits `config`. Normalize all of them — and
|
|
5488
|
-
* unwrap volatile references so the returned Config is plain data
|
|
5489
|
-
* host generation.
|
|
5420
|
+
* unwrap volatile references so the returned Config is plain data.
|
|
5490
5421
|
*/
|
|
5491
5422
|
function normalizeOptions(options) {
|
|
5492
5423
|
if (typeof options === "function") return plainConfig(options());
|
|
@@ -6024,8 +5955,8 @@ async function writePrivate(path, contents) {
|
|
|
6024
5955
|
* devices) and loopback Funnel-origin listeners. The web UI and the rest of
|
|
6025
5956
|
* DSH's API are never exposed by these listeners.
|
|
6026
5957
|
*
|
|
6027
|
-
* Data plane: an in-process HostBridge consumes a local
|
|
6028
|
-
*
|
|
5958
|
+
* Data plane: an in-process HostBridge consumes a local adapter over DSH
|
|
5959
|
+
* Session/Workspace controllers, mirrors session summaries,
|
|
6029
5960
|
* tracks pending approvals/questions, and fans projected protocol-v2 pushes
|
|
6030
5961
|
* out to every connected device.
|
|
6031
5962
|
*
|
|
@@ -6066,36 +5997,10 @@ function apply(ctx, options) {
|
|
|
6066
5997
|
};
|
|
6067
5998
|
const auditSalt = randomBytes(32);
|
|
6068
5999
|
const auditLabel = (value) => createHash("sha256").update(auditSalt).update(value).digest("hex").slice(0, 12);
|
|
6069
|
-
/**
|
|
6070
|
-
* Settings-section source: while a settings service is attached this holds
|
|
6071
|
-
* the user-edited section value; otherwise the composition defaults. Read
|
|
6072
|
-
* through currentConfig() everywhere (normalizeOptions prefers it).
|
|
6073
|
-
*/
|
|
6074
|
-
let liveSource;
|
|
6075
6000
|
let scheduleRemoteReconcile;
|
|
6076
6001
|
let scheduleLocalReconcile;
|
|
6077
|
-
const currentConfig = () =>
|
|
6078
|
-
if (liveSource !== void 0) return normalizeOptions(liveSource());
|
|
6079
|
-
return normalizeOptions(options);
|
|
6080
|
-
};
|
|
6002
|
+
const currentConfig = () => normalizeOptions(options);
|
|
6081
6003
|
const enabledNow = () => currentConfig().enabled === true;
|
|
6082
|
-
const settingsHooks = {
|
|
6083
|
-
setSource: (source) => {
|
|
6084
|
-
liveSource = source;
|
|
6085
|
-
queueMicrotask(() => {
|
|
6086
|
-
scheduleLocalReconcile?.();
|
|
6087
|
-
scheduleRemoteReconcile?.();
|
|
6088
|
-
});
|
|
6089
|
-
},
|
|
6090
|
-
onChange: () => queueMicrotask(() => {
|
|
6091
|
-
scheduleLocalReconcile?.();
|
|
6092
|
-
scheduleRemoteReconcile?.();
|
|
6093
|
-
})
|
|
6094
|
-
};
|
|
6095
|
-
ctx.inject(["settings"], (settingsCtx) => {
|
|
6096
|
-
if (typeof settingsCtx.settings?.installSection !== "function") return;
|
|
6097
|
-
settingsCtx.settings.installSection(ctx, "deeppilot", Config, normalizeOptions(void 0), settingsHooks);
|
|
6098
|
-
});
|
|
6099
6004
|
ctx.on("loader/volatile-update", () => queueMicrotask(() => {
|
|
6100
6005
|
scheduleLocalReconcile?.();
|
|
6101
6006
|
scheduleRemoteReconcile?.();
|
|
@@ -7105,9 +7010,9 @@ function apply(ctx, options) {
|
|
|
7105
7010
|
const apiCtx = sub;
|
|
7106
7011
|
let proxy;
|
|
7107
7012
|
try {
|
|
7108
|
-
proxy = new
|
|
7013
|
+
proxy = new DshApiProxy(apiCtx, { shouldSurfaceInteraction: hasPairedPhoneSurface });
|
|
7109
7014
|
} catch (error) {
|
|
7110
|
-
log("
|
|
7015
|
+
log("DSH session bridge unavailable: " + String(error));
|
|
7111
7016
|
return;
|
|
7112
7017
|
}
|
|
7113
7018
|
const bridge = new HostBridge(proxy, cfg.historyBufferMax, join(dataDir, "prompt-deliveries-v1.json"));
|