@otto-code/client 0.7.6 → 0.8.0
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/dist/compat/normalize-provider-models.js +1 -1
- package/dist/daemon-client.d.ts +80 -30
- package/dist/daemon-client.js +179 -28
- package/package.json +3 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { normalizeAgentModelDefinition } from "@otto-code/protocol/agent-types";
|
|
2
|
-
// COMPAT(model-normalize): daemon normalizes at source (provider-registry)
|
|
2
|
+
// COMPAT(model-normalize): daemon normalizes at source (provider-registry) - shim covers older daemons; drop when floor >= v0.1.104
|
|
3
3
|
function normalizeAgentModels(models) {
|
|
4
4
|
if (!models) {
|
|
5
5
|
return models;
|
package/dist/daemon-client.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { AgentRefreshedStatusPayloadSchema, CheckoutRenameBranchResponseSchema,
|
|
|
6
6
|
import type { AgentStreamEventPayload, AgentSnapshotPayload, ProjectPlacementPayload, AgentPermissionResolvedMessage, CreateAgentRequestMessage, CreateOttoWorktreeRequest, CodeListFilesResponse, CodeSymbolLocation, CodeDefinitionLocation, CodeDefinitionStatus, CodeRenameApplyStatus, CodeRenameFileOutcome, CodeRenameUndoFile, CodeRenameUndoStatus, CodeHoverRange, CodeRenameEdit, CodeRenameFilePlan, LspLanguageState, LspRunningServer, CodeSolutionGetTreeResponse, CodeSolutionLoadProjectResponse, SolutionFormat, SolutionRef, SolutionTreeFolder, SolutionTreeProject, SolutionProjectNode, SolutionProjectStatus, SolutionPackageReference, FileCreateResult, FileDeleteResult, FileDownloadTokenResponse, FileEntryKind, FileEol, FileRenameResult, FileReplaceFileResult, FileReplaceRequest, FileReplaceResponse, FileSearchResultPayload, FileSearchSummary, FileUploadResponse, FileExplorerResponse, FileWatchEventPayload, FileWriteResult, FileRefineResult, FileRefineDocument, FileRefineReference, FetchAgentTimelineResponseMessage, AgentForkContextResponseMessage, GitSetupOptions, CheckoutStatusResponse, CheckoutCommitResponse, CheckoutGitCommitResponse, CheckoutGitCommitAgentResponse, CheckoutGitRollbackResponse, CheckoutGitFileHistoryResponse, CheckoutGitFileCommitDiffResponse, CheckoutGitFileBlameResponse, CheckoutGitFileOriginResponse, CheckoutGitGetOperationLogResponse, CheckoutMergeResponse, CheckoutMergeFromBaseResponse, CheckoutPullResponse, CheckoutPushResponse, CheckoutRefreshResponse, CheckoutPrCreateResponse, CheckoutPrMergeResponse, CheckoutPrMergeMethod, CheckoutGithubSetAutoMergeResponse, CheckoutGithubGetCheckDetailsResponse, PreviewListConfigResponse, PreviewStartResponse, PreviewBindTabResponse, PreviewStopResponse, CheckoutPrStatusResponse, PullRequestTimelineResponse, CheckoutSwitchBranchResponse, StashSaveResponse, StashPopResponse, StashListResponse, ValidateBranchResponse, BranchSuggestionsResponse, FileVersion, CheckoutCommit, ParsedDiffFile, WorkspaceRecoveryState, CheckoutForgeGetCheckDetailsResponse, CheckoutForgeSetAutoMergeResponse, ProjectCreateDirectoryResponse, FsFileWriteResult, FsFileWriteBinaryResult, GitHubSearchResponse, GitHubSearchRequest, ForgeSearchResponse, ForgeSearchRequest, GitHostingProviderId, HostingSearchRequest, HostingSearchResponse, HostingAuthStatusResponse, DirectorySuggestionsResponse, OttoWorktreeListResponse, OttoWorktreeArchiveResponse, ProjectIconResponse, ContextCategory, ContextPromptPreviewGetResponseMessage, ContextReportGetResponseMessage, ContextEdgeConvertResponseMessage, ContextFindingsFixResponseMessage, PersonalityMemoryListResponseMessage, PersonalityMemoryUpdateResponseMessage, PersonalityMemoryTransferResponseMessage, PersonalityMemoryStatsResponseMessage, ProjectAddResponse, ProjectScaffoldGit, ProjectScaffoldProgress, ProjectScaffoldResponse, HostingListRepositoriesResponse, HostingListOwnersResponse, OpenProjectResponseMessage, ArchiveWorkspaceResponseMessage, WorkspaceArchivePreflightResponse, WorktreeBaseRefSetResponse, WorktreeReattachListResponse, WorktreeReattachResponse, WorktreeReattachTarget, WorkspaceSetupStatusResponseMessage, ListCommandsResponse, ListProviderFeaturesResponseMessage, ListProviderModelsResponseMessage, ListProviderModesResponseMessage, ListAvailableProvidersResponse, GetProvidersSnapshotResponseMessage, RefreshProvidersSnapshotResponseMessage, ProviderDiagnosticResponseMessage, ProviderUsageListResponseMessage, StatsActivityGetResponseMessage, StatsActivityResetResponseMessage, UsageLogGetResponseMessage, AgentContextGetUsageResponseMessage, DaemonGetStatusResponse, DaemonGetPairingOfferResponse, DiagnosticsResponse, AgentRewindResponseMessage, ListTerminalsResponse, CreateTerminalResponse, SubscribeTerminalResponse, SubscribeTerminalRequest, CloseItemsResponse, AttachmentsImagesClearResponse, AttachmentsImagesStatsResponse, HistoryAgentsClearArchivedResponse, KillTerminalResponse, CaptureTerminalResponse, TerminalInput, SessionInboundMessage, SessionOutboundMessage, SendAgentMessageRequest, AgentPromptDelivery, TasksSuggestedStartMode, OttoConfigRaw, OttoConfigRevision, WorkspaceCreateRequest } from "@otto-code/protocol/messages";
|
|
7
7
|
import type { AgentPermissionRequest, AgentPermissionResponse, AgentPersistenceHandle, AgentProviderNotice, AgentProvider, AgentSessionConfig } from "@otto-code/protocol/agent-types";
|
|
8
8
|
import type { OrchestrationGraph, PromptTemplate, Run } from "@otto-code/protocol/orchestration";
|
|
9
|
-
import type { BrainCatalogModel, BrainEvals, BrainHfSearchResult, BrainHostStatus, BrainInstalledModel, BrainJob, BrainNetworkInfo, BrainRemoteConfig, BrainRepoQuant, BrainRuntime, ConnectorsListToolsResponse, CueMoment, MutableDaemonConfig, MutableDaemonConfigPatch, ProjectLink, SpeechSettingsOptions, SpeechTtsPreviewResult, SpeechTtsSpeakResult, SpeechTtsSpeakCancelResult, VisualizerVoiceCuesResult, AgentPersonalitiesGenerateProfileResult } from "@otto-code/protocol/messages";
|
|
9
|
+
import type { BrainCatalogModel, BrainDiskUsage, BrainEvals, BrainHfSearchResult, BrainHostStatus, BrainInstalledModel, BrainInventoryModel, BrainJob, BrainLogsTailResponse, BrainModelBudgetGetResponse, BrainModelDeleteResponse, BrainModelLoadResponse, BrainModelProfileGetResponse, BrainModelProfileSetResponse, BrainNetworkInfo, BrainRemoteConfig, BrainRepoQuant, BrainRuntime, ConnectorsListToolsResponse, ConnectorsOauthAuthorizeResponse, ConnectorsOauthDisconnectResponse, CueMoment, MutableDaemonConfig, MutableDaemonConfigPatch, ProjectLink, SpeechSettingsOptions, SpeechTtsPreviewResult, SpeechTtsSpeakResult, SpeechTtsSpeakCancelResult, VisualizerVoiceCuesResult, AgentPersonalitiesGenerateProfileResult } from "@otto-code/protocol/messages";
|
|
10
10
|
import { type DaemonTransportFactory, type WebSocketFactory } from "./daemon-client-transport.js";
|
|
11
11
|
import { type DaemonClientTrafficHotspot, type DaemonClientTrafficTotals } from "./daemon-client-runtime-metrics.js";
|
|
12
12
|
import { type TerminalStreamEvent } from "./terminal-stream-router.js";
|
|
@@ -255,7 +255,7 @@ export interface FileReadResult {
|
|
|
255
255
|
modifiedAt: string;
|
|
256
256
|
/**
|
|
257
257
|
* Detected line endings. Optional because only the inline JSON read path
|
|
258
|
-
* reports them
|
|
258
|
+
* reports them - the chunked binary transfer never does, and neither do
|
|
259
259
|
* daemons older than v0.4.4. Absent means "not reported", not "LF".
|
|
260
260
|
*/
|
|
261
261
|
eol?: FileEol;
|
|
@@ -284,7 +284,7 @@ export interface FileWriteOptions {
|
|
|
284
284
|
/**
|
|
285
285
|
* Bytes to a workspace path. Gated on `features.binaryFileWrite`. Unlike
|
|
286
286
|
* {@link FileWriteOptions} this carries no precondition: `overwrite` is the
|
|
287
|
-
* whole policy
|
|
287
|
+
* whole policy - see `FsFileWriteBinaryRequestSchema` for why a generated
|
|
288
288
|
* artifact has nothing to reconcile against.
|
|
289
289
|
*/
|
|
290
290
|
export interface FileWriteBinaryOptions {
|
|
@@ -299,7 +299,7 @@ export interface FileWriteBinaryOptions {
|
|
|
299
299
|
chunkSize?: number;
|
|
300
300
|
}
|
|
301
301
|
/**
|
|
302
|
-
* The general file-mutation surface
|
|
302
|
+
* The general file-mutation surface - what exists in a directory, rather than
|
|
303
303
|
* what is inside a file. Gated on `features.fileMutations`; there is no
|
|
304
304
|
* client-side substitute, so callers check the flag before offering the action.
|
|
305
305
|
*/
|
|
@@ -325,14 +325,14 @@ export interface FileRenameOptions {
|
|
|
325
325
|
requestId?: string;
|
|
326
326
|
}
|
|
327
327
|
/**
|
|
328
|
-
* Refine
|
|
328
|
+
* Refine - ask the daemon for proposed rewrites of a pinned set of documents.
|
|
329
329
|
* This call never writes: accepted proposals go back through {@link
|
|
330
330
|
* DaemonClient.writeFile}, one per file, like any other save.
|
|
331
331
|
*/
|
|
332
332
|
export interface FileRefineOptions {
|
|
333
333
|
/** Provider resolution only; the documents themselves travel inline. */
|
|
334
334
|
cwd: string;
|
|
335
|
-
/** What the model may rewrite
|
|
335
|
+
/** What the model may rewrite - this list is the request's blast radius. */
|
|
336
336
|
documents: FileRefineDocument[];
|
|
337
337
|
/** What it may read for context but must never rewrite. */
|
|
338
338
|
references?: FileRefineReference[];
|
|
@@ -1008,7 +1008,7 @@ export declare class DaemonClient {
|
|
|
1008
1008
|
* the whole archived set. Pass `dryRun: true` first to get the count the
|
|
1009
1009
|
* confirm dialog quotes, then the same call with `dryRun: false` to delete.
|
|
1010
1010
|
*
|
|
1011
|
-
* Removes Otto's records only
|
|
1011
|
+
* Removes Otto's records only - provider transcripts are left on disk. Gated
|
|
1012
1012
|
* by `server_info.features.historyDelete`; there is no fallback path, so check
|
|
1013
1013
|
* the flag before offering the action.
|
|
1014
1014
|
*/
|
|
@@ -1029,7 +1029,7 @@ export declare class DaemonClient {
|
|
|
1029
1029
|
* `dryRun: false` to delete.
|
|
1030
1030
|
*
|
|
1031
1031
|
* Cleared images do not come back: a message that referenced one renders its
|
|
1032
|
-
* alt text from then on. Scope is the whole host
|
|
1032
|
+
* alt text from then on. Scope is the whole host - filenames are a content
|
|
1033
1033
|
* hash, so per-chat or per-workspace scope does not exist. Gated by
|
|
1034
1034
|
* `server_info.features.attachmentStorage`.
|
|
1035
1035
|
*/
|
|
@@ -1050,7 +1050,7 @@ export declare class DaemonClient {
|
|
|
1050
1050
|
stopObservedSubagent(agentId: string): Promise<void>;
|
|
1051
1051
|
/**
|
|
1052
1052
|
* Stop a running background shell task (Claude Bash tool run_in_background).
|
|
1053
|
-
* Not an AI subagent
|
|
1053
|
+
* Not an AI subagent - the daemon resolves it to its owning provider task and
|
|
1054
1054
|
* calls the provider's stopTask, same mechanism as stopObservedSubagent.
|
|
1055
1055
|
*/
|
|
1056
1056
|
stopBackgroundShellTask(parentAgentId: string, taskId: string): Promise<void>;
|
|
@@ -1061,7 +1061,7 @@ export declare class DaemonClient {
|
|
|
1061
1061
|
clearBackgroundShellTasks(parentAgentId: string, taskIds: readonly string[]): Promise<void>;
|
|
1062
1062
|
/**
|
|
1063
1063
|
* Start one or more suggested tasks (from `spawn_task` chips), applying the
|
|
1064
|
-
* same mode to each
|
|
1064
|
+
* same mode to each - a new worktree workspace per task, a new local session
|
|
1065
1065
|
* per task, or steering the parent's current session. Individual actions pass
|
|
1066
1066
|
* a single-element array; the "Start all" collective action passes the whole
|
|
1067
1067
|
* pending queue. Resolves to the count started; throws only if all failed.
|
|
@@ -1087,7 +1087,7 @@ export declare class DaemonClient {
|
|
|
1087
1087
|
clearFinishedRuns(): Promise<string[]>;
|
|
1088
1088
|
/**
|
|
1089
1089
|
* Orchestration: delete one finished (or draft) run. Throws with the
|
|
1090
|
-
* daemon's reason when it refuses
|
|
1090
|
+
* daemon's reason when it refuses - an active run has to be canceled first.
|
|
1091
1091
|
*/
|
|
1092
1092
|
deleteRun(runId: string): Promise<string>;
|
|
1093
1093
|
/** Orchestration: list the host's reusable graph templates. */
|
|
@@ -1217,7 +1217,7 @@ export declare class DaemonClient {
|
|
|
1217
1217
|
} | null>;
|
|
1218
1218
|
/**
|
|
1219
1219
|
* Move one queued message to a new position. Resolves false when the entry
|
|
1220
|
-
* was already drained or was already there
|
|
1220
|
+
* was already drained or was already there - the authoritative order arrives
|
|
1221
1221
|
* on the agent snapshot either way. Requires
|
|
1222
1222
|
* `server_info.features.steerQueueReorder`.
|
|
1223
1223
|
*/
|
|
@@ -1235,7 +1235,7 @@ export declare class DaemonClient {
|
|
|
1235
1235
|
/**
|
|
1236
1236
|
* Live-switch a running agent's personality (null clears it). The daemon
|
|
1237
1237
|
* re-resolves the roster id against the agent's cwd and applies the full
|
|
1238
|
-
* personality
|
|
1238
|
+
* personality - system prompt, identity, model/mode/effort - restarting the
|
|
1239
1239
|
* provider query so the prompt takes effect on the next turn. Gate on
|
|
1240
1240
|
* server_info.features.setAgentPersonality.
|
|
1241
1241
|
*/
|
|
@@ -1436,10 +1436,10 @@ export declare class DaemonClient {
|
|
|
1436
1436
|
expectedModifiedAt: string;
|
|
1437
1437
|
expectedRevision?: string;
|
|
1438
1438
|
}): Promise<FsFileWriteResult>;
|
|
1439
|
-
/** Conditional save
|
|
1439
|
+
/** Conditional save - see FileWriteRequestSchema for the no-clobber contract. */
|
|
1440
1440
|
writeFile(options: FileWriteOptions): Promise<FileWriteResult>;
|
|
1441
1441
|
/**
|
|
1442
|
-
* Write bytes to a workspace file
|
|
1442
|
+
* Write bytes to a workspace file - the path for generated artifacts the
|
|
1443
1443
|
* text write cannot carry (it refuses binary targets outright). Gated on
|
|
1444
1444
|
* `features.binaryFileWrite`; there is no client-side substitute, because
|
|
1445
1445
|
* the client never touches a workspace file on any platform.
|
|
@@ -1454,9 +1454,9 @@ export declare class DaemonClient {
|
|
|
1454
1454
|
* frames leave in order and behind the JSON request that announced them.
|
|
1455
1455
|
*/
|
|
1456
1456
|
private sendFileTransfer;
|
|
1457
|
-
/** Create an empty file or a directory. Never overwrites
|
|
1457
|
+
/** Create an empty file or a directory. Never overwrites - see FileCreateResultSchema. */
|
|
1458
1458
|
createFileEntry(options: FileCreateOptions): Promise<FileCreateResult>;
|
|
1459
|
-
/** Permanent delete
|
|
1459
|
+
/** Permanent delete - an unlink, not a move to any trash. */
|
|
1460
1460
|
deleteFileEntry(options: FileDeleteOptions): Promise<FileDeleteResult>;
|
|
1461
1461
|
/** Rename, which is also move. Never clobbers an occupied destination. */
|
|
1462
1462
|
renameFileEntry(options: FileRenameOptions): Promise<FileRenameResult>;
|
|
@@ -1483,7 +1483,7 @@ export declare class DaemonClient {
|
|
|
1483
1483
|
findCodeDefinition(input: CodeDefinitionQuery, requestId?: string): Promise<CodeDefinitionResult>;
|
|
1484
1484
|
/**
|
|
1485
1485
|
* Mirror the editor's current buffer to the daemon so definitions resolve against
|
|
1486
|
-
* unsaved edits. Debounced by the caller
|
|
1486
|
+
* unsaved edits. Debounced by the caller - this is not a per-keystroke RPC.
|
|
1487
1487
|
*/
|
|
1488
1488
|
syncCodeDocument(cwd: string, path: string, text: string, requestId?: string): Promise<void>;
|
|
1489
1489
|
/** Release the daemon-side mirror when a file tab closes. */
|
|
@@ -1497,7 +1497,7 @@ export declare class DaemonClient {
|
|
|
1497
1497
|
/** Every reference to the symbol at a position, for the references results tab. */
|
|
1498
1498
|
findCodeReferences(input: CodeDefinitionQuery, requestId?: string): Promise<CodeReferencesResult>;
|
|
1499
1499
|
/**
|
|
1500
|
-
* A rename **dry run**
|
|
1500
|
+
* A rename **dry run** - every edit it would make, and nothing written. The client
|
|
1501
1501
|
* puts this in front of the user as a job to audit before applying.
|
|
1502
1502
|
*/
|
|
1503
1503
|
previewCodeRename(input: CodeRenamePreviewQuery, requestId?: string): Promise<CodeRenamePlan>;
|
|
@@ -1531,7 +1531,7 @@ export declare class DaemonClient {
|
|
|
1531
1531
|
*
|
|
1532
1532
|
* Never throws and never carries an error the caller has to render. A workspace with no
|
|
1533
1533
|
* solution, a host with no .NET SDK, and a host with the feature switched off all answer with an
|
|
1534
|
-
* empty list, so the caller has one silent case
|
|
1534
|
+
* empty list, so the caller has one silent case - "no switcher" - rather than four states.
|
|
1535
1535
|
*/
|
|
1536
1536
|
listSolutions(cwd: string, requestId?: string): Promise<SolutionRef[]>;
|
|
1537
1537
|
/** One solution's organisation: folders, the projects inside them, configurations. */
|
|
@@ -1552,7 +1552,7 @@ export declare class DaemonClient {
|
|
|
1552
1552
|
}, requestId?: string): Promise<SolutionProjectContents>;
|
|
1553
1553
|
/** Definition symbols for a single file (document outline). */
|
|
1554
1554
|
getCodeOutline(cwd: string, path: string, requestId?: string): Promise<CodeSymbolLocation[]>;
|
|
1555
|
-
/** Preview-first project replace
|
|
1555
|
+
/** Preview-first project replace - see FileReplaceRequestSchema. */
|
|
1556
1556
|
replaceFiles(options: {
|
|
1557
1557
|
cwd: string;
|
|
1558
1558
|
replacement: string;
|
|
@@ -1606,7 +1606,7 @@ export declare class DaemonClient {
|
|
|
1606
1606
|
*
|
|
1607
1607
|
* Pass `workspaceId` whenever the write may be project-scoped: the daemon
|
|
1608
1608
|
* binds the entry to the repo root that workspace resolves to, and an entry
|
|
1609
|
-
* scoped to "project" with no root is filtered out of every brief
|
|
1609
|
+
* scoped to "project" with no root is filtered out of every brief - stored,
|
|
1610
1610
|
* listed, and never sent.
|
|
1611
1611
|
*/
|
|
1612
1612
|
updatePersonalityMemory(input: {
|
|
@@ -1683,7 +1683,23 @@ export declare class DaemonClient {
|
|
|
1683
1683
|
config: MutableDaemonConfig;
|
|
1684
1684
|
}>;
|
|
1685
1685
|
connectorsListTools(connectorId: string, requestId?: string): Promise<ConnectorsListToolsResponse["payload"]>;
|
|
1686
|
-
|
|
1686
|
+
/**
|
|
1687
|
+
* Start a connector's OAuth login. Resolves with the URL to open, or with
|
|
1688
|
+
* status "authorized" when the daemon already held a usable token. The login
|
|
1689
|
+
* itself settles later on the `connectors.oauth.status` push, because the user
|
|
1690
|
+
* is in a browser by then.
|
|
1691
|
+
*/
|
|
1692
|
+
connectorsOauthAuthorize(connectorId: string, scope?: string, requestId?: string): Promise<ConnectorsOauthAuthorizeResponse["payload"]>;
|
|
1693
|
+
/** Drop a connector's stored authorization. */
|
|
1694
|
+
connectorsOauthDisconnect(connectorId: string, requestId?: string): Promise<ConnectorsOauthDisconnectResponse["payload"]>;
|
|
1695
|
+
/**
|
|
1696
|
+
* The brain's status. Pass `resources` only from a surface that renders the
|
|
1697
|
+
* live CPU/RAM/GPU/slot numbers: it costs an `nvidia-smi` spawn plus a /slots
|
|
1698
|
+
* round trip on the brain, and this call is also the liveness poll.
|
|
1699
|
+
*/
|
|
1700
|
+
brainHostStatus(options?: {
|
|
1701
|
+
resources?: boolean;
|
|
1702
|
+
}, requestId?: string): Promise<BrainHostStatus>;
|
|
1687
1703
|
brainHostStart(model?: string | null, requestId?: string): Promise<BrainHostStatus>;
|
|
1688
1704
|
brainHostStop(requestId?: string): Promise<BrainHostStatus>;
|
|
1689
1705
|
brainHostRestart(model?: string | null, requestId?: string): Promise<BrainHostStatus>;
|
|
@@ -1705,6 +1721,40 @@ export declare class DaemonClient {
|
|
|
1705
1721
|
brainBench(model?: string | null, requestId?: string): Promise<BrainJob>;
|
|
1706
1722
|
brainJobsList(requestId?: string): Promise<BrainJob[]>;
|
|
1707
1723
|
brainJobsCancel(jobId: string, requestId?: string): Promise<BrainJob[]>;
|
|
1724
|
+
/**
|
|
1725
|
+
* The joined model inventory: scan row, GGUF metadata, saved profile,
|
|
1726
|
+
* calibration state, VRAM budget and benchmark score per model, plus disk
|
|
1727
|
+
* usage. One call feeds the whole Models tab.
|
|
1728
|
+
*/
|
|
1729
|
+
brainModelsInventory(requestId?: string): Promise<{
|
|
1730
|
+
models: BrainInventoryModel[];
|
|
1731
|
+
disk: BrainDiskUsage | null;
|
|
1732
|
+
}>;
|
|
1733
|
+
/** One model's saved profile, the field descriptors, and its warnings. */
|
|
1734
|
+
brainModelProfileGet(modelId: string, requestId?: string): Promise<BrainModelProfileGetResponse["payload"]>;
|
|
1735
|
+
/**
|
|
1736
|
+
* Write the editable profile fields. The reply carries the recomputed budget,
|
|
1737
|
+
* so an edit costs one round trip rather than a write the UI has to follow
|
|
1738
|
+
* with a read.
|
|
1739
|
+
*/
|
|
1740
|
+
brainModelProfileSet(modelId: string, patch: Record<string, unknown>, requestId?: string): Promise<BrainModelProfileSetResponse["payload"]>;
|
|
1741
|
+
/**
|
|
1742
|
+
* The VRAM budget for a hypothetical profile. `overrides` are string-encoded
|
|
1743
|
+
* field values, so the UI can preview the budget while a control is mid-drag
|
|
1744
|
+
* without persisting a value the user is scrubbing past.
|
|
1745
|
+
*/
|
|
1746
|
+
brainModelBudget(modelId: string, overrides?: Record<string, string>, requestId?: string): Promise<BrainModelBudgetGetResponse["payload"]>;
|
|
1747
|
+
/**
|
|
1748
|
+
* Load a model into the running brain. This is not `brainHostStart`, which
|
|
1749
|
+
* restarts the daemon's child process and has no remote equivalent.
|
|
1750
|
+
*/
|
|
1751
|
+
brainModelLoad(modelId: string, requestId?: string): Promise<BrainModelLoadResponse["payload"]>;
|
|
1752
|
+
/** Unload the resident model, leaving the brain up and serving nothing. */
|
|
1753
|
+
brainModelUnload(requestId?: string): Promise<BrainHostStatus | null>;
|
|
1754
|
+
/** Delete a model's files. The brain refuses while that model is loaded. */
|
|
1755
|
+
brainModelDelete(modelId: string, requestId?: string): Promise<BrainModelDeleteResponse["payload"]>;
|
|
1756
|
+
/** Tail the brain's llama-server log. */
|
|
1757
|
+
brainLogsTail(limit?: number | null, requestId?: string): Promise<BrainLogsTailResponse["payload"]>;
|
|
1708
1758
|
getSpeechSettingsOptions(requestId?: string): Promise<{
|
|
1709
1759
|
requestId: string;
|
|
1710
1760
|
options: SpeechSettingsOptions;
|
|
@@ -1758,7 +1808,7 @@ export declare class DaemonClient {
|
|
|
1758
1808
|
listProviderUsage(options?: {
|
|
1759
1809
|
requestId?: string;
|
|
1760
1810
|
}): Promise<ProviderUsageListPayload>;
|
|
1761
|
-
/** Daemon-wide "fun stats"
|
|
1811
|
+
/** Daemon-wide "fun stats" - see docs/data-model.md ActivityStatsStore. */
|
|
1762
1812
|
getActivityStats(options?: {
|
|
1763
1813
|
requestId?: string;
|
|
1764
1814
|
}): Promise<StatsActivityGetResponseMessage["payload"]>;
|
|
@@ -1766,7 +1816,7 @@ export declare class DaemonClient {
|
|
|
1766
1816
|
resetActivityStats(options?: {
|
|
1767
1817
|
requestId?: string;
|
|
1768
1818
|
}): Promise<StatsActivityResetResponseMessage["payload"]>;
|
|
1769
|
-
/** Itemized usage ledger
|
|
1819
|
+
/** Itemized usage ledger - the scrollable rows behind the stats tiles (usage-ledger). */
|
|
1770
1820
|
getUsageLog(options?: {
|
|
1771
1821
|
limit?: number;
|
|
1772
1822
|
before?: number;
|
|
@@ -1895,7 +1945,7 @@ export declare class DaemonClient {
|
|
|
1895
1945
|
/**
|
|
1896
1946
|
* Session totals for inbound daemon traffic, including the main-thread time
|
|
1897
1947
|
* spent handling it. Null when runtime metrics are disabled for this client.
|
|
1898
|
-
* Read by the app's resource monitor
|
|
1948
|
+
* Read by the app's resource monitor - the wire is a first-class suspect when
|
|
1899
1949
|
* the UI thread degrades, so it has to be measurable rather than inferred.
|
|
1900
1950
|
*/
|
|
1901
1951
|
getTrafficTotals(): DaemonClientTrafficTotals | null;
|
|
@@ -1932,7 +1982,7 @@ export declare class DaemonClient {
|
|
|
1932
1982
|
/**
|
|
1933
1983
|
* `includeDiscovered` also returns the Scripts the workspace's own project
|
|
1934
1984
|
* files declare (package.json scripts today), each tagged with its `source`.
|
|
1935
|
-
* Gate it on `server_info.features.workspaceScriptDiscovery`
|
|
1985
|
+
* Gate it on `server_info.features.workspaceScriptDiscovery` - an older
|
|
1936
1986
|
* daemon ignores the flag and answers with the otto.json list only.
|
|
1937
1987
|
*/
|
|
1938
1988
|
listWorkspaceScripts(workspaceId: string, options?: {
|
|
@@ -1950,7 +2000,7 @@ export declare class DaemonClient {
|
|
|
1950
2000
|
connectHub(hubUrl: string, token: string, requestId?: string): Promise<{
|
|
1951
2001
|
requestId: string;
|
|
1952
2002
|
status: {
|
|
1953
|
-
state: "
|
|
2003
|
+
state: "connected" | "connecting" | "not_connected" | "reconnecting" | "disconnecting" | "revoked";
|
|
1954
2004
|
daemonId: string | null;
|
|
1955
2005
|
hubOrigin: string | null;
|
|
1956
2006
|
scopes: string[];
|
|
@@ -1961,7 +2011,7 @@ export declare class DaemonClient {
|
|
|
1961
2011
|
getHubStatus(requestId?: string): Promise<{
|
|
1962
2012
|
requestId: string;
|
|
1963
2013
|
status: {
|
|
1964
|
-
state: "
|
|
2014
|
+
state: "connected" | "connecting" | "not_connected" | "reconnecting" | "disconnecting" | "revoked";
|
|
1965
2015
|
daemonId: string | null;
|
|
1966
2016
|
hubOrigin: string | null;
|
|
1967
2017
|
scopes: string[];
|
|
@@ -1972,7 +2022,7 @@ export declare class DaemonClient {
|
|
|
1972
2022
|
disconnectHub(force?: boolean, requestId?: string): Promise<{
|
|
1973
2023
|
requestId: string;
|
|
1974
2024
|
status: {
|
|
1975
|
-
state: "
|
|
2025
|
+
state: "connected" | "connecting" | "not_connected" | "reconnecting" | "disconnecting" | "revoked";
|
|
1976
2026
|
daemonId: string | null;
|
|
1977
2027
|
hubOrigin: string | null;
|
|
1978
2028
|
scopes: string[];
|
package/dist/daemon-client.js
CHANGED
|
@@ -293,7 +293,7 @@ export class DaemonClient {
|
|
|
293
293
|
const runtimeMetricsIntervalMs = typeof config.runtimeMetricsIntervalMs === "number" && config.runtimeMetricsIntervalMs > 0
|
|
294
294
|
? config.runtimeMetricsIntervalMs
|
|
295
295
|
: 0;
|
|
296
|
-
// The metrics object is always constructed
|
|
296
|
+
// The metrics object is always constructed - it is a handful of Maps keyed
|
|
297
297
|
// by message type, and its per-message cost is dwarfed by the JSON.parse it
|
|
298
298
|
// is measuring. What `runtimeMetricsIntervalMs` gates is the *periodic log*,
|
|
299
299
|
// which is the part that is actually noisy. Keeping the counters on
|
|
@@ -1393,7 +1393,7 @@ export class DaemonClient {
|
|
|
1393
1393
|
* the whole archived set. Pass `dryRun: true` first to get the count the
|
|
1394
1394
|
* confirm dialog quotes, then the same call with `dryRun: false` to delete.
|
|
1395
1395
|
*
|
|
1396
|
-
* Removes Otto's records only
|
|
1396
|
+
* Removes Otto's records only - provider transcripts are left on disk. Gated
|
|
1397
1397
|
* by `server_info.features.historyDelete`; there is no fallback path, so check
|
|
1398
1398
|
* the flag before offering the action.
|
|
1399
1399
|
*/
|
|
@@ -1424,7 +1424,7 @@ export class DaemonClient {
|
|
|
1424
1424
|
* `dryRun: false` to delete.
|
|
1425
1425
|
*
|
|
1426
1426
|
* Cleared images do not come back: a message that referenced one renders its
|
|
1427
|
-
* alt text from then on. Scope is the whole host
|
|
1427
|
+
* alt text from then on. Scope is the whole host - filenames are a content
|
|
1428
1428
|
* hash, so per-chat or per-workspace scope does not exist. Gated by
|
|
1429
1429
|
* `server_info.features.attachmentStorage`.
|
|
1430
1430
|
*/
|
|
@@ -1490,7 +1490,7 @@ export class DaemonClient {
|
|
|
1490
1490
|
}
|
|
1491
1491
|
/**
|
|
1492
1492
|
* Stop a running background shell task (Claude Bash tool run_in_background).
|
|
1493
|
-
* Not an AI subagent
|
|
1493
|
+
* Not an AI subagent - the daemon resolves it to its owning provider task and
|
|
1494
1494
|
* calls the provider's stopTask, same mechanism as stopObservedSubagent.
|
|
1495
1495
|
*/
|
|
1496
1496
|
async stopBackgroundShellTask(parentAgentId, taskId) {
|
|
@@ -1523,7 +1523,7 @@ export class DaemonClient {
|
|
|
1523
1523
|
}
|
|
1524
1524
|
/**
|
|
1525
1525
|
* Start one or more suggested tasks (from `spawn_task` chips), applying the
|
|
1526
|
-
* same mode to each
|
|
1526
|
+
* same mode to each - a new worktree workspace per task, a new local session
|
|
1527
1527
|
* per task, or steering the parent's current session. Individual actions pass
|
|
1528
1528
|
* a single-element array; the "Start all" collective action passes the whole
|
|
1529
1529
|
* pending queue. Resolves to the count started; throws only if all failed.
|
|
@@ -1591,7 +1591,7 @@ export class DaemonClient {
|
|
|
1591
1591
|
}
|
|
1592
1592
|
/**
|
|
1593
1593
|
* Orchestration: delete one finished (or draft) run. Throws with the
|
|
1594
|
-
* daemon's reason when it refuses
|
|
1594
|
+
* daemon's reason when it refuses - an active run has to be canceled first.
|
|
1595
1595
|
*/
|
|
1596
1596
|
async deleteRun(runId) {
|
|
1597
1597
|
const payload = await this.sendNamespacedCorrelatedSessionRequest({
|
|
@@ -2298,7 +2298,7 @@ export class DaemonClient {
|
|
|
2298
2298
|
}
|
|
2299
2299
|
/**
|
|
2300
2300
|
* Move one queued message to a new position. Resolves false when the entry
|
|
2301
|
-
* was already drained or was already there
|
|
2301
|
+
* was already drained or was already there - the authoritative order arrives
|
|
2302
2302
|
* on the agent snapshot either way. Requires
|
|
2303
2303
|
* `server_info.features.steerQueueReorder`.
|
|
2304
2304
|
*/
|
|
@@ -2408,7 +2408,7 @@ export class DaemonClient {
|
|
|
2408
2408
|
});
|
|
2409
2409
|
// A refused cancellation comes back as an error payload, not a rejected
|
|
2410
2410
|
// frame. Dropping it reported Stop as successful while the provider was
|
|
2411
|
-
// still running and still spending tokens
|
|
2411
|
+
// still running and still spending tokens - the exact outcome the daemon
|
|
2412
2412
|
// refuses the cancel to avoid.
|
|
2413
2413
|
if (payload.error) {
|
|
2414
2414
|
throw new Error(payload.error);
|
|
@@ -2527,7 +2527,7 @@ export class DaemonClient {
|
|
|
2527
2527
|
/**
|
|
2528
2528
|
* Live-switch a running agent's personality (null clears it). The daemon
|
|
2529
2529
|
* re-resolves the roster id against the agent's cwd and applies the full
|
|
2530
|
-
* personality
|
|
2530
|
+
* personality - system prompt, identity, model/mode/effort - restarting the
|
|
2531
2531
|
* provider query so the prompt takes effect on the next turn. Gate on
|
|
2532
2532
|
* server_info.features.setAgentPersonality.
|
|
2533
2533
|
*/
|
|
@@ -2619,7 +2619,7 @@ export class DaemonClient {
|
|
|
2619
2619
|
return this.sendRequest({
|
|
2620
2620
|
requestId: resolvedRequestId,
|
|
2621
2621
|
message,
|
|
2622
|
-
timeout: 300000, // 5 minutes
|
|
2622
|
+
timeout: 300000, // 5 minutes - npm update can be slow on remote machines
|
|
2623
2623
|
options: { skipQueue: true },
|
|
2624
2624
|
select: (msg) => {
|
|
2625
2625
|
const parsed = DaemonUpdateResponseSchema.safeParse(msg);
|
|
@@ -3017,7 +3017,7 @@ export class DaemonClient {
|
|
|
3017
3017
|
});
|
|
3018
3018
|
}
|
|
3019
3019
|
// ── Git file investigation ────────────────────────────────────────────────
|
|
3020
|
-
// Local git only: no remote, no forge, and no per-provider variant
|
|
3020
|
+
// Local git only: no remote, no forge, and no per-provider variant - the same
|
|
3021
3021
|
// four calls answer for every agent provider. Gated by
|
|
3022
3022
|
// server_info.features.checkoutGitFileHistory.
|
|
3023
3023
|
async checkoutGitFileHistory(cwd, input, requestId) {
|
|
@@ -3510,7 +3510,7 @@ export class DaemonClient {
|
|
|
3510
3510
|
content: file.content,
|
|
3511
3511
|
size: file.size,
|
|
3512
3512
|
modifiedAt: file.modifiedAt,
|
|
3513
|
-
// COMPAT(textEditor): added in v0.4.4
|
|
3513
|
+
// COMPAT(textEditor): added in v0.4.4 - the editor is gated on
|
|
3514
3514
|
// features.textEditor, so a gated daemon always sends both fields.
|
|
3515
3515
|
eol: file.eol ?? "lf",
|
|
3516
3516
|
hash: file.hash ?? null,
|
|
@@ -3528,7 +3528,7 @@ export class DaemonClient {
|
|
|
3528
3528
|
});
|
|
3529
3529
|
return payload.result;
|
|
3530
3530
|
}
|
|
3531
|
-
/** Conditional save
|
|
3531
|
+
/** Conditional save - see FileWriteRequestSchema for the no-clobber contract. */
|
|
3532
3532
|
async writeFile(options) {
|
|
3533
3533
|
const payload = await this.sendCorrelatedSessionRequest({
|
|
3534
3534
|
requestId: options.requestId,
|
|
@@ -3547,7 +3547,7 @@ export class DaemonClient {
|
|
|
3547
3547
|
return payload.result;
|
|
3548
3548
|
}
|
|
3549
3549
|
/**
|
|
3550
|
-
* Write bytes to a workspace file
|
|
3550
|
+
* Write bytes to a workspace file - the path for generated artifacts the
|
|
3551
3551
|
* text write cannot carry (it refuses binary targets outright). Gated on
|
|
3552
3552
|
* `features.binaryFileWrite`; there is no client-side substitute, because
|
|
3553
3553
|
* the client never touches a workspace file on any platform.
|
|
@@ -3576,8 +3576,8 @@ export class DaemonClient {
|
|
|
3576
3576
|
this.sendFileTransfer({
|
|
3577
3577
|
requestId: resolvedRequestId,
|
|
3578
3578
|
bytes,
|
|
3579
|
-
// Nothing downstream reads the mime for a workspace write
|
|
3580
|
-
// decides what the file is
|
|
3579
|
+
// Nothing downstream reads the mime for a workspace write - the path
|
|
3580
|
+
// decides what the file is - but the frame metadata requires one.
|
|
3581
3581
|
mime: "application/octet-stream",
|
|
3582
3582
|
chunkSize: options.chunkSize,
|
|
3583
3583
|
});
|
|
@@ -3613,7 +3613,7 @@ export class DaemonClient {
|
|
|
3613
3613
|
requestId: input.requestId,
|
|
3614
3614
|
}));
|
|
3615
3615
|
}
|
|
3616
|
-
/** Create an empty file or a directory. Never overwrites
|
|
3616
|
+
/** Create an empty file or a directory. Never overwrites - see FileCreateResultSchema. */
|
|
3617
3617
|
async createFileEntry(options) {
|
|
3618
3618
|
const payload = await this.sendCorrelatedSessionRequest({
|
|
3619
3619
|
requestId: options.requestId,
|
|
@@ -3627,7 +3627,7 @@ export class DaemonClient {
|
|
|
3627
3627
|
});
|
|
3628
3628
|
return payload.result;
|
|
3629
3629
|
}
|
|
3630
|
-
/** Permanent delete
|
|
3630
|
+
/** Permanent delete - an unlink, not a move to any trash. */
|
|
3631
3631
|
async deleteFileEntry(options) {
|
|
3632
3632
|
const payload = await this.sendCorrelatedSessionRequest({
|
|
3633
3633
|
requestId: options.requestId,
|
|
@@ -3749,7 +3749,7 @@ export class DaemonClient {
|
|
|
3749
3749
|
}
|
|
3750
3750
|
/**
|
|
3751
3751
|
* Mirror the editor's current buffer to the daemon so definitions resolve against
|
|
3752
|
-
* unsaved edits. Debounced by the caller
|
|
3752
|
+
* unsaved edits. Debounced by the caller - this is not a per-keystroke RPC.
|
|
3753
3753
|
*/
|
|
3754
3754
|
async syncCodeDocument(cwd, path, text, requestId) {
|
|
3755
3755
|
const payload = await this.sendCorrelatedSessionRequest({
|
|
@@ -3813,7 +3813,7 @@ export class DaemonClient {
|
|
|
3813
3813
|
return { status: payload.status, locations: payload.locations, error: payload.error };
|
|
3814
3814
|
}
|
|
3815
3815
|
/**
|
|
3816
|
-
* A rename **dry run**
|
|
3816
|
+
* A rename **dry run** - every edit it would make, and nothing written. The client
|
|
3817
3817
|
* puts this in front of the user as a job to audit before applying.
|
|
3818
3818
|
*/
|
|
3819
3819
|
async previewCodeRename(input, requestId) {
|
|
@@ -3924,7 +3924,7 @@ export class DaemonClient {
|
|
|
3924
3924
|
*
|
|
3925
3925
|
* Never throws and never carries an error the caller has to render. A workspace with no
|
|
3926
3926
|
* solution, a host with no .NET SDK, and a host with the feature switched off all answer with an
|
|
3927
|
-
* empty list, so the caller has one silent case
|
|
3927
|
+
* empty list, so the caller has one silent case - "no switcher" - rather than four states.
|
|
3928
3928
|
*/
|
|
3929
3929
|
async listSolutions(cwd, requestId) {
|
|
3930
3930
|
const payload = await this.sendCorrelatedSessionRequest({
|
|
@@ -3999,7 +3999,7 @@ export class DaemonClient {
|
|
|
3999
3999
|
}
|
|
4000
4000
|
return payload.symbols;
|
|
4001
4001
|
}
|
|
4002
|
-
/** Preview-first project replace
|
|
4002
|
+
/** Preview-first project replace - see FileReplaceRequestSchema. */
|
|
4003
4003
|
async replaceFiles(options) {
|
|
4004
4004
|
return this.sendCorrelatedSessionRequest({
|
|
4005
4005
|
requestId: options.requestId,
|
|
@@ -4171,7 +4171,7 @@ export class DaemonClient {
|
|
|
4171
4171
|
*
|
|
4172
4172
|
* Pass `workspaceId` whenever the write may be project-scoped: the daemon
|
|
4173
4173
|
* binds the entry to the repo root that workspace resolves to, and an entry
|
|
4174
|
-
* scoped to "project" with no root is filtered out of every brief
|
|
4174
|
+
* scoped to "project" with no root is filtered out of every brief - stored,
|
|
4175
4175
|
* listed, and never sent.
|
|
4176
4176
|
*/
|
|
4177
4177
|
async updatePersonalityMemory(input, requestId) {
|
|
@@ -4358,11 +4358,45 @@ export class DaemonClient {
|
|
|
4358
4358
|
responseType: "connectors.list_tools.response",
|
|
4359
4359
|
});
|
|
4360
4360
|
}
|
|
4361
|
-
|
|
4361
|
+
/**
|
|
4362
|
+
* Start a connector's OAuth login. Resolves with the URL to open, or with
|
|
4363
|
+
* status "authorized" when the daemon already held a usable token. The login
|
|
4364
|
+
* itself settles later on the `connectors.oauth.status` push, because the user
|
|
4365
|
+
* is in a browser by then.
|
|
4366
|
+
*/
|
|
4367
|
+
async connectorsOauthAuthorize(connectorId, scope, requestId) {
|
|
4368
|
+
return this.sendCorrelatedSessionRequest({
|
|
4369
|
+
requestId,
|
|
4370
|
+
message: {
|
|
4371
|
+
type: "connectors.oauth.authorize.request",
|
|
4372
|
+
connectorId,
|
|
4373
|
+
...(scope ? { scope } : {}),
|
|
4374
|
+
},
|
|
4375
|
+
responseType: "connectors.oauth.authorize.response",
|
|
4376
|
+
});
|
|
4377
|
+
}
|
|
4378
|
+
/** Drop a connector's stored authorization. */
|
|
4379
|
+
async connectorsOauthDisconnect(connectorId, requestId) {
|
|
4380
|
+
return this.sendCorrelatedSessionRequest({
|
|
4381
|
+
requestId,
|
|
4382
|
+
message: {
|
|
4383
|
+
type: "connectors.oauth.disconnect.request",
|
|
4384
|
+
connectorId,
|
|
4385
|
+
},
|
|
4386
|
+
responseType: "connectors.oauth.disconnect.response",
|
|
4387
|
+
});
|
|
4388
|
+
}
|
|
4389
|
+
/**
|
|
4390
|
+
* The brain's status. Pass `resources` only from a surface that renders the
|
|
4391
|
+
* live CPU/RAM/GPU/slot numbers: it costs an `nvidia-smi` spawn plus a /slots
|
|
4392
|
+
* round trip on the brain, and this call is also the liveness poll.
|
|
4393
|
+
*/
|
|
4394
|
+
async brainHostStatus(options, requestId) {
|
|
4362
4395
|
const payload = await this.sendCorrelatedSessionRequest({
|
|
4363
4396
|
requestId,
|
|
4364
4397
|
message: {
|
|
4365
4398
|
type: "brain.host.status.request",
|
|
4399
|
+
resources: options?.resources ?? false,
|
|
4366
4400
|
},
|
|
4367
4401
|
responseType: "brain.host.status.response",
|
|
4368
4402
|
});
|
|
@@ -4588,6 +4622,123 @@ export class DaemonClient {
|
|
|
4588
4622
|
}
|
|
4589
4623
|
return payload.jobs;
|
|
4590
4624
|
}
|
|
4625
|
+
// --- Brain Console --------------------------------------------------------
|
|
4626
|
+
// These proxy the brain's own /__host/* management API and work against a
|
|
4627
|
+
// local or a remote brain identically. Gated by features.brainConsole on the
|
|
4628
|
+
// daemon, and by `capabilities` on brain.host.status for the brain itself.
|
|
4629
|
+
// Each throws the brain's own message on failure, because "could not delete
|
|
4630
|
+
// the model" with no reason is not a usable error.
|
|
4631
|
+
/**
|
|
4632
|
+
* The joined model inventory: scan row, GGUF metadata, saved profile,
|
|
4633
|
+
* calibration state, VRAM budget and benchmark score per model, plus disk
|
|
4634
|
+
* usage. One call feeds the whole Models tab.
|
|
4635
|
+
*/
|
|
4636
|
+
async brainModelsInventory(requestId) {
|
|
4637
|
+
const payload = await this.sendCorrelatedSessionRequest({
|
|
4638
|
+
requestId,
|
|
4639
|
+
message: { type: "brain.models.inventory.request" },
|
|
4640
|
+
responseType: "brain.models.inventory.response",
|
|
4641
|
+
});
|
|
4642
|
+
if (payload.error) {
|
|
4643
|
+
throw new Error(payload.error);
|
|
4644
|
+
}
|
|
4645
|
+
return { models: payload.models, disk: payload.disk };
|
|
4646
|
+
}
|
|
4647
|
+
/** One model's saved profile, the field descriptors, and its warnings. */
|
|
4648
|
+
async brainModelProfileGet(modelId, requestId) {
|
|
4649
|
+
const payload = await this.sendCorrelatedSessionRequest({
|
|
4650
|
+
requestId,
|
|
4651
|
+
message: { type: "brain.model.profile.get.request", modelId },
|
|
4652
|
+
responseType: "brain.model.profile.get.response",
|
|
4653
|
+
});
|
|
4654
|
+
if (payload.error) {
|
|
4655
|
+
throw new Error(payload.error);
|
|
4656
|
+
}
|
|
4657
|
+
return payload;
|
|
4658
|
+
}
|
|
4659
|
+
/**
|
|
4660
|
+
* Write the editable profile fields. The reply carries the recomputed budget,
|
|
4661
|
+
* so an edit costs one round trip rather than a write the UI has to follow
|
|
4662
|
+
* with a read.
|
|
4663
|
+
*/
|
|
4664
|
+
async brainModelProfileSet(modelId, patch, requestId) {
|
|
4665
|
+
const payload = await this.sendCorrelatedSessionRequest({
|
|
4666
|
+
requestId,
|
|
4667
|
+
message: { type: "brain.model.profile.set.request", modelId, patch },
|
|
4668
|
+
responseType: "brain.model.profile.set.response",
|
|
4669
|
+
});
|
|
4670
|
+
if (payload.error) {
|
|
4671
|
+
throw new Error(payload.error);
|
|
4672
|
+
}
|
|
4673
|
+
return payload;
|
|
4674
|
+
}
|
|
4675
|
+
/**
|
|
4676
|
+
* The VRAM budget for a hypothetical profile. `overrides` are string-encoded
|
|
4677
|
+
* field values, so the UI can preview the budget while a control is mid-drag
|
|
4678
|
+
* without persisting a value the user is scrubbing past.
|
|
4679
|
+
*/
|
|
4680
|
+
async brainModelBudget(modelId, overrides, requestId) {
|
|
4681
|
+
const payload = await this.sendCorrelatedSessionRequest({
|
|
4682
|
+
requestId,
|
|
4683
|
+
message: { type: "brain.model.budget.get.request", modelId, overrides: overrides ?? {} },
|
|
4684
|
+
responseType: "brain.model.budget.get.response",
|
|
4685
|
+
});
|
|
4686
|
+
if (payload.error) {
|
|
4687
|
+
throw new Error(payload.error);
|
|
4688
|
+
}
|
|
4689
|
+
return payload;
|
|
4690
|
+
}
|
|
4691
|
+
/**
|
|
4692
|
+
* Load a model into the running brain. This is not `brainHostStart`, which
|
|
4693
|
+
* restarts the daemon's child process and has no remote equivalent.
|
|
4694
|
+
*/
|
|
4695
|
+
async brainModelLoad(modelId, requestId) {
|
|
4696
|
+
const payload = await this.sendCorrelatedSessionRequest({
|
|
4697
|
+
requestId,
|
|
4698
|
+
message: { type: "brain.model.load.request", modelId },
|
|
4699
|
+
responseType: "brain.model.load.response",
|
|
4700
|
+
});
|
|
4701
|
+
if (payload.error) {
|
|
4702
|
+
throw new Error(payload.error);
|
|
4703
|
+
}
|
|
4704
|
+
return payload;
|
|
4705
|
+
}
|
|
4706
|
+
/** Unload the resident model, leaving the brain up and serving nothing. */
|
|
4707
|
+
async brainModelUnload(requestId) {
|
|
4708
|
+
const payload = await this.sendCorrelatedSessionRequest({
|
|
4709
|
+
requestId,
|
|
4710
|
+
message: { type: "brain.model.unload.request" },
|
|
4711
|
+
responseType: "brain.model.unload.response",
|
|
4712
|
+
});
|
|
4713
|
+
if (payload.error) {
|
|
4714
|
+
throw new Error(payload.error);
|
|
4715
|
+
}
|
|
4716
|
+
return payload.status;
|
|
4717
|
+
}
|
|
4718
|
+
/** Delete a model's files. The brain refuses while that model is loaded. */
|
|
4719
|
+
async brainModelDelete(modelId, requestId) {
|
|
4720
|
+
const payload = await this.sendCorrelatedSessionRequest({
|
|
4721
|
+
requestId,
|
|
4722
|
+
message: { type: "brain.model.delete.request", modelId },
|
|
4723
|
+
responseType: "brain.model.delete.response",
|
|
4724
|
+
});
|
|
4725
|
+
if (payload.error) {
|
|
4726
|
+
throw new Error(payload.error);
|
|
4727
|
+
}
|
|
4728
|
+
return payload;
|
|
4729
|
+
}
|
|
4730
|
+
/** Tail the brain's llama-server log. */
|
|
4731
|
+
async brainLogsTail(limit, requestId) {
|
|
4732
|
+
const payload = await this.sendCorrelatedSessionRequest({
|
|
4733
|
+
requestId,
|
|
4734
|
+
message: { type: "brain.logs.tail.request", limit: limit ?? null },
|
|
4735
|
+
responseType: "brain.logs.tail.response",
|
|
4736
|
+
});
|
|
4737
|
+
if (payload.error) {
|
|
4738
|
+
throw new Error(payload.error);
|
|
4739
|
+
}
|
|
4740
|
+
return payload;
|
|
4741
|
+
}
|
|
4591
4742
|
async getSpeechSettingsOptions(requestId) {
|
|
4592
4743
|
return this.sendNamespacedCorrelatedSessionRequest({
|
|
4593
4744
|
requestId,
|
|
@@ -4733,7 +4884,7 @@ export class DaemonClient {
|
|
|
4733
4884
|
},
|
|
4734
4885
|
});
|
|
4735
4886
|
}
|
|
4736
|
-
/** Daemon-wide "fun stats"
|
|
4887
|
+
/** Daemon-wide "fun stats" - see docs/data-model.md ActivityStatsStore. */
|
|
4737
4888
|
async getActivityStats(options) {
|
|
4738
4889
|
return this.sendNamespacedCorrelatedSessionRequest({
|
|
4739
4890
|
requestId: options?.requestId,
|
|
@@ -4751,7 +4902,7 @@ export class DaemonClient {
|
|
|
4751
4902
|
},
|
|
4752
4903
|
});
|
|
4753
4904
|
}
|
|
4754
|
-
/** Itemized usage ledger
|
|
4905
|
+
/** Itemized usage ledger - the scrollable rows behind the stats tiles (usage-ledger). */
|
|
4755
4906
|
async getUsageLog(options) {
|
|
4756
4907
|
return this.sendNamespacedCorrelatedSessionRequest({
|
|
4757
4908
|
requestId: options?.requestId,
|
|
@@ -5475,7 +5626,7 @@ export class DaemonClient {
|
|
|
5475
5626
|
/**
|
|
5476
5627
|
* Session totals for inbound daemon traffic, including the main-thread time
|
|
5477
5628
|
* spent handling it. Null when runtime metrics are disabled for this client.
|
|
5478
|
-
* Read by the app's resource monitor
|
|
5629
|
+
* Read by the app's resource monitor - the wire is a first-class suspect when
|
|
5479
5630
|
* the UI thread degrades, so it has to be measurable rather than inferred.
|
|
5480
5631
|
*/
|
|
5481
5632
|
getTrafficTotals() {
|
|
@@ -6043,7 +6194,7 @@ export class DaemonClient {
|
|
|
6043
6194
|
/**
|
|
6044
6195
|
* `includeDiscovered` also returns the Scripts the workspace's own project
|
|
6045
6196
|
* files declare (package.json scripts today), each tagged with its `source`.
|
|
6046
|
-
* Gate it on `server_info.features.workspaceScriptDiscovery`
|
|
6197
|
+
* Gate it on `server_info.features.workspaceScriptDiscovery` - an older
|
|
6047
6198
|
* daemon ignores the flag and answers with the otto.json list only.
|
|
6048
6199
|
*/
|
|
6049
6200
|
async listWorkspaceScripts(workspaceId, options) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@otto-code/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Otto client SDK package",
|
|
5
5
|
"license": "AGPL-3.0-or-later",
|
|
6
6
|
"files": [
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"test": "vitest run"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@otto-code/protocol": "0.
|
|
40
|
-
"@otto-code/relay": "0.
|
|
39
|
+
"@otto-code/protocol": "0.8.0",
|
|
40
|
+
"@otto-code/relay": "0.8.0",
|
|
41
41
|
"zod": "^4.4.3"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|