nolo-cli 0.1.32 → 0.1.34
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 +4 -10
- package/agent-runtime/agentRecordConfig.ts +10 -0
- package/agent-runtime/hostAdapter.ts +10 -1
- package/agent-runtime/index.ts +9 -20
- package/agent-runtime/localLoop.ts +49 -2
- package/agent-runtime/localToolPolicy.ts +76 -34
- package/agent-runtime/localWorkspaceTools.ts +30 -333
- package/agent-runtime/openAiCompatibleProvider.ts +7 -3
- package/agent-runtime/openAiCompatibleProviderConfig.ts +15 -26
- package/agent-runtime/platformChatProvider.ts +47 -73
- package/agent-runtime/providerResolution.ts +244 -0
- package/agent-runtime/runtimeToolPolicy.ts +77 -29
- package/agent-runtime/shellCommandPolicy.ts +120 -0
- package/agentAliases.ts +14 -83
- package/agentCommandSupport.ts +3 -6
- package/agentInternalCommandEntries.ts +4 -13
- package/agentListCommands.ts +18 -27
- package/agentMachineCommands.ts +40 -336
- package/agentPullCommand.ts +30 -55
- package/agentRecordCommands.ts +84 -1
- package/agentRecordHelpers.ts +102 -186
- package/agentRunCommand.ts +438 -107
- package/agentRuntimeLocal.ts +2 -9
- package/ai/agent/cliExecutor.ts +19 -323
- package/ai/tools/toolNameAliases.ts +70 -0
- package/authCommands.ts +2 -36
- package/cli/agentAliases.ts +14 -83
- package/cli/agentCommandSupport.ts +3 -6
- package/cli/agentInternalCommandEntries.ts +4 -13
- package/cli/agentListCommands.ts +18 -27
- package/cli/agentMachineCommands.ts +40 -336
- package/cli/agentPullCommand.ts +30 -55
- package/cli/agentRecordCommands.ts +84 -1
- package/cli/agentRecordHelpers.ts +102 -186
- package/cli/agentRunCommand.ts +438 -107
- package/cli/agentRuntimeLocal.ts +2 -9
- package/cli/authCommands.ts +2 -36
- package/cli/cliCommandDispatch.ts +2 -2
- package/cli/cliEnvHelpers.ts +34 -107
- package/cli/client/agentRun.ts +854 -57
- package/cli/client/localRuntimeAdapter.ts +59 -159
- package/cli/client/streamingOutput.ts +3 -1
- package/cli/client/taskRunPrompt.ts +24 -7
- package/cli/commandRegistry.ts +4 -5
- 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 +30 -44
- package/cli/machineWsSession.ts +0 -2
- package/cli/offlineMarxistsAgentCommand.ts +314 -0
- package/cli/runtimeDoctorCommands.ts +72 -15
- 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/cliCommandDispatch.ts +2 -2
- package/cliEnvHelpers.ts +34 -107
- package/client/agentConfigResolver.test.ts +2 -0
- package/client/agentRun.test.ts +12 -208
- package/client/agentRun.ts +854 -57
- package/client/localProviderResolver.test.ts +26 -2
- package/client/localRuntimeAdapter.test.ts +296 -171
- package/client/localRuntimeAdapter.ts +59 -159
- package/client/localToolPolicy.test.ts +4 -28
- package/client/streamingOutput.ts +3 -1
- package/client/taskRunPrompt.ts +24 -7
- package/commandRegistry.ts +4 -5
- package/connectorRunArtifact.ts +10 -34
- package/connectorWebSocketTarget.ts +6 -10
- package/database/server/serverStoreFactory.ts +2 -8
- 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 +30 -44
- package/machineWsSession.ts +0 -2
- package/offlineMarxistsAgentCommand.ts +314 -0
- package/package.json +52 -188
- package/runtimeDoctorCommands.ts +72 -15
- 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/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/cliCommandDispatch.ts
CHANGED
|
@@ -31,7 +31,7 @@ function readOption(args: string[], flag: string) {
|
|
|
31
31
|
|
|
32
32
|
function buildDaemonEnv(args: string[], runtimeEnv: NodeJS.ProcessEnv) {
|
|
33
33
|
const serverUrl = readOption(args, "--server-url") || readOption(args, "--server");
|
|
34
|
-
const apiKey = readOption(args, "--
|
|
34
|
+
const apiKey = readOption(args, "--machine-key") || readOption(args, "--token");
|
|
35
35
|
return {
|
|
36
36
|
...runtimeEnv,
|
|
37
37
|
...(serverUrl ? { NOLO_SERVER: serverUrl } : {}),
|
|
@@ -40,7 +40,7 @@ function buildDaemonEnv(args: string[], runtimeEnv: NodeJS.ProcessEnv) {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
export function looksLikeDaemonShortcut(args: string[]) {
|
|
43
|
-
return args.includes("--server-url") || args.includes("--
|
|
43
|
+
return args.includes("--server-url") || args.includes("--machine-key");
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
export function createCliRuntimeContext(args: {
|
package/cliEnvHelpers.ts
CHANGED
|
@@ -3,63 +3,13 @@ import { NOLO_CLUSTER_SERVERS } from "./database/config";
|
|
|
3
3
|
|
|
4
4
|
export type EnvLike = Record<string, string | undefined>;
|
|
5
5
|
|
|
6
|
-
function trimTrailingSlashes(value: string) {
|
|
7
|
-
return value.trim().replace(/\/+$/, "");
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
function firstDefinedEnvValue(env: EnvLike, keys: string[]) {
|
|
11
|
-
for (const key of keys) {
|
|
12
|
-
const value = env[key];
|
|
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
6
|
export function resolveServerUrlFromEnv(env: EnvLike) {
|
|
44
|
-
return
|
|
45
|
-
firstDefinedEnvValue(env, ["NOLO_SERVER_URL", "NOLO_SERVER", "BASE_URL"]) ||
|
|
46
|
-
DEFAULT_NOLO_SERVER_URL,
|
|
47
|
-
);
|
|
7
|
+
return (env.NOLO_SERVER || env.BASE_URL || DEFAULT_NOLO_SERVER_URL).replace(/\/+$/, "");
|
|
48
8
|
}
|
|
49
9
|
|
|
50
|
-
|
|
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;
|
|
10
|
+
type ResolverInput = string[] | EnvLike;
|
|
61
11
|
|
|
62
|
-
function isCliArgs(value:
|
|
12
|
+
function isCliArgs(value: ResolverInput): value is string[] {
|
|
63
13
|
return Array.isArray(value);
|
|
64
14
|
}
|
|
65
15
|
|
|
@@ -73,9 +23,12 @@ function buildServerCandidates(values: Array<string | null | undefined>) {
|
|
|
73
23
|
|
|
74
24
|
export function resolveServerUrl(env: EnvLike): string;
|
|
75
25
|
export function resolveServerUrl(args: string[], env: EnvLike): string;
|
|
76
|
-
export function resolveServerUrl(input:
|
|
26
|
+
export function resolveServerUrl(input: ResolverInput, env?: EnvLike) {
|
|
77
27
|
if (isCliArgs(input)) {
|
|
78
|
-
|
|
28
|
+
const explicit =
|
|
29
|
+
readOption(input, "--server-url") ||
|
|
30
|
+
readOption(input, "--server");
|
|
31
|
+
return explicit?.replace(/\/+$/, "") || resolveServerUrlFromEnv(env ?? {});
|
|
79
32
|
}
|
|
80
33
|
return resolveServerUrlFromEnv(input);
|
|
81
34
|
}
|
|
@@ -87,13 +40,13 @@ export function resolveServerCandidates(
|
|
|
87
40
|
preferred?: string | null,
|
|
88
41
|
): string[];
|
|
89
42
|
export function resolveServerCandidates(
|
|
90
|
-
input:
|
|
43
|
+
input: ResolverInput,
|
|
91
44
|
envOrPreferred?: EnvLike | string | null,
|
|
92
45
|
preferred?: string | null,
|
|
93
46
|
) {
|
|
94
47
|
if (isCliArgs(input)) {
|
|
95
48
|
const env = (envOrPreferred ?? {}) as EnvLike;
|
|
96
|
-
const explicitServer =
|
|
49
|
+
const explicitServer = resolveServerUrl(input, env);
|
|
97
50
|
return buildServerCandidates([
|
|
98
51
|
explicitServer,
|
|
99
52
|
preferred?.trim(),
|
|
@@ -104,6 +57,7 @@ export function resolveServerCandidates(
|
|
|
104
57
|
...NOLO_CLUSTER_SERVERS,
|
|
105
58
|
]);
|
|
106
59
|
}
|
|
60
|
+
|
|
107
61
|
const env = input;
|
|
108
62
|
return buildServerCandidates([
|
|
109
63
|
typeof envOrPreferred === "string" ? envOrPreferred.trim() : undefined,
|
|
@@ -115,71 +69,44 @@ export function resolveServerCandidates(
|
|
|
115
69
|
]);
|
|
116
70
|
}
|
|
117
71
|
|
|
72
|
+
export function resolveAuthTokenFromEnv(env: EnvLike, extraEnvKeys: string[] = []) {
|
|
73
|
+
for (const key of ["AUTH_TOKEN", "AUTH", ...extraEnvKeys]) {
|
|
74
|
+
const value = env[key];
|
|
75
|
+
if (typeof value === "string" && value.trim()) return value;
|
|
76
|
+
}
|
|
77
|
+
return "";
|
|
78
|
+
}
|
|
79
|
+
|
|
118
80
|
export function resolveAuthToken(env: EnvLike, extraEnvKeys?: string[]): string;
|
|
119
81
|
export function resolveAuthToken(args: string[], env: EnvLike, extraEnvKeys?: string[]): string;
|
|
120
82
|
export function resolveAuthToken(
|
|
121
|
-
input:
|
|
83
|
+
input: ResolverInput,
|
|
122
84
|
envOrExtraEnvKeys?: EnvLike | string[],
|
|
123
85
|
extraEnvKeys: string[] = [],
|
|
124
86
|
) {
|
|
125
87
|
if (isCliArgs(input)) {
|
|
126
|
-
|
|
88
|
+
const env = (envOrExtraEnvKeys ?? {}) as EnvLike;
|
|
89
|
+
return (
|
|
90
|
+
readOption(input, "--token") ||
|
|
91
|
+
readOption(input, "--machine-key") ||
|
|
92
|
+
resolveAuthTokenFromEnv(env, extraEnvKeys)
|
|
93
|
+
);
|
|
127
94
|
}
|
|
128
95
|
return resolveAuthTokenFromEnv(input, (envOrExtraEnvKeys as string[] | undefined) ?? []);
|
|
129
96
|
}
|
|
130
97
|
|
|
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
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export function decodeJwtPayload(token: string): Record<string, unknown> | null {
|
|
159
|
-
const trimmed = token.trim();
|
|
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;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
98
|
export function parseUserIdFromAuthToken(token: string) {
|
|
174
|
-
const
|
|
175
|
-
|
|
99
|
+
const payload = token.trim().split(".")[0];
|
|
100
|
+
if (!payload) return "";
|
|
101
|
+
try {
|
|
102
|
+
const parsed = JSON.parse(Buffer.from(payload, "base64").toString("utf8"));
|
|
103
|
+
return typeof parsed?.userId === "string" ? parsed.userId : "";
|
|
104
|
+
} catch {
|
|
105
|
+
return "";
|
|
106
|
+
}
|
|
176
107
|
}
|
|
177
108
|
|
|
178
109
|
export function readOption(args: string[], flag: string) {
|
|
179
110
|
const index = args.indexOf(flag);
|
|
180
111
|
return index >= 0 ? args[index + 1] : undefined;
|
|
181
112
|
}
|
|
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,
|