@gajae-code/coding-agent 0.12.10 → 0.12.11
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 +9 -2
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +3 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +3 -2
- package/dist/types/session/internal/managed-session-storage.d.ts +12 -2
- package/dist/types/session/session-manager.d.ts +17 -0
- package/dist/types/session/session-storage.d.ts +1 -0
- package/dist/types/tools/computer.d.ts +35 -2
- package/dist/types/tools/todo-write.d.ts +2 -0
- package/package.json +8 -8
- package/src/internal-urls/docs-index.generated.ts +2 -2
- package/src/prompts/tools/computer.md +6 -1
- package/src/sdk/bus/chat-daemon-control.ts +5 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +3 -2
- package/src/session/agent-session.ts +111 -21
- package/src/session/internal/managed-session-storage.ts +244 -246
- package/src/session/session-manager.ts +140 -6
- package/src/session/session-storage.ts +3 -0
- package/src/tools/computer.ts +322 -45
- package/src/tools/todo-write.ts +29 -11
|
@@ -56,9 +56,10 @@ export const NOTIFICATION_PROTOCOL_VERSION = 3;
|
|
|
56
56
|
* adds durable provider-intent admission without changing owner, reclaim,
|
|
57
57
|
* signal, or spawn authority.
|
|
58
58
|
* Generation 42 applies first-class provider-settings admission to Telegram
|
|
59
|
-
* lifecycle controls.
|
|
59
|
+
* lifecycle controls. Generation 43 applies identity-bound exact replacement
|
|
60
|
+
* cleanup shared by managed-session and daemon filesystem authority.
|
|
60
61
|
*/
|
|
61
|
-
export const DAEMON_GENERATION =
|
|
62
|
+
export const DAEMON_GENERATION = 43;
|
|
62
63
|
|
|
63
64
|
/**
|
|
64
65
|
* Serving-compatibility boundary for daemon lifecycle requests. Epoch 1 covers
|
|
@@ -427,6 +427,7 @@ import {
|
|
|
427
427
|
getLatestCompactionEntry,
|
|
428
428
|
getSessionMessageEntryId,
|
|
429
429
|
getSessionMessageObservationId,
|
|
430
|
+
SessionAppendPersistenceError,
|
|
430
431
|
transferSessionMessageIdentity,
|
|
431
432
|
} from "./session-manager";
|
|
432
433
|
import { getEntriesForInternalRead, getSessionContextForInternalRead } from "./session-manager-internal";
|
|
@@ -3899,14 +3900,19 @@ export class AgentSession {
|
|
|
3899
3900
|
) {
|
|
3900
3901
|
const isRosterReminder = event.message.role === "custom" && event.message.customType === "irc-peer-roster";
|
|
3901
3902
|
if (!isRosterReminder) {
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3903
|
+
try {
|
|
3904
|
+
this.#appendCustomMessageEntry(
|
|
3905
|
+
event.message.customType,
|
|
3906
|
+
event.message.content,
|
|
3907
|
+
event.message.display,
|
|
3908
|
+
event.message.details,
|
|
3909
|
+
event.message.attribution ?? "agent",
|
|
3910
|
+
getSessionMessageObservationId(event.message),
|
|
3911
|
+
);
|
|
3912
|
+
} catch (error) {
|
|
3913
|
+
this.agent.abort();
|
|
3914
|
+
throw error;
|
|
3915
|
+
}
|
|
3910
3916
|
}
|
|
3911
3917
|
} else if (
|
|
3912
3918
|
event.message.role === "user" ||
|
|
@@ -3915,7 +3921,73 @@ export class AgentSession {
|
|
|
3915
3921
|
event.message.role === "toolResult" ||
|
|
3916
3922
|
event.message.role === "fileMention"
|
|
3917
3923
|
) {
|
|
3918
|
-
|
|
3924
|
+
try {
|
|
3925
|
+
this.sessionManager.appendMessage(event.message);
|
|
3926
|
+
} catch (error) {
|
|
3927
|
+
if (
|
|
3928
|
+
event.message.role !== "toolResult" ||
|
|
3929
|
+
event.message.toolName !== "todo_write" ||
|
|
3930
|
+
!(error instanceof SessionAppendPersistenceError) ||
|
|
3931
|
+
error.phase !== "current_append"
|
|
3932
|
+
) {
|
|
3933
|
+
this.agent.abort();
|
|
3934
|
+
throw error;
|
|
3935
|
+
}
|
|
3936
|
+
this.agent.abort();
|
|
3937
|
+
|
|
3938
|
+
const failure = error.persistenceError.message;
|
|
3939
|
+
const failedEntryId = error.entryId;
|
|
3940
|
+
this.#syncTodoPhasesFromBranch();
|
|
3941
|
+
event.message.isError = true;
|
|
3942
|
+
event.message.content = [
|
|
3943
|
+
{
|
|
3944
|
+
type: "text",
|
|
3945
|
+
text: `Todo state persistence failed: ${failure}\nDo not change the payload solely because of this failure. The durable outcome is unknown; reconcile the session state before retrying or continuing.`,
|
|
3946
|
+
},
|
|
3947
|
+
];
|
|
3948
|
+
event.message.details = {
|
|
3949
|
+
...(event.message.details && typeof event.message.details === "object" ? event.message.details : {}),
|
|
3950
|
+
phases: this.getTodoPhases(),
|
|
3951
|
+
failureKind: "persistence",
|
|
3952
|
+
};
|
|
3953
|
+
this.agent.touchContext();
|
|
3954
|
+
let recovered = false;
|
|
3955
|
+
try {
|
|
3956
|
+
await this.sessionManager.recoverPersistenceFailure();
|
|
3957
|
+
recovered = true;
|
|
3958
|
+
} catch (recoveryError) {
|
|
3959
|
+
logger.warn("Todo persistence recovery failed", {
|
|
3960
|
+
error: recoveryError instanceof Error ? recoveryError.message : String(recoveryError),
|
|
3961
|
+
});
|
|
3962
|
+
}
|
|
3963
|
+
if (recovered) {
|
|
3964
|
+
const durableTodoResult = this.sessionManager
|
|
3965
|
+
.getBranch()
|
|
3966
|
+
.find(
|
|
3967
|
+
entry =>
|
|
3968
|
+
entry.id === failedEntryId &&
|
|
3969
|
+
entry.type === "message" &&
|
|
3970
|
+
entry.message.role === "toolResult" &&
|
|
3971
|
+
entry.message.toolName === "todo_write",
|
|
3972
|
+
);
|
|
3973
|
+
this.#syncTodoPhasesFromBranch();
|
|
3974
|
+
if (durableTodoResult?.type === "message" && durableTodoResult.message.role === "toolResult") {
|
|
3975
|
+
event.message.content = durableTodoResult.message.content;
|
|
3976
|
+
event.message.details = durableTodoResult.message.details;
|
|
3977
|
+
event.message.isError = durableTodoResult.message.isError;
|
|
3978
|
+
} else {
|
|
3979
|
+
event.message.details = {
|
|
3980
|
+
...(event.message.details && typeof event.message.details === "object"
|
|
3981
|
+
? event.message.details
|
|
3982
|
+
: {}),
|
|
3983
|
+
phases: this.getTodoPhases(),
|
|
3984
|
+
failureKind: "persistence",
|
|
3985
|
+
};
|
|
3986
|
+
this.sessionManager.appendMessage(event.message);
|
|
3987
|
+
this.agent.touchContext();
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
}
|
|
3919
3991
|
}
|
|
3920
3992
|
}
|
|
3921
3993
|
|
|
@@ -4189,7 +4261,13 @@ export class AgentSession {
|
|
|
4189
4261
|
if (event.message.role === "toolResult") {
|
|
4190
4262
|
const { toolName, details, isError, content } = event.message as {
|
|
4191
4263
|
toolName?: string;
|
|
4192
|
-
details?: {
|
|
4264
|
+
details?: {
|
|
4265
|
+
path?: string;
|
|
4266
|
+
phases?: TodoPhase[];
|
|
4267
|
+
report?: string;
|
|
4268
|
+
startedAt?: string;
|
|
4269
|
+
failureKind?: "payload_rejected" | "argument_validation" | "execution" | "persistence";
|
|
4270
|
+
};
|
|
4193
4271
|
isError?: boolean;
|
|
4194
4272
|
content?: Array<TextContent | ImageContent>;
|
|
4195
4273
|
};
|
|
@@ -4202,22 +4280,34 @@ export class AgentSession {
|
|
|
4202
4280
|
}
|
|
4203
4281
|
if (toolName === "todo_write" && isError) {
|
|
4204
4282
|
const errorText = content?.find(part => part.type === "text")?.text;
|
|
4283
|
+
const payloadRejected =
|
|
4284
|
+
details?.failureKind === "payload_rejected" || details?.failureKind === "argument_validation";
|
|
4205
4285
|
const reminderText = [
|
|
4206
4286
|
"<system-reminder>",
|
|
4207
|
-
|
|
4287
|
+
payloadRejected
|
|
4288
|
+
? "todo_write rejected its payload. The requested todo update was not applied."
|
|
4289
|
+
: "todo_write did not complete because the turn aborted during runtime execution or persistence.",
|
|
4208
4290
|
errorText ? `Failure: ${errorText}` : "Failure: todo_write returned an error.",
|
|
4209
|
-
|
|
4291
|
+
payloadRejected
|
|
4292
|
+
? "Correct the payload and call todo_write again before continuing."
|
|
4293
|
+
: "Do not change the payload solely because of this failure. The durable outcome is unknown; reconcile the session state before retrying or continuing.",
|
|
4210
4294
|
"</system-reminder>",
|
|
4211
4295
|
].join("\n");
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4296
|
+
try {
|
|
4297
|
+
await this.sendCustomMessage(
|
|
4298
|
+
{
|
|
4299
|
+
customType: "todo-write-error-reminder",
|
|
4300
|
+
content: reminderText,
|
|
4301
|
+
display: false,
|
|
4302
|
+
details: { toolName, errorText },
|
|
4303
|
+
},
|
|
4304
|
+
{ deliverAs: "nextTurn" },
|
|
4305
|
+
);
|
|
4306
|
+
} catch (error) {
|
|
4307
|
+
logger.warn("Todo write error reminder persistence failed", {
|
|
4308
|
+
error: error instanceof Error ? error.message : String(error),
|
|
4309
|
+
});
|
|
4310
|
+
}
|
|
4221
4311
|
}
|
|
4222
4312
|
if (toolName === "checkpoint" && !isError) {
|
|
4223
4313
|
const checkpointEntryId = this.sessionManager.getLeafId();
|