@gajae-code/coding-agent 0.11.4 → 0.11.6
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 +23 -0
- package/dist/types/cli/notify-cli.d.ts +5 -1
- package/dist/types/config/settings-schema.d.ts +31 -1
- package/dist/types/export/html/template.generated.d.ts +1 -1
- package/dist/types/gjc-runtime/deep-interview-state.d.ts +28 -0
- package/dist/types/gjc-runtime/launch-tmux.d.ts +3 -0
- package/dist/types/gjc-runtime/managed-owner-admission.d.ts +42 -0
- package/dist/types/gjc-runtime/managed-owner-supervisor.d.ts +41 -0
- package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +9 -0
- package/dist/types/gjc-runtime/ultragoal-owner-loss-recovery.d.ts +94 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +1 -0
- package/dist/types/harness-control-plane/owner.d.ts +3 -1
- package/dist/types/internal-urls/local-protocol.d.ts +18 -0
- package/dist/types/main.d.ts +2 -2
- package/dist/types/modes/components/ansi-display-validator.d.ts +2 -0
- package/dist/types/modes/components/notifications-settings-editor.d.ts +4 -0
- package/dist/types/modes/components/session-observer-overlay.d.ts +3 -1
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/modes/components/tool-transcript-format.d.ts +58 -0
- package/dist/types/modes/components/transcript-viewer-overlay.d.ts +3 -0
- package/dist/types/modes/controllers/goal-mode-controller.d.ts +8 -1
- package/dist/types/modes/controllers/selector-controller.d.ts +15 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-broker.d.ts +3 -0
- package/dist/types/modes/shared/agent-wire/workflow-gate-types.d.ts +16 -0
- package/dist/types/plan-mode/approved-plan.d.ts +1 -0
- package/dist/types/runtime-mcp/manager.d.ts +2 -0
- package/dist/types/runtime-mcp/oauth-discovery.d.ts +12 -1
- package/dist/types/sdk/bus/chat-daemon-cli.d.ts +3 -1
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +42 -4
- package/dist/types/sdk/bus/config-commands.d.ts +8 -0
- package/dist/types/sdk/bus/config.d.ts +22 -0
- package/dist/types/sdk/bus/index.d.ts +162 -2
- package/dist/types/sdk/bus/notification-service.d.ts +71 -8
- package/dist/types/sdk/bus/session-control.d.ts +11 -8
- package/dist/types/sdk/bus/telegram-daemon-cli.d.ts +5 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +11 -3
- package/dist/types/sdk/bus/telegram-daemon-control.d.ts +23 -4
- package/dist/types/sdk/bus/telegram-daemon.d.ts +214 -20
- package/dist/types/sdk/session.d.ts +16 -1
- package/dist/types/secrets/index.d.ts +4 -2
- package/dist/types/secrets/obfuscator.d.ts +1 -1
- package/dist/types/session/agent-session.d.ts +31 -2
- package/dist/types/session/artifacts.d.ts +30 -8
- package/dist/types/session/internal/managed-session-scope.d.ts +7 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +63 -6
- package/dist/types/session/session-manager.d.ts +98 -18
- package/dist/types/session/session-storage.d.ts +27 -0
- package/dist/types/session/streaming-output.d.ts +4 -0
- package/dist/types/session/yield-queue.d.ts +8 -0
- package/dist/types/task/executor.d.ts +9 -0
- package/dist/types/tool-discovery/tool-index.d.ts +2 -0
- package/dist/types/tools/ask.d.ts +48 -0
- package/dist/types/tools/bash-skill-urls.d.ts +2 -2
- package/dist/types/tools/index.d.ts +4 -0
- package/package.json +9 -9
- package/scripts/generate-sdk-operation-inventory.ts +3 -0
- package/src/cli/notify-cli.ts +40 -18
- package/src/commands/sdk.ts +7 -2
- package/src/config/settings-schema.ts +31 -1
- package/src/daemon/runtime.ts +2 -2
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +70 -49
- package/src/defaults/gjc/skills/ralplan/SKILL.md +0 -6
- package/src/defaults/gjc/skills/team/SKILL.md +7 -9
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +0 -2
- package/src/eval/py/index.ts +2 -2
- package/src/export/html/template.generated.ts +1 -1
- package/src/extensibility/plugins/marketplace/manager.ts +94 -10
- package/src/gjc-runtime/deep-interview-recorder.ts +7 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +10 -0
- package/src/gjc-runtime/deep-interview-state.ts +127 -3
- package/src/gjc-runtime/launch-tmux.ts +61 -6
- package/src/gjc-runtime/managed-owner-admission.ts +352 -0
- package/src/gjc-runtime/managed-owner-supervisor.ts +162 -0
- package/src/gjc-runtime/state-runtime.ts +38 -12
- package/src/gjc-runtime/team-runtime.ts +1 -1
- package/src/gjc-runtime/tmux-owner-isolation.ts +117 -0
- package/src/gjc-runtime/ultragoal-owner-loss-recovery.ts +328 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +14 -0
- package/src/harness-control-plane/owner.ts +59 -3
- package/src/hindsight/client.ts +65 -2
- package/src/internal-urls/agent-protocol.ts +76 -5
- package/src/internal-urls/docs-index.generated.ts +8 -7
- package/src/internal-urls/local-protocol.ts +416 -18
- package/src/lsp/index.ts +4 -88
- package/src/main.ts +36 -12
- package/src/modes/acp/acp-agent.ts +8 -0
- package/src/modes/components/ansi-display-validator.ts +54 -0
- package/src/modes/components/notifications-settings-editor.ts +26 -2
- package/src/modes/components/session-observer-overlay.ts +40 -24
- package/src/modes/components/settings-selector.ts +3 -1
- package/src/modes/components/tool-transcript-format.ts +321 -0
- package/src/modes/components/transcript-viewer-overlay.ts +39 -17
- package/src/modes/controllers/command-controller.ts +15 -0
- package/src/modes/controllers/extension-ui-controller.ts +14 -2
- package/src/modes/controllers/goal-mode-controller.ts +20 -1
- package/src/modes/controllers/plan-mode-controller.ts +2 -0
- package/src/modes/controllers/runtime-mcp-command-controller.ts +3 -0
- package/src/modes/controllers/selector-controller.ts +70 -8
- package/src/modes/interactive-mode.ts +1 -0
- package/src/modes/runtime-init.ts +16 -2
- package/src/modes/shared/agent-wire/deep-interview-gate.ts +31 -1
- package/src/modes/shared/agent-wire/workflow-gate-broker.ts +17 -1
- package/src/modes/shared/agent-wire/workflow-gate-schema.ts +4 -2
- package/src/modes/shared/agent-wire/workflow-gate-types.ts +120 -3
- package/src/plan-mode/approved-plan.ts +3 -1
- package/src/prompts/agents/architect.md +1 -0
- package/src/prompts/agents/critic.md +1 -0
- package/src/prompts/system/custom-system-prompt.md +1 -1
- package/src/prompts/system/system-prompt.md +2 -1
- package/src/prompts/tools/lsp.md +3 -3
- package/src/runtime-mcp/manager.ts +16 -1
- package/src/runtime-mcp/oauth-discovery.ts +116 -26
- package/src/sdk/broker/session-index.ts +122 -64
- package/src/sdk/bus/chat-daemon-cli.ts +72 -10
- package/src/sdk/bus/chat-daemon-control.ts +538 -130
- package/src/sdk/bus/chat-daemon-runtime.ts +1 -0
- package/src/sdk/bus/config-commands.ts +22 -0
- package/src/sdk/bus/config.ts +37 -0
- package/src/sdk/bus/index.ts +388 -94
- package/src/sdk/bus/lifecycle-control-runtime.ts +53 -3
- package/src/sdk/bus/notification-service.ts +284 -62
- package/src/sdk/bus/recent-activity.ts +14 -5
- package/src/sdk/bus/session-control.ts +150 -44
- package/src/sdk/bus/telegram-daemon-cli.ts +20 -14
- package/src/sdk/bus/telegram-daemon-contract.ts +11 -3
- package/src/sdk/bus/telegram-daemon-control.ts +312 -76
- package/src/sdk/bus/telegram-daemon.ts +1916 -285
- package/src/sdk/host/control/dispatch.ts +14 -5
- package/src/sdk/protocol/operation-inventory.generated.json +29 -0
- package/src/sdk/session.ts +155 -27
- package/src/secrets/index.ts +53 -10
- package/src/secrets/obfuscator.ts +21 -18
- package/src/secrets/regex.ts +2 -0
- package/src/session/agent-session.ts +1447 -852
- package/src/session/artifacts.ts +188 -23
- package/src/session/context-estimation.ts +7 -2
- package/src/session/internal/managed-session-scope.ts +200 -38
- package/src/session/internal/managed-session-storage.ts +1152 -46
- package/src/session/session-manager.ts +1121 -148
- package/src/session/session-storage.ts +109 -11
- package/src/session/streaming-output.ts +6 -0
- package/src/session/yield-queue.ts +20 -0
- package/src/slash-commands/builtin-registry.ts +36 -0
- package/src/task/executor.ts +71 -26
- package/src/task/index.ts +63 -20
- package/src/tool-discovery/tool-index.ts +18 -0
- package/src/tools/ask-answer-registry.ts +15 -1
- package/src/tools/ask.ts +129 -32
- package/src/tools/bash-skill-urls.ts +14 -3
- package/src/tools/bash.ts +2 -2
- package/src/tools/index.ts +4 -0
- package/src/tools/plan-mode-guard.ts +1 -0
- package/src/tools/sqlite-reader.ts +3 -2
- package/src/tools/subagent.ts +2 -0
package/src/main.ts
CHANGED
|
@@ -36,6 +36,8 @@ import { BUNDLED_GROK_BUILD_EXTENSION_ID, getBundledGrokBuildExtensionFactory }
|
|
|
36
36
|
import { initializeWithSettings } from "./discovery";
|
|
37
37
|
import { exportFromFile } from "./export/html";
|
|
38
38
|
import type { ExtensionUIContext } from "./extensibility/extensions/types";
|
|
39
|
+
import { admitManagedOwnerBeforeCli, completeManagedOwnerRecovery } from "./gjc-runtime/managed-owner-admission";
|
|
40
|
+
import { isManagedOwnerSupervisorArgv, runManagedOwnerSupervisor } from "./gjc-runtime/managed-owner-supervisor";
|
|
39
41
|
import { persistCoordinatorRuntimeInputReady } from "./gjc-runtime/session-state-sidecar";
|
|
40
42
|
import { isTmuxOwnerIsolationCliArgv, runTmuxOwnerIsolationCliFromStdin } from "./gjc-runtime/tmux-owner-isolation-cli";
|
|
41
43
|
import type { AcpStartupOptions } from "./modes/acp/startup-options";
|
|
@@ -58,6 +60,7 @@ import type { AgentSession } from "./session/agent-session";
|
|
|
58
60
|
import {
|
|
59
61
|
type ResumeSessionIdentity,
|
|
60
62
|
resolveResumableSession,
|
|
63
|
+
type SessionDestination,
|
|
61
64
|
type SessionDirectoryMigrationPolicy,
|
|
62
65
|
type SessionInfo,
|
|
63
66
|
SessionManager,
|
|
@@ -535,7 +538,8 @@ type ListForResumePickerReadOnly = (cwd: string, sessionDir?: string) => Promise
|
|
|
535
538
|
type SelectResumeSession = (sessions: SessionInfo[]) => Promise<SessionSelectionResult>;
|
|
536
539
|
type OpenExistingSessionStrict = (
|
|
537
540
|
identity: ResumeSessionIdentity,
|
|
538
|
-
|
|
541
|
+
destination: SessionDestination,
|
|
542
|
+
storage?: undefined,
|
|
539
543
|
migrationPolicy?: SessionDirectoryMigrationPolicy,
|
|
540
544
|
) => Promise<StrictSessionOpenResult>;
|
|
541
545
|
|
|
@@ -722,6 +726,10 @@ export async function createSessionManager(
|
|
|
722
726
|
activeSettings: Settings = settings,
|
|
723
727
|
): Promise<SessionManager | undefined> {
|
|
724
728
|
const migrationPolicy = activeSettings.get("session.directoryMigration") === "disabled" ? "disabled" : "copy-retain";
|
|
729
|
+
const sessionDestination = () =>
|
|
730
|
+
parsed.sessionDir
|
|
731
|
+
? SessionManager.explicitDestination(parsed.sessionDir)
|
|
732
|
+
: SessionManager.managedDestination(cwd, activeSettings.getAgentDir());
|
|
725
733
|
if (parsed.resume === true) {
|
|
726
734
|
return undefined;
|
|
727
735
|
}
|
|
@@ -731,13 +739,13 @@ export async function createSessionManager(
|
|
|
731
739
|
}
|
|
732
740
|
const forkSource = parsed.fork;
|
|
733
741
|
if (forkSource.includes("/") || forkSource.includes("\\") || forkSource.endsWith(".jsonl")) {
|
|
734
|
-
return await SessionManager.forkFrom(forkSource, cwd,
|
|
742
|
+
return await SessionManager.forkFrom(forkSource, cwd, sessionDestination(), undefined, migrationPolicy);
|
|
735
743
|
}
|
|
736
744
|
const match = await resolveResumableSession(forkSource, cwd, parsed.sessionDir);
|
|
737
745
|
if (!match) {
|
|
738
746
|
throw new Error(`Session "${forkSource}" not found.`);
|
|
739
747
|
}
|
|
740
|
-
return await SessionManager.forkFrom(match.session.path, cwd,
|
|
748
|
+
return await SessionManager.forkFrom(match.session.path, cwd, sessionDestination(), undefined, migrationPolicy);
|
|
741
749
|
}
|
|
742
750
|
|
|
743
751
|
if (parsed.noSession) {
|
|
@@ -746,7 +754,12 @@ export async function createSessionManager(
|
|
|
746
754
|
if (typeof parsed.resume === "string") {
|
|
747
755
|
const sessionArg = parsed.resume;
|
|
748
756
|
if (sessionArg.includes("/") || sessionArg.includes("\\") || sessionArg.endsWith(".jsonl")) {
|
|
749
|
-
return await SessionManager.open(
|
|
757
|
+
return await SessionManager.open(
|
|
758
|
+
sessionArg,
|
|
759
|
+
SessionManager.explicitDestination(path.dirname(sessionArg)),
|
|
760
|
+
undefined,
|
|
761
|
+
migrationPolicy,
|
|
762
|
+
);
|
|
750
763
|
}
|
|
751
764
|
const match = await resolveResumableSession(sessionArg, cwd, parsed.sessionDir);
|
|
752
765
|
if (!match) {
|
|
@@ -763,21 +776,21 @@ export async function createSessionManager(
|
|
|
763
776
|
return await SessionManager.forkFrom(
|
|
764
777
|
match.session.path,
|
|
765
778
|
cwd,
|
|
766
|
-
|
|
779
|
+
sessionDestination(),
|
|
767
780
|
undefined,
|
|
768
781
|
migrationPolicy,
|
|
769
782
|
);
|
|
770
783
|
}
|
|
771
784
|
}
|
|
772
|
-
return await SessionManager.open(match.session.path,
|
|
785
|
+
return await SessionManager.open(match.session.path, sessionDestination(), undefined, migrationPolicy);
|
|
773
786
|
}
|
|
774
787
|
if (parsed.continue) {
|
|
775
|
-
return await SessionManager.continueRecent(cwd,
|
|
788
|
+
return await SessionManager.continueRecent(cwd, sessionDestination(), undefined, migrationPolicy);
|
|
776
789
|
}
|
|
777
790
|
// --resume without value is handled separately (needs picker UI)
|
|
778
791
|
// If --session-dir provided without --continue/--resume, create new session there
|
|
779
792
|
if (parsed.sessionDir) {
|
|
780
|
-
return SessionManager.create(cwd, parsed.sessionDir);
|
|
793
|
+
return SessionManager.create(cwd, SessionManager.explicitDestination(parsed.sessionDir));
|
|
781
794
|
}
|
|
782
795
|
// A lifecycle `/session_create` child must start a FRESH session that adopts
|
|
783
796
|
// the pre-allocated id (GJC_SESSION_ID), never auto-resume existing history in
|
|
@@ -795,14 +808,13 @@ export async function createSessionManager(
|
|
|
795
808
|
// buildSessionOptions restores the session's model/thinking instead of
|
|
796
809
|
// overriding them with CLI defaults.
|
|
797
810
|
if (activeSettings.get("autoResume")) {
|
|
798
|
-
const manager = await SessionManager.continueRecent(cwd,
|
|
811
|
+
const manager = await SessionManager.continueRecent(cwd, sessionDestination(), undefined, migrationPolicy);
|
|
799
812
|
if (manager.getEntries().length > 0) {
|
|
800
813
|
parsed.continue = true;
|
|
801
814
|
}
|
|
802
815
|
return manager;
|
|
803
816
|
}
|
|
804
|
-
|
|
805
|
-
return SessionManager.create(cwd, sessionDir);
|
|
817
|
+
return SessionManager.create(cwd, SessionManager.managedDestination(cwd, activeSettings.getAgentDir()));
|
|
806
818
|
}
|
|
807
819
|
|
|
808
820
|
async function maybeAutoChdir(parsed: Args): Promise<void> {
|
|
@@ -1106,7 +1118,9 @@ export async function runRootCommand(
|
|
|
1106
1118
|
try {
|
|
1107
1119
|
opened = await (deps.openExistingSessionStrict ?? SessionManager.openExistingStrict)(
|
|
1108
1120
|
selection.identity,
|
|
1109
|
-
parsedArgs.sessionDir
|
|
1121
|
+
parsedArgs.sessionDir
|
|
1122
|
+
? SessionManager.explicitDestination(parsedArgs.sessionDir)
|
|
1123
|
+
: SessionManager.managedDestination(resumeCwd, settings.getAgentDir()),
|
|
1110
1124
|
undefined,
|
|
1111
1125
|
resumeMigrationPolicy,
|
|
1112
1126
|
);
|
|
@@ -1604,6 +1618,16 @@ export async function main(args: string[]): Promise<void> {
|
|
|
1604
1618
|
await runTmuxOwnerIsolationCliFromStdin();
|
|
1605
1619
|
return;
|
|
1606
1620
|
}
|
|
1621
|
+
if (isManagedOwnerSupervisorArgv(args)) {
|
|
1622
|
+
await runManagedOwnerSupervisor();
|
|
1623
|
+
return;
|
|
1624
|
+
}
|
|
1625
|
+
const admission = await admitManagedOwnerBeforeCli();
|
|
1626
|
+
if (admission.kind === "blocked") return;
|
|
1627
|
+
if (admission.kind === "recovery") {
|
|
1628
|
+
await completeManagedOwnerRecovery(admission.context);
|
|
1629
|
+
return;
|
|
1630
|
+
}
|
|
1607
1631
|
const { runCli } = await import("./cli");
|
|
1608
1632
|
await runCli(args.length === 0 ? ["launch"] : args);
|
|
1609
1633
|
}
|
|
@@ -74,6 +74,7 @@ interface PromptWaiter {
|
|
|
74
74
|
/** Highest inbound frame sequence already observed when the prompt was acknowledged. */
|
|
75
75
|
boundary: number;
|
|
76
76
|
correlation: PromptCorrelation;
|
|
77
|
+
messageProgress?: { textEmitted: boolean; thoughtEmitted: boolean };
|
|
77
78
|
pendingTerminal?: PromptCorrelation;
|
|
78
79
|
resolve: (response: PromptResponse) => void;
|
|
79
80
|
reject: (error: Error) => void;
|
|
@@ -1298,9 +1299,16 @@ export class AcpAgent implements Agent {
|
|
|
1298
1299
|
if (wirePayload) {
|
|
1299
1300
|
for (const notification of mapAgentWireEventPayloadToAcpSessionUpdates(wirePayload as never, id, {
|
|
1300
1301
|
cwd: record.cwd,
|
|
1302
|
+
getMessageProgress: message => {
|
|
1303
|
+
if (!activePrompt || !object(message)) return undefined;
|
|
1304
|
+
activePrompt.messageProgress ??= { textEmitted: false, thoughtEmitted: false };
|
|
1305
|
+
return activePrompt.messageProgress;
|
|
1306
|
+
},
|
|
1301
1307
|
}))
|
|
1302
1308
|
await this.#publishSessionUpdate(id, notification, adapter);
|
|
1303
1309
|
}
|
|
1310
|
+
if (event.type === "message_end" && object(event.message)?.role === "assistant" && activePrompt)
|
|
1311
|
+
activePrompt.messageProgress = undefined;
|
|
1304
1312
|
if (event.type === "agent_end") await this.#emitEndOfTurnUpdates(id, adapter);
|
|
1305
1313
|
if (activePrompt) this.#settlePrompt(record, activePrompt);
|
|
1306
1314
|
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Removes every terminal control sequence except bounded SGR parameters (0-255). */
|
|
2
|
+
export function validateDisplayLine(line: string): string {
|
|
3
|
+
let result = "";
|
|
4
|
+
for (let index = 0; index < line.length; index++) {
|
|
5
|
+
const char = line[index]!;
|
|
6
|
+
const code = char.charCodeAt(0);
|
|
7
|
+
if (char === "\t") {
|
|
8
|
+
result += " ";
|
|
9
|
+
continue;
|
|
10
|
+
}
|
|
11
|
+
if (char === "\x1b") {
|
|
12
|
+
const next = line[index + 1];
|
|
13
|
+
if (next === "[") {
|
|
14
|
+
const match = /^\x1b\[([0-9]{1,3}(?:;[0-9]{1,3})*)m/.exec(line.slice(index));
|
|
15
|
+
if (match && match[0].length <= 64 && match[1]!.split(";").every(parameter => Number(parameter) <= 255)) {
|
|
16
|
+
result += match[0];
|
|
17
|
+
index += match[0].length - 1;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
index = skipEscapeSequence(line, index + 2, /[@-~]/);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (next === "]" || next === "P" || next === "_" || next === "^" || next === "X") {
|
|
24
|
+
index = skipStringControl(line, index + 2);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
if (next === "_") {
|
|
28
|
+
index = skipStringControl(line, index + 2);
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
index += next ? 1 : 0;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (code >= 0x80 && code <= 0x9f) continue;
|
|
35
|
+
if (code < 0x20 || code === 0x7f) continue;
|
|
36
|
+
result += char;
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function skipEscapeSequence(text: string, start: number, final: RegExp): number {
|
|
42
|
+
for (let index = start; index < text.length; index++) {
|
|
43
|
+
if (final.test(text[index]!)) return index;
|
|
44
|
+
}
|
|
45
|
+
return text.length - 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function skipStringControl(text: string, start: number): number {
|
|
49
|
+
for (let index = start; index < text.length; index++) {
|
|
50
|
+
if (text[index] === "\x07") return index;
|
|
51
|
+
if (text[index] === "\x1b" && text[index + 1] === "\\") return index + 1;
|
|
52
|
+
}
|
|
53
|
+
return text.length - 1;
|
|
54
|
+
}
|
|
@@ -30,6 +30,8 @@ export interface NotificationsEditorPreferences {
|
|
|
30
30
|
sessionScope: "all" | "primary";
|
|
31
31
|
richEnabled: boolean;
|
|
32
32
|
richDraftEnabled: boolean;
|
|
33
|
+
toolActivityEnabled: boolean;
|
|
34
|
+
streamingEnabled: boolean;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
/** Secret-safe snapshot used to render the Notifications tab. */
|
|
@@ -50,6 +52,7 @@ export interface NotificationsEditorSetupInput {
|
|
|
50
52
|
chatId?: string;
|
|
51
53
|
richEnabled: boolean;
|
|
52
54
|
richDraftEnabled: boolean;
|
|
55
|
+
streamingEnabled: boolean;
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
/**
|
|
@@ -62,6 +65,7 @@ export interface PreparedTelegramConfiguration {
|
|
|
62
65
|
tokenFingerprint?: string;
|
|
63
66
|
richEnabled: boolean;
|
|
64
67
|
richDraftEnabled: boolean;
|
|
68
|
+
streamingEnabled: boolean;
|
|
65
69
|
}
|
|
66
70
|
|
|
67
71
|
export interface NotificationsPreflightResult {
|
|
@@ -155,7 +159,8 @@ type HomeActionId =
|
|
|
155
159
|
| "recover"
|
|
156
160
|
| "reconnect"
|
|
157
161
|
| "remove"
|
|
158
|
-
| "preferences"
|
|
162
|
+
| "preferences"
|
|
163
|
+
| "tool-activity";
|
|
159
164
|
|
|
160
165
|
interface Action {
|
|
161
166
|
id: HomeActionId | "telegram" | "external" | "save" | "save-inactive" | "cancel" | "confirm";
|
|
@@ -190,6 +195,8 @@ function emptyState(): NotificationsEditorState {
|
|
|
190
195
|
sessionScope: "all",
|
|
191
196
|
richEnabled: true,
|
|
192
197
|
richDraftEnabled: false,
|
|
198
|
+
toolActivityEnabled: true,
|
|
199
|
+
streamingEnabled: true,
|
|
193
200
|
},
|
|
194
201
|
};
|
|
195
202
|
}
|
|
@@ -549,6 +556,7 @@ export class NotificationsSettingsEditorComponent implements Component, Focusabl
|
|
|
549
556
|
chatId,
|
|
550
557
|
richEnabled: preferences.richEnabled,
|
|
551
558
|
richDraftEnabled: preferences.richDraftEnabled,
|
|
559
|
+
streamingEnabled: preferences.streamingEnabled,
|
|
552
560
|
},
|
|
553
561
|
signal,
|
|
554
562
|
),
|
|
@@ -928,6 +936,12 @@ export class NotificationsSettingsEditorComponent implements Component, Focusabl
|
|
|
928
936
|
case "refresh":
|
|
929
937
|
draft.richDraftEnabled = !draft.richDraftEnabled;
|
|
930
938
|
return;
|
|
939
|
+
case "tool-activity":
|
|
940
|
+
draft.toolActivityEnabled = !draft.toolActivityEnabled;
|
|
941
|
+
return;
|
|
942
|
+
case "test":
|
|
943
|
+
draft.streamingEnabled = !draft.streamingEnabled;
|
|
944
|
+
return;
|
|
931
945
|
default:
|
|
932
946
|
return;
|
|
933
947
|
}
|
|
@@ -1068,6 +1082,16 @@ export class NotificationsSettingsEditorComponent implements Component, Focusabl
|
|
|
1068
1082
|
label: `Telegram rich drafts: ${draft.richDraftEnabled ? "on" : "off"}`,
|
|
1069
1083
|
description: "Toggle the unsaved rich-draft preference.",
|
|
1070
1084
|
},
|
|
1085
|
+
{
|
|
1086
|
+
id: "tool-activity",
|
|
1087
|
+
label: `Telegram tool activity: ${draft.toolActivityEnabled ? "on" : "off"}`,
|
|
1088
|
+
description: "Toggle tool start and completion notifications.",
|
|
1089
|
+
},
|
|
1090
|
+
{
|
|
1091
|
+
id: "test",
|
|
1092
|
+
label: `Telegram streaming: ${draft.streamingEnabled ? "on" : "off"}`,
|
|
1093
|
+
description: "Toggle the unsaved Telegram streaming preference.",
|
|
1094
|
+
},
|
|
1071
1095
|
{ id: "save", label: "Save preferences", description: "Atomically persist this preference draft." },
|
|
1072
1096
|
{ id: "cancel", label: "Cancel and discard draft", description: "Leave saved preferences unchanged." },
|
|
1073
1097
|
];
|
|
@@ -1162,7 +1186,7 @@ export class NotificationsSettingsEditorComponent implements Component, Focusabl
|
|
|
1162
1186
|
);
|
|
1163
1187
|
lines.push(
|
|
1164
1188
|
this.#truncate(
|
|
1165
|
-
` Private chat: ${draft?.chatId ?? "(expired)"} rich: ${draft?.richEnabled ? "on" : "off"} drafts: ${draft?.richDraftEnabled ? "on" : "off"}`,
|
|
1189
|
+
` Private chat: ${draft?.chatId ?? "(expired)"} rich: ${draft?.richEnabled ? "on" : "off"} drafts: ${draft?.richDraftEnabled ? "on" : "off"} streaming: ${draft?.streamingEnabled ? "on" : "off"}`,
|
|
1166
1190
|
width,
|
|
1167
1191
|
),
|
|
1168
1192
|
);
|
|
@@ -8,7 +8,11 @@ import type { SessionMessageEntry } from "../../session/session-manager";
|
|
|
8
8
|
import { parseSessionEntries } from "../../session/session-manager";
|
|
9
9
|
import type { ObservableSession, SessionObserverRegistry } from "../session-observer-registry";
|
|
10
10
|
import { theme } from "../theme/theme";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
buildToolTranscriptEntry,
|
|
13
|
+
composeToolText,
|
|
14
|
+
createToolTranscriptRenderDescriptor,
|
|
15
|
+
} from "./tool-transcript-format";
|
|
12
16
|
import { type TranscriptViewerEntry, TranscriptViewerOverlay } from "./transcript-viewer-overlay";
|
|
13
17
|
|
|
14
18
|
/** Session-observer adapter. The shared viewer owns navigation and fold state. */
|
|
@@ -148,7 +152,7 @@ export class SessionObserverOverlayComponent extends TranscriptViewerOverlay {
|
|
|
148
152
|
}
|
|
149
153
|
}
|
|
150
154
|
|
|
151
|
-
function entriesFromMessages(entries: readonly SessionMessageEntry[]): TranscriptViewerEntry[] {
|
|
155
|
+
export function entriesFromMessages(entries: readonly SessionMessageEntry[]): TranscriptViewerEntry[] {
|
|
152
156
|
const results = new Map<string, ToolResultMessage>();
|
|
153
157
|
for (const entry of entries)
|
|
154
158
|
if (entry.message.role === "toolResult") results.set(entry.message.toolCallId, entry.message);
|
|
@@ -190,30 +194,42 @@ function entriesFromMessages(entries: readonly SessionMessageEntry[]): Transcrip
|
|
|
190
194
|
.map(part => part.text)
|
|
191
195
|
.join("\n")
|
|
192
196
|
.trim() ?? "";
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
197
|
+
const canonicalPayload = {
|
|
198
|
+
text: composeToolText({
|
|
199
|
+
name: content.name,
|
|
200
|
+
args: content.arguments,
|
|
201
|
+
intent: content.intent,
|
|
202
|
+
resultText,
|
|
203
|
+
isError: result?.isError ?? false,
|
|
204
|
+
hasResult: results.has(content.id),
|
|
205
|
+
}),
|
|
206
|
+
metadata: {
|
|
207
|
+
name: content.name,
|
|
208
|
+
arguments: content.arguments,
|
|
209
|
+
intent: content.intent,
|
|
210
|
+
resultText,
|
|
211
|
+
isError: result?.isError ?? false,
|
|
212
|
+
hasResult: results.has(content.id),
|
|
213
|
+
detailsData: result?.details,
|
|
214
|
+
},
|
|
215
|
+
source: { call: content, result },
|
|
216
|
+
};
|
|
217
|
+
output.push(
|
|
218
|
+
buildToolTranscriptEntry({
|
|
219
|
+
canonicalPayload,
|
|
220
|
+
renderDescriptor: createToolTranscriptRenderDescriptor({
|
|
208
221
|
name: content.name,
|
|
209
|
-
|
|
222
|
+
args: content.arguments,
|
|
210
223
|
intent: content.intent,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
224
|
+
resultContent: resultText,
|
|
225
|
+
isError: result?.isError,
|
|
226
|
+
hasResult: results.has(content.id),
|
|
227
|
+
detailsData: result?.details,
|
|
228
|
+
}),
|
|
229
|
+
capabilities: { copyable: true, foldable: true, rawViewable: true },
|
|
230
|
+
identity: { id: `tool:${content.id}`, label: content.name, display: "full" },
|
|
231
|
+
}),
|
|
232
|
+
);
|
|
217
233
|
}
|
|
218
234
|
});
|
|
219
235
|
}
|
|
@@ -669,6 +669,8 @@ export interface SettingsRuntimeContext {
|
|
|
669
669
|
cwd: string;
|
|
670
670
|
/** Whether this terminal can render the pet overlay. */
|
|
671
671
|
petAvailable?: boolean;
|
|
672
|
+
/** Terminal environment used to select unavailable-pet guidance. Omitted in production to use Bun.env. */
|
|
673
|
+
terminalEnv?: NodeJS.ProcessEnv;
|
|
672
674
|
}
|
|
673
675
|
|
|
674
676
|
/** Status line settings subset for preview */
|
|
@@ -896,7 +898,7 @@ export class SettingsSelectorComponent extends Container {
|
|
|
896
898
|
options = createPetSelectItems(options, currentValue, petAvailable);
|
|
897
899
|
// Unsupported terminals must see the same actionable guidance the
|
|
898
900
|
// startup notice and /pet show, not only dimmed option descriptions.
|
|
899
|
-
if (!petAvailable) description = getPetUnavailableWarning();
|
|
901
|
+
if (!petAvailable) description = getPetUnavailableWarning(this.context.terminalEnv);
|
|
900
902
|
}
|
|
901
903
|
// Preview handlers
|
|
902
904
|
let onPreview: ((value: string) => void | Promise<void>) | undefined;
|