@gajae-code/coding-agent 0.12.6 → 0.12.8
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/CHANGELOG.md +22 -1
- package/dist/types/async/job-manager.d.ts +36 -1
- package/dist/types/commands/notify.d.ts +4 -0
- package/dist/types/config/file-lock.d.ts +3 -0
- package/dist/types/config/model-discovery-manager.d.ts +6 -1
- package/dist/types/config/model-registry.d.ts +2 -0
- package/dist/types/config/resolve-config-value.d.ts +2 -1
- package/dist/types/config/settings-schema.d.ts +17 -1
- package/dist/types/eval/backend.d.ts +2 -2
- package/dist/types/exec/bash-executor.d.ts +8 -10
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +0 -36
- package/dist/types/internal-urls/registry-helpers.d.ts +0 -18
- package/dist/types/main.d.ts +1 -0
- package/dist/types/modes/components/hook-selector.d.ts +20 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +53 -4
- package/dist/types/modes/controllers/extension-ui-controller.d.ts +1 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +4 -2
- package/dist/types/sdk/broker/broker.d.ts +5 -1
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +1 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +11 -3
- package/dist/types/sdk/bus/config.d.ts +75 -113
- package/dist/types/sdk/bus/discord-live-provider.d.ts +8 -2
- package/dist/types/sdk/bus/discord-provider.d.ts +19 -0
- package/dist/types/sdk/bus/index.d.ts +1 -1
- package/dist/types/sdk/bus/notification-orchestration.d.ts +127 -18
- package/dist/types/sdk/bus/notification-service.d.ts +31 -4
- package/dist/types/sdk/bus/session-control.d.ts +8 -3
- package/dist/types/sdk/bus/slack-live-provider.d.ts +9 -2
- package/dist/types/sdk/bus/slack-provider.d.ts +22 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +9 -4
- package/dist/types/sdk/client/discovery.d.ts +2 -1
- package/dist/types/sdk/host/host.d.ts +2 -23
- package/dist/types/sdk/host/query/handlers.d.ts +2 -0
- package/dist/types/sdk/host/reverse-leases.d.ts +4 -7
- package/dist/types/sdk/index.d.ts +1 -0
- package/dist/types/sdk/providers.d.ts +22 -0
- package/dist/types/sdk/session-directory.d.ts +1 -1
- package/dist/types/session/artifacts.d.ts +5 -8
- package/dist/types/session/client-bridge.d.ts +0 -14
- package/dist/types/session/internal/managed-session-scope.d.ts +17 -1
- package/dist/types/session/internal/managed-session-storage.d.ts +11 -4
- package/dist/types/session/internal/native-publish-outcome.d.ts +1 -0
- package/dist/types/session/internal/session-open-errors.d.ts +5 -0
- package/dist/types/session/messages.d.ts +1 -4
- package/dist/types/session/session-manager.d.ts +7 -6
- package/dist/types/session/session-storage.d.ts +2 -0
- package/dist/types/session/streaming-output.d.ts +0 -32
- package/dist/types/task/receipt.d.ts +1 -2
- package/dist/types/task/types.d.ts +43 -178
- package/dist/types/tools/bash.d.ts +1 -1
- package/dist/types/tools/fetch.d.ts +0 -3
- package/dist/types/tools/output-meta.d.ts +5 -37
- package/dist/types/tools/subagent.d.ts +15 -0
- package/dist/types/tools/todo-write.d.ts +3 -0
- package/dist/types/tools/tool-result.d.ts +0 -1
- package/package.json +10 -8
- package/scripts/build-sdk-package-smoke.ts +51 -0
- package/scripts/capture-notifications-settings-showcase.ts +1 -1
- package/src/async/job-manager.ts +430 -46
- package/src/cli/notify-cli.ts +204 -94
- package/src/commands/notify.ts +19 -8
- package/src/config/file-lock.ts +6 -0
- package/src/config/model-discovery-manager.ts +50 -8
- package/src/config/model-registry.ts +862 -75
- package/src/config/resolve-config-value.ts +10 -8
- package/src/config/settings-schema.ts +25 -15
- package/src/config/settings.ts +15 -15
- package/src/cursor.ts +13 -20
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +2 -3
- package/src/eval/backend.ts +2 -2
- package/src/exec/bash-executor.ts +151 -425
- package/src/gjc-runtime/session-state-sidecar.ts +12 -2
- package/src/gjc-runtime/ultragoal-runtime.ts +3 -280
- package/src/gjc-runtime/workflow-manifest.generated.json +1 -40
- package/src/gjc-runtime/workflow-manifest.ts +0 -12
- package/src/internal-urls/agent-protocol.ts +38 -98
- package/src/internal-urls/artifact-protocol.ts +17 -28
- package/src/internal-urls/docs-index.generated.ts +7 -7
- package/src/internal-urls/registry-helpers.ts +0 -62
- package/src/main.ts +43 -7
- package/src/modes/DESIGN.md +11 -11
- package/src/modes/acp/acp-agent.ts +0 -24
- package/src/modes/acp/acp-client-bridge.ts +11 -154
- package/src/modes/components/hook-selector.ts +155 -44
- package/src/modes/components/model-selector.ts +242 -49
- package/src/modes/components/notifications-settings-editor.ts +631 -85
- package/src/modes/controllers/extension-ui-controller.ts +114 -15
- package/src/modes/controllers/selector-controller.ts +464 -50
- package/src/prompts/tools/bash.md +2 -2
- package/src/sdk/acp/adapter.ts +9 -200
- package/src/sdk/broker/broker.ts +54 -10
- package/src/sdk/broker/lifecycle-ledger.ts +34 -1
- package/src/sdk/broker/lifecycle.ts +47 -50
- package/src/sdk/bus/chat-daemon-cli.ts +12 -5
- package/src/sdk/bus/chat-daemon-control.ts +35 -8
- package/src/sdk/bus/chat-daemon-runtime.ts +16 -2
- package/src/sdk/bus/config.ts +534 -286
- package/src/sdk/bus/discord-live-provider.ts +57 -2
- package/src/sdk/bus/discord-provider.ts +21 -0
- package/src/sdk/bus/index.ts +105 -359
- package/src/sdk/bus/notification-orchestration.ts +371 -68
- package/src/sdk/bus/notification-service.ts +431 -130
- package/src/sdk/bus/session-control.ts +119 -44
- package/src/sdk/bus/slack-live-provider.ts +78 -2
- package/src/sdk/bus/slack-provider.ts +24 -0
- package/src/sdk/bus/telegram-daemon-cli.ts +9 -2
- package/src/sdk/bus/telegram-daemon-contract.ts +9 -4
- package/src/sdk/bus/telegram-daemon-control.ts +3 -3
- package/src/sdk/bus/telegram-daemon.ts +23 -15
- package/src/sdk/client/discovery.ts +10 -4
- package/src/sdk/host/host.ts +9 -187
- package/src/sdk/host/query/handlers.ts +20 -1
- package/src/sdk/host/reverse-leases.ts +42 -249
- package/src/sdk/index.ts +1 -0
- package/src/sdk/protocol/operation-inventory.generated.json +18 -0
- package/src/sdk/protocol/operation-registry.ts +5 -2
- package/src/sdk/providers.ts +51 -0
- package/src/sdk/session-directory.ts +1 -0
- package/src/sdk/session.ts +10 -7
- package/src/session/agent-session.ts +59 -202
- package/src/session/artifacts.ts +74 -211
- package/src/session/client-bridge.ts +0 -15
- package/src/session/internal/managed-session-scope.ts +981 -450
- package/src/session/internal/managed-session-storage.ts +362 -124
- package/src/session/internal/native-publish-outcome.ts +3 -1
- package/src/session/internal/session-open-errors.ts +11 -0
- package/src/session/messages.ts +7 -32
- package/src/session/session-manager.ts +48 -15
- package/src/session/session-storage.ts +72 -5
- package/src/session/streaming-output.ts +40 -198
- package/src/slash-commands/builtin-registry.ts +82 -4
- package/src/task/index.ts +237 -65
- package/src/task/receipt.ts +2 -4
- package/src/task/render.ts +0 -30
- package/src/task/types.ts +10 -34
- package/src/tools/ask.ts +1 -1
- package/src/tools/bash.ts +239 -818
- package/src/tools/eval.ts +4 -99
- package/src/tools/fetch.ts +15 -77
- package/src/tools/find.ts +3 -7
- package/src/tools/output-meta.ts +114 -696
- package/src/tools/search.ts +4 -9
- package/src/tools/subagent.ts +97 -75
- package/src/tools/telegram-send.ts +4 -2
- package/src/tools/todo-write.ts +47 -0
- package/src/tools/tool-result.ts +0 -1
- package/dist/types/gjc-runtime/ultragoal-review-source.d.ts +0 -83
- package/dist/types/utils/artifact-id.d.ts +0 -2
- package/src/gjc-runtime/ultragoal-review-source.ts +0 -378
- package/src/utils/artifact-id.ts +0 -6
package/src/task/index.ts
CHANGED
|
@@ -53,9 +53,6 @@ import {
|
|
|
53
53
|
RepositoryBindingError,
|
|
54
54
|
resolveTaskRepositoryBinding,
|
|
55
55
|
} from "../gjc-runtime/repository-binding";
|
|
56
|
-
import { reconcileReviewSourceDelivery } from "../gjc-runtime/ultragoal-review-source";
|
|
57
|
-
import { classifyUltragoalReviewDelivery, validateUltragoalReviewDispatch } from "../gjc-runtime/ultragoal-runtime";
|
|
58
|
-
|
|
59
56
|
import { initializeLocalRoot, type LocalProtocolOptions, resolveLocalUrlToPath } from "../internal-urls";
|
|
60
57
|
import { ArtifactManager } from "../session/artifacts";
|
|
61
58
|
import { generateCommitMessage } from "../utils/commit-message-generator";
|
|
@@ -91,6 +88,18 @@ import {
|
|
|
91
88
|
type WorktreeBaseline,
|
|
92
89
|
} from "./worktree";
|
|
93
90
|
|
|
91
|
+
interface DuplicateIdentity {
|
|
92
|
+
role: string;
|
|
93
|
+
ownerId?: string;
|
|
94
|
+
parentSession: string | null;
|
|
95
|
+
repository: { root: string; relativeSubdir: string | null };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
interface DuplicateDisposition {
|
|
99
|
+
action: "warned" | "superseded";
|
|
100
|
+
predecessorIds: string[];
|
|
101
|
+
}
|
|
102
|
+
|
|
94
103
|
interface TaskResumeDescriptor {
|
|
95
104
|
toolCallId: string;
|
|
96
105
|
params: TaskParams;
|
|
@@ -99,6 +108,11 @@ interface TaskResumeDescriptor {
|
|
|
99
108
|
durableOutputAllowed?: boolean;
|
|
100
109
|
forkContextSeed?: ForkContextSeed;
|
|
101
110
|
agentSource: AgentDefinition["source"];
|
|
111
|
+
repositoryBinding: RepositoryBinding;
|
|
112
|
+
duplicateIdentity: DuplicateIdentity;
|
|
113
|
+
duplicatePolicy: "warn" | "supersede";
|
|
114
|
+
initialDisposition?: DuplicateDisposition;
|
|
115
|
+
lastAdmissionFailure?: string;
|
|
102
116
|
}
|
|
103
117
|
|
|
104
118
|
function isTaskResumeDescriptor(value: unknown): value is TaskResumeDescriptor {
|
|
@@ -188,18 +202,12 @@ async function resolveTaskItemsWithRepositoryBindings(
|
|
|
188
202
|
for (const task of tasks) {
|
|
189
203
|
try {
|
|
190
204
|
const binding = await resolveTaskRepositoryBinding(cwd, task.repositoryBinding);
|
|
191
|
-
if (binding.relativeSubdir)
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
resolved.push({
|
|
195
|
-
...task,
|
|
196
|
-
repositoryBinding: binding,
|
|
197
|
-
});
|
|
205
|
+
if (binding.relativeSubdir) assertPathUnderRepositoryBinding(binding, ".");
|
|
206
|
+
resolved.push({ ...task, repositoryBinding: binding });
|
|
198
207
|
} catch (error) {
|
|
199
208
|
const id = task.id?.trim() ? task.id : "(missing-id)";
|
|
200
|
-
if (error instanceof RepositoryBindingError)
|
|
209
|
+
if (error instanceof RepositoryBindingError)
|
|
201
210
|
return { tasks: [], error: `Task "${id}" repository binding rejected: ${error.message}` };
|
|
202
|
-
}
|
|
203
211
|
return {
|
|
204
212
|
tasks: [],
|
|
205
213
|
error: `Task "${id}" repository binding rejected: ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -209,6 +217,31 @@ async function resolveTaskItemsWithRepositoryBindings(
|
|
|
209
217
|
return { tasks: resolved };
|
|
210
218
|
}
|
|
211
219
|
|
|
220
|
+
function duplicateIdentityForTask(
|
|
221
|
+
task: TaskItem,
|
|
222
|
+
role: string,
|
|
223
|
+
ownerId: string | undefined,
|
|
224
|
+
parentSession: string | null,
|
|
225
|
+
): DuplicateIdentity {
|
|
226
|
+
const binding = task.repositoryBinding as RepositoryBinding;
|
|
227
|
+
return {
|
|
228
|
+
role: role.trim(),
|
|
229
|
+
ownerId,
|
|
230
|
+
parentSession,
|
|
231
|
+
repository: { root: binding.commonDir ?? binding.worktreeRoot, relativeSubdir: binding.relativeSubdir ?? null },
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function duplicateIdentityKey(identity: DuplicateIdentity): string {
|
|
236
|
+
return JSON.stringify([
|
|
237
|
+
identity.role,
|
|
238
|
+
identity.ownerId ?? null,
|
|
239
|
+
identity.parentSession,
|
|
240
|
+
identity.repository.root,
|
|
241
|
+
identity.repository.relativeSubdir,
|
|
242
|
+
]);
|
|
243
|
+
}
|
|
244
|
+
|
|
212
245
|
function repositoryBindingFromTask(task: TaskItem): RepositoryBinding | undefined {
|
|
213
246
|
return task.repositoryBinding ? publicRepositoryBinding(task.repositoryBinding as RepositoryBinding) : undefined;
|
|
214
247
|
}
|
|
@@ -859,7 +892,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
859
892
|
}
|
|
860
893
|
|
|
861
894
|
const startedJobs: Array<{ jobId: string; taskId: string }> = [];
|
|
862
|
-
const failedSchedules:
|
|
895
|
+
const failedSchedules: Array<{
|
|
896
|
+
task: TaskItem & { id: string };
|
|
897
|
+
taskIndex: number;
|
|
898
|
+
message: string;
|
|
899
|
+
signalSkip: boolean;
|
|
900
|
+
duplicateDisposition?: DuplicateDisposition;
|
|
901
|
+
}> = [];
|
|
863
902
|
let completedJobs = 0;
|
|
864
903
|
let failedJobs = 0;
|
|
865
904
|
|
|
@@ -886,21 +925,105 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
886
925
|
};
|
|
887
926
|
|
|
888
927
|
const maxConcurrency = this.session.settings.get("task.maxConcurrency");
|
|
928
|
+
const ownerId = this.session.getAgentId?.() ?? undefined;
|
|
929
|
+
const parentSession = this.session.getSessionFile();
|
|
930
|
+
const admitDuplicateLaunch = (
|
|
931
|
+
subagentId: string,
|
|
932
|
+
task: TaskItem,
|
|
933
|
+
policy: "warn" | "supersede",
|
|
934
|
+
selfSubagentId?: string,
|
|
935
|
+
): { ok: boolean; disposition?: DuplicateDisposition; error?: string; identity: DuplicateIdentity } => {
|
|
936
|
+
const identity = duplicateIdentityForTask(task, params.agent, ownerId, parentSession);
|
|
937
|
+
const key = duplicateIdentityKey(identity);
|
|
938
|
+
const predecessors = (manager.getSubagentRecords?.({ ownerId }) ?? [])
|
|
939
|
+
.filter(record => {
|
|
940
|
+
if (record.subagentId === selfSubagentId || record.subagentId === subagentId) return false;
|
|
941
|
+
if (record.status !== "running" && record.status !== "paused" && record.status !== "queued")
|
|
942
|
+
return false;
|
|
943
|
+
return record.duplicateIdentity === key;
|
|
944
|
+
})
|
|
945
|
+
.sort(
|
|
946
|
+
(a, b) =>
|
|
947
|
+
(b.currentJobId ? (manager.getJob(b.currentJobId)?.startTime ?? 0) : 0) -
|
|
948
|
+
(a.currentJobId ? (manager.getJob(a.currentJobId)?.startTime ?? 0) : 0) ||
|
|
949
|
+
a.subagentId.localeCompare(b.subagentId),
|
|
950
|
+
);
|
|
951
|
+
if (predecessors.length === 0) return { ok: true, identity };
|
|
952
|
+
if (policy === "warn")
|
|
953
|
+
return {
|
|
954
|
+
ok: true,
|
|
955
|
+
identity,
|
|
956
|
+
disposition: { action: "warned", predecessorIds: predecessors.map(record => record.subagentId) },
|
|
957
|
+
};
|
|
958
|
+
for (const predecessor of predecessors)
|
|
959
|
+
if (!manager.cancelSubagent(predecessor.subagentId, { ownerId }))
|
|
960
|
+
return { ok: false, identity, error: "duplicate_supersede_failed" };
|
|
961
|
+
return {
|
|
962
|
+
ok: true,
|
|
963
|
+
identity,
|
|
964
|
+
disposition: { action: "superseded", predecessorIds: predecessors.map(record => record.subagentId) },
|
|
965
|
+
};
|
|
966
|
+
};
|
|
889
967
|
let resumeRunner: ResumeRunner | undefined;
|
|
890
968
|
if (typeof manager.setResumeRunner === "function") {
|
|
891
969
|
resumeRunner = (_subagentId, message, resumeDescriptor) => {
|
|
892
970
|
const descriptor = isTaskResumeDescriptor(resumeDescriptor?.data) ? resumeDescriptor.data : undefined;
|
|
893
971
|
if (!descriptor) return undefined;
|
|
972
|
+
const admission = (() => {
|
|
973
|
+
const identity = descriptor.duplicateIdentity;
|
|
974
|
+
const key = duplicateIdentityKey(identity);
|
|
975
|
+
const predecessors = manager
|
|
976
|
+
.getSubagentRecords({ ownerId })
|
|
977
|
+
.filter(record => {
|
|
978
|
+
if (
|
|
979
|
+
record.subagentId === descriptor.task.id ||
|
|
980
|
+
!["running", "paused", "queued"].includes(record.status)
|
|
981
|
+
)
|
|
982
|
+
return false;
|
|
983
|
+
return record.duplicateIdentity === key;
|
|
984
|
+
})
|
|
985
|
+
.sort(
|
|
986
|
+
(a, b) =>
|
|
987
|
+
(b.currentJobId ? (manager.getJob(b.currentJobId)?.startTime ?? 0) : 0) -
|
|
988
|
+
(a.currentJobId ? (manager.getJob(a.currentJobId)?.startTime ?? 0) : 0) ||
|
|
989
|
+
a.subagentId.localeCompare(b.subagentId),
|
|
990
|
+
);
|
|
991
|
+
if (predecessors.length === 0) return { ok: true, identity };
|
|
992
|
+
if (descriptor.duplicatePolicy === "warn")
|
|
993
|
+
return {
|
|
994
|
+
ok: true,
|
|
995
|
+
identity,
|
|
996
|
+
disposition: { action: "warned", predecessorIds: predecessors.map(record => record.subagentId) },
|
|
997
|
+
};
|
|
998
|
+
for (const predecessor of predecessors)
|
|
999
|
+
if (!manager.cancelSubagent(predecessor.subagentId, { ownerId }))
|
|
1000
|
+
return { ok: false, identity, error: "duplicate_supersede_failed" };
|
|
1001
|
+
return {
|
|
1002
|
+
ok: true,
|
|
1003
|
+
identity,
|
|
1004
|
+
disposition: { action: "superseded", predecessorIds: predecessors.map(record => record.subagentId) },
|
|
1005
|
+
};
|
|
1006
|
+
})();
|
|
1007
|
+
if (!admission.ok) {
|
|
1008
|
+
descriptor.lastAdmissionFailure = admission.error;
|
|
1009
|
+
return undefined;
|
|
1010
|
+
}
|
|
1011
|
+
if (!descriptor) return undefined;
|
|
894
1012
|
const forkSeeds = descriptor.forkContextSeed
|
|
895
1013
|
? new Map([[descriptor.task.id, descriptor.forkContextSeed]])
|
|
896
1014
|
: undefined;
|
|
1015
|
+
const resumedTask = {
|
|
1016
|
+
...descriptor.task,
|
|
1017
|
+
repositoryBinding: descriptor.repositoryBinding,
|
|
1018
|
+
duplicate_policy: descriptor.duplicatePolicy,
|
|
1019
|
+
};
|
|
897
1020
|
return manager.register(
|
|
898
1021
|
"task",
|
|
899
1022
|
descriptor.task.id,
|
|
900
1023
|
async ({ signal: runSignal }) => {
|
|
901
1024
|
const result = await this.#executeSync(
|
|
902
1025
|
descriptor.toolCallId,
|
|
903
|
-
{ ...descriptor.params, tasks: [
|
|
1026
|
+
{ ...descriptor.params, tasks: [resumedTask] },
|
|
904
1027
|
runSignal,
|
|
905
1028
|
undefined,
|
|
906
1029
|
[descriptor.task.id],
|
|
@@ -921,7 +1044,22 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
921
1044
|
},
|
|
922
1045
|
);
|
|
923
1046
|
const finalText = result.content.find(part => part.type === "text")?.text ?? "(no output)";
|
|
924
|
-
const
|
|
1047
|
+
const rawSingleResult = result.details?.results[0];
|
|
1048
|
+
const singleResult = rawSingleResult
|
|
1049
|
+
? {
|
|
1050
|
+
...rawSingleResult,
|
|
1051
|
+
duplicateDisposition: (() => {
|
|
1052
|
+
const initial = descriptor.initialDisposition;
|
|
1053
|
+
const current = admission.disposition;
|
|
1054
|
+
if (!initial) return current;
|
|
1055
|
+
if (!current) return initial;
|
|
1056
|
+
return {
|
|
1057
|
+
action: current.action,
|
|
1058
|
+
predecessorIds: [...new Set([...initial.predecessorIds, ...current.predecessorIds])],
|
|
1059
|
+
};
|
|
1060
|
+
})(),
|
|
1061
|
+
}
|
|
1062
|
+
: rawSingleResult;
|
|
925
1063
|
return subagentRunOutcomeFromSingleResult(finalText, singleResult);
|
|
926
1064
|
},
|
|
927
1065
|
{
|
|
@@ -932,6 +1070,9 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
932
1070
|
id: descriptor.task.id,
|
|
933
1071
|
agent: descriptor.params.agent,
|
|
934
1072
|
agentSource: descriptor.agentSource,
|
|
1073
|
+
duplicateIdentity: duplicateIdentityKey(descriptor.duplicateIdentity),
|
|
1074
|
+
duplicateDisposition: (admission.disposition?.action ??
|
|
1075
|
+
descriptor.initialDisposition?.action) as DuplicateDisposition["action"] | undefined,
|
|
935
1076
|
description: descriptor.task.description,
|
|
936
1077
|
assignment: descriptor.task.assignment.trim(),
|
|
937
1078
|
},
|
|
@@ -968,7 +1109,12 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
968
1109
|
for (let i = 0; i < taskItems.length; i++) {
|
|
969
1110
|
const taskItem = taskItems[i];
|
|
970
1111
|
if (signal?.aborted) {
|
|
971
|
-
failedSchedules.push(
|
|
1112
|
+
failedSchedules.push({
|
|
1113
|
+
task: taskItem as TaskItem & { id: string },
|
|
1114
|
+
taskIndex: i,
|
|
1115
|
+
message: "cancelled before scheduling",
|
|
1116
|
+
signalSkip: true,
|
|
1117
|
+
});
|
|
972
1118
|
const progress = progressByTaskId.get(taskItem.id);
|
|
973
1119
|
if (progress) {
|
|
974
1120
|
progress.status = "aborted";
|
|
@@ -981,13 +1127,25 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
981
1127
|
if (signal?.aborted) {
|
|
982
1128
|
for (let skippedIndex = i; skippedIndex < taskItems.length; skippedIndex++) {
|
|
983
1129
|
const skippedTask = taskItems[skippedIndex]!;
|
|
984
|
-
failedSchedules.push(
|
|
1130
|
+
failedSchedules.push({
|
|
1131
|
+
task: skippedTask as TaskItem & { id: string },
|
|
1132
|
+
taskIndex: skippedIndex,
|
|
1133
|
+
message: "cancelled before scheduling",
|
|
1134
|
+
signalSkip: true,
|
|
1135
|
+
});
|
|
985
1136
|
const skippedProgress = progressByTaskId.get(skippedTask.id);
|
|
986
1137
|
if (skippedProgress) skippedProgress.status = "aborted";
|
|
987
1138
|
}
|
|
988
1139
|
break;
|
|
989
1140
|
}
|
|
990
|
-
if (frozenForkSeed)
|
|
1141
|
+
if (frozenForkSeed) {
|
|
1142
|
+
frozenForkSeeds.set(uniqueId, frozenForkSeed);
|
|
1143
|
+
// The async callback may execute through a compatibility path that retains
|
|
1144
|
+
// the caller's task id instead of the allocated artifact id. Preserve the
|
|
1145
|
+
// same immutable seed under both identities so detached execution never
|
|
1146
|
+
// rebuilds context after dispatch.
|
|
1147
|
+
frozenForkSeeds.set(taskItem.id, frozenForkSeed);
|
|
1148
|
+
}
|
|
991
1149
|
const singleParams: TaskParams = { ...params, tasks: [taskItem] };
|
|
992
1150
|
const label = uniqueId;
|
|
993
1151
|
try {
|
|
@@ -997,6 +1155,17 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
997
1155
|
const subtaskSessionFile = managedPersistence
|
|
998
1156
|
? null
|
|
999
1157
|
: path.join(batchArtifactsDir ?? externalTaskSessionsDir!, `${uniqueId}.jsonl`);
|
|
1158
|
+
const admission = admitDuplicateLaunch(uniqueId, taskItem, taskItem.duplicate_policy ?? "warn");
|
|
1159
|
+
if (!admission.ok) {
|
|
1160
|
+
failedSchedules.push({
|
|
1161
|
+
task: taskItem as TaskItem & { id: string },
|
|
1162
|
+
taskIndex: i,
|
|
1163
|
+
message: admission.error ?? "duplicate_supersede_failed",
|
|
1164
|
+
signalSkip: false,
|
|
1165
|
+
duplicateDisposition: admission.disposition,
|
|
1166
|
+
});
|
|
1167
|
+
continue;
|
|
1168
|
+
}
|
|
1000
1169
|
const jobId = manager.register(
|
|
1001
1170
|
"task",
|
|
1002
1171
|
label,
|
|
@@ -1036,7 +1205,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1036
1205
|
},
|
|
1037
1206
|
);
|
|
1038
1207
|
const finalText = result.content.find(part => part.type === "text")?.text ?? "(no output)";
|
|
1039
|
-
const
|
|
1208
|
+
const rawSingleResult = result.details?.results[0];
|
|
1209
|
+
const singleResult = rawSingleResult
|
|
1210
|
+
? {
|
|
1211
|
+
...rawSingleResult,
|
|
1212
|
+
duplicateDisposition: rawSingleResult.duplicateDisposition ?? admission.disposition,
|
|
1213
|
+
}
|
|
1214
|
+
: rawSingleResult;
|
|
1040
1215
|
if (progress) {
|
|
1041
1216
|
progress.status = singleResult?.paused
|
|
1042
1217
|
? "paused"
|
|
@@ -1119,6 +1294,8 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1119
1294
|
id: uniqueId,
|
|
1120
1295
|
agent: params.agent,
|
|
1121
1296
|
agentSource: fallbackAgentSource,
|
|
1297
|
+
duplicateIdentity: duplicateIdentityKey(admission.identity),
|
|
1298
|
+
duplicateDisposition: admission.disposition?.action,
|
|
1122
1299
|
description: taskItem.description,
|
|
1123
1300
|
assignment: taskItem.assignment.trim(),
|
|
1124
1301
|
},
|
|
@@ -1145,6 +1322,10 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1145
1322
|
durableOutputAllowed: Boolean(batchArtifactsDir),
|
|
1146
1323
|
forkContextSeed: frozenForkSeed,
|
|
1147
1324
|
agentSource: fallbackAgentSource,
|
|
1325
|
+
repositoryBinding: taskItem.repositoryBinding as RepositoryBinding,
|
|
1326
|
+
duplicateIdentity: admission.identity,
|
|
1327
|
+
duplicatePolicy: taskItem.duplicate_policy ?? "warn",
|
|
1328
|
+
initialDisposition: admission.disposition,
|
|
1148
1329
|
} satisfies TaskResumeDescriptor,
|
|
1149
1330
|
},
|
|
1150
1331
|
resumeRunner,
|
|
@@ -1155,10 +1336,13 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1155
1336
|
subagentId: uniqueId,
|
|
1156
1337
|
ownerId: this.session.getAgentId?.() ?? undefined,
|
|
1157
1338
|
currentJobId: jobId,
|
|
1339
|
+
currentJobGeneration: manager.getJob(jobId)?.generation,
|
|
1158
1340
|
historicalJobIds: [],
|
|
1159
1341
|
status: manager.getJob(jobId)?.status ?? "running",
|
|
1160
1342
|
sessionFile: null,
|
|
1161
1343
|
resumable: true,
|
|
1344
|
+
duplicateIdentity: duplicateIdentityKey(admission.identity),
|
|
1345
|
+
duplicateDisposition: admission.disposition?.action,
|
|
1162
1346
|
});
|
|
1163
1347
|
}
|
|
1164
1348
|
} catch (error) {
|
|
@@ -1168,7 +1352,12 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1168
1352
|
: error instanceof Error
|
|
1169
1353
|
? error.message
|
|
1170
1354
|
: String(error);
|
|
1171
|
-
failedSchedules.push(
|
|
1355
|
+
failedSchedules.push({
|
|
1356
|
+
task: taskItem as TaskItem & { id: string },
|
|
1357
|
+
taskIndex: i,
|
|
1358
|
+
message,
|
|
1359
|
+
signalSkip: false,
|
|
1360
|
+
});
|
|
1172
1361
|
const progress = progressByTaskId.get(taskItem.id);
|
|
1173
1362
|
if (progress) {
|
|
1174
1363
|
progress.status = "failed";
|
|
@@ -1181,11 +1370,36 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1181
1370
|
failedJobs += failedSchedules.length;
|
|
1182
1371
|
}
|
|
1183
1372
|
|
|
1373
|
+
const scheduleFailureReceipts = failedSchedules
|
|
1374
|
+
.slice()
|
|
1375
|
+
.sort((a, b) => a.taskIndex - b.taskIndex)
|
|
1376
|
+
.map((entry, index) =>
|
|
1377
|
+
buildTaskReceipt({
|
|
1378
|
+
index,
|
|
1379
|
+
id: entry.task.id,
|
|
1380
|
+
agent: params.agent,
|
|
1381
|
+
agentSource: fallbackAgentSource,
|
|
1382
|
+
task: renderTaskAssignment(entry.task.assignment, simpleMode),
|
|
1383
|
+
assignment: entry.task.assignment,
|
|
1384
|
+
description: entry.task.description,
|
|
1385
|
+
status: "failed",
|
|
1386
|
+
exitCode: 1,
|
|
1387
|
+
aborted: entry.signalSkip ? true : undefined,
|
|
1388
|
+
abortReason: entry.signalSkip ? "Cancelled before start" : undefined,
|
|
1389
|
+
truncated: false,
|
|
1390
|
+
durationMs: 0,
|
|
1391
|
+
tokens: 0,
|
|
1392
|
+
output: "",
|
|
1393
|
+
stderr: entry.message,
|
|
1394
|
+
error: entry.message,
|
|
1395
|
+
duplicateDisposition: entry.duplicateDisposition,
|
|
1396
|
+
} as SingleResult),
|
|
1397
|
+
);
|
|
1184
1398
|
if (startedJobs.length === 0) {
|
|
1185
|
-
const failureText = `Failed to start background task jobs: ${failedSchedules.join("; ")}`;
|
|
1399
|
+
const failureText = `Failed to start background task jobs: ${failedSchedules.map(entry => `${entry.task.id}: ${entry.message}`).join("; ")}`;
|
|
1186
1400
|
return {
|
|
1187
1401
|
content: [{ type: "text", text: failureText }],
|
|
1188
|
-
details: { projectAgentsDir: null, results:
|
|
1402
|
+
details: { projectAgentsDir: null, results: scheduleFailureReceipts, totalDurationMs: 0 },
|
|
1189
1403
|
};
|
|
1190
1404
|
}
|
|
1191
1405
|
|
|
@@ -1233,7 +1447,7 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1233
1447
|
],
|
|
1234
1448
|
details: {
|
|
1235
1449
|
projectAgentsDir: null,
|
|
1236
|
-
results:
|
|
1450
|
+
results: scheduleFailureReceipts,
|
|
1237
1451
|
totalDurationMs: 0,
|
|
1238
1452
|
progress: getProgressSnapshot(),
|
|
1239
1453
|
async: { state: asyncState, jobId: startedJobs[0].jobId, type: "task" },
|
|
@@ -1705,27 +1919,6 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1705
1919
|
if (taskRepositoryBinding.relativeSubdir) {
|
|
1706
1920
|
assertPathUnderRepositoryBinding(taskRepositoryBinding, ".");
|
|
1707
1921
|
}
|
|
1708
|
-
if (task.reviewSource) {
|
|
1709
|
-
await validateUltragoalReviewDispatch({
|
|
1710
|
-
cwd: this.session.cwd,
|
|
1711
|
-
dispatchId: task.reviewSource.dispatchId,
|
|
1712
|
-
cohortId: task.reviewSource.cohortId,
|
|
1713
|
-
taskId: task.id,
|
|
1714
|
-
lane: task.reviewSource.lane,
|
|
1715
|
-
snapshotId: task.reviewSource.snapshotId,
|
|
1716
|
-
generation: task.reviewSource.generation,
|
|
1717
|
-
repositoryBindingDigest: task.reviewSource.repositoryBindingDigest,
|
|
1718
|
-
stateRevision: task.reviewSource.stateRevision,
|
|
1719
|
-
rerunCommand: task.reviewSource.rerunCommand,
|
|
1720
|
-
taskSourceTaskId: task.reviewSource.taskId,
|
|
1721
|
-
createdAt: task.reviewSource.createdAt,
|
|
1722
|
-
});
|
|
1723
|
-
}
|
|
1724
|
-
if (isIsolated && task.reviewSource) {
|
|
1725
|
-
throw new Error(
|
|
1726
|
-
"source-aware review tasks cannot use generic task isolation; dispatch them against the coordinator-owned source snapshot",
|
|
1727
|
-
);
|
|
1728
|
-
}
|
|
1729
1922
|
if (!isIsolated) {
|
|
1730
1923
|
await assertExecutionRootMatchesRepositoryBinding(this.session.cwd, taskRepositoryBinding);
|
|
1731
1924
|
const result = await runSubprocess({
|
|
@@ -1780,32 +1973,11 @@ export class TaskTool implements AgentTool<TaskToolSchemaInstance, TaskToolDetai
|
|
|
1780
1973
|
parentTelemetry: this.session.getTelemetry?.(),
|
|
1781
1974
|
forkContextSeed,
|
|
1782
1975
|
});
|
|
1783
|
-
const reviewSourceDisposition = task.reviewSource
|
|
1784
|
-
? await reconcileReviewSourceDelivery({
|
|
1785
|
-
cwd: this.session.cwd,
|
|
1786
|
-
repositoryBinding: taskRepositoryBinding,
|
|
1787
|
-
reviewSource: task.reviewSource,
|
|
1788
|
-
})
|
|
1789
|
-
: undefined;
|
|
1790
|
-
const reviewSource =
|
|
1791
|
-
task.reviewSource && reviewSourceDisposition
|
|
1792
|
-
? {
|
|
1793
|
-
...task.reviewSource,
|
|
1794
|
-
...reviewSourceDisposition,
|
|
1795
|
-
...(await classifyUltragoalReviewDelivery({
|
|
1796
|
-
cwd: this.session.cwd,
|
|
1797
|
-
cohortId: task.reviewSource.cohortId,
|
|
1798
|
-
dispatchId: task.reviewSource.dispatchId,
|
|
1799
|
-
observedDisposition: reviewSourceDisposition.disposition,
|
|
1800
|
-
})),
|
|
1801
|
-
}
|
|
1802
|
-
: undefined;
|
|
1803
1976
|
return {
|
|
1804
1977
|
...result,
|
|
1805
1978
|
...(forkContext ? { forkContext } : {}),
|
|
1806
1979
|
forkContextAdvisory,
|
|
1807
1980
|
repositoryBinding: publicRepositoryBinding(taskRepositoryBinding),
|
|
1808
|
-
...(reviewSource ? { reviewSource } : {}),
|
|
1809
1981
|
};
|
|
1810
1982
|
}
|
|
1811
1983
|
|
package/src/task/receipt.ts
CHANGED
|
@@ -43,6 +43,7 @@ export interface TaskResultReceipt {
|
|
|
43
43
|
retryFailure?: { attempt: number; errorSummary: string };
|
|
44
44
|
setupFailure?: { summary: string };
|
|
45
45
|
errorSummary?: string;
|
|
46
|
+
duplicateDisposition?: SingleResult["duplicateDisposition"];
|
|
46
47
|
abortSummary?: string;
|
|
47
48
|
preview: string;
|
|
48
49
|
previewTruncated: boolean;
|
|
@@ -67,9 +68,6 @@ export interface TaskResultReceipt {
|
|
|
67
68
|
forkContextAdvisory?: SingleResult["forkContextAdvisory"];
|
|
68
69
|
/** Resolved repository identity for this delegated lane (#2901). */
|
|
69
70
|
repositoryBinding?: SingleResult["repositoryBinding"];
|
|
70
|
-
/** Runtime-derived review source disposition and rerun guidance (#3469). */
|
|
71
|
-
reviewSource?: SingleResult["reviewSource"];
|
|
72
|
-
|
|
73
71
|
roi?: TaskRoi;
|
|
74
72
|
}
|
|
75
73
|
|
|
@@ -296,6 +294,7 @@ export function buildTaskReceipt(raw: SingleResult): TaskResultReceipt {
|
|
|
296
294
|
retryFailure: raw.retryFailure
|
|
297
295
|
? { attempt: raw.retryFailure.attempt, errorSummary: "Retry failure recorded." }
|
|
298
296
|
: undefined,
|
|
297
|
+
duplicateDisposition: raw.duplicateDisposition,
|
|
299
298
|
errorSummary:
|
|
300
299
|
raw.setupFailure?.summary ??
|
|
301
300
|
(raw.error
|
|
@@ -314,7 +313,6 @@ export function buildTaskReceipt(raw: SingleResult): TaskResultReceipt {
|
|
|
314
313
|
forkContext: raw.forkContext,
|
|
315
314
|
forkContextAdvisory: raw.forkContextAdvisory,
|
|
316
315
|
repositoryBinding: raw.repositoryBinding,
|
|
317
|
-
reviewSource: raw.reviewSource,
|
|
318
316
|
roi: buildTaskRoi(raw),
|
|
319
317
|
};
|
|
320
318
|
}
|
package/src/task/render.ts
CHANGED
|
@@ -916,36 +916,6 @@ function renderAgentResult(result: TaskResultReceipt, isLast: boolean, expanded:
|
|
|
916
916
|
if (result.roi?.lowRoi) {
|
|
917
917
|
lines.push(`${continuePrefix}${theme.fg("warning", "low ROI: produced no material contribution")}`);
|
|
918
918
|
}
|
|
919
|
-
if (result.reviewSource?.disposition === "stale_review_delivery") {
|
|
920
|
-
lines.push(
|
|
921
|
-
`${continuePrefix}${theme.fg(
|
|
922
|
-
"warning",
|
|
923
|
-
truncateToWidth(
|
|
924
|
-
replaceTabs(
|
|
925
|
-
sanitizeText(
|
|
926
|
-
`STALE REVIEW: source advanced after dispatch; excluded from review gates. Rerun: ${result.reviewSource.rerunCommand}`,
|
|
927
|
-
),
|
|
928
|
-
),
|
|
929
|
-
|
|
930
|
-
100,
|
|
931
|
-
),
|
|
932
|
-
)}`,
|
|
933
|
-
);
|
|
934
|
-
} else if (result.reviewSource?.disposition === "invalid_provenance") {
|
|
935
|
-
lines.push(
|
|
936
|
-
`${continuePrefix}${theme.fg(
|
|
937
|
-
"error",
|
|
938
|
-
truncateToWidth(
|
|
939
|
-
replaceTabs(
|
|
940
|
-
sanitizeText(
|
|
941
|
-
`INVALID REVIEW PROVENANCE: receipt cannot satisfy review gates. Rerun: ${result.reviewSource.rerunCommand}`,
|
|
942
|
-
),
|
|
943
|
-
),
|
|
944
|
-
100,
|
|
945
|
-
),
|
|
946
|
-
)}`,
|
|
947
|
-
);
|
|
948
|
-
}
|
|
949
919
|
|
|
950
920
|
if (result.persistence?.recoveryRef) {
|
|
951
921
|
const label = result.persistence.ownerWorktreeApplied ? "Recovery patch" : "Unapplied recovery patch";
|
package/src/task/types.ts
CHANGED
|
@@ -2,7 +2,6 @@ import type { ThinkingLevel } from "@gajae-code/agent-core";
|
|
|
2
2
|
import type { Usage } from "@gajae-code/ai";
|
|
3
3
|
import { $env } from "@gajae-code/utils";
|
|
4
4
|
import * as z from "zod/v4";
|
|
5
|
-
import type { ReviewDeliveryDisposition, ReviewSourceLane } from "../gjc-runtime/ultragoal-review-source";
|
|
6
5
|
import { isValidTaskId, TASK_ID_DESCRIPTION } from "./id";
|
|
7
6
|
import type { TaskResultReceipt } from "./receipt";
|
|
8
7
|
import type { SpawnRoiReconciliation } from "./roi-reconciliation";
|
|
@@ -115,26 +114,9 @@ const createTaskItemSchema = (_contextEnabled: boolean) =>
|
|
|
115
114
|
.describe(
|
|
116
115
|
"authoritative repository identity; omitted items are stamped from session cwd before discovery/spawn and still fail closed on sibling drift",
|
|
117
116
|
),
|
|
118
|
-
|
|
117
|
+
duplicate_policy: z.enum(["warn", "supersede"]).optional().describe("duplicate launch policy; defaults to warn"),
|
|
119
118
|
});
|
|
120
119
|
|
|
121
|
-
const reviewSourceSchema = z
|
|
122
|
-
.object({
|
|
123
|
-
schema: z.literal("gjc.review_source_dispatch.v1"),
|
|
124
|
-
cohortId: z.string().min(1),
|
|
125
|
-
generation: z.number().int().min(1),
|
|
126
|
-
lane: z.enum(["cleaner", "architect", "qa", "critic"]),
|
|
127
|
-
snapshotId: z.string().startsWith("sha256:"),
|
|
128
|
-
repositoryBindingDigest: z.string().startsWith("sha256:"),
|
|
129
|
-
stateRevision: z.number().int().min(0),
|
|
130
|
-
dispatchId: z.string().min(1),
|
|
131
|
-
rerunCommand: z.string().min(1),
|
|
132
|
-
taskId: z.string().min(1),
|
|
133
|
-
createdAt: z.string().min(1),
|
|
134
|
-
})
|
|
135
|
-
.strict()
|
|
136
|
-
.describe("leader-issued immutable review source identity; review lanes only");
|
|
137
|
-
|
|
138
120
|
/** Single task item for parallel execution (default shape with context enabled). */
|
|
139
121
|
export const taskItemSchema = createTaskItemSchema(true);
|
|
140
122
|
export type TaskItem = z.infer<typeof taskItemSchema>;
|
|
@@ -218,6 +200,7 @@ export interface TaskParams {
|
|
|
218
200
|
spawnPlan?: SpawnPlanReceipt;
|
|
219
201
|
tasks: TaskItem[];
|
|
220
202
|
isolated?: boolean;
|
|
203
|
+
duplicate_policy?: "warn" | "supersede";
|
|
221
204
|
}
|
|
222
205
|
|
|
223
206
|
/** A code review finding reported by the reviewer agent */
|
|
@@ -452,6 +435,12 @@ export interface TaskRecoveryArtifactRef {
|
|
|
452
435
|
durability: "session";
|
|
453
436
|
}
|
|
454
437
|
|
|
438
|
+
/** Bounded duplicate-launch disposition carried into task receipts. */
|
|
439
|
+
export interface DuplicateDisposition {
|
|
440
|
+
action: "warned" | "superseded";
|
|
441
|
+
predecessorIds: string[];
|
|
442
|
+
}
|
|
443
|
+
|
|
455
444
|
export interface TaskPersistenceResult {
|
|
456
445
|
outcome: "applied" | "no_changes" | "recovery_available";
|
|
457
446
|
ownerWorktreeApplied: boolean;
|
|
@@ -488,6 +477,8 @@ export interface SingleResult {
|
|
|
488
477
|
setupFailure?: SetupFailureSummary;
|
|
489
478
|
aborted?: boolean;
|
|
490
479
|
abortReason?: string;
|
|
480
|
+
|
|
481
|
+
duplicateDisposition?: DuplicateDisposition;
|
|
491
482
|
paused?: boolean;
|
|
492
483
|
/** Aggregated usage from the subprocess, accumulated incrementally from message_end events. */
|
|
493
484
|
usage?: Usage;
|
|
@@ -543,21 +534,6 @@ export interface SingleResult {
|
|
|
543
534
|
head?: string;
|
|
544
535
|
branch?: string;
|
|
545
536
|
};
|
|
546
|
-
/** Leader-issued immutable source identity for source-aware review lanes (#3469). */
|
|
547
|
-
reviewSource?: {
|
|
548
|
-
schema: "gjc.review_source_dispatch.v1";
|
|
549
|
-
cohortId: string;
|
|
550
|
-
generation: number;
|
|
551
|
-
lane: ReviewSourceLane;
|
|
552
|
-
snapshotId: string;
|
|
553
|
-
repositoryBindingDigest: string;
|
|
554
|
-
stateRevision: number;
|
|
555
|
-
dispatchId: string;
|
|
556
|
-
rerunCommand: string;
|
|
557
|
-
disposition: ReviewDeliveryDisposition;
|
|
558
|
-
currentSnapshotId?: string;
|
|
559
|
-
deliveryId?: string;
|
|
560
|
-
};
|
|
561
537
|
}
|
|
562
538
|
|
|
563
539
|
/** True only for complete, factual five-bucket cost accounting. */
|
package/src/tools/ask.ts
CHANGED
|
@@ -1613,7 +1613,7 @@ export class AskTool implements AgentTool<AskParametersSchema, AskToolDetails> {
|
|
|
1613
1613
|
signal,
|
|
1614
1614
|
initialSelection,
|
|
1615
1615
|
navigation: options?.navigation,
|
|
1616
|
-
scrollTitleRows:
|
|
1616
|
+
scrollTitleRows: DEEP_INTERVIEW_SELECTOR_SCROLL_TITLE_ROWS,
|
|
1617
1617
|
otherOptionLabel,
|
|
1618
1618
|
autoSelectOnTimeout: !intentContract(q.deepInterview) && !intentReview(q.deepInterview),
|
|
1619
1619
|
clarificationOptionLabel,
|