agents 0.12.0 → 0.12.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/README.md +10 -0
- package/dist/{agent-tool-types-tBGRsPm0.d.ts → agent-tool-types-DSteYkkS.d.ts} +125 -4
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-CIO14miM.d.ts → agent-tools-eGTCdVZX.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/chat/index.d.ts +3 -2
- package/dist/chat/index.js +31 -0
- package/dist/chat/index.js.map +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +426 -4
- package/dist/index.js.map +1 -1
- package/dist/mcp/client.d.ts +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/react.d.ts +1 -1
- package/dist/react.js +9 -0
- package/dist/react.js.map +1 -1
- package/dist/sub-routing.d.ts +1 -1
- package/dist/sub-routing.js +7 -1
- package/dist/sub-routing.js.map +1 -1
- package/dist/workflows.d.ts +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -40,6 +40,52 @@ var SqlError = class extends Error {
|
|
|
40
40
|
this.query = query;
|
|
41
41
|
}
|
|
42
42
|
};
|
|
43
|
+
var _connection2 = /* @__PURE__ */ new WeakMap();
|
|
44
|
+
var _broadcast = /* @__PURE__ */ new WeakMap();
|
|
45
|
+
var SubAgentConnectionBridge = class extends RpcTarget {
|
|
46
|
+
constructor(connection, broadcast) {
|
|
47
|
+
super();
|
|
48
|
+
_classPrivateFieldInitSpec(this, _connection2, void 0);
|
|
49
|
+
_classPrivateFieldInitSpec(this, _broadcast, void 0);
|
|
50
|
+
_classPrivateFieldSet2(_connection2, this, connection);
|
|
51
|
+
_classPrivateFieldSet2(_broadcast, this, broadcast);
|
|
52
|
+
}
|
|
53
|
+
send(message) {
|
|
54
|
+
_classPrivateFieldGet2(_connection2, this).send(message);
|
|
55
|
+
}
|
|
56
|
+
close(code, reason) {
|
|
57
|
+
_classPrivateFieldGet2(_connection2, this).close(code, reason);
|
|
58
|
+
}
|
|
59
|
+
setState(state) {
|
|
60
|
+
return _classPrivateFieldGet2(_connection2, this).setState(state);
|
|
61
|
+
}
|
|
62
|
+
broadcast(ownerPath, message, without) {
|
|
63
|
+
_classPrivateFieldGet2(_broadcast, this)?.call(this, ownerPath, message, without);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
var _root = /* @__PURE__ */ new WeakMap();
|
|
67
|
+
var _connectionId = /* @__PURE__ */ new WeakMap();
|
|
68
|
+
var RootSubAgentConnectionBridge = class {
|
|
69
|
+
constructor(root, connectionId) {
|
|
70
|
+
_classPrivateFieldInitSpec(this, _root, void 0);
|
|
71
|
+
_classPrivateFieldInitSpec(this, _connectionId, void 0);
|
|
72
|
+
_classPrivateFieldSet2(_root, this, root);
|
|
73
|
+
_classPrivateFieldSet2(_connectionId, this, connectionId);
|
|
74
|
+
}
|
|
75
|
+
send(message) {
|
|
76
|
+
_classPrivateFieldGet2(_root, this)._cf_sendToSubAgentConnection(_classPrivateFieldGet2(_connectionId, this), message);
|
|
77
|
+
}
|
|
78
|
+
close(code, reason) {
|
|
79
|
+
_classPrivateFieldGet2(_root, this)._cf_closeSubAgentConnection(_classPrivateFieldGet2(_connectionId, this), code, reason);
|
|
80
|
+
}
|
|
81
|
+
setState(state) {
|
|
82
|
+
_classPrivateFieldGet2(_root, this)._cf_setSubAgentConnectionState(_classPrivateFieldGet2(_connectionId, this), state);
|
|
83
|
+
return state;
|
|
84
|
+
}
|
|
85
|
+
broadcast(ownerPath, message, without) {
|
|
86
|
+
_classPrivateFieldGet2(_root, this)._cf_broadcastToSubAgent(ownerPath, message, without);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
43
89
|
/**
|
|
44
90
|
* Decorator that marks a method as callable by clients
|
|
45
91
|
* @param metadata Optional metadata about the callable method
|
|
@@ -99,13 +145,30 @@ const CF_READONLY_KEY = "_cf_readonly";
|
|
|
99
145
|
*/
|
|
100
146
|
const CF_NO_PROTOCOL_KEY = "_cf_no_protocol";
|
|
101
147
|
/**
|
|
148
|
+
* Internal key used to store voice call state in connection state.
|
|
149
|
+
* Used by the voice mixin to track whether a connection is in an active call.
|
|
150
|
+
*/
|
|
151
|
+
const CF_VOICE_IN_CALL_KEY = "_cf_voiceInCall";
|
|
152
|
+
/**
|
|
153
|
+
* Internal key used to remember the outer `/sub/...` URL for a
|
|
154
|
+
* WebSocket accepted by the parent on behalf of a child facet.
|
|
155
|
+
* Hibernated events then wake the parent, which forwards frames to
|
|
156
|
+
* the child over serializable RPC while keeping native WebSocket I/O
|
|
157
|
+
* parent-owned.
|
|
158
|
+
*/
|
|
159
|
+
const CF_SUB_AGENT_OUTER_URL_KEY = "_cf_subAgentOuterUrl";
|
|
160
|
+
const CF_SUB_AGENT_TAGS_KEY = "_cf_subAgentTags";
|
|
161
|
+
const SUB_AGENT_OUTER_URL_HEADER = "x-cf-agents-subagent-url";
|
|
162
|
+
/**
|
|
102
163
|
* The set of all internal keys stored in connection state that must be
|
|
103
164
|
* hidden from user code and preserved across setState calls.
|
|
104
165
|
*/
|
|
105
166
|
const CF_INTERNAL_KEYS = new Set([
|
|
106
167
|
CF_READONLY_KEY,
|
|
107
168
|
CF_NO_PROTOCOL_KEY,
|
|
108
|
-
|
|
169
|
+
CF_VOICE_IN_CALL_KEY,
|
|
170
|
+
CF_SUB_AGENT_OUTER_URL_KEY,
|
|
171
|
+
CF_SUB_AGENT_TAGS_KEY
|
|
109
172
|
]);
|
|
110
173
|
/** Check if a raw connection state object contains any internal keys. */
|
|
111
174
|
function rawHasInternalKeys(raw) {
|
|
@@ -524,6 +587,7 @@ var Agent = class Agent extends Server {
|
|
|
524
587
|
this._persistenceHookMode = "none";
|
|
525
588
|
this._isFacet = false;
|
|
526
589
|
this._suppressProtocolBroadcasts = false;
|
|
590
|
+
this._cf_virtualSubAgentConnections = /* @__PURE__ */ new Map();
|
|
527
591
|
this._parentPath = [];
|
|
528
592
|
this._insideOnStart = false;
|
|
529
593
|
this._warnedScheduleInOnStart = /* @__PURE__ */ new Set();
|
|
@@ -587,6 +651,7 @@ var Agent = class Agent extends Server {
|
|
|
587
651
|
};
|
|
588
652
|
const _onMessage = this.onMessage.bind(this);
|
|
589
653
|
this.onMessage = async (connection, message) => {
|
|
654
|
+
if (await this._cf_forwardSubAgentWebSocketMessage(connection, message)) return;
|
|
590
655
|
this._ensureConnectionWrapped(connection);
|
|
591
656
|
return __DO_NOT_USE_WILL_BREAK__agentContext.run({
|
|
592
657
|
agent: this,
|
|
@@ -678,8 +743,11 @@ var Agent = class Agent extends Server {
|
|
|
678
743
|
});
|
|
679
744
|
};
|
|
680
745
|
const _onConnect = this.onConnect.bind(this);
|
|
681
|
-
this.onConnect = (connection, ctx) => {
|
|
746
|
+
this.onConnect = async (connection, ctx) => {
|
|
682
747
|
this._ensureConnectionWrapped(connection);
|
|
748
|
+
const subAgentOuterUrl = ctx.request.headers.get(SUB_AGENT_OUTER_URL_HEADER);
|
|
749
|
+
if (subAgentOuterUrl) this._unsafe_setConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY, subAgentOuterUrl);
|
|
750
|
+
if (await this._cf_forwardSubAgentWebSocketConnect(connection, ctx.request, { gate: false })) return;
|
|
683
751
|
return __DO_NOT_USE_WILL_BREAK__agentContext.run({
|
|
684
752
|
agent: this,
|
|
685
753
|
connection,
|
|
@@ -717,7 +785,8 @@ var Agent = class Agent extends Server {
|
|
|
717
785
|
});
|
|
718
786
|
};
|
|
719
787
|
const _onClose = this.onClose.bind(this);
|
|
720
|
-
this.onClose = (connection, code, reason, wasClean) => {
|
|
788
|
+
this.onClose = async (connection, code, reason, wasClean) => {
|
|
789
|
+
if (await this._cf_forwardSubAgentWebSocketClose(connection, code, reason, wasClean)) return;
|
|
721
790
|
return __DO_NOT_USE_WILL_BREAK__agentContext.run({
|
|
722
791
|
agent: this,
|
|
723
792
|
connection,
|
|
@@ -743,6 +812,11 @@ var Agent = class Agent extends Server {
|
|
|
743
812
|
if (await this.ctx.storage.get("cf_agents_is_facet")) this._isFacet = true;
|
|
744
813
|
const storedParentPath = await this.ctx.storage.get("cf_agents_parent_path");
|
|
745
814
|
if (isValidParentPath(storedParentPath)) this._parentPath = storedParentPath;
|
|
815
|
+
try {
|
|
816
|
+
await this._cf_hydrateSubAgentConnectionsFromRoot();
|
|
817
|
+
} catch (error) {
|
|
818
|
+
console.warn("[Agent] Unable to hydrate sub-agent WebSocket connections:", error);
|
|
819
|
+
}
|
|
746
820
|
await this._tryCatch(async () => {
|
|
747
821
|
await this.mcp.restoreConnectionsFromStorage(this.name);
|
|
748
822
|
await this._restoreRpcMcpServers();
|
|
@@ -2577,8 +2651,349 @@ var Agent = class Agent extends Server {
|
|
|
2577
2651
|
});
|
|
2578
2652
|
if (decision instanceof Response) return decision;
|
|
2579
2653
|
const forwardReq = decision instanceof Request ? decision : request;
|
|
2654
|
+
if (request.headers.get("Upgrade")?.toLowerCase() === "websocket") {
|
|
2655
|
+
const acceptHeaders = new Headers(forwardReq.headers);
|
|
2656
|
+
const routedUrl = new URL(forwardReq.url);
|
|
2657
|
+
routedUrl.pathname = new URL(request.url).pathname;
|
|
2658
|
+
acceptHeaders.set(SUB_AGENT_OUTER_URL_HEADER, routedUrl.toString());
|
|
2659
|
+
return super.fetch(new Request(forwardReq, { headers: acceptHeaders }));
|
|
2660
|
+
}
|
|
2580
2661
|
return this._cf_forwardToFacet(forwardReq, match);
|
|
2581
2662
|
}
|
|
2663
|
+
broadcast(msg, without) {
|
|
2664
|
+
if (this._isFacet) {
|
|
2665
|
+
this._cf_broadcastToParentSubAgent(msg, without);
|
|
2666
|
+
return;
|
|
2667
|
+
}
|
|
2668
|
+
for (const connection of super.getConnections()) {
|
|
2669
|
+
if (without?.includes(connection.id)) continue;
|
|
2670
|
+
if (this._cf_connectionHasSubAgentTarget(connection)) continue;
|
|
2671
|
+
connection.send(msg);
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
getConnection(id) {
|
|
2675
|
+
if (this._isFacet) {
|
|
2676
|
+
const stored = this._cf_virtualSubAgentConnections.get(id);
|
|
2677
|
+
if (stored) return this._cf_createSubAgentBridgeConnection(stored.bridge, stored.meta);
|
|
2678
|
+
}
|
|
2679
|
+
const connection = super.getConnection(id);
|
|
2680
|
+
if (!connection || this._cf_connectionHasSubAgentTarget(connection)) return;
|
|
2681
|
+
return connection;
|
|
2682
|
+
}
|
|
2683
|
+
*getConnections(tag) {
|
|
2684
|
+
if (this._isFacet) {
|
|
2685
|
+
for (const stored of this._cf_virtualSubAgentConnections.values()) if (!tag || stored.meta.tags.includes(tag)) yield this._cf_createSubAgentBridgeConnection(stored.bridge, stored.meta);
|
|
2686
|
+
}
|
|
2687
|
+
for (const connection of super.getConnections(tag)) {
|
|
2688
|
+
if (this._cf_connectionHasSubAgentTarget(connection)) continue;
|
|
2689
|
+
yield connection;
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
async _cf_broadcastToParentSubAgent(message, without) {
|
|
2693
|
+
if (this._cf_currentSubAgentBridge) {
|
|
2694
|
+
this._cf_currentSubAgentBridge.broadcast(this.selfPath, message, without);
|
|
2695
|
+
return;
|
|
2696
|
+
}
|
|
2697
|
+
await (await this._rootAlarmOwner())._cf_broadcastToSubAgent(this.selfPath, message, without);
|
|
2698
|
+
}
|
|
2699
|
+
async _cf_broadcastToSubAgent(ownerPath, message, without) {
|
|
2700
|
+
if (this._isFacet && this._cf_currentSubAgentBridge) {
|
|
2701
|
+
this._cf_currentSubAgentBridge.broadcast(ownerPath, message, without);
|
|
2702
|
+
return;
|
|
2703
|
+
}
|
|
2704
|
+
for (const connection of super.getConnections()) {
|
|
2705
|
+
if (without?.includes(connection.id)) continue;
|
|
2706
|
+
const targetPath = this._cf_subAgentTargetPath(connection);
|
|
2707
|
+
if (!targetPath) continue;
|
|
2708
|
+
if (!this._isSameAgentPath(targetPath, ownerPath)) continue;
|
|
2709
|
+
connection.send(message);
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
async _cf_subAgentConnectionMetas(ownerPath) {
|
|
2713
|
+
const metas = [];
|
|
2714
|
+
for (const connection of super.getConnections()) {
|
|
2715
|
+
const meta = this._cf_subAgentConnectionMetaForPath(connection, ownerPath);
|
|
2716
|
+
if (meta) metas.push(meta);
|
|
2717
|
+
}
|
|
2718
|
+
return metas;
|
|
2719
|
+
}
|
|
2720
|
+
async _cf_sendToSubAgentConnection(connectionId, message) {
|
|
2721
|
+
const connection = super.getConnection(connectionId);
|
|
2722
|
+
if (!connection || !this._cf_connectionHasSubAgentTarget(connection)) return;
|
|
2723
|
+
connection.send(message);
|
|
2724
|
+
}
|
|
2725
|
+
async _cf_closeSubAgentConnection(connectionId, code, reason) {
|
|
2726
|
+
const connection = super.getConnection(connectionId);
|
|
2727
|
+
if (!connection || !this._cf_connectionHasSubAgentTarget(connection)) return;
|
|
2728
|
+
connection.close(code, reason);
|
|
2729
|
+
}
|
|
2730
|
+
async _cf_setSubAgentConnectionState(connectionId, state) {
|
|
2731
|
+
const connection = super.getConnection(connectionId);
|
|
2732
|
+
if (!connection || !this._cf_connectionHasSubAgentTarget(connection)) return null;
|
|
2733
|
+
this._ensureConnectionWrapped(connection);
|
|
2734
|
+
connection.setState(state);
|
|
2735
|
+
return this._cf_getForwardedSubAgentState(connection);
|
|
2736
|
+
}
|
|
2737
|
+
_cf_subAgentConnectionMetaForPath(connection, ownerPath) {
|
|
2738
|
+
this._ensureConnectionWrapped(connection);
|
|
2739
|
+
const outerUri = this._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY);
|
|
2740
|
+
if (typeof outerUri !== "string") return null;
|
|
2741
|
+
const target = this._cf_subAgentPathFromOuterUri(outerUri, ownerPath);
|
|
2742
|
+
if (!target) return null;
|
|
2743
|
+
const raw = this._cf_getRawConnectionState(connection);
|
|
2744
|
+
const rawTags = raw != null && typeof raw === "object" ? raw[CF_SUB_AGENT_TAGS_KEY] : void 0;
|
|
2745
|
+
const tags = Array.isArray(rawTags) ? rawTags.filter((tag) => typeof tag === "string") : [...connection.tags];
|
|
2746
|
+
return {
|
|
2747
|
+
id: connection.id,
|
|
2748
|
+
uri: target.uri,
|
|
2749
|
+
tags,
|
|
2750
|
+
state: this._cf_getForwardedSubAgentState(connection)
|
|
2751
|
+
};
|
|
2752
|
+
}
|
|
2753
|
+
_cf_subAgentTargetPath(connection) {
|
|
2754
|
+
this._ensureConnectionWrapped(connection);
|
|
2755
|
+
const outerUri = this._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY);
|
|
2756
|
+
if (typeof outerUri !== "string") return null;
|
|
2757
|
+
return this._cf_subAgentPathFromOuterUri(outerUri)?.path ?? null;
|
|
2758
|
+
}
|
|
2759
|
+
_cf_subAgentPathFromOuterUri(outerUri, stopAt) {
|
|
2760
|
+
const ctx = this.ctx;
|
|
2761
|
+
const knownClasses = ctx.exports ? Object.keys(ctx.exports) : void 0;
|
|
2762
|
+
const path = [...this.selfPath];
|
|
2763
|
+
let currentUrl = outerUri;
|
|
2764
|
+
while (true) {
|
|
2765
|
+
const match = parseSubAgentPath(currentUrl, { knownClasses });
|
|
2766
|
+
if (!match) break;
|
|
2767
|
+
path.push({
|
|
2768
|
+
className: match.childClass,
|
|
2769
|
+
name: match.childName
|
|
2770
|
+
});
|
|
2771
|
+
const rewritten = new URL(currentUrl);
|
|
2772
|
+
rewritten.pathname = match.remainingPath;
|
|
2773
|
+
currentUrl = rewritten.toString();
|
|
2774
|
+
if (stopAt && this._isSameAgentPath(path, stopAt)) return {
|
|
2775
|
+
path,
|
|
2776
|
+
uri: currentUrl
|
|
2777
|
+
};
|
|
2778
|
+
}
|
|
2779
|
+
if (path.length === this.selfPath.length) return null;
|
|
2780
|
+
if (stopAt) return null;
|
|
2781
|
+
return {
|
|
2782
|
+
path,
|
|
2783
|
+
uri: currentUrl
|
|
2784
|
+
};
|
|
2785
|
+
}
|
|
2786
|
+
_isSameAgentPath(a, b) {
|
|
2787
|
+
if (a.length !== b.length) return false;
|
|
2788
|
+
return a.every((step, index) => step.className === b[index]?.className && step.name === b[index]?.name);
|
|
2789
|
+
}
|
|
2790
|
+
_cf_connectionHasSubAgentTarget(connection) {
|
|
2791
|
+
this._ensureConnectionWrapped(connection);
|
|
2792
|
+
return typeof this._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY) === "string";
|
|
2793
|
+
}
|
|
2794
|
+
_cf_connectionTargetsSubAgent(connection) {
|
|
2795
|
+
if (!connection.uri) return false;
|
|
2796
|
+
const ctx = this.ctx;
|
|
2797
|
+
return parseSubAgentPath(connection.uri, { knownClasses: ctx.exports ? Object.keys(ctx.exports) : void 0 }) !== null;
|
|
2798
|
+
}
|
|
2799
|
+
/**
|
|
2800
|
+
* Returns true when the current request is addressed to a child facet of
|
|
2801
|
+
* this agent rather than to this agent itself.
|
|
2802
|
+
*
|
|
2803
|
+
* Chat-style subclasses wrap `onConnect` before the base Agent forwarding
|
|
2804
|
+
* wrapper runs, so they need a request-level check to avoid sending their
|
|
2805
|
+
* own protocol frames on sockets that are about to be forwarded to a child.
|
|
2806
|
+
*/
|
|
2807
|
+
_cf_requestTargetsSubAgent(request) {
|
|
2808
|
+
const ctx = this.ctx;
|
|
2809
|
+
return parseSubAgentPath(request.url, { knownClasses: ctx.exports ? Object.keys(ctx.exports) : void 0 }) !== null;
|
|
2810
|
+
}
|
|
2811
|
+
async _cf_forwardSubAgentWebSocketConnect(connection, request, options) {
|
|
2812
|
+
const routed = await this._cf_resolveSubAgentConnection(connection, request, options);
|
|
2813
|
+
if (!routed) return false;
|
|
2814
|
+
await routed.child._cf_handleSubAgentWebSocketConnect(this._cf_createSubAgentConnectionBridge(connection), routed.meta);
|
|
2815
|
+
return true;
|
|
2816
|
+
}
|
|
2817
|
+
_cf_createSubAgentConnectionBridge(connection) {
|
|
2818
|
+
return new SubAgentConnectionBridge(connection, (ownerPath, message, without) => {
|
|
2819
|
+
this._cf_broadcastToSubAgent(ownerPath, message, without);
|
|
2820
|
+
});
|
|
2821
|
+
}
|
|
2822
|
+
async _cf_forwardSubAgentWebSocketMessage(connection, message) {
|
|
2823
|
+
const routed = await this._cf_resolveSubAgentConnection(connection);
|
|
2824
|
+
if (!routed) return false;
|
|
2825
|
+
await routed.child._cf_handleSubAgentWebSocketMessage(message, this._cf_createSubAgentConnectionBridge(connection), routed.meta);
|
|
2826
|
+
return true;
|
|
2827
|
+
}
|
|
2828
|
+
async _cf_forwardSubAgentWebSocketClose(connection, code, reason, wasClean) {
|
|
2829
|
+
const routed = await this._cf_resolveSubAgentConnection(connection);
|
|
2830
|
+
if (!routed) return false;
|
|
2831
|
+
await routed.child._cf_handleSubAgentWebSocketClose(code, reason, wasClean, this._cf_createSubAgentConnectionBridge(connection), routed.meta);
|
|
2832
|
+
return true;
|
|
2833
|
+
}
|
|
2834
|
+
async _cf_resolveSubAgentConnection(connection, request, options = { gate: false }) {
|
|
2835
|
+
this._ensureConnectionWrapped(connection);
|
|
2836
|
+
const outerUri = this._unsafe_getConnectionFlag(connection, CF_SUB_AGENT_OUTER_URL_KEY);
|
|
2837
|
+
const uri = typeof outerUri === "string" ? outerUri : connection.uri;
|
|
2838
|
+
if (!uri) return null;
|
|
2839
|
+
const ctx = this.ctx;
|
|
2840
|
+
let match = parseSubAgentPath(uri, { knownClasses: ctx.exports ? Object.keys(ctx.exports) : void 0 });
|
|
2841
|
+
if (!match) return null;
|
|
2842
|
+
if (this._ParentClass.name === match.childClass && this.name === match.childName) {
|
|
2843
|
+
const tailUri = new URL(uri);
|
|
2844
|
+
tailUri.pathname = match.remainingPath;
|
|
2845
|
+
match = parseSubAgentPath(tailUri.toString(), { knownClasses: ctx.exports ? Object.keys(ctx.exports) : void 0 });
|
|
2846
|
+
if (!match) return null;
|
|
2847
|
+
}
|
|
2848
|
+
let forwardReq = request;
|
|
2849
|
+
if (request && options.gate) {
|
|
2850
|
+
const decision = await this.onBeforeSubAgent(request, {
|
|
2851
|
+
className: match.childClass,
|
|
2852
|
+
name: match.childName
|
|
2853
|
+
});
|
|
2854
|
+
if (decision instanceof Response) {
|
|
2855
|
+
connection.close(1008, "Sub-agent connection rejected");
|
|
2856
|
+
return null;
|
|
2857
|
+
}
|
|
2858
|
+
forwardReq = decision instanceof Request ? decision : request;
|
|
2859
|
+
}
|
|
2860
|
+
const child = await this._cf_resolveSubAgent(match.childClass, match.childName);
|
|
2861
|
+
const childUri = new URL(forwardReq?.url ?? uri);
|
|
2862
|
+
childUri.pathname = match.remainingPath;
|
|
2863
|
+
const raw = this._cf_getRawConnectionState(connection);
|
|
2864
|
+
const rawTags = raw != null && typeof raw === "object" ? raw[CF_SUB_AGENT_TAGS_KEY] : void 0;
|
|
2865
|
+
const tags = Array.isArray(rawTags) ? rawTags.filter((tag) => typeof tag === "string") : [...connection.tags];
|
|
2866
|
+
return {
|
|
2867
|
+
child,
|
|
2868
|
+
meta: {
|
|
2869
|
+
id: connection.id,
|
|
2870
|
+
uri: childUri.toString(),
|
|
2871
|
+
tags,
|
|
2872
|
+
state: this._cf_getForwardedSubAgentState(connection),
|
|
2873
|
+
requestHeaders: forwardReq ? [...forwardReq.headers] : void 0
|
|
2874
|
+
}
|
|
2875
|
+
};
|
|
2876
|
+
}
|
|
2877
|
+
async _cf_handleSubAgentWebSocketConnect(bridge, meta) {
|
|
2878
|
+
await this._cf_runWithSubAgentBridge(bridge, async () => {
|
|
2879
|
+
const connection = this._cf_createSubAgentBridgeConnection(bridge, meta);
|
|
2880
|
+
const request = new Request(meta.uri ?? "http://placeholder/", { headers: meta.requestHeaders });
|
|
2881
|
+
if (await this._cf_forwardSubAgentWebSocketConnect(connection, request, { gate: true })) return;
|
|
2882
|
+
if (this.shouldConnectionBeReadonly(connection, { request })) this.setConnectionReadonly(connection, true);
|
|
2883
|
+
if (!this.shouldSendProtocolMessages(connection, { request })) this._setConnectionNoProtocol(connection);
|
|
2884
|
+
const childTags = await this.getConnectionTags(connection, { request });
|
|
2885
|
+
connection.tags = [connection.id, ...childTags.filter((tag) => tag !== connection.id)];
|
|
2886
|
+
this._cf_storeVirtualSubAgentConnection(bridge, connection);
|
|
2887
|
+
await this.onConnect(connection, { request });
|
|
2888
|
+
this._cf_storeVirtualSubAgentConnection(bridge, connection);
|
|
2889
|
+
});
|
|
2890
|
+
}
|
|
2891
|
+
async _cf_handleSubAgentWebSocketMessage(message, bridge, meta) {
|
|
2892
|
+
const connection = this._cf_createSubAgentBridgeConnection(bridge, meta);
|
|
2893
|
+
this._cf_storeVirtualSubAgentConnection(bridge, connection);
|
|
2894
|
+
await this._cf_runWithSubAgentBridge(bridge, () => this.onMessage(connection, message));
|
|
2895
|
+
}
|
|
2896
|
+
async _cf_handleSubAgentWebSocketClose(code, reason, wasClean, bridge, meta) {
|
|
2897
|
+
const connection = this._cf_createSubAgentBridgeConnection(bridge, meta);
|
|
2898
|
+
this._cf_storeVirtualSubAgentConnection(bridge, connection);
|
|
2899
|
+
await this._cf_runWithSubAgentBridge(bridge, () => this.onClose(connection, code, reason, wasClean));
|
|
2900
|
+
this._cf_virtualSubAgentConnections.delete(meta.id);
|
|
2901
|
+
}
|
|
2902
|
+
async _cf_runWithSubAgentBridge(bridge, fn) {
|
|
2903
|
+
const previous = this._cf_currentSubAgentBridge;
|
|
2904
|
+
this._cf_currentSubAgentBridge = bridge;
|
|
2905
|
+
try {
|
|
2906
|
+
return await fn();
|
|
2907
|
+
} finally {
|
|
2908
|
+
this._cf_currentSubAgentBridge = previous;
|
|
2909
|
+
}
|
|
2910
|
+
}
|
|
2911
|
+
_cf_createSubAgentBridgeConnection(bridge, meta) {
|
|
2912
|
+
let stored = this._cf_virtualSubAgentConnections.get(meta.id);
|
|
2913
|
+
if (stored) {
|
|
2914
|
+
stored.bridge = bridge;
|
|
2915
|
+
stored.meta = meta;
|
|
2916
|
+
if (stored.connection) {
|
|
2917
|
+
stored.connection.uri = meta.uri;
|
|
2918
|
+
stored.connection.tags = meta.tags;
|
|
2919
|
+
return stored.connection;
|
|
2920
|
+
}
|
|
2921
|
+
} else {
|
|
2922
|
+
stored = {
|
|
2923
|
+
bridge,
|
|
2924
|
+
meta
|
|
2925
|
+
};
|
|
2926
|
+
this._cf_virtualSubAgentConnections.set(meta.id, stored);
|
|
2927
|
+
}
|
|
2928
|
+
const getStored = () => this._cf_virtualSubAgentConnections.get(meta.id) ?? stored;
|
|
2929
|
+
const updateStoredState = (nextState) => {
|
|
2930
|
+
const current = this._cf_virtualSubAgentConnections.get(meta.id);
|
|
2931
|
+
if (current) current.meta = {
|
|
2932
|
+
...current.meta,
|
|
2933
|
+
state: nextState
|
|
2934
|
+
};
|
|
2935
|
+
};
|
|
2936
|
+
const connection = {
|
|
2937
|
+
id: meta.id,
|
|
2938
|
+
uri: meta.uri,
|
|
2939
|
+
tags: meta.tags,
|
|
2940
|
+
server: this.name,
|
|
2941
|
+
get state() {
|
|
2942
|
+
return getStored().meta.state;
|
|
2943
|
+
},
|
|
2944
|
+
setState(next) {
|
|
2945
|
+
const currentState = getStored().meta.state;
|
|
2946
|
+
const state = typeof next === "function" ? next(currentState) : next;
|
|
2947
|
+
updateStoredState(state);
|
|
2948
|
+
getStored().bridge.setState(state);
|
|
2949
|
+
return state;
|
|
2950
|
+
},
|
|
2951
|
+
send(message) {
|
|
2952
|
+
getStored().bridge.send(message);
|
|
2953
|
+
},
|
|
2954
|
+
close(code, reason) {
|
|
2955
|
+
getStored().bridge.close(code, reason);
|
|
2956
|
+
},
|
|
2957
|
+
addEventListener() {},
|
|
2958
|
+
removeEventListener() {}
|
|
2959
|
+
};
|
|
2960
|
+
stored.connection = connection;
|
|
2961
|
+
this._ensureConnectionWrapped(connection);
|
|
2962
|
+
return connection;
|
|
2963
|
+
}
|
|
2964
|
+
_cf_storeVirtualSubAgentConnection(bridge, connection) {
|
|
2965
|
+
this._unsafe_setConnectionFlag(connection, CF_SUB_AGENT_TAGS_KEY, [...connection.tags]);
|
|
2966
|
+
const stored = this._cf_virtualSubAgentConnections.get(connection.id);
|
|
2967
|
+
this._cf_virtualSubAgentConnections.set(connection.id, {
|
|
2968
|
+
bridge,
|
|
2969
|
+
meta: {
|
|
2970
|
+
id: connection.id,
|
|
2971
|
+
uri: connection.uri,
|
|
2972
|
+
tags: [...connection.tags],
|
|
2973
|
+
state: this._cf_getRawConnectionState(connection)
|
|
2974
|
+
},
|
|
2975
|
+
connection: stored?.connection ?? connection
|
|
2976
|
+
});
|
|
2977
|
+
}
|
|
2978
|
+
async _cf_hydrateSubAgentConnectionsFromRoot() {
|
|
2979
|
+
if (!this._isFacet || this._parentPath.length === 0) return;
|
|
2980
|
+
const root = await this._rootAlarmOwner();
|
|
2981
|
+
const metas = await root._cf_subAgentConnectionMetas(this.selfPath);
|
|
2982
|
+
for (const meta of metas) this._cf_virtualSubAgentConnections.set(meta.id, {
|
|
2983
|
+
bridge: new RootSubAgentConnectionBridge(root, meta.id),
|
|
2984
|
+
meta
|
|
2985
|
+
});
|
|
2986
|
+
}
|
|
2987
|
+
_cf_getRawConnectionState(connection) {
|
|
2988
|
+
this._ensureConnectionWrapped(connection);
|
|
2989
|
+
return this._rawStateAccessors.get(connection)?.getRaw() ?? null;
|
|
2990
|
+
}
|
|
2991
|
+
_cf_getForwardedSubAgentState(connection) {
|
|
2992
|
+
const raw = this._cf_getRawConnectionState(connection);
|
|
2993
|
+
if (raw == null || typeof raw !== "object") return raw;
|
|
2994
|
+
const { [CF_SUB_AGENT_OUTER_URL_KEY]: _, ...rest } = raw;
|
|
2995
|
+
return Object.keys(rest).length > 0 ? rest : null;
|
|
2996
|
+
}
|
|
2582
2997
|
/**
|
|
2583
2998
|
* Parent-side middleware hook. Fires before a request is
|
|
2584
2999
|
* forwarded into a facet sub-agent. Mirrors `onBeforeConnect` /
|
|
@@ -2640,7 +3055,14 @@ var Agent = class Agent extends Server {
|
|
|
2640
3055
|
}
|
|
2641
3056
|
const rewritten = new URL(req.url);
|
|
2642
3057
|
rewritten.pathname = match.remainingPath;
|
|
2643
|
-
const
|
|
3058
|
+
const forwardedHeaders = new Headers(req.headers);
|
|
3059
|
+
const forwardedInit = {
|
|
3060
|
+
method: req.method,
|
|
3061
|
+
headers: forwardedHeaders
|
|
3062
|
+
};
|
|
3063
|
+
if (req.headers.get("Upgrade")?.toLowerCase() === "websocket") forwardedHeaders.set(SUB_AGENT_OUTER_URL_HEADER, req.url);
|
|
3064
|
+
if (req.body && req.method !== "GET" && req.method !== "HEAD") forwardedInit.body = await req.arrayBuffer();
|
|
3065
|
+
const forwarded = new Request(rewritten, forwardedInit);
|
|
2644
3066
|
return fetcher.fetch(forwarded);
|
|
2645
3067
|
}
|
|
2646
3068
|
/**
|