nolo-cli 0.1.21 → 0.1.23
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/agent-runtime/agentRecordConfig.ts +4 -0
- package/agent-runtime/hostAdapter.ts +2 -0
- package/agent-runtime/index.ts +7 -0
- package/agent-runtime/localLoop.ts +2 -0
- package/agent-runtime/platformChatProvider.ts +3 -0
- package/agent-runtime/runtimeToolPolicy.ts +92 -0
- package/agent-runtime/types.ts +42 -0
- package/agentRunCommand.ts +74 -1
- package/agentRuntimeCommands.ts +17 -89
- package/ai/agent/streamAgentChatTurn.ts +104 -20
- package/ai/chat/fetchUtils.native.ts +2 -0
- package/ai/chat/fetchUtils.ts +2 -0
- package/ai/chat/sendOpenAICompletionsRequest.ts +56 -0
- package/ai/chat/sendOpenAIResponseRequest.ts +64 -0
- package/ai/llm/kimi.ts +1 -1
- package/ai/llm/providers.ts +3 -0
- package/ai/llm/reasoningModels.ts +1 -0
- package/ai/skills/skillDocProtocol.ts +95 -3
- package/ai/taskRun/taskRunProtocol.ts +1 -0
- package/ai/tools/agent/agentTools.ts +17 -0
- package/ai/tools/agent/startAgentDialogTool.ts +53 -0
- package/ai/tools/modelUsageTools.ts +5 -0
- package/client/agentRun.test.ts +257 -7
- package/client/agentRun.ts +133 -34
- package/client/localRuntimeAdapter.test.ts +2 -0
- package/client/localRuntimeAdapter.ts +15 -2
- package/database/actions/common.ts +4 -3
- package/database/config.ts +19 -0
- package/machineCommands.ts +400 -45
- package/package.json +4 -2
- package/render/canvas/canvasEditContext.ts +127 -0
- package/render/canvas/canvasRuntime.ts +57 -0
- package/render/canvas/canvasSnapshotParser.ts +76 -0
- package/render/canvas/canvasTree.ts +308 -0
- package/render/canvas/types.ts +46 -0
- package/render/layout/deleteBehavior.ts +52 -0
- package/render/layout/mainLayoutSidebar.ts +17 -0
- package/render/layout/mainLayoutViewMode.ts +56 -0
- package/render/layout/topbarUtils.ts +87 -0
- package/render/layout/useDevReloadPending.ts +30 -0
- package/render/page/createPageAction.ts +183 -0
- package/render/page/docSlice.ts +468 -0
- package/render/page/server/createPage.ts +174 -0
- package/render/page/server/handleCreatePage.ts +91 -0
- package/render/page/server/index.ts +4 -0
- package/render/page/types.ts +17 -0
- package/render/page/useKeyboardSave.ts +48 -0
- package/render/styles/zIndex.ts +12 -0
- package/render/surf/WeatherIconStyles.ts +17 -0
- package/render/surf/color.ts +9 -0
- package/render/surf/config.ts +46 -0
- package/render/surf/screens/style.ts +1 -0
- package/render/surf/styles/ToggleButtonStyles.ts +8 -0
- package/render/surf/utils/groupedWeatherData.ts +32 -0
- package/render/surf/weatherUtils.ts +50 -0
- package/render/table/activityColumns.ts +6 -0
- package/render/table/createTableAction.ts +270 -0
- package/render/table/deleteTableAction.ts +129 -0
- package/render/table/fetchAndCacheTableRows.ts +174 -0
- package/render/table/tableSlice.ts +1106 -0
- package/render/table/tableView.ts +289 -0
- package/render/table/toolValueUtils.ts +363 -0
- package/render/table/types.ts +252 -0
- package/render/table/useCreateTable.ts +72 -0
- package/render/table/useTable.ts +61 -0
- package/render/table/utils/tableSerialization.ts +50 -0
- package/render/web/elements/artifactPreviewCode.ts +43 -0
- package/render/web/elements/artifactRuntimePreload.ts +52 -0
- package/render/web/elements/codeBlockAutoPreview.ts +10 -0
- package/render/web/elements/mermaidPreview.ts +21 -0
- package/render/web/ui/useInlineEdit.ts +135 -0
- package/tableCommands.ts +42 -5
|
@@ -73,6 +73,9 @@ export function resolveAgentRuntimeConfigFromRecord(
|
|
|
73
73
|
const maxTokens = numberField(record, "max_tokens");
|
|
74
74
|
const reasoningEffort = stringField(record, "reasoning_effort");
|
|
75
75
|
const runtimeBinding = objectField(record, "runtimeBinding");
|
|
76
|
+
const runtimeToolPolicy =
|
|
77
|
+
objectField(record, "runtimeToolPolicy") ??
|
|
78
|
+
objectField(runtimeBinding ?? {}, "runtimeToolPolicy");
|
|
76
79
|
const localWorkspaceMode = localWorkspaceModeField(record);
|
|
77
80
|
const delegation = objectField(record, "delegation");
|
|
78
81
|
return {
|
|
@@ -92,6 +95,7 @@ export function resolveAgentRuntimeConfigFromRecord(
|
|
|
92
95
|
...(maxTokens !== undefined ? { max_tokens: maxTokens } : {}),
|
|
93
96
|
...(reasoningEffort ? { reasoning_effort: reasoningEffort } : {}),
|
|
94
97
|
...(runtimeBinding ? { runtimeBinding } : {}),
|
|
98
|
+
...(runtimeToolPolicy ? { runtimeToolPolicy } : {}),
|
|
95
99
|
...(localWorkspaceMode ? { localWorkspaceMode } : {}),
|
|
96
100
|
...(delegation ? { delegation } : {}),
|
|
97
101
|
rawRecord: record,
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
AgentRuntimeChatMessage,
|
|
3
3
|
AgentRuntimeHost,
|
|
4
4
|
AgentRuntimeResult,
|
|
5
|
+
AgentRuntimeToolPolicy,
|
|
5
6
|
} from "./types";
|
|
6
7
|
|
|
7
8
|
export type AgentRuntimeAgentConfig = {
|
|
@@ -21,6 +22,7 @@ export type AgentRuntimeAgentConfig = {
|
|
|
21
22
|
max_tokens?: number;
|
|
22
23
|
reasoning_effort?: string;
|
|
23
24
|
runtimeBinding?: Record<string, unknown>;
|
|
25
|
+
runtimeToolPolicy?: AgentRuntimeToolPolicy;
|
|
24
26
|
localWorkspaceMode?: "current" | "task-worktree";
|
|
25
27
|
delegation?: Record<string, unknown>;
|
|
26
28
|
rawRecord?: Record<string, unknown>;
|
package/agent-runtime/index.ts
CHANGED
|
@@ -45,6 +45,11 @@ export {
|
|
|
45
45
|
executeLocalToolWithPolicy,
|
|
46
46
|
resolveLocalToolPolicy,
|
|
47
47
|
} from "./localToolPolicy";
|
|
48
|
+
export {
|
|
49
|
+
mergeAgentRuntimeToolPolicies,
|
|
50
|
+
normalizeAgentRuntimeToolPolicy,
|
|
51
|
+
resolveEffectiveRuntimeToolPolicy,
|
|
52
|
+
} from "./runtimeToolPolicy";
|
|
48
53
|
export {
|
|
49
54
|
buildLocalWorkspaceOpenAiTools,
|
|
50
55
|
buildLocalWorkspacePolicyToolNames,
|
|
@@ -94,5 +99,7 @@ export type {
|
|
|
94
99
|
AgentRuntimeMode,
|
|
95
100
|
AgentRuntimeRequestedMode,
|
|
96
101
|
AgentRuntimeResult,
|
|
102
|
+
AgentRuntimeToolPolicy,
|
|
97
103
|
AgentRuntimeToolCall,
|
|
104
|
+
AgentRuntimeWorkspaceMode,
|
|
98
105
|
} from "./types";
|
|
@@ -26,6 +26,7 @@ export type LocalAgentToolEvent = {
|
|
|
26
26
|
toolCallId: string;
|
|
27
27
|
toolName: string;
|
|
28
28
|
message?: string;
|
|
29
|
+
metadata?: Record<string, unknown>;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
const DEFAULT_LOCAL_AGENT_MAX_TOOL_ROUNDS = 16;
|
|
@@ -119,6 +120,7 @@ export async function runLocalAgentTurn(
|
|
|
119
120
|
round,
|
|
120
121
|
toolCallId: toolCall.id,
|
|
121
122
|
toolName,
|
|
123
|
+
metadata: toolResult.metadata,
|
|
122
124
|
});
|
|
123
125
|
} catch (error) {
|
|
124
126
|
if (!shouldReturnToolExecutionErrors(input.adapter)) throw error;
|
|
@@ -23,6 +23,7 @@ const PROVIDER_ENDPOINTS: Record<string, string> = {
|
|
|
23
23
|
export type PlatformChatProviderConfig = {
|
|
24
24
|
serverUrl: string;
|
|
25
25
|
authToken: string;
|
|
26
|
+
agentKey: string;
|
|
26
27
|
model: string;
|
|
27
28
|
provider: string;
|
|
28
29
|
endpoint: string;
|
|
@@ -93,6 +94,7 @@ export function resolvePlatformChatProviderConfig(args: {
|
|
|
93
94
|
return {
|
|
94
95
|
serverUrl: resolvePlatformServerUrl(args.env),
|
|
95
96
|
authToken: resolvePlatformAuthToken(args.env),
|
|
97
|
+
agentKey: args.agentConfig.key,
|
|
96
98
|
model: args.agentConfig.model || "gpt-4.1-mini",
|
|
97
99
|
provider,
|
|
98
100
|
endpoint: resolveProviderEndpoint(args.agentConfig),
|
|
@@ -118,6 +120,7 @@ export function buildPlatformChatCompletionRequest(args: {
|
|
|
118
120
|
...(shouldDisableThinking(args.providerConfig) ? { thinking: { type: "disabled" } } : {}),
|
|
119
121
|
url: args.providerConfig.endpoint,
|
|
120
122
|
provider: args.providerConfig.provider,
|
|
123
|
+
agentKey: args.providerConfig.agentKey,
|
|
121
124
|
...(args.providerConfig.apiSource ? { apiSource: args.providerConfig.apiSource } : {}),
|
|
122
125
|
...(args.providerConfig.apiKey ? { KEY: args.providerConfig.apiKey } : {}),
|
|
123
126
|
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { AgentRuntimeAgentConfig } from "./hostAdapter";
|
|
2
|
+
import type { AgentRuntimeToolPolicy } from "./types";
|
|
3
|
+
|
|
4
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
5
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function stringArray(value: unknown): string[] {
|
|
9
|
+
if (!Array.isArray(value)) return [];
|
|
10
|
+
return value.filter((item): item is string => typeof item === "string" && !!item.trim());
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function unique(values: string[]) {
|
|
14
|
+
return [...new Set(values)];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function mergeRecords<T extends Record<string, unknown>>(
|
|
18
|
+
base: T | undefined,
|
|
19
|
+
override: T | undefined,
|
|
20
|
+
): T | undefined {
|
|
21
|
+
if (!base && !override) return undefined;
|
|
22
|
+
return {
|
|
23
|
+
...(base ?? {}),
|
|
24
|
+
...(override ?? {}),
|
|
25
|
+
} as T;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function normalizeAgentRuntimeToolPolicy(
|
|
29
|
+
value: unknown,
|
|
30
|
+
): AgentRuntimeToolPolicy | undefined {
|
|
31
|
+
if (!isRecord(value)) return undefined;
|
|
32
|
+
return {
|
|
33
|
+
version: 1,
|
|
34
|
+
...(stringArray(value.agentTools).length
|
|
35
|
+
? { agentTools: unique(stringArray(value.agentTools)) }
|
|
36
|
+
: {}),
|
|
37
|
+
...(stringArray(value.runtimeTools).length
|
|
38
|
+
? { runtimeTools: unique(stringArray(value.runtimeTools)) }
|
|
39
|
+
: {}),
|
|
40
|
+
...(isRecord(value.workspace) ? { workspace: { ...value.workspace } } : {}),
|
|
41
|
+
...(isRecord(value.shell) ? { shell: { ...value.shell } } : {}),
|
|
42
|
+
...(isRecord(value.git) ? { git: { ...value.git } } : {}),
|
|
43
|
+
...(isRecord(value.budget) ? { budget: { ...value.budget } } : {}),
|
|
44
|
+
...(isRecord(value.audit) ? { audit: { ...value.audit } } : {}),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function mergeAgentRuntimeToolPolicies(
|
|
49
|
+
base?: AgentRuntimeToolPolicy,
|
|
50
|
+
override?: AgentRuntimeToolPolicy,
|
|
51
|
+
): AgentRuntimeToolPolicy | undefined {
|
|
52
|
+
if (!base && !override) return undefined;
|
|
53
|
+
return {
|
|
54
|
+
version: 1,
|
|
55
|
+
agentTools: unique([
|
|
56
|
+
...(base?.agentTools ?? []),
|
|
57
|
+
...(override?.agentTools ?? []),
|
|
58
|
+
]),
|
|
59
|
+
runtimeTools: unique([
|
|
60
|
+
...(base?.runtimeTools ?? []),
|
|
61
|
+
...(override?.runtimeTools ?? []),
|
|
62
|
+
]),
|
|
63
|
+
workspace: {
|
|
64
|
+
...(base?.workspace ?? {}),
|
|
65
|
+
...(override?.workspace ?? {}),
|
|
66
|
+
writableRoots: unique([
|
|
67
|
+
...(base?.workspace?.writableRoots ?? []),
|
|
68
|
+
...(override?.workspace?.writableRoots ?? []),
|
|
69
|
+
]),
|
|
70
|
+
},
|
|
71
|
+
shell: mergeRecords(base?.shell, override?.shell),
|
|
72
|
+
git: mergeRecords(base?.git, override?.git),
|
|
73
|
+
budget: mergeRecords(base?.budget, override?.budget),
|
|
74
|
+
audit: mergeRecords(base?.audit, override?.audit),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function resolveEffectiveRuntimeToolPolicy(args: {
|
|
79
|
+
agentConfig: Pick<AgentRuntimeAgentConfig, "runtimeToolPolicy" | "runtimeBinding">;
|
|
80
|
+
taskRunControl?: { runtimeToolPolicy?: unknown } | null;
|
|
81
|
+
}): AgentRuntimeToolPolicy | undefined {
|
|
82
|
+
const agentPolicy = normalizeAgentRuntimeToolPolicy(
|
|
83
|
+
args.agentConfig.runtimeToolPolicy ??
|
|
84
|
+
(isRecord(args.agentConfig.runtimeBinding)
|
|
85
|
+
? args.agentConfig.runtimeBinding.runtimeToolPolicy
|
|
86
|
+
: undefined),
|
|
87
|
+
);
|
|
88
|
+
const taskPolicy = normalizeAgentRuntimeToolPolicy(
|
|
89
|
+
args.taskRunControl?.runtimeToolPolicy,
|
|
90
|
+
);
|
|
91
|
+
return mergeAgentRuntimeToolPolicies(agentPolicy, taskPolicy);
|
|
92
|
+
}
|
package/agent-runtime/types.ts
CHANGED
|
@@ -81,6 +81,48 @@ export type AgentRuntimeDecisionInput = {
|
|
|
81
81
|
serverFallbackAvailable: boolean;
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
+
export type AgentRuntimeWorkspaceMode = "none" | "current" | "task-worktree" | "lease";
|
|
85
|
+
|
|
86
|
+
export type AgentRuntimeShellPolicy = {
|
|
87
|
+
enabled?: boolean;
|
|
88
|
+
mode?: "off" | "worktree";
|
|
89
|
+
commandPolicy?: "denylist" | "allowlist" | "approval";
|
|
90
|
+
networkPolicy?: "default-deny" | "allowed" | "approval";
|
|
91
|
+
maxSeconds?: number;
|
|
92
|
+
maxOutputBytes?: number;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export type AgentRuntimeGitPolicy = {
|
|
96
|
+
canCommit?: boolean;
|
|
97
|
+
canPushAlpha?: boolean;
|
|
98
|
+
canMergeMain?: boolean;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export type AgentRuntimeAuditPolicy = {
|
|
102
|
+
logToolCalls?: boolean;
|
|
103
|
+
logShellCommands?: boolean;
|
|
104
|
+
writeToDialog?: boolean;
|
|
105
|
+
writeToTask?: boolean;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export type AgentRuntimeToolPolicy = {
|
|
109
|
+
version?: 1;
|
|
110
|
+
agentTools?: string[];
|
|
111
|
+
runtimeTools?: string[];
|
|
112
|
+
workspace?: {
|
|
113
|
+
mode?: AgentRuntimeWorkspaceMode;
|
|
114
|
+
writableRoots?: string[];
|
|
115
|
+
cwd?: string;
|
|
116
|
+
};
|
|
117
|
+
shell?: AgentRuntimeShellPolicy;
|
|
118
|
+
git?: AgentRuntimeGitPolicy;
|
|
119
|
+
budget?: {
|
|
120
|
+
dailyUsdLimit?: number;
|
|
121
|
+
maxRunSeconds?: number;
|
|
122
|
+
};
|
|
123
|
+
audit?: AgentRuntimeAuditPolicy;
|
|
124
|
+
};
|
|
125
|
+
|
|
84
126
|
export type AgentRuntimeDecision = {
|
|
85
127
|
mode: AgentRuntimeMode;
|
|
86
128
|
runnable: boolean;
|
package/agentRunCommand.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { runAgentTurn, type RunAgentTurnResult } from "./client/agentRun";
|
|
|
3
3
|
import type { AgentRuntimeHostAdapter, AgentRuntimeRequestedMode } from "./agentRuntimeLocal";
|
|
4
4
|
import { existsSync, readFileSync } from "node:fs";
|
|
5
5
|
import { extname, resolve } from "node:path";
|
|
6
|
+
import { parseSkillDocProtocol, type WorkflowReferenceConfig } from "./ai/skills/skillDocProtocol";
|
|
6
7
|
import { resolveCliAgentKeyInput } from "./agentAliases";
|
|
7
8
|
import {
|
|
8
9
|
ensureWorkspacePackageLinks,
|
|
@@ -27,6 +28,7 @@ type AgentRunCommandDeps = {
|
|
|
27
28
|
prepareTaskWorktree?: typeof prepareTaskWorktree;
|
|
28
29
|
ensureWorkspacePackageLinks?: typeof ensureWorkspacePackageLinks;
|
|
29
30
|
inspectLocalRunWorkspace?: typeof inspectLocalRunWorkspace;
|
|
31
|
+
resolveWorkflowReference?: typeof resolveWorkflowReference;
|
|
30
32
|
};
|
|
31
33
|
|
|
32
34
|
type LocalRunWorkspaceInspection = {
|
|
@@ -63,6 +65,13 @@ type ParsedAgentRunArgs = {
|
|
|
63
65
|
traceTools: boolean;
|
|
64
66
|
useTaskWorktree: boolean;
|
|
65
67
|
taskRunContext?: TaskRunPromptContext;
|
|
68
|
+
workflowRef?: string;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
type ResolvedWorkflowReference = {
|
|
72
|
+
ref: string;
|
|
73
|
+
content: string;
|
|
74
|
+
config?: Partial<WorkflowReferenceConfig>;
|
|
66
75
|
};
|
|
67
76
|
|
|
68
77
|
const DEFAULT_TEST_ROOT_DIALOG_ID = "01KN6V3MVEQA4Q1PNKVM2W7YY8";
|
|
@@ -171,6 +180,7 @@ export function parseAgentRunArgs(
|
|
|
171
180
|
...readRepeatedFlagValues(args, "--image-url"),
|
|
172
181
|
];
|
|
173
182
|
const useTaskWorktree = args.includes("--worktree-task");
|
|
183
|
+
const workflowRef = readFlagValue(args, "--workflow");
|
|
174
184
|
const taskRowDbKey = readFlagValue(args, "--task-row-dbkey");
|
|
175
185
|
const artifactIds = readFlagValue(args, "--artifact-ids")
|
|
176
186
|
?.split(",")
|
|
@@ -183,6 +193,7 @@ export function parseAgentRunArgs(
|
|
|
183
193
|
allowShell: args.includes("--dangerously-allow-shell"),
|
|
184
194
|
traceTools: args.includes("--trace-tools"),
|
|
185
195
|
useTaskWorktree,
|
|
196
|
+
...(workflowRef ? { workflowRef } : {}),
|
|
186
197
|
...(taskRowDbKey
|
|
187
198
|
? {
|
|
188
199
|
taskRunContext: {
|
|
@@ -208,6 +219,57 @@ export function parseAgentRunArgs(
|
|
|
208
219
|
};
|
|
209
220
|
}
|
|
210
221
|
|
|
222
|
+
function workflowRefToCandidatePath(cwd: string, ref: string) {
|
|
223
|
+
const normalized = ref.trim();
|
|
224
|
+
if (!normalized) return "";
|
|
225
|
+
if (normalized.endsWith(".md") || normalized.includes("/") || normalized.includes("\\")) {
|
|
226
|
+
const directPath = resolve(cwd, normalized);
|
|
227
|
+
if (existsSync(directPath)) return directPath;
|
|
228
|
+
}
|
|
229
|
+
const fileName = normalized.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]+/g, "-").replace(/^-+|-+$/g, "");
|
|
230
|
+
return resolve(cwd, "docs", "workflows", `${fileName}.md`);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export async function resolveWorkflowReference(ref: string, cwd = process.cwd()): Promise<ResolvedWorkflowReference> {
|
|
234
|
+
const path = workflowRefToCandidatePath(cwd, ref);
|
|
235
|
+
if (!path || !existsSync(path)) {
|
|
236
|
+
throw new Error(`Workflow reference not found: ${ref}`);
|
|
237
|
+
}
|
|
238
|
+
const markdown = readFileSync(path, "utf8");
|
|
239
|
+
const parsed = parseSkillDocProtocol(markdown);
|
|
240
|
+
return {
|
|
241
|
+
ref,
|
|
242
|
+
content: parsed.content,
|
|
243
|
+
...(parsed.meta?.workflowConfig ? { config: parsed.meta.workflowConfig } : {}),
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function prependWorkflowReferencePrompt(message: string, workflow?: ResolvedWorkflowReference): string {
|
|
248
|
+
if (!workflow) return message;
|
|
249
|
+
const config = workflow.config;
|
|
250
|
+
return [
|
|
251
|
+
"AI-native workflow reference:",
|
|
252
|
+
"- This reference is guidance for the agent, not a central workflow engine.",
|
|
253
|
+
`- ref: ${workflow.ref}`,
|
|
254
|
+
...(config?.id ? [`- id: ${config.id}`] : []),
|
|
255
|
+
...(config?.name ? [`- name: ${config.name}`] : []),
|
|
256
|
+
...(config?.defaultAgent ? [`- suggested defaultAgent: ${config.defaultAgent}`] : []),
|
|
257
|
+
...(config?.inputs?.length ? [`- inputs: ${config.inputs.join(", ")}`] : []),
|
|
258
|
+
...(config?.recommendedTools?.length ? [`- recommendedTools: ${config.recommendedTools.join(", ")}`] : []),
|
|
259
|
+
...(config?.requiredTools?.length ? [`- requiredTools: ${config.requiredTools.join(", ")}`] : []),
|
|
260
|
+
...(config?.requiredOutputs?.length ? [`- requiredOutputs: ${config.requiredOutputs.join(", ")}`] : []),
|
|
261
|
+
...(config?.gates?.length ? [`- gates: ${config.gates.join(", ")}`] : []),
|
|
262
|
+
...(config?.contextStrategy ? [`- contextStrategy: ${config.contextStrategy}`] : []),
|
|
263
|
+
...(config?.failureProtocol ? [`- failureProtocol: ${config.failureProtocol}`] : []),
|
|
264
|
+
"",
|
|
265
|
+
"Reference body:",
|
|
266
|
+
workflow.content,
|
|
267
|
+
"",
|
|
268
|
+
"User task:",
|
|
269
|
+
message,
|
|
270
|
+
].join("\n");
|
|
271
|
+
}
|
|
272
|
+
|
|
211
273
|
function parseDialogReference(rawInput: string) {
|
|
212
274
|
const normalized = rawInput.trim();
|
|
213
275
|
if (normalized.startsWith("dialog-")) {
|
|
@@ -353,6 +415,17 @@ export async function runAgentRunCommand(args: string[], deps: AgentRunCommandDe
|
|
|
353
415
|
}
|
|
354
416
|
|
|
355
417
|
const runner = deps.runner ?? runAgentTurn;
|
|
418
|
+
let workflowReference: ResolvedWorkflowReference | undefined;
|
|
419
|
+
if (parsed.workflowRef) {
|
|
420
|
+
try {
|
|
421
|
+
workflowReference = await (deps.resolveWorkflowReference ?? resolveWorkflowReference)(
|
|
422
|
+
parsed.workflowRef
|
|
423
|
+
);
|
|
424
|
+
} catch (error) {
|
|
425
|
+
output.write(`[nolo] ${error instanceof Error ? error.message : String(error)}\n`);
|
|
426
|
+
return 1;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
356
429
|
let localRuntimeCwd = parsed.cwd;
|
|
357
430
|
if (shouldPrepareTaskWorktree(parsed)) {
|
|
358
431
|
try {
|
|
@@ -399,7 +472,7 @@ export async function runAgentRunCommand(args: string[], deps: AgentRunCommandDe
|
|
|
399
472
|
agentName: parsed.agentKey,
|
|
400
473
|
agentKey: parsed.agentKey,
|
|
401
474
|
serverUrl: resolveServerUrl(env),
|
|
402
|
-
message: parsed.message,
|
|
475
|
+
message: prependWorkflowReferencePrompt(parsed.message, workflowReference),
|
|
403
476
|
imageUrls: parsed.imageUrls.map(normalizeCliImageInput),
|
|
404
477
|
scriptDir: deps.scriptDir,
|
|
405
478
|
env: runEnv,
|
package/agentRuntimeCommands.ts
CHANGED
|
@@ -2,19 +2,11 @@ import type { MachineHeartbeat } from "./connector-experimental/protocol";
|
|
|
2
2
|
import { detectMachineInfo } from "./connector-experimental/machineInfo";
|
|
3
3
|
import { resolveAgentRuntimeDecision } from "./agent-runtime/runtimeDecision";
|
|
4
4
|
import { resolveCliLocalRuntimeDbPath } from "./localRuntimeDb";
|
|
5
|
-
import {
|
|
6
|
-
assertMachineRunAllowed,
|
|
7
|
-
buildMachinePermissionPromptBlock,
|
|
8
|
-
resolveMachineRunPermissionPolicy,
|
|
9
|
-
} from "./ai/agent/machineRunPermissions";
|
|
5
|
+
import { resolveMachineRunPermissionPolicy } from "./ai/agent/machineRunPermissions";
|
|
10
6
|
import { resolveConnectorWebSocketTarget } from "./connectorWebSocketTarget";
|
|
11
7
|
import { DEFAULT_NOLO_SERVER_URL } from "./defaultServer";
|
|
12
8
|
import { resolveCliAgentKeyInput } from "./agentAliases";
|
|
13
|
-
import {
|
|
14
|
-
collectConnectorRunArtifact,
|
|
15
|
-
readConnectorGitHead,
|
|
16
|
-
resolveConnectorRunCwd,
|
|
17
|
-
} from "./connectorRunArtifact";
|
|
9
|
+
import { handleConnectorRunMessage } from "./machineCommands";
|
|
18
10
|
|
|
19
11
|
type EnvLike = Record<string, string | undefined>;
|
|
20
12
|
type OutputLike = { write(chunk: string): unknown };
|
|
@@ -138,22 +130,6 @@ function detectLaunchableMachineInfo() {
|
|
|
138
130
|
return detectMachineInfo({ probeLaunchable: true });
|
|
139
131
|
}
|
|
140
132
|
|
|
141
|
-
function buildConnectorCliPrompt(agentConfig: any, userInput: string) {
|
|
142
|
-
const policy = resolveMachineRunPermissionPolicy(agentConfig);
|
|
143
|
-
return [
|
|
144
|
-
typeof agentConfig?.prompt === "string" ? agentConfig.prompt.trim() : "",
|
|
145
|
-
buildMachinePermissionPromptBlock(policy),
|
|
146
|
-
`--- User task ---\n${userInput}`,
|
|
147
|
-
].filter(Boolean).join("\n\n");
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function normalizeConnectorRunTimeoutMs(value: unknown): number | undefined {
|
|
151
|
-
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
152
|
-
return undefined;
|
|
153
|
-
}
|
|
154
|
-
return Math.floor(value);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
133
|
function requiredCapabilityForAgent(agent: any) {
|
|
158
134
|
if (agent?.apiSource !== "cli") return "";
|
|
159
135
|
const cliProvider = String(agent?.cliProvider || "").trim();
|
|
@@ -255,64 +231,6 @@ async function defaultConnectWebSocket(url: string, options: SmokeWebSocketOptio
|
|
|
255
231
|
});
|
|
256
232
|
}
|
|
257
233
|
|
|
258
|
-
async function handleSmokeConnectorMessage(
|
|
259
|
-
message: string,
|
|
260
|
-
send: (message: string) => void,
|
|
261
|
-
executeCli: LocalCliExecutor
|
|
262
|
-
) {
|
|
263
|
-
let parsed: any;
|
|
264
|
-
try {
|
|
265
|
-
parsed = JSON.parse(message);
|
|
266
|
-
} catch {
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
if (parsed?.type !== "agent.run" || typeof parsed.requestId !== "string") return;
|
|
270
|
-
const agentConfig = parsed.payload?.agentConfig ?? {};
|
|
271
|
-
try {
|
|
272
|
-
if (agentConfig.apiSource !== "cli") {
|
|
273
|
-
throw new Error("Connector can only execute CLI agents. Set the agent apiSource to cli and choose a cliProvider.");
|
|
274
|
-
}
|
|
275
|
-
const provider = String(agentConfig.cliProvider || "copilot");
|
|
276
|
-
const policy = resolveMachineRunPermissionPolicy(agentConfig);
|
|
277
|
-
const userInput = String(parsed.payload?.userInput ?? "");
|
|
278
|
-
const timeout = normalizeConnectorRunTimeoutMs(parsed.payload?.timeoutMs);
|
|
279
|
-
assertMachineRunAllowed(userInput, policy);
|
|
280
|
-
const cwd = resolveConnectorRunCwd({ env: process.env, policy });
|
|
281
|
-
const baseSha = await readConnectorGitHead(cwd);
|
|
282
|
-
const result = await executeCli(
|
|
283
|
-
provider,
|
|
284
|
-
buildConnectorCliPrompt(agentConfig, userInput),
|
|
285
|
-
{
|
|
286
|
-
model: agentConfig.model || undefined,
|
|
287
|
-
timeout,
|
|
288
|
-
cwd,
|
|
289
|
-
yolo: true,
|
|
290
|
-
}
|
|
291
|
-
);
|
|
292
|
-
const artifacts = await collectConnectorRunArtifact({
|
|
293
|
-
cwd,
|
|
294
|
-
baseSha,
|
|
295
|
-
exitStatus: "completed",
|
|
296
|
-
});
|
|
297
|
-
send(JSON.stringify({
|
|
298
|
-
type: "agent.run.result",
|
|
299
|
-
requestId: parsed.requestId,
|
|
300
|
-
result: {
|
|
301
|
-
content: result.text,
|
|
302
|
-
model: agentConfig.model ?? provider,
|
|
303
|
-
trace: [{ role: "assistant", content: result.text }],
|
|
304
|
-
artifacts,
|
|
305
|
-
},
|
|
306
|
-
}));
|
|
307
|
-
} catch (error) {
|
|
308
|
-
send(JSON.stringify({
|
|
309
|
-
type: "agent.run.result",
|
|
310
|
-
requestId: parsed.requestId,
|
|
311
|
-
error: error instanceof Error ? error.message : String(error),
|
|
312
|
-
}));
|
|
313
|
-
}
|
|
314
|
-
}
|
|
315
|
-
|
|
316
234
|
async function readAgentRecord(args: {
|
|
317
235
|
agentKey: string;
|
|
318
236
|
authToken: string;
|
|
@@ -625,11 +543,21 @@ export async function runAgentSmokeCurrentCommand(
|
|
|
625
543
|
{
|
|
626
544
|
headers: { Authorization: `Bearer ${authToken}` },
|
|
627
545
|
sentMessages,
|
|
628
|
-
onMessage: (message) =>
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
546
|
+
onMessage: (message) => handleConnectorRunMessage(
|
|
547
|
+
machine,
|
|
548
|
+
message,
|
|
549
|
+
(response) => sentMessages.push(response),
|
|
550
|
+
deps.executeCli ?? defaultExecuteCli,
|
|
551
|
+
{
|
|
552
|
+
...env,
|
|
553
|
+
NOLO_SERVER: serverUrl,
|
|
554
|
+
NOLO_SERVER_URL: serverUrl,
|
|
555
|
+
BASE_URL: serverUrl,
|
|
556
|
+
AUTH_TOKEN: authToken,
|
|
557
|
+
NOLO_MACHINE_API_KEY: authToken,
|
|
558
|
+
},
|
|
559
|
+
fetchImpl
|
|
560
|
+
),
|
|
633
561
|
onOpen: async () => {
|
|
634
562
|
const res = await fetchImpl(`${serverUrl}/api/agent/run`, {
|
|
635
563
|
method: "POST",
|