nolo-cli 0.1.41 → 0.1.43
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 +27 -12
- package/agent-runtime/agentThread.ts +222 -0
- package/agent-runtime/agentThreadAdmission.ts +74 -0
- package/agent-runtime/dialogWritePlan.ts +42 -0
- package/agent-runtime/hostAdapter.ts +1 -0
- package/agent-runtime/index.ts +43 -0
- package/agent-runtime/localLoop.ts +31 -2
- package/agent-runtime/localToolPolicy.ts +1 -0
- package/agent-runtime/localWorkspaceTools.ts +1258 -78
- package/agent-runtime/noloWorkspaceTools.ts +20 -1
- package/agent-runtime/runtimeToolPolicy.ts +1 -5
- package/agent-runtime/runtimeToolSurface.ts +1 -0
- package/agentAliases.ts +29 -9
- package/agentInternalCommandEntries.ts +11 -3
- package/agentMachineCommands.ts +1 -0
- package/agentRecordCommands.ts +2 -2
- package/agentRecordHelpers.ts +59 -6
- package/agentRunCommand.ts +84 -19
- package/ai/agent/buildSystemPrompt.ts +14 -0
- package/ai/agent/cliExecutor.ts +202 -43
- package/ai/agent/createAgentSchema.ts +2 -2
- package/ai/agent/liveAudioModel.ts +1 -1
- package/ai/agent/streamAgentChatTurn.ts +154 -20
- package/ai/agent/streamAgentChatTurnUtils.ts +63 -0
- package/ai/ai.locale.ts +70 -0
- package/ai/chat/inlineImageUrlsForCustomProvider.ts +7 -2
- package/ai/chat/sendOpenAICompletionsRequest.ts +25 -1
- package/ai/llm/kimi.ts +0 -1
- package/ai/llm/openrouterModels.ts +27 -2
- package/ai/memory/policy.ts +49 -0
- package/ai/memory/queryShared.ts +10 -4
- package/ai/memory/recentRelationshipRecap.ts +4 -0
- package/ai/memory/remember.ts +48 -104
- package/ai/memory/scope.ts +74 -0
- package/ai/memory/types.ts +6 -0
- package/ai/memory/understanding.ts +10 -18
- package/ai/policy/runtimePolicy.ts +95 -23
- package/ai/tools/agent/agentTools.ts +0 -21
- package/ai/tools/agent/startAgentDialogTool.ts +2 -1
- package/ai/tools/index.ts +2 -20
- package/ai/tools/prepareTools.ts +171 -1
- package/ai/tools/readXhsProfileTool.ts +80 -69
- package/ai/tools/table/createTableTool.ts +11 -0
- package/ai/tools/toolPacks.ts +19 -0
- package/ai/types.ts +3 -0
- package/app/favorite/deletedFavoriteProjection.ts +31 -0
- package/app/hooks/deleteDbKey.ts +24 -3
- package/app/i18n/translations/interface.locale.ts +48 -16
- package/app/types/appSummary.ts +4 -0
- package/app/utils/desktopAgentRuntimeTurnClient.ts +2 -0
- package/auth/adminPermissions.ts +64 -4
- package/auth/routes.ts +5 -0
- package/chat/chat.locale.ts +4 -0
- package/chat/dialog/actions/handleSendMessageAction.ts +7 -2
- package/chat/dialog/dialogAttachmentCleanup.ts +135 -0
- package/chat/dialog/dialogSlice.ts +117 -4
- package/chat/messages/activityCompletion.ts +97 -0
- package/chat/messages/imagePayloadPersistence.ts +22 -0
- package/chat/messages/messageContent.ts +20 -16
- package/chat/messages/messageSlice.ts +20 -1
- package/chat/messages/toolThunks.ts +32 -11
- package/chat/messages/types.ts +8 -1
- package/chat/messages/web/toolDisplayName.ts +686 -0
- package/cli/agentAliases.ts +29 -9
- package/cli/agentInternalCommandEntries.ts +11 -3
- package/cli/agentMachineCommands.ts +1 -0
- package/cli/agentRecordCommands.ts +2 -2
- package/cli/agentRecordHelpers.ts +59 -6
- package/cli/agentRunCommand.ts +84 -19
- package/cli/client/agentRun.ts +65 -253
- package/cli/client/localRuntimeAdapter.ts +179 -53
- package/cli/commandRegistry.ts +7 -4
- package/cli/dialogAttachmentCleanup.ts +151 -0
- package/cli/dialogCommands.ts +163 -61
- package/cli/dialogInternalCommandEntries.ts +1 -1
- package/cli/docCreateCommands.ts +345 -0
- package/cli/docInternalCommandEntries.ts +11 -0
- package/cli/docPageHelpers.ts +80 -0
- package/cli/docSkillHelpers.ts +67 -0
- package/cli/docSpaceHelpers.ts +46 -0
- package/cli/internalCommandEntries.ts +4 -0
- package/cli/machineCommands.ts +18 -34
- package/cli/memoryCommands.ts +253 -0
- package/cli/memoryInternalCommandEntries.ts +9 -0
- package/cli/qoderUsageProbe.ts +252 -0
- package/cli/scriptCommandEntries.ts +0 -3
- package/cli/secretScan.ts +31 -0
- package/cli/tableCommands.ts +248 -13
- package/cli/workflowInternalCommandEntries.ts +2 -3
- package/client/agentRun.test.ts +68 -84
- package/client/agentRun.ts +65 -253
- package/client/localRuntimeAdapter.test.ts +505 -74
- package/client/localRuntimeAdapter.ts +179 -53
- package/commandRegistry.ts +7 -4
- package/connector-experimental/capabilities.ts +10 -9
- package/create/space/sidebarVisibleTypes.ts +19 -0
- package/dialogAttachmentCleanup.ts +151 -0
- package/dialogCommands.ts +163 -61
- package/dialogInternalCommandEntries.ts +1 -1
- package/docCreateCommands.ts +345 -0
- package/docInternalCommandEntries.ts +11 -0
- package/docPageHelpers.ts +80 -0
- package/docSkillHelpers.ts +67 -0
- package/docSpaceHelpers.ts +46 -0
- package/integrations/google/models.ts +4 -4
- package/integrations/openai/generateOpenAIRequestBody.ts +0 -3
- package/integrations/xhs-reader/types.ts +36 -3
- package/integrations/xhs-reader/url.ts +24 -1
- package/internalCommandEntries.ts +4 -0
- package/machineCommands.ts +18 -34
- package/memoryCommands.ts +253 -0
- package/memoryInternalCommandEntries.ts +9 -0
- package/package.json +141 -114
- package/qoderUsageProbe.ts +252 -0
- package/render/contentIcon/types.ts +167 -0
- package/render/page/docSlice.ts +30 -3
- package/render/page/types.ts +2 -0
- package/render/table/createTableAction.ts +4 -0
- package/render/table/tableSlice.ts +61 -0
- package/render/table/types.ts +10 -0
- package/scriptCommandEntries.ts +0 -3
- package/secretScan.ts +31 -0
- package/server/handlers/agentRun/types.ts +24 -23
- package/tableCommands.ts +248 -13
- package/workflowInternalCommandEntries.ts +2 -3
- package/ai/tools/agent/taskRunTool.ts +0 -112
- package/cli/client/taskRunPrompt.ts +0 -27
- package/cli/taskRunCommand.ts +0 -265
- package/client/taskRunPrompt.ts +0 -27
- package/integrations/xhs-reader/analyze/profileAnalyzer.ts +0 -205
- package/integrations/xhs-reader/backends/playwrightProfileCollector.ts +0 -624
- package/integrations/xhs-reader/bridge/readXhsProfileWithBridge.ts +0 -227
- package/integrations/xhs-reader/client/xhsWebApiClient.ts +0 -229
- package/integrations/xhs-reader/normalize.ts +0 -390
- package/integrations/xhs-reader/orchestrator.ts +0 -178
- package/taskRunCommand.ts +0 -265
|
@@ -43,9 +43,13 @@ import {
|
|
|
43
43
|
} from "./hybridRecordStore";
|
|
44
44
|
import { executeLocalToolWithPolicy } from "./localToolPolicy";
|
|
45
45
|
import { inferCaptureIntent } from "../../ai/policy/runtimePolicy";
|
|
46
|
+
import { TOOL_PACKS } from "../../ai/tools/toolPacks";
|
|
46
47
|
import { prepareTools } from "../../ai/tools/prepareTools";
|
|
47
|
-
import { taskRunFunctionSchema } from "../../ai/tools/agent/taskRunTool";
|
|
48
48
|
import {
|
|
49
|
+
LOCAL_CODEX_AGENT_ID,
|
|
50
|
+
LOCAL_CODEX_AGENT_KEY,
|
|
51
|
+
LOCAL_QODER_AGENT_ID,
|
|
52
|
+
LOCAL_QODER_AGENT_KEY,
|
|
49
53
|
MIMO_MONTH_AGENT_KEY,
|
|
50
54
|
NOLO_DEFAULT_AGENT_ID,
|
|
51
55
|
NOLO_DEFAULT_AGENT_KEY,
|
|
@@ -62,7 +66,10 @@ import {
|
|
|
62
66
|
readXhsProfileFunc,
|
|
63
67
|
readXhsProfileFunctionSchema,
|
|
64
68
|
} from "../../ai/tools/readXhsProfileTool";
|
|
65
|
-
import {
|
|
69
|
+
import {
|
|
70
|
+
readXPostFunc,
|
|
71
|
+
readXPostFunctionSchema,
|
|
72
|
+
} from "../../ai/tools/readXPostTool";
|
|
66
73
|
|
|
67
74
|
type EnvLike = Record<string, string | undefined>;
|
|
68
75
|
type FetchInput = Parameters<typeof fetch>[0];
|
|
@@ -106,6 +113,7 @@ export type CliLocalRuntimeAdapterDeps = {
|
|
|
106
113
|
cwd?: string;
|
|
107
114
|
output?: { write(chunk: string): unknown };
|
|
108
115
|
localToolExecutors?: Record<string, (call: any) => Promise<{ content: string; metadata?: Record<string, unknown> }>>;
|
|
116
|
+
readXPost?: typeof readXPostFunc;
|
|
109
117
|
readXhsProfile?: typeof readXhsProfileFunc;
|
|
110
118
|
executeCli?: LocalCliExecutor;
|
|
111
119
|
sleep?: (ms: number) => Promise<void>;
|
|
@@ -124,6 +132,55 @@ function resolveLocalUserId(env: EnvLike) {
|
|
|
124
132
|
return env.NOLO_LOCAL_USER_ID || env.NOLO_USER_ID || "local";
|
|
125
133
|
}
|
|
126
134
|
|
|
135
|
+
function resolveBuiltinLocalCliAgentConfig(agentRef: string, userId: string): AgentRuntimeAgentConfig | null {
|
|
136
|
+
const normalized = agentRef.trim();
|
|
137
|
+
if (normalized === LOCAL_CODEX_AGENT_KEY || normalized === LOCAL_CODEX_AGENT_ID) {
|
|
138
|
+
return {
|
|
139
|
+
key: LOCAL_CODEX_AGENT_KEY,
|
|
140
|
+
name: "Local Codex",
|
|
141
|
+
prompt: "You are a local Codex CLI coding agent. Use the workspace and dialog evidence available to you, keep changes scoped, run relevant checks, and report worktree, branch, commit or dirty diff, tests, and blockers.",
|
|
142
|
+
apiSource: "cli",
|
|
143
|
+
provider: "cli",
|
|
144
|
+
cliProvider: "codex",
|
|
145
|
+
toolNames: ["readFile", "searchFiles", "execShell"],
|
|
146
|
+
rawRecord: {
|
|
147
|
+
dbKey: LOCAL_CODEX_AGENT_KEY,
|
|
148
|
+
id: LOCAL_CODEX_AGENT_ID,
|
|
149
|
+
userId,
|
|
150
|
+
type: "agent",
|
|
151
|
+
name: "Local Codex",
|
|
152
|
+
apiSource: "cli",
|
|
153
|
+
provider: "cli",
|
|
154
|
+
cliProvider: "codex",
|
|
155
|
+
},
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (normalized === LOCAL_QODER_AGENT_KEY || normalized === LOCAL_QODER_AGENT_ID) {
|
|
159
|
+
return {
|
|
160
|
+
key: LOCAL_QODER_AGENT_KEY,
|
|
161
|
+
name: "Local Qoder",
|
|
162
|
+
prompt: "You are a local Qoder CLI coding agent. Use the workspace and dialog evidence available to you, keep changes scoped, run relevant checks, and report worktree, branch, commit or dirty diff, tests, and blockers.",
|
|
163
|
+
apiSource: "cli",
|
|
164
|
+
provider: "cli",
|
|
165
|
+
cliProvider: "qoder",
|
|
166
|
+
model: "Qwen3.7-Max",
|
|
167
|
+
toolNames: ["readFile", "searchFiles", "execShell"],
|
|
168
|
+
rawRecord: {
|
|
169
|
+
dbKey: LOCAL_QODER_AGENT_KEY,
|
|
170
|
+
id: LOCAL_QODER_AGENT_ID,
|
|
171
|
+
userId,
|
|
172
|
+
type: "agent",
|
|
173
|
+
name: "Local Qoder",
|
|
174
|
+
apiSource: "cli",
|
|
175
|
+
provider: "cli",
|
|
176
|
+
cliProvider: "qoder",
|
|
177
|
+
model: "Qwen3.7-Max",
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
|
|
127
184
|
function parseLocalToolBudgets(env: EnvLike) {
|
|
128
185
|
const raw = env.NOLO_LOCAL_TOOL_BUDGETS?.trim();
|
|
129
186
|
if (!raw) return {};
|
|
@@ -371,6 +428,25 @@ function shouldExposeLocalPlatformTools(agentKey?: string) {
|
|
|
371
428
|
return agentKey !== MIMO_MONTH_AGENT_KEY;
|
|
372
429
|
}
|
|
373
430
|
|
|
431
|
+
function addDefaultLightWebToolsForConfiguredAgents(
|
|
432
|
+
toolNames: string[],
|
|
433
|
+
agentConfig?: AgentRuntimeAgentConfig | null,
|
|
434
|
+
) {
|
|
435
|
+
const explicitToolNames = Array.isArray((agentConfig as any)?.toolSurface?.explicitToolNames)
|
|
436
|
+
? (agentConfig as any).toolSurface.explicitToolNames
|
|
437
|
+
: agentConfig?.toolNames;
|
|
438
|
+
if (!Array.isArray(explicitToolNames) || explicitToolNames.length === 0) return toolNames;
|
|
439
|
+
const webCapable = explicitToolNames.some((toolName) =>
|
|
440
|
+
toolName === "fetchWebpage" ||
|
|
441
|
+
toolName === "exa_search" ||
|
|
442
|
+
toolName === "read_x_post" ||
|
|
443
|
+
toolName === "read_xhs_profile" ||
|
|
444
|
+
toolName.startsWith("browser_")
|
|
445
|
+
);
|
|
446
|
+
if (!webCapable) return toolNames;
|
|
447
|
+
return [...new Set([...toolNames, ...TOOL_PACKS.LIGHT_WEB])];
|
|
448
|
+
}
|
|
449
|
+
|
|
374
450
|
function buildOpenAiTools(args: { agentKey?: string; toolNames?: string[]; env: EnvLike }) {
|
|
375
451
|
const toolset = buildLocalWorkspaceToolsetForEnv(args);
|
|
376
452
|
const exposePlatformTools = shouldExposeLocalPlatformTools(args.agentKey);
|
|
@@ -378,6 +454,14 @@ function buildOpenAiTools(args: { agentKey?: string; toolNames?: string[]; env:
|
|
|
378
454
|
...buildLocalWorkspaceOpenAiTools({
|
|
379
455
|
toolNames: toolset.toolNames,
|
|
380
456
|
exposeShellTools: toolset.exposeShellTools,
|
|
457
|
+
listFilesDescriptionVariant: resolveListFilesDescriptionVariant(args.env),
|
|
458
|
+
listFilesParameterVariant: resolveListFilesParameterVariant(args.env),
|
|
459
|
+
readFileDescriptionVariant: resolveReadFileDescriptionVariant(args.env),
|
|
460
|
+
readFileParameterVariant: resolveReadFileParameterVariant(args.env),
|
|
461
|
+
globFilesDescriptionVariant: resolveGlobFilesDescriptionVariant(args.env),
|
|
462
|
+
globFilesParameterVariant: resolveGlobFilesParameterVariant(args.env),
|
|
463
|
+
searchFilesDescriptionVariant: resolveSearchFilesDescriptionVariant(args.env),
|
|
464
|
+
searchFilesParameterVariant: resolveSearchFilesParameterVariant(args.env),
|
|
381
465
|
}),
|
|
382
466
|
...(exposePlatformTools ? buildServerPlatformOpenAiTools({ toolNames: args.toolNames }) : []),
|
|
383
467
|
...(exposePlatformTools ? buildNoloWorkspaceOpenAiTools({ toolNames: args.toolNames }) : []),
|
|
@@ -385,44 +469,91 @@ function buildOpenAiTools(args: { agentKey?: string; toolNames?: string[]; env:
|
|
|
385
469
|
}
|
|
386
470
|
|
|
387
471
|
function buildLocalWorkspaceToolsetForEnv(args: { toolNames?: string[]; env: EnvLike }) {
|
|
388
|
-
void args.env;
|
|
389
472
|
const toolset = buildLocalWorkspaceToolset({
|
|
390
473
|
declaredToolNames: args.toolNames,
|
|
391
474
|
exposeShellTools: true,
|
|
475
|
+
useDeclaredToolNamesOnly: shouldUseDeclaredOnlyLocalWorkspaceTools(args.env),
|
|
392
476
|
});
|
|
393
477
|
return toolset;
|
|
394
478
|
}
|
|
395
479
|
|
|
396
480
|
function buildLocalPolicyToolNames(args: { toolNames?: string[]; env: EnvLike }) {
|
|
397
|
-
void args.env;
|
|
398
481
|
return [
|
|
399
482
|
...buildLocalWorkspacePolicyToolNames({
|
|
400
483
|
declaredToolNames: args.toolNames,
|
|
401
484
|
exposeShellTools: true,
|
|
485
|
+
useDeclaredToolNamesOnly: shouldUseDeclaredOnlyLocalWorkspaceTools(args.env),
|
|
402
486
|
}),
|
|
403
|
-
...((args.toolNames ?? []).includes("
|
|
487
|
+
...((args.toolNames ?? []).includes("read_x_post") ? ["read_x_post"] : []),
|
|
404
488
|
...((args.toolNames ?? []).includes("read_xhs_profile") ? ["read_xhs_profile"] : []),
|
|
405
489
|
...(args.toolNames ?? []).filter((name) => LOCAL_SERVER_TABLE_TOOL_NAME_SET.has(name)),
|
|
406
490
|
...filterNoloWorkspaceToolNames(args.toolNames),
|
|
407
491
|
];
|
|
408
492
|
}
|
|
409
493
|
|
|
494
|
+
function shouldUseDeclaredOnlyLocalWorkspaceTools(env: EnvLike) {
|
|
495
|
+
const value = env.NOLO_LOCAL_WORKSPACE_TOOLSET || env.NOLO_LOCAL_TOOLSET_MODE || "";
|
|
496
|
+
return value === "declared-only" || value === "declared";
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function resolveGlobFilesDescriptionVariant(env: EnvLike) {
|
|
500
|
+
return resolveLocalWorkspaceDescriptionVariant(env.NOLO_GLOBFILES_DESCRIPTION_VARIANT);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function resolveListFilesDescriptionVariant(env: EnvLike) {
|
|
504
|
+
return resolveLocalWorkspaceDescriptionVariant(env.NOLO_LISTFILES_DESCRIPTION_VARIANT);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
function resolveListFilesParameterVariant(env: EnvLike) {
|
|
508
|
+
return resolveLocalWorkspaceParameterVariant(env.NOLO_LISTFILES_PARAMETER_VARIANT);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
function resolveReadFileDescriptionVariant(env: EnvLike) {
|
|
512
|
+
return resolveLocalWorkspaceDescriptionVariant(env.NOLO_READFILE_DESCRIPTION_VARIANT);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
function resolveReadFileParameterVariant(env: EnvLike) {
|
|
516
|
+
return resolveLocalWorkspaceParameterVariant(env.NOLO_READFILE_PARAMETER_VARIANT);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
function resolveGlobFilesParameterVariant(env: EnvLike) {
|
|
520
|
+
return resolveLocalWorkspaceParameterVariant(env.NOLO_GLOBFILES_PARAMETER_VARIANT);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function resolveSearchFilesDescriptionVariant(env: EnvLike) {
|
|
524
|
+
return resolveLocalWorkspaceDescriptionVariant(env.NOLO_SEARCHFILES_DESCRIPTION_VARIANT);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
function resolveSearchFilesParameterVariant(env: EnvLike) {
|
|
528
|
+
return resolveLocalWorkspaceParameterVariant(env.NOLO_SEARCHFILES_PARAMETER_VARIANT);
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
function resolveLocalWorkspaceDescriptionVariant(value: string | undefined) {
|
|
532
|
+
return value === "brief" || value === "strategy" || value === "workflow" || value === "antiShell"
|
|
533
|
+
? value
|
|
534
|
+
: "strategy";
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function resolveLocalWorkspaceParameterVariant(value: string | undefined) {
|
|
538
|
+
return value === "minimal" || value === "scoped" || value === "rich" ? value : "rich";
|
|
539
|
+
}
|
|
540
|
+
|
|
410
541
|
function buildServerPlatformOpenAiTools(args: { toolNames?: string[] }) {
|
|
411
542
|
const toolNames = new Set(args.toolNames ?? []);
|
|
412
543
|
const tableTools = prepareTools(
|
|
413
544
|
(args.toolNames ?? []).filter((name) => LOCAL_SERVER_TABLE_TOOL_NAME_SET.has(name)),
|
|
414
545
|
);
|
|
415
546
|
return [
|
|
416
|
-
...(toolNames.has("
|
|
547
|
+
...(toolNames.has("read_xhs_profile")
|
|
417
548
|
? [{
|
|
418
549
|
type: "function",
|
|
419
|
-
function:
|
|
550
|
+
function: readXhsProfileFunctionSchema,
|
|
420
551
|
}]
|
|
421
552
|
: []),
|
|
422
|
-
...(toolNames.has("
|
|
553
|
+
...(toolNames.has("read_x_post")
|
|
423
554
|
? [{
|
|
424
555
|
type: "function",
|
|
425
|
-
function:
|
|
556
|
+
function: readXPostFunctionSchema,
|
|
426
557
|
}]
|
|
427
558
|
: []),
|
|
428
559
|
...tableTools,
|
|
@@ -555,15 +686,7 @@ function buildServerPlatformToolExecutors(args: {
|
|
|
555
686
|
},
|
|
556
687
|
]),
|
|
557
688
|
);
|
|
558
|
-
return
|
|
559
|
-
taskRun: async (call: any) => {
|
|
560
|
-
return {
|
|
561
|
-
content: await postServer("/api/task-run", parseNoloWorkspaceToolArguments(call.arguments)),
|
|
562
|
-
metadata: { serverPlatformTool: true },
|
|
563
|
-
};
|
|
564
|
-
},
|
|
565
|
-
...tableExecutors,
|
|
566
|
-
};
|
|
689
|
+
return tableExecutors;
|
|
567
690
|
}
|
|
568
691
|
|
|
569
692
|
function buildLocalToolExecutors(args: {
|
|
@@ -571,34 +694,11 @@ function buildLocalToolExecutors(args: {
|
|
|
571
694
|
env: EnvLike;
|
|
572
695
|
fetchImpl: typeof fetch;
|
|
573
696
|
localToolExecutors?: CliLocalRuntimeAdapterDeps["localToolExecutors"];
|
|
697
|
+
readXPost?: CliLocalRuntimeAdapterDeps["readXPost"];
|
|
574
698
|
readXhsProfile?: CliLocalRuntimeAdapterDeps["readXhsProfile"];
|
|
575
699
|
commandTimeoutMs?: number;
|
|
576
700
|
commandOutputLimit?: number;
|
|
577
701
|
}) {
|
|
578
|
-
const resolveCliDefaultXhsArgs = (parsedArgs: any) => {
|
|
579
|
-
if (
|
|
580
|
-
parsedArgs?.profileDir ||
|
|
581
|
-
parsedArgs?.profile_dir ||
|
|
582
|
-
args.env.NOLO_XHS_READER_PROFILE_DIR
|
|
583
|
-
) {
|
|
584
|
-
return parsedArgs;
|
|
585
|
-
}
|
|
586
|
-
return {
|
|
587
|
-
...parsedArgs,
|
|
588
|
-
profileDir: resolveDefaultXhsProfileDir({
|
|
589
|
-
env: {
|
|
590
|
-
...process.env,
|
|
591
|
-
...args.env,
|
|
592
|
-
NOLO_DESKTOP: "1",
|
|
593
|
-
NOLO_DESKTOP_CHANNEL:
|
|
594
|
-
args.env.NOLO_DESKTOP_CHANNEL?.trim() ||
|
|
595
|
-
args.env.NOLO_XHS_READER_DESKTOP_CHANNEL?.trim() ||
|
|
596
|
-
"stable",
|
|
597
|
-
},
|
|
598
|
-
}),
|
|
599
|
-
};
|
|
600
|
-
};
|
|
601
|
-
|
|
602
702
|
return {
|
|
603
703
|
...createLocalWorkspaceToolExecutors({
|
|
604
704
|
workspaceRoot: args.workspaceRoot,
|
|
@@ -612,12 +712,28 @@ function buildLocalToolExecutors(args: {
|
|
|
612
712
|
...buildCliWorkspaceToolExecutors({
|
|
613
713
|
env: args.env,
|
|
614
714
|
}),
|
|
715
|
+
read_x_post: async (call: any) => {
|
|
716
|
+
const parsedArgs = (() => {
|
|
717
|
+
try { return JSON.parse(call.arguments || "{}"); } catch { return {}; }
|
|
718
|
+
})();
|
|
719
|
+
const result = await (args.readXPost ?? readXPostFunc)(
|
|
720
|
+
parsedArgs,
|
|
721
|
+
undefined,
|
|
722
|
+
);
|
|
723
|
+
return {
|
|
724
|
+
content: JSON.stringify(result.rawData),
|
|
725
|
+
metadata: {
|
|
726
|
+
xPostLocalBridge: true,
|
|
727
|
+
displayData: result.displayData,
|
|
728
|
+
},
|
|
729
|
+
};
|
|
730
|
+
},
|
|
615
731
|
read_xhs_profile: async (call: any) => {
|
|
616
732
|
const parsedArgs = (() => {
|
|
617
733
|
try { return JSON.parse(call.arguments || "{}"); } catch { return {}; }
|
|
618
734
|
})();
|
|
619
735
|
const result = await (args.readXhsProfile ?? readXhsProfileFunc)(
|
|
620
|
-
|
|
736
|
+
parsedArgs,
|
|
621
737
|
undefined,
|
|
622
738
|
);
|
|
623
739
|
return {
|
|
@@ -713,6 +829,7 @@ export function createCliLocalRuntimeAdapter(
|
|
|
713
829
|
env: deps.env,
|
|
714
830
|
fetchImpl,
|
|
715
831
|
localToolExecutors: deps.localToolExecutors,
|
|
832
|
+
readXPost: deps.readXPost,
|
|
716
833
|
readXhsProfile: deps.readXhsProfile,
|
|
717
834
|
...runtimeToolExecutionLimits,
|
|
718
835
|
});
|
|
@@ -721,16 +838,22 @@ export function createCliLocalRuntimeAdapter(
|
|
|
721
838
|
host: "cli",
|
|
722
839
|
capabilities: ["leveldb-agent-config", "local-provider", "leveldb-persistence", "local-tools"],
|
|
723
840
|
loadAgentConfig: async (agentRef) => {
|
|
841
|
+
const storedAgentConfig = await readAgentFromStore({
|
|
842
|
+
agentRef,
|
|
843
|
+
store: await resolveStore(deps),
|
|
844
|
+
userId,
|
|
845
|
+
});
|
|
846
|
+
const fallbackLocalCliAgentConfig =
|
|
847
|
+
storedAgentConfig ? null : resolveBuiltinLocalCliAgentConfig(agentRef, userId);
|
|
724
848
|
const agentConfig = withResolvedRuntimeToolSurface(
|
|
725
|
-
|
|
726
|
-
agentRef,
|
|
727
|
-
store: await resolveStore(deps),
|
|
728
|
-
userId,
|
|
729
|
-
}),
|
|
849
|
+
storedAgentConfig ?? fallbackLocalCliAgentConfig,
|
|
730
850
|
deps.env
|
|
731
851
|
);
|
|
732
852
|
const requestedToolNames = agentConfig
|
|
733
|
-
?
|
|
853
|
+
? addDefaultLightWebToolsForConfiguredAgents(
|
|
854
|
+
resolveRequestedRuntimeToolNames({ agentConfig }),
|
|
855
|
+
agentConfig,
|
|
856
|
+
)
|
|
734
857
|
: [];
|
|
735
858
|
activeAgentToolNames = buildLocalPolicyToolNames({
|
|
736
859
|
toolNames: requestedToolNames,
|
|
@@ -744,6 +867,7 @@ export function createCliLocalRuntimeAdapter(
|
|
|
744
867
|
env: deps.env,
|
|
745
868
|
fetchImpl,
|
|
746
869
|
localToolExecutors: deps.localToolExecutors,
|
|
870
|
+
readXPost: deps.readXPost,
|
|
747
871
|
readXhsProfile: deps.readXhsProfile,
|
|
748
872
|
...runtimeToolExecutionLimits,
|
|
749
873
|
});
|
|
@@ -828,9 +952,10 @@ export function createCliLocalRuntimeAdapter(
|
|
|
828
952
|
return {
|
|
829
953
|
model: providerConfig.model,
|
|
830
954
|
complete: async (messages, options) => {
|
|
831
|
-
const requestedToolNames =
|
|
955
|
+
const requestedToolNames = addDefaultLightWebToolsForConfiguredAgents(
|
|
956
|
+
resolveRequestedRuntimeToolNames({ agentConfig }),
|
|
832
957
|
agentConfig,
|
|
833
|
-
|
|
958
|
+
);
|
|
834
959
|
const tools = buildOpenAiTools({
|
|
835
960
|
agentKey: agentConfig.key,
|
|
836
961
|
toolNames: requestedToolNames,
|
|
@@ -901,9 +1026,10 @@ export function createCliLocalRuntimeAdapter(
|
|
|
901
1026
|
return {
|
|
902
1027
|
model: providerConfig.model,
|
|
903
1028
|
complete: async (messages, options) => {
|
|
904
|
-
const requestedToolNames =
|
|
1029
|
+
const requestedToolNames = addDefaultLightWebToolsForConfiguredAgents(
|
|
1030
|
+
resolveRequestedRuntimeToolNames({ agentConfig }),
|
|
905
1031
|
agentConfig,
|
|
906
|
-
|
|
1032
|
+
);
|
|
907
1033
|
const tools = buildOpenAiTools({
|
|
908
1034
|
agentKey: agentConfig.key,
|
|
909
1035
|
toolNames: requestedToolNames,
|
package/cli/commandRegistry.ts
CHANGED
|
@@ -14,6 +14,7 @@ export const COMMANDS: CommandEntry[] = [
|
|
|
14
14
|
];
|
|
15
15
|
|
|
16
16
|
export const GROUP_ORDER = [
|
|
17
|
+
"run",
|
|
17
18
|
"chat",
|
|
18
19
|
"doc",
|
|
19
20
|
"skill-doc",
|
|
@@ -21,9 +22,9 @@ export const GROUP_ORDER = [
|
|
|
21
22
|
"agent",
|
|
22
23
|
"doctor",
|
|
23
24
|
"dialog",
|
|
25
|
+
"memory",
|
|
24
26
|
"space",
|
|
25
27
|
"table",
|
|
26
|
-
"task-run",
|
|
27
28
|
"llama",
|
|
28
29
|
"model-runtime",
|
|
29
30
|
"dev",
|
|
@@ -55,23 +56,25 @@ export function renderHelpText() {
|
|
|
55
56
|
" nolo doctor",
|
|
56
57
|
" nolo doctor runtime",
|
|
57
58
|
" nolo update",
|
|
59
|
+
' nolo run "review this repository" # no Nolo login required; uses local Codex CLI',
|
|
58
60
|
' nolo doc create --title "Trip Notes" --body "hello" --sync local,us --dry-run',
|
|
59
61
|
' nolo skill-doc create --title "Agent Query Skill" --description "Inspect recent agent dialogs" --sync local,main,us',
|
|
60
62
|
" nolo agent list --json",
|
|
61
63
|
" nolo space list --json",
|
|
62
64
|
" nolo agent pull agent-pub-01APPBUILDER00000001YAII3I",
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
" nolo agent read agent-pub-01APPBUILDER00000001YAII3I",
|
|
66
|
+
" nolo agent usage qoder",
|
|
67
|
+
' nolo agent run frontend-implementer --msg "polish notifications"',
|
|
65
68
|
" nolo agent bind-current agent-user-1-agent-1",
|
|
66
69
|
" nolo agent runtime-doctor agent-user-1-agent-1",
|
|
67
70
|
' nolo agent smoke-current agent-user-1-agent-1 --msg "ping"',
|
|
68
71
|
' nolo chat --agent agent-pub-01APPBUILDER00000001YAII3I --msg "你好"',
|
|
72
|
+
" nolo memory delete --source-dialog 01ABC... --yes --json",
|
|
69
73
|
" nolo space read 01KKY77TT0DA9NY7TNW3R7255N --content-key page-user-id --brief",
|
|
70
74
|
" nolo space delete --name-prefix rn_owner_verify_0504 --yes",
|
|
71
75
|
" nolo table query --table 01ABCXYZ",
|
|
72
76
|
' nolo table query --table meta-0e95801d90-NOLOTASKBOARD --columns \'["title","status","owner","priority","codeStatus"]\' --no-base-fields --output items',
|
|
73
77
|
' nolo table update-row --table meta-0e95801d90-NOLOTASKBOARD --row 01ROWID --changes \'{"status":"已完成"}\'',
|
|
74
|
-
" nolo task-run read-context --row-dbkey row-user-table-row",
|
|
75
78
|
" nolo llama status",
|
|
76
79
|
];
|
|
77
80
|
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { deleteDbRecordOnServers, readDbRecordFromServers, type GlobalDeleteResult } from "./globalRecordOperations";
|
|
2
|
+
import {
|
|
3
|
+
buildDialogAttachmentPlan,
|
|
4
|
+
extractFileContentIds,
|
|
5
|
+
type DialogAttachmentCandidate,
|
|
6
|
+
type DialogAttachmentPlan,
|
|
7
|
+
} from "../chat/dialog/dialogAttachmentCleanup";
|
|
8
|
+
|
|
9
|
+
export { buildDialogAttachmentPlan, extractFileContentIds };
|
|
10
|
+
|
|
11
|
+
export type DialogAttachmentDeleteResult = {
|
|
12
|
+
fileId: string;
|
|
13
|
+
fileDbKey: string;
|
|
14
|
+
deleteResults: GlobalDeleteResult[];
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function asText(value: unknown) {
|
|
18
|
+
return typeof value === "string" && value.trim() ? value.trim() : null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
async function readDialogMessages(args: {
|
|
22
|
+
authToken: string;
|
|
23
|
+
dialogId: string;
|
|
24
|
+
fetchImpl: typeof fetch;
|
|
25
|
+
serverUrl: string;
|
|
26
|
+
}) {
|
|
27
|
+
const response = await args.fetchImpl(`${args.serverUrl}/rpc/getConvMsgs`, {
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: {
|
|
30
|
+
Authorization: `Bearer ${args.authToken}`,
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
},
|
|
33
|
+
body: JSON.stringify({ dialogId: args.dialogId, limit: 10000 }),
|
|
34
|
+
});
|
|
35
|
+
if (!response.ok) {
|
|
36
|
+
throw new Error(`read dialog messages failed on ${args.serverUrl}: HTTP ${response.status}`);
|
|
37
|
+
}
|
|
38
|
+
const payload = await response.json();
|
|
39
|
+
return Array.isArray(payload) ? payload : [];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function planDialogAttachmentCleanup(args: {
|
|
43
|
+
authToken: string;
|
|
44
|
+
dialogId: string;
|
|
45
|
+
ownerId?: string | null;
|
|
46
|
+
includeUserOwnedReferenced?: boolean;
|
|
47
|
+
fallbackFetchImpl?: typeof fetch;
|
|
48
|
+
fetchImpl: typeof fetch;
|
|
49
|
+
serverUrl: string;
|
|
50
|
+
serverUrls: string[];
|
|
51
|
+
}): Promise<DialogAttachmentPlan> {
|
|
52
|
+
const messages = await readDialogMessages({
|
|
53
|
+
authToken: args.authToken,
|
|
54
|
+
dialogId: args.dialogId,
|
|
55
|
+
fetchImpl: args.fetchImpl,
|
|
56
|
+
serverUrl: args.serverUrl,
|
|
57
|
+
});
|
|
58
|
+
const fileIds = [...new Set(messages.flatMap((message) => extractFileContentIds(message)))];
|
|
59
|
+
const metadataByFileId: Record<string, any> = {};
|
|
60
|
+
const metadataReadFailures: Array<{ fileId: string; error: string }> = [];
|
|
61
|
+
|
|
62
|
+
for (const fileId of fileIds) {
|
|
63
|
+
try {
|
|
64
|
+
const result = await readDbRecordFromServers({
|
|
65
|
+
authToken: args.authToken,
|
|
66
|
+
dbKey: `file-id-${fileId}`,
|
|
67
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
68
|
+
fetchImpl: args.fetchImpl,
|
|
69
|
+
serverUrls: args.serverUrls,
|
|
70
|
+
label: `file metadata index ${fileId}`,
|
|
71
|
+
});
|
|
72
|
+
const mainKey = asText(result.record?.mainKey);
|
|
73
|
+
if (!mainKey) throw new Error(`file-id index missing mainKey`);
|
|
74
|
+
const metadata = await readDbRecordFromServers({
|
|
75
|
+
authToken: args.authToken,
|
|
76
|
+
dbKey: mainKey,
|
|
77
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
78
|
+
fetchImpl: args.fetchImpl,
|
|
79
|
+
serverUrls: args.serverUrls,
|
|
80
|
+
label: `file metadata ${fileId}`,
|
|
81
|
+
});
|
|
82
|
+
metadataByFileId[fileId] = {
|
|
83
|
+
...metadata.record,
|
|
84
|
+
dbKey: asText(metadata.record?.dbKey) ?? mainKey,
|
|
85
|
+
};
|
|
86
|
+
} catch (error) {
|
|
87
|
+
const fallbackKey =
|
|
88
|
+
args.ownerId && !fileId.startsWith("file-")
|
|
89
|
+
? `file-${args.ownerId}-${fileId}`
|
|
90
|
+
: null;
|
|
91
|
+
if (fallbackKey) {
|
|
92
|
+
try {
|
|
93
|
+
const metadata = await readDbRecordFromServers({
|
|
94
|
+
authToken: args.authToken,
|
|
95
|
+
dbKey: fallbackKey,
|
|
96
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
97
|
+
fetchImpl: args.fetchImpl,
|
|
98
|
+
serverUrls: args.serverUrls,
|
|
99
|
+
label: `file metadata ${fileId}`,
|
|
100
|
+
});
|
|
101
|
+
metadataByFileId[fileId] = {
|
|
102
|
+
...metadata.record,
|
|
103
|
+
dbKey: asText(metadata.record?.dbKey) ?? fallbackKey,
|
|
104
|
+
};
|
|
105
|
+
continue;
|
|
106
|
+
} catch {
|
|
107
|
+
// Keep the original index error; it explains why the preferred path failed.
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
metadataReadFailures.push({
|
|
111
|
+
fileId,
|
|
112
|
+
error: error instanceof Error ? error.message : String(error),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return buildDialogAttachmentPlan({
|
|
118
|
+
dialogId: args.dialogId,
|
|
119
|
+
ownerId: args.ownerId,
|
|
120
|
+
includeUserOwnedReferenced: args.includeUserOwnedReferenced,
|
|
121
|
+
messages,
|
|
122
|
+
metadataByFileId,
|
|
123
|
+
metadataReadFailures,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export async function deleteDialogAttachmentCandidates(args: {
|
|
128
|
+
authToken: string;
|
|
129
|
+
candidates: DialogAttachmentCandidate[];
|
|
130
|
+
fallbackFetchImpl?: typeof fetch;
|
|
131
|
+
fetchImpl: typeof fetch;
|
|
132
|
+
serverUrls: string[];
|
|
133
|
+
}): Promise<DialogAttachmentDeleteResult[]> {
|
|
134
|
+
const results: DialogAttachmentDeleteResult[] = [];
|
|
135
|
+
for (const candidate of args.candidates) {
|
|
136
|
+
if (candidate.status !== "delete" || !candidate.fileDbKey) continue;
|
|
137
|
+
const deleteResults = await deleteDbRecordOnServers({
|
|
138
|
+
authToken: args.authToken,
|
|
139
|
+
dbKey: candidate.fileDbKey,
|
|
140
|
+
fallbackFetchImpl: args.fallbackFetchImpl,
|
|
141
|
+
fetchImpl: args.fetchImpl,
|
|
142
|
+
serverUrls: args.serverUrls,
|
|
143
|
+
});
|
|
144
|
+
results.push({
|
|
145
|
+
fileId: candidate.fileId,
|
|
146
|
+
fileDbKey: candidate.fileDbKey,
|
|
147
|
+
deleteResults,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return results;
|
|
151
|
+
}
|