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/config.js
CHANGED
|
@@ -8,10 +8,16 @@ const SETTINGS_MODEL_DEFAULTS = Object.freeze({
|
|
|
8
8
|
agent: Object.freeze({
|
|
9
9
|
codex: "gpt-5.5",
|
|
10
10
|
claude: "opus-4.7",
|
|
11
|
+
// agy (Antigravity CLI) only supports model selection via in-REPL
|
|
12
|
+
// `/model` slash command, which persists across launches. There is no
|
|
13
|
+
// command-line flag for model, so the value here is a placeholder for
|
|
14
|
+
// display; we never pass it on the agy command line.
|
|
15
|
+
agy: "",
|
|
11
16
|
}),
|
|
12
17
|
router: Object.freeze({
|
|
13
18
|
codex: "gpt-5.3-codex-spark",
|
|
14
19
|
claude: "sonnet-4.7",
|
|
20
|
+
agy: "",
|
|
15
21
|
}),
|
|
16
22
|
});
|
|
17
23
|
|
|
@@ -42,7 +48,6 @@ const DEFAULT_UCODE_CONFIG = {
|
|
|
42
48
|
function normalizeLaunchMode(value) {
|
|
43
49
|
if (value === "auto") return "auto";
|
|
44
50
|
if (value === "internal") return "internal";
|
|
45
|
-
if (value === "internal-pty") return "internal-pty";
|
|
46
51
|
if (value === "tmux") return "tmux";
|
|
47
52
|
if (value === "terminal") return "terminal";
|
|
48
53
|
if (value === "host") return "host";
|
|
@@ -51,12 +56,14 @@ function normalizeLaunchMode(value) {
|
|
|
51
56
|
|
|
52
57
|
function normalizeAgentProvider(value) {
|
|
53
58
|
if (value === "claude-cli") return "claude-cli";
|
|
59
|
+
if (value === "agy-cli" || value === "agy" || value === "antigravity") return "agy-cli";
|
|
54
60
|
return "codex-cli";
|
|
55
61
|
}
|
|
56
62
|
|
|
57
63
|
function providerKey(value = "") {
|
|
58
64
|
const text = String(value || "").trim().toLowerCase();
|
|
59
65
|
if (text === "claude" || text === "claude-cli" || text === "claude-code" || text === "anthropic") return "claude";
|
|
66
|
+
if (text === "agy" || text === "agy-cli" || text === "antigravity") return "agy";
|
|
60
67
|
return "codex";
|
|
61
68
|
}
|
|
62
69
|
|
|
@@ -69,7 +76,12 @@ function defaultAgentModelForProvider(value = "") {
|
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
function defaultRouterProviderForAgentProvider(value = "") {
|
|
72
|
-
|
|
79
|
+
const key = providerKey(value);
|
|
80
|
+
if (key === "claude") return "claude";
|
|
81
|
+
// agy has no router-model API; fall back to codex (the controller still
|
|
82
|
+
// routes via codex/claude regardless of which agent provider runs).
|
|
83
|
+
if (key === "agy") return "codex";
|
|
84
|
+
return "codex";
|
|
73
85
|
}
|
|
74
86
|
|
|
75
87
|
function defaultRouterModelForProvider(value = "") {
|
|
@@ -256,6 +268,7 @@ module.exports = {
|
|
|
256
268
|
saveGlobalUcodeConfig,
|
|
257
269
|
normalizeLaunchMode,
|
|
258
270
|
normalizeAgentProvider,
|
|
271
|
+
providerKey,
|
|
259
272
|
sameModelProvider,
|
|
260
273
|
defaultAgentModelForProvider,
|
|
261
274
|
defaultRouterProviderForAgentProvider,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const fs = require("fs");
|
|
2
|
-
const { getUfooPaths } = require("../
|
|
2
|
+
const { getUfooPaths } = require("../state/paths");
|
|
3
3
|
const { spawn, spawnSync } = require("child_process");
|
|
4
|
-
const { createTerminalAdapterRouter } = require("
|
|
4
|
+
const { createTerminalAdapterRouter } = require("../../runtime/terminal/adapterRouter");
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* 激活指定 agent 的终端
|
|
@@ -4,8 +4,15 @@ const { readJSON, writeJSON, isPidAlive, isAgentPidAlive, isMetaActive, ensureDi
|
|
|
4
4
|
const Injector = require("./inject");
|
|
5
5
|
const QueueManager = require("./queue");
|
|
6
6
|
const MessageManager = require("./message");
|
|
7
|
-
const { createTerminalAdapterRouter } = require("
|
|
8
|
-
const {
|
|
7
|
+
const { createTerminalAdapterRouter } = require("../../runtime/terminal/adapterRouter");
|
|
8
|
+
const {
|
|
9
|
+
INJECTION_MODES,
|
|
10
|
+
getInjectionModeFromEvent,
|
|
11
|
+
} = require("./messageMeta");
|
|
12
|
+
const {
|
|
13
|
+
buildPromptInjectionText,
|
|
14
|
+
shouldRenderPromptEnvelope,
|
|
15
|
+
} = require("./promptEnvelope");
|
|
9
16
|
|
|
10
17
|
function isBusyActivityState(value = "") {
|
|
11
18
|
const state = String(value || "").trim().toLowerCase();
|
|
@@ -128,7 +135,7 @@ class BusDaemon {
|
|
|
128
135
|
const child = spawn(
|
|
129
136
|
process.execPath,
|
|
130
137
|
[
|
|
131
|
-
path.join(__dirname, "..", "..", "bin", "ufoo.js"),
|
|
138
|
+
path.join(__dirname, "..", "..", "..", "bin", "ufoo.js"),
|
|
132
139
|
"bus",
|
|
133
140
|
"daemon",
|
|
134
141
|
"--interval",
|
|
@@ -293,7 +300,7 @@ class BusDaemon {
|
|
|
293
300
|
const launchMode = meta?.launch_mode || "";
|
|
294
301
|
// Delivery ownership:
|
|
295
302
|
// - notifier/injector: terminal/tmux
|
|
296
|
-
// - internal queue loop: internal
|
|
303
|
+
// - internal queue loop: internal
|
|
297
304
|
// Bus daemon only handles legacy/unknown launch modes.
|
|
298
305
|
const adapter = this.adapterRouter.getAdapter({ launchMode, agentId: subscriber, meta });
|
|
299
306
|
const { supportsNotifierInjector, supportsInternalQueueLoop } = adapter.capabilities;
|
|
@@ -348,8 +355,9 @@ class BusDaemon {
|
|
|
348
355
|
continue;
|
|
349
356
|
}
|
|
350
357
|
try {
|
|
358
|
+
const injectionText = buildPromptInjectionText(evt, subscriber, busData.agents || {});
|
|
351
359
|
// eslint-disable-next-line no-await-in-loop
|
|
352
|
-
await this.injector.inject(subscriber,
|
|
360
|
+
await this.injector.inject(subscriber, injectionText);
|
|
353
361
|
deliveredCount += 1;
|
|
354
362
|
currentActivityState = "working";
|
|
355
363
|
this.lastWorkingAt.set(subscriber, Date.now());
|
|
@@ -523,3 +531,5 @@ class BusDaemon {
|
|
|
523
531
|
}
|
|
524
532
|
|
|
525
533
|
module.exports = BusDaemon;
|
|
534
|
+
module.exports.buildPromptInjectionText = buildPromptInjectionText;
|
|
535
|
+
module.exports.shouldRenderPromptEnvelope = shouldRenderPromptEnvelope;
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const ACTION_TAGS = ["reply", "report", "fyi"];
|
|
4
|
+
const ACTION_TAG_SET = new Set(ACTION_TAGS);
|
|
5
|
+
const MUTUALLY_EXCLUSIVE_WITH_FYI = new Set(["reply", "report"]);
|
|
6
|
+
|
|
7
|
+
const TAG_RENDER_ORDER = ["reply", "report", "fyi"];
|
|
8
|
+
const MAX_TAG_COUNT = 8;
|
|
9
|
+
|
|
10
|
+
const TASK_ID_PATTERN = /^[A-Za-z0-9_.\-]+$/;
|
|
11
|
+
const TASK_ID_MAX_LENGTH = 64;
|
|
12
|
+
|
|
13
|
+
function asTrimmedString(value) {
|
|
14
|
+
return typeof value === "string" ? value.trim() : "";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function normalizeTagList(input) {
|
|
18
|
+
if (input == null) return [];
|
|
19
|
+
const list = Array.isArray(input) ? input : String(input).split(/[\s,]+/);
|
|
20
|
+
const seen = new Set();
|
|
21
|
+
const out = [];
|
|
22
|
+
for (const item of list) {
|
|
23
|
+
const tag = asTrimmedString(item).toLowerCase();
|
|
24
|
+
if (!tag) continue;
|
|
25
|
+
if (seen.has(tag)) continue;
|
|
26
|
+
seen.add(tag);
|
|
27
|
+
out.push(tag);
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function validateTags(tags) {
|
|
33
|
+
if (tags.length > MAX_TAG_COUNT) {
|
|
34
|
+
throw new Error(`Too many tags (max ${MAX_TAG_COUNT}): ${tags.join(", ")}`);
|
|
35
|
+
}
|
|
36
|
+
for (const tag of tags) {
|
|
37
|
+
if (!ACTION_TAG_SET.has(tag)) {
|
|
38
|
+
throw new Error(`Unknown tag "${tag}". Allowed action tags: ${ACTION_TAGS.join(", ")}`);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (tags.includes("fyi")) {
|
|
42
|
+
const conflicts = tags.filter((tag) => MUTUALLY_EXCLUSIVE_WITH_FYI.has(tag));
|
|
43
|
+
if (conflicts.length > 0) {
|
|
44
|
+
throw new Error(`[fyi] is mutually exclusive with [${conflicts.join("], [")}]`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function validateTaskId(taskId) {
|
|
50
|
+
const id = asTrimmedString(taskId);
|
|
51
|
+
if (!id) return "";
|
|
52
|
+
if (id.length > TASK_ID_MAX_LENGTH) {
|
|
53
|
+
throw new Error(`task_id too long (max ${TASK_ID_MAX_LENGTH}): "${id}"`);
|
|
54
|
+
}
|
|
55
|
+
if (!TASK_ID_PATTERN.test(id)) {
|
|
56
|
+
throw new Error(`task_id contains invalid characters (allowed: A-Z a-z 0-9 _ . -): "${id}"`);
|
|
57
|
+
}
|
|
58
|
+
return id;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function sortTagsForRender(tags) {
|
|
62
|
+
const order = new Map(TAG_RENDER_ORDER.map((tag, index) => [tag, index]));
|
|
63
|
+
return tags.slice().sort((a, b) => {
|
|
64
|
+
const ai = order.has(a) ? order.get(a) : TAG_RENDER_ORDER.length;
|
|
65
|
+
const bi = order.has(b) ? order.get(b) : TAG_RENDER_ORDER.length;
|
|
66
|
+
if (ai !== bi) return ai - bi;
|
|
67
|
+
return a.localeCompare(b);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function parseTagsFromOptions(options = {}) {
|
|
72
|
+
const opts = options && typeof options === "object" ? options : {};
|
|
73
|
+
const collected = [];
|
|
74
|
+
if (opts.reply) collected.push("reply");
|
|
75
|
+
if (opts.report) collected.push("report");
|
|
76
|
+
if (opts.fyi) collected.push("fyi");
|
|
77
|
+
|
|
78
|
+
if (Array.isArray(opts.tags)) {
|
|
79
|
+
for (const tag of opts.tags) {
|
|
80
|
+
const value = asTrimmedString(tag).toLowerCase();
|
|
81
|
+
if (value) collected.push(value);
|
|
82
|
+
}
|
|
83
|
+
} else if (typeof opts.tags === "string") {
|
|
84
|
+
for (const tag of opts.tags.split(/[\s,]+/)) {
|
|
85
|
+
const value = asTrimmedString(tag).toLowerCase();
|
|
86
|
+
if (value) collected.push(value);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const tags = normalizeTagList(collected);
|
|
91
|
+
validateTags(tags);
|
|
92
|
+
|
|
93
|
+
const taskId = validateTaskId(opts.taskId || opts.task_id || opts.task);
|
|
94
|
+
const reportTo = asTrimmedString(opts.reportTo || opts.report_to);
|
|
95
|
+
|
|
96
|
+
return { tags, taskId, reportTo };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function formatTagList({ tags = [], taskId = "" } = {}) {
|
|
100
|
+
const segments = [];
|
|
101
|
+
for (const tag of sortTagsForRender(tags)) {
|
|
102
|
+
segments.push(`[${tag}]`);
|
|
103
|
+
}
|
|
104
|
+
const id = asTrimmedString(taskId);
|
|
105
|
+
if (id) segments.push(`[task:${id}]`);
|
|
106
|
+
return segments.join(" ");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function buildPartyLabel({ id = "", nickname = "" } = {}) {
|
|
110
|
+
const trimmedId = asTrimmedString(id);
|
|
111
|
+
const trimmedNickname = asTrimmedString(nickname);
|
|
112
|
+
if (!trimmedId && !trimmedNickname) return "";
|
|
113
|
+
if (trimmedId && trimmedNickname && trimmedId !== trimmedNickname) {
|
|
114
|
+
return `${trimmedId}(${trimmedNickname})`;
|
|
115
|
+
}
|
|
116
|
+
return trimmedId || trimmedNickname;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function renderHeader({
|
|
120
|
+
kind = "bus",
|
|
121
|
+
fromId = "",
|
|
122
|
+
fromNickname = "",
|
|
123
|
+
toId = "",
|
|
124
|
+
toNickname = "",
|
|
125
|
+
tags = [],
|
|
126
|
+
taskId = "",
|
|
127
|
+
} = {}) {
|
|
128
|
+
let prefix;
|
|
129
|
+
let partyLabel;
|
|
130
|
+
if (kind === "manual") {
|
|
131
|
+
prefix = "[manual]<to:";
|
|
132
|
+
partyLabel = buildPartyLabel({ id: toId, nickname: toNickname });
|
|
133
|
+
} else {
|
|
134
|
+
prefix = "[ufoo]<from:";
|
|
135
|
+
partyLabel = buildPartyLabel({ id: fromId, nickname: fromNickname });
|
|
136
|
+
}
|
|
137
|
+
if (!partyLabel) partyLabel = "unknown";
|
|
138
|
+
|
|
139
|
+
const tagSegment = formatTagList({ tags, taskId });
|
|
140
|
+
const head = `${prefix}${partyLabel}>`;
|
|
141
|
+
return tagSegment ? `${head} ${tagSegment}` : head;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function renderEnvelope({
|
|
145
|
+
kind = "bus",
|
|
146
|
+
fromId = "",
|
|
147
|
+
fromNickname = "",
|
|
148
|
+
toId = "",
|
|
149
|
+
toNickname = "",
|
|
150
|
+
tags = [],
|
|
151
|
+
taskId = "",
|
|
152
|
+
message = "",
|
|
153
|
+
} = {}) {
|
|
154
|
+
const header = renderHeader({ kind, fromId, fromNickname, toId, toNickname, tags, taskId });
|
|
155
|
+
const body = String(message || "");
|
|
156
|
+
return body ? `${header}\n${body}` : header;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
module.exports = {
|
|
160
|
+
ACTION_TAGS,
|
|
161
|
+
TAG_RENDER_ORDER,
|
|
162
|
+
MAX_TAG_COUNT,
|
|
163
|
+
TASK_ID_PATTERN,
|
|
164
|
+
TASK_ID_MAX_LENGTH,
|
|
165
|
+
normalizeTagList,
|
|
166
|
+
validateTags,
|
|
167
|
+
validateTaskId,
|
|
168
|
+
sortTagsForRender,
|
|
169
|
+
parseTagsFromOptions,
|
|
170
|
+
formatTagList,
|
|
171
|
+
renderHeader,
|
|
172
|
+
renderEnvelope,
|
|
173
|
+
};
|
|
@@ -16,7 +16,7 @@ const {
|
|
|
16
16
|
sleep,
|
|
17
17
|
} = require("./utils");
|
|
18
18
|
const { shakeTerminalByTty } = require("./shake");
|
|
19
|
-
const { resolveDisplayNickname } = require("
|
|
19
|
+
const { resolveDisplayNickname } = require("../../runtime/daemon/nicknameScope");
|
|
20
20
|
const QueueManager = require("./queue");
|
|
21
21
|
const SubscriberManager = require("./subscriber");
|
|
22
22
|
const MessageManager = require("./message");
|
|
@@ -319,7 +319,11 @@ class EventBus {
|
|
|
319
319
|
|
|
320
320
|
try {
|
|
321
321
|
const eventName = options.event || "message";
|
|
322
|
-
const data = options.data
|
|
322
|
+
const data = options.data && typeof options.data === "object"
|
|
323
|
+
? { ...options.data }
|
|
324
|
+
: { message };
|
|
325
|
+
if (options.rawInject === true) data.raw_inject = true;
|
|
326
|
+
if (options.envelope === false) data.envelope = false;
|
|
323
327
|
const result = eventName === "message"
|
|
324
328
|
? await this.messageManager.send(target, message, publisher, {
|
|
325
329
|
data,
|
|
@@ -639,7 +643,7 @@ class EventBus {
|
|
|
639
643
|
ensureDir(logDir);
|
|
640
644
|
|
|
641
645
|
const args = [
|
|
642
|
-
path.join(__dirname, "..", "..", "bin", "ufoo.js"),
|
|
646
|
+
path.join(__dirname, "..", "..", "..", "bin", "ufoo.js"),
|
|
643
647
|
"bus",
|
|
644
648
|
"alert",
|
|
645
649
|
subscriber,
|
|
@@ -3,7 +3,7 @@ const fs = require("fs");
|
|
|
3
3
|
const net = require("net");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const { subscriberToSafeName, isValidTty } = require("./utils");
|
|
6
|
-
const { createTerminalAdapterRouter } = require("
|
|
6
|
+
const { createTerminalAdapterRouter } = require("../../runtime/terminal/adapterRouter");
|
|
7
7
|
|
|
8
8
|
const SHOULD_LOG_INJECT = process.env.UFOO_INJECT_DEBUG === "1";
|
|
9
9
|
const logInject = (message) => {
|
|
@@ -415,10 +415,18 @@ class Injector {
|
|
|
415
415
|
throw new Error(`Inject disabled for ${subscriber}. ufoo-code consumes bus internally.`);
|
|
416
416
|
}
|
|
417
417
|
|
|
418
|
-
//
|
|
418
|
+
// 确定注入命令:
|
|
419
|
+
// - codex: 裸 "ubus"(codex 没有 slash-command 命名空间)
|
|
420
|
+
// - agy: 裸 "ubus"(agy 的 `/` 是它自己的 slash-command 命名空间,
|
|
421
|
+
// "/ubus" 会被识别为 unknown slash command 而不是 prompt)
|
|
422
|
+
// - claude-code 及其他: "/ubus"
|
|
419
423
|
const command = commandOverride
|
|
420
424
|
? String(commandOverride)
|
|
421
|
-
: (
|
|
425
|
+
: (
|
|
426
|
+
subscriber.startsWith("codex:") || subscriber.startsWith("agy:")
|
|
427
|
+
? "ubus"
|
|
428
|
+
: "/ubus"
|
|
429
|
+
);
|
|
422
430
|
|
|
423
431
|
const meta = this.getAgentMeta(subscriber) || {};
|
|
424
432
|
const launchMode = meta.launch_mode || "";
|
|
@@ -12,7 +12,7 @@ const {
|
|
|
12
12
|
} = require("./utils");
|
|
13
13
|
const NicknameManager = require("./nickname");
|
|
14
14
|
const { buildMessageData } = require("./messageMeta");
|
|
15
|
-
const { getUfooPaths } = require("../
|
|
15
|
+
const { getUfooPaths } = require("../state/paths");
|
|
16
16
|
|
|
17
17
|
const SEQ_LOCK_TIMEOUT_MS = 5000;
|
|
18
18
|
const SEQ_LOCK_POLL_MS = 25;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
parseTagsFromOptions,
|
|
5
|
+
validateTags,
|
|
6
|
+
validateTaskId,
|
|
7
|
+
normalizeTagList,
|
|
8
|
+
} = require("./envelope");
|
|
9
|
+
|
|
10
|
+
const INJECTION_MODES = {
|
|
11
|
+
IMMEDIATE: "immediate",
|
|
12
|
+
QUEUED: "queued",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
function normalizeInjectionMode(value, fallback = INJECTION_MODES.IMMEDIATE) {
|
|
16
|
+
const raw = String(value || "").trim().toLowerCase();
|
|
17
|
+
if (raw === INJECTION_MODES.QUEUED) return INJECTION_MODES.QUEUED;
|
|
18
|
+
if (raw === INJECTION_MODES.IMMEDIATE) return INJECTION_MODES.IMMEDIATE;
|
|
19
|
+
return fallback;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function normalizeMessageSource(value) {
|
|
23
|
+
const raw = String(value || "").trim();
|
|
24
|
+
return raw || "";
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function asTrimmedString(value) {
|
|
28
|
+
return typeof value === "string" ? value.trim() : "";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function resolveTagsFromOptions(options = {}) {
|
|
32
|
+
const dataIn = options && typeof options.data === "object" && options.data ? options.data : {};
|
|
33
|
+
const hasFlagOption = "reply" in options || "report" in options || "fyi" in options;
|
|
34
|
+
const hasTagsOption = "tags" in options;
|
|
35
|
+
const hasTaskOption = "taskId" in options || "task_id" in options || "task" in options;
|
|
36
|
+
const hasReportToOption = "reportTo" in options || "report_to" in options;
|
|
37
|
+
|
|
38
|
+
if (hasFlagOption || hasTagsOption || hasTaskOption || hasReportToOption) {
|
|
39
|
+
return parseTagsFromOptions(options);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const tags = normalizeTagList(dataIn.tags);
|
|
43
|
+
validateTags(tags);
|
|
44
|
+
const taskId = validateTaskId(dataIn.task_id);
|
|
45
|
+
const reportTo = asTrimmedString(dataIn.report_to);
|
|
46
|
+
return { tags, taskId, reportTo };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function buildMessageData(message, options = {}) {
|
|
50
|
+
const base = options && typeof options.data === "object" && options.data
|
|
51
|
+
? { ...options.data }
|
|
52
|
+
: {};
|
|
53
|
+
const data = { ...base, message };
|
|
54
|
+
data.injection_mode = normalizeInjectionMode(
|
|
55
|
+
options.injectionMode || data.injection_mode,
|
|
56
|
+
INJECTION_MODES.IMMEDIATE,
|
|
57
|
+
);
|
|
58
|
+
const source = normalizeMessageSource(options.source || data.source);
|
|
59
|
+
if (source) {
|
|
60
|
+
data.source = source;
|
|
61
|
+
} else {
|
|
62
|
+
delete data.source;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { tags, taskId, reportTo } = resolveTagsFromOptions(options);
|
|
66
|
+
|
|
67
|
+
if (tags.length > 0) {
|
|
68
|
+
data.tags = tags;
|
|
69
|
+
} else {
|
|
70
|
+
delete data.tags;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (taskId) {
|
|
74
|
+
data.task_id = taskId;
|
|
75
|
+
} else {
|
|
76
|
+
delete data.task_id;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (reportTo) {
|
|
80
|
+
data.report_to = reportTo;
|
|
81
|
+
} else {
|
|
82
|
+
delete data.report_to;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return data;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function getInjectionModeFromEvent(evt, fallback = INJECTION_MODES.IMMEDIATE) {
|
|
89
|
+
const data = evt && typeof evt.data === "object" && evt.data ? evt.data : {};
|
|
90
|
+
return normalizeInjectionMode(
|
|
91
|
+
data.injection_mode || evt?.injection_mode,
|
|
92
|
+
fallback,
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function getTagsFromEvent(evt) {
|
|
97
|
+
const data = evt && typeof evt.data === "object" && evt.data ? evt.data : {};
|
|
98
|
+
const tags = normalizeTagList(data.tags);
|
|
99
|
+
try {
|
|
100
|
+
validateTags(tags);
|
|
101
|
+
} catch {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
return tags;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function getTaskIdFromEvent(evt) {
|
|
108
|
+
const data = evt && typeof evt.data === "object" && evt.data ? evt.data : {};
|
|
109
|
+
try {
|
|
110
|
+
return validateTaskId(data.task_id);
|
|
111
|
+
} catch {
|
|
112
|
+
return "";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function getReportToFromEvent(evt) {
|
|
117
|
+
const data = evt && typeof evt.data === "object" && evt.data ? evt.data : {};
|
|
118
|
+
return asTrimmedString(data.report_to);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = {
|
|
122
|
+
INJECTION_MODES,
|
|
123
|
+
normalizeInjectionMode,
|
|
124
|
+
normalizeMessageSource,
|
|
125
|
+
buildMessageData,
|
|
126
|
+
getInjectionModeFromEvent,
|
|
127
|
+
getTagsFromEvent,
|
|
128
|
+
getTaskIdFromEvent,
|
|
129
|
+
getReportToFromEvent,
|
|
130
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const { getTagsFromEvent, getTaskIdFromEvent } = require("./messageMeta");
|
|
4
|
+
const { renderEnvelope } = require("./envelope");
|
|
5
|
+
|
|
6
|
+
const MANUAL_INJECTION_SOURCES = new Set([
|
|
7
|
+
"chat-direct",
|
|
8
|
+
"chat-internal-agent-view",
|
|
9
|
+
"chat-manual",
|
|
10
|
+
"manual",
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
function asTrimmedString(value) {
|
|
14
|
+
return typeof value === "string" ? value.trim() : "";
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function shouldRenderPromptEnvelope(evt = {}) {
|
|
18
|
+
const data = evt && typeof evt.data === "object" && evt.data ? evt.data : {};
|
|
19
|
+
return data.raw_inject !== true
|
|
20
|
+
&& data.rawInject !== true
|
|
21
|
+
&& data.envelope !== false
|
|
22
|
+
&& data.prompt_envelope !== false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function getPublisherId(evt = {}) {
|
|
26
|
+
const publisher = evt.publisher;
|
|
27
|
+
if (typeof publisher === "string") return publisher;
|
|
28
|
+
if (publisher && typeof publisher === "object") {
|
|
29
|
+
return asTrimmedString(publisher.subscriber || publisher.id || publisher.nickname);
|
|
30
|
+
}
|
|
31
|
+
return "";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function getAgentNickname(meta = {}) {
|
|
35
|
+
return asTrimmedString(meta.display_nickname || meta.nickname || meta.scoped_nickname);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function buildPromptInjectionText(evt = {}, subscriber = "", agents = {}) {
|
|
39
|
+
const data = evt && typeof evt.data === "object" && evt.data ? evt.data : {};
|
|
40
|
+
const message = String(data.message || "");
|
|
41
|
+
if (!shouldRenderPromptEnvelope(evt)) return message;
|
|
42
|
+
|
|
43
|
+
const source = asTrimmedString(data.source).toLowerCase();
|
|
44
|
+
const kind = MANUAL_INJECTION_SOURCES.has(source) ? "manual" : "bus";
|
|
45
|
+
const publisherId = getPublisherId(evt);
|
|
46
|
+
const publisherMeta = publisherId && agents ? agents[publisherId] : null;
|
|
47
|
+
const targetMeta = subscriber && agents ? agents[subscriber] : null;
|
|
48
|
+
|
|
49
|
+
return renderEnvelope({
|
|
50
|
+
kind,
|
|
51
|
+
fromId: publisherId,
|
|
52
|
+
fromNickname: publisherMeta ? getAgentNickname(publisherMeta) : "",
|
|
53
|
+
toId: subscriber,
|
|
54
|
+
toNickname: targetMeta ? getAgentNickname(targetMeta) : "",
|
|
55
|
+
tags: getTagsFromEvent(evt),
|
|
56
|
+
taskId: getTaskIdFromEvent(evt),
|
|
57
|
+
message,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = {
|
|
62
|
+
buildPromptInjectionText,
|
|
63
|
+
getPublisherId,
|
|
64
|
+
shouldRenderPromptEnvelope,
|
|
65
|
+
};
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const { getTimestamp, ensureDir, safeNameToSubscriber, getTtyProcessInfo } = require("./utils");
|
|
6
|
-
const { getUfooPaths } = require("../
|
|
7
|
-
const { loadAgentsData, saveAgentsData } = require("../
|
|
8
|
-
const { appendAgentRegistryDiagnostic } = require("../
|
|
6
|
+
const { getUfooPaths } = require("../state/paths");
|
|
7
|
+
const { loadAgentsData, saveAgentsData } = require("../state/agentsStore");
|
|
8
|
+
const { appendAgentRegistryDiagnostic } = require("../state/agentRegistryDiagnostics");
|
|
9
9
|
|
|
10
10
|
function readQueueTty(queueDir) {
|
|
11
11
|
try {
|
|
@@ -2,7 +2,7 @@ const fs = require("fs");
|
|
|
2
2
|
const { getTimestamp, isAgentPidAlive, isMetaActive, isValidTty, getTtyProcessInfo } = require("./utils");
|
|
3
3
|
const NicknameManager = require("./nickname");
|
|
4
4
|
const { spawnSync } = require("child_process");
|
|
5
|
-
const { appendAgentRegistryDiagnostic } = require("../
|
|
5
|
+
const { appendAgentRegistryDiagnostic } = require("../state/agentRegistryDiagnostics");
|
|
6
6
|
|
|
7
7
|
function detectTerminalAppFromEnv() {
|
|
8
8
|
const termProgram = process.env.TERM_PROGRAM || "";
|
|
@@ -92,7 +92,7 @@ function getJoinedPid() {
|
|
|
92
92
|
|
|
93
93
|
function isInternalLaunchMode(meta) {
|
|
94
94
|
const mode = String(meta?.launch_mode || "").trim();
|
|
95
|
-
return mode === "internal"
|
|
95
|
+
return mode === "internal";
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
function hasProviderSession(meta) {
|
|
@@ -2,8 +2,8 @@ const crypto = require("crypto");
|
|
|
2
2
|
const fs = require("fs");
|
|
3
3
|
const path = require("path");
|
|
4
4
|
const { spawnSync } = require("child_process");
|
|
5
|
-
const { redactSecrets } = require("
|
|
6
|
-
const { appendAgentRegistryDiagnostic } = require("../
|
|
5
|
+
const { redactSecrets } = require("../../runtime/privacy/redactor");
|
|
6
|
+
const { appendAgentRegistryDiagnostic } = require("../state/agentRegistryDiagnostics");
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* 获取当前 UTC 时间戳(ISO 8601 格式)
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const os = require("os");
|
|
5
5
|
const path = require("path");
|
|
6
|
-
const { getUfooPaths } = require("../
|
|
7
|
-
const { loadAgentsData } = require("../
|
|
8
|
-
const { redactSecrets, redactString } = require("
|
|
6
|
+
const { getUfooPaths } = require("../state/paths");
|
|
7
|
+
const { loadAgentsData } = require("../state/agentsStore");
|
|
8
|
+
const { redactSecrets, redactString } = require("../../runtime/privacy/redactor");
|
|
9
9
|
|
|
10
10
|
const HISTORY_DEBUG = process.env.UFOO_HISTORY_DEBUG === "1";
|
|
11
11
|
const debugLog = (...args) => { if (HISTORY_DEBUG) console.error("[history]", ...args); };
|
|
@@ -223,7 +223,7 @@ function extractUserText(record) {
|
|
|
223
223
|
return "";
|
|
224
224
|
}
|
|
225
225
|
|
|
226
|
-
function
|
|
226
|
+
function isLegacyUfooMarker(text) {
|
|
227
227
|
return /^\/ufoo\s+\S+$/.test(text) || /^\$ufoo\s+\S+$/.test(text);
|
|
228
228
|
}
|
|
229
229
|
|
|
@@ -321,7 +321,7 @@ function collectClaudeManualInputs(projectRoot, watermark = {}) {
|
|
|
321
321
|
if (new Date(record.timestamp).getTime() <= cutoffMs) return;
|
|
322
322
|
}
|
|
323
323
|
const text = extractUserText(record);
|
|
324
|
-
if (!text ||
|
|
324
|
+
if (!text || isLegacyUfooMarker(text)) return;
|
|
325
325
|
entries.push({
|
|
326
326
|
ts: record.timestamp || "",
|
|
327
327
|
source: "manual",
|
|
@@ -2,7 +2,7 @@ const fs = require("fs");
|
|
|
2
2
|
const os = require("os");
|
|
3
3
|
const path = require("path");
|
|
4
4
|
|
|
5
|
-
const { redactSecrets, redactString } = require("
|
|
5
|
+
const { redactSecrets, redactString } = require("../../runtime/privacy/redactor");
|
|
6
6
|
|
|
7
7
|
const MAX_RESULTS = 3;
|
|
8
8
|
const MAX_TOTAL_TEXT_CHARS = 2000;
|