nolo-cli 0.1.32 → 0.1.33
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 +0 -6
- package/agent-runtime/agentRecordConfig.ts +2 -0
- package/agent-runtime/hostAdapter.ts +1 -0
- package/agent-runtime/index.ts +0 -21
- package/agent-runtime/localToolPolicy.ts +6 -13
- package/agent-runtime/localWorkspaceTools.ts +30 -333
- package/agent-runtime/platformChatProvider.ts +1 -4
- package/agent-runtime/runtimeToolPolicy.ts +47 -32
- package/agentAliases.ts +14 -83
- package/agentCommandSupport.ts +3 -6
- package/agentInternalCommandEntries.ts +2 -13
- package/agentListCommands.ts +19 -28
- package/agentMachineCommands.ts +40 -336
- package/agentPullCommand.ts +36 -56
- package/agentRecordCommands.ts +3 -5
- package/agentRecordHelpers.ts +22 -189
- package/agentRunCommand.ts +438 -107
- package/agentRuntimeLocal.ts +0 -10
- package/ai/agent/cliExecutor.ts +19 -323
- package/authCommands.ts +2 -36
- package/cli/agentAliases.ts +14 -83
- package/cli/agentCommandSupport.ts +3 -6
- package/cli/agentInternalCommandEntries.ts +2 -13
- package/cli/agentListCommands.ts +19 -28
- package/cli/agentMachineCommands.ts +40 -336
- package/cli/agentPullCommand.ts +36 -56
- package/cli/agentRecordCommands.ts +3 -5
- package/cli/agentRecordHelpers.ts +22 -189
- package/cli/agentRunCommand.ts +438 -107
- package/cli/agentRuntimeLocal.ts +0 -10
- package/cli/authCommands.ts +2 -36
- package/cli/cliEnvHelpers.ts +21 -162
- package/cli/client/agentRun.ts +853 -57
- package/cli/client/localRuntimeAdapter.ts +22 -159
- package/cli/client/streamingOutput.ts +3 -1
- package/cli/client/taskRunPrompt.ts +24 -7
- package/cli/commandRegistry.ts +2 -3
- package/cli/connectorRunArtifact.ts +10 -34
- package/cli/connectorWebSocketTarget.ts +6 -10
- package/cli/internalCommandEntries.ts +0 -8
- package/cli/localRuntimeDb.ts +2 -39
- package/cli/machineCommands.ts +189 -190
- package/cli/machineDaemonCommands.ts +165 -9
- package/cli/machineHeartbeatCommands.ts +2 -1
- package/cli/machineStatusCommands.ts +13 -5
- package/cli/machineWatchCommands.ts +1 -1
- package/cli/machineWsRunDispatch.ts +14 -48
- package/cli/machineWsSession.ts +0 -2
- package/cli/offlineMarxistsAgentCommand.ts +314 -0
- package/cli/runtimeDoctorCommands.ts +69 -18
- package/cli/scriptCommandEntries.ts +45 -5
- package/cli/tableCommands.ts +133 -33
- package/cli/taskRunCommand.ts +211 -16
- package/cli/tui/session.ts +372 -43
- package/cli/workflowInternalCommandEntries.ts +0 -20
- package/cliEnvHelpers.ts +21 -162
- package/client/agentConfigResolver.test.ts +2 -0
- package/client/agentRun.test.ts +12 -208
- package/client/agentRun.ts +853 -57
- package/client/localRuntimeAdapter.test.ts +9 -168
- package/client/localRuntimeAdapter.ts +22 -159
- package/client/localToolPolicy.test.ts +4 -28
- package/client/streamingOutput.ts +3 -1
- package/client/taskRunPrompt.ts +24 -7
- package/commandRegistry.ts +2 -3
- package/connectorRunArtifact.ts +10 -34
- package/connectorWebSocketTarget.ts +6 -10
- package/database/server/db.ts +34 -15
- package/internalCommandEntries.ts +0 -8
- package/localRuntimeDb.ts +2 -39
- package/machineCommands.ts +189 -190
- package/machineDaemonCommands.ts +165 -9
- package/machineHeartbeatCommands.ts +2 -1
- package/machineStatusCommands.ts +13 -5
- package/machineWatchCommands.ts +1 -1
- package/machineWsRunDispatch.ts +14 -48
- package/machineWsSession.ts +0 -2
- package/offlineMarxistsAgentCommand.ts +314 -0
- package/package.json +49 -193
- package/runtimeDoctorCommands.ts +69 -18
- package/scriptCommandEntries.ts +45 -5
- package/tableCommands.ts +133 -33
- package/taskRunCommand.ts +211 -16
- package/tui/session.ts +372 -43
- package/workflowInternalCommandEntries.ts +0 -20
- package/agent-runtime/dialogStatus.ts +0 -139
- package/agent-runtime/hostRuntimeConfig.ts +0 -86
- package/agentCreateCustomCommands.ts +0 -278
- package/agentDialogsCommands.ts +0 -227
- package/agentDoctorCommands.ts +0 -203
- package/agentRunLocalWorkspace.ts +0 -182
- package/agentRunParsing.ts +0 -298
- package/agentSuperviseCommands.ts +0 -8
- package/agentUnpublishCommands.ts +0 -113
- package/ai/agent/agentRunDialogLineage.ts +0 -56
- package/ai/policy/types.ts +0 -64
- package/ai/skills/skillSummaryMarker.ts +0 -26
- package/app/types.ts +0 -358
- package/build.ts +0 -16
- package/buildPublish.ts +0 -138
- package/buildPublishArtifactAssembly.ts +0 -724
- package/buildPublishImportAnalysis.ts +0 -242
- package/chat/messages/fetchMessages.ts +0 -84
- package/chat/messages/types.ts +0 -185
- package/cli/agentCreateCustomCommands.ts +0 -278
- package/cli/agentDialogsCommands.ts +0 -227
- package/cli/agentDoctorCommands.ts +0 -203
- package/cli/agentRunLocalWorkspace.ts +0 -182
- package/cli/agentRunParsing.ts +0 -298
- package/cli/agentSuperviseCommands.ts +0 -8
- package/cli/agentUnpublishCommands.ts +0 -113
- package/cli/buildPublish.ts +0 -138
- package/cli/buildPublishArtifactAssembly.ts +0 -724
- package/cli/buildPublishImportAnalysis.ts +0 -242
- package/cli/cliIoTypes.ts +0 -3
- package/cli/cliRuntimeDoctorReport.ts +0 -193
- package/cli/client/agentRunInput.ts +0 -10
- package/cli/client/agentRunLocalExecution.ts +0 -124
- package/cli/client/agentRunLocalExecutor.ts +0 -179
- package/cli/client/agentRunRuntimeSelection.ts +0 -145
- package/cli/client/agentRunServerTransport.ts +0 -397
- package/cli/client/agentRunTaskRunRecorder.ts +0 -176
- package/cli/customCodingAgentFlow.ts +0 -208
- package/cli/customCodingAgentRecord.ts +0 -179
- package/cli/dialogDataAccess.ts +0 -186
- package/cli/dialogInternalCommandEntries.ts +0 -11
- package/cli/dialogReadCommands.ts +0 -180
- package/cli/dialogReadHelpers.ts +0 -226
- package/cli/dialogStatusCommands.ts +0 -123
- package/cli/docInternalCommandEntries.ts +0 -20
- package/cli/hybridReadHelpers.ts +0 -109
- package/cli/machineCommandPrompts.ts +0 -79
- package/cli/machineCommandResolution.ts +0 -43
- package/cli/noloReadBridgePrompt.ts +0 -16
- package/cli/pageCreateCommands.ts +0 -219
- package/cli/pageDeleteCommands.ts +0 -167
- package/cli/pageReadCommands.ts +0 -151
- package/cli/pageUpdateCommands.ts +0 -249
- package/cli/pageWriteHelpers.ts +0 -209
- package/cli/publishPackage.ts +0 -36
- package/cli/runtimeInternalCommandEntries.ts +0 -15
- package/cli/runtimePassthroughCommands.ts +0 -22
- package/cli/scriptPassthroughHelpers.ts +0 -28
- package/cli/secretScanHelpers.ts +0 -31
- package/cli/spaceAttachCommands.ts +0 -134
- package/cli/spaceCategoryCommands.ts +0 -263
- package/cli/spaceCommands.ts +0 -295
- package/cli/spaceDeleteCommands.ts +0 -312
- package/cli/spaceInternalCommandEntries.ts +0 -21
- package/cli/spaceMutationHelpers.ts +0 -135
- package/cli/spaceReadCommands.ts +0 -323
- package/cli/tableDataOutput.ts +0 -41
- package/cli/tableDataSafety.ts +0 -26
- package/cli/tableMetaCommands.ts +0 -307
- package/cli/tableMutationCommands.ts +0 -266
- package/cli/tableQueryParsing.ts +0 -90
- package/cli/tableQueryRequest.ts +0 -53
- package/cli/taskRunActions.ts +0 -122
- package/cli/taskRunParsing.ts +0 -86
- package/cli/taskRunPromptShared.ts +0 -55
- package/cli/tui/tuiCatalog.ts +0 -22
- package/cli/tui/tuiCommandInterpreter.ts +0 -253
- package/cli/tui/tuiPresentation.ts +0 -146
- package/cliIoTypes.ts +0 -3
- package/cliRuntimeDoctorReport.ts +0 -193
- package/client/agentRunInput.ts +0 -10
- package/client/agentRunLocalExecution.test.ts +0 -123
- package/client/agentRunLocalExecution.ts +0 -124
- package/client/agentRunLocalExecutor.ts +0 -179
- package/client/agentRunRuntimeSelection.test.ts +0 -159
- package/client/agentRunRuntimeSelection.ts +0 -145
- package/client/agentRunServerTransport.ts +0 -397
- package/client/agentRunTaskRunRecorder.ts +0 -176
- package/connector-experimental/daemonLauncher.ts +0 -223
- package/create/space/spaceKeys.ts +0 -65
- package/create/types.ts +0 -21
- package/customCodingAgentFlow.ts +0 -208
- package/customCodingAgentRecord.ts +0 -179
- package/database/keys.ts +0 -765
- package/database/server/authorityStoreTypes.ts +0 -31
- package/database/server/legacyServerDb.ts +0 -58
- package/database/server/levelAuthorityStore.ts +0 -75
- package/database/server/memoryAuthorityStore.ts +0 -133
- package/database/server/serverStoreFactory.ts +0 -124
- package/database/tombstones.ts +0 -52
- package/database/utils/ulid.ts +0 -1
- package/dialogDataAccess.ts +0 -186
- package/dialogInternalCommandEntries.ts +0 -11
- package/dialogReadCommands.ts +0 -180
- package/dialogReadHelpers.ts +0 -226
- package/dialogStatusCommands.ts +0 -123
- package/docInternalCommandEntries.ts +0 -20
- package/hybridReadHelpers.ts +0 -109
- package/machineCommandPrompts.ts +0 -79
- package/machineCommandResolution.ts +0 -43
- package/noloReadBridgePrompt.ts +0 -16
- package/pageCreateCommands.ts +0 -219
- package/pageDeleteCommands.ts +0 -167
- package/pageReadCommands.ts +0 -151
- package/pageUpdateCommands.ts +0 -249
- package/pageWriteHelpers.ts +0 -209
- package/publishPackage.ts +0 -36
- package/runtimeInternalCommandEntries.ts +0 -15
- package/runtimePassthroughCommands.ts +0 -22
- package/scriptPassthroughHelpers.ts +0 -28
- package/secretScanHelpers.ts +0 -31
- package/share/helpers.ts +0 -302
- package/share/keys.ts +0 -243
- package/share/types.ts +0 -100
- package/spaceAttachCommands.ts +0 -134
- package/spaceCategoryCommands.ts +0 -263
- package/spaceCommands.ts +0 -295
- package/spaceDeleteCommands.ts +0 -312
- package/spaceInternalCommandEntries.ts +0 -21
- package/spaceMutationHelpers.ts +0 -135
- package/spaceReadCommands.ts +0 -323
- package/tableDataOutput.ts +0 -41
- package/tableDataSafety.ts +0 -26
- package/tableMetaCommands.ts +0 -307
- package/tableMutationCommands.ts +0 -266
- package/tableQueryParsing.ts +0 -90
- package/tableQueryRequest.ts +0 -53
- package/taskRunActions.ts +0 -122
- package/taskRunParsing.ts +0 -86
- package/taskRunPromptShared.ts +0 -55
- package/tui/tuiCatalog.ts +0 -22
- package/tui/tuiCommandInterpreter.test.ts +0 -169
- package/tui/tuiCommandInterpreter.ts +0 -253
- package/tui/tuiPresentation.test.ts +0 -154
- package/tui/tuiPresentation.ts +0 -146
package/cli/tui/session.ts
CHANGED
|
@@ -1,50 +1,379 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
1
|
+
import { DEFAULT_NOLO_SERVER_URL } from "../defaultServer";
|
|
2
|
+
import type { AgentRuntimeRequestedMode } from "../agentRuntimeLocal";
|
|
3
|
+
|
|
4
|
+
export const DEFAULT_TUI_AGENT_KEY = "agent-pub-01NOLOAPPBLD000000019KCKT0";
|
|
5
|
+
export const DEFAULT_TUI_SERVER_URL = DEFAULT_NOLO_SERVER_URL;
|
|
6
|
+
|
|
7
|
+
const KNOWN_AGENTS: Array<{
|
|
8
|
+
name: string;
|
|
9
|
+
key: string;
|
|
10
|
+
description: string;
|
|
11
|
+
}> = [
|
|
12
|
+
{
|
|
13
|
+
name: "nolo",
|
|
14
|
+
key: "agent-pub-01NOLOAPPBLD000000019KCKT0",
|
|
15
|
+
description: "one assistant that routes work across your agents and data",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
name: "app-builder",
|
|
19
|
+
key: "agent-pub-01APPBUILDER00000001YAII3I",
|
|
20
|
+
description: "builds web apps, tools, charts, and product prototypes",
|
|
21
|
+
},
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const KNOWN_AGENT_ALIASES: Record<string, { name: string; key: string }> =
|
|
25
|
+
Object.fromEntries(KNOWN_AGENTS.map((agent) => [agent.name, agent]));
|
|
26
|
+
|
|
27
|
+
function shortenDialogId(dialogId: string) {
|
|
28
|
+
return dialogId.length > 12
|
|
29
|
+
? `${dialogId.slice(0, 6)}...${dialogId.slice(-4)}`
|
|
30
|
+
: dialogId;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function resolveDialogLabel(
|
|
34
|
+
state: Pick<TuiState, "dialogId" | "dialogLabel">
|
|
35
|
+
) {
|
|
36
|
+
return state.dialogId ? shortenDialogId(state.dialogId) : state.dialogLabel;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type TuiState = {
|
|
40
|
+
agentKey: string;
|
|
41
|
+
agentName: string;
|
|
42
|
+
dialogId?: string;
|
|
43
|
+
dialogLabel: string;
|
|
44
|
+
profileName: string;
|
|
45
|
+
serverUrl: string;
|
|
46
|
+
cliVersion?: string;
|
|
47
|
+
attachedDocs: string[];
|
|
48
|
+
runtimeMode: AgentRuntimeRequestedMode;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type TuiAction =
|
|
52
|
+
| {
|
|
53
|
+
type: "chat";
|
|
54
|
+
message: string;
|
|
55
|
+
agentKey: string;
|
|
56
|
+
runtimeMode: AgentRuntimeRequestedMode;
|
|
57
|
+
continueDialogId?: string;
|
|
58
|
+
}
|
|
59
|
+
| {
|
|
60
|
+
type: "compact";
|
|
61
|
+
dialogId: string;
|
|
62
|
+
}
|
|
63
|
+
| {
|
|
64
|
+
type: "self-update";
|
|
65
|
+
}
|
|
66
|
+
| {
|
|
67
|
+
type: "exit";
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export type TuiInputResult = {
|
|
71
|
+
nextState: TuiState;
|
|
72
|
+
output: string;
|
|
73
|
+
action?: TuiAction;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
type EnvLike = Record<string, string | undefined>;
|
|
77
|
+
|
|
78
|
+
export function createInitialTuiState(env: EnvLike = process.env): TuiState {
|
|
79
|
+
const agentKey = env.NOLO_AGENT?.trim() || DEFAULT_TUI_AGENT_KEY;
|
|
80
|
+
const agentName = env.NOLO_AGENT_NAME?.trim() || "nolo";
|
|
81
|
+
|
|
29
82
|
return {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
83
|
+
agentKey,
|
|
84
|
+
agentName,
|
|
85
|
+
dialogId: env.NOLO_DIALOG_ID?.trim() || undefined,
|
|
86
|
+
dialogLabel: env.NOLO_DIALOG?.trim() || "new",
|
|
87
|
+
profileName: env.NOLO_PROFILE?.trim() || "local",
|
|
88
|
+
serverUrl: (env.NOLO_SERVER || env.BASE_URL || DEFAULT_TUI_SERVER_URL).replace(
|
|
89
|
+
/\/+$/,
|
|
90
|
+
""
|
|
91
|
+
),
|
|
92
|
+
cliVersion: env.NOLO_CLI_VERSION?.trim() || undefined,
|
|
93
|
+
attachedDocs: [],
|
|
94
|
+
runtimeMode: env.NOLO_RUNTIME_MODE === "local" || env.NOLO_RUNTIME_MODE === "server"
|
|
95
|
+
? env.NOLO_RUNTIME_MODE
|
|
96
|
+
: "auto",
|
|
34
97
|
};
|
|
35
98
|
}
|
|
36
99
|
|
|
37
|
-
export {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
100
|
+
export function renderStatusLine(state: TuiState) {
|
|
101
|
+
const docs =
|
|
102
|
+
state.attachedDocs.length > 0
|
|
103
|
+
? String(state.attachedDocs.length)
|
|
104
|
+
: "0";
|
|
105
|
+
|
|
106
|
+
return [
|
|
107
|
+
`agent ${state.agentName}`,
|
|
108
|
+
`dialog ${resolveDialogLabel(state)}`,
|
|
109
|
+
`docs ${docs}`,
|
|
110
|
+
`runtime ${state.runtimeMode}`,
|
|
111
|
+
`profile ${state.profileName}`,
|
|
112
|
+
].join(" | ");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function renderWelcome(state: TuiState) {
|
|
116
|
+
const docs = state.attachedDocs.length > 0
|
|
117
|
+
? `${state.attachedDocs.length} attached`
|
|
118
|
+
: "none";
|
|
119
|
+
return [
|
|
120
|
+
"",
|
|
121
|
+
`Nolo workspace${state.cliVersion ? ` nolo ${state.cliVersion}` : ""}`,
|
|
122
|
+
`agent ${state.agentName} | dialog ${resolveDialogLabel(state)} | docs ${docs} | profile ${state.profileName}`,
|
|
123
|
+
`server ${state.serverUrl}`,
|
|
124
|
+
"",
|
|
125
|
+
"Tell nolo what you want. Use /help for commands. Use /version if this install feels stale.",
|
|
126
|
+
"",
|
|
127
|
+
].join("\n");
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function renderPrompt(_state: TuiState) {
|
|
131
|
+
return "you > ";
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function renderTuiHelp() {
|
|
135
|
+
return [
|
|
136
|
+
"Commands:",
|
|
137
|
+
" /help Show this help",
|
|
138
|
+
" /new Start a fresh dialog",
|
|
139
|
+
" /compact Compact current dialog and fork a new one",
|
|
140
|
+
" /context Show workspace context and next actions",
|
|
141
|
+
" /runtime <mode> Use auto, local, or server runtime",
|
|
142
|
+
" /agent Show the current agent",
|
|
143
|
+
" /agents List built-in agent shortcuts",
|
|
144
|
+
" /switch <agent> Switch the current agent",
|
|
145
|
+
" /dialog Show the current dialog",
|
|
146
|
+
" /doc List attached docs",
|
|
147
|
+
" /doc attach <doc> Attach a doc to this workspace",
|
|
148
|
+
" /customize Describe how you want to tune nolo",
|
|
149
|
+
" /login Show login/profile hint",
|
|
150
|
+
" /profile Show active profile",
|
|
151
|
+
" /update Update the global nolo install",
|
|
152
|
+
" /version Show version/update hint",
|
|
153
|
+
" /exit Leave the workspace",
|
|
154
|
+
"",
|
|
155
|
+
"You can also type normally. nolo will send it to the current agent.",
|
|
156
|
+
].join("\n");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function renderContextPanel(state: TuiState) {
|
|
160
|
+
const docs = state.attachedDocs.length
|
|
161
|
+
? state.attachedDocs.join(", ")
|
|
162
|
+
: "none";
|
|
163
|
+
return [
|
|
164
|
+
"Workspace context",
|
|
165
|
+
"-----------------",
|
|
166
|
+
`agent ${state.agentName}`,
|
|
167
|
+
`dialog ${resolveDialogLabel(state)}`,
|
|
168
|
+
`docs ${docs}`,
|
|
169
|
+
`profile ${state.profileName}`,
|
|
170
|
+
`runtime ${state.runtimeMode}`,
|
|
171
|
+
`server ${state.serverUrl}`,
|
|
172
|
+
"",
|
|
173
|
+
"Next:",
|
|
174
|
+
" /agents see specialist shortcuts",
|
|
175
|
+
" /doc attach <doc> add working context",
|
|
176
|
+
" /new start a clean dialog",
|
|
177
|
+
].join("\n");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export function renderKnownAgents() {
|
|
181
|
+
return [
|
|
182
|
+
"Agents:",
|
|
183
|
+
...KNOWN_AGENTS.map(
|
|
184
|
+
(agent, index) =>
|
|
185
|
+
` ${index + 1} ${agent.name.padEnd(11)} ${agent.description}`
|
|
186
|
+
),
|
|
187
|
+
"",
|
|
188
|
+
"Tip: stay on nolo for the one-assistant feel; switch only when you want a specialist directly.",
|
|
189
|
+
].join("\n");
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function resolveSwitchTarget(rawTarget: string) {
|
|
193
|
+
const target = rawTarget.trim();
|
|
194
|
+
if (/^\d+$/.test(target)) {
|
|
195
|
+
const agent = KNOWN_AGENTS[Number(target) - 1];
|
|
196
|
+
return agent ? { name: agent.name, key: agent.key } : null;
|
|
197
|
+
}
|
|
198
|
+
const alias = KNOWN_AGENT_ALIASES[target.toLowerCase()];
|
|
199
|
+
if (alias) return alias;
|
|
200
|
+
if (target.startsWith("agent-") || target.startsWith("agent-pub-")) {
|
|
201
|
+
return { name: target, key: target };
|
|
202
|
+
}
|
|
203
|
+
return null;
|
|
204
|
+
}
|
|
47
205
|
|
|
48
206
|
export function handleTuiInput(input: string, state: TuiState): TuiInputResult {
|
|
49
|
-
|
|
207
|
+
const trimmed = input.trim();
|
|
208
|
+
if (!trimmed) {
|
|
209
|
+
return { nextState: state, output: "" };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (!trimmed.startsWith("/")) {
|
|
213
|
+
return {
|
|
214
|
+
nextState: state,
|
|
215
|
+
output: "",
|
|
216
|
+
action: {
|
|
217
|
+
type: "chat",
|
|
218
|
+
message: trimmed,
|
|
219
|
+
agentKey: state.agentKey,
|
|
220
|
+
runtimeMode: state.runtimeMode,
|
|
221
|
+
...(state.dialogId ? { continueDialogId: state.dialogId } : {}),
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const [command = "", ...rest] = trimmed.split(/\s+/);
|
|
227
|
+
const argText = rest.join(" ").trim();
|
|
228
|
+
|
|
229
|
+
switch (command) {
|
|
230
|
+
case "/help":
|
|
231
|
+
return { nextState: state, output: renderTuiHelp() };
|
|
232
|
+
case "/context":
|
|
233
|
+
case "/ctx":
|
|
234
|
+
return { nextState: state, output: renderContextPanel(state) };
|
|
235
|
+
case "/runtime": {
|
|
236
|
+
if (argText !== "auto" && argText !== "local" && argText !== "server") {
|
|
237
|
+
return {
|
|
238
|
+
nextState: state,
|
|
239
|
+
output: "Usage: /runtime <auto|local|server>",
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
nextState: { ...state, runtimeMode: argText },
|
|
244
|
+
output: `Runtime: ${argText}`,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
case "/exit":
|
|
248
|
+
case "/quit":
|
|
249
|
+
return { nextState: state, output: "Bye.", action: { type: "exit" } };
|
|
250
|
+
case "/new":
|
|
251
|
+
return {
|
|
252
|
+
nextState: {
|
|
253
|
+
...state,
|
|
254
|
+
dialogId: undefined,
|
|
255
|
+
dialogLabel: "new",
|
|
256
|
+
attachedDocs: [],
|
|
257
|
+
},
|
|
258
|
+
output: "Started a fresh dialog.",
|
|
259
|
+
};
|
|
260
|
+
case "/compact":
|
|
261
|
+
if (argText) {
|
|
262
|
+
return {
|
|
263
|
+
nextState: state,
|
|
264
|
+
output: `Unknown command: ${trimmed}\n\n${renderTuiHelp()}`,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
if (!state.dialogId) {
|
|
268
|
+
return {
|
|
269
|
+
nextState: state,
|
|
270
|
+
output: "Current dialog: new (nothing to compact yet)",
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
nextState: state,
|
|
275
|
+
output: "Compacting current dialog...",
|
|
276
|
+
action: { type: "compact", dialogId: state.dialogId },
|
|
277
|
+
};
|
|
278
|
+
case "/agent":
|
|
279
|
+
return {
|
|
280
|
+
nextState: state,
|
|
281
|
+
output: `Current agent: ${state.agentName} (${state.agentKey})`,
|
|
282
|
+
};
|
|
283
|
+
case "/agents":
|
|
284
|
+
return {
|
|
285
|
+
nextState: state,
|
|
286
|
+
output: renderKnownAgents(),
|
|
287
|
+
};
|
|
288
|
+
case "/switch": {
|
|
289
|
+
if (!argText) {
|
|
290
|
+
return {
|
|
291
|
+
nextState: state,
|
|
292
|
+
output: "Usage: /switch <agent-key|alias>",
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
const resolvedTarget = resolveSwitchTarget(argText);
|
|
296
|
+
if (!resolvedTarget) {
|
|
297
|
+
return {
|
|
298
|
+
nextState: state,
|
|
299
|
+
output:
|
|
300
|
+
`I don't know agent shortcut "${argText}" yet.\n` +
|
|
301
|
+
"Use /switch nolo, /switch app-builder, or a full agent key like agent-pub-...",
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
return {
|
|
305
|
+
nextState: {
|
|
306
|
+
...state,
|
|
307
|
+
agentName: resolvedTarget.name,
|
|
308
|
+
agentKey: resolvedTarget.key,
|
|
309
|
+
},
|
|
310
|
+
output: `Switched to ${resolvedTarget.name}.`,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
case "/dialog":
|
|
314
|
+
return {
|
|
315
|
+
nextState: state,
|
|
316
|
+
output: state.dialogId
|
|
317
|
+
? `Current dialog: ${state.dialogId}`
|
|
318
|
+
: "Current dialog: new",
|
|
319
|
+
};
|
|
320
|
+
case "/doc": {
|
|
321
|
+
if (rest[0] === "attach") {
|
|
322
|
+
const docName = rest.slice(1).join(" ").trim();
|
|
323
|
+
if (!docName) {
|
|
324
|
+
return { nextState: state, output: "Usage: /doc attach <doc>" };
|
|
325
|
+
}
|
|
326
|
+
const attachedDocs = state.attachedDocs.includes(docName)
|
|
327
|
+
? state.attachedDocs
|
|
328
|
+
: [...state.attachedDocs, docName];
|
|
329
|
+
return {
|
|
330
|
+
nextState: { ...state, attachedDocs },
|
|
331
|
+
output: `Attached doc: ${docName}`,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
nextState: state,
|
|
336
|
+
output:
|
|
337
|
+
state.attachedDocs.length > 0
|
|
338
|
+
? `Attached docs: ${state.attachedDocs.join(", ")}`
|
|
339
|
+
: "No docs attached. Use /doc attach <doc>.",
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
case "/customize":
|
|
343
|
+
return {
|
|
344
|
+
nextState: state,
|
|
345
|
+
output:
|
|
346
|
+
"Tell nolo what to change, for example: /customize make my default agent more concise.",
|
|
347
|
+
};
|
|
348
|
+
case "/login":
|
|
349
|
+
return {
|
|
350
|
+
nextState: state,
|
|
351
|
+
output:
|
|
352
|
+
"MVP login uses profile/env auth. Set AUTH_TOKEN, NOLO_SERVER, or NOLO_PROFILE before starting nolo.",
|
|
353
|
+
};
|
|
354
|
+
case "/profile":
|
|
355
|
+
return {
|
|
356
|
+
nextState: state,
|
|
357
|
+
output: `Profile: ${state.profileName}`,
|
|
358
|
+
};
|
|
359
|
+
case "/update":
|
|
360
|
+
return {
|
|
361
|
+
nextState: state,
|
|
362
|
+
output: "Starting self-update...",
|
|
363
|
+
action: { type: "self-update" },
|
|
364
|
+
};
|
|
365
|
+
case "/version":
|
|
366
|
+
return {
|
|
367
|
+
nextState: state,
|
|
368
|
+
output:
|
|
369
|
+
`nolo ${state.cliVersion || "unknown version"}\n` +
|
|
370
|
+
"Update this install with: nolo update\n" +
|
|
371
|
+
"If repo-local output differs, publish/install the latest npm package first.",
|
|
372
|
+
};
|
|
373
|
+
default:
|
|
374
|
+
return {
|
|
375
|
+
nextState: state,
|
|
376
|
+
output: `Unknown command: ${command}\n\n${renderTuiHelp()}`,
|
|
377
|
+
};
|
|
378
|
+
}
|
|
50
379
|
}
|
|
@@ -1,31 +1,11 @@
|
|
|
1
1
|
import { createEnvCommand } from "./cliCommandFactories";
|
|
2
2
|
import type { CommandEntry } from "./cliCommandTypes";
|
|
3
|
-
import { runTableMetaCommand } from "./tableMetaCommands";
|
|
4
|
-
import {
|
|
5
|
-
runTableAddColumnCommand,
|
|
6
|
-
runTableAddRowCommand,
|
|
7
|
-
runTableAddRowsCommand,
|
|
8
|
-
runTableDataCommand,
|
|
9
|
-
runTableDeleteRowCommand,
|
|
10
|
-
runTableDeleteRowsCommand,
|
|
11
|
-
runTableUpdateRowCommand,
|
|
12
|
-
runTableUpdateRowsCommand,
|
|
13
|
-
} from "./tableMutationCommands";
|
|
14
3
|
import { runTableQueryCommand } from "./tableCommands";
|
|
15
4
|
import { runTaskRunCommand } from "./taskRunCommand";
|
|
16
5
|
|
|
17
6
|
export function getWorkflowInternalCommandEntries(): CommandEntry[] {
|
|
18
7
|
return [
|
|
19
8
|
createEnvCommand(["table", "query"], "Query table rows", runTableQueryCommand),
|
|
20
|
-
createEnvCommand(["table", "meta"], "Create or update table metadata", runTableMetaCommand),
|
|
21
|
-
createEnvCommand(["table", "add-column"], "Add one table column", runTableAddColumnCommand),
|
|
22
|
-
createEnvCommand(["table", "add-row"], "Add one table row", runTableAddRowCommand),
|
|
23
|
-
createEnvCommand(["table", "add-rows"], "Add table rows", runTableAddRowsCommand),
|
|
24
|
-
createEnvCommand(["table", "update-row"], "Update one table row", runTableUpdateRowCommand),
|
|
25
|
-
createEnvCommand(["table", "update-rows"], "Update table rows", runTableUpdateRowsCommand),
|
|
26
|
-
createEnvCommand(["table", "delete-row"], "Delete one table row", runTableDeleteRowCommand),
|
|
27
|
-
createEnvCommand(["table", "delete-rows"], "Delete table rows", runTableDeleteRowsCommand),
|
|
28
|
-
createEnvCommand(["table", "data"], "Low-level table row command", runTableDataCommand),
|
|
29
9
|
createEnvCommand(["task-run"], "Update durable task-run state through the runner bridge", runTaskRunCommand),
|
|
30
10
|
];
|
|
31
11
|
}
|
package/cliEnvHelpers.ts
CHANGED
|
@@ -3,183 +3,42 @@ import { NOLO_CLUSTER_SERVERS } from "./database/config";
|
|
|
3
3
|
|
|
4
4
|
export type EnvLike = Record<string, string | undefined>;
|
|
5
5
|
|
|
6
|
-
function
|
|
7
|
-
return
|
|
6
|
+
export function resolveServerUrl(env: EnvLike) {
|
|
7
|
+
return (env.NOLO_SERVER || env.BASE_URL || DEFAULT_NOLO_SERVER_URL).replace(/\/+$/, "");
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
if (typeof value === "string" && value.length > 0) return value;
|
|
14
|
-
}
|
|
15
|
-
return "";
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function hasFlag(args: string[], flag: string) {
|
|
19
|
-
return args.includes(flag);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function readCliOptionValue(args: string[], flag: string): string {
|
|
23
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
24
|
-
const arg = args[i];
|
|
25
|
-
if (arg === flag) {
|
|
26
|
-
const next = args[i + 1];
|
|
27
|
-
if (typeof next === "string" && !next.startsWith("-")) return next;
|
|
28
|
-
return "";
|
|
29
|
-
}
|
|
30
|
-
if (arg.startsWith(`${flag}=`)) return arg.slice(flag.length + 1);
|
|
31
|
-
}
|
|
32
|
-
return "";
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function hasExplicitServerOverride(args: string[]) {
|
|
36
|
-
return Boolean(
|
|
37
|
-
readCliOptionValue(args, "--server-url") ||
|
|
38
|
-
readCliOptionValue(args, "--server") ||
|
|
39
|
-
readCliOptionValue(args, "--base-url")
|
|
40
|
-
);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function resolveServerUrlFromEnv(env: EnvLike) {
|
|
44
|
-
return trimTrailingSlashes(
|
|
45
|
-
firstDefinedEnvValue(env, ["NOLO_SERVER_URL", "NOLO_SERVER", "BASE_URL"]) ||
|
|
46
|
-
DEFAULT_NOLO_SERVER_URL,
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function resolveServerUrlFromArgs(args: string[], env: EnvLike) {
|
|
51
|
-
return trimTrailingSlashes(
|
|
52
|
-
readCliOptionValue(args, "--server-url") ||
|
|
53
|
-
readCliOptionValue(args, "--server") ||
|
|
54
|
-
readCliOptionValue(args, "--base-url") ||
|
|
55
|
-
firstDefinedEnvValue(env, ["NOLO_SERVER_URL", "NOLO_SERVER", "BASE_URL"]) ||
|
|
56
|
-
DEFAULT_NOLO_SERVER_URL,
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
type ServerResolverInput = string[] | EnvLike;
|
|
61
|
-
|
|
62
|
-
function isCliArgs(value: ServerResolverInput): value is string[] {
|
|
63
|
-
return Array.isArray(value);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function buildServerCandidates(values: Array<string | null | undefined>) {
|
|
67
|
-
return [...new Set(
|
|
68
|
-
values
|
|
69
|
-
.filter((value): value is string => typeof value === "string" && value.trim().length > 0)
|
|
70
|
-
.map((value) => value.replace(/\/+$/, ""))
|
|
71
|
-
)];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export function resolveServerUrl(env: EnvLike): string;
|
|
75
|
-
export function resolveServerUrl(args: string[], env: EnvLike): string;
|
|
76
|
-
export function resolveServerUrl(input: ServerResolverInput, env?: EnvLike) {
|
|
77
|
-
if (isCliArgs(input)) {
|
|
78
|
-
return resolveServerUrlFromArgs(input, env ?? {});
|
|
79
|
-
}
|
|
80
|
-
return resolveServerUrlFromEnv(input);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function resolveServerCandidates(env: EnvLike, preferred?: string | null): string[];
|
|
84
|
-
export function resolveServerCandidates(
|
|
85
|
-
args: string[],
|
|
86
|
-
env: EnvLike,
|
|
87
|
-
preferred?: string | null,
|
|
88
|
-
): string[];
|
|
89
|
-
export function resolveServerCandidates(
|
|
90
|
-
input: ServerResolverInput,
|
|
91
|
-
envOrPreferred?: EnvLike | string | null,
|
|
92
|
-
preferred?: string | null,
|
|
93
|
-
) {
|
|
94
|
-
if (isCliArgs(input)) {
|
|
95
|
-
const env = (envOrPreferred ?? {}) as EnvLike;
|
|
96
|
-
const explicitServer = resolveServerUrlFromArgs(input, env);
|
|
97
|
-
return buildServerCandidates([
|
|
98
|
-
explicitServer,
|
|
99
|
-
preferred?.trim(),
|
|
100
|
-
env.NOLO_SERVER,
|
|
101
|
-
env.BASE_URL,
|
|
102
|
-
env.NOLO_SERVER_URL,
|
|
103
|
-
DEFAULT_NOLO_SERVER_URL,
|
|
104
|
-
...NOLO_CLUSTER_SERVERS,
|
|
105
|
-
]);
|
|
106
|
-
}
|
|
107
|
-
const env = input;
|
|
108
|
-
return buildServerCandidates([
|
|
109
|
-
typeof envOrPreferred === "string" ? envOrPreferred.trim() : undefined,
|
|
10
|
+
export function resolveServerCandidates(env: EnvLike, preferred?: string | null) {
|
|
11
|
+
const values = [
|
|
12
|
+
preferred?.trim(),
|
|
110
13
|
env.NOLO_SERVER,
|
|
111
14
|
env.BASE_URL,
|
|
112
15
|
env.NOLO_SERVER_URL,
|
|
113
16
|
DEFAULT_NOLO_SERVER_URL,
|
|
114
17
|
...NOLO_CLUSTER_SERVERS,
|
|
115
|
-
]
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
input: ServerResolverInput,
|
|
122
|
-
envOrExtraEnvKeys?: EnvLike | string[],
|
|
123
|
-
extraEnvKeys: string[] = [],
|
|
124
|
-
) {
|
|
125
|
-
if (isCliArgs(input)) {
|
|
126
|
-
return resolveAuthTokenFromArgs(input, (envOrExtraEnvKeys ?? {}) as EnvLike, extraEnvKeys);
|
|
127
|
-
}
|
|
128
|
-
return resolveAuthTokenFromEnv(input, (envOrExtraEnvKeys as string[] | undefined) ?? []);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export function resolveAuthTokenFromEnv(env: EnvLike, extraEnvKeys: string[] = []) {
|
|
132
|
-
return (
|
|
133
|
-
firstDefinedEnvValue(env, [...extraEnvKeys, "BENCHMARK_AUTH_TOKEN", "AUTH_TOKEN", "AUTH"]) ||
|
|
134
|
-
""
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
export function resolveAuthTokenFromArgs(
|
|
139
|
-
args: string[],
|
|
140
|
-
env: EnvLike,
|
|
141
|
-
extraEnvKeys: string[] = [],
|
|
142
|
-
) {
|
|
143
|
-
return (
|
|
144
|
-
readCliOptionValue(args, "--api-key") ||
|
|
145
|
-
readCliOptionValue(args, "--token") ||
|
|
146
|
-
firstDefinedEnvValue(env, [
|
|
147
|
-
...extraEnvKeys,
|
|
148
|
-
"BENCHMARK_AUTH_TOKEN",
|
|
149
|
-
"NOLO_TASK_RUN_TOKEN",
|
|
150
|
-
"NOLO_MACHINE_API_KEY",
|
|
151
|
-
"AUTH_TOKEN",
|
|
152
|
-
"AUTH",
|
|
153
|
-
]) ||
|
|
154
|
-
""
|
|
155
|
-
);
|
|
18
|
+
];
|
|
19
|
+
return [...new Set(
|
|
20
|
+
values
|
|
21
|
+
.filter((value): value is string => typeof value === "string" && value.trim().length > 0)
|
|
22
|
+
.map((value) => value.replace(/\/+$/, ""))
|
|
23
|
+
)];
|
|
156
24
|
}
|
|
157
25
|
|
|
158
|
-
export function
|
|
159
|
-
|
|
160
|
-
if (!trimmed) return null;
|
|
161
|
-
const parts = trimmed.split(".").filter(Boolean);
|
|
162
|
-
const payloadCandidates = parts.length >= 3 ? [parts[1], parts[0]] : [parts[0]];
|
|
163
|
-
for (const payload of payloadCandidates) {
|
|
164
|
-
try {
|
|
165
|
-
return JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
|
|
166
|
-
} catch {
|
|
167
|
-
continue;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
return null;
|
|
26
|
+
export function resolveAuthToken(env: EnvLike) {
|
|
27
|
+
return env.AUTH_TOKEN || env.AUTH || "";
|
|
171
28
|
}
|
|
172
29
|
|
|
173
30
|
export function parseUserIdFromAuthToken(token: string) {
|
|
174
|
-
const
|
|
175
|
-
|
|
31
|
+
const payload = token.trim().split(".")[0];
|
|
32
|
+
if (!payload) return "";
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
|
|
35
|
+
return typeof parsed?.userId === "string" ? parsed.userId : "";
|
|
36
|
+
} catch {
|
|
37
|
+
return "";
|
|
38
|
+
}
|
|
176
39
|
}
|
|
177
40
|
|
|
178
41
|
export function readOption(args: string[], flag: string) {
|
|
179
42
|
const index = args.indexOf(flag);
|
|
180
43
|
return index >= 0 ? args[index + 1] : undefined;
|
|
181
44
|
}
|
|
182
|
-
|
|
183
|
-
export function readOptionValue(args: string[], flag: string) {
|
|
184
|
-
return readCliOptionValue(args, flag);
|
|
185
|
-
}
|
|
@@ -17,6 +17,7 @@ describe("agent config resolver", () => {
|
|
|
17
17
|
toolNames: ["legacyTool", "readFile"],
|
|
18
18
|
tools: ["readFile", "applyEdit"],
|
|
19
19
|
runtimeBinding: { machineId: "machine-1", localWorkspaceMode: "task-worktree" },
|
|
20
|
+
delegation: { target: "local" },
|
|
20
21
|
temperature: 0.2,
|
|
21
22
|
top_p: 0.9,
|
|
22
23
|
max_tokens: 4096,
|
|
@@ -35,6 +36,7 @@ describe("agent config resolver", () => {
|
|
|
35
36
|
toolNames: ["legacyTool", "readFile", "applyEdit"],
|
|
36
37
|
runtimeBinding: { machineId: "machine-1", localWorkspaceMode: "task-worktree" },
|
|
37
38
|
localWorkspaceMode: "task-worktree",
|
|
39
|
+
delegation: { target: "local" },
|
|
38
40
|
temperature: 0.2,
|
|
39
41
|
top_p: 0.9,
|
|
40
42
|
max_tokens: 4096,
|