@factory/droid-sdk 0.9.1 → 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/README.md +22 -0
- package/dist/{chunk-YSKO6SPT.js → chunk-OBPHU4RT.js} +13559 -6545
- package/dist/chunk-OBPHU4RT.js.map +1 -0
- package/dist/{chunk-TWSTJMV7.mjs → chunk-TWAVPIPS.mjs} +11941 -4927
- package/dist/chunk-TWAVPIPS.mjs.map +1 -0
- package/dist/{index-C06W9tbN.d.mts → index-DWBA4zgW.d.mts} +142111 -115283
- package/dist/{index-C06W9tbN.d.ts → index-DWBA4zgW.d.ts} +142111 -115283
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +72 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +77 -7
- package/dist/node.d.mts +114 -26
- package/dist/node.d.ts +114 -26
- package/dist/node.js +973 -590
- package/dist/node.js.map +1 -1
- package/dist/node.mjs +558 -175
- package/dist/node.mjs.map +1 -1
- package/examples/browser/daemon-lifecycle.ts +4 -6
- package/examples/node/custom-model-editing-disposable.sh +88 -0
- package/examples/node/custom-model-editing-disposable.ts +171 -0
- package/examples/node/custom-model-editing.ts +55 -0
- package/examples/node/hook-execution.ts +3 -2
- package/examples/node/sdk-mcp-tool.ts +5 -3
- package/examples/node/tool-controls.ts +7 -5
- package/package.json +2 -1
- package/dist/chunk-TWSTJMV7.mjs.map +0 -1
- package/dist/chunk-YSKO6SPT.js.map +0 -1
package/dist/node.mjs
CHANGED
|
@@ -68,6 +68,7 @@ import {
|
|
|
68
68
|
ConnectionError,
|
|
69
69
|
ConnectionFailureReason,
|
|
70
70
|
ContentBlockSchema,
|
|
71
|
+
ContextApiError,
|
|
71
72
|
ContextBreakdownCategorySchema,
|
|
72
73
|
ContextStatsAccuracy,
|
|
73
74
|
ContextStatsSchema,
|
|
@@ -104,6 +105,7 @@ import {
|
|
|
104
105
|
ErrorDetailSchema,
|
|
105
106
|
ErrorNotificationSchema,
|
|
106
107
|
ExecToolInfoSchema,
|
|
108
|
+
ExecToolInfoWithSchemasSchema,
|
|
107
109
|
ExecuteRewindRequestParamsSchema,
|
|
108
110
|
ExecuteRewindRequestSchema,
|
|
109
111
|
ExecuteRewindResponseSchema,
|
|
@@ -183,6 +185,7 @@ import {
|
|
|
183
185
|
LEGACY_FACTORY_API_VERSION,
|
|
184
186
|
LEGACY_FACTORY_API_VERSION2,
|
|
185
187
|
LOCAL_MACHINE_ID,
|
|
188
|
+
LfLineDecoder,
|
|
186
189
|
ListCommandsResponseSchema,
|
|
187
190
|
ListMcpRegistryRequestParamsSchema,
|
|
188
191
|
ListMcpRegistryRequestSchema,
|
|
@@ -206,7 +209,9 @@ import {
|
|
|
206
209
|
ListToolsRequestParamsSchema,
|
|
207
210
|
ListToolsRequestSchema,
|
|
208
211
|
ListToolsResponseSchema,
|
|
212
|
+
ListToolsResponseWithSchemasSchema,
|
|
209
213
|
ListToolsResultSchema,
|
|
214
|
+
ListToolsResultWithSchemasSchema,
|
|
210
215
|
LoadSessionRequestParamsSchema,
|
|
211
216
|
LoadSessionRequestSchema,
|
|
212
217
|
LoadSessionResponseSchema,
|
|
@@ -261,6 +266,12 @@ import {
|
|
|
261
266
|
OutputFormatSchema,
|
|
262
267
|
OutputFormatType,
|
|
263
268
|
PermissionResolvedNotificationSchema,
|
|
269
|
+
PickOptionsRequestParamsSchema,
|
|
270
|
+
PickOptionsRequestSchema,
|
|
271
|
+
PickOptionsResponseSchema,
|
|
272
|
+
PickOptionsResultSchema,
|
|
273
|
+
PickOptionsRowSchema,
|
|
274
|
+
PickOptionsUnavailableError,
|
|
264
275
|
ProcessExitError,
|
|
265
276
|
ProgressLogEntrySchema,
|
|
266
277
|
ProgressLogEntryType,
|
|
@@ -272,6 +283,7 @@ import {
|
|
|
272
283
|
ReasoningEffort,
|
|
273
284
|
RedactedThinkingBlockSchema,
|
|
274
285
|
RefreshComputerResponseSchema,
|
|
286
|
+
RefreshConnectorToolCatalogResponseSchema,
|
|
275
287
|
RelayConnectionError,
|
|
276
288
|
RemoteSessionListResponseSchema,
|
|
277
289
|
RemoteSessionSchema,
|
|
@@ -298,6 +310,12 @@ import {
|
|
|
298
310
|
SESSION_INIT_TIMEOUT,
|
|
299
311
|
SLACK_DELEGATION_MAX_RETRIES,
|
|
300
312
|
ServerRequestHandlerType,
|
|
313
|
+
SessionArtifactAction,
|
|
314
|
+
SessionArtifactKind,
|
|
315
|
+
SessionArtifactProvider,
|
|
316
|
+
SessionArtifactSchema,
|
|
317
|
+
SessionArtifactSource,
|
|
318
|
+
SessionArtifactsSchema,
|
|
301
319
|
SessionError,
|
|
302
320
|
SessionMetadataSchema,
|
|
303
321
|
SessionNotFoundError,
|
|
@@ -371,11 +389,15 @@ import {
|
|
|
371
389
|
ToolConfirmationListItemSchema,
|
|
372
390
|
ToolConfirmationOutcome,
|
|
373
391
|
ToolConfirmationType,
|
|
392
|
+
ToolJsonSchemaSchema,
|
|
374
393
|
ToolProgressUpdateNotificationSchema,
|
|
375
394
|
ToolProgressUpdateSchema,
|
|
376
395
|
ToolResultNotificationSchema,
|
|
377
396
|
ToolResultSchema,
|
|
397
|
+
ToolResultSchemaDescriptorSchema,
|
|
398
|
+
ToolSchemasSchema,
|
|
378
399
|
ToolSelectionOverridesSchema,
|
|
400
|
+
ToolSourceSchema,
|
|
379
401
|
ToolUseSchema,
|
|
380
402
|
ToolUseSchema2,
|
|
381
403
|
TraceContextMetaSchema,
|
|
@@ -395,6 +417,7 @@ import {
|
|
|
395
417
|
WorkerSelectedFeatureEntrySchema,
|
|
396
418
|
WorkerStartedEntrySchema,
|
|
397
419
|
WorkerStateInfoSchema,
|
|
420
|
+
appendContextSession,
|
|
398
421
|
buildUserMessageContentBlocks,
|
|
399
422
|
configureDaemonCoreDeps,
|
|
400
423
|
connectAndAuthenticate,
|
|
@@ -402,15 +425,26 @@ import {
|
|
|
402
425
|
connectWithRetry,
|
|
403
426
|
convertNotificationToStreamMessage,
|
|
404
427
|
createComputer,
|
|
428
|
+
createContextDocument,
|
|
429
|
+
createContextFile,
|
|
430
|
+
createContextSpace,
|
|
405
431
|
createResponseSchema,
|
|
406
432
|
createWebSocketDaemonClient,
|
|
407
433
|
defaultDaemonCoreDeps,
|
|
408
434
|
deleteComputer,
|
|
435
|
+
deleteContextDocument,
|
|
436
|
+
deleteContextFile,
|
|
437
|
+
emitDroidLog,
|
|
438
|
+
escapeJsonLineSeparators,
|
|
409
439
|
extractInnerNotification,
|
|
410
440
|
filterMessagesForUI,
|
|
411
441
|
getComputer,
|
|
412
442
|
getComputerByName,
|
|
413
443
|
getComputerMetrics,
|
|
444
|
+
getContextDocument,
|
|
445
|
+
getContextDocumentByPath,
|
|
446
|
+
getContextSession,
|
|
447
|
+
getContextSpace,
|
|
414
448
|
getMachineTemplate,
|
|
415
449
|
getPermissionToolInputForDisplay,
|
|
416
450
|
getQueuedUserMessageDisplayGroup,
|
|
@@ -420,20 +454,27 @@ import {
|
|
|
420
454
|
getToolResultToolUseId,
|
|
421
455
|
hasDecoupledInteractionSettings,
|
|
422
456
|
hasSubagentSessionTag,
|
|
457
|
+
injectDroidTraceContext,
|
|
423
458
|
inspectJsonRpcEnvelope,
|
|
424
459
|
isDaemonQueuedMessageKind,
|
|
425
460
|
isPendingToolResultMarker,
|
|
426
461
|
isPersistedHookMessage,
|
|
462
|
+
isProtocolVersionAtLeast,
|
|
427
463
|
isReviewableQueuedMessageKind,
|
|
428
464
|
listComputers,
|
|
465
|
+
listContextDocuments,
|
|
466
|
+
listContextSessions,
|
|
467
|
+
listContextSpaces,
|
|
429
468
|
listMachineTemplates,
|
|
430
469
|
listRemoteSessions,
|
|
431
470
|
machineTypeToMachineConnectionType,
|
|
432
471
|
mergeSessionSettings,
|
|
433
|
-
|
|
472
|
+
readContextFilePart,
|
|
473
|
+
readContextSessionRecords,
|
|
434
474
|
recordComputerConnectSli,
|
|
475
|
+
recordDroidMetric,
|
|
435
476
|
refreshComputer,
|
|
436
|
-
|
|
477
|
+
registerContextSession,
|
|
437
478
|
restartComputer,
|
|
438
479
|
retryInstallDeps,
|
|
439
480
|
retryWithLogger,
|
|
@@ -443,9 +484,11 @@ import {
|
|
|
443
484
|
toError,
|
|
444
485
|
unwrapResponseResult,
|
|
445
486
|
updateComputer,
|
|
487
|
+
updateContextDocument,
|
|
488
|
+
uploadContextFilePart,
|
|
446
489
|
wireAbortSignal,
|
|
447
490
|
withSdkTag
|
|
448
|
-
} from "./chunk-
|
|
491
|
+
} from "./chunk-TWAVPIPS.mjs";
|
|
449
492
|
|
|
450
493
|
// src/exec-core/client.ts
|
|
451
494
|
import EventEmitter from "events";
|
|
@@ -517,6 +560,9 @@ var defaultExecCoreDeps = {
|
|
|
517
560
|
},
|
|
518
561
|
sanitizeSpawnEnv(env) {
|
|
519
562
|
return env;
|
|
563
|
+
},
|
|
564
|
+
buildRuntimeSettingsAuthorityEnv() {
|
|
565
|
+
return {};
|
|
520
566
|
}
|
|
521
567
|
}
|
|
522
568
|
};
|
|
@@ -526,6 +572,7 @@ var DroidClientEvent = /* @__PURE__ */ ((DroidClientEvent2) => {
|
|
|
526
572
|
DroidClientEvent2["SESSION_NOTIFICATION"] = "session_notification";
|
|
527
573
|
DroidClientEvent2["REQUEST_PERMISSION"] = "request_permission";
|
|
528
574
|
DroidClientEvent2["ASK_USER"] = "ask_user";
|
|
575
|
+
DroidClientEvent2["PICK_OPTIONS"] = "pick_options";
|
|
529
576
|
DroidClientEvent2["ERROR"] = "error";
|
|
530
577
|
return DroidClientEvent2;
|
|
531
578
|
})(DroidClientEvent || {});
|
|
@@ -541,90 +588,6 @@ var TransportDirection = /* @__PURE__ */ ((TransportDirection2) => {
|
|
|
541
588
|
return TransportDirection2;
|
|
542
589
|
})(TransportDirection || {});
|
|
543
590
|
|
|
544
|
-
// ../droid-sdk-core/src/observability.ts
|
|
545
|
-
function sanitizeAttributes(attributes) {
|
|
546
|
-
if (attributes === void 0) {
|
|
547
|
-
return void 0;
|
|
548
|
-
}
|
|
549
|
-
const sanitized = {};
|
|
550
|
-
for (const [key, value] of Object.entries(attributes)) {
|
|
551
|
-
if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
552
|
-
sanitized[key] = value;
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
|
-
return Object.keys(sanitized).length > 0 ? sanitized : void 0;
|
|
556
|
-
}
|
|
557
|
-
function serializeError(error) {
|
|
558
|
-
if (error instanceof Error) {
|
|
559
|
-
const code = "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
560
|
-
return {
|
|
561
|
-
name: error.name || void 0,
|
|
562
|
-
message: error.message,
|
|
563
|
-
...code !== void 0 && { code }
|
|
564
|
-
};
|
|
565
|
-
}
|
|
566
|
-
return { message: String(error) };
|
|
567
|
-
}
|
|
568
|
-
function handleSinkFailure(error, options) {
|
|
569
|
-
try {
|
|
570
|
-
options?.onError?.(error);
|
|
571
|
-
} catch {
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
function emitDroidLog(observability, event, options) {
|
|
575
|
-
const sink = observability?.logger;
|
|
576
|
-
if (!sink) {
|
|
577
|
-
return false;
|
|
578
|
-
}
|
|
579
|
-
try {
|
|
580
|
-
sink.log({
|
|
581
|
-
level: event.level,
|
|
582
|
-
name: event.name,
|
|
583
|
-
message: event.message,
|
|
584
|
-
attributes: sanitizeAttributes(event.attributes),
|
|
585
|
-
...event.error !== void 0 && {
|
|
586
|
-
error: serializeError(event.error)
|
|
587
|
-
}
|
|
588
|
-
});
|
|
589
|
-
return true;
|
|
590
|
-
} catch (error) {
|
|
591
|
-
handleSinkFailure(error, options);
|
|
592
|
-
return false;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
function recordDroidMetric(observability, event, options) {
|
|
596
|
-
const sink = observability?.metrics;
|
|
597
|
-
if (!sink) {
|
|
598
|
-
return false;
|
|
599
|
-
}
|
|
600
|
-
try {
|
|
601
|
-
sink.record({
|
|
602
|
-
name: event.name,
|
|
603
|
-
kind: event.kind,
|
|
604
|
-
value: event.value,
|
|
605
|
-
unit: event.unit,
|
|
606
|
-
attributes: sanitizeAttributes(event.attributes)
|
|
607
|
-
});
|
|
608
|
-
return true;
|
|
609
|
-
} catch (error) {
|
|
610
|
-
handleSinkFailure(error, options);
|
|
611
|
-
return false;
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
function injectDroidTraceContext(observability, carrier, options) {
|
|
615
|
-
const sink = observability?.tracing;
|
|
616
|
-
if (!sink) {
|
|
617
|
-
return false;
|
|
618
|
-
}
|
|
619
|
-
try {
|
|
620
|
-
sink.inject(carrier);
|
|
621
|
-
return true;
|
|
622
|
-
} catch (error) {
|
|
623
|
-
handleSinkFailure(error, options);
|
|
624
|
-
return false;
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
591
|
// src/exec-core/deps.ts
|
|
629
592
|
function logWarn(logger, message, metadata) {
|
|
630
593
|
logger.warn(message, metadata);
|
|
@@ -788,6 +751,7 @@ var JsonRpcEnvelopePeekSchema = JsonRpcEnvelopeSchema.partial().extend({
|
|
|
788
751
|
method: z.string().optional(),
|
|
789
752
|
id: z.string().nullable().optional()
|
|
790
753
|
}).passthrough();
|
|
754
|
+
var MCP_OAUTH_OPT_OUT_PROTOCOL_VERSION = "1.78.0";
|
|
791
755
|
function inspectJsonRpcEnvelope2(message) {
|
|
792
756
|
const result = JsonRpcEnvelopePeekSchema.safeParse(message);
|
|
793
757
|
if (!result.success) {
|
|
@@ -811,8 +775,10 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
811
775
|
pendingRequests = /* @__PURE__ */ new Map();
|
|
812
776
|
permissionHandlers = /* @__PURE__ */ new Map();
|
|
813
777
|
askUserHandlers = /* @__PURE__ */ new Map();
|
|
778
|
+
pickOptionsHandlers = /* @__PURE__ */ new Map();
|
|
814
779
|
pendingPermissionRequests = /* @__PURE__ */ new Map();
|
|
815
780
|
pendingAskUserRequests = /* @__PURE__ */ new Map();
|
|
781
|
+
pendingPickOptionsRequests = /* @__PURE__ */ new Map();
|
|
816
782
|
currentSessionId = null;
|
|
817
783
|
peerProtocolVersion;
|
|
818
784
|
/**
|
|
@@ -828,8 +794,8 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
828
794
|
getRequestAttribution;
|
|
829
795
|
constructor(options, deps = defaultExecCoreDeps) {
|
|
830
796
|
super();
|
|
831
|
-
this.transport = options.transport;
|
|
832
797
|
const resolved = resolveExecCoreDeps(options.observability, deps);
|
|
798
|
+
this.transport = options.transport;
|
|
833
799
|
this.logger = resolved.logger;
|
|
834
800
|
this.tracing = resolved.tracing;
|
|
835
801
|
this.requestTimeout = options.requestTimeout ?? DEFAULT_REQUEST_TIMEOUT2;
|
|
@@ -849,13 +815,28 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
849
815
|
});
|
|
850
816
|
this.transport.onError((error) => {
|
|
851
817
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
818
|
+
const pendingSessionIds = /* @__PURE__ */ new Set();
|
|
819
|
+
let hasPendingIdlessSessionStart = false;
|
|
820
|
+
for (const pendingRequest of this.pendingRequests.values()) {
|
|
821
|
+
if (pendingRequest.method === "droid.initialize_session" /* INITIALIZE_SESSION */ && pendingRequest.sessionId === void 0) {
|
|
822
|
+
hasPendingIdlessSessionStart = true;
|
|
823
|
+
} else if (pendingRequest.sessionId !== void 0) {
|
|
824
|
+
pendingSessionIds.add(pendingRequest.sessionId);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
const pendingSessionId = pendingSessionIds.size === 1 ? pendingSessionIds.values().next().value : void 0;
|
|
828
|
+
const sessionId = hasPendingIdlessSessionStart || pendingSessionIds.size > 1 ? void 0 : pendingSessionId ?? this.currentSessionId ?? void 0;
|
|
852
829
|
const expectedCleanExit = err instanceof ProcessExitError && err.exitCode === 0 && this.completedTurnObserved;
|
|
853
830
|
if (expectedCleanExit) {
|
|
854
831
|
this.logger.info("[DroidClient] Process exited after completed turn", {
|
|
855
|
-
|
|
832
|
+
sessionId,
|
|
833
|
+
exitCode: err.exitCode,
|
|
834
|
+
signal: err.signal
|
|
856
835
|
});
|
|
857
836
|
} else {
|
|
858
|
-
this.logger.exception(err, "Transport error"
|
|
837
|
+
this.logger.exception(err, "Transport error", {
|
|
838
|
+
sessionId
|
|
839
|
+
});
|
|
859
840
|
}
|
|
860
841
|
this.transportError = err;
|
|
861
842
|
this.rejectAllPending(err);
|
|
@@ -877,14 +858,18 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
877
858
|
return this.transport.isConnected;
|
|
878
859
|
}
|
|
879
860
|
requireMcpOAuthOptOutSupport() {
|
|
880
|
-
if (
|
|
861
|
+
if (isProtocolVersionAtLeast(
|
|
862
|
+
this.peerProtocolVersion,
|
|
863
|
+
MCP_OAUTH_OPT_OUT_PROTOCOL_VERSION
|
|
864
|
+
)) {
|
|
881
865
|
return;
|
|
882
866
|
}
|
|
883
867
|
throw new ProtocolError(
|
|
884
|
-
|
|
868
|
+
`MCP OAuth opt-out requires Droid protocol version ${MCP_OAUTH_OPT_OUT_PROTOCOL_VERSION} or newer. The connected Droid reported an older or unknown protocol version and cannot disable OAuth for MCP servers.`,
|
|
885
869
|
{
|
|
886
870
|
value: {
|
|
887
871
|
localFactoryProtocolVersion: FACTORY_PROTOCOL_VERSION,
|
|
872
|
+
minimumFactoryProtocolVersion: MCP_OAUTH_OPT_OUT_PROTOCOL_VERSION,
|
|
888
873
|
peerFactoryProtocolVersion: this.peerProtocolVersion
|
|
889
874
|
}
|
|
890
875
|
}
|
|
@@ -907,7 +892,8 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
907
892
|
};
|
|
908
893
|
const rawResponse = await this.sendRequest(
|
|
909
894
|
request,
|
|
910
|
-
this.sessionInitTimeout
|
|
895
|
+
this.sessionInitTimeout,
|
|
896
|
+
params.sessionId
|
|
911
897
|
);
|
|
912
898
|
const response = InitializeSessionResponseSchema.parse(rawResponse);
|
|
913
899
|
this.peerProtocolVersion = response.factoryProtocolVersion;
|
|
@@ -936,7 +922,8 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
936
922
|
};
|
|
937
923
|
const rawResponse = await this.sendRequest(
|
|
938
924
|
request,
|
|
939
|
-
this.sessionInitTimeout
|
|
925
|
+
this.sessionInitTimeout,
|
|
926
|
+
params.sessionId
|
|
940
927
|
);
|
|
941
928
|
const response = LoadSessionResponseSchema.parse(rawResponse);
|
|
942
929
|
this.peerProtocolVersion = response.factoryProtocolVersion;
|
|
@@ -1358,6 +1345,24 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1358
1345
|
const response = ListMcpRegistryResponseSchema.parse(rawResponse);
|
|
1359
1346
|
return response;
|
|
1360
1347
|
}
|
|
1348
|
+
async refreshConnectorToolCatalog(params = {}) {
|
|
1349
|
+
if (!this.currentSessionId) {
|
|
1350
|
+
throw new SessionError(
|
|
1351
|
+
"No active session. Call initializeSession or loadSession first."
|
|
1352
|
+
);
|
|
1353
|
+
}
|
|
1354
|
+
const request = {
|
|
1355
|
+
factoryApiVersion: LEGACY_FACTORY_API_VERSION,
|
|
1356
|
+
factoryProtocolVersion: FACTORY_PROTOCOL_VERSION,
|
|
1357
|
+
type: "request",
|
|
1358
|
+
jsonrpc: JSONRPC_VERSION2,
|
|
1359
|
+
id: uuidv4(),
|
|
1360
|
+
method: "droid.refresh_connector_tool_catalog" /* REFRESH_CONNECTOR_TOOL_CATALOG */,
|
|
1361
|
+
params
|
|
1362
|
+
};
|
|
1363
|
+
const response = await this.sendRequest(request, this.requestTimeout);
|
|
1364
|
+
return RefreshConnectorToolCatalogResponseSchema.parse(response);
|
|
1365
|
+
}
|
|
1361
1366
|
async listMcpTools() {
|
|
1362
1367
|
if (!this.currentSessionId) {
|
|
1363
1368
|
throw new SessionError(
|
|
@@ -1378,6 +1383,7 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1378
1383
|
return response;
|
|
1379
1384
|
}
|
|
1380
1385
|
async listTools(params = {}) {
|
|
1386
|
+
const schemasRequested = params.includeSchemas === true;
|
|
1381
1387
|
const request = {
|
|
1382
1388
|
factoryApiVersion: LEGACY_FACTORY_API_VERSION,
|
|
1383
1389
|
factoryProtocolVersion: FACTORY_PROTOCOL_VERSION,
|
|
@@ -1389,7 +1395,28 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1389
1395
|
};
|
|
1390
1396
|
const rawResponse = await this.sendRequest(request, this.requestTimeout);
|
|
1391
1397
|
const response = ListToolsResponseSchema.parse(rawResponse);
|
|
1392
|
-
|
|
1398
|
+
if (!schemasRequested || !("result" in response)) {
|
|
1399
|
+
return response;
|
|
1400
|
+
}
|
|
1401
|
+
const strictResult = ListToolsResultWithSchemasSchema.safeParse(
|
|
1402
|
+
response.result
|
|
1403
|
+
);
|
|
1404
|
+
if (strictResult.success) {
|
|
1405
|
+
return response;
|
|
1406
|
+
}
|
|
1407
|
+
const result = ListToolsResultSchema.parse(response.result);
|
|
1408
|
+
const missingSchemaIds = [];
|
|
1409
|
+
for (const tool2 of result.tools) {
|
|
1410
|
+
if (tool2.schemas === void 0) {
|
|
1411
|
+
missingSchemaIds.push(tool2.llmId);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
if (missingSchemaIds.length > 0) {
|
|
1415
|
+
throw new ProtocolError(
|
|
1416
|
+
`The installed Droid version did not return requested schemas for tool IDs: ${missingSchemaIds.join(", ")}. Update Droid and try again.`
|
|
1417
|
+
);
|
|
1418
|
+
}
|
|
1419
|
+
throw strictResult.error;
|
|
1393
1420
|
}
|
|
1394
1421
|
async listMcpServers() {
|
|
1395
1422
|
if (!this.currentSessionId) {
|
|
@@ -1467,7 +1494,7 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1467
1494
|
const response = SubmitMcpAuthErrorResponseSchema.parse(rawResponse);
|
|
1468
1495
|
return response;
|
|
1469
1496
|
}
|
|
1470
|
-
async listSkills() {
|
|
1497
|
+
async listSkills(params = {}) {
|
|
1471
1498
|
if (!this.currentSessionId) {
|
|
1472
1499
|
throw new SessionError(
|
|
1473
1500
|
"No active session. Call initializeSession or loadSession first."
|
|
@@ -1480,7 +1507,7 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1480
1507
|
jsonrpc: JSONRPC_VERSION2,
|
|
1481
1508
|
id: uuidv4(),
|
|
1482
1509
|
method: "droid.list_skills" /* LIST_SKILLS */,
|
|
1483
|
-
params
|
|
1510
|
+
params
|
|
1484
1511
|
};
|
|
1485
1512
|
const rawResponse = await this.sendRequest(request, this.requestTimeout);
|
|
1486
1513
|
const response = ListSkillsResponseSchema.parse(rawResponse);
|
|
@@ -1642,7 +1669,8 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1642
1669
|
id: uuidv4(),
|
|
1643
1670
|
method: "droid.compact_session" /* COMPACT_SESSION */,
|
|
1644
1671
|
params: {
|
|
1645
|
-
customInstructions: params.customInstructions
|
|
1672
|
+
customInstructions: params.customInstructions,
|
|
1673
|
+
mode: params.mode
|
|
1646
1674
|
}
|
|
1647
1675
|
};
|
|
1648
1676
|
const rawResponse = await this.sendRequest(request, COMPACTION_TIMEOUT2);
|
|
@@ -1738,13 +1766,34 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1738
1766
|
clearAskUserHandler() {
|
|
1739
1767
|
this.askUserHandlers.delete("default");
|
|
1740
1768
|
}
|
|
1741
|
-
|
|
1769
|
+
setPickOptionsHandler(handler) {
|
|
1770
|
+
this.pickOptionsHandlers.set(
|
|
1771
|
+
"default",
|
|
1772
|
+
async (event) => await handler(event)
|
|
1773
|
+
);
|
|
1774
|
+
}
|
|
1775
|
+
clearPickOptionsHandler() {
|
|
1776
|
+
this.pickOptionsHandlers.delete("default");
|
|
1777
|
+
}
|
|
1778
|
+
async close(options) {
|
|
1742
1779
|
const closeError = new ConnectionError(
|
|
1743
1780
|
"Droid client closed: pending requests cancelled"
|
|
1744
1781
|
);
|
|
1782
|
+
if (options?.closeTransportFirst) {
|
|
1783
|
+
try {
|
|
1784
|
+
await this.transport.close();
|
|
1785
|
+
} finally {
|
|
1786
|
+
this.rejectAllPending(closeError);
|
|
1787
|
+
this.permissionHandlers.clear();
|
|
1788
|
+
this.askUserHandlers.clear();
|
|
1789
|
+
this.removeAllListeners();
|
|
1790
|
+
}
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1745
1793
|
this.rejectAllPending(closeError);
|
|
1746
1794
|
this.permissionHandlers.clear();
|
|
1747
1795
|
this.askUserHandlers.clear();
|
|
1796
|
+
this.pickOptionsHandlers.clear();
|
|
1748
1797
|
this.removeAllListeners();
|
|
1749
1798
|
await this.transport.close();
|
|
1750
1799
|
}
|
|
@@ -1765,6 +1814,10 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1765
1814
|
reject(error);
|
|
1766
1815
|
});
|
|
1767
1816
|
this.pendingAskUserRequests.clear();
|
|
1817
|
+
this.pendingPickOptionsRequests.forEach(({ reject }) => {
|
|
1818
|
+
reject(error);
|
|
1819
|
+
});
|
|
1820
|
+
this.pendingPickOptionsRequests.clear();
|
|
1768
1821
|
}
|
|
1769
1822
|
settleRequest(requestId) {
|
|
1770
1823
|
this.pendingRequests.delete(requestId);
|
|
@@ -1776,7 +1829,7 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1776
1829
|
} catch {
|
|
1777
1830
|
}
|
|
1778
1831
|
}
|
|
1779
|
-
async sendRequest(request, timeout) {
|
|
1832
|
+
async sendRequest(request, timeout, sessionId) {
|
|
1780
1833
|
if (this.transportError) {
|
|
1781
1834
|
throw this.transportError;
|
|
1782
1835
|
}
|
|
@@ -1802,16 +1855,19 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1802
1855
|
method: request.method,
|
|
1803
1856
|
resolve: resolve2,
|
|
1804
1857
|
reject,
|
|
1805
|
-
timeoutId
|
|
1858
|
+
timeoutId,
|
|
1859
|
+
sessionId
|
|
1806
1860
|
});
|
|
1807
1861
|
}
|
|
1808
1862
|
);
|
|
1863
|
+
void responsePromise.catch(() => {
|
|
1864
|
+
});
|
|
1809
1865
|
try {
|
|
1810
1866
|
this.logger.info("[DroidClient] [daemon -> droid] sending request", {
|
|
1811
1867
|
requestId: request.id,
|
|
1812
1868
|
method: request.method
|
|
1813
1869
|
});
|
|
1814
|
-
await this.transport.send(
|
|
1870
|
+
await this.transport.send(requestWithMeta);
|
|
1815
1871
|
} catch (error) {
|
|
1816
1872
|
const pending = this.pendingRequests.get(request.id);
|
|
1817
1873
|
if (pending) {
|
|
@@ -1831,20 +1887,13 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1831
1887
|
}
|
|
1832
1888
|
async handleMessage(message) {
|
|
1833
1889
|
try {
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
this.handleResponse(parsed);
|
|
1837
|
-
} else if ("method" in parsed) {
|
|
1838
|
-
await this.handleEvent(parsed);
|
|
1890
|
+
if (message.type === "response") {
|
|
1891
|
+
this.handleResponse(message);
|
|
1839
1892
|
} else {
|
|
1840
|
-
|
|
1841
|
-
message
|
|
1842
|
-
});
|
|
1893
|
+
await this.handleEvent(message);
|
|
1843
1894
|
}
|
|
1844
1895
|
} catch {
|
|
1845
|
-
this.logger.warn("[DroidClient] Failed to handle message"
|
|
1846
|
-
messageByteLength: new TextEncoder().encode(message).byteLength
|
|
1847
|
-
});
|
|
1896
|
+
this.logger.warn("[DroidClient] Failed to handle message");
|
|
1848
1897
|
}
|
|
1849
1898
|
}
|
|
1850
1899
|
handleResponse(response) {
|
|
@@ -1912,6 +1961,9 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
1912
1961
|
case "droid.list_tools" /* LIST_TOOLS */:
|
|
1913
1962
|
validatedResponse = ListToolsResponseSchema.parse(response);
|
|
1914
1963
|
break;
|
|
1964
|
+
case "droid.refresh_connector_tool_catalog" /* REFRESH_CONNECTOR_TOOL_CATALOG */:
|
|
1965
|
+
validatedResponse = RefreshConnectorToolCatalogResponseSchema.parse(response);
|
|
1966
|
+
break;
|
|
1915
1967
|
case "droid.toggle_mcp_tool" /* TOGGLE_MCP_TOOL */:
|
|
1916
1968
|
validatedResponse = ToggleMcpToolResponseSchema.parse(response);
|
|
1917
1969
|
break;
|
|
@@ -2052,6 +2104,8 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
2052
2104
|
await this.handlePermissionRequest(validatedEvent);
|
|
2053
2105
|
} else if (validatedEvent.method === "droid.ask_user" /* ASK_USER */) {
|
|
2054
2106
|
await this.handleAskUserRequest(validatedEvent);
|
|
2107
|
+
} else if (validatedEvent.method === "droid.pick_options" /* PICK_OPTIONS */) {
|
|
2108
|
+
await this.handlePickOptionsRequest(validatedEvent);
|
|
2055
2109
|
}
|
|
2056
2110
|
} catch (error) {
|
|
2057
2111
|
this.logDroppedEventParseError(error, event);
|
|
@@ -2086,7 +2140,7 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
2086
2140
|
}
|
|
2087
2141
|
};
|
|
2088
2142
|
try {
|
|
2089
|
-
await this.transport.send(
|
|
2143
|
+
await this.transport.send(errorResponse);
|
|
2090
2144
|
} catch (sendError) {
|
|
2091
2145
|
this.logger.exception(
|
|
2092
2146
|
sendError,
|
|
@@ -2149,6 +2203,8 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
2149
2203
|
let selectedOption = "cancel" /* Cancel */;
|
|
2150
2204
|
let comment;
|
|
2151
2205
|
let editedSpecContent;
|
|
2206
|
+
let clientStartsHandoffSession;
|
|
2207
|
+
let specHandoffId;
|
|
2152
2208
|
const handler = this.permissionHandlers.get("default");
|
|
2153
2209
|
if (handler) {
|
|
2154
2210
|
try {
|
|
@@ -2179,6 +2235,8 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
2179
2235
|
selectedOption = parsedHandlerResult.data.selectedOption;
|
|
2180
2236
|
comment = parsedHandlerResult.data.comment;
|
|
2181
2237
|
editedSpecContent = parsedHandlerResult.data.editedSpecContent;
|
|
2238
|
+
clientStartsHandoffSession = parsedHandlerResult.data.clientStartsHandoffSession;
|
|
2239
|
+
specHandoffId = parsedHandlerResult.data.specHandoffId;
|
|
2182
2240
|
} else {
|
|
2183
2241
|
throw new DroidClientError(
|
|
2184
2242
|
"Permission handler returned invalid result",
|
|
@@ -2222,7 +2280,7 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
2222
2280
|
}
|
|
2223
2281
|
};
|
|
2224
2282
|
try {
|
|
2225
|
-
await this.transport.send(
|
|
2283
|
+
await this.transport.send(cancelResponse);
|
|
2226
2284
|
} catch (sendError) {
|
|
2227
2285
|
this.logger.exception(
|
|
2228
2286
|
sendError,
|
|
@@ -2248,14 +2306,18 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
2248
2306
|
result: {
|
|
2249
2307
|
selectedOption,
|
|
2250
2308
|
...comment !== void 0 && { comment },
|
|
2251
|
-
...editedSpecContent !== void 0 && { editedSpecContent }
|
|
2309
|
+
...editedSpecContent !== void 0 && { editedSpecContent },
|
|
2310
|
+
...clientStartsHandoffSession !== void 0 && {
|
|
2311
|
+
clientStartsHandoffSession
|
|
2312
|
+
},
|
|
2313
|
+
...specHandoffId !== void 0 && { specHandoffId }
|
|
2252
2314
|
}
|
|
2253
2315
|
};
|
|
2254
2316
|
this.logger.info("[DroidClient] Sending permission response back to CLI", {
|
|
2255
2317
|
requestId: event.id,
|
|
2256
2318
|
result: String(selectedOption)
|
|
2257
2319
|
});
|
|
2258
|
-
await this.transport.send(
|
|
2320
|
+
await this.transport.send(response);
|
|
2259
2321
|
}
|
|
2260
2322
|
async handleAskUserRequest(event) {
|
|
2261
2323
|
this.logger.info("[DroidClient] Handling ask-user request", {
|
|
@@ -2319,7 +2381,7 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
2319
2381
|
}
|
|
2320
2382
|
};
|
|
2321
2383
|
try {
|
|
2322
|
-
await this.transport.send(
|
|
2384
|
+
await this.transport.send(cancelResponse);
|
|
2323
2385
|
} catch (sendError) {
|
|
2324
2386
|
this.logger.exception(
|
|
2325
2387
|
sendError,
|
|
@@ -2341,7 +2403,105 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
2341
2403
|
requestId: event.id,
|
|
2342
2404
|
cancelled: result.cancelled ?? false
|
|
2343
2405
|
});
|
|
2344
|
-
await this.transport.send(
|
|
2406
|
+
await this.transport.send(response);
|
|
2407
|
+
}
|
|
2408
|
+
/**
|
|
2409
|
+
* Same shape as the ask-user round trip: the handler (a UI) resolves with
|
|
2410
|
+
* the user's selection, and any failure or missing handler answers the CLI
|
|
2411
|
+
* with a cancellation so its tool call never hangs. A handler that rejects
|
|
2412
|
+
* with {@link PickOptionsUnavailableError} is relayed as that JSON-RPC
|
|
2413
|
+
* error instead, which the CLI does not read as the user's cancel.
|
|
2414
|
+
*/
|
|
2415
|
+
async handlePickOptionsRequest(event) {
|
|
2416
|
+
this.logger.info("[DroidClient] Handling pick-options request", {
|
|
2417
|
+
requestId: event.id,
|
|
2418
|
+
toolCallId: event.params.toolCallId,
|
|
2419
|
+
count: event.params.rows.length
|
|
2420
|
+
});
|
|
2421
|
+
this.emit("pick_options" /* PICK_OPTIONS */, event);
|
|
2422
|
+
let result = { cancelled: true, selectedIds: [] };
|
|
2423
|
+
const handler = this.pickOptionsHandlers.get("default");
|
|
2424
|
+
if (handler) {
|
|
2425
|
+
try {
|
|
2426
|
+
const handlerPromise = new Promise(
|
|
2427
|
+
(resolve2, reject) => {
|
|
2428
|
+
this.pendingPickOptionsRequests.set(event.id, { reject });
|
|
2429
|
+
handler(event).then(resolve2).catch(reject).finally(() => {
|
|
2430
|
+
this.pendingPickOptionsRequests.delete(event.id);
|
|
2431
|
+
});
|
|
2432
|
+
}
|
|
2433
|
+
);
|
|
2434
|
+
const parsedResult = PickOptionsResultSchema.safeParse(
|
|
2435
|
+
await handlerPromise
|
|
2436
|
+
);
|
|
2437
|
+
if (!parsedResult.success) {
|
|
2438
|
+
throw new DroidClientError(
|
|
2439
|
+
"PickOptions handler returned invalid result",
|
|
2440
|
+
{ cause: parsedResult.error }
|
|
2441
|
+
);
|
|
2442
|
+
}
|
|
2443
|
+
result = parsedResult.data;
|
|
2444
|
+
} catch (error) {
|
|
2445
|
+
this.pendingPickOptionsRequests.delete(event.id);
|
|
2446
|
+
if (error instanceof PickOptionsUnavailableError) {
|
|
2447
|
+
this.logger.info("[DroidClient] Pick-options request unavailable", {
|
|
2448
|
+
requestId: event.id,
|
|
2449
|
+
code: error.rpcError.code
|
|
2450
|
+
});
|
|
2451
|
+
const failure = {
|
|
2452
|
+
jsonrpc: JSONRPC_VERSION2,
|
|
2453
|
+
factoryApiVersion: LEGACY_FACTORY_API_VERSION,
|
|
2454
|
+
factoryProtocolVersion: FACTORY_PROTOCOL_VERSION,
|
|
2455
|
+
type: "response",
|
|
2456
|
+
id: event.id,
|
|
2457
|
+
error: error.rpcError
|
|
2458
|
+
};
|
|
2459
|
+
try {
|
|
2460
|
+
await this.transport.send(failure);
|
|
2461
|
+
} catch (sendError) {
|
|
2462
|
+
this.logger.exception(
|
|
2463
|
+
sendError,
|
|
2464
|
+
"Failed to send pick-options failure"
|
|
2465
|
+
);
|
|
2466
|
+
}
|
|
2467
|
+
return;
|
|
2468
|
+
}
|
|
2469
|
+
this.logger.exception(error, "Failed to handle pick-options request");
|
|
2470
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
2471
|
+
this.emit(
|
|
2472
|
+
"session_notification" /* SESSION_NOTIFICATION */,
|
|
2473
|
+
_DroidClient.createNotificationEvent(
|
|
2474
|
+
_DroidClient.createErrorNotification(err)
|
|
2475
|
+
)
|
|
2476
|
+
);
|
|
2477
|
+
const cancelResponse = {
|
|
2478
|
+
jsonrpc: JSONRPC_VERSION2,
|
|
2479
|
+
factoryApiVersion: LEGACY_FACTORY_API_VERSION,
|
|
2480
|
+
factoryProtocolVersion: FACTORY_PROTOCOL_VERSION,
|
|
2481
|
+
type: "response",
|
|
2482
|
+
id: event.id,
|
|
2483
|
+
result: { cancelled: true, selectedIds: [] }
|
|
2484
|
+
};
|
|
2485
|
+
try {
|
|
2486
|
+
await this.transport.send(cancelResponse);
|
|
2487
|
+
} catch (sendError) {
|
|
2488
|
+
this.logger.exception(
|
|
2489
|
+
sendError,
|
|
2490
|
+
"Failed to send pick-options cancellation"
|
|
2491
|
+
);
|
|
2492
|
+
}
|
|
2493
|
+
return;
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
const response = {
|
|
2497
|
+
type: "response",
|
|
2498
|
+
jsonrpc: JSONRPC_VERSION2,
|
|
2499
|
+
factoryApiVersion: LEGACY_FACTORY_API_VERSION,
|
|
2500
|
+
factoryProtocolVersion: FACTORY_PROTOCOL_VERSION,
|
|
2501
|
+
id: event.id,
|
|
2502
|
+
result
|
|
2503
|
+
};
|
|
2504
|
+
await this.transport.send(response);
|
|
2345
2505
|
}
|
|
2346
2506
|
static getErrorType(error) {
|
|
2347
2507
|
switch (error.constructor) {
|
|
@@ -2403,10 +2563,52 @@ var DroidClient = class _DroidClient extends EventEmitter {
|
|
|
2403
2563
|
}
|
|
2404
2564
|
};
|
|
2405
2565
|
|
|
2566
|
+
// src/exec-core/message-transport.ts
|
|
2567
|
+
var JsonRpcCodecTransport = class {
|
|
2568
|
+
transport;
|
|
2569
|
+
logger;
|
|
2570
|
+
constructor(transport, logger) {
|
|
2571
|
+
this.transport = transport;
|
|
2572
|
+
this.logger = logger;
|
|
2573
|
+
}
|
|
2574
|
+
send(message) {
|
|
2575
|
+
return this.transport.send(JSON.stringify(message));
|
|
2576
|
+
}
|
|
2577
|
+
onMessage(handler) {
|
|
2578
|
+
this.transport.onMessage((frame) => {
|
|
2579
|
+
const message = decodeDroidMessage(frame, this.logger);
|
|
2580
|
+
if (message) handler(message);
|
|
2581
|
+
});
|
|
2582
|
+
}
|
|
2583
|
+
onError(handler) {
|
|
2584
|
+
this.transport.onError(handler);
|
|
2585
|
+
}
|
|
2586
|
+
close() {
|
|
2587
|
+
return this.transport.close();
|
|
2588
|
+
}
|
|
2589
|
+
get isConnected() {
|
|
2590
|
+
return this.transport.isConnected;
|
|
2591
|
+
}
|
|
2592
|
+
};
|
|
2593
|
+
function withJsonRpcCodec(transport, deps = defaultExecCoreDeps) {
|
|
2594
|
+
const { logger } = resolveExecCoreDeps(void 0, deps);
|
|
2595
|
+
return new JsonRpcCodecTransport(transport, logger);
|
|
2596
|
+
}
|
|
2597
|
+
function decodeDroidMessage(frame, logger) {
|
|
2598
|
+
try {
|
|
2599
|
+
return JsonRpcMessageSchema.parse(JSON.parse(frame));
|
|
2600
|
+
} catch (error) {
|
|
2601
|
+
logWarn(logger, "[DroidClient] Failed to handle message", {
|
|
2602
|
+
errorName: error instanceof Error ? error.name : typeof error,
|
|
2603
|
+
messageByteLength: new TextEncoder().encode(frame).byteLength
|
|
2604
|
+
});
|
|
2605
|
+
return void 0;
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2406
2609
|
// src/exec-core/managed-process.ts
|
|
2407
2610
|
import { spawnSync } from "child_process";
|
|
2408
2611
|
import fs2 from "fs";
|
|
2409
|
-
import * as readline from "readline";
|
|
2410
2612
|
|
|
2411
2613
|
// src/exec-core/runtime-utils.ts
|
|
2412
2614
|
import { homedir } from "os";
|
|
@@ -2637,7 +2839,13 @@ var ManagedProcessImpl = class {
|
|
|
2637
2839
|
_childProcess;
|
|
2638
2840
|
messageHandler = null;
|
|
2639
2841
|
errorHandler = null;
|
|
2640
|
-
|
|
2842
|
+
stdoutDecoder = new LfLineDecoder();
|
|
2843
|
+
stdoutDataHandler = (chunk) => {
|
|
2844
|
+
const text = typeof chunk === "string" ? chunk : chunk.toString("utf8");
|
|
2845
|
+
for (const line of this.stdoutDecoder.push(text)) {
|
|
2846
|
+
this.handleStdoutLine(line);
|
|
2847
|
+
}
|
|
2848
|
+
};
|
|
2641
2849
|
isClosing = false;
|
|
2642
2850
|
/** Latch so exit teardown/classification runs exactly once per process. */
|
|
2643
2851
|
exitFinalized = false;
|
|
@@ -2660,31 +2868,12 @@ var ManagedProcessImpl = class {
|
|
|
2660
2868
|
if (!this.childProcess.stdout) {
|
|
2661
2869
|
throw new ConnectionError("Failed to get process stdout");
|
|
2662
2870
|
}
|
|
2663
|
-
this.
|
|
2664
|
-
|
|
2665
|
-
crlfDelay: Infinity
|
|
2666
|
-
});
|
|
2667
|
-
this.readlineInterface.on("line", (line) => {
|
|
2668
|
-
const trimmedLine = line.trim();
|
|
2669
|
-
if (this.messageHandler && trimmedLine) {
|
|
2670
|
-
if (trimmedLine.startsWith("{") || trimmedLine.startsWith("[")) {
|
|
2671
|
-
logTransportMessage(
|
|
2672
|
-
"in" /* In */,
|
|
2673
|
-
trimmedLine,
|
|
2674
|
-
this._childProcess?.pid,
|
|
2675
|
-
this.transportLoggerDeps
|
|
2676
|
-
);
|
|
2677
|
-
this.messageHandler(trimmedLine);
|
|
2678
|
-
} else {
|
|
2679
|
-
const truncated = trimmedLine.length > MAX_NON_JSON_LOG_LENGTH ? trimmedLine.substring(0, MAX_NON_JSON_LOG_LENGTH) : trimmedLine;
|
|
2680
|
-
this.logger.warn("[droid process] non-JSON output", {
|
|
2681
|
-
state: this.logPrefix,
|
|
2682
|
-
output: truncated
|
|
2683
|
-
});
|
|
2684
|
-
}
|
|
2685
|
-
}
|
|
2686
|
-
});
|
|
2871
|
+
this.childProcess.stdout.setEncoding("utf8");
|
|
2872
|
+
this.childProcess.stdout.on("data", this.stdoutDataHandler);
|
|
2687
2873
|
this.childProcess.on("error", (error) => {
|
|
2874
|
+
if (this.processError || this.isClosing || this.exitFinalized) {
|
|
2875
|
+
return;
|
|
2876
|
+
}
|
|
2688
2877
|
this.processError = new ConnectionError(
|
|
2689
2878
|
describeSpawnError(error, this.spawnContext),
|
|
2690
2879
|
{
|
|
@@ -2693,9 +2882,16 @@ var ManagedProcessImpl = class {
|
|
|
2693
2882
|
execPath: this.spawnContext?.execPath
|
|
2694
2883
|
}
|
|
2695
2884
|
);
|
|
2696
|
-
|
|
2697
|
-
|
|
2885
|
+
this.errorHandler?.(this.processError);
|
|
2886
|
+
});
|
|
2887
|
+
this.childProcess.stdin?.on("error", (error) => {
|
|
2888
|
+
if (this.processError || this.isClosing || this.exitFinalized) {
|
|
2889
|
+
return;
|
|
2698
2890
|
}
|
|
2891
|
+
this.processError = new ConnectionError("Process stdin failed", {
|
|
2892
|
+
error
|
|
2893
|
+
});
|
|
2894
|
+
this.errorHandler?.(this.processError);
|
|
2699
2895
|
});
|
|
2700
2896
|
this.childProcess.on("exit", (code, signal) => {
|
|
2701
2897
|
this.exitDrainTimer = setTimeout(() => {
|
|
@@ -2704,6 +2900,9 @@ var ManagedProcessImpl = class {
|
|
|
2704
2900
|
this.exitDrainTimer.unref?.();
|
|
2705
2901
|
});
|
|
2706
2902
|
this.childProcess.on("close", (code, signal) => {
|
|
2903
|
+
for (const line of this.stdoutDecoder.finish()) {
|
|
2904
|
+
this.handleStdoutLine(line);
|
|
2905
|
+
}
|
|
2707
2906
|
this.finalizeExit(code, signal);
|
|
2708
2907
|
});
|
|
2709
2908
|
if (this.childProcess.stderr) {
|
|
@@ -2715,6 +2914,27 @@ var ManagedProcessImpl = class {
|
|
|
2715
2914
|
});
|
|
2716
2915
|
}
|
|
2717
2916
|
}
|
|
2917
|
+
handleStdoutLine(line) {
|
|
2918
|
+
const trimmedLine = line.trim();
|
|
2919
|
+
if (!this.messageHandler || !trimmedLine) {
|
|
2920
|
+
return;
|
|
2921
|
+
}
|
|
2922
|
+
if (trimmedLine.startsWith("{") || trimmedLine.startsWith("[")) {
|
|
2923
|
+
logTransportMessage(
|
|
2924
|
+
"in" /* In */,
|
|
2925
|
+
trimmedLine,
|
|
2926
|
+
this._childProcess?.pid,
|
|
2927
|
+
this.transportLoggerDeps
|
|
2928
|
+
);
|
|
2929
|
+
this.messageHandler(trimmedLine);
|
|
2930
|
+
return;
|
|
2931
|
+
}
|
|
2932
|
+
const truncated = trimmedLine.length > MAX_NON_JSON_LOG_LENGTH ? trimmedLine.substring(0, MAX_NON_JSON_LOG_LENGTH) : trimmedLine;
|
|
2933
|
+
this.logger.warn("[droid process] non-JSON output", {
|
|
2934
|
+
state: this.logPrefix,
|
|
2935
|
+
output: truncated
|
|
2936
|
+
});
|
|
2937
|
+
}
|
|
2718
2938
|
finalizeExit(code, signal) {
|
|
2719
2939
|
if (this.exitFinalized) {
|
|
2720
2940
|
return;
|
|
@@ -2724,12 +2944,10 @@ var ManagedProcessImpl = class {
|
|
|
2724
2944
|
clearTimeout(this.exitDrainTimer);
|
|
2725
2945
|
this.exitDrainTimer = null;
|
|
2726
2946
|
}
|
|
2947
|
+
this._childProcess?.stdout?.off("data", this.stdoutDataHandler);
|
|
2727
2948
|
this._childProcess = null;
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
this.readlineInterface = null;
|
|
2731
|
-
}
|
|
2732
|
-
if (!this.isClosing) {
|
|
2949
|
+
this.stdoutDecoder.reset();
|
|
2950
|
+
if (!this.isClosing && !this.processError) {
|
|
2733
2951
|
this.processError = new ProcessExitError(
|
|
2734
2952
|
describeExitError(code, signal),
|
|
2735
2953
|
{
|
|
@@ -2768,7 +2986,7 @@ var ManagedProcessImpl = class {
|
|
|
2768
2986
|
return;
|
|
2769
2987
|
}
|
|
2770
2988
|
const childPid = this._childProcess?.pid;
|
|
2771
|
-
stdin.write(`${message}
|
|
2989
|
+
stdin.write(`${escapeJsonLineSeparators(message)}
|
|
2772
2990
|
`, (error) => {
|
|
2773
2991
|
if (error) {
|
|
2774
2992
|
logTransportMessage(
|
|
@@ -2858,11 +3076,9 @@ var ManagedProcessImpl = class {
|
|
|
2858
3076
|
}
|
|
2859
3077
|
});
|
|
2860
3078
|
}
|
|
3079
|
+
processToClose.stdout?.off("data", this.stdoutDataHandler);
|
|
2861
3080
|
}
|
|
2862
|
-
|
|
2863
|
-
this.readlineInterface.close();
|
|
2864
|
-
this.readlineInterface = null;
|
|
2865
|
-
}
|
|
3081
|
+
this.stdoutDecoder.reset();
|
|
2866
3082
|
this.exitFinalized = true;
|
|
2867
3083
|
if (this.exitDrainTimer) {
|
|
2868
3084
|
clearTimeout(this.exitDrainTimer);
|
|
@@ -3011,6 +3227,14 @@ async function spawnWithWindowsJobObjectRetry(spawnFactory, options = {}) {
|
|
|
3011
3227
|
}
|
|
3012
3228
|
|
|
3013
3229
|
// src/exec-core/process-manager.ts
|
|
3230
|
+
var NATIVE_PROCESS_LIFECYCLE_MESSAGE = "[droid process] native lifecycle";
|
|
3231
|
+
var MAX_SPAWN_ERROR_CODE_LENGTH = 64;
|
|
3232
|
+
function getSpawnErrorCode(error) {
|
|
3233
|
+
if (typeof error !== "object" || error === null || !("code" in error) || typeof error.code !== "string" && typeof error.code !== "number") {
|
|
3234
|
+
return void 0;
|
|
3235
|
+
}
|
|
3236
|
+
return String(error.code).slice(0, MAX_SPAWN_ERROR_CODE_LENGTH);
|
|
3237
|
+
}
|
|
3014
3238
|
function buildArgs(config) {
|
|
3015
3239
|
const args = [];
|
|
3016
3240
|
if (config.mode === "acp" /* Acp */) {
|
|
@@ -3029,6 +3253,13 @@ function buildArgs(config) {
|
|
|
3029
3253
|
}
|
|
3030
3254
|
return args;
|
|
3031
3255
|
}
|
|
3256
|
+
function ensureIpcStdio(stdio) {
|
|
3257
|
+
if (Array.isArray(stdio)) {
|
|
3258
|
+
return stdio.includes("ipc") ? stdio : [...stdio, "ipc"];
|
|
3259
|
+
}
|
|
3260
|
+
const standardChannel = stdio ?? "pipe";
|
|
3261
|
+
return [standardChannel, standardChannel, standardChannel, "ipc"];
|
|
3262
|
+
}
|
|
3032
3263
|
var DroidProcessManager = class {
|
|
3033
3264
|
deps;
|
|
3034
3265
|
transportLoggerDeps;
|
|
@@ -3109,6 +3340,7 @@ var DroidProcessManager = class {
|
|
|
3109
3340
|
}
|
|
3110
3341
|
);
|
|
3111
3342
|
if (!childProcess.stdout || !childProcess.stdin) {
|
|
3343
|
+
childProcess.kill();
|
|
3112
3344
|
throw new ConnectionError("Failed to get process stdio");
|
|
3113
3345
|
}
|
|
3114
3346
|
return new ManagedProcessImpl(
|
|
@@ -3155,20 +3387,87 @@ var DroidProcessManager = class {
|
|
|
3155
3387
|
};
|
|
3156
3388
|
}
|
|
3157
3389
|
invokeNodeSpawn(planned) {
|
|
3390
|
+
const stdio = planned.enableIpc ? ensureIpcStdio(planned.stdio) : planned.stdio ?? ["pipe", "pipe", "pipe"];
|
|
3158
3391
|
const options = {
|
|
3159
3392
|
cwd: planned.expandedCwd,
|
|
3160
3393
|
env: planned.env,
|
|
3161
|
-
stdio
|
|
3394
|
+
stdio
|
|
3162
3395
|
};
|
|
3163
3396
|
if (planned.enableIpc) {
|
|
3164
3397
|
options.serialization = "json";
|
|
3165
3398
|
}
|
|
3166
|
-
|
|
3399
|
+
const spawnedAt = Date.now();
|
|
3400
|
+
let childProcess;
|
|
3401
|
+
try {
|
|
3402
|
+
childProcess = spawn(planned.execPath, planned.args, options);
|
|
3403
|
+
} catch (error) {
|
|
3404
|
+
const failedAt = Date.now();
|
|
3405
|
+
this.logNativeProcessLifecycle({
|
|
3406
|
+
state: "spawn_error",
|
|
3407
|
+
pid: null,
|
|
3408
|
+
createdAt: spawnedAt,
|
|
3409
|
+
eventDate: new Date(failedAt).toISOString(),
|
|
3410
|
+
durationMs: failedAt - spawnedAt,
|
|
3411
|
+
errnoCode: getSpawnErrorCode(error)
|
|
3412
|
+
});
|
|
3413
|
+
throw error;
|
|
3414
|
+
}
|
|
3415
|
+
const pid = childProcess.pid;
|
|
3416
|
+
if (pid === void 0) {
|
|
3417
|
+
childProcess.once("error", (error) => {
|
|
3418
|
+
const failedAt = Date.now();
|
|
3419
|
+
this.logNativeProcessLifecycle({
|
|
3420
|
+
state: "spawn_error",
|
|
3421
|
+
pid: null,
|
|
3422
|
+
createdAt: spawnedAt,
|
|
3423
|
+
eventDate: new Date(failedAt).toISOString(),
|
|
3424
|
+
durationMs: failedAt - spawnedAt,
|
|
3425
|
+
errnoCode: getSpawnErrorCode(error)
|
|
3426
|
+
});
|
|
3427
|
+
});
|
|
3428
|
+
} else {
|
|
3429
|
+
childProcess.once("exit", (exitCode, signal) => {
|
|
3430
|
+
const exitedAt = Date.now();
|
|
3431
|
+
this.logNativeProcessLifecycle({
|
|
3432
|
+
state: "exited",
|
|
3433
|
+
pid,
|
|
3434
|
+
createdAt: spawnedAt,
|
|
3435
|
+
eventDate: new Date(exitedAt).toISOString(),
|
|
3436
|
+
durationMs: exitedAt - spawnedAt,
|
|
3437
|
+
exitCode,
|
|
3438
|
+
signal
|
|
3439
|
+
});
|
|
3440
|
+
});
|
|
3441
|
+
this.logNativeProcessLifecycle({
|
|
3442
|
+
state: "spawned",
|
|
3443
|
+
pid,
|
|
3444
|
+
createdAt: spawnedAt,
|
|
3445
|
+
eventDate: new Date(spawnedAt).toISOString()
|
|
3446
|
+
});
|
|
3447
|
+
}
|
|
3448
|
+
return childProcess;
|
|
3449
|
+
}
|
|
3450
|
+
/**
|
|
3451
|
+
* Emits the content-free native process record consumed by lifecycle
|
|
3452
|
+
* measurement harnesses. `createdAt` is the wall-clock lower bound captured
|
|
3453
|
+
* immediately before spawn; `eventDate` is the wall-clock observation time.
|
|
3454
|
+
*/
|
|
3455
|
+
logNativeProcessLifecycle(record) {
|
|
3456
|
+
try {
|
|
3457
|
+
this.logger.info(NATIVE_PROCESS_LIFECYCLE_MESSAGE, record);
|
|
3458
|
+
} catch (loggingError) {
|
|
3459
|
+
void loggingError;
|
|
3460
|
+
logWarn(
|
|
3461
|
+
defaultExecCoreDeps.logger,
|
|
3462
|
+
"[droid process] native lifecycle logger failed"
|
|
3463
|
+
);
|
|
3464
|
+
}
|
|
3167
3465
|
}
|
|
3168
3466
|
spawnChildProcess(config) {
|
|
3169
3467
|
const planned = this.prepareSpawn(config);
|
|
3170
3468
|
const childProcess = this.invokeNodeSpawn(planned);
|
|
3171
3469
|
if (!childProcess.stdout || !childProcess.stdin) {
|
|
3470
|
+
childProcess.kill();
|
|
3172
3471
|
throw new ConnectionError("Failed to get process stdio");
|
|
3173
3472
|
}
|
|
3174
3473
|
return {
|
|
@@ -3187,12 +3486,20 @@ var ProcessTransport = class {
|
|
|
3187
3486
|
options;
|
|
3188
3487
|
// Store handlers that may be registered before connect() is called
|
|
3189
3488
|
messageHandler = null;
|
|
3489
|
+
logger;
|
|
3490
|
+
handleMessage = (frame) => {
|
|
3491
|
+
const message = decodeDroidMessage(frame, this.logger);
|
|
3492
|
+
if (message) this.messageHandler?.(message);
|
|
3493
|
+
};
|
|
3190
3494
|
errorHandler = null;
|
|
3191
3495
|
metrics;
|
|
3496
|
+
environmentResolver;
|
|
3192
3497
|
constructor(options = {}, deps = defaultExecCoreDeps) {
|
|
3193
3498
|
this.options = options;
|
|
3194
3499
|
const resolved = resolveExecCoreDeps(options.observability, deps);
|
|
3500
|
+
this.logger = resolved.logger;
|
|
3195
3501
|
this.metrics = resolved.metrics;
|
|
3502
|
+
this.environmentResolver = resolved.environmentResolver;
|
|
3196
3503
|
this.processManager = new DroidProcessManager(
|
|
3197
3504
|
{
|
|
3198
3505
|
observability: options.observability
|
|
@@ -3210,13 +3517,21 @@ var ProcessTransport = class {
|
|
|
3210
3517
|
mode: "stream-jsonrpc" /* StreamJsonRpc */,
|
|
3211
3518
|
cwd: this.options.cwd,
|
|
3212
3519
|
env: this.options.env,
|
|
3520
|
+
trustedEnv: {
|
|
3521
|
+
...this.options.runtimeSettingsAuthority ? this.environmentResolver.buildRuntimeSettingsAuthorityEnv(
|
|
3522
|
+
this.options.runtimeSettingsAuthority
|
|
3523
|
+
) : {},
|
|
3524
|
+
...this.options.trustedEnv
|
|
3525
|
+
},
|
|
3213
3526
|
extraArgs: this.options.droidExecExtraArgs,
|
|
3214
|
-
enableIpc: this.options.enableIpc
|
|
3527
|
+
enableIpc: this.options.enableIpc,
|
|
3528
|
+
stdio: this.options.stdio
|
|
3215
3529
|
};
|
|
3216
3530
|
const spawnStart = performance.now();
|
|
3217
3531
|
let spawnOutcome = "error";
|
|
3532
|
+
let managedProcess;
|
|
3218
3533
|
try {
|
|
3219
|
-
|
|
3534
|
+
managedProcess = process.platform === "win32" ? await this.processManager.spawnWithWindowsRetry(config) : this.processManager.spawn(config);
|
|
3220
3535
|
spawnOutcome = "success";
|
|
3221
3536
|
} finally {
|
|
3222
3537
|
this.metrics.recordDuration(
|
|
@@ -3225,8 +3540,15 @@ var ProcessTransport = class {
|
|
|
3225
3540
|
{ outcome: spawnOutcome, source: "process_transport" }
|
|
3226
3541
|
);
|
|
3227
3542
|
}
|
|
3543
|
+
try {
|
|
3544
|
+
this.options.onSpawned?.(managedProcess.childProcess);
|
|
3545
|
+
} catch (error) {
|
|
3546
|
+
await managedProcess.close();
|
|
3547
|
+
throw error;
|
|
3548
|
+
}
|
|
3549
|
+
this.managedProcess = managedProcess;
|
|
3228
3550
|
if (this.messageHandler) {
|
|
3229
|
-
this.managedProcess.onMessage(this.
|
|
3551
|
+
this.managedProcess.onMessage(this.handleMessage);
|
|
3230
3552
|
}
|
|
3231
3553
|
if (this.errorHandler) {
|
|
3232
3554
|
this.managedProcess.onError(this.errorHandler);
|
|
@@ -3236,12 +3558,12 @@ var ProcessTransport = class {
|
|
|
3236
3558
|
if (!this.managedProcess) {
|
|
3237
3559
|
throw new ConnectionError("Transport not connected");
|
|
3238
3560
|
}
|
|
3239
|
-
return this.managedProcess.send(message);
|
|
3561
|
+
return await this.managedProcess.send(JSON.stringify(message));
|
|
3240
3562
|
}
|
|
3241
3563
|
onMessage(handler) {
|
|
3242
3564
|
this.messageHandler = handler;
|
|
3243
3565
|
if (this.managedProcess) {
|
|
3244
|
-
this.managedProcess.onMessage(
|
|
3566
|
+
this.managedProcess.onMessage(this.handleMessage);
|
|
3245
3567
|
}
|
|
3246
3568
|
}
|
|
3247
3569
|
onError(handler) {
|
|
@@ -3372,15 +3694,21 @@ import http from "http";
|
|
|
3372
3694
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3373
3695
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
3374
3696
|
import { z as z2 } from "zod";
|
|
3375
|
-
function tool(name, description, inputSchemaOrHandler,
|
|
3697
|
+
function tool(name, description, inputSchemaOrHandler, handlerOrOptions, maybeOptions) {
|
|
3698
|
+
const options = typeof handlerOrOptions === "function" ? maybeOptions : handlerOrOptions;
|
|
3699
|
+
const annotationFields = options?.annotations && {
|
|
3700
|
+
annotations: options.annotations
|
|
3701
|
+
};
|
|
3376
3702
|
if (typeof inputSchemaOrHandler === "function") {
|
|
3377
3703
|
const actualHandler = inputSchemaOrHandler;
|
|
3378
3704
|
return {
|
|
3379
3705
|
name,
|
|
3380
3706
|
description,
|
|
3381
|
-
handler: (input) => actualHandler(input)
|
|
3707
|
+
handler: (input) => actualHandler(input),
|
|
3708
|
+
...annotationFields
|
|
3382
3709
|
};
|
|
3383
3710
|
}
|
|
3711
|
+
const handler = typeof handlerOrOptions === "function" ? handlerOrOptions : void 0;
|
|
3384
3712
|
if (!handler) {
|
|
3385
3713
|
throw new Error(`Missing handler for SDK MCP tool "${name}"`);
|
|
3386
3714
|
}
|
|
@@ -3389,7 +3717,8 @@ function tool(name, description, inputSchemaOrHandler, handler) {
|
|
|
3389
3717
|
name,
|
|
3390
3718
|
description,
|
|
3391
3719
|
inputSchema: inputSchemaOrHandler,
|
|
3392
|
-
handler: (input) => handler(inputObjectSchema.parse(input))
|
|
3720
|
+
handler: (input) => handler(inputObjectSchema.parse(input)),
|
|
3721
|
+
...annotationFields
|
|
3393
3722
|
};
|
|
3394
3723
|
}
|
|
3395
3724
|
function isSdkMcpServer(server) {
|
|
@@ -3515,7 +3844,8 @@ var SdkMcpServer = class {
|
|
|
3515
3844
|
description: sdkTool.description,
|
|
3516
3845
|
...sdkTool.inputSchema && {
|
|
3517
3846
|
inputSchema: sdkTool.inputSchema
|
|
3518
|
-
}
|
|
3847
|
+
},
|
|
3848
|
+
...sdkTool.annotations && { annotations: sdkTool.annotations }
|
|
3519
3849
|
},
|
|
3520
3850
|
async (input) => toCallToolResult(await sdkTool.handler(input))
|
|
3521
3851
|
);
|
|
@@ -3717,6 +4047,11 @@ var DroidSession = class _DroidSession {
|
|
|
3717
4047
|
this._ensureNotClosed();
|
|
3718
4048
|
return unwrapResponseResult(await this._client.listMcpTools()).tools;
|
|
3719
4049
|
}
|
|
4050
|
+
/** Refresh connector discovery. MCP configuration has its own lifecycle. */
|
|
4051
|
+
async refreshConnectorToolCatalog() {
|
|
4052
|
+
this._ensureNotClosed();
|
|
4053
|
+
unwrapResponseResult(await this._client.refreshConnectorToolCatalog());
|
|
4054
|
+
}
|
|
3720
4055
|
async listTools(params = {}) {
|
|
3721
4056
|
this._ensureNotClosed();
|
|
3722
4057
|
return unwrapResponseResult(await this._client.listTools(params)).tools.map(
|
|
@@ -3733,9 +4068,9 @@ var DroidSession = class _DroidSession {
|
|
|
3733
4068
|
await this._client.authenticateMcpServer(params)
|
|
3734
4069
|
);
|
|
3735
4070
|
}
|
|
3736
|
-
async listSkills() {
|
|
4071
|
+
async listSkills(params) {
|
|
3737
4072
|
this._ensureNotClosed();
|
|
3738
|
-
return unwrapResponseResult(await this._client.listSkills());
|
|
4073
|
+
return unwrapResponseResult(await this._client.listSkills(params));
|
|
3739
4074
|
}
|
|
3740
4075
|
async setSkillDisabled(params) {
|
|
3741
4076
|
this._ensureNotClosed();
|
|
@@ -3760,7 +4095,14 @@ var DroidSession = class _DroidSession {
|
|
|
3760
4095
|
}
|
|
3761
4096
|
async compact(params) {
|
|
3762
4097
|
const { session, result } = await this._runReplacement(
|
|
3763
|
-
() => this._client.compactSession(params ?? {}).then(unwrapResponseResult)
|
|
4098
|
+
() => this._client.compactSession(params ?? {}).then(unwrapResponseResult),
|
|
4099
|
+
{ retainSourceWhenSameId: true }
|
|
4100
|
+
);
|
|
4101
|
+
return { session, removedCount: result.removedCount };
|
|
4102
|
+
}
|
|
4103
|
+
async handoff(params) {
|
|
4104
|
+
const { session, result } = await this._runReplacement(
|
|
4105
|
+
() => this._client.compactSession({ ...params, mode: "handoff" }).then(unwrapResponseResult)
|
|
3764
4106
|
);
|
|
3765
4107
|
return { session, removedCount: result.removedCount };
|
|
3766
4108
|
}
|
|
@@ -3808,7 +4150,7 @@ var DroidSession = class _DroidSession {
|
|
|
3808
4150
|
}
|
|
3809
4151
|
this._status = "replacing";
|
|
3810
4152
|
}
|
|
3811
|
-
async _runReplacement(operation) {
|
|
4153
|
+
async _runReplacement(operation, options) {
|
|
3812
4154
|
this._beginReplacement();
|
|
3813
4155
|
let result;
|
|
3814
4156
|
try {
|
|
@@ -3829,6 +4171,10 @@ var DroidSession = class _DroidSession {
|
|
|
3829
4171
|
)
|
|
3830
4172
|
});
|
|
3831
4173
|
}
|
|
4174
|
+
if (options?.retainSourceWhenSameId && result.newSessionId === this._sessionId) {
|
|
4175
|
+
this._status = "active";
|
|
4176
|
+
return { session: this, result };
|
|
4177
|
+
}
|
|
3832
4178
|
return {
|
|
3833
4179
|
session: await this._loadReplacement(result.newSessionId),
|
|
3834
4180
|
result
|
|
@@ -4360,6 +4706,7 @@ export {
|
|
|
4360
4706
|
ConnectionError,
|
|
4361
4707
|
ConnectionFailureReason,
|
|
4362
4708
|
ContentBlockSchema,
|
|
4709
|
+
ContextApiError,
|
|
4363
4710
|
ContextBreakdownCategorySchema,
|
|
4364
4711
|
GetContextBreakdownResultSchema as ContextBreakdownResultSchema,
|
|
4365
4712
|
ContextStatsAccuracy,
|
|
@@ -4403,6 +4750,7 @@ export {
|
|
|
4403
4750
|
ErrorDetailSchema,
|
|
4404
4751
|
ErrorNotificationSchema,
|
|
4405
4752
|
ExecToolInfoSchema,
|
|
4753
|
+
ExecToolInfoWithSchemasSchema,
|
|
4406
4754
|
ExecuteRewindRequestParamsSchema,
|
|
4407
4755
|
ExecuteRewindRequestSchema,
|
|
4408
4756
|
ExecuteRewindResponseSchema,
|
|
@@ -4496,7 +4844,9 @@ export {
|
|
|
4496
4844
|
ListToolsRequestParamsSchema,
|
|
4497
4845
|
ListToolsRequestSchema,
|
|
4498
4846
|
ListToolsResponseSchema,
|
|
4847
|
+
ListToolsResponseWithSchemasSchema,
|
|
4499
4848
|
ListToolsResultSchema,
|
|
4849
|
+
ListToolsResultWithSchemasSchema,
|
|
4500
4850
|
LoadSessionRequestParamsSchema,
|
|
4501
4851
|
LoadSessionRequestSchema,
|
|
4502
4852
|
LoadSessionResponseSchema,
|
|
@@ -4551,6 +4901,12 @@ export {
|
|
|
4551
4901
|
OutputFormatSchema,
|
|
4552
4902
|
OutputFormatType,
|
|
4553
4903
|
PermissionResolvedNotificationSchema,
|
|
4904
|
+
PickOptionsRequestParamsSchema,
|
|
4905
|
+
PickOptionsRequestSchema,
|
|
4906
|
+
PickOptionsResponseSchema,
|
|
4907
|
+
PickOptionsResultSchema,
|
|
4908
|
+
PickOptionsRowSchema,
|
|
4909
|
+
PickOptionsUnavailableError,
|
|
4554
4910
|
ProcessExitError,
|
|
4555
4911
|
ProcessTransport,
|
|
4556
4912
|
ProgressLogEntrySchema,
|
|
@@ -4587,6 +4943,12 @@ export {
|
|
|
4587
4943
|
SLACK_DELEGATION_MAX_RETRIES,
|
|
4588
4944
|
SdkMcpServer,
|
|
4589
4945
|
ServerRequestHandlerType,
|
|
4946
|
+
SessionArtifactAction,
|
|
4947
|
+
SessionArtifactKind,
|
|
4948
|
+
SessionArtifactProvider,
|
|
4949
|
+
SessionArtifactSchema,
|
|
4950
|
+
SessionArtifactSource,
|
|
4951
|
+
SessionArtifactsSchema,
|
|
4590
4952
|
SessionError,
|
|
4591
4953
|
SessionMetadataSchema,
|
|
4592
4954
|
SessionNotFoundError,
|
|
@@ -4658,11 +5020,15 @@ export {
|
|
|
4658
5020
|
ToolConfirmationListItemSchema,
|
|
4659
5021
|
ToolConfirmationOutcome,
|
|
4660
5022
|
ToolConfirmationType,
|
|
5023
|
+
ToolJsonSchemaSchema,
|
|
4661
5024
|
ToolProgressUpdateNotificationSchema,
|
|
4662
5025
|
ToolProgressUpdateSchema,
|
|
4663
5026
|
ToolResultSchema as ToolResultBlockSchema,
|
|
4664
5027
|
ToolResultNotificationSchema,
|
|
5028
|
+
ToolResultSchemaDescriptorSchema,
|
|
5029
|
+
ToolSchemasSchema,
|
|
4665
5030
|
ToolSelectionOverridesSchema,
|
|
5031
|
+
ToolSourceSchema,
|
|
4666
5032
|
ToolUseSchema as ToolUseBlockSchema,
|
|
4667
5033
|
ToolUseSchema2 as ToolUseSchema,
|
|
4668
5034
|
TraceContextMetaSchema,
|
|
@@ -4684,6 +5050,7 @@ export {
|
|
|
4684
5050
|
WorkerStartedEntrySchema,
|
|
4685
5051
|
WorkerStateInfoSchema,
|
|
4686
5052
|
__resetTransportLoggerForTests,
|
|
5053
|
+
appendContextSession,
|
|
4687
5054
|
buildUserMessageContentBlocks,
|
|
4688
5055
|
configureDaemonCoreDeps,
|
|
4689
5056
|
connectAndAuthenticate,
|
|
@@ -4691,16 +5058,25 @@ export {
|
|
|
4691
5058
|
connectWithRetry,
|
|
4692
5059
|
convertNotificationToStreamMessage,
|
|
4693
5060
|
createComputer,
|
|
5061
|
+
createContextDocument,
|
|
5062
|
+
createContextFile,
|
|
5063
|
+
createContextSpace,
|
|
4694
5064
|
createResponseSchema,
|
|
4695
5065
|
createSdkMcpServer,
|
|
4696
5066
|
createSession,
|
|
4697
5067
|
createWebSocketDaemonClient,
|
|
4698
5068
|
defaultDaemonCoreDeps,
|
|
4699
5069
|
deleteComputer,
|
|
5070
|
+
deleteContextDocument,
|
|
5071
|
+
deleteContextFile,
|
|
4700
5072
|
filterMessagesForUI,
|
|
4701
5073
|
getComputer,
|
|
4702
5074
|
getComputerByName,
|
|
4703
5075
|
getComputerMetrics,
|
|
5076
|
+
getContextDocument,
|
|
5077
|
+
getContextDocumentByPath,
|
|
5078
|
+
getContextSession,
|
|
5079
|
+
getContextSpace,
|
|
4704
5080
|
getMachineTemplate,
|
|
4705
5081
|
getPermissionToolInputForDisplay,
|
|
4706
5082
|
getQueuedUserMessageDisplayGroup,
|
|
@@ -4717,6 +5093,9 @@ export {
|
|
|
4717
5093
|
isReviewableQueuedMessageKind,
|
|
4718
5094
|
isTransportLoggingEnabled,
|
|
4719
5095
|
listComputers,
|
|
5096
|
+
listContextDocuments,
|
|
5097
|
+
listContextSessions,
|
|
5098
|
+
listContextSpaces,
|
|
4720
5099
|
listMachineTemplates,
|
|
4721
5100
|
listModels,
|
|
4722
5101
|
listRemoteSessions,
|
|
@@ -4724,10 +5103,11 @@ export {
|
|
|
4724
5103
|
logTransportMessage,
|
|
4725
5104
|
machineTypeToMachineConnectionType,
|
|
4726
5105
|
noopLogger,
|
|
4727
|
-
|
|
5106
|
+
readContextFilePart,
|
|
5107
|
+
readContextSessionRecords,
|
|
4728
5108
|
recordComputerConnectSli,
|
|
4729
5109
|
refreshComputer,
|
|
4730
|
-
|
|
5110
|
+
registerContextSession,
|
|
4731
5111
|
resolveExecCoreDeps,
|
|
4732
5112
|
restartComputer,
|
|
4733
5113
|
resumeSession,
|
|
@@ -4739,6 +5119,9 @@ export {
|
|
|
4739
5119
|
summarizeSessionToolUsage,
|
|
4740
5120
|
toError,
|
|
4741
5121
|
tool,
|
|
4742
|
-
updateComputer
|
|
5122
|
+
updateComputer,
|
|
5123
|
+
updateContextDocument,
|
|
5124
|
+
uploadContextFilePart,
|
|
5125
|
+
withJsonRpcCodec
|
|
4743
5126
|
};
|
|
4744
5127
|
//# sourceMappingURL=node.mjs.map
|