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/README.md
CHANGED
|
@@ -90,7 +90,7 @@ nolo chat
|
|
|
90
90
|
nolo connect
|
|
91
91
|
nolo connect --watch
|
|
92
92
|
nolo connect --daemon
|
|
93
|
-
nolo daemon --server-url https://api.nolo.chat --
|
|
93
|
+
nolo daemon --server-url https://api.nolo.chat --machine-key sk_machine_xxx
|
|
94
94
|
nolo machine status
|
|
95
95
|
nolo run "summarize my latest agent dialogs"
|
|
96
96
|
nolo doc create --title "Trip Notes" --body "hello" --sync local,us --dry-run
|
|
@@ -100,7 +100,6 @@ nolo space read 01KKY77TT0DA9NY7TNW3R7255N --content-key page-user-id --brief
|
|
|
100
100
|
nolo agent list --json
|
|
101
101
|
nolo agent bind-current agent-user-1-agent-1
|
|
102
102
|
nolo agent runtime-doctor agent-user-1-agent-1
|
|
103
|
-
nolo agent smoke-bound agent-user-1-agent-1 --msg "ping"
|
|
104
103
|
nolo agent smoke-current agent-user-1-agent-1 --msg "ping"
|
|
105
104
|
nolo chat --agent agent-pub-01APPBUILDER00000001YAII3I --msg "你好"
|
|
106
105
|
```
|
|
@@ -117,7 +116,7 @@ nolo connect # send one machine heartbeat
|
|
|
117
116
|
nolo connect --watch # keep this terminal process online with periodic heartbeats
|
|
118
117
|
nolo connect --ws # keep a live connector websocket for bound agent runs
|
|
119
118
|
nolo connect --daemon # start connect --ws silently in the background
|
|
120
|
-
nolo daemon --server-url https://api.nolo.chat --
|
|
119
|
+
nolo daemon --server-url https://api.nolo.chat --machine-key sk_machine_xxx
|
|
121
120
|
nolo machine status # list machines registered to the current profile
|
|
122
121
|
```
|
|
123
122
|
|
|
@@ -127,13 +126,13 @@ They do not expose shell, file-write, or raw local LLM endpoints.
|
|
|
127
126
|
Run a Slock-style connector command:
|
|
128
127
|
|
|
129
128
|
```bash
|
|
130
|
-
nolo daemon --server-url https://api.nolo.chat --
|
|
129
|
+
nolo daemon --server-url https://api.nolo.chat --machine-key sk_machine_xxx
|
|
131
130
|
```
|
|
132
131
|
|
|
133
132
|
Future published package shape:
|
|
134
133
|
|
|
135
134
|
```bash
|
|
136
|
-
npx @nolo/daemon@latest --server-url https://api.nolo.chat --
|
|
135
|
+
npx @nolo/daemon@latest --server-url https://api.nolo.chat --machine-key sk_machine_xxx
|
|
137
136
|
```
|
|
138
137
|
|
|
139
138
|
The daemon registers this computer, reports local CLI capabilities, keeps a live
|
|
@@ -153,7 +152,6 @@ Run a one-command connector smoke test:
|
|
|
153
152
|
|
|
154
153
|
```bash
|
|
155
154
|
nolo agent runtime-doctor <agentKey>
|
|
156
|
-
nolo agent smoke-bound <agentKey> --msg "ping"
|
|
157
155
|
nolo agent smoke-current <agentKey> --msg "ping"
|
|
158
156
|
```
|
|
159
157
|
|
|
@@ -161,10 +159,6 @@ nolo agent smoke-current <agentKey> --msg "ping"
|
|
|
161
159
|
machine has the required CLI capability. `smoke-current` heartbeats the current
|
|
162
160
|
machine, binds the agent to it, opens a temporary connector websocket, calls
|
|
163
161
|
`/api/agent/run`, and prints the returned dialog id/content.
|
|
164
|
-
`smoke-bound` does not start a local connector or rebind anything. It validates
|
|
165
|
-
the agent through its existing runtime binding by calling the real
|
|
166
|
-
`/api/agent/run` path, so it is the safer probe for shared-Space member runs
|
|
167
|
-
that should execute through another owner's online connector.
|
|
168
162
|
|
|
169
163
|
## Product Shape
|
|
170
164
|
|
|
@@ -64,6 +64,10 @@ export function resolveAgentRuntimeConfigFromRecord(
|
|
|
64
64
|
const apiSource = stringField(record, "apiSource");
|
|
65
65
|
const cliProvider = stringField(record, "cliProvider");
|
|
66
66
|
const customProviderUrl = stringField(record, "customProviderUrl");
|
|
67
|
+
const apiKey = stringField(record, "apiKey");
|
|
68
|
+
const apiKeyHeader = stringField(record, "apiKeyHeader");
|
|
69
|
+
const apiKeyFromAgentKey = stringField(record, "apiKeyFromAgentKey");
|
|
70
|
+
const useServerProxy = record.useServerProxy === true;
|
|
67
71
|
const provider = stringField(record, "provider") ?? stringField(record, "apiSource");
|
|
68
72
|
const toolNames = resolveAgentRuntimeToolNames(record);
|
|
69
73
|
const temperature = numberField(record, "temperature");
|
|
@@ -77,6 +81,7 @@ export function resolveAgentRuntimeConfigFromRecord(
|
|
|
77
81
|
objectField(record, "runtimeToolPolicy") ??
|
|
78
82
|
objectField(runtimeBinding ?? {}, "runtimeToolPolicy");
|
|
79
83
|
const localWorkspaceMode = localWorkspaceModeField(record);
|
|
84
|
+
const delegation = objectField(record, "delegation");
|
|
80
85
|
return {
|
|
81
86
|
key,
|
|
82
87
|
...(name ? { name } : {}),
|
|
@@ -86,6 +91,10 @@ export function resolveAgentRuntimeConfigFromRecord(
|
|
|
86
91
|
...(apiSource ? { apiSource } : {}),
|
|
87
92
|
...(cliProvider ? { cliProvider } : {}),
|
|
88
93
|
...(customProviderUrl ? { customProviderUrl } : {}),
|
|
94
|
+
...(apiKey ? { apiKey } : {}),
|
|
95
|
+
...(apiKeyHeader ? { apiKeyHeader } : {}),
|
|
96
|
+
...(apiKeyFromAgentKey ? { apiKeyFromAgentKey } : {}),
|
|
97
|
+
...(useServerProxy ? { useServerProxy } : {}),
|
|
89
98
|
...(toolNames ? { toolNames } : {}),
|
|
90
99
|
...(temperature !== undefined ? { temperature } : {}),
|
|
91
100
|
...(topP !== undefined ? { top_p: topP } : {}),
|
|
@@ -96,6 +105,7 @@ export function resolveAgentRuntimeConfigFromRecord(
|
|
|
96
105
|
...(runtimeBinding ? { runtimeBinding } : {}),
|
|
97
106
|
...(runtimeToolPolicy ? { runtimeToolPolicy } : {}),
|
|
98
107
|
...(localWorkspaceMode ? { localWorkspaceMode } : {}),
|
|
108
|
+
...(delegation ? { delegation } : {}),
|
|
99
109
|
rawRecord: record,
|
|
100
110
|
};
|
|
101
111
|
}
|
|
@@ -14,6 +14,10 @@ export type AgentRuntimeAgentConfig = {
|
|
|
14
14
|
apiSource?: string;
|
|
15
15
|
cliProvider?: string;
|
|
16
16
|
customProviderUrl?: string;
|
|
17
|
+
apiKey?: string;
|
|
18
|
+
apiKeyHeader?: string;
|
|
19
|
+
apiKeyFromAgentKey?: string;
|
|
20
|
+
useServerProxy?: boolean;
|
|
17
21
|
toolNames?: string[];
|
|
18
22
|
temperature?: number;
|
|
19
23
|
top_p?: number;
|
|
@@ -24,18 +28,23 @@ export type AgentRuntimeAgentConfig = {
|
|
|
24
28
|
runtimeBinding?: Record<string, unknown>;
|
|
25
29
|
runtimeToolPolicy?: AgentRuntimeToolPolicy;
|
|
26
30
|
localWorkspaceMode?: "current" | "task-worktree";
|
|
31
|
+
delegation?: Record<string, unknown>;
|
|
27
32
|
rawRecord?: Record<string, unknown>;
|
|
28
33
|
};
|
|
29
34
|
|
|
30
35
|
export type AgentRuntimeProvider = {
|
|
31
36
|
model: string;
|
|
32
|
-
complete(
|
|
37
|
+
complete(
|
|
38
|
+
messages: AgentRuntimeChatMessage[],
|
|
39
|
+
options?: { timeoutMs?: number }
|
|
40
|
+
): Promise<AgentRuntimeResult>;
|
|
33
41
|
};
|
|
34
42
|
|
|
35
43
|
export type AgentRuntimeToolCallInput = {
|
|
36
44
|
id: string;
|
|
37
45
|
name: string;
|
|
38
46
|
arguments: string;
|
|
47
|
+
userInput?: string;
|
|
39
48
|
};
|
|
40
49
|
|
|
41
50
|
export type AgentRuntimeToolResult = {
|
package/agent-runtime/index.ts
CHANGED
|
@@ -10,6 +10,11 @@ export {
|
|
|
10
10
|
parseOpenAiCompatibleChatCompletionResponse,
|
|
11
11
|
} from "./openAiCompatibleProvider";
|
|
12
12
|
export { resolveOpenAiCompatibleProviderConfig } from "./openAiCompatibleProviderConfig";
|
|
13
|
+
export {
|
|
14
|
+
buildProviderAuthHeaders,
|
|
15
|
+
buildProviderExecutionPlan,
|
|
16
|
+
resolveAgentProviderMode,
|
|
17
|
+
} from "./providerResolution";
|
|
13
18
|
export {
|
|
14
19
|
buildPlatformChatCompletionRequest,
|
|
15
20
|
canUsePlatformChatProvider,
|
|
@@ -27,11 +32,6 @@ export {
|
|
|
27
32
|
} from "./agentRecordKeys";
|
|
28
33
|
export { resolveAgentRuntimeConfigFromRecord } from "./agentRecordConfig";
|
|
29
34
|
export { dialogMessageRecordToAgentRuntimeMessage } from "./dialogMessageRecord";
|
|
30
|
-
export {
|
|
31
|
-
renderDialogStatus,
|
|
32
|
-
resolveDialogActiveHealth,
|
|
33
|
-
resolveDialogTerminalState,
|
|
34
|
-
} from "./dialogStatus";
|
|
35
35
|
export { buildAgentRuntimeDialogWritePlan } from "./dialogWritePlan";
|
|
36
36
|
export {
|
|
37
37
|
createHybridRecordStore,
|
|
@@ -46,16 +46,14 @@ export {
|
|
|
46
46
|
formatPreparedGitTaskWorkspace,
|
|
47
47
|
prepareGitTaskWorkspace,
|
|
48
48
|
} from "./taskWorkspace";
|
|
49
|
-
export {
|
|
50
|
-
createHostRuntimeConfig,
|
|
51
|
-
createHostRuntimeCapabilities,
|
|
52
|
-
resolveHostRuntimeConfigFromEnv,
|
|
53
|
-
resolveHostRuntimeCapabilitiesFromEnv,
|
|
54
|
-
} from "./hostRuntimeConfig";
|
|
55
49
|
export {
|
|
56
50
|
executeLocalToolWithPolicy,
|
|
57
51
|
resolveLocalToolPolicy,
|
|
58
52
|
} from "./localToolPolicy";
|
|
53
|
+
export {
|
|
54
|
+
evaluateShellCommandPolicy,
|
|
55
|
+
isDestructiveShellCommand,
|
|
56
|
+
} from "./shellCommandPolicy";
|
|
59
57
|
export {
|
|
60
58
|
mergeAgentRuntimeToolPolicies,
|
|
61
59
|
normalizeAgentRuntimeToolPolicy,
|
|
@@ -93,12 +91,6 @@ export type {
|
|
|
93
91
|
export type {
|
|
94
92
|
PreparedGitTaskWorkspace,
|
|
95
93
|
} from "./taskWorkspace";
|
|
96
|
-
export type {
|
|
97
|
-
HostRuntimeConfig,
|
|
98
|
-
HostRuntimeCapabilities,
|
|
99
|
-
HostRuntimeSurface,
|
|
100
|
-
HostRuntimeWorkspaceBinding,
|
|
101
|
-
} from "./hostRuntimeConfig";
|
|
102
94
|
export type {
|
|
103
95
|
LocalToolPolicyDecision,
|
|
104
96
|
} from "./localToolPolicy";
|
|
@@ -108,9 +100,6 @@ export type {
|
|
|
108
100
|
export type {
|
|
109
101
|
PlatformChatProviderConfig,
|
|
110
102
|
} from "./platformChatProvider";
|
|
111
|
-
export type {
|
|
112
|
-
DialogStatusSnapshot,
|
|
113
|
-
} from "./dialogStatus";
|
|
114
103
|
export type {
|
|
115
104
|
AgentRuntimeChatMessage,
|
|
116
105
|
AgentRuntimeDecision,
|
|
@@ -13,6 +13,7 @@ export type LocalAgentTurnInput = {
|
|
|
13
13
|
input: AgentRuntimeMessageContent;
|
|
14
14
|
continueDialogId?: string;
|
|
15
15
|
maxToolRounds?: number;
|
|
16
|
+
timeoutMs?: number;
|
|
16
17
|
onToolEvent?: (event: LocalAgentToolEvent) => void;
|
|
17
18
|
};
|
|
18
19
|
|
|
@@ -40,6 +41,29 @@ function formatToolExecutionError(args: {
|
|
|
40
41
|
return `${args.toolName} failed: ${message}`;
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
function formatStructuredToolExecutionError(args: {
|
|
45
|
+
toolName: string;
|
|
46
|
+
error: unknown;
|
|
47
|
+
}) {
|
|
48
|
+
if (!args.error || typeof args.error !== "object") return null;
|
|
49
|
+
const error = args.error as {
|
|
50
|
+
code?: unknown;
|
|
51
|
+
message?: unknown;
|
|
52
|
+
policy?: unknown;
|
|
53
|
+
};
|
|
54
|
+
if (typeof error.code !== "string") return null;
|
|
55
|
+
return JSON.stringify({
|
|
56
|
+
error: error.code,
|
|
57
|
+
message:
|
|
58
|
+
typeof error.message === "string"
|
|
59
|
+
? error.message
|
|
60
|
+
: formatToolExecutionError(args),
|
|
61
|
+
...(error.policy && typeof error.policy === "object"
|
|
62
|
+
? { policy: error.policy }
|
|
63
|
+
: {}),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
43
67
|
function shouldReturnToolExecutionErrors(adapter: AgentRuntimeHostAdapter) {
|
|
44
68
|
return adapter.capabilities.includes("local-tools");
|
|
45
69
|
}
|
|
@@ -66,6 +90,16 @@ function buildMessages(args: {
|
|
|
66
90
|
];
|
|
67
91
|
}
|
|
68
92
|
|
|
93
|
+
function extractUserInputText(content: AgentRuntimeMessageContent): string {
|
|
94
|
+
if (typeof content === "string") return content;
|
|
95
|
+
if (!Array.isArray(content)) return "";
|
|
96
|
+
return content
|
|
97
|
+
.map((part) => (part?.type === "text" ? part.text : ""))
|
|
98
|
+
.filter(Boolean)
|
|
99
|
+
.join("\n")
|
|
100
|
+
.trim();
|
|
101
|
+
}
|
|
102
|
+
|
|
69
103
|
export async function runLocalAgentTurn(
|
|
70
104
|
input: LocalAgentTurnInput
|
|
71
105
|
): Promise<LocalAgentTurnResult> {
|
|
@@ -92,10 +126,13 @@ export async function runLocalAgentTurn(
|
|
|
92
126
|
});
|
|
93
127
|
const provider = await input.adapter.resolveProvider(agentConfig);
|
|
94
128
|
const maxToolRounds = input.maxToolRounds ?? DEFAULT_LOCAL_AGENT_MAX_TOOL_ROUNDS;
|
|
129
|
+
const userInputText = extractUserInputText(input.input);
|
|
95
130
|
let toolCallCount = 0;
|
|
96
131
|
let result: AgentRuntimeResult;
|
|
97
132
|
for (let round = 0; round <= maxToolRounds; round += 1) {
|
|
98
|
-
result = await provider.complete(messages
|
|
133
|
+
result = await provider.complete(messages, {
|
|
134
|
+
...(typeof input.timeoutMs === "number" ? { timeoutMs: input.timeoutMs } : {}),
|
|
135
|
+
});
|
|
99
136
|
const toolCalls = result.tool_calls ?? [];
|
|
100
137
|
if (toolCalls.length === 0) break;
|
|
101
138
|
if (round === maxToolRounds) {
|
|
@@ -122,6 +159,7 @@ export async function runLocalAgentTurn(
|
|
|
122
159
|
id: toolCall.id,
|
|
123
160
|
name: toolName,
|
|
124
161
|
arguments: toolCall.function.arguments,
|
|
162
|
+
...(userInputText ? { userInput: userInputText } : {}),
|
|
125
163
|
});
|
|
126
164
|
emitToolEvent(input, {
|
|
127
165
|
type: "tool-result",
|
|
@@ -140,11 +178,20 @@ export async function runLocalAgentTurn(
|
|
|
140
178
|
message: error instanceof Error ? error.message : String(error),
|
|
141
179
|
});
|
|
142
180
|
toolResult = {
|
|
143
|
-
content:
|
|
181
|
+
content:
|
|
182
|
+
formatStructuredToolExecutionError({ toolName, error }) ??
|
|
183
|
+
formatToolExecutionError({ toolName, error }),
|
|
144
184
|
metadata: {
|
|
145
185
|
error: true,
|
|
146
186
|
toolName,
|
|
147
187
|
message: error instanceof Error ? error.message : String(error),
|
|
188
|
+
...(
|
|
189
|
+
error &&
|
|
190
|
+
typeof error === "object" &&
|
|
191
|
+
typeof (error as { code?: unknown }).code === "string"
|
|
192
|
+
? { code: (error as { code: string }).code }
|
|
193
|
+
: {}
|
|
194
|
+
),
|
|
148
195
|
},
|
|
149
196
|
};
|
|
150
197
|
}
|
|
@@ -2,7 +2,8 @@ import type {
|
|
|
2
2
|
AgentRuntimeToolCallInput,
|
|
3
3
|
AgentRuntimeToolResult,
|
|
4
4
|
} from "./types";
|
|
5
|
-
import
|
|
5
|
+
import { canonicalizeToolName } from "../ai/tools/toolNameAliases";
|
|
6
|
+
import { evaluateShellCommandPolicy } from "./shellCommandPolicy";
|
|
6
7
|
|
|
7
8
|
type EnvLike = Record<string, string | undefined>;
|
|
8
9
|
|
|
@@ -49,6 +50,26 @@ function parseToolAllowlist(value: string | undefined) {
|
|
|
49
50
|
.filter(Boolean);
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
function normalizeLocalToolName(toolName: string) {
|
|
54
|
+
return canonicalizeToolName(
|
|
55
|
+
String(toolName ?? "").replace(/^functions\./, "").trim(),
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function parseShellCommandPayload(rawArguments: string) {
|
|
60
|
+
try {
|
|
61
|
+
const parsed = JSON.parse(rawArguments || "{}");
|
|
62
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
63
|
+
return parsed as { command?: unknown; cmd?: unknown; input?: unknown };
|
|
64
|
+
} catch {
|
|
65
|
+
return {};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function isLocalShellModeEnabled(env: EnvLike) {
|
|
70
|
+
return ["worktree", "dangerous", "1", "true"].includes(env.NOLO_LOCAL_SHELL_MODE || "");
|
|
71
|
+
}
|
|
72
|
+
|
|
52
73
|
function isRestrictedLocalToolMode(env: EnvLike) {
|
|
53
74
|
return env.NOLO_LOCAL_TOOL_MODE === "restricted";
|
|
54
75
|
}
|
|
@@ -66,84 +87,105 @@ function isToolDeclaredOrExplicitlyFree(args: {
|
|
|
66
87
|
|
|
67
88
|
export function resolveLocalToolPolicy(args: {
|
|
68
89
|
env: EnvLike;
|
|
69
|
-
hostRuntimeConfig?: HostRuntimeConfig;
|
|
70
90
|
agentToolNames?: string[];
|
|
71
91
|
toolName: string;
|
|
72
92
|
}): LocalToolPolicyDecision {
|
|
93
|
+
const toolName = normalizeLocalToolName(args.toolName);
|
|
73
94
|
const restrictedMode = isRestrictedLocalToolMode(args.env);
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
95
|
+
if (!toolName) {
|
|
96
|
+
return {
|
|
97
|
+
allowed: false,
|
|
98
|
+
toolName,
|
|
99
|
+
reason: "Tool name is required.",
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (toolName === "execShell") {
|
|
104
|
+
if (isLocalShellModeEnabled(args.env)) {
|
|
105
|
+
return { allowed: true, toolName };
|
|
84
106
|
}
|
|
85
107
|
return {
|
|
86
108
|
allowed: false,
|
|
87
|
-
toolName
|
|
88
|
-
reason: "execShell requires
|
|
109
|
+
toolName,
|
|
110
|
+
reason: "execShell requires NOLO_LOCAL_SHELL_MODE=worktree.",
|
|
89
111
|
};
|
|
90
112
|
}
|
|
91
113
|
|
|
92
|
-
if (NEVER_LOCAL_TOOLS.has(
|
|
114
|
+
if (NEVER_LOCAL_TOOLS.has(toolName)) {
|
|
93
115
|
return {
|
|
94
116
|
allowed: false,
|
|
95
|
-
toolName
|
|
96
|
-
reason: `${
|
|
117
|
+
toolName,
|
|
118
|
+
reason: `${toolName} is blocked by the local runtime safety policy.`,
|
|
97
119
|
};
|
|
98
120
|
}
|
|
99
121
|
|
|
100
|
-
if (REMOVED_LOCAL_TOOLS.has(
|
|
122
|
+
if (REMOVED_LOCAL_TOOLS.has(toolName)) {
|
|
101
123
|
return {
|
|
102
124
|
allowed: false,
|
|
103
|
-
toolName
|
|
104
|
-
reason: `${
|
|
125
|
+
toolName,
|
|
126
|
+
reason: `${toolName} has been removed from the local runtime tool surface. Use execShell in shell-enabled workspace runs when shell is needed.`,
|
|
105
127
|
};
|
|
106
128
|
}
|
|
107
129
|
|
|
108
130
|
const allowedByEnv = new Set(parseToolAllowlist(args.env.NOLO_LOCAL_ALLOWED_TOOLS));
|
|
109
|
-
const agentTools = new Set(
|
|
110
|
-
|
|
111
|
-
|
|
131
|
+
const agentTools = new Set(
|
|
132
|
+
(args.agentToolNames ?? []).map(normalizeLocalToolName).filter(Boolean),
|
|
133
|
+
);
|
|
134
|
+
if (!restrictedMode && agentTools.has(toolName)) {
|
|
135
|
+
return { allowed: true, toolName };
|
|
112
136
|
}
|
|
113
|
-
if (DEFAULT_LOCAL_TOOLS.has(
|
|
114
|
-
return { allowed: true, toolName
|
|
137
|
+
if (DEFAULT_LOCAL_TOOLS.has(toolName) && agentTools.has(toolName)) {
|
|
138
|
+
return { allowed: true, toolName };
|
|
115
139
|
}
|
|
116
|
-
if (allowedByEnv.has(
|
|
117
|
-
return { allowed: true, toolName
|
|
140
|
+
if (allowedByEnv.has(toolName) && agentTools.has(toolName)) {
|
|
141
|
+
return { allowed: true, toolName };
|
|
118
142
|
}
|
|
119
143
|
|
|
120
144
|
return {
|
|
121
145
|
allowed: false,
|
|
122
|
-
toolName
|
|
146
|
+
toolName,
|
|
123
147
|
reason:
|
|
124
|
-
`${
|
|
148
|
+
`${toolName} is not enabled for local runtime runs. ` +
|
|
125
149
|
"Set NOLO_LOCAL_ALLOWED_TOOLS and make sure the agent declares the tool before using it locally.",
|
|
126
150
|
};
|
|
127
151
|
}
|
|
128
152
|
|
|
129
153
|
export async function executeLocalToolWithPolicy(args: {
|
|
130
154
|
env: EnvLike;
|
|
131
|
-
hostRuntimeConfig?: HostRuntimeConfig;
|
|
132
155
|
agentToolNames?: string[];
|
|
133
156
|
call: AgentRuntimeToolCallInput;
|
|
134
157
|
executors?: Record<string, (call: AgentRuntimeToolCallInput) => Promise<AgentRuntimeToolResult>>;
|
|
135
158
|
}): Promise<AgentRuntimeToolResult> {
|
|
136
159
|
const decision = resolveLocalToolPolicy({
|
|
137
160
|
env: args.env,
|
|
138
|
-
hostRuntimeConfig: args.hostRuntimeConfig,
|
|
139
161
|
agentToolNames: args.agentToolNames,
|
|
140
162
|
toolName: args.call.name,
|
|
141
163
|
});
|
|
142
164
|
if (!decision.allowed) throw new Error(decision.reason);
|
|
143
165
|
|
|
144
|
-
const executor = args.executors?.[
|
|
166
|
+
const executor = args.executors?.[decision.toolName];
|
|
145
167
|
if (!executor) {
|
|
146
|
-
throw new Error(`${
|
|
168
|
+
throw new Error(`${decision.toolName} is allowed by policy but no local executor is registered.`);
|
|
147
169
|
}
|
|
148
|
-
|
|
170
|
+
if (decision.toolName === "execShell") {
|
|
171
|
+
const parsed = parseShellCommandPayload(args.call.arguments);
|
|
172
|
+
const shellPolicy = evaluateShellCommandPolicy({
|
|
173
|
+
command: parsed.command ?? parsed.cmd,
|
|
174
|
+
input: parsed.input,
|
|
175
|
+
userInput: args.call.userInput,
|
|
176
|
+
});
|
|
177
|
+
if (shellPolicy.verdict === "forbidden") {
|
|
178
|
+
const error = new Error(shellPolicy.reason) as Error & {
|
|
179
|
+
code?: string;
|
|
180
|
+
policy?: Record<string, unknown>;
|
|
181
|
+
};
|
|
182
|
+
error.code = shellPolicy.code;
|
|
183
|
+
error.policy = shellPolicy.policy;
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return executor({
|
|
188
|
+
...args.call,
|
|
189
|
+
name: decision.toolName,
|
|
190
|
+
});
|
|
149
191
|
}
|