@makerbi/remodex 3.1.0 → 3.2.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/package.json
CHANGED
|
@@ -1865,11 +1865,9 @@ function createDesktopIpcActionFollower({
|
|
|
1865
1865
|
return {
|
|
1866
1866
|
threadId,
|
|
1867
1867
|
method: "thread-follower-start-turn",
|
|
1868
|
-
params: {
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
turnStartParams: params,
|
|
1872
|
-
},
|
|
1868
|
+
params: { conversationId: threadId },
|
|
1869
|
+
senderRequestId: requestId,
|
|
1870
|
+
turnStartParams: params,
|
|
1873
1871
|
};
|
|
1874
1872
|
}
|
|
1875
1873
|
if (method === "turn/steer") {
|
|
@@ -1889,7 +1887,8 @@ function createDesktopIpcActionFollower({
|
|
|
1889
1887
|
method: "thread-follower-interrupt-turn",
|
|
1890
1888
|
params: {
|
|
1891
1889
|
conversationId: threadId,
|
|
1892
|
-
|
|
1890
|
+
mode: "user-stop",
|
|
1891
|
+
expectedTurnId: readString(params.turnId) || readString(params.turn_id),
|
|
1893
1892
|
},
|
|
1894
1893
|
};
|
|
1895
1894
|
}
|
|
@@ -1908,11 +1907,11 @@ function createDesktopIpcActionFollower({
|
|
|
1908
1907
|
|
|
1909
1908
|
function submitDesktopFollowerRequest(route, originalMessage) {
|
|
1910
1909
|
Promise.resolve()
|
|
1911
|
-
.then(() =>
|
|
1912
|
-
.then(async (
|
|
1910
|
+
.then(() => resolveFollowerRequest(route))
|
|
1911
|
+
.then(async (resolvedRequest) => {
|
|
1913
1912
|
if (route.method === "thread-follower-start-turn") {
|
|
1914
1913
|
try {
|
|
1915
|
-
await syncDesktopOwnerRuntimeSettings(route.threadId,
|
|
1914
|
+
await syncDesktopOwnerRuntimeSettings(route.threadId, resolvedRequest.turnStartParams);
|
|
1916
1915
|
} catch (error) {
|
|
1917
1916
|
// The actual turn has not reached Desktop yet. Even if the settings
|
|
1918
1917
|
// request timed out after being applied, continuing through the local
|
|
@@ -1921,16 +1920,16 @@ function createDesktopIpcActionFollower({
|
|
|
1921
1920
|
}
|
|
1922
1921
|
}
|
|
1923
1922
|
return {
|
|
1924
|
-
|
|
1925
|
-
result: await ipc.sendRequest(route.method,
|
|
1923
|
+
resolvedRequest,
|
|
1924
|
+
result: await ipc.sendRequest(route.method, resolvedRequest.params),
|
|
1926
1925
|
};
|
|
1927
1926
|
})
|
|
1928
|
-
.then(({
|
|
1927
|
+
.then(({ resolvedRequest, result }) => {
|
|
1929
1928
|
const appServerResult = appServerResultForFollowerRequest(route.method, result);
|
|
1930
1929
|
if (route.method === "thread-follower-start-turn") {
|
|
1931
1930
|
commitPhoneRuntimeSettings(
|
|
1932
1931
|
route.threadId,
|
|
1933
|
-
|
|
1932
|
+
resolvedRequest.turnStartParams,
|
|
1934
1933
|
readTurnIdFromAppServerResult(appServerResult)
|
|
1935
1934
|
);
|
|
1936
1935
|
}
|
|
@@ -2026,19 +2025,34 @@ function createDesktopIpcActionFollower({
|
|
|
2026
2025
|
|
|
2027
2026
|
// Desktop-followed turn starts must apply the same param normalization as
|
|
2028
2027
|
// requests forwarded straight to the local app-server.
|
|
2029
|
-
async function
|
|
2028
|
+
async function resolveFollowerRequest(route) {
|
|
2030
2029
|
if (route.method !== "thread-follower-start-turn") {
|
|
2031
|
-
return
|
|
2030
|
+
return {
|
|
2031
|
+
params: route.params,
|
|
2032
|
+
turnStartParams: null,
|
|
2033
|
+
};
|
|
2032
2034
|
}
|
|
2033
2035
|
|
|
2034
2036
|
const normalized = await Promise.resolve(
|
|
2035
|
-
normalizeTurnStartParams(cloneJSON(route.
|
|
2037
|
+
normalizeTurnStartParams(cloneJSON(route.turnStartParams))
|
|
2036
2038
|
);
|
|
2037
2039
|
const turnStartParams = normalized && typeof normalized === "object" && !Array.isArray(normalized)
|
|
2038
2040
|
? normalized
|
|
2039
|
-
: route.
|
|
2041
|
+
: route.turnStartParams;
|
|
2042
|
+
const request = cloneJSON(turnStartParams);
|
|
2043
|
+
if (!readString(request.clientUserMessageId)) {
|
|
2044
|
+
request.clientUserMessageId = route.senderRequestId;
|
|
2045
|
+
}
|
|
2040
2046
|
return {
|
|
2041
|
-
|
|
2047
|
+
params: {
|
|
2048
|
+
...route.params,
|
|
2049
|
+
turnStart: {
|
|
2050
|
+
request,
|
|
2051
|
+
context: {
|
|
2052
|
+
inheritThreadSettings: true,
|
|
2053
|
+
},
|
|
2054
|
+
},
|
|
2055
|
+
},
|
|
2042
2056
|
turnStartParams,
|
|
2043
2057
|
};
|
|
2044
2058
|
}
|
|
@@ -454,14 +454,24 @@ function buildConversationStateFromThread(thread, {
|
|
|
454
454
|
now,
|
|
455
455
|
});
|
|
456
456
|
|
|
457
|
-
|
|
457
|
+
const state = {
|
|
458
458
|
id: threadId,
|
|
459
|
+
forkedFromId: previous?.forkedFromId || null,
|
|
459
460
|
hostId,
|
|
460
461
|
turns,
|
|
461
462
|
requests: cloneJSON(previous?.requests || []),
|
|
462
463
|
createdAt: createdAtMs,
|
|
463
464
|
updatedAt: updatedAtMs,
|
|
465
|
+
recencyAt: updatedAtMs,
|
|
464
466
|
title: readString(thread?.name) || previous?.title || null,
|
|
467
|
+
source: readString(thread?.source) || previous?.source || "vscode",
|
|
468
|
+
agentNickname: previous?.agentNickname || null,
|
|
469
|
+
threadSource: readString(thread?.threadSource) || previous?.threadSource || "user",
|
|
470
|
+
historyMode: previous?.historyMode || "legacy",
|
|
471
|
+
parentThreadId: previous?.parentThreadId || null,
|
|
472
|
+
mode: previous?.mode || "default",
|
|
473
|
+
threadStartKind: previous?.threadStartKind || "default",
|
|
474
|
+
modelProvider: readString(thread?.modelProvider) || previous?.modelProvider || "openai",
|
|
465
475
|
latestModel,
|
|
466
476
|
latestReasoningEffort: previous?.latestReasoningEffort || null,
|
|
467
477
|
latestServiceTier: previous?.latestServiceTier || null,
|
|
@@ -488,7 +498,10 @@ function buildConversationStateFromThread(thread, {
|
|
|
488
498
|
workspaceBrowserRoot: previous?.workspaceBrowserRoot || null,
|
|
489
499
|
projectlessOutputDirectory: previous?.projectlessOutputDirectory || null,
|
|
490
500
|
currentPermissions: cloneJSON(previous?.currentPermissions || null),
|
|
501
|
+
sessionId: readString(thread?.sessionId) || previous?.sessionId || null,
|
|
491
502
|
};
|
|
503
|
+
synchronizeDesktopConversationCompatibility(state);
|
|
504
|
+
return state;
|
|
492
505
|
}
|
|
493
506
|
|
|
494
507
|
function mergeConversationTurnsFromThread(threadTurns, {
|
|
@@ -552,7 +565,7 @@ function createEmptyConversationState(threadId, {
|
|
|
552
565
|
cwd = "",
|
|
553
566
|
} = {}) {
|
|
554
567
|
const timestamp = now();
|
|
555
|
-
|
|
568
|
+
const state = {
|
|
556
569
|
id: threadId,
|
|
557
570
|
hostId,
|
|
558
571
|
turns: [],
|
|
@@ -587,6 +600,189 @@ function createEmptyConversationState(threadId, {
|
|
|
587
600
|
projectlessOutputDirectory: null,
|
|
588
601
|
currentPermissions: null,
|
|
589
602
|
};
|
|
603
|
+
synchronizeDesktopConversationCompatibility(state);
|
|
604
|
+
return state;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
// Desktop 26.825 moved rendered history to a canonical entity graph. It still
|
|
608
|
+
// accepts legacy turns during normalization, but unified-timeline selectors now
|
|
609
|
+
// assume the graph and several nested collections exist. Keep the bridge's
|
|
610
|
+
// mutable legacy turns for app-server event handling, and mirror them into the
|
|
611
|
+
// current Desktop shape before every stream broadcast.
|
|
612
|
+
function synchronizeDesktopConversationCompatibility(state) {
|
|
613
|
+
if (!state || typeof state !== "object" || Array.isArray(state)) {
|
|
614
|
+
return state;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
const turns = Array.isArray(state.turns) ? state.turns : [];
|
|
618
|
+
const entries = [];
|
|
619
|
+
const entitiesByKey = {};
|
|
620
|
+
for (const turn of turns) {
|
|
621
|
+
const turnId = readString(turn?.turnId) || readString(turn?.id);
|
|
622
|
+
if (!turnId) {
|
|
623
|
+
continue;
|
|
624
|
+
}
|
|
625
|
+
turn.params = normalizeTurnParamsCompatibility(turn.params, {
|
|
626
|
+
cwd: readString(turn.params?.cwd) || readString(state.cwd),
|
|
627
|
+
});
|
|
628
|
+
turn.items = Array.isArray(turn.items) ? turn.items : [];
|
|
629
|
+
turn.hookRuns = Array.isArray(turn.hookRuns) ? turn.hookRuns : [];
|
|
630
|
+
const key = `turn:${turnId}`;
|
|
631
|
+
entries.push({ key, value: key });
|
|
632
|
+
const { id: _legacyId, ...canonicalTurn } = turn;
|
|
633
|
+
entitiesByKey[key] = {
|
|
634
|
+
...canonicalTurn,
|
|
635
|
+
turnId,
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
const islandId = "tail:0";
|
|
640
|
+
state.turnHistory = {
|
|
641
|
+
kind: "canonical",
|
|
642
|
+
history: {
|
|
643
|
+
entitiesByKey,
|
|
644
|
+
generation: 0,
|
|
645
|
+
isComplete: true,
|
|
646
|
+
islands: [{
|
|
647
|
+
id: islandId,
|
|
648
|
+
entries,
|
|
649
|
+
olderBoundary: {
|
|
650
|
+
status: "exhausted",
|
|
651
|
+
boundaryId: `${islandId}:older`,
|
|
652
|
+
},
|
|
653
|
+
newerBoundary: {
|
|
654
|
+
status: "exhausted",
|
|
655
|
+
boundaryId: `${islandId}:newer`,
|
|
656
|
+
},
|
|
657
|
+
}],
|
|
658
|
+
},
|
|
659
|
+
};
|
|
660
|
+
state.turnsPagination = {
|
|
661
|
+
olderCursor: null,
|
|
662
|
+
oldestLoadedTurnId: readString(turns[0]?.turnId) || readString(turns[0]?.id) || null,
|
|
663
|
+
isLoadingOlder: false,
|
|
664
|
+
hasLoadedOldest: true,
|
|
665
|
+
};
|
|
666
|
+
|
|
667
|
+
const latestParams = [...turns]
|
|
668
|
+
.reverse()
|
|
669
|
+
.map((turn) => turn?.params)
|
|
670
|
+
.find((params) => params && typeof params === "object") || null;
|
|
671
|
+
const sandboxPolicy = normalizeSandboxPolicyCompatibility(
|
|
672
|
+
latestParams?.sandboxPolicy || state.currentPermissions?.sandboxPolicy
|
|
673
|
+
);
|
|
674
|
+
if (sandboxPolicy) {
|
|
675
|
+
const runtimeWorkspaceRoots = Array.isArray(latestParams?.runtimeWorkspaceRoots)
|
|
676
|
+
? cloneJSON(latestParams.runtimeWorkspaceRoots)
|
|
677
|
+
: Array.isArray(state.currentPermissions?.runtimeWorkspaceRoots)
|
|
678
|
+
? cloneJSON(state.currentPermissions.runtimeWorkspaceRoots)
|
|
679
|
+
: [];
|
|
680
|
+
state.currentPermissions = {
|
|
681
|
+
activePermissionProfile: cloneJSON(
|
|
682
|
+
latestParams?.activePermissionProfile
|
|
683
|
+
?? state.currentPermissions?.activePermissionProfile
|
|
684
|
+
?? permissionProfileFromId(latestParams?.permissions)
|
|
685
|
+
),
|
|
686
|
+
approvalPolicy: latestParams?.approvalPolicy
|
|
687
|
+
?? state.currentPermissions?.approvalPolicy
|
|
688
|
+
?? "on-request",
|
|
689
|
+
approvalsReviewer: latestParams?.approvalsReviewer
|
|
690
|
+
?? state.currentPermissions?.approvalsReviewer
|
|
691
|
+
?? "user",
|
|
692
|
+
runtimeWorkspaceRoots,
|
|
693
|
+
sandboxPolicy,
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
state.recencyAt = Number.isFinite(state.recencyAt) ? state.recencyAt : state.updatedAt;
|
|
698
|
+
state.source ||= "vscode";
|
|
699
|
+
state.threadSource ||= "user";
|
|
700
|
+
state.historyMode ||= "legacy";
|
|
701
|
+
state.mode ||= "default";
|
|
702
|
+
state.threadStartKind ||= "default";
|
|
703
|
+
state.modelProvider ||= "openai";
|
|
704
|
+
state.latestThreadSettings = {
|
|
705
|
+
cwd: readString(latestParams?.cwd) || readString(state.cwd) || null,
|
|
706
|
+
approvalPolicy: latestParams?.approvalPolicy ?? state.currentPermissions?.approvalPolicy ?? null,
|
|
707
|
+
approvalsReviewer: latestParams?.approvalsReviewer
|
|
708
|
+
?? state.currentPermissions?.approvalsReviewer
|
|
709
|
+
?? null,
|
|
710
|
+
...(sandboxPolicy ? { sandboxPolicy } : {}),
|
|
711
|
+
activePermissionProfile: cloneJSON(state.currentPermissions?.activePermissionProfile ?? null),
|
|
712
|
+
model: readString(state.latestThreadSettings?.model)
|
|
713
|
+
|| readString(latestParams?.model)
|
|
714
|
+
|| readString(state.latestModel)
|
|
715
|
+
|| null,
|
|
716
|
+
modelProvider: readString(state.latestThreadSettings?.modelProvider)
|
|
717
|
+
|| readString(state.modelProvider)
|
|
718
|
+
|| "openai",
|
|
719
|
+
serviceTier: readString(state.latestThreadSettings?.serviceTier)
|
|
720
|
+
|| readString(latestParams?.serviceTier)
|
|
721
|
+
|| readString(state.latestServiceTier)
|
|
722
|
+
|| null,
|
|
723
|
+
effort: state.latestThreadSettings?.effort
|
|
724
|
+
?? latestParams?.effort
|
|
725
|
+
?? state.latestReasoningEffort
|
|
726
|
+
?? null,
|
|
727
|
+
summary: latestParams?.summary ?? state.latestThreadSettings?.summary ?? "none",
|
|
728
|
+
collaborationMode: cloneJSON(
|
|
729
|
+
state.latestThreadSettings?.collaborationMode
|
|
730
|
+
|| latestParams?.collaborationMode
|
|
731
|
+
|| state.latestCollaborationMode
|
|
732
|
+
|| null
|
|
733
|
+
),
|
|
734
|
+
multiAgentMode: latestParams?.multiAgentMode
|
|
735
|
+
?? state.latestThreadSettings?.multiAgentMode
|
|
736
|
+
?? null,
|
|
737
|
+
personality: latestParams?.personality
|
|
738
|
+
?? state.latestThreadSettings?.personality
|
|
739
|
+
?? null,
|
|
740
|
+
};
|
|
741
|
+
return state;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function normalizeTurnParamsCompatibility(params, { cwd = "" } = {}) {
|
|
745
|
+
const normalized = params && typeof params === "object" && !Array.isArray(params)
|
|
746
|
+
? params
|
|
747
|
+
: {};
|
|
748
|
+
normalized.input = Array.isArray(normalized.input) ? normalized.input : [];
|
|
749
|
+
normalized.attachments = Array.isArray(normalized.attachments) ? normalized.attachments : [];
|
|
750
|
+
normalized.cwd = readString(normalized.cwd) || readString(cwd) || null;
|
|
751
|
+
normalized.summary ??= "none";
|
|
752
|
+
normalized.personality ??= null;
|
|
753
|
+
normalized.outputSchema ??= null;
|
|
754
|
+
normalized.collaborationMode ??= null;
|
|
755
|
+
const sandboxPolicy = normalizeSandboxPolicyCompatibility(normalized.sandboxPolicy);
|
|
756
|
+
if (sandboxPolicy) {
|
|
757
|
+
normalized.sandboxPolicy = sandboxPolicy;
|
|
758
|
+
}
|
|
759
|
+
return normalized;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
function normalizeSandboxPolicyCompatibility(policy) {
|
|
763
|
+
if (!policy || typeof policy !== "object" || Array.isArray(policy)) {
|
|
764
|
+
return null;
|
|
765
|
+
}
|
|
766
|
+
const normalized = cloneJSON(policy);
|
|
767
|
+
if (normalizeToken(normalized.type) === "workspacewrite") {
|
|
768
|
+
normalized.type = "workspaceWrite";
|
|
769
|
+
normalized.writableRoots = Array.isArray(normalized.writableRoots)
|
|
770
|
+
? normalized.writableRoots
|
|
771
|
+
: [];
|
|
772
|
+
normalized.excludeSlashTmp = Boolean(normalized.excludeSlashTmp);
|
|
773
|
+
normalized.excludeTmpdirEnvVar = Boolean(normalized.excludeTmpdirEnvVar);
|
|
774
|
+
normalized.networkAccess = Boolean(normalized.networkAccess);
|
|
775
|
+
}
|
|
776
|
+
if (normalizeToken(normalized.type) === "readonly") {
|
|
777
|
+
normalized.type = "readOnly";
|
|
778
|
+
normalized.networkAccess = Boolean(normalized.networkAccess);
|
|
779
|
+
}
|
|
780
|
+
return normalized;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
function permissionProfileFromId(value) {
|
|
784
|
+
const id = readString(value);
|
|
785
|
+
return id ? { id, extends: null } : null;
|
|
590
786
|
}
|
|
591
787
|
|
|
592
788
|
function buildConversationTurn(turn, {
|
|
@@ -596,7 +792,7 @@ function buildConversationTurn(turn, {
|
|
|
596
792
|
now = () => Date.now(),
|
|
597
793
|
} = {}) {
|
|
598
794
|
const turnId = readString(turn?.id) || readString(turn?.turnId) || readString(turn?.turn_id);
|
|
599
|
-
const params = cloneJSON(previousTurn?.params || {
|
|
795
|
+
const params = normalizeTurnParamsCompatibility(cloneJSON(previousTurn?.params || {
|
|
600
796
|
threadId,
|
|
601
797
|
input: [],
|
|
602
798
|
cwd: cwd || null,
|
|
@@ -611,7 +807,7 @@ function buildConversationTurn(turn, {
|
|
|
611
807
|
outputSchema: null,
|
|
612
808
|
collaborationMode: null,
|
|
613
809
|
attachments: [],
|
|
614
|
-
});
|
|
810
|
+
}), { cwd });
|
|
615
811
|
const builtTurn = {
|
|
616
812
|
id: turnId,
|
|
617
813
|
turnId,
|
|
@@ -678,6 +874,9 @@ function applyPendingTurnStartParams(
|
|
|
678
874
|
...turn.params,
|
|
679
875
|
...cloneJSON(pendingParams),
|
|
680
876
|
};
|
|
877
|
+
turn.params = normalizeTurnParamsCompatibility(turn.params, {
|
|
878
|
+
cwd: readString(turn.params?.cwd) || readString(conversation?.cwd),
|
|
879
|
+
});
|
|
681
880
|
normalizeTurnInitialPrompt(turn);
|
|
682
881
|
}
|
|
683
882
|
|
|
@@ -1262,6 +1461,7 @@ module.exports = {
|
|
|
1262
1461
|
readThreadIdFromParams,
|
|
1263
1462
|
readTurnIdFromParams,
|
|
1264
1463
|
readTurnIdFromTurn,
|
|
1464
|
+
synchronizeDesktopConversationCompatibility,
|
|
1265
1465
|
timestampSecondsToMs,
|
|
1266
1466
|
upsertItem,
|
|
1267
1467
|
upsertTurn,
|
|
@@ -27,6 +27,7 @@ const {
|
|
|
27
27
|
buildConversationStateFromThread,
|
|
28
28
|
createEmptyConversationState,
|
|
29
29
|
readThreadIdFromParams,
|
|
30
|
+
synchronizeDesktopConversationCompatibility,
|
|
30
31
|
} = require("./desktop-ipc-conversation-adapter");
|
|
31
32
|
const {
|
|
32
33
|
DEFAULT_MAX_PATCH_BYTES,
|
|
@@ -94,20 +95,33 @@ const OWNER_INBOUND_METHODS = new Set([
|
|
|
94
95
|
|
|
95
96
|
const THREAD_READ_METHODS = new Set(["thread/read", "thread/resume"]);
|
|
96
97
|
|
|
97
|
-
|
|
98
|
+
// Current app-server v2 TurnStartParams fields. Desktop's adjacent turnStart.context
|
|
99
|
+
// is presentation state, not part of this RPC shape, so it stays outside the request.
|
|
100
|
+
const APP_SERVER_TURN_START_PARAM_KEYS = new Set([
|
|
98
101
|
"threadId",
|
|
99
102
|
"input",
|
|
103
|
+
"additionalContext",
|
|
100
104
|
"cwd",
|
|
101
105
|
"approvalPolicy",
|
|
102
106
|
"approvalsReviewer",
|
|
103
107
|
"sandboxPolicy",
|
|
104
108
|
"model",
|
|
105
109
|
"serviceTier",
|
|
110
|
+
"serviceTierForTurn",
|
|
106
111
|
"effort",
|
|
107
112
|
"summary",
|
|
108
113
|
"personality",
|
|
109
114
|
"outputSchema",
|
|
110
115
|
"collaborationMode",
|
|
116
|
+
"clientUserMessageId",
|
|
117
|
+
"cyberAccessProgram",
|
|
118
|
+
"environments",
|
|
119
|
+
"multiAgentMode",
|
|
120
|
+
"permissions",
|
|
121
|
+
"responsesapiClientMetadata",
|
|
122
|
+
"runtimeWorkspaceRoots",
|
|
123
|
+
"toolOutput",
|
|
124
|
+
"turnTrigger",
|
|
111
125
|
]);
|
|
112
126
|
|
|
113
127
|
function createDesktopIpcLiveOwner({
|
|
@@ -1104,6 +1118,7 @@ function createDesktopIpcLiveOwner({
|
|
|
1104
1118
|
return true;
|
|
1105
1119
|
}
|
|
1106
1120
|
runtimeSettingsStore?.attachToConversation?.(threadId, conversationState);
|
|
1121
|
+
synchronizeDesktopConversationCompatibility(conversationState);
|
|
1107
1122
|
if (shouldDelayInitialSnapshotForHistory(threadId)) {
|
|
1108
1123
|
return false;
|
|
1109
1124
|
}
|
|
@@ -1367,10 +1382,7 @@ function createDesktopIpcLiveOwner({
|
|
|
1367
1382
|
}
|
|
1368
1383
|
|
|
1369
1384
|
async function handleFollowerStartTurn(conversationId, params) {
|
|
1370
|
-
const rawTurnStartParams = params
|
|
1371
|
-
|| params.turn_start_params
|
|
1372
|
-
|| params.turnStart
|
|
1373
|
-
|| params;
|
|
1385
|
+
const rawTurnStartParams = readFollowerTurnStartParams(params);
|
|
1374
1386
|
const codexParams = mergeFollowerRuntimeOverrides(conversationId, sanitizeTurnStartParams({
|
|
1375
1387
|
...rawTurnStartParams,
|
|
1376
1388
|
threadId: conversationId,
|
|
@@ -1380,7 +1392,9 @@ function createDesktopIpcLiveOwner({
|
|
|
1380
1392
|
? normalizedParams
|
|
1381
1393
|
: codexParams;
|
|
1382
1394
|
markOwnedThread(conversationId);
|
|
1383
|
-
const senderRequestId = params.senderRequestId
|
|
1395
|
+
const senderRequestId = params.senderRequestId
|
|
1396
|
+
|| params.sender_request_id
|
|
1397
|
+
|| rawTurnStartParams.clientUserMessageId;
|
|
1384
1398
|
const isKnownHeldPhoneStart = Boolean(
|
|
1385
1399
|
requestIdKey(senderRequestId)
|
|
1386
1400
|
&& pendingTurnStartEntriesByRequestId.has(requestIdKey(senderRequestId))
|
|
@@ -1417,6 +1431,17 @@ function createDesktopIpcLiveOwner({
|
|
|
1417
1431
|
}
|
|
1418
1432
|
}
|
|
1419
1433
|
|
|
1434
|
+
function readFollowerTurnStartParams(params) {
|
|
1435
|
+
const turnStart = isPlainJSONObject(params.turnStart) ? params.turnStart : null;
|
|
1436
|
+
if (isPlainJSONObject(turnStart?.request)) {
|
|
1437
|
+
return turnStart.request;
|
|
1438
|
+
}
|
|
1439
|
+
return params.turnStartParams
|
|
1440
|
+
|| params.turn_start_params
|
|
1441
|
+
|| params.turnStart
|
|
1442
|
+
|| params;
|
|
1443
|
+
}
|
|
1444
|
+
|
|
1420
1445
|
function mirrorFollowerUserPromptToPhone(threadId, turnStartParams, turnStartResult = null) {
|
|
1421
1446
|
const text = visibleUserPromptFromInputEntries(turnStartParams?.input);
|
|
1422
1447
|
if (!text) {
|
|
@@ -1461,16 +1486,50 @@ function createDesktopIpcLiveOwner({
|
|
|
1461
1486
|
}
|
|
1462
1487
|
|
|
1463
1488
|
async function handleFollowerInterruptTurn(conversationId, params) {
|
|
1464
|
-
const
|
|
1465
|
-
|| readString(params.
|
|
1466
|
-
||
|
|
1489
|
+
const requestedTurnId = readString(params.expectedTurnId)
|
|
1490
|
+
|| readString(params.expected_turn_id)
|
|
1491
|
+
|| readString(params.turnId)
|
|
1492
|
+
|| readString(params.turn_id);
|
|
1493
|
+
const activeTurnId = activeTurnIdForConversation(conversationId);
|
|
1494
|
+
if (requestedTurnId && requestedTurnId !== activeTurnId) {
|
|
1495
|
+
return {
|
|
1496
|
+
interruptedTurnId: null,
|
|
1497
|
+
ok: true,
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
const goalPauseError = await pauseActiveGoalForUserStop(
|
|
1502
|
+
conversationId,
|
|
1503
|
+
params.mode,
|
|
1504
|
+
Boolean(requestedTurnId)
|
|
1505
|
+
);
|
|
1506
|
+
const turnId = requestedTurnId || activeTurnId;
|
|
1467
1507
|
if (!turnId) {
|
|
1468
|
-
|
|
1508
|
+
return followerInterruptResult(null, goalPauseError);
|
|
1469
1509
|
}
|
|
1470
|
-
|
|
1510
|
+
await sendCodexRequest("turn/interrupt", {
|
|
1471
1511
|
threadId: conversationId,
|
|
1472
1512
|
turnId,
|
|
1473
1513
|
});
|
|
1514
|
+
return followerInterruptResult(turnId, goalPauseError);
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1517
|
+
async function pauseActiveGoalForUserStop(conversationId, mode, hasRequestedTurnId) {
|
|
1518
|
+
if (mode !== "user-stop" || hasRequestedTurnId) {
|
|
1519
|
+
return "";
|
|
1520
|
+
}
|
|
1521
|
+
if (conversations.get(conversationId)?.threadGoal?.status !== "active") {
|
|
1522
|
+
return "";
|
|
1523
|
+
}
|
|
1524
|
+
try {
|
|
1525
|
+
await sendCodexRequest("thread/goal/set", {
|
|
1526
|
+
threadId: conversationId,
|
|
1527
|
+
status: "paused",
|
|
1528
|
+
});
|
|
1529
|
+
return "";
|
|
1530
|
+
} catch (error) {
|
|
1531
|
+
return error?.message || "Failed to pause thread goal.";
|
|
1532
|
+
}
|
|
1474
1533
|
}
|
|
1475
1534
|
|
|
1476
1535
|
// Desktop follower approvals only carry decision-style payloads, but app-server
|
|
@@ -1786,8 +1845,7 @@ function createDesktopIpcLiveOwner({
|
|
|
1786
1845
|
return turnId;
|
|
1787
1846
|
}
|
|
1788
1847
|
}
|
|
1789
|
-
|
|
1790
|
-
return readString(latestTurn?.turnId) || readString(latestTurn?.id);
|
|
1848
|
+
return "";
|
|
1791
1849
|
}
|
|
1792
1850
|
|
|
1793
1851
|
return {
|
|
@@ -1881,7 +1939,7 @@ function normalizeInputEntriesForDesktop(input) {
|
|
|
1881
1939
|
function sanitizeTurnStartParams(params) {
|
|
1882
1940
|
const sanitized = {};
|
|
1883
1941
|
for (const [key, value] of Object.entries(params || {})) {
|
|
1884
|
-
if (
|
|
1942
|
+
if (APP_SERVER_TURN_START_PARAM_KEYS.has(key)) {
|
|
1885
1943
|
sanitized[key] = value;
|
|
1886
1944
|
}
|
|
1887
1945
|
}
|
|
@@ -1891,6 +1949,14 @@ function sanitizeTurnStartParams(params) {
|
|
|
1891
1949
|
return sanitized;
|
|
1892
1950
|
}
|
|
1893
1951
|
|
|
1952
|
+
function followerInterruptResult(interruptedTurnId, goalPauseError) {
|
|
1953
|
+
return {
|
|
1954
|
+
interruptedTurnId,
|
|
1955
|
+
...(goalPauseError ? { goalPauseError } : {}),
|
|
1956
|
+
ok: true,
|
|
1957
|
+
};
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1894
1960
|
function readThreadFromResponse(message) {
|
|
1895
1961
|
const result = message?.result || message?.payload || {};
|
|
1896
1962
|
return readThreadFromPayload(result);
|
|
@@ -28,12 +28,12 @@ const DESKTOP_IPC_METHOD_VERSIONS = new Map([
|
|
|
28
28
|
["thread-unarchived", 1],
|
|
29
29
|
["thread-read-state-changed", 2],
|
|
30
30
|
["thread-queued-followups-changed", 1],
|
|
31
|
-
["thread-follower-start-turn",
|
|
31
|
+
["thread-follower-start-turn", 2],
|
|
32
32
|
["thread-follower-load-complete-history", 1],
|
|
33
33
|
["thread-follower-update-thread-settings", 1],
|
|
34
34
|
["thread-follower-compact-thread", 1],
|
|
35
35
|
["thread-follower-steer-turn", 1],
|
|
36
|
-
["thread-follower-interrupt-turn",
|
|
36
|
+
["thread-follower-interrupt-turn", 4],
|
|
37
37
|
["thread-follower-set-model-and-reasoning", 1],
|
|
38
38
|
["thread-follower-set-collaboration-mode", 1],
|
|
39
39
|
["thread-follower-edit-last-user-turn", 2],
|