nolo-cli 0.1.32 → 0.1.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -6
- package/agent-runtime/agentRecordConfig.ts +2 -0
- package/agent-runtime/hostAdapter.ts +1 -0
- package/agent-runtime/index.ts +0 -21
- package/agent-runtime/localToolPolicy.ts +6 -13
- package/agent-runtime/localWorkspaceTools.ts +30 -333
- package/agent-runtime/platformChatProvider.ts +1 -4
- package/agent-runtime/runtimeToolPolicy.ts +47 -32
- package/agentAliases.ts +14 -83
- package/agentCommandSupport.ts +3 -6
- package/agentInternalCommandEntries.ts +2 -13
- package/agentListCommands.ts +19 -28
- package/agentMachineCommands.ts +40 -336
- package/agentPullCommand.ts +36 -56
- package/agentRecordCommands.ts +3 -5
- package/agentRecordHelpers.ts +22 -189
- package/agentRunCommand.ts +438 -107
- package/agentRuntimeLocal.ts +0 -10
- package/ai/agent/cliExecutor.ts +19 -323
- package/authCommands.ts +2 -36
- package/cli/agentAliases.ts +14 -83
- package/cli/agentCommandSupport.ts +3 -6
- package/cli/agentInternalCommandEntries.ts +2 -13
- package/cli/agentListCommands.ts +19 -28
- package/cli/agentMachineCommands.ts +40 -336
- package/cli/agentPullCommand.ts +36 -56
- package/cli/agentRecordCommands.ts +3 -5
- package/cli/agentRecordHelpers.ts +22 -189
- package/cli/agentRunCommand.ts +438 -107
- package/cli/agentRuntimeLocal.ts +0 -10
- package/cli/authCommands.ts +2 -36
- package/cli/cliEnvHelpers.ts +21 -162
- package/cli/client/agentRun.ts +853 -57
- package/cli/client/localRuntimeAdapter.ts +22 -159
- package/cli/client/streamingOutput.ts +3 -1
- package/cli/client/taskRunPrompt.ts +24 -7
- package/cli/commandRegistry.ts +2 -3
- package/cli/connectorRunArtifact.ts +10 -34
- package/cli/connectorWebSocketTarget.ts +6 -10
- package/cli/internalCommandEntries.ts +0 -8
- package/cli/localRuntimeDb.ts +2 -39
- package/cli/machineCommands.ts +189 -190
- package/cli/machineDaemonCommands.ts +165 -9
- package/cli/machineHeartbeatCommands.ts +2 -1
- package/cli/machineStatusCommands.ts +13 -5
- package/cli/machineWatchCommands.ts +1 -1
- package/cli/machineWsRunDispatch.ts +14 -48
- package/cli/machineWsSession.ts +0 -2
- package/cli/offlineMarxistsAgentCommand.ts +314 -0
- package/cli/runtimeDoctorCommands.ts +69 -18
- package/cli/scriptCommandEntries.ts +45 -5
- package/cli/tableCommands.ts +133 -33
- package/cli/taskRunCommand.ts +211 -16
- package/cli/tui/session.ts +372 -43
- package/cli/workflowInternalCommandEntries.ts +0 -20
- package/cliEnvHelpers.ts +21 -162
- package/client/agentConfigResolver.test.ts +2 -0
- package/client/agentRun.test.ts +12 -208
- package/client/agentRun.ts +853 -57
- package/client/localRuntimeAdapter.test.ts +9 -168
- package/client/localRuntimeAdapter.ts +22 -159
- package/client/localToolPolicy.test.ts +4 -28
- package/client/streamingOutput.ts +3 -1
- package/client/taskRunPrompt.ts +24 -7
- package/commandRegistry.ts +2 -3
- package/connectorRunArtifact.ts +10 -34
- package/connectorWebSocketTarget.ts +6 -10
- package/database/server/db.ts +34 -15
- package/internalCommandEntries.ts +0 -8
- package/localRuntimeDb.ts +2 -39
- package/machineCommands.ts +189 -190
- package/machineDaemonCommands.ts +165 -9
- package/machineHeartbeatCommands.ts +2 -1
- package/machineStatusCommands.ts +13 -5
- package/machineWatchCommands.ts +1 -1
- package/machineWsRunDispatch.ts +14 -48
- package/machineWsSession.ts +0 -2
- package/offlineMarxistsAgentCommand.ts +314 -0
- package/package.json +49 -193
- package/runtimeDoctorCommands.ts +69 -18
- package/scriptCommandEntries.ts +45 -5
- package/tableCommands.ts +133 -33
- package/taskRunCommand.ts +211 -16
- package/tui/session.ts +372 -43
- package/workflowInternalCommandEntries.ts +0 -20
- package/agent-runtime/dialogStatus.ts +0 -139
- package/agent-runtime/hostRuntimeConfig.ts +0 -86
- package/agentCreateCustomCommands.ts +0 -278
- package/agentDialogsCommands.ts +0 -227
- package/agentDoctorCommands.ts +0 -203
- package/agentRunLocalWorkspace.ts +0 -182
- package/agentRunParsing.ts +0 -298
- package/agentSuperviseCommands.ts +0 -8
- package/agentUnpublishCommands.ts +0 -113
- package/ai/agent/agentRunDialogLineage.ts +0 -56
- package/ai/policy/types.ts +0 -64
- package/ai/skills/skillSummaryMarker.ts +0 -26
- package/app/types.ts +0 -358
- package/build.ts +0 -16
- package/buildPublish.ts +0 -138
- package/buildPublishArtifactAssembly.ts +0 -724
- package/buildPublishImportAnalysis.ts +0 -242
- package/chat/messages/fetchMessages.ts +0 -84
- package/chat/messages/types.ts +0 -185
- package/cli/agentCreateCustomCommands.ts +0 -278
- package/cli/agentDialogsCommands.ts +0 -227
- package/cli/agentDoctorCommands.ts +0 -203
- package/cli/agentRunLocalWorkspace.ts +0 -182
- package/cli/agentRunParsing.ts +0 -298
- package/cli/agentSuperviseCommands.ts +0 -8
- package/cli/agentUnpublishCommands.ts +0 -113
- package/cli/buildPublish.ts +0 -138
- package/cli/buildPublishArtifactAssembly.ts +0 -724
- package/cli/buildPublishImportAnalysis.ts +0 -242
- package/cli/cliIoTypes.ts +0 -3
- package/cli/cliRuntimeDoctorReport.ts +0 -193
- package/cli/client/agentRunInput.ts +0 -10
- package/cli/client/agentRunLocalExecution.ts +0 -124
- package/cli/client/agentRunLocalExecutor.ts +0 -179
- package/cli/client/agentRunRuntimeSelection.ts +0 -145
- package/cli/client/agentRunServerTransport.ts +0 -397
- package/cli/client/agentRunTaskRunRecorder.ts +0 -176
- package/cli/customCodingAgentFlow.ts +0 -208
- package/cli/customCodingAgentRecord.ts +0 -179
- package/cli/dialogDataAccess.ts +0 -186
- package/cli/dialogInternalCommandEntries.ts +0 -11
- package/cli/dialogReadCommands.ts +0 -180
- package/cli/dialogReadHelpers.ts +0 -226
- package/cli/dialogStatusCommands.ts +0 -123
- package/cli/docInternalCommandEntries.ts +0 -20
- package/cli/hybridReadHelpers.ts +0 -109
- package/cli/machineCommandPrompts.ts +0 -79
- package/cli/machineCommandResolution.ts +0 -43
- package/cli/noloReadBridgePrompt.ts +0 -16
- package/cli/pageCreateCommands.ts +0 -219
- package/cli/pageDeleteCommands.ts +0 -167
- package/cli/pageReadCommands.ts +0 -151
- package/cli/pageUpdateCommands.ts +0 -249
- package/cli/pageWriteHelpers.ts +0 -209
- package/cli/publishPackage.ts +0 -36
- package/cli/runtimeInternalCommandEntries.ts +0 -15
- package/cli/runtimePassthroughCommands.ts +0 -22
- package/cli/scriptPassthroughHelpers.ts +0 -28
- package/cli/secretScanHelpers.ts +0 -31
- package/cli/spaceAttachCommands.ts +0 -134
- package/cli/spaceCategoryCommands.ts +0 -263
- package/cli/spaceCommands.ts +0 -295
- package/cli/spaceDeleteCommands.ts +0 -312
- package/cli/spaceInternalCommandEntries.ts +0 -21
- package/cli/spaceMutationHelpers.ts +0 -135
- package/cli/spaceReadCommands.ts +0 -323
- package/cli/tableDataOutput.ts +0 -41
- package/cli/tableDataSafety.ts +0 -26
- package/cli/tableMetaCommands.ts +0 -307
- package/cli/tableMutationCommands.ts +0 -266
- package/cli/tableQueryParsing.ts +0 -90
- package/cli/tableQueryRequest.ts +0 -53
- package/cli/taskRunActions.ts +0 -122
- package/cli/taskRunParsing.ts +0 -86
- package/cli/taskRunPromptShared.ts +0 -55
- package/cli/tui/tuiCatalog.ts +0 -22
- package/cli/tui/tuiCommandInterpreter.ts +0 -253
- package/cli/tui/tuiPresentation.ts +0 -146
- package/cliIoTypes.ts +0 -3
- package/cliRuntimeDoctorReport.ts +0 -193
- package/client/agentRunInput.ts +0 -10
- package/client/agentRunLocalExecution.test.ts +0 -123
- package/client/agentRunLocalExecution.ts +0 -124
- package/client/agentRunLocalExecutor.ts +0 -179
- package/client/agentRunRuntimeSelection.test.ts +0 -159
- package/client/agentRunRuntimeSelection.ts +0 -145
- package/client/agentRunServerTransport.ts +0 -397
- package/client/agentRunTaskRunRecorder.ts +0 -176
- package/connector-experimental/daemonLauncher.ts +0 -223
- package/create/space/spaceKeys.ts +0 -65
- package/create/types.ts +0 -21
- package/customCodingAgentFlow.ts +0 -208
- package/customCodingAgentRecord.ts +0 -179
- package/database/keys.ts +0 -765
- package/database/server/authorityStoreTypes.ts +0 -31
- package/database/server/legacyServerDb.ts +0 -58
- package/database/server/levelAuthorityStore.ts +0 -75
- package/database/server/memoryAuthorityStore.ts +0 -133
- package/database/server/serverStoreFactory.ts +0 -124
- package/database/tombstones.ts +0 -52
- package/database/utils/ulid.ts +0 -1
- package/dialogDataAccess.ts +0 -186
- package/dialogInternalCommandEntries.ts +0 -11
- package/dialogReadCommands.ts +0 -180
- package/dialogReadHelpers.ts +0 -226
- package/dialogStatusCommands.ts +0 -123
- package/docInternalCommandEntries.ts +0 -20
- package/hybridReadHelpers.ts +0 -109
- package/machineCommandPrompts.ts +0 -79
- package/machineCommandResolution.ts +0 -43
- package/noloReadBridgePrompt.ts +0 -16
- package/pageCreateCommands.ts +0 -219
- package/pageDeleteCommands.ts +0 -167
- package/pageReadCommands.ts +0 -151
- package/pageUpdateCommands.ts +0 -249
- package/pageWriteHelpers.ts +0 -209
- package/publishPackage.ts +0 -36
- package/runtimeInternalCommandEntries.ts +0 -15
- package/runtimePassthroughCommands.ts +0 -22
- package/scriptPassthroughHelpers.ts +0 -28
- package/secretScanHelpers.ts +0 -31
- package/share/helpers.ts +0 -302
- package/share/keys.ts +0 -243
- package/share/types.ts +0 -100
- package/spaceAttachCommands.ts +0 -134
- package/spaceCategoryCommands.ts +0 -263
- package/spaceCommands.ts +0 -295
- package/spaceDeleteCommands.ts +0 -312
- package/spaceInternalCommandEntries.ts +0 -21
- package/spaceMutationHelpers.ts +0 -135
- package/spaceReadCommands.ts +0 -323
- package/tableDataOutput.ts +0 -41
- package/tableDataSafety.ts +0 -26
- package/tableMetaCommands.ts +0 -307
- package/tableMutationCommands.ts +0 -266
- package/tableQueryParsing.ts +0 -90
- package/tableQueryRequest.ts +0 -53
- package/taskRunActions.ts +0 -122
- package/taskRunParsing.ts +0 -86
- package/taskRunPromptShared.ts +0 -55
- package/tui/tuiCatalog.ts +0 -22
- package/tui/tuiCommandInterpreter.test.ts +0 -169
- package/tui/tuiCommandInterpreter.ts +0 -253
- package/tui/tuiPresentation.test.ts +0 -154
- package/tui/tuiPresentation.ts +0 -146
package/cli/tableCommands.ts
CHANGED
|
@@ -1,21 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
parseJsonOption,
|
|
7
|
-
parseJsonOptionAlias,
|
|
8
|
-
parseJwtTenantId,
|
|
9
|
-
parseOutputMode,
|
|
10
|
-
parseTableArg,
|
|
11
|
-
readOption,
|
|
12
|
-
resolveAuthToken,
|
|
13
|
-
resolveServerUrl,
|
|
14
|
-
} from "./tableQueryParsing";
|
|
15
|
-
import {
|
|
16
|
-
buildTableQueryRequest,
|
|
17
|
-
mergeQueryShortcutFilters,
|
|
18
|
-
} from "./tableQueryRequest";
|
|
1
|
+
import { DEFAULT_NOLO_SERVER_URL } from "./defaultServer";
|
|
2
|
+
import { includeTableActivityColumns } from "../render/table/activityColumns";
|
|
3
|
+
|
|
4
|
+
type EnvLike = Record<string, string | undefined>;
|
|
5
|
+
type OutputLike = { write(chunk: string): unknown };
|
|
19
6
|
|
|
20
7
|
type TableCommandDeps = {
|
|
21
8
|
env?: EnvLike;
|
|
@@ -23,6 +10,121 @@ type TableCommandDeps = {
|
|
|
23
10
|
fetchImpl?: typeof fetch;
|
|
24
11
|
};
|
|
25
12
|
|
|
13
|
+
type OutputMode = "full" | "raw" | "items" | "jsonl";
|
|
14
|
+
|
|
15
|
+
function readOption(args: string[], flag: string): string {
|
|
16
|
+
for (let i = 0; i < args.length; i++) {
|
|
17
|
+
const value = args[i];
|
|
18
|
+
if (value === flag) return args[i + 1] ?? "";
|
|
19
|
+
if (value.startsWith(`${flag}=`)) return value.slice(flag.length + 1);
|
|
20
|
+
}
|
|
21
|
+
return "";
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function hasFlag(args: string[], flag: string): boolean {
|
|
25
|
+
return args.includes(flag);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function parseJsonOption<T>(args: string[], flag: string): T | undefined {
|
|
29
|
+
const raw = readOption(args, flag);
|
|
30
|
+
if (!raw) return undefined;
|
|
31
|
+
try {
|
|
32
|
+
return JSON.parse(raw) as T;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
throw new Error(`${flag} must be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function parseJsonOptionAlias<T>(args: string[], primaryFlag: string, aliasFlag: string): T | undefined {
|
|
39
|
+
const primary = readOption(args, primaryFlag);
|
|
40
|
+
const alias = readOption(args, aliasFlag);
|
|
41
|
+
const raw = primary || alias;
|
|
42
|
+
if (!raw) return undefined;
|
|
43
|
+
try {
|
|
44
|
+
return JSON.parse(raw) as T;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
const usedFlag = primary ? primaryFlag : aliasFlag;
|
|
47
|
+
throw new Error(`${usedFlag} must be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function parseOutputMode(raw: string): OutputMode {
|
|
52
|
+
if (!raw) return "full";
|
|
53
|
+
if (raw === "json") return "raw";
|
|
54
|
+
if (raw === "full" || raw === "raw" || raw === "items" || raw === "jsonl") return raw;
|
|
55
|
+
throw new Error(`--output must be one of full, raw, items, json, jsonl; got ${raw}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function parseTableArg(raw: string): { tenantId?: string; tableId?: string } {
|
|
59
|
+
const trimmed = raw.trim();
|
|
60
|
+
if (!trimmed) return {};
|
|
61
|
+
if (!trimmed.startsWith("meta-")) return { tableId: trimmed };
|
|
62
|
+
const parts = trimmed.split("-");
|
|
63
|
+
return {
|
|
64
|
+
tenantId: parts[1],
|
|
65
|
+
tableId: parts.slice(2).join("-"),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function resolveServerUrl(args: string[], env: EnvLike): string {
|
|
70
|
+
return (
|
|
71
|
+
readOption(args, "--server-url") ||
|
|
72
|
+
readOption(args, "--server") ||
|
|
73
|
+
readOption(args, "--base-url") ||
|
|
74
|
+
env.NOLO_SERVER_URL ||
|
|
75
|
+
env.NOLO_SERVER ||
|
|
76
|
+
env.BASE_URL ||
|
|
77
|
+
DEFAULT_NOLO_SERVER_URL
|
|
78
|
+
).replace(/\/+$/, "");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function resolveAuthToken(args: string[], env: EnvLike): string {
|
|
82
|
+
return (
|
|
83
|
+
readOption(args, "--api-key") ||
|
|
84
|
+
readOption(args, "--token") ||
|
|
85
|
+
env.AUTH_TOKEN ||
|
|
86
|
+
env.AUTH ||
|
|
87
|
+
""
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function parseJwtTenantId(token: string): string | undefined {
|
|
92
|
+
const [, payload] = token.split(".");
|
|
93
|
+
if (!payload) return undefined;
|
|
94
|
+
try {
|
|
95
|
+
const normalized = payload.replace(/-/g, "+").replace(/_/g, "/");
|
|
96
|
+
const decoded = Buffer.from(normalized, "base64").toString("utf8");
|
|
97
|
+
const parsed = JSON.parse(decoded);
|
|
98
|
+
return typeof parsed.userId === "string" ? parsed.userId : typeof parsed.sub === "string" ? parsed.sub : undefined;
|
|
99
|
+
} catch {
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function formatOutput(input: { envelope: any; rawData: any; mode: OutputMode }): string {
|
|
105
|
+
if (input.mode === "full") return JSON.stringify(input.envelope, null, 2);
|
|
106
|
+
if (input.mode === "raw") return JSON.stringify(input.rawData, null, 2);
|
|
107
|
+
const items = Array.isArray(input.rawData?.items) ? input.rawData.items : input.rawData;
|
|
108
|
+
if (input.mode === "items") return JSON.stringify(items, null, 2);
|
|
109
|
+
return Array.isArray(items) ? items.map((item) => JSON.stringify(item)).join("\n") : JSON.stringify(items);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function mergeQueryShortcutFilters(args: string[], filters: Record<string, unknown> | undefined): Record<string, unknown> | undefined {
|
|
113
|
+
const row = readOption(args, "--row") || readOption(args, "--row-id");
|
|
114
|
+
const rowDbKey = readOption(args, "--row-dbkey");
|
|
115
|
+
const shortcutFilters: Record<string, unknown> = {};
|
|
116
|
+
if (row) {
|
|
117
|
+
if (row.startsWith("row-")) shortcutFilters.dbKey = row;
|
|
118
|
+
else shortcutFilters.rowId = row;
|
|
119
|
+
}
|
|
120
|
+
if (rowDbKey) shortcutFilters.dbKey = rowDbKey;
|
|
121
|
+
if (Object.keys(shortcutFilters).length === 0) return filters;
|
|
122
|
+
return {
|
|
123
|
+
...(filters ?? {}),
|
|
124
|
+
...shortcutFilters,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
26
128
|
function usage(): string {
|
|
27
129
|
return [
|
|
28
130
|
"Usage:",
|
|
@@ -78,21 +180,19 @@ export async function runTableQueryCommand(args: string[], deps: TableCommandDep
|
|
|
78
180
|
Authorization: `Bearer ${authToken}`,
|
|
79
181
|
"Content-Type": "application/json",
|
|
80
182
|
},
|
|
81
|
-
body: JSON.stringify(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
columns
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
})
|
|
95
|
-
),
|
|
183
|
+
body: JSON.stringify({
|
|
184
|
+
tenantId,
|
|
185
|
+
tableId,
|
|
186
|
+
filters: filters ?? {},
|
|
187
|
+
columns: hasFlag(args, "--include-activity")
|
|
188
|
+
? includeTableActivityColumns(columns)
|
|
189
|
+
: columns,
|
|
190
|
+
includeBaseFields: !hasFlag(args, "--no-base-fields"),
|
|
191
|
+
limit: Number(readOption(args, "--limit") || (hasSingleRowShortcut ? 1 : 20)),
|
|
192
|
+
offset: Number(readOption(args, "--offset") || 0),
|
|
193
|
+
sortBy: readOption(args, "--sort-by") || "updatedAt",
|
|
194
|
+
sortOrder: readOption(args, "--sort-order") === "asc" ? "asc" : "desc",
|
|
195
|
+
}),
|
|
96
196
|
});
|
|
97
197
|
} catch (error) {
|
|
98
198
|
output.write(`[nolo] table query failed: ${error instanceof Error ? error.message : String(error)}\n`);
|
package/cli/taskRunCommand.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from "./taskRunParsing";
|
|
1
|
+
import { DEFAULT_NOLO_SERVER_URL } from "./defaultServer";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
|
|
6
|
+
type EnvLike = Record<string, string | undefined>;
|
|
7
|
+
type OutputLike = { write(chunk: string): unknown };
|
|
9
8
|
|
|
10
9
|
type TaskRunCommandDeps = {
|
|
11
10
|
env?: EnvLike;
|
|
@@ -13,13 +12,211 @@ type TaskRunCommandDeps = {
|
|
|
13
12
|
fetchImpl?: typeof fetch;
|
|
14
13
|
};
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
function parseEnvFile(path: string): EnvLike {
|
|
16
|
+
if (!path || !existsSync(path)) return {};
|
|
17
|
+
const parsed: EnvLike = {};
|
|
18
|
+
for (const rawLine of readFileSync(path, "utf8").split(/\r?\n/)) {
|
|
19
|
+
const line = rawLine.trim();
|
|
20
|
+
if (!line || line.startsWith("#")) continue;
|
|
21
|
+
const index = line.indexOf("=");
|
|
22
|
+
if (index <= 0) continue;
|
|
23
|
+
const key = line.slice(0, index).trim();
|
|
24
|
+
let value = line.slice(index + 1).trim();
|
|
25
|
+
if (
|
|
26
|
+
(value.startsWith('"') && value.endsWith('"')) ||
|
|
27
|
+
(value.startsWith("'") && value.endsWith("'"))
|
|
28
|
+
) {
|
|
29
|
+
value = value.slice(1, -1);
|
|
30
|
+
}
|
|
31
|
+
if (key) parsed[key] = value;
|
|
32
|
+
}
|
|
33
|
+
return parsed;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function loadTaskRunEnv(env: EnvLike, options: { includeDefaultEnvFiles?: boolean } = {}) {
|
|
37
|
+
const envFileCandidates = [
|
|
38
|
+
env.NOLO_TASK_RUN_ENV_FILE,
|
|
39
|
+
env.NOLO_MACHINE_ENV_FILE,
|
|
40
|
+
...(options.includeDefaultEnvFiles
|
|
41
|
+
? ["/etc/nolo/machine-runner.env", join(homedir(), ".nolo", "machine-runner.env")]
|
|
42
|
+
: []),
|
|
43
|
+
].filter((path): path is string => Boolean(path));
|
|
44
|
+
const fileEnv = Object.assign({}, ...envFileCandidates.map(parseEnvFile));
|
|
45
|
+
return { ...fileEnv, ...env };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function readOption(args: string[], flag: string) {
|
|
49
|
+
for (let i = 0; i < args.length; i++) {
|
|
50
|
+
const value = args[i];
|
|
51
|
+
if (value === flag) return args[i + 1] ?? "";
|
|
52
|
+
if (value.startsWith(`${flag}=`)) return value.slice(flag.length + 1);
|
|
53
|
+
}
|
|
54
|
+
return "";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function csv(raw: string) {
|
|
58
|
+
return raw.split(",").map((item) => item.trim()).filter(Boolean);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function optionalJson(args: string[], flag: string) {
|
|
62
|
+
const value = optional(args, flag);
|
|
63
|
+
if (!value) return undefined;
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(value);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw new Error(`${flag} must be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function resolveServerUrl(args: string[], env: EnvLike) {
|
|
72
|
+
return (
|
|
73
|
+
readOption(args, "--server-url") ||
|
|
74
|
+
readOption(args, "--server") ||
|
|
75
|
+
readOption(args, "--base-url") ||
|
|
76
|
+
env.NOLO_SERVER_URL ||
|
|
77
|
+
env.NOLO_SERVER ||
|
|
78
|
+
env.BASE_URL ||
|
|
79
|
+
DEFAULT_NOLO_SERVER_URL
|
|
80
|
+
).replace(/\/+$/, "");
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function resolveAuthToken(args: string[], env: EnvLike) {
|
|
84
|
+
return (
|
|
85
|
+
readOption(args, "--api-key") ||
|
|
86
|
+
readOption(args, "--token") ||
|
|
87
|
+
env.NOLO_TASK_RUN_TOKEN ||
|
|
88
|
+
env.NOLO_MACHINE_API_KEY ||
|
|
89
|
+
env.AUTH_TOKEN ||
|
|
90
|
+
env.AUTH ||
|
|
91
|
+
""
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function required(args: string[], flag: string) {
|
|
96
|
+
const value = readOption(args, flag).trim();
|
|
97
|
+
if (!value) throw new Error(`${flag} is required`);
|
|
98
|
+
return value;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function optional(args: string[], flag: string) {
|
|
102
|
+
const value = readOption(args, flag).trim();
|
|
103
|
+
return value || undefined;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function buildBody(command: string, args: string[]) {
|
|
107
|
+
const dbKey = required(args, "--row-dbkey");
|
|
108
|
+
if (command === "read-context" || command === "readTaskContext") {
|
|
109
|
+
return { action: "readTaskContext", dbKey };
|
|
110
|
+
}
|
|
111
|
+
if (command === "claim-work-item" || command === "claimWorkItem") {
|
|
112
|
+
return {
|
|
113
|
+
action: "claimWorkItem",
|
|
114
|
+
dbKey,
|
|
115
|
+
workItemId: required(args, "--work-item-id"),
|
|
116
|
+
agentKey: required(args, "--agent-key"),
|
|
117
|
+
role: optional(args, "--role"),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
if (command === "record-agent-run" || command === "recordAgentRun") {
|
|
121
|
+
const toolTraceSummary = optionalJson(args, "--tool-trace-summary");
|
|
122
|
+
return {
|
|
123
|
+
action: "recordAgentRun",
|
|
124
|
+
dbKey,
|
|
125
|
+
...(optional(args, "--run-id") ? { runId: optional(args, "--run-id") } : {}),
|
|
126
|
+
agentKey: required(args, "--agent-key"),
|
|
127
|
+
...(optional(args, "--role") ? { role: optional(args, "--role") } : {}),
|
|
128
|
+
runStatus: required(args, "--run-status"),
|
|
129
|
+
...(optional(args, "--work-item-id") ? { workItemId: optional(args, "--work-item-id") } : {}),
|
|
130
|
+
...(optional(args, "--dialog-id") ? { dialogId: optional(args, "--dialog-id") } : {}),
|
|
131
|
+
...(optional(args, "--result-summary") ? { resultSummary: optional(args, "--result-summary") } : {}),
|
|
132
|
+
...(optional(args, "--error-code") ? { errorCode: optional(args, "--error-code") } : {}),
|
|
133
|
+
...(optional(args, "--tools-used") ? { toolsUsed: csv(optional(args, "--tools-used")!) } : {}),
|
|
134
|
+
...(toolTraceSummary ? { toolTraceSummary } : {}),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (command === "set-blocker" || command === "setBlocker") {
|
|
138
|
+
return {
|
|
139
|
+
action: "setBlocker",
|
|
140
|
+
dbKey,
|
|
141
|
+
workItemId: optional(args, "--work-item-id"),
|
|
142
|
+
blocker: {
|
|
143
|
+
layer: required(args, "--layer"),
|
|
144
|
+
code: required(args, "--code"),
|
|
145
|
+
message: required(args, "--message"),
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (command === "clear-blocker" || command === "clearBlocker") {
|
|
150
|
+
return {
|
|
151
|
+
action: "clearBlocker",
|
|
152
|
+
dbKey,
|
|
153
|
+
blockerId: required(args, "--blocker-id"),
|
|
154
|
+
workItemId: optional(args, "--work-item-id"),
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
if (command === "submit-outcome" || command === "submitOutcome") {
|
|
158
|
+
return {
|
|
159
|
+
action: "submitOutcome",
|
|
160
|
+
dbKey,
|
|
161
|
+
workItemId: required(args, "--work-item-id"),
|
|
162
|
+
summary: required(args, "--summary"),
|
|
163
|
+
...(optional(args, "--dialog-id") ? { dialogId: optional(args, "--dialog-id") } : {}),
|
|
164
|
+
...(optional(args, "--artifact-ids") ? { artifactIds: csv(optional(args, "--artifact-ids")!) } : {}),
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
if (command === "request-review" || command === "requestReview") {
|
|
168
|
+
return {
|
|
169
|
+
action: "requestReview",
|
|
170
|
+
dbKey,
|
|
171
|
+
workItemId: optional(args, "--work-item-id"),
|
|
172
|
+
reviewerAgentKey: required(args, "--reviewer-agent-key"),
|
|
173
|
+
...(optional(args, "--dialog-id") ? { dialogId: optional(args, "--dialog-id") } : {}),
|
|
174
|
+
...(optional(args, "--message") ? { message: optional(args, "--message") } : {}),
|
|
175
|
+
...(optional(args, "--artifact-ids") ? { artifactIds: csv(optional(args, "--artifact-ids")!) } : {}),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
if (command === "record-review" || command === "recordReview") {
|
|
179
|
+
return {
|
|
180
|
+
action: "recordReview",
|
|
181
|
+
dbKey,
|
|
182
|
+
...(optional(args, "--work-item-id") ? { workItemId: optional(args, "--work-item-id") } : {}),
|
|
183
|
+
reviewStatus: required(args, "--review-status"),
|
|
184
|
+
...(optional(args, "--reviewer-agent-key")
|
|
185
|
+
? { reviewerAgentKey: optional(args, "--reviewer-agent-key") }
|
|
186
|
+
: {}),
|
|
187
|
+
...(optional(args, "--dialog-id") ? { dialogId: optional(args, "--dialog-id") } : {}),
|
|
188
|
+
...(optional(args, "--findings") ? { findings: optional(args, "--findings") } : {}),
|
|
189
|
+
...(optional(args, "--artifact-ids") ? { artifactIds: csv(optional(args, "--artifact-ids")!) } : {}),
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (command === "close-work-item" || command === "complete-work-item" || command === "closeWorkItem" || command === "completeWorkItem") {
|
|
193
|
+
return {
|
|
194
|
+
action: "closeWorkItem",
|
|
195
|
+
dbKey,
|
|
196
|
+
workItemId: required(args, "--work-item-id"),
|
|
197
|
+
summary: required(args, "--summary"),
|
|
198
|
+
...(optional(args, "--reason") ? { reason: optional(args, "--reason") } : {}),
|
|
199
|
+
...(optional(args, "--dialog-id") ? { dialogId: optional(args, "--dialog-id") } : {}),
|
|
200
|
+
...(optional(args, "--artifact-ids") ? { artifactIds: csv(optional(args, "--artifact-ids")!) } : {}),
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
throw new Error(`Unknown task-run command: ${command}`);
|
|
204
|
+
}
|
|
17
205
|
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
206
|
+
function usage() {
|
|
207
|
+
return [
|
|
208
|
+
"Usage:",
|
|
209
|
+
" nolo task-run read-context --row-dbkey <row>",
|
|
210
|
+
" nolo task-run claim-work-item --row-dbkey <row> --work-item-id <id> --agent-key <agent> [--role <role>]",
|
|
211
|
+
" nolo task-run record-agent-run --row-dbkey <row> --agent-key <agent> --run-status <status> [--tools-used <csv>]",
|
|
212
|
+
" nolo task-run set-blocker --row-dbkey <row> [--work-item-id <id>] --layer <layer> --code <code> --message <message>",
|
|
213
|
+
" nolo task-run clear-blocker --row-dbkey <row> --blocker-id <id> [--work-item-id <id>]",
|
|
214
|
+
" nolo task-run submit-outcome --row-dbkey <row> --work-item-id <id> --summary <summary> [--dialog-id <id>]",
|
|
215
|
+
" nolo task-run request-review --row-dbkey <row> --reviewer-agent-key <agent> [--work-item-id <id>]",
|
|
216
|
+
" nolo task-run record-review --row-dbkey <row> [--work-item-id <id>] --review-status <passed|needs_changes|blocked> [--findings <text>]",
|
|
217
|
+
" nolo task-run close-work-item --row-dbkey <row> --work-item-id <id> --summary <summary>",
|
|
218
|
+
"",
|
|
219
|
+
].join("\n");
|
|
23
220
|
}
|
|
24
221
|
|
|
25
222
|
export async function runTaskRunCommand(args: string[], deps: TaskRunCommandDeps = {}) {
|
|
@@ -47,7 +244,6 @@ export async function runTaskRunCommand(args: string[], deps: TaskRunCommandDeps
|
|
|
47
244
|
}
|
|
48
245
|
|
|
49
246
|
const serverUrl = resolveServerUrl(args, env);
|
|
50
|
-
const timeoutMs = resolveTaskRunTimeoutMs(env);
|
|
51
247
|
let response: Response;
|
|
52
248
|
try {
|
|
53
249
|
response = await fetchImpl(`${serverUrl}/api/task-run`, {
|
|
@@ -57,7 +253,6 @@ export async function runTaskRunCommand(args: string[], deps: TaskRunCommandDeps
|
|
|
57
253
|
"Content-Type": "application/json",
|
|
58
254
|
},
|
|
59
255
|
body: JSON.stringify(body),
|
|
60
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
61
256
|
});
|
|
62
257
|
} catch (error) {
|
|
63
258
|
output.write(`[nolo] task-run failed: ${error instanceof Error ? error.message : String(error)}\n`);
|