u-foo 2.3.32 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -213
- package/README.zh-CN.md +151 -197
- package/SKILLS/ufoo/SKILL.md +8 -8
- package/bin/uagy.js +69 -0
- package/bin/uclaude.js +2 -2
- package/bin/ucode.js +4 -4
- package/bin/ucodex.js +2 -2
- package/bin/ufoo.js +5 -23
- package/modules/AGENTS.template.md +1 -1
- package/modules/bus/SKILLS/ubus/SKILL.md +35 -10
- package/package.json +5 -5
- package/scripts/chat-app-smoke.js +1 -1
- package/scripts/global-chat-switch-benchmark.js +5 -5
- package/scripts/ink-demo.js +1 -1
- package/scripts/ink-smoke.js +1 -1
- package/scripts/ucode-app-smoke.js +1 -1
- package/src/{agent → agents/activity}/activityDetector.js +39 -2
- package/src/{agent → agents/activity}/activityStatePublisher.js +1 -1
- package/src/{agent → agents/activity}/activityStateWriter.js +2 -2
- package/src/{agent → agents/activity}/activityTracker.js +1 -1
- package/src/agents/activity/index.js +8 -0
- package/src/{agent → agents/controller}/controllerToolExecutor.js +4 -4
- package/src/agents/controller/index.js +8 -0
- package/src/{agent → agents/controller}/loopObservability.js +2 -2
- package/src/{agent → agents/controller}/loopRuntime.js +1 -1
- package/src/{agent → agents/controller}/ufooAgent.js +9 -9
- package/src/agents/index.js +10 -0
- package/src/agents/internal/index.js +3 -0
- package/src/{agent → agents/internal}/internalRunner.js +45 -22
- package/src/agents/launch/agyConversation.js +159 -0
- package/src/agents/launch/index.js +12 -0
- package/src/{agent → agents/launch}/launchEnvironment.js +2 -3
- package/src/{agent → agents/launch}/launcher.js +64 -21
- package/src/{agent → agents/launch}/notifier.js +23 -12
- package/src/{agent → agents/launch}/ptyRunner.js +44 -12
- package/src/{agent → agents/launch}/ptyWrapper.js +2 -2
- package/src/{agent → agents/launch}/publisherRouting.js +1 -1
- package/src/{agent → agents/launch}/readyDetector.js +23 -0
- package/src/{agent → agents/prompts}/defaultBootstrap.js +63 -4
- package/src/{group/bootstrap.js → agents/prompts/groupBootstrap.js} +41 -6
- package/src/agents/prompts/index.js +8 -0
- package/src/{code/prompts → agents/prompts/native}/index.js +1 -1
- package/src/{agent → agents/providers}/claudeThreadProvider.js +1 -1
- package/src/{agent → agents/providers}/codexThreadProvider.js +1 -1
- package/src/{agent → agents/providers}/directAuthStatus.js +184 -1
- package/src/agents/providers/index.js +13 -0
- package/src/{agent → agents/providers}/upstreamTransport.js +2 -2
- package/src/{chat → app/chat}/agentSockets.js +1 -1
- package/src/{chat → app/chat}/commandExecutor.js +50 -26
- package/src/{chat → app/chat}/commands.js +119 -5
- package/src/{chat → app/chat}/daemonConnection.js +1 -1
- package/src/{chat → app/chat}/daemonMessageRouter.js +45 -3
- package/src/{chat → app/chat}/dashboardView.js +2 -1
- package/src/app/chat/index.js +6 -0
- package/src/{chat → app/chat}/inputSubmitHandler.js +4 -13
- package/src/{chat → app/chat}/internalAgentLogHistory.js +1 -1
- package/src/app/chat/multiWindow/index.js +268 -0
- package/src/app/chat/multiWindow/paneLayout.js +84 -0
- package/src/app/chat/multiWindow/paneManager.js +299 -0
- package/src/app/chat/multiWindow/renderer.js +384 -0
- package/src/app/chat/multiWindow/virtualTerminal.js +327 -0
- package/src/{chat → app/chat}/transport.js +1 -1
- package/src/{cli → app/cli}/ctxCoreCommands.js +3 -3
- package/src/{doctor/index.js → app/cli/features/doctor.js} +1 -1
- package/src/{init/index.js → app/cli/features/init.js} +14 -32
- package/src/{cli → app/cli}/groupCoreCommands.js +2 -2
- package/src/app/cli/index.js +9 -0
- package/src/{cli → app/cli}/onlineCoreCommands.js +5 -5
- package/src/{cli.js → app/cli/run.js} +59 -57
- package/src/app/index.js +6 -0
- package/src/code/agent.js +10 -9
- package/src/code/index.js +2 -0
- package/src/code/launcher/index.js +9 -0
- package/src/{agent → code/launcher}/ucode.js +7 -8
- package/src/{agent → code/launcher}/ucodeBootstrap.js +3 -3
- package/src/{agent → code/launcher}/ucodeBuild.js +2 -2
- package/src/{agent → code/launcher}/ucodeDoctor.js +2 -2
- package/src/{agent → code/launcher}/ucodeRuntimeConfig.js +1 -2
- package/src/code/nativeRunner.js +4 -4
- package/src/code/tui.js +3 -1454
- package/src/config.js +15 -2
- package/src/{bus → coordination/bus}/activate.js +2 -2
- package/src/{bus → coordination/bus}/daemon.js +15 -5
- package/src/coordination/bus/envelope.js +173 -0
- package/src/{bus → coordination/bus}/index.js +7 -3
- package/src/{bus → coordination/bus}/inject.js +11 -3
- package/src/{bus → coordination/bus}/message.js +1 -1
- package/src/coordination/bus/messageMeta.js +130 -0
- package/src/coordination/bus/promptEnvelope.js +65 -0
- package/src/{bus → coordination/bus}/shake.js +1 -1
- package/src/{bus → coordination/bus}/store.js +3 -3
- package/src/{bus → coordination/bus}/subscriber.js +2 -2
- package/src/{bus → coordination/bus}/utils.js +2 -2
- package/src/{history → coordination/history}/inputTimeline.js +5 -5
- package/src/coordination/index.js +10 -0
- package/src/{memory → coordination/memory}/historySearch.js +1 -1
- package/src/{memory → coordination/memory}/index.js +3 -3
- package/src/{report → coordination/report}/store.js +2 -2
- package/src/{status → coordination/status}/index.js +3 -3
- package/src/online/bridge.js +2 -2
- package/src/{controller → orchestration/controller}/flags.js +1 -1
- package/src/{controller → orchestration/controller}/gateRouter.js +1 -1
- package/src/orchestration/controller/index.js +10 -0
- package/src/{controller → orchestration/controller}/shadowGuard.js +1 -1
- package/src/orchestration/groups/bootstrap.js +3 -0
- package/src/orchestration/groups/index.js +10 -0
- package/src/orchestration/groups/promptProfiles.js +3 -0
- package/src/{group → orchestration/groups}/templates.js +1 -1
- package/src/{group → orchestration/groups}/validateTemplate.js +1 -1
- package/src/orchestration/index.js +7 -0
- package/src/orchestration/solo/index.js +3 -0
- package/src/{daemon → runtime/daemon}/agentProcessManager.js +1 -1
- package/src/{daemon → runtime/daemon}/cronOps.js +3 -2
- package/src/{daemon → runtime/daemon}/groupOrchestrator.js +26 -9
- package/src/{daemon → runtime/daemon}/index.js +105 -53
- package/src/{daemon → runtime/daemon}/ipcServer.js +1 -1
- package/src/{daemon → runtime/daemon}/nicknameScope.js +6 -3
- package/src/{daemon → runtime/daemon}/ops.js +48 -61
- package/src/{daemon → runtime/daemon}/promptLoop.js +1 -1
- package/src/{daemon → runtime/daemon}/promptRequest.js +7 -7
- package/src/runtime/daemon/providerSessions.js +230 -0
- package/src/{daemon → runtime/daemon}/reporting.js +4 -4
- package/src/{daemon → runtime/daemon}/run.js +4 -4
- package/src/{daemon → runtime/daemon}/soloBootstrap.js +7 -7
- package/src/{daemon → runtime/daemon}/status.js +5 -5
- package/src/runtime/index.js +10 -0
- package/src/{projects → runtime/projects}/registry.js +1 -1
- package/src/{terminal → runtime/terminal}/adapterRouter.js +0 -10
- package/src/{terminal → runtime/terminal}/adapters/internalAdapter.js +0 -4
- package/src/tools/handlers/common.js +1 -1
- package/src/tools/handlers/listAgents.js +1 -1
- package/src/tools/handlers/memory.js +3 -3
- package/src/tools/handlers/readBusSummary.js +1 -1
- package/src/tools/handlers/readOpenDecisions.js +1 -1
- package/src/tools/handlers/readProjectRegistry.js +1 -1
- package/src/tools/handlers/readPromptHistory.js +2 -2
- package/src/tools/schemaFixtures.js +1 -1
- package/src/ui/MIGRATION.md +42 -88
- package/src/ui/format/index.js +5 -28
- package/src/ui/index.js +1 -1
- package/src/ui/{components → ink}/ChatApp.js +812 -88
- package/src/ui/ink/DashboardBar.js +685 -0
- package/src/ui/{components → ink}/MultilineInput.js +230 -5
- package/src/ui/{components → ink}/UcodeApp.js +16 -7
- package/src/ui/{components → ink}/agentMirror.js +24 -19
- package/src/ui/{components → ink}/chatReducer.js +29 -7
- package/src/bus/messageMeta.js +0 -52
- package/src/chat/agentViewController.js +0 -1072
- package/src/chat/chatLogController.js +0 -138
- package/src/chat/completionController.js +0 -533
- package/src/chat/dashboardKeyController.js +0 -533
- package/src/chat/index.js +0 -2222
- package/src/chat/inputHistoryController.js +0 -135
- package/src/chat/inputListenerController.js +0 -470
- package/src/chat/layout.js +0 -186
- package/src/chat/pasteController.js +0 -81
- package/src/chat/statusLineController.js +0 -223
- package/src/chat/streamTracker.js +0 -156
- package/src/code/config +0 -0
- package/src/daemon/providerSessions.js +0 -488
- package/src/terminal/adapters/internalPtyAdapter.js +0 -42
- package/src/ui/components/DashboardBar.js +0 -417
- /package/src/{code/prompts → agents/prompts/native}/actions.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/efficiency.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/environment.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/identity.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/safety.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/sections.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/system.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/tasks.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/bash.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/edit.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/read.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/toolDescriptions/write.js +0 -0
- /package/src/{code/prompts → agents/prompts/native}/ufoo.js +0 -0
- /package/src/{group → agents/prompts}/promptProfiles.js +0 -0
- /package/src/{agent → agents/providers}/claudeEventTranslator.js +0 -0
- /package/src/{agent → agents/providers}/claudeOauthTokenReader.js +0 -0
- /package/src/{agent → agents/providers}/claudeSessionFiles.js +0 -0
- /package/src/{agent → agents/providers}/codexEventTranslator.js +0 -0
- /package/src/{agent → agents/providers}/credentials/claude.js +0 -0
- /package/src/{agent → agents/providers}/credentials/codex.js +0 -0
- /package/src/{agent → agents/providers}/credentials/index.js +0 -0
- /package/src/{chat → app/chat}/agentBar.js +0 -0
- /package/src/{chat → app/chat}/agentDirectory.js +0 -0
- /package/src/{chat → app/chat}/cronScheduler.js +0 -0
- /package/src/{chat → app/chat}/daemonCoordinator.js +0 -0
- /package/src/{chat → app/chat}/daemonReconnect.js +0 -0
- /package/src/{chat → app/chat}/daemonTransport.js +0 -0
- /package/src/{chat → app/chat}/daemonTransportDefaults.js +0 -0
- /package/src/{chat → app/chat}/inputMath.js +0 -0
- /package/src/{chat → app/chat}/projectCloseController.js +0 -0
- /package/src/{chat → app/chat}/rawKeyMap.js +0 -0
- /package/src/{chat → app/chat}/settingsController.js +0 -0
- /package/src/{chat → app/chat}/shellCommand.js +0 -0
- /package/src/{chat → app/chat}/text.js +0 -0
- /package/src/{chat → app/chat}/transientAgentState.js +0 -0
- /package/src/{cli → app/cli}/busCoreCommands.js +0 -0
- /package/src/{skills/index.js → app/cli/features/skills.js} +0 -0
- /package/src/{bus → coordination/bus}/nickname.js +0 -0
- /package/src/{bus → coordination/bus}/queue.js +0 -0
- /package/src/{context → coordination/context}/decisions.js +0 -0
- /package/src/{context → coordination/context}/doctor.js +0 -0
- /package/src/{context → coordination/context}/index.js +0 -0
- /package/src/{context → coordination/context}/sync.js +0 -0
- /package/src/{ufoo → coordination/state}/agentRegistryDiagnostics.js +0 -0
- /package/src/{ufoo → coordination/state}/agentsStore.js +0 -0
- /package/src/{ufoo → coordination/state}/paths.js +0 -0
- /package/src/{controller → orchestration/controller}/launchRouting.js +0 -0
- /package/src/{controller → orchestration/controller}/routerFastPath.js +0 -0
- /package/src/{controller → orchestration/controller}/routerFinalize.js +0 -0
- /package/src/{group → orchestration/groups}/diagram.js +0 -0
- /package/src/{group → orchestration/groups}/templateValidation.js +0 -0
- /package/src/{solo → orchestration/solo}/commands.js +0 -0
- /package/src/{shared → runtime/contracts}/eventContract.js +0 -0
- /package/src/{shared → runtime/contracts}/ptySocketContract.js +0 -0
- /package/src/{providerapi → runtime/privacy}/redactor.js +0 -0
- /package/src/{providerapi → runtime/privacy}/shadowDiff.js +0 -0
- /package/src/{utils → runtime/process}/nodeExecutable.js +0 -0
- /package/src/{projects → runtime/projects}/identity.js +0 -0
- /package/src/{projects → runtime/projects}/index.js +0 -0
- /package/src/{projects → runtime/projects}/projectId.js +0 -0
- /package/src/{projects → runtime/projects}/runtimes.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapterContract.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/externalAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/hostAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/internalQueueAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/terminalAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/adapters/tmuxAdapter.js +0 -0
- /package/src/{terminal → runtime/terminal}/detect.js +0 -0
- /package/src/{terminal → runtime/terminal}/index.js +0 -0
- /package/src/{terminal → runtime/terminal}/iterm2.js +0 -0
- /package/src/{utils → ui/format}/banner.js +0 -0
- /package/src/{shared → ui/format}/markdownRenderer.js +0 -0
- /package/src/ui/{components → ink}/InkDemo.js +0 -0
package/src/chat/layout.js
DELETED
|
@@ -1,186 +0,0 @@
|
|
|
1
|
-
function createChatLayout(options = {}) {
|
|
2
|
-
const {
|
|
3
|
-
blessed,
|
|
4
|
-
currentInputHeight = 4,
|
|
5
|
-
dashboardHeight = 1,
|
|
6
|
-
version = "unknown",
|
|
7
|
-
logBorder = false,
|
|
8
|
-
logScrollbar = false,
|
|
9
|
-
} = options;
|
|
10
|
-
const normalizedDashboardHeight = Number.isFinite(dashboardHeight) && dashboardHeight > 0
|
|
11
|
-
? Math.floor(dashboardHeight)
|
|
12
|
-
: 1;
|
|
13
|
-
const reservedBottomLines = Math.max(2, currentInputHeight + 1);
|
|
14
|
-
|
|
15
|
-
const screen = blessed.screen({
|
|
16
|
-
smartCSR: true,
|
|
17
|
-
title: "ufoo chat",
|
|
18
|
-
fullUnicode: true,
|
|
19
|
-
// Toggle mouse at runtime to balance copy vs scroll
|
|
20
|
-
sendFocus: true,
|
|
21
|
-
mouse: false,
|
|
22
|
-
// Allow Ctrl+C to exit even when input grabs keys
|
|
23
|
-
ignoreLocked: ["C-c"],
|
|
24
|
-
});
|
|
25
|
-
// Prefer normal buffer for reliable terminal selection/copy
|
|
26
|
-
if (screen.program && typeof screen.program.normalBuffer === "function") {
|
|
27
|
-
screen.program.normalBuffer();
|
|
28
|
-
if (screen.program.put && typeof screen.program.put.keypad_local === "function") {
|
|
29
|
-
screen.program.put.keypad_local();
|
|
30
|
-
}
|
|
31
|
-
if (typeof screen.program.clear === "function") {
|
|
32
|
-
screen.program.clear();
|
|
33
|
-
screen.program.cup(0, 0);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
// Log area
|
|
38
|
-
const logBox = blessed.log({
|
|
39
|
-
parent: screen,
|
|
40
|
-
top: 0,
|
|
41
|
-
left: 0,
|
|
42
|
-
width: "100%",
|
|
43
|
-
height: `100%-${reservedBottomLines}`, // Will be adjusted dynamically
|
|
44
|
-
border: logBorder ? { type: "line" } : null,
|
|
45
|
-
tags: true,
|
|
46
|
-
scrollable: true,
|
|
47
|
-
alwaysScroll: true,
|
|
48
|
-
scrollback: 10000,
|
|
49
|
-
scrollbar: logScrollbar
|
|
50
|
-
? {
|
|
51
|
-
ch: " ",
|
|
52
|
-
track: { bg: "black" },
|
|
53
|
-
style: { bg: "gray" },
|
|
54
|
-
}
|
|
55
|
-
: null,
|
|
56
|
-
keys: true,
|
|
57
|
-
vi: true,
|
|
58
|
-
// Mouse handled globally (toggleable) to keep copy working
|
|
59
|
-
mouse: false,
|
|
60
|
-
// Ensure proper wrapping and width calculation
|
|
61
|
-
wrap: true,
|
|
62
|
-
padding: logBorder ? { left: 1, right: 1 } : undefined,
|
|
63
|
-
style: logBorder
|
|
64
|
-
? {
|
|
65
|
-
border: { fg: "gray" },
|
|
66
|
-
scrollbar: { bg: "gray" },
|
|
67
|
-
}
|
|
68
|
-
: undefined,
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
// Status line just above input
|
|
72
|
-
const statusLine = blessed.box({
|
|
73
|
-
parent: screen,
|
|
74
|
-
bottom: currentInputHeight,
|
|
75
|
-
left: 0,
|
|
76
|
-
width: "100%",
|
|
77
|
-
height: 1,
|
|
78
|
-
style: { fg: "gray" },
|
|
79
|
-
tags: true,
|
|
80
|
-
content: "",
|
|
81
|
-
});
|
|
82
|
-
const bannerText = `{bold}UFOO{/bold} · Chat Manager{|}v${version}`;
|
|
83
|
-
statusLine.setContent(bannerText);
|
|
84
|
-
|
|
85
|
-
// Command completion panel
|
|
86
|
-
const completionPanel = blessed.box({
|
|
87
|
-
parent: screen,
|
|
88
|
-
bottom: currentInputHeight - 1,
|
|
89
|
-
left: 0,
|
|
90
|
-
width: "100%",
|
|
91
|
-
height: 0,
|
|
92
|
-
hidden: true,
|
|
93
|
-
wrap: false,
|
|
94
|
-
border: {
|
|
95
|
-
type: "line",
|
|
96
|
-
top: true,
|
|
97
|
-
left: false,
|
|
98
|
-
right: false,
|
|
99
|
-
bottom: false,
|
|
100
|
-
},
|
|
101
|
-
style: {
|
|
102
|
-
border: { fg: "yellow" },
|
|
103
|
-
fg: "white",
|
|
104
|
-
// No bg - uses terminal default background
|
|
105
|
-
},
|
|
106
|
-
padding: {
|
|
107
|
-
left: 0,
|
|
108
|
-
right: 0,
|
|
109
|
-
top: 0,
|
|
110
|
-
bottom: 0,
|
|
111
|
-
},
|
|
112
|
-
tags: true,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Dashboard at very bottom
|
|
116
|
-
const dashboard = blessed.box({
|
|
117
|
-
parent: screen,
|
|
118
|
-
bottom: 0,
|
|
119
|
-
left: 0,
|
|
120
|
-
width: "100%",
|
|
121
|
-
height: normalizedDashboardHeight,
|
|
122
|
-
style: { fg: "gray" },
|
|
123
|
-
tags: true,
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
// Bottom border line for input area (above dashboard)
|
|
127
|
-
const inputBottomLine = blessed.line({
|
|
128
|
-
parent: screen,
|
|
129
|
-
bottom: normalizedDashboardHeight,
|
|
130
|
-
left: 1,
|
|
131
|
-
width: "100%-2",
|
|
132
|
-
orientation: "horizontal",
|
|
133
|
-
style: { fg: "gray" },
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
// Prompt indicator
|
|
137
|
-
const promptBox = blessed.box({
|
|
138
|
-
parent: screen,
|
|
139
|
-
bottom: normalizedDashboardHeight + 1,
|
|
140
|
-
left: 0,
|
|
141
|
-
width: 2,
|
|
142
|
-
height: Math.max(1, currentInputHeight - normalizedDashboardHeight - 2),
|
|
143
|
-
content: ">",
|
|
144
|
-
style: { fg: "cyan" },
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// Input area without left/right border
|
|
148
|
-
const input = blessed.textarea({
|
|
149
|
-
parent: screen,
|
|
150
|
-
bottom: normalizedDashboardHeight + 1,
|
|
151
|
-
left: 2,
|
|
152
|
-
width: "100%-2",
|
|
153
|
-
height: Math.max(1, currentInputHeight - normalizedDashboardHeight - 2),
|
|
154
|
-
inputOnFocus: true,
|
|
155
|
-
keys: true,
|
|
156
|
-
});
|
|
157
|
-
// Avoid textarea's extra wrap margin (causes a phantom empty column)
|
|
158
|
-
input.type = "box";
|
|
159
|
-
|
|
160
|
-
// Top border line for input area (just above input)
|
|
161
|
-
const inputTopLine = blessed.line({
|
|
162
|
-
parent: screen,
|
|
163
|
-
bottom: currentInputHeight - 1, // 4-1=3: above input(2) + inputHeight(1)
|
|
164
|
-
left: 1,
|
|
165
|
-
width: "100%-2",
|
|
166
|
-
orientation: "horizontal",
|
|
167
|
-
style: { fg: "gray" },
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
return {
|
|
171
|
-
screen,
|
|
172
|
-
logBox,
|
|
173
|
-
statusLine,
|
|
174
|
-
bannerText,
|
|
175
|
-
completionPanel,
|
|
176
|
-
dashboard,
|
|
177
|
-
inputBottomLine,
|
|
178
|
-
promptBox,
|
|
179
|
-
input,
|
|
180
|
-
inputTopLine,
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
module.exports = {
|
|
185
|
-
createChatLayout,
|
|
186
|
-
};
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
function createPasteController(options = {}) {
|
|
2
|
-
const {
|
|
3
|
-
shouldHandle = () => true,
|
|
4
|
-
normalizePaste = (text) => text,
|
|
5
|
-
insertTextAtCursor = () => {},
|
|
6
|
-
setImmediateFn = setImmediate,
|
|
7
|
-
clearImmediateFn = clearImmediate,
|
|
8
|
-
} = options;
|
|
9
|
-
|
|
10
|
-
const PASTE_START = "\x1b[200~";
|
|
11
|
-
const PASTE_END = "\x1b[201~";
|
|
12
|
-
let pasteActive = false;
|
|
13
|
-
let pasteBuffer = "";
|
|
14
|
-
let pasteRemainder = "";
|
|
15
|
-
let suppressKeypress = false;
|
|
16
|
-
let suppressReset = null;
|
|
17
|
-
|
|
18
|
-
function keepMarkerPrefixTail(text, marker) {
|
|
19
|
-
const max = Math.min(marker.length - 1, text.length);
|
|
20
|
-
for (let len = max; len > 0; len -= 1) {
|
|
21
|
-
if (text.endsWith(marker.slice(0, len))) {
|
|
22
|
-
return text.slice(-len);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
return "";
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function scheduleSuppressReset() {
|
|
29
|
-
suppressKeypress = true;
|
|
30
|
-
if (suppressReset) clearImmediateFn(suppressReset);
|
|
31
|
-
suppressReset = setImmediateFn(() => {
|
|
32
|
-
if (!pasteActive) suppressKeypress = false;
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function handleProgramData(data) {
|
|
37
|
-
if (!shouldHandle()) return;
|
|
38
|
-
let buffer = pasteRemainder + data.toString("utf8");
|
|
39
|
-
pasteRemainder = "";
|
|
40
|
-
while (buffer.length > 0) {
|
|
41
|
-
if (!pasteActive) {
|
|
42
|
-
const start = buffer.indexOf(PASTE_START);
|
|
43
|
-
if (start === -1) {
|
|
44
|
-
pasteRemainder = keepMarkerPrefixTail(buffer, PASTE_START);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
buffer = buffer.slice(start + PASTE_START.length);
|
|
48
|
-
pasteActive = true;
|
|
49
|
-
pasteBuffer = "";
|
|
50
|
-
scheduleSuppressReset();
|
|
51
|
-
continue;
|
|
52
|
-
}
|
|
53
|
-
const end = buffer.indexOf(PASTE_END);
|
|
54
|
-
if (end === -1) {
|
|
55
|
-
pasteBuffer += buffer;
|
|
56
|
-
scheduleSuppressReset();
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
pasteBuffer += buffer.slice(0, end);
|
|
60
|
-
buffer = buffer.slice(end + PASTE_END.length);
|
|
61
|
-
pasteActive = false;
|
|
62
|
-
scheduleSuppressReset();
|
|
63
|
-
const normalized = normalizePaste(pasteBuffer);
|
|
64
|
-
pasteBuffer = "";
|
|
65
|
-
if (normalized) insertTextAtCursor(normalized);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function isSuppressKeypress() {
|
|
70
|
-
return suppressKeypress;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return {
|
|
74
|
-
handleProgramData,
|
|
75
|
-
isSuppressKeypress,
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
module.exports = {
|
|
80
|
-
createPasteController,
|
|
81
|
-
};
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
function createStatusLineController(options = {}) {
|
|
2
|
-
const {
|
|
3
|
-
statusLine,
|
|
4
|
-
bannerText = "",
|
|
5
|
-
renderScreen = () => {},
|
|
6
|
-
setIntervalFn = setInterval,
|
|
7
|
-
clearIntervalFn = clearInterval,
|
|
8
|
-
now = () => Date.now(),
|
|
9
|
-
} = options;
|
|
10
|
-
|
|
11
|
-
if (!statusLine) {
|
|
12
|
-
throw new Error("createStatusLineController requires statusLine");
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
const pendingStatusLines = [];
|
|
16
|
-
const busStatusQueue = [];
|
|
17
|
-
let primaryStatusText = bannerText;
|
|
18
|
-
let primaryStatusPending = false;
|
|
19
|
-
|
|
20
|
-
const shimmerStart = now();
|
|
21
|
-
let animationTimer = null;
|
|
22
|
-
const STATUS_ANIM_FRAME_MS = 50;
|
|
23
|
-
const SHIMMER_PADDING = 10;
|
|
24
|
-
const SHIMMER_BAND_HALF_WIDTH = 5;
|
|
25
|
-
const SHIMMER_SWEEP_MS = 2000;
|
|
26
|
-
const SPINNER_PERIOD_MS = 600;
|
|
27
|
-
|
|
28
|
-
function formatProcessingText(text) {
|
|
29
|
-
if (!text) return text;
|
|
30
|
-
if (text.includes("{")) return text;
|
|
31
|
-
if (!/processing/i.test(text)) return text;
|
|
32
|
-
return text;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function shimmerText(text, nowMs) {
|
|
36
|
-
if (!text) return "";
|
|
37
|
-
if (text.includes("{")) return text;
|
|
38
|
-
const chars = Array.from(text);
|
|
39
|
-
const period = chars.length + SHIMMER_PADDING * 2;
|
|
40
|
-
const pos = Math.floor(((nowMs - shimmerStart) % SHIMMER_SWEEP_MS) / SHIMMER_SWEEP_MS * period);
|
|
41
|
-
let out = "";
|
|
42
|
-
for (let i = 0; i < chars.length; i += 1) {
|
|
43
|
-
const iPos = i + SHIMMER_PADDING;
|
|
44
|
-
const dist = Math.abs(iPos - pos);
|
|
45
|
-
let intensity = 0;
|
|
46
|
-
if (dist <= SHIMMER_BAND_HALF_WIDTH) {
|
|
47
|
-
const x = Math.PI * (dist / SHIMMER_BAND_HALF_WIDTH);
|
|
48
|
-
intensity = 0.5 * (1 + Math.cos(x));
|
|
49
|
-
}
|
|
50
|
-
const ch = chars[i];
|
|
51
|
-
if (intensity < 0.2) {
|
|
52
|
-
out += `{gray-fg}${ch}{/gray-fg}`;
|
|
53
|
-
} else if (intensity < 0.6) {
|
|
54
|
-
out += ch;
|
|
55
|
-
} else {
|
|
56
|
-
out += `{bold}{white-fg}${ch}{/white-fg}{/bold}`;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
return out;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
function spinnerFrame(nowMs) {
|
|
63
|
-
const on = Math.floor((nowMs - shimmerStart) / SPINNER_PERIOD_MS) % 2 === 0;
|
|
64
|
-
return on ? "{gray-fg}•{/gray-fg}" : "{gray-fg}◦{/gray-fg}";
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function renderPendingStatus(text, nowMs) {
|
|
68
|
-
const spinner = spinnerFrame(nowMs);
|
|
69
|
-
const shimmer = shimmerText(text, nowMs);
|
|
70
|
-
return shimmer ? `${spinner} ${shimmer}` : spinner;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function renderStatusLine(nowMs = now()) {
|
|
74
|
-
let content = primaryStatusText || "";
|
|
75
|
-
if (primaryStatusPending) {
|
|
76
|
-
content = renderPendingStatus(primaryStatusText, nowMs);
|
|
77
|
-
}
|
|
78
|
-
if (busStatusQueue.length > 0) {
|
|
79
|
-
const extra = busStatusQueue.length > 1
|
|
80
|
-
? ` {gray-fg}(+${busStatusQueue.length - 1}){/gray-fg}`
|
|
81
|
-
: "";
|
|
82
|
-
const busText = `${busStatusQueue[0].text}${extra}`;
|
|
83
|
-
content = content
|
|
84
|
-
? `${content} {gray-fg}·{/gray-fg} ${busText}`
|
|
85
|
-
: busText;
|
|
86
|
-
}
|
|
87
|
-
statusLine.setContent(content);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function updateAnimation() {
|
|
91
|
-
if (primaryStatusPending && !animationTimer) {
|
|
92
|
-
animationTimer = setIntervalFn(() => {
|
|
93
|
-
if (!primaryStatusPending) return;
|
|
94
|
-
renderStatusLine(now());
|
|
95
|
-
renderScreen();
|
|
96
|
-
}, STATUS_ANIM_FRAME_MS);
|
|
97
|
-
} else if (!primaryStatusPending && animationTimer) {
|
|
98
|
-
clearIntervalFn(animationTimer);
|
|
99
|
-
animationTimer = null;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function setPrimaryStatus(text, options = {}) {
|
|
104
|
-
primaryStatusText = text || "";
|
|
105
|
-
primaryStatusPending = Boolean(options.pending);
|
|
106
|
-
updateAnimation();
|
|
107
|
-
renderStatusLine();
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function normalizePendingItem(text, options = {}) {
|
|
111
|
-
const key = options && typeof options.key === "string"
|
|
112
|
-
? options.key.trim()
|
|
113
|
-
: "";
|
|
114
|
-
return {
|
|
115
|
-
text: text || "",
|
|
116
|
-
key,
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function headPendingText() {
|
|
121
|
-
if (pendingStatusLines.length === 0) return "";
|
|
122
|
-
const item = pendingStatusLines[0];
|
|
123
|
-
return item && typeof item.text === "string" ? item.text : "";
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function queueStatusLine(text, options = {}) {
|
|
127
|
-
const item = normalizePendingItem(text, options);
|
|
128
|
-
if (item.key) {
|
|
129
|
-
const existingIndex = pendingStatusLines.findIndex((entry) => entry.key === item.key);
|
|
130
|
-
if (existingIndex >= 0) {
|
|
131
|
-
pendingStatusLines[existingIndex] = item;
|
|
132
|
-
if (existingIndex === 0) {
|
|
133
|
-
setPrimaryStatus(item.text, { pending: true });
|
|
134
|
-
renderScreen();
|
|
135
|
-
}
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
pendingStatusLines.push(item);
|
|
141
|
-
if (pendingStatusLines.length === 1) {
|
|
142
|
-
setPrimaryStatus(item.text, { pending: true });
|
|
143
|
-
renderScreen();
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function resolveStatusLine(text, options = {}) {
|
|
148
|
-
const key = options && typeof options.key === "string"
|
|
149
|
-
? options.key.trim()
|
|
150
|
-
: "";
|
|
151
|
-
let removedHead = false;
|
|
152
|
-
|
|
153
|
-
if (pendingStatusLines.length > 0) {
|
|
154
|
-
if (key) {
|
|
155
|
-
const index = pendingStatusLines.findIndex((entry) => entry.key === key);
|
|
156
|
-
if (index >= 0) {
|
|
157
|
-
pendingStatusLines.splice(index, 1);
|
|
158
|
-
removedHead = index === 0;
|
|
159
|
-
}
|
|
160
|
-
} else {
|
|
161
|
-
pendingStatusLines.shift();
|
|
162
|
-
removedHead = true;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
if (pendingStatusLines.length > 0) {
|
|
167
|
-
if (removedHead || !primaryStatusPending) {
|
|
168
|
-
setPrimaryStatus(headPendingText(), { pending: true });
|
|
169
|
-
}
|
|
170
|
-
} else {
|
|
171
|
-
setPrimaryStatus(text || "", { pending: false });
|
|
172
|
-
}
|
|
173
|
-
renderScreen();
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function enqueueBusStatus(item) {
|
|
177
|
-
if (!item || !item.text) return;
|
|
178
|
-
const key = item.key || item.text;
|
|
179
|
-
const formatted = formatProcessingText(item.text);
|
|
180
|
-
const existing = busStatusQueue.find((entry) => entry.key === key);
|
|
181
|
-
if (existing) {
|
|
182
|
-
existing.text = formatted;
|
|
183
|
-
} else {
|
|
184
|
-
busStatusQueue.push({ key, text: formatted });
|
|
185
|
-
}
|
|
186
|
-
renderStatusLine();
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
function resolveBusStatus(item) {
|
|
190
|
-
if (!item) return;
|
|
191
|
-
const key = item.key || item.text;
|
|
192
|
-
let index = -1;
|
|
193
|
-
if (key) {
|
|
194
|
-
index = busStatusQueue.findIndex((entry) => entry.key === key);
|
|
195
|
-
}
|
|
196
|
-
if (index === -1 && item.text) {
|
|
197
|
-
index = busStatusQueue.findIndex((entry) => entry.text === item.text);
|
|
198
|
-
}
|
|
199
|
-
if (index === -1) return;
|
|
200
|
-
busStatusQueue.splice(index, 1);
|
|
201
|
-
renderStatusLine();
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function destroy() {
|
|
205
|
-
if (animationTimer) {
|
|
206
|
-
clearIntervalFn(animationTimer);
|
|
207
|
-
animationTimer = null;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
return {
|
|
212
|
-
queueStatusLine,
|
|
213
|
-
resolveStatusLine,
|
|
214
|
-
enqueueBusStatus,
|
|
215
|
-
resolveBusStatus,
|
|
216
|
-
renderStatusLine,
|
|
217
|
-
destroy,
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
module.exports = {
|
|
222
|
-
createStatusLineController,
|
|
223
|
-
};
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
const { renderMarkdownLines } = require("../shared/markdownRenderer");
|
|
2
|
-
|
|
3
|
-
function createStreamTracker(options = {}) {
|
|
4
|
-
const {
|
|
5
|
-
logBox,
|
|
6
|
-
writeSpacer,
|
|
7
|
-
appendHistory,
|
|
8
|
-
escapeBlessed,
|
|
9
|
-
onStreamStart,
|
|
10
|
-
now = () => new Date().toISOString(),
|
|
11
|
-
} = options;
|
|
12
|
-
|
|
13
|
-
const streamStates = new Map();
|
|
14
|
-
const pendingDeliveries = new Map();
|
|
15
|
-
|
|
16
|
-
function renderLine(line, mdState) {
|
|
17
|
-
const rendered = renderMarkdownLines(line, mdState, escapeBlessed);
|
|
18
|
-
return rendered.length > 0 ? rendered[0] : escapeBlessed(line);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function buildStreamDisplayText(fullText, prefix, continuationPrefix) {
|
|
22
|
-
const mdState = {};
|
|
23
|
-
const lines = String(fullText || "").split("\n");
|
|
24
|
-
return lines.map((line, i) => {
|
|
25
|
-
const p = i === 0 ? prefix : continuationPrefix;
|
|
26
|
-
return `${p}${renderLine(line, mdState)}`;
|
|
27
|
-
}).join("\n");
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function beginStream(publisher, prefix, continuationPrefix, meta) {
|
|
31
|
-
let state = streamStates.get(publisher);
|
|
32
|
-
if (state) return state;
|
|
33
|
-
|
|
34
|
-
if (typeof writeSpacer === "function") {
|
|
35
|
-
writeSpacer();
|
|
36
|
-
}
|
|
37
|
-
logBox.pushLine(prefix);
|
|
38
|
-
state = {
|
|
39
|
-
publisher,
|
|
40
|
-
prefix,
|
|
41
|
-
continuationPrefix,
|
|
42
|
-
lineIndex: logBox.getLines().length - 1,
|
|
43
|
-
buffer: "",
|
|
44
|
-
full: "",
|
|
45
|
-
linesEmitted: 0,
|
|
46
|
-
meta,
|
|
47
|
-
mdState: {},
|
|
48
|
-
};
|
|
49
|
-
streamStates.set(publisher, state);
|
|
50
|
-
if (typeof onStreamStart === "function") {
|
|
51
|
-
onStreamStart();
|
|
52
|
-
}
|
|
53
|
-
return state;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function appendStreamDelta(state, delta) {
|
|
57
|
-
if (!delta || !state) return;
|
|
58
|
-
state.full += delta;
|
|
59
|
-
state.buffer += delta;
|
|
60
|
-
const parts = state.buffer.split("\n");
|
|
61
|
-
if (parts.length > 1) {
|
|
62
|
-
const completed = parts.slice(0, -1);
|
|
63
|
-
for (const line of completed) {
|
|
64
|
-
const prefix = state.linesEmitted === 0 ? state.prefix : state.continuationPrefix;
|
|
65
|
-
logBox.setLine(state.lineIndex, `${prefix}${renderLine(line, state.mdState)}`);
|
|
66
|
-
state.linesEmitted += 1;
|
|
67
|
-
logBox.pushLine(state.continuationPrefix);
|
|
68
|
-
state.lineIndex = logBox.getLines().length - 1;
|
|
69
|
-
}
|
|
70
|
-
state.buffer = parts[parts.length - 1];
|
|
71
|
-
}
|
|
72
|
-
const prefix = state.linesEmitted === 0 ? state.prefix : state.continuationPrefix;
|
|
73
|
-
// For the current incomplete line, render with a snapshot of mdState
|
|
74
|
-
// to avoid mutating state on partial lines
|
|
75
|
-
const snapState = { inCodeBlock: state.mdState.inCodeBlock };
|
|
76
|
-
logBox.setLine(state.lineIndex, `${prefix}${renderLine(state.buffer, snapState)}`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function finalizeStream(publisher, meta, reason = "") {
|
|
80
|
-
const state = streamStates.get(publisher);
|
|
81
|
-
if (!state) return;
|
|
82
|
-
const text = buildStreamDisplayText(state.full, state.prefix, state.continuationPrefix);
|
|
83
|
-
appendHistory({
|
|
84
|
-
ts: now(),
|
|
85
|
-
type: "bus",
|
|
86
|
-
text,
|
|
87
|
-
meta: { ...(meta || {}), stream_done: true, stream_reason: reason },
|
|
88
|
-
});
|
|
89
|
-
streamStates.delete(publisher);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function hasStream(publisher) {
|
|
93
|
-
return streamStates.has(publisher);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function markPendingDelivery(agentId, agentLabel) {
|
|
97
|
-
const key = agentId || agentLabel;
|
|
98
|
-
if (!key) return;
|
|
99
|
-
const existing = pendingDeliveries.get(key);
|
|
100
|
-
const state = existing || { count: 0, keys: new Set() };
|
|
101
|
-
state.count += 1;
|
|
102
|
-
if (agentId) {
|
|
103
|
-
pendingDeliveries.set(agentId, state);
|
|
104
|
-
state.keys.add(agentId);
|
|
105
|
-
}
|
|
106
|
-
if (agentLabel && agentLabel !== agentId) {
|
|
107
|
-
pendingDeliveries.set(agentLabel, state);
|
|
108
|
-
state.keys.add(agentLabel);
|
|
109
|
-
}
|
|
110
|
-
if (!agentId && !agentLabel) {
|
|
111
|
-
pendingDeliveries.set(key, state);
|
|
112
|
-
state.keys.add(key);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function getPendingState(publisher, displayName) {
|
|
117
|
-
if (publisher && pendingDeliveries.has(publisher)) {
|
|
118
|
-
return { key: publisher, state: pendingDeliveries.get(publisher) };
|
|
119
|
-
}
|
|
120
|
-
if (displayName && pendingDeliveries.has(displayName)) {
|
|
121
|
-
return { key: displayName, state: pendingDeliveries.get(displayName) };
|
|
122
|
-
}
|
|
123
|
-
return null;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function consumePendingDelivery(publisher, displayName) {
|
|
127
|
-
const hit = getPendingState(publisher, displayName);
|
|
128
|
-
if (!hit) return false;
|
|
129
|
-
const state = hit.state;
|
|
130
|
-
state.count -= 1;
|
|
131
|
-
if (state.count <= 0) {
|
|
132
|
-
for (const key of state.keys || []) {
|
|
133
|
-
pendingDeliveries.delete(key);
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
return true;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function discardAll() {
|
|
140
|
-
streamStates.clear();
|
|
141
|
-
pendingDeliveries.clear();
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
return {
|
|
145
|
-
beginStream,
|
|
146
|
-
appendStreamDelta,
|
|
147
|
-
finalizeStream,
|
|
148
|
-
hasStream,
|
|
149
|
-
discardAll,
|
|
150
|
-
markPendingDelivery,
|
|
151
|
-
getPendingState,
|
|
152
|
-
consumePendingDelivery,
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
module.exports = { createStreamTracker };
|
package/src/code/config
DELETED
|
File without changes
|