nolo-cli 0.1.22 → 0.1.26
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 +25 -3
- package/agent-runtime/agentRecordConfig.ts +4 -0
- package/agent-runtime/hostAdapter.ts +2 -0
- package/agent-runtime/hybridRecordStore.ts +30 -9
- package/agent-runtime/index.ts +7 -0
- package/agent-runtime/localLoop.ts +14 -4
- package/agent-runtime/localToolPolicy.ts +22 -10
- package/agent-runtime/localWorkspaceTools.ts +140 -374
- package/agent-runtime/platformChatProvider.ts +3 -0
- package/agent-runtime/runtimeToolPolicy.ts +133 -0
- package/agent-runtime/types.ts +47 -0
- package/agentAliases.ts +1 -1
- package/agentCommandSupport.ts +77 -0
- package/agentInternalCommandEntries.ts +34 -0
- package/agentListCommands.ts +123 -0
- package/agentListHelpers.ts +187 -0
- package/agentMachineCommands.ts +402 -0
- package/agentRecordCommands.ts +141 -0
- package/agentRecordHelpers.ts +395 -0
- package/agentRunCommand.ts +75 -3
- package/agentRuntimeCommands.ts +7 -773
- package/ai/agent/_executeModel.ts +29 -3
- package/ai/agent/buildSystemPrompt.ts +17 -0
- package/ai/agent/cliChatClient.ts +38 -4
- package/ai/agent/cliExecutor.ts +304 -25
- package/ai/agent/createAgentSchema.ts +2 -2
- package/ai/agent/guidedCreation/assistant.ts +82 -0
- package/ai/agent/guidedCreation/capabilities.ts +84 -0
- package/ai/agent/guidedCreation/draft.ts +62 -0
- package/ai/agent/guidedCreation/types.ts +38 -0
- package/ai/agent/machineRunPermissions.ts +21 -3
- package/ai/agent/runtimeGuidance.ts +1 -1
- package/ai/agent/server/fetchPublicAgents.ts +6 -1
- package/ai/agent/streamAgentChatTurn.ts +593 -36
- package/ai/agent/web/useGuidedAgentCreation.ts +217 -0
- package/ai/ai.locale.ts +14 -2
- package/ai/chat/fetchUtils.native.ts +2 -0
- package/ai/chat/fetchUtils.ts +2 -0
- package/ai/chat/sendOpenAICompletionsRequest.ts +82 -1
- package/ai/chat/sendOpenAIResponseRequest.ts +65 -0
- package/ai/llm/getPricing.ts +14 -0
- package/ai/llm/kimi.ts +4 -1
- package/ai/llm/modelAvatar.ts +1 -0
- package/ai/llm/providers.ts +4 -1
- package/ai/llm/reasoningModels.ts +1 -0
- package/ai/taskRun/taskRunProtocol.ts +25 -10
- package/ai/token/modelUsageQuery.ts +17 -0
- package/ai/tools/agent/agentTools.ts +38 -0
- package/ai/tools/agent/prepareAgentDraftTool.ts +159 -0
- package/ai/tools/agent/startAgentDialogTool.ts +53 -0
- package/ai/tools/checkEnvTool.ts +52 -20
- package/ai/tools/convertMarxistsBookTool.ts +103 -0
- package/ai/tools/{execBashTool.ts → execShellTool.ts} +44 -161
- package/ai/tools/index.ts +24 -14
- package/ai/tools/marxistsOfflineBook.ts +253 -0
- package/ai/tools/modelUsageTools.ts +9 -2
- package/ai/tools/readTool.ts +31 -0
- package/ai/tools/toolApiClient.ts +35 -1
- package/ai/tools/toolNameAliases.ts +13 -0
- package/cliCommandAdapters.ts +28 -0
- package/cliCommandDispatch.ts +66 -0
- package/cliCommandFactories.ts +34 -0
- package/cliCommandTypes.ts +49 -0
- package/cliEnvHelpers.ts +44 -0
- package/client/agentRun.test.ts +330 -24
- package/client/agentRun.ts +117 -35
- package/client/hybridRecordStore.test.ts +42 -0
- package/client/hybridRecordStore.ts +11 -0
- package/client/localRuntimeAdapter.test.ts +191 -21
- package/client/localRuntimeAdapter.ts +99 -10
- package/client/localRuntimeDryRun.test.ts +5 -2
- package/client/taskRunPrompt.ts +1 -0
- package/commandRegistry.ts +11 -61
- package/connector-experimental/capabilities.ts +1 -0
- package/database/actions/common.ts +4 -3
- package/database/config.ts +19 -0
- package/database/server/coreDataProxy.ts +43 -26
- package/index.ts +54 -191
- package/internalCommandEntries.ts +12 -0
- package/machineCommands.ts +688 -64
- package/offlineMarxistsAgentCommand.ts +314 -0
- package/package.json +22 -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/runtimeDoctorCommands.ts +118 -0
- package/scriptCommandEntries.ts +71 -0
- package/systemInternalCommandEntries.ts +71 -0
- package/tableCommands.ts +42 -5
- package/workflowInternalCommandEntries.ts +11 -0
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
type HybridRecordStore,
|
|
35
35
|
} from "./hybridRecordStore";
|
|
36
36
|
import { executeLocalToolWithPolicy } from "./localToolPolicy";
|
|
37
|
+
import { taskRunFunctionSchema } from "../ai/tools/agent/taskRunTool";
|
|
37
38
|
import { prepareTaskWorktree } from "./taskWorktree";
|
|
38
39
|
import {
|
|
39
40
|
activateWorkspaceSession,
|
|
@@ -58,6 +59,7 @@ export type CliLocalRuntimeAdapterDeps = {
|
|
|
58
59
|
createId?: () => string;
|
|
59
60
|
fetchImpl?: typeof fetch;
|
|
60
61
|
cwd?: string;
|
|
62
|
+
useCwdAsTaskWorkspaceBase?: boolean;
|
|
61
63
|
output?: { write(chunk: string): unknown };
|
|
62
64
|
prepareTaskWorktree?: typeof prepareTaskWorktree;
|
|
63
65
|
localToolExecutors?: Record<string, (call: any) => Promise<{ content: string; metadata?: Record<string, unknown> }>>;
|
|
@@ -143,10 +145,13 @@ async function fetchWithTransientRetry(
|
|
|
143
145
|
|
|
144
146
|
function buildOpenAiTools(args: { toolNames?: string[]; env: EnvLike }) {
|
|
145
147
|
const toolset = buildLocalWorkspaceToolsetForEnv(args);
|
|
146
|
-
return
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
148
|
+
return [
|
|
149
|
+
...buildLocalWorkspaceOpenAiTools({
|
|
150
|
+
toolNames: toolset.toolNames,
|
|
151
|
+
exposeShellTools: toolset.exposeShellTools,
|
|
152
|
+
}),
|
|
153
|
+
...buildServerPlatformOpenAiTools({ toolNames: args.toolNames }),
|
|
154
|
+
];
|
|
150
155
|
}
|
|
151
156
|
|
|
152
157
|
function buildLocalWorkspaceToolsetForEnv(args: { toolNames?: string[]; env: EnvLike }) {
|
|
@@ -158,18 +163,86 @@ function buildLocalWorkspaceToolsetForEnv(args: { toolNames?: string[]; env: Env
|
|
|
158
163
|
}
|
|
159
164
|
|
|
160
165
|
function buildLocalPolicyToolNames(args: { toolNames?: string[]; env: EnvLike }) {
|
|
161
|
-
return
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
166
|
+
return [
|
|
167
|
+
...buildLocalWorkspacePolicyToolNames({
|
|
168
|
+
declaredToolNames: args.toolNames,
|
|
169
|
+
exposeShellTools: shellModeEnabled(args.env),
|
|
170
|
+
}),
|
|
171
|
+
...((args.toolNames ?? []).includes("taskRun") ? ["taskRun"] : []),
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
function buildServerPlatformOpenAiTools(args: { toolNames?: string[] }) {
|
|
176
|
+
const toolNames = new Set(args.toolNames ?? []);
|
|
177
|
+
return [
|
|
178
|
+
...(toolNames.has("taskRun")
|
|
179
|
+
? [{
|
|
180
|
+
type: "function",
|
|
181
|
+
function: taskRunFunctionSchema,
|
|
182
|
+
}]
|
|
183
|
+
: []),
|
|
184
|
+
];
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function parseToolArguments(raw: string) {
|
|
188
|
+
try {
|
|
189
|
+
const parsed = JSON.parse(raw || "{}");
|
|
190
|
+
return parsed && typeof parsed === "object" ? parsed : {};
|
|
191
|
+
} catch {
|
|
192
|
+
return {};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function resolveRuntimeServerUrl(env: EnvLike) {
|
|
197
|
+
return (env.NOLO_SERVER_URL || env.NOLO_SERVER || env.BASE_URL || "").replace(/\/+$/, "");
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function resolveRuntimeAuthToken(env: EnvLike) {
|
|
201
|
+
return env.AUTH_TOKEN || env.AUTH || env.NOLO_MACHINE_API_KEY || "";
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function buildServerPlatformToolExecutors(args: {
|
|
205
|
+
env: EnvLike;
|
|
206
|
+
fetchImpl: typeof fetch;
|
|
207
|
+
}) {
|
|
208
|
+
return {
|
|
209
|
+
taskRun: async (call: any) => {
|
|
210
|
+
const serverUrl = resolveRuntimeServerUrl(args.env);
|
|
211
|
+
const authToken = resolveRuntimeAuthToken(args.env);
|
|
212
|
+
if (!serverUrl) throw new Error("taskRun requires NOLO_SERVER_URL, NOLO_SERVER, or BASE_URL.");
|
|
213
|
+
if (!authToken) throw new Error("taskRun requires AUTH_TOKEN or NOLO_MACHINE_API_KEY.");
|
|
214
|
+
const response = await args.fetchImpl(`${serverUrl}/api/task-run`, {
|
|
215
|
+
method: "POST",
|
|
216
|
+
headers: {
|
|
217
|
+
"Content-Type": "application/json",
|
|
218
|
+
Authorization: `Bearer ${authToken}`,
|
|
219
|
+
},
|
|
220
|
+
body: JSON.stringify(parseToolArguments(call.arguments)),
|
|
221
|
+
});
|
|
222
|
+
const text = await response.text().catch(() => "");
|
|
223
|
+
if (!response.ok) {
|
|
224
|
+
throw new Error(`taskRun bridge failed: HTTP ${response.status} ${text.slice(0, 500)}`);
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
content: text,
|
|
228
|
+
metadata: { serverPlatformTool: true },
|
|
229
|
+
};
|
|
230
|
+
},
|
|
231
|
+
};
|
|
165
232
|
}
|
|
166
233
|
|
|
167
234
|
function buildLocalToolExecutors(args: {
|
|
168
235
|
workspaceRoot: string;
|
|
236
|
+
env: EnvLike;
|
|
237
|
+
fetchImpl: typeof fetch;
|
|
169
238
|
localToolExecutors?: CliLocalRuntimeAdapterDeps["localToolExecutors"];
|
|
170
239
|
}) {
|
|
171
240
|
return {
|
|
172
241
|
...createLocalWorkspaceToolExecutors({ workspaceRoot: args.workspaceRoot }),
|
|
242
|
+
...buildServerPlatformToolExecutors({
|
|
243
|
+
env: args.env,
|
|
244
|
+
fetchImpl: args.fetchImpl,
|
|
245
|
+
}),
|
|
173
246
|
...(args.localToolExecutors ?? {}),
|
|
174
247
|
};
|
|
175
248
|
}
|
|
@@ -254,9 +327,15 @@ export function createCliLocalRuntimeAdapter(
|
|
|
254
327
|
const localToolBudgets = parseLocalToolBudgets(deps.env);
|
|
255
328
|
const localToolUsage = new Map<string, number>();
|
|
256
329
|
let activeAgentToolNames: string[] = [];
|
|
257
|
-
let workspaceSession: WorkspaceSession = createWorkspaceSession(
|
|
330
|
+
let workspaceSession: WorkspaceSession = createWorkspaceSession(
|
|
331
|
+
deps.useCwdAsTaskWorkspaceBase
|
|
332
|
+
? { defaultCwd: deps.cwd }
|
|
333
|
+
: { cwd: deps.cwd }
|
|
334
|
+
);
|
|
258
335
|
let localToolExecutors = buildLocalToolExecutors({
|
|
259
336
|
workspaceRoot: workspaceSession.workspaceRoot,
|
|
337
|
+
env: deps.env,
|
|
338
|
+
fetchImpl,
|
|
260
339
|
localToolExecutors: deps.localToolExecutors,
|
|
261
340
|
});
|
|
262
341
|
|
|
@@ -274,6 +353,8 @@ export function createCliLocalRuntimeAdapter(
|
|
|
274
353
|
if (workspaceSession.workspaceRoot === previousWorkspaceRoot) return;
|
|
275
354
|
localToolExecutors = buildLocalToolExecutors({
|
|
276
355
|
workspaceRoot: workspaceSession.workspaceRoot,
|
|
356
|
+
env: deps.env,
|
|
357
|
+
fetchImpl,
|
|
277
358
|
localToolExecutors: deps.localToolExecutors,
|
|
278
359
|
});
|
|
279
360
|
deps.output?.write(formatWorkspaceSessionActivation(workspaceSession));
|
|
@@ -378,12 +459,20 @@ export function createCliLocalRuntimeAdapter(
|
|
|
378
459
|
budgets: localToolBudgets,
|
|
379
460
|
usage: localToolUsage,
|
|
380
461
|
});
|
|
381
|
-
|
|
462
|
+
const result = await executeLocalToolWithPolicy({
|
|
382
463
|
env: deps.env,
|
|
383
464
|
agentToolNames: activeAgentToolNames,
|
|
384
465
|
call,
|
|
385
466
|
executors: localToolExecutors,
|
|
386
467
|
});
|
|
468
|
+
return {
|
|
469
|
+
...result,
|
|
470
|
+
metadata: {
|
|
471
|
+
...(result.metadata ?? {}),
|
|
472
|
+
workspaceRoot: workspaceSession.workspaceRoot,
|
|
473
|
+
workspaceKind: workspaceSession.kind,
|
|
474
|
+
},
|
|
475
|
+
};
|
|
387
476
|
},
|
|
388
477
|
};
|
|
389
478
|
}
|
|
@@ -4,7 +4,6 @@ import { join } from "node:path";
|
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
5
|
|
|
6
6
|
import { runLocalAgentTurn } from "../agent-runtime/localLoop";
|
|
7
|
-
import { buildLocalWorkspaceToolset } from "../agent-runtime/localWorkspaceTools";
|
|
8
7
|
import { createCliLocalRuntimeAdapter } from "./localRuntimeAdapter";
|
|
9
8
|
|
|
10
9
|
describe("CLI local runtime dry run", () => {
|
|
@@ -54,7 +53,11 @@ describe("CLI local runtime dry run", () => {
|
|
|
54
53
|
completeCount += 1;
|
|
55
54
|
if (completeCount === 1) {
|
|
56
55
|
expect(body.tools.map((tool: any) => tool.function.name)).toEqual([
|
|
57
|
-
|
|
56
|
+
"writeWorkspaceFile",
|
|
57
|
+
"listFiles",
|
|
58
|
+
"readFile",
|
|
59
|
+
"editFile",
|
|
60
|
+
"searchFiles",
|
|
58
61
|
]);
|
|
59
62
|
return Response.json({
|
|
60
63
|
model: "qwen-coder",
|
package/client/taskRunPrompt.ts
CHANGED
|
@@ -16,6 +16,7 @@ export function prependTaskRunPrompt(message: string, context?: TaskRunPromptCon
|
|
|
16
16
|
...(context.taskRunId ? [`- taskRunId: ${context.taskRunId}`] : []),
|
|
17
17
|
...(context.workItemId ? [`- workItemId: ${context.workItemId}`] : []),
|
|
18
18
|
...(artifactIds.length ? [`- artifactIds: ${artifactIds.join(",")}`] : []),
|
|
19
|
+
"- Handoff rule: start from the durable task context, then inspect existing refs such as workItems.dialogIds, workItems.outcome, review.dialogId, activityRefs, agentRuns.dialogId/resultSummary, and artifactRefs. Use dialog read/search for exact evidence.",
|
|
19
20
|
"- When you create, update, hand off, block, or review work, update the task context with `bun run task:run -- ...`.",
|
|
20
21
|
"- If this turn already includes a server TaskRun preflight snapshot, use that snapshot directly for read-only reporting or planning.",
|
|
21
22
|
"- Keep long reasoning and logs in the dialog; record only resumable references in task row meta.",
|
package/commandRegistry.ts
CHANGED
|
@@ -1,66 +1,16 @@
|
|
|
1
|
-
export type CommandEntry
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
};
|
|
1
|
+
export type { CliPackageInfo, CliRuntimeContext, CommandEntry } from "./cliCommandTypes";
|
|
2
|
+
export {
|
|
3
|
+
createCliRuntimeContext,
|
|
4
|
+
looksLikeDaemonShortcut,
|
|
5
|
+
runResolvedCommand,
|
|
6
|
+
} from "./cliCommandDispatch";
|
|
7
|
+
import type { CommandEntry } from "./cliCommandTypes";
|
|
8
|
+
import { getInternalCommandEntries } from "./internalCommandEntries";
|
|
9
|
+
import { getScriptCommandEntries } from "./scriptCommandEntries";
|
|
7
10
|
|
|
8
11
|
export const COMMANDS: CommandEntry[] = [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
{ path: ["doc", "create"], script: "createDoc.ts", description: "Create a normal doc" },
|
|
12
|
-
{ path: ["doc", "read"], script: "readDoc.ts", description: "Read a normal doc" },
|
|
13
|
-
{ path: ["doc", "update"], script: "updateDoc.ts", description: "Update a normal doc" },
|
|
14
|
-
{ path: ["doc", "delete"], script: "deleteDoc.ts", description: "Delete a normal doc" },
|
|
15
|
-
|
|
16
|
-
{ path: ["skill-doc", "create"], script: "createSkillDoc.ts", description: "Create a skill doc" },
|
|
17
|
-
{ path: ["skill-doc", "read"], script: "readSkillDoc.ts", description: "Read a skill doc" },
|
|
18
|
-
{ path: ["skill-doc", "update"], script: "updateSkillDoc.ts", description: "Update a skill doc" },
|
|
19
|
-
{ path: ["skill-doc", "delete"], script: "deleteSkillDoc.ts", description: "Delete a skill doc" },
|
|
20
|
-
{ path: ["skill", "create-doc"], script: "createSkillDoc.ts", description: "Create a skill-backed doc" },
|
|
21
|
-
|
|
22
|
-
{ path: ["dialog", "read"], script: "readDialog.ts", description: "Read a dialog" },
|
|
23
|
-
{ path: ["dialog", "status"], script: "dialogStatus.ts", description: "Read compact dialog status" },
|
|
24
|
-
{ path: ["space", "list"], script: "listSpaces.ts", description: "List joined spaces" },
|
|
25
|
-
{ path: ["space", "read"], script: "readSpace.ts", description: "Read a space" },
|
|
26
|
-
{ path: ["space", "delete"], script: "deleteSpaces.ts", description: "Delete spaces by safe filters" },
|
|
27
|
-
{ path: ["space", "category"], script: "upsertSpaceCategory.ts", description: "Create or update a space category" },
|
|
28
|
-
{ path: ["space", "content-category"], script: "setSpaceContentCategory.ts", description: "Move content into a space category" },
|
|
29
|
-
|
|
30
|
-
{ path: ["table", "query"], script: "tableData.ts", fixedArgs: ["--action", "query"], description: "Query table rows" },
|
|
31
|
-
{ path: ["table", "add-column"], script: "tableData.ts", fixedArgs: ["--action", "add-column"], description: "Add one table column" },
|
|
32
|
-
{ path: ["table", "add-row"], script: "tableData.ts", fixedArgs: ["--action", "add-row"], description: "Add one table row" },
|
|
33
|
-
{ path: ["table", "add-rows"], script: "tableData.ts", fixedArgs: ["--action", "add-rows"], description: "Add table rows" },
|
|
34
|
-
{ path: ["table", "update-row"], script: "tableData.ts", fixedArgs: ["--action", "update-row"], description: "Update one table row" },
|
|
35
|
-
{ path: ["table", "update-rows"], script: "tableData.ts", fixedArgs: ["--action", "update-rows"], description: "Update table rows" },
|
|
36
|
-
{ path: ["table", "delete-row"], script: "tableData.ts", fixedArgs: ["--action", "delete-row"], description: "Delete one table row" },
|
|
37
|
-
{ path: ["table", "delete-rows"], script: "tableData.ts", fixedArgs: ["--action", "delete-rows"], description: "Delete table rows" },
|
|
38
|
-
{ path: ["table", "data"], script: "tableData.ts", description: "Low-level table row script bridge" },
|
|
39
|
-
{ path: ["table", "meta"], script: "upsertTableMeta.ts", description: "Create or update table metadata" },
|
|
40
|
-
{ path: ["task-run"], script: "", description: "Update durable task-run state through the runner bridge" },
|
|
41
|
-
|
|
42
|
-
{ path: ["agent", "list"], script: "listMyAgents.ts", description: "List owned agents" },
|
|
43
|
-
{ path: ["agent", "pull"], script: "", description: "Cache an agent for local runs" },
|
|
44
|
-
{ path: ["agent", "read"], script: "", description: "Read a single agent" },
|
|
45
|
-
{ path: ["agent", "run"], script: "", description: "Run an agent" },
|
|
46
|
-
{ path: ["agent", "update"], script: "updateAgent.ts", description: "Update agent fields" },
|
|
47
|
-
{ path: ["agent", "bind-current"], script: "", description: "Bind an agent to this machine" },
|
|
48
|
-
{ path: ["agent", "smoke-current"], script: "", description: "Smoke test a bound agent through this machine" },
|
|
49
|
-
{ path: ["agent", "runtime-doctor"], script: "", description: "Diagnose current machine runtime compatibility" },
|
|
50
|
-
{ path: ["agent", "unpublish"], script: "unpublishAgent.ts", description: "Remove an agent's public record" },
|
|
51
|
-
{ path: ["agent", "chat"], script: "", description: "Chat with an agent" },
|
|
52
|
-
{ path: ["agent", "dialogs"], script: "queryAgentDialogs.ts", description: "Inspect recent dialogs for an agent" },
|
|
53
|
-
{ path: ["agent", "doctor"], script: "doctorAgentWorkspace.ts", description: "Audit agent workspace health" },
|
|
54
|
-
{ path: ["agent", "create-custom"], script: "createCustomCodingAgent.ts", description: "Create a custom coding agent" },
|
|
55
|
-
{ path: ["agent", "create-space"], script: "createSpaceAgents.ts", description: "Create or attach shared-space agents" },
|
|
56
|
-
{ path: ["agent", "setup-demo"], script: "setupDemoAgent.ts", description: "Bootstrap demo publisher agents" },
|
|
57
|
-
{ path: ["agent", "supervise"], script: "runAutonomousAgent.ts", description: "Run an agent in autonomous cycles" },
|
|
58
|
-
|
|
59
|
-
{ path: ["doctor", "runtime"], script: "", description: "Diagnose local-first agent runtime selection" },
|
|
60
|
-
|
|
61
|
-
{ path: ["llama"], script: "llamaServerSupervisor.ts", description: "Manage the llama.cpp runtime" },
|
|
62
|
-
{ path: ["model-runtime"], script: "localModelRuntimeSupervisor.ts", description: "Manage local model runtime processes" },
|
|
63
|
-
{ path: ["dev"], script: "devControl.ts", description: "Manage the local dev environment" },
|
|
12
|
+
...getInternalCommandEntries(renderHelpText),
|
|
13
|
+
...getScriptCommandEntries(),
|
|
64
14
|
];
|
|
65
15
|
|
|
66
16
|
export const GROUP_ORDER = [
|
|
@@ -29,6 +29,7 @@ const COMMAND_CAPABILITIES: Array<[probes: CommandProbe[], capability: string]>
|
|
|
29
29
|
],
|
|
30
30
|
[[{ command: "gemini", args: ["--version"] }], "gemini-cli"],
|
|
31
31
|
[[{ command: "kimi", args: ["--version"] }], "kimi-cli"],
|
|
32
|
+
[[{ command: "agy", args: ["--help"] }], "agy-cli"],
|
|
32
33
|
];
|
|
33
34
|
|
|
34
35
|
function defaultCommandExists(command: string) {
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import pino from "pino";
|
|
4
4
|
import { getIsDesktopApp } from "app/utils/env";
|
|
5
|
-
import {
|
|
5
|
+
import { fetchWithTransientReadRetry } from "app/utils/retryFetch";
|
|
6
|
+
import { API_ENDPOINTS, NOLO_CLUSTER_SERVERS, normalizeKnownServerOrigin } from "../config";
|
|
6
7
|
|
|
7
8
|
// RN 下 pino 的 browser 写法可能有兼容性问题
|
|
8
9
|
// 使用简单的 console 封装作为 fallback
|
|
@@ -23,7 +24,7 @@ export const logger = isRN ? {
|
|
|
23
24
|
// },
|
|
24
25
|
});
|
|
25
26
|
const normalizeServer = (server: string): string =>
|
|
26
|
-
server.trim().replace(/\/+$/, "");
|
|
27
|
+
normalizeKnownServerOrigin(server) ?? server.trim().replace(/\/+$/, "");
|
|
27
28
|
const isNoloClusterServer = (server: string): boolean =>
|
|
28
29
|
/^https?:\/\/(?:us\.)?nolo\.chat$/i.test(normalizeServer(server));
|
|
29
30
|
|
|
@@ -202,7 +203,7 @@ export const fetchFromServer = async (
|
|
|
202
203
|
signal?.addEventListener("abort", onExternalAbort);
|
|
203
204
|
|
|
204
205
|
try {
|
|
205
|
-
const res = await
|
|
206
|
+
const res = await fetchWithTransientReadRetry(
|
|
206
207
|
`${server}${buildReadUrl(dbKey)}`,
|
|
207
208
|
{
|
|
208
209
|
signal: controller.signal as any,
|
package/database/config.ts
CHANGED
|
@@ -8,6 +8,25 @@ export const SERVERS = {
|
|
|
8
8
|
} as const;
|
|
9
9
|
export const NOLO_CLUSTER_SERVERS = Object.values(SERVERS);
|
|
10
10
|
|
|
11
|
+
const LEGACY_SERVER_ORIGIN_MAP: Record<string, string> = {
|
|
12
|
+
"https://nolotus.com": SERVERS.MAIN,
|
|
13
|
+
"https://www.nolotus.com": SERVERS.MAIN,
|
|
14
|
+
"https://us.nolotus.com": SERVERS.US,
|
|
15
|
+
"https://www.us.nolotus.com": SERVERS.US,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const normalizeKnownServerOrigin = (server: unknown): string | null => {
|
|
19
|
+
if (typeof server !== "string" || server.trim().length === 0) return null;
|
|
20
|
+
const trimmed = server.trim();
|
|
21
|
+
let origin: string;
|
|
22
|
+
try {
|
|
23
|
+
origin = new URL(trimmed).origin;
|
|
24
|
+
} catch {
|
|
25
|
+
origin = trimmed.replace(/\/+$/, "");
|
|
26
|
+
}
|
|
27
|
+
return LEGACY_SERVER_ORIGIN_MAP[origin.toLowerCase()] ?? origin;
|
|
28
|
+
};
|
|
29
|
+
|
|
11
30
|
export const API_ENDPOINTS = {
|
|
12
31
|
DATABASE: `${API_VERSION}/db`,
|
|
13
32
|
SHARE: `${API_VERSION}/share`,
|
|
@@ -9,7 +9,7 @@ const normalizeOrigin = (value: string | URL | null | undefined): string => {
|
|
|
9
9
|
}
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
const getDbKeyForOperation = (args: {
|
|
12
|
+
const getDbKeyForOperation = (args: {
|
|
13
13
|
operation: string;
|
|
14
14
|
pathname: string;
|
|
15
15
|
req: { body?: Record<string, any> };
|
|
@@ -26,10 +26,32 @@ const getDbKeyForOperation = (args: {
|
|
|
26
26
|
return typeof req.body?.customKey === "string" ? req.body.customKey : null;
|
|
27
27
|
default:
|
|
28
28
|
return null;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export function resolveCoreDataProxyTarget(args: {
|
|
33
|
+
dbKey: string;
|
|
34
|
+
requestUrl?: string | URL | null;
|
|
35
|
+
coreBaseUrl?: string | null;
|
|
36
|
+
}): string | null {
|
|
37
|
+
const coreBaseUrl = normalizeOrigin(args.coreBaseUrl);
|
|
38
|
+
if (!coreBaseUrl) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const requestOrigin = normalizeOrigin(args.requestUrl);
|
|
43
|
+
if (requestOrigin && requestOrigin === coreBaseUrl) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (classifyCoreDataKey(args.dbKey).owner !== "core") {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return coreBaseUrl;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export async function maybeProxyDatabaseRequestToCore(args: {
|
|
33
55
|
req: {
|
|
34
56
|
method?: string;
|
|
35
57
|
url?: string | URL;
|
|
@@ -40,27 +62,22 @@ export async function maybeProxyDatabaseRequestToCore(args: {
|
|
|
40
62
|
search: string;
|
|
41
63
|
coreBaseUrl?: string | null;
|
|
42
64
|
fetchImpl?: typeof fetch;
|
|
43
|
-
}): Promise<Response | null> {
|
|
44
|
-
const { req, pathname, search, fetchImpl = fetch } = args;
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (classifyCoreDataKey(dbKey).owner !== "core") {
|
|
62
|
-
return null;
|
|
63
|
-
}
|
|
65
|
+
}): Promise<Response | null> {
|
|
66
|
+
const { req, pathname, search, fetchImpl = fetch } = args;
|
|
67
|
+
const operation = pathname.slice("/api/v1/db/".length).split("/")[0] ?? "";
|
|
68
|
+
const dbKey = getDbKeyForOperation({ operation, pathname, req });
|
|
69
|
+
if (!dbKey) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const coreBaseUrl = resolveCoreDataProxyTarget({
|
|
74
|
+
dbKey,
|
|
75
|
+
requestUrl: req.url,
|
|
76
|
+
coreBaseUrl: args.coreBaseUrl,
|
|
77
|
+
});
|
|
78
|
+
if (!coreBaseUrl) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
64
81
|
|
|
65
82
|
const headers = new Headers(req.headers ?? {});
|
|
66
83
|
const init: RequestInit = {
|