@achasoft/dsh-advanced-sidebar 0.1.0 → 0.3.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/README.md +279 -128
- package/cordis.patch.yml +31 -3
- package/lib/client.js +2803 -466
- package/lib/client.js.map +1 -1
- package/lib/host.js +2071 -418
- package/lib/index.js +6 -2
- package/lib/preview-content-BVUQ5oOR.js +465 -0
- package/lib/remote.js +330 -25
- package/lib/typert.host.js +330 -25
- package/lib/ui-preview.js +352 -0
- package/package.json +8 -2
- package/types/client/ActionMenu.d.ts +16 -1
- package/types/client/LogDownloadDialog.d.ts +24 -0
- package/types/client/contract.d.ts +57 -1
- package/types/client/index.d.ts +4 -2
- package/types/client/locales.d.ts +100 -0
- package/types/client/log-download.d.ts +179 -0
- package/types/client/panels/PreviewPanel.d.ts +20 -15
- package/types/client/panels/preview-file.d.ts +61 -0
- package/types/client/panels/preview-mode.d.ts +67 -0
- package/types/client/panels/preview-scratchpad.d.ts +53 -0
- package/types/client/panels/preview-url.d.ts +17 -0
- package/types/client/panels/shared.d.ts +15 -2
- package/types/client/preview-driver.d.ts +121 -0
- package/types/client/preview-storage.d.ts +43 -0
- package/types/client/preview-types.d.ts +21 -0
- package/types/client/preview-values.d.ts +43 -0
- package/types/host/deletion.d.ts +32 -23
- package/types/host/git.d.ts +94 -8
- package/types/host/index.d.ts +97 -5
- package/types/host/preview-content.d.ts +179 -0
- package/types/host/preview-serve.d.ts +242 -0
- package/types/host/settings-section.d.ts +49 -0
- package/types/host/types.d.ts +341 -0
- package/types/host/ui-bridge.d.ts +197 -0
- package/types/host/ui-preview-tool.d.ts +60 -0
- package/types/index.d.ts +6 -2
- package/types/ui-preview.d.ts +11 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The panel's end of the agent channel: poll for work, execute it against the frame, report back.
|
|
3
|
+
*
|
|
4
|
+
* There is no host-to-browser push in an out-of-tree plugin, so the direction is inverted — the
|
|
5
|
+
* panel asks the Host whether the agent wants anything, and answers with what it found. This module
|
|
6
|
+
* owns that loop, the frame-side execution, and the console capture the agent reads through.
|
|
7
|
+
*
|
|
8
|
+
* Three rules shape everything here:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Only same-origin frames can be inspected.** A page framed from another origin has no
|
|
11
|
+
* reachable `document`, and `contentDocument === null` is the only reliable test for it. Every
|
|
12
|
+
* read and every write refuses such a frame by name, so the model gets "this page is
|
|
13
|
+
* cross-origin" instead of a timeout or an empty DOM.
|
|
14
|
+
* 2. **The agent's window into the frame is bounded.** The DOM walk stops at a node count and a
|
|
15
|
+
* text length, the eval result is serialized with a cycle-safe replacer under a character cap,
|
|
16
|
+
* and the console buffer is a ring. A page that logs per animation frame cannot flood a model's
|
|
17
|
+
* context through this tool.
|
|
18
|
+
* 3. **Nothing here throws across the boundary.** A command that a page rejects — a missing
|
|
19
|
+
* selector, an expression that throws, a frame that navigated mid-command — comes back as a
|
|
20
|
+
* readable sentence, because a rejected promise at this layer would be an unexplained tool
|
|
21
|
+
* timeout.
|
|
22
|
+
* @module @achasoft/dsh-advanced-sidebar/client/preview-driver
|
|
23
|
+
*/
|
|
24
|
+
import type { PreviewControlMessage } from '../host/types.ts';
|
|
25
|
+
import type { PreviewFace } from './preview-types.ts';
|
|
26
|
+
/** The frame as this driver needs to see it. */
|
|
27
|
+
export interface FrameView {
|
|
28
|
+
/** The iframe element, or null while none is mounted. */
|
|
29
|
+
readonly element: HTMLIFrameElement | null;
|
|
30
|
+
/**
|
|
31
|
+
* The frame's document, or null when it is cross-origin or not loaded yet.
|
|
32
|
+
*
|
|
33
|
+
* Read from the element each time rather than cached: a navigation replaces the document, and a
|
|
34
|
+
* cached reference to the old one would answer about the page the operator just left.
|
|
35
|
+
*/
|
|
36
|
+
readonly document: Document | null;
|
|
37
|
+
/** The frame's window, or null when it is cross-origin or not loaded yet. */
|
|
38
|
+
readonly window: Window | null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* What the driver needs from the panel around it.
|
|
42
|
+
*
|
|
43
|
+
* Callbacks rather than a React reference: the loop runs outside the render cycle, and a panel that
|
|
44
|
+
* re-rendered on every tick would re-run its own effects at poll cadence.
|
|
45
|
+
*/
|
|
46
|
+
export interface DriverHooks {
|
|
47
|
+
/** Read the frame as it is right now. */
|
|
48
|
+
frame: () => FrameView;
|
|
49
|
+
/** Apply a mode change the agent asked for. */
|
|
50
|
+
control: (message: PreviewControlMessage) => void;
|
|
51
|
+
/** Force the frame to remount and reload. */
|
|
52
|
+
reload: () => void;
|
|
53
|
+
/** Apply a viewport the agent asked for. */
|
|
54
|
+
resize: (width: number, height: number) => void;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The polling driver. One instance per mounted panel; `stop()` releases it.
|
|
58
|
+
*/
|
|
59
|
+
export declare class PreviewDriver {
|
|
60
|
+
private readonly face;
|
|
61
|
+
private readonly clientId;
|
|
62
|
+
private readonly sessionId;
|
|
63
|
+
private readonly hooks;
|
|
64
|
+
/** Console entries captured since the last report, oldest first. */
|
|
65
|
+
private readonly buffer;
|
|
66
|
+
/** Commands currently executing, so a poll that overlaps the previous one does not double-run. */
|
|
67
|
+
private readonly running;
|
|
68
|
+
private timer;
|
|
69
|
+
private stopped;
|
|
70
|
+
/**
|
|
71
|
+
* @param face - the Remote face the panel was handed.
|
|
72
|
+
* @param clientId - this browser tab's identity, generated once per panel mount.
|
|
73
|
+
* @param sessionId - the session the panel serves.
|
|
74
|
+
* @param hooks - how to read and act on the frame.
|
|
75
|
+
*/
|
|
76
|
+
constructor(face: PreviewFace, clientId: string, sessionId: string, hooks: DriverHooks);
|
|
77
|
+
/**
|
|
78
|
+
* Start polling. Idempotent, so a re-render may call it again freely.
|
|
79
|
+
* @param bind - the panel's current state, refreshed on every poll.
|
|
80
|
+
*/
|
|
81
|
+
start(bind: () => {
|
|
82
|
+
mounted: boolean;
|
|
83
|
+
mode: 'server' | 'file' | 'url' | 'scratchpad';
|
|
84
|
+
filePath?: string | undefined;
|
|
85
|
+
workspacePath?: string | undefined;
|
|
86
|
+
url?: string | undefined;
|
|
87
|
+
inspectable: boolean;
|
|
88
|
+
width: number;
|
|
89
|
+
height: number;
|
|
90
|
+
}): void;
|
|
91
|
+
/** Stop polling. Called when the panel unmounts. */
|
|
92
|
+
stop(): void;
|
|
93
|
+
/**
|
|
94
|
+
* Execute one command and report what it did.
|
|
95
|
+
* @param command - the command.
|
|
96
|
+
*/
|
|
97
|
+
private execute;
|
|
98
|
+
/**
|
|
99
|
+
* Run one command against the frame.
|
|
100
|
+
* @param command - the command.
|
|
101
|
+
* @returns the result, or the sentence explaining the refusal.
|
|
102
|
+
*/
|
|
103
|
+
private run;
|
|
104
|
+
/**
|
|
105
|
+
* Take everything captured since the last drain.
|
|
106
|
+
* @returns the entries, oldest first.
|
|
107
|
+
*/
|
|
108
|
+
private drain;
|
|
109
|
+
/**
|
|
110
|
+
* Wrap the frame's console, once per document.
|
|
111
|
+
*
|
|
112
|
+
* Called from the poll rather than from a load listener because a navigation can complete between
|
|
113
|
+
* two polls, and the check is one property read on the frame's own window.
|
|
114
|
+
*/
|
|
115
|
+
private captureConsole;
|
|
116
|
+
/**
|
|
117
|
+
* Append one captured entry, dropping the oldest past the ring.
|
|
118
|
+
* @param entry - the entry.
|
|
119
|
+
*/
|
|
120
|
+
private push;
|
|
121
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the Preview panel's scratchpad document lives between reloads.
|
|
3
|
+
*
|
|
4
|
+
* A scratchpad is a thought being worked out, not a deliverable, so it is stored in this browser
|
|
5
|
+
* rather than written to the workspace as a file — and per workspace, because two projects'
|
|
6
|
+
* experiments have nothing to do with each other.
|
|
7
|
+
*
|
|
8
|
+
* Split out of the mode component so the rules are testable without a DOM, and so every storage
|
|
9
|
+
* failure is handled in one place: `localStorage` may be absent (a non-browser host), disabled
|
|
10
|
+
* (private modes and hardened settings), or full, and none of those may take the panel down. Each is
|
|
11
|
+
* reported as "nothing saved" or "the write was refused", which the editor renders as a note.
|
|
12
|
+
* @module @achasoft/dsh-plugins/dsh-advanced-sidebar/client/preview-storage
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Largest document this mode will store.
|
|
16
|
+
*
|
|
17
|
+
* A person typing HTML reaches a few kilobytes; a megabyte is a paste of something that belongs in a
|
|
18
|
+
* file. The Host's own route refuses more than its limit, so reading is capped here too rather than
|
|
19
|
+
* discovering the refusal after a round trip.
|
|
20
|
+
*/
|
|
21
|
+
export declare const MAX_SCRATCHPAD_CHARS: number;
|
|
22
|
+
/**
|
|
23
|
+
* The storage key one workspace's scratchpad lives under.
|
|
24
|
+
*
|
|
25
|
+
* The workspace path is the whole identity: two sessions in one directory are editing the same
|
|
26
|
+
* experiment, and a session with no directory shares one global scratchpad rather than losing it.
|
|
27
|
+
* @param workspace - the absolute workspace path, or undefined.
|
|
28
|
+
* @returns the key.
|
|
29
|
+
*/
|
|
30
|
+
export declare function scratchpadKey(workspace: string | undefined): string;
|
|
31
|
+
/**
|
|
32
|
+
* Read one workspace's saved document.
|
|
33
|
+
* @param workspace - the absolute workspace path.
|
|
34
|
+
* @returns the saved document, or undefined when there is none or storage refuses.
|
|
35
|
+
*/
|
|
36
|
+
export declare function readScratchpad(workspace: string | undefined): string | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Write one workspace's document, reporting a refused write instead of throwing.
|
|
39
|
+
* @param workspace - the absolute workspace path.
|
|
40
|
+
* @param text - the document.
|
|
41
|
+
* @returns true when the browser accepted it.
|
|
42
|
+
*/
|
|
43
|
+
export declare function writeScratchpad(workspace: string | undefined, text: string): boolean;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Preview panel's own faces: what its modes are handed, and the narrow slice of the dock's
|
|
3
|
+
* injected face the command driver needs.
|
|
4
|
+
*
|
|
5
|
+
* Split out from the panel component so the driver — which is not a React component and must be
|
|
6
|
+
* testable and readable on its own — does not import the component that imports it.
|
|
7
|
+
* @module @achasoft/dsh-advanced-sidebar/client/preview-types
|
|
8
|
+
*/
|
|
9
|
+
import type { PanelHostInjected } from './contract.ts';
|
|
10
|
+
/** The dock's injected face without the reserved `hooks` compartment, as every panel receives it. */
|
|
11
|
+
export type PanelFace = Omit<PanelHostInjected, 'hooks'>;
|
|
12
|
+
/**
|
|
13
|
+
* The endpoints the command driver calls, and only those.
|
|
14
|
+
*
|
|
15
|
+
* Narrowed deliberately: a driver handed the whole panel face could reach a git write, and the
|
|
16
|
+
* point of the split is that the agent channel's browser end can do exactly three things — ask for
|
|
17
|
+
* work, report a result, and say it left.
|
|
18
|
+
*/
|
|
19
|
+
export type PreviewFace = Pick<PanelFace, 'previewPoll' | 'previewResult' | 'previewRelease'>;
|
|
20
|
+
/** Which mode the Preview panel is showing. */
|
|
21
|
+
export type PreviewMode = 'server' | 'file' | 'url' | 'scratchpad';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How a value that crossed the frame boundary is turned into text a model can read.
|
|
3
|
+
*
|
|
4
|
+
* Everything the agent channel reports — a console argument, an `eval` result, an element — arrived
|
|
5
|
+
* from a page nobody controls. A page can hold a cyclic object, a `BigInt`, a getter that throws, a
|
|
6
|
+
* function, a DOM node, or an `Error`, and `JSON.stringify` refuses three of those outright. Each is
|
|
7
|
+
* projected to something readable rather than failing the command, because "a model asked for
|
|
8
|
+
* something awkward" is an ordinary event and an unexplained tool failure is not.
|
|
9
|
+
*
|
|
10
|
+
* Pure and frame-free, so the whole projection is stated in tests without a document.
|
|
11
|
+
* @module @achasoft/dsh-advanced-sidebar/client/preview-values
|
|
12
|
+
*/
|
|
13
|
+
/** Largest JSON body one `eval` result may produce. */
|
|
14
|
+
export declare const EVAL_CAP: number;
|
|
15
|
+
/**
|
|
16
|
+
* Render one console argument the way a browser's own console would read it.
|
|
17
|
+
* @param value - the argument.
|
|
18
|
+
* @returns a string.
|
|
19
|
+
*/
|
|
20
|
+
export declare function describeValue(value: unknown): string;
|
|
21
|
+
/**
|
|
22
|
+
* Serialize a value with cycles broken and DOM nodes projected to their markup.
|
|
23
|
+
* @param value - the value.
|
|
24
|
+
* @returns the JSON text, or undefined when the value serializes to `undefined`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function stringify(value: unknown): string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Build a replacer that keeps one reference per object, so a cycle serializes instead of throwing.
|
|
29
|
+
*
|
|
30
|
+
* A fresh replacer per call, because the seen-set is per serialization: sharing one across calls
|
|
31
|
+
* would label a value `[circular]` only because an earlier, unrelated call had already seen it.
|
|
32
|
+
* @returns the replacer.
|
|
33
|
+
*/
|
|
34
|
+
export declare function createReplacer(): (key: string, value: unknown) => unknown;
|
|
35
|
+
/**
|
|
36
|
+
* Serialize a value the way a model can read it.
|
|
37
|
+
* @param value - the evaluated value.
|
|
38
|
+
* @returns the JSON text, and why it is not JSON when it is not.
|
|
39
|
+
*/
|
|
40
|
+
export declare function safeJson(value: unknown): {
|
|
41
|
+
text: string;
|
|
42
|
+
note?: string;
|
|
43
|
+
};
|
package/types/host/deletion.d.ts
CHANGED
|
@@ -1,29 +1,46 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Session deletion.
|
|
3
3
|
*
|
|
4
|
-
* No harness capability deletes a session
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* honest about which one it managed:
|
|
4
|
+
* No harness capability deletes a session. Delete is therefore the one thing that does exist — the
|
|
5
|
+
* workspace registry's ARCHIVE, which hides a session while keeping its log and its accounting slot —
|
|
6
|
+
* and it is honest that this is all it did.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* that, and a backend that keeps no per-session artifact (SQLite) reports the archive alone.
|
|
8
|
+
* `deleteMode: 'purge'` asked for more: the backend's own per-session artifact removed as well. On
|
|
9
|
+
* the harness this release targets (`0.1.5-rc.2`) that cannot be done correctly, and so it is not
|
|
10
|
+
* attempted:
|
|
13
11
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
12
|
+
* - The published `SessionPersistence` contract is `create`, `open`, `flush`, `stat` and `list`. It
|
|
13
|
+
* has no removal verb and no way to ask where a session's bytes live; the `supportsRawArtifacts`
|
|
14
|
+
* flag and `locate()` this module used to read were never part of it, so purging was silently
|
|
15
|
+
* impossible while the settings still offered it.
|
|
16
|
+
* - The JSONL backend keeps a session as a DIRECTORY — one immutable file per format generation plus
|
|
17
|
+
* a `session.lock` write lease — behind an in-process cold-log memo, and the workspace registry and
|
|
18
|
+
* the session projection cache index its header. Unlinking files underneath all of that bypasses the
|
|
19
|
+
* lease another process may hold, leaves stale caches answering for a log that is gone, and is the
|
|
20
|
+
* same class of out-of-band edit that produces "torn record" corruption reports.
|
|
21
|
+
*
|
|
22
|
+
* So the capability is reported as unavailable with that reason, the settings card shows the reason
|
|
23
|
+
* and refuses to select `purge`, and a composition that still configures it gets an archive whose
|
|
24
|
+
* result says, every time, why nothing was removed. When the harness grows a supported removal verb,
|
|
25
|
+
* this is the one module to change.
|
|
16
26
|
* @module @achasoft/dsh-advanced-sidebar/host/deletion
|
|
17
27
|
*/
|
|
18
28
|
import type { Context } from '@deepseek-ai/cordis';
|
|
19
29
|
import type { AdvancedSidebarSettings, DeleteSessionRequest, DeleteSessionResult } from './types.ts';
|
|
20
30
|
/** What Delete can do on this Host right now. */
|
|
21
31
|
export interface DeletionCapability {
|
|
22
|
-
/** Whether
|
|
32
|
+
/** Whether a session's durable log can be removed. Always false on this harness; see the module. */
|
|
23
33
|
readonly canPurge: boolean;
|
|
24
34
|
/** Why purging is unavailable, when it is. */
|
|
25
35
|
readonly reason?: string;
|
|
26
36
|
}
|
|
37
|
+
/**
|
|
38
|
+
* Why `purge` is unavailable, in the words the settings card and the Delete result show.
|
|
39
|
+
*
|
|
40
|
+
* One sentence for both, so the reason a person reads before choosing a mode is the reason they read
|
|
41
|
+
* after pressing Delete.
|
|
42
|
+
*/
|
|
43
|
+
export declare const PURGE_UNAVAILABLE_REASON: string;
|
|
27
44
|
/**
|
|
28
45
|
* Commits Delete for the sidebar menu. Stateless apart from the context and settings it reads.
|
|
29
46
|
*/
|
|
@@ -31,27 +48,19 @@ export declare class SessionDeleter {
|
|
|
31
48
|
private readonly ctx;
|
|
32
49
|
private readonly source;
|
|
33
50
|
/**
|
|
34
|
-
* @param ctx - Host context carrying the workspace registry
|
|
51
|
+
* @param ctx - Host context carrying the workspace registry.
|
|
35
52
|
* @param source - reads the current settings section; called per request.
|
|
36
53
|
*/
|
|
37
54
|
constructor(ctx: Context, source: () => AdvancedSidebarSettings);
|
|
38
55
|
/**
|
|
39
56
|
* Report whether the durable log can be removed at all.
|
|
40
|
-
* @returns the capability, with
|
|
57
|
+
* @returns the capability, with the reason purging is impossible.
|
|
41
58
|
*/
|
|
42
59
|
describe(): DeletionCapability;
|
|
43
60
|
/**
|
|
44
|
-
* Hide one session, and
|
|
61
|
+
* Hide one session, and say plainly when a requested purge did not happen.
|
|
45
62
|
* @param request - the session to delete.
|
|
46
|
-
* @param signal - cancellation for the persistence listing.
|
|
47
63
|
* @returns what was actually done, or a classified failure.
|
|
48
64
|
*/
|
|
49
|
-
delete(request: DeleteSessionRequest
|
|
50
|
-
/**
|
|
51
|
-
* Find the backend artifact for one session, or say why it will not be removed.
|
|
52
|
-
* @param sessionId - the session to look up.
|
|
53
|
-
* @param signal - cancellation for the persistence listing.
|
|
54
|
-
* @returns the artifact path, or the reason purging is skipped.
|
|
55
|
-
*/
|
|
56
|
-
private locateArtifact;
|
|
65
|
+
delete(request: DeleteSessionRequest): Promise<DeleteSessionResult>;
|
|
57
66
|
}
|
package/types/host/git.d.ts
CHANGED
|
@@ -19,6 +19,20 @@ import type { AdvancedSidebarSettings, CapabilityState, GitCommitMessageRequest,
|
|
|
19
19
|
* @returns the message, trimmed.
|
|
20
20
|
*/
|
|
21
21
|
export declare function stripFence(text: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* The `-c` overrides that disarm the untrusted filter programs one config listing names.
|
|
24
|
+
*
|
|
25
|
+
* An empty value is git's own "no command" for a filter (`convert.c` runs a driver only when its
|
|
26
|
+
* command is non-empty), so the file is then hashed as its bytes, exactly as with no driver at all.
|
|
27
|
+
* @param listing - `git config --show-scope --name-only --get-regexp` output, one `scope<TAB>key` per
|
|
28
|
+
* line; a line with no scope (an older git) is treated as untrusted.
|
|
29
|
+
* @returns the overrides, or the key git could not be told about safely.
|
|
30
|
+
*/
|
|
31
|
+
export declare function filterOverrides(listing: string): {
|
|
32
|
+
readonly config: readonly string[];
|
|
33
|
+
} | {
|
|
34
|
+
readonly unsafeKey: string;
|
|
35
|
+
};
|
|
22
36
|
/**
|
|
23
37
|
* Reads one workspace's git state. One instance serves every request; the resolved `git` path is
|
|
24
38
|
* cached across calls and dropped whenever a lookup fails, so installing git later needs no restart.
|
|
@@ -91,6 +105,47 @@ export declare class GitReader {
|
|
|
91
105
|
* @returns the push, the reading after it, or a classified failure.
|
|
92
106
|
*/
|
|
93
107
|
push(request: GitPushRequest, signal?: AbortSignal): Promise<GitPushResult>;
|
|
108
|
+
/**
|
|
109
|
+
* The arguments that publish one branch to one remote and record it as the upstream.
|
|
110
|
+
*
|
|
111
|
+
* Both names come from repository state, not from the browser — and repository state is not
|
|
112
|
+
* trusted either. A HEAD of `refs/heads/--receive-pack=/tmp/x` is a valid ref (`check-ref-format`
|
|
113
|
+
* accepts it) that `git status` reports as the branch `--receive-pack=/tmp/x`; handed to
|
|
114
|
+
* `git push` as a bare argument, git parsed it as the option and ran `/tmp/x` as the remote's
|
|
115
|
+
* receive-pack. So three independent things stand in the way:
|
|
116
|
+
*
|
|
117
|
+
* 1. Both names are refused outright when they begin with `-`.
|
|
118
|
+
* 2. The branch must pass `git check-ref-format --branch`, which is git's own branch-name grammar
|
|
119
|
+
* (it rejects a leading `-`, `..`, control characters, `@{`) and must echo back unchanged, so a
|
|
120
|
+
* `@{-1}` shorthand cannot be expanded into some other branch. The remote must make a valid
|
|
121
|
+
* remote-tracking ref, which is how git itself validates a remote name.
|
|
122
|
+
* 3. The push names the refs after `--`, where `git push` (parse-options) stops reading options,
|
|
123
|
+
* and as a fully qualified `refs/heads/<b>:refs/heads/<b>` refspec, which also cannot be read as
|
|
124
|
+
* a shorter ref with the same name on the remote. `--set-upstream` records the same tracking
|
|
125
|
+
* branch it records for the short spelling.
|
|
126
|
+
* @param repository - the resolved repository.
|
|
127
|
+
* @param remote - the remote to publish to, from `git remote`.
|
|
128
|
+
* @param branch - the current branch, from `git status`.
|
|
129
|
+
* @param signal - cancellation for the validation invocations.
|
|
130
|
+
* @returns the push arguments, or the failure to return.
|
|
131
|
+
*/
|
|
132
|
+
private publishArgv;
|
|
133
|
+
/**
|
|
134
|
+
* Whether git accepts a name as a branch name, spelled exactly as given.
|
|
135
|
+
* @param repository - the resolved repository.
|
|
136
|
+
* @param branch - the name, already known not to begin with `-`.
|
|
137
|
+
* @param signal - cancellation for the invocation.
|
|
138
|
+
* @returns true when `check-ref-format --branch` accepts it and echoes it back unchanged.
|
|
139
|
+
*/
|
|
140
|
+
private isValidBranchName;
|
|
141
|
+
/**
|
|
142
|
+
* Whether git accepts a name as a remote name.
|
|
143
|
+
* @param repository - the resolved repository.
|
|
144
|
+
* @param remote - the name, already known not to begin with `-`.
|
|
145
|
+
* @param signal - cancellation for the invocation.
|
|
146
|
+
* @returns true when `refs/remotes/<remote>/HEAD` is a well-formed ref, git's own remote-name rule.
|
|
147
|
+
*/
|
|
148
|
+
private isValidRemoteName;
|
|
94
149
|
/**
|
|
95
150
|
* Ask the deployment's own model to write a commit message for what is staged.
|
|
96
151
|
*
|
|
@@ -104,7 +159,7 @@ export declare class GitReader {
|
|
|
104
159
|
draftCommitMessage(request: GitCommitMessageRequest, signal?: AbortSignal): Promise<GitCommitMessageResult>;
|
|
105
160
|
/**
|
|
106
161
|
* The patch a drafted message describes, bounded so a large change cannot become a large request.
|
|
107
|
-
* @param
|
|
162
|
+
* @param repository - the resolved repository.
|
|
108
163
|
* @param amend - describe the previous commit's content as well as the index.
|
|
109
164
|
* @param signal - cancellation for the invocations.
|
|
110
165
|
* @returns the patch and whether it was cut, or the failure to return.
|
|
@@ -112,14 +167,14 @@ export declare class GitReader {
|
|
|
112
167
|
private stagedPatch;
|
|
113
168
|
/**
|
|
114
169
|
* Whether HEAD has a parent commit.
|
|
115
|
-
* @param
|
|
170
|
+
* @param repository - the resolved repository.
|
|
116
171
|
* @param signal - cancellation for the invocation.
|
|
117
172
|
* @returns true when `HEAD~1` resolves.
|
|
118
173
|
*/
|
|
119
174
|
private hasParent;
|
|
120
175
|
/**
|
|
121
176
|
* The remote an unpublished branch would be published to.
|
|
122
|
-
* @param
|
|
177
|
+
* @param repository - the resolved repository.
|
|
123
178
|
* @param signal - cancellation for the invocation.
|
|
124
179
|
* @returns `origin` when it exists, else the first remote, else undefined.
|
|
125
180
|
*/
|
|
@@ -147,21 +202,21 @@ export declare class GitReader {
|
|
|
147
202
|
private contain;
|
|
148
203
|
/**
|
|
149
204
|
* The author `git commit` would record.
|
|
150
|
-
* @param
|
|
205
|
+
* @param repository - the resolved repository.
|
|
151
206
|
* @param signal - cancellation for the invocation.
|
|
152
207
|
* @returns `Name <email>`, or undefined when git has no identity configured.
|
|
153
208
|
*/
|
|
154
209
|
private author;
|
|
155
210
|
/**
|
|
156
211
|
* Whether the index differs from HEAD.
|
|
157
|
-
* @param
|
|
212
|
+
* @param repository - the resolved repository.
|
|
158
213
|
* @param signal - cancellation for the invocation.
|
|
159
214
|
* @returns true when a commit would record something.
|
|
160
215
|
*/
|
|
161
216
|
private hasStaged;
|
|
162
217
|
/**
|
|
163
218
|
* Report what the panel may do to this repository.
|
|
164
|
-
* @param
|
|
219
|
+
* @param repository - the resolved repository.
|
|
165
220
|
* @param signal - cancellation for the identity lookup.
|
|
166
221
|
* @returns the write capability.
|
|
167
222
|
*/
|
|
@@ -181,10 +236,41 @@ export declare class GitReader {
|
|
|
181
236
|
*/
|
|
182
237
|
private locateRepository;
|
|
183
238
|
/**
|
|
184
|
-
*
|
|
239
|
+
* The overrides that switch off the content filters a repository's own config defines.
|
|
240
|
+
*
|
|
241
|
+
* Listing config runs nothing — `git config` reads files — so this is safe to ask before any
|
|
242
|
+
* reading. `--show-scope` arrived in git 2.26; an older git refuses the flag, and the listing is
|
|
243
|
+
* then repeated without it and every filter it names is treated as untrusted, which can only make
|
|
244
|
+
* a reading more conservative. A listing that fails both ways fails the reading: a status that
|
|
245
|
+
* cannot prove its filters are disarmed is not run.
|
|
246
|
+
* @param root - absolute repository root.
|
|
247
|
+
* @param signal - cancellation for the listing.
|
|
248
|
+
* @returns the `-c` pairs, or the failure to return.
|
|
249
|
+
*/
|
|
250
|
+
private untrustedFilterConfig;
|
|
251
|
+
/**
|
|
252
|
+
* Run one READING: an invocation the panel makes on its own, which must run no program the
|
|
253
|
+
* repository's config names.
|
|
254
|
+
*
|
|
255
|
+
* On top of {@link git}'s own `core.fsmonitor` override it disarms the repository's content
|
|
256
|
+
* filters. Writes (`add`, `restore`, `commit`, `push`) deliberately do not go through here: they are
|
|
257
|
+
* an operator's explicit action, a filter such as LFS is part of what staging correctly means, and a
|
|
258
|
+
* commit's hooks are a real answer the panel reports.
|
|
259
|
+
* @param repository - the resolved repository, carrying its filter overrides.
|
|
260
|
+
* @param args - arguments after the executable and the overrides.
|
|
261
|
+
* @param signal - the caller's cancellation.
|
|
262
|
+
* @param maxBytes - the caller's own output bound, when it has one.
|
|
263
|
+
* @param cwd - directory to run in; the repository root unless the reading is relative to the workspace.
|
|
264
|
+
* @returns the finished command.
|
|
265
|
+
*/
|
|
266
|
+
private read;
|
|
267
|
+
/**
|
|
268
|
+
* Run one git invocation with this plugin's own bounds and {@link INVOCATION_CONFIG}.
|
|
185
269
|
* @param cwd - directory to run in.
|
|
186
|
-
* @param args - arguments after the executable.
|
|
270
|
+
* @param args - arguments after the executable and the invocation config.
|
|
187
271
|
* @param signal - the caller's cancellation.
|
|
272
|
+
* @param maxBytes - the caller's own output bound, when it has one.
|
|
273
|
+
* @param timeoutMs - the caller's own wall-clock bound, when it has one.
|
|
188
274
|
* @returns the finished command.
|
|
189
275
|
*/
|
|
190
276
|
private git;
|
package/types/host/index.d.ts
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
import { Context } from '@deepseek-ai/cordis';
|
|
18
18
|
import z from '@deepseek-ai/schemastery';
|
|
19
19
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
20
|
-
import type {
|
|
20
|
+
import type { PreviewCommandBody } from './ui-preview-tool.ts';
|
|
21
|
+
import type { AdvancedSidebarSettings, AdvancedSidebarView, DeleteSessionRequest, DeleteSessionResult, GitCommitMessageRequest, GitCommitMessageResult, GitCommitRequest, GitCommitResult, GitDiffRequest, GitDiffResult, GitPushRequest, GitPushResult, GitStageRequest, GitStageResult, GitStatusRequest, GitStatusResult, ListEntriesRequest, ListEntriesResult, OpenInRequest, OpenInResult, PreviewCommandResult, PreviewFileInfoRequest, PreviewFileInfoResult, PreviewFileKind, PreviewListRequest, PreviewListResult, PreviewLogsRequest, PreviewLogsResult, PreviewPollRequest, PreviewPollResult, PreviewReleaseRequest, PreviewReleaseResult, PreviewResultAck, PreviewResultRequest, PreviewStartRequest, PreviewStartResult, PreviewStopRequest, PreviewStopResult, ReadFileRequest, ReadFileResult, TaskKillRequest, TaskKillResult, TaskOutputRequest, TaskOutputResult, TerminalAckResult, TerminalCloseRequest, TerminalOpenRequest, TerminalOpenResult, TerminalReadRequest, TerminalReadResult, TerminalSignalRequest, TerminalWriteRequest } from './types.ts';
|
|
21
22
|
export type * from './types.ts';
|
|
22
23
|
export { REVEAL_TARGET_ID } from './open-in.ts';
|
|
23
24
|
/**
|
|
@@ -27,7 +28,7 @@ export { REVEAL_TARGET_ID } from './open-in.ts';
|
|
|
27
28
|
* Host validates, while a Remote namespace is read as `ctx.remote.advancedSidebar.…` and so must be
|
|
28
29
|
* an identifier.
|
|
29
30
|
*/
|
|
30
|
-
export declare const ADVANCED_SIDEBAR_SETTINGS_NAMESPACE:
|
|
31
|
+
export declare const ADVANCED_SIDEBAR_SETTINGS_NAMESPACE: "advanced-sidebar";
|
|
31
32
|
/** Deployment configuration for the advanced sidebar; the `advanced-sidebar` section's own shape. */
|
|
32
33
|
export type Config = AdvancedSidebarSettings;
|
|
33
34
|
declare module '@deepseek-ai/cordis' {
|
|
@@ -47,6 +48,8 @@ export declare class AdvancedSidebarService extends TypertRemoteService {
|
|
|
47
48
|
private readonly tasks;
|
|
48
49
|
private readonly deleter;
|
|
49
50
|
private readonly preview;
|
|
51
|
+
private readonly surface;
|
|
52
|
+
private readonly bindings;
|
|
50
53
|
/**
|
|
51
54
|
* @param ctx - Host context; every capability this service uses is resolved optionally, so a
|
|
52
55
|
* deployment missing one still serves a view that explains which panel is dark and why.
|
|
@@ -173,6 +176,38 @@ export declare class AdvancedSidebarService extends TypertRemoteService {
|
|
|
173
176
|
* @returns the delta and the state, or a classified failure.
|
|
174
177
|
*/
|
|
175
178
|
previewLogs(request: PreviewLogsRequest): Promise<PreviewLogsResult>;
|
|
179
|
+
/**
|
|
180
|
+
* Describe one workspace file for the Preview panel's Files mode.
|
|
181
|
+
*
|
|
182
|
+
* Separate from `readFile`, which returns text for the Files panel's reader: a preview needs the
|
|
183
|
+
* kind, the size, the same-origin URL, and a change token, and it must not pull a 200 MB video
|
|
184
|
+
* through the wire to find out what it is.
|
|
185
|
+
* @param request - the workspace and the file inside it.
|
|
186
|
+
* @param signal - gateway-supplied cancellation for the resolution and metadata reads.
|
|
187
|
+
* @returns the file's kind and frame URL, or a classified failure.
|
|
188
|
+
*/
|
|
189
|
+
previewFileInfo(request: PreviewFileInfoRequest, signal: AbortSignal): Promise<PreviewFileInfoResult>;
|
|
190
|
+
/**
|
|
191
|
+
* Register one Preview panel and take whatever the agent queued for it.
|
|
192
|
+
*
|
|
193
|
+
* This is the polling half of the agent channel: the browser calls it while a preview is mounted,
|
|
194
|
+
* the call is the panel's liveness heartbeat, and its answer carries the commands to execute.
|
|
195
|
+
* @param request - which panel, where it is, and whether a preview is actually rendered.
|
|
196
|
+
* @returns the work to do, or a classified failure.
|
|
197
|
+
*/
|
|
198
|
+
previewPoll(request: PreviewPollRequest): Promise<PreviewPollResult>;
|
|
199
|
+
/**
|
|
200
|
+
* Record what one command did.
|
|
201
|
+
* @param request - the panel, the command id, and the outcome.
|
|
202
|
+
* @returns settlement.
|
|
203
|
+
*/
|
|
204
|
+
previewResult(request: PreviewResultRequest): Promise<PreviewResultAck>;
|
|
205
|
+
/**
|
|
206
|
+
* Say that one panel is gone, so its queued work is dropped and its waits fail now.
|
|
207
|
+
* @param request - the panel that closed.
|
|
208
|
+
* @returns settlement.
|
|
209
|
+
*/
|
|
210
|
+
previewRelease(request: PreviewReleaseRequest): Promise<PreviewReleaseResult>;
|
|
176
211
|
/**
|
|
177
212
|
* Read one file for the Files panel preview.
|
|
178
213
|
* @param request - the file and the workspace it must stay inside.
|
|
@@ -200,11 +235,68 @@ export declare class AdvancedSidebarService extends TypertRemoteService {
|
|
|
200
235
|
*/
|
|
201
236
|
taskOutput(request: TaskOutputRequest): Promise<TaskOutputResult>;
|
|
202
237
|
/**
|
|
203
|
-
* Delete one session: archive it, and
|
|
238
|
+
* Delete one session: archive it, and report plainly that a configured purge did not happen.
|
|
204
239
|
* @param request - the session to delete.
|
|
205
|
-
* @param signal - gateway-supplied cancellation for the persistence listing.
|
|
206
240
|
* @returns what was actually done, or a classified failure.
|
|
207
241
|
*/
|
|
208
|
-
deleteSession(request: DeleteSessionRequest
|
|
242
|
+
deleteSession(request: DeleteSessionRequest): Promise<DeleteSessionResult>;
|
|
243
|
+
/**
|
|
244
|
+
* Queue one command against the session's Preview panel and wait for its answer.
|
|
245
|
+
* @param sessionId - the session whose panel should execute it.
|
|
246
|
+
* @param body - the command, without its id, panel, or deadline.
|
|
247
|
+
* @returns the result, or a sentence explaining why there is none.
|
|
248
|
+
*/
|
|
249
|
+
queueCommand(sessionId: string, body: PreviewCommandBody): Promise<{
|
|
250
|
+
ok: true;
|
|
251
|
+
result: PreviewCommandResult;
|
|
252
|
+
} | {
|
|
253
|
+
ok: false;
|
|
254
|
+
message: string;
|
|
255
|
+
}>;
|
|
256
|
+
/**
|
|
257
|
+
* Point the session's panel at a URL.
|
|
258
|
+
*
|
|
259
|
+
* The panel decides for itself how to frame it — a loopback URL goes through this Host's proxy and
|
|
260
|
+
* becomes inspectable, anything else is framed cross-origin and is not — so the answer says which
|
|
261
|
+
* happened rather than the tool guessing.
|
|
262
|
+
* @param sessionId - the session whose panel should show it.
|
|
263
|
+
* @param url - the absolute `http(s)` URL, already validated by the caller.
|
|
264
|
+
* @param waitMs - how long the panel may take to mount and load.
|
|
265
|
+
* @returns the outcome and what the panel is now framing.
|
|
266
|
+
*/
|
|
267
|
+
openUrl(sessionId: string, url: string, waitMs: number): Promise<{
|
|
268
|
+
ok: true;
|
|
269
|
+
message: string;
|
|
270
|
+
detail: Record<string, unknown>;
|
|
271
|
+
} | {
|
|
272
|
+
ok: false;
|
|
273
|
+
message: string;
|
|
274
|
+
}>;
|
|
275
|
+
/**
|
|
276
|
+
* Point the session's panel at one workspace file.
|
|
277
|
+
* @param request - the session, the workspace, the file, its kind, and the wait budget.
|
|
278
|
+
* @returns the outcome and where the panel is now framed from.
|
|
279
|
+
*/
|
|
280
|
+
openFile(request: {
|
|
281
|
+
sessionId: string;
|
|
282
|
+
workspacePath: string;
|
|
283
|
+
filePath: string;
|
|
284
|
+
kind: PreviewFileKind;
|
|
285
|
+
waitMs: number;
|
|
286
|
+
}): Promise<{
|
|
287
|
+
ok: true;
|
|
288
|
+
message: string;
|
|
289
|
+
detail: Record<string, unknown>;
|
|
290
|
+
} | {
|
|
291
|
+
ok: false;
|
|
292
|
+
message: string;
|
|
293
|
+
}>;
|
|
294
|
+
/**
|
|
295
|
+
* Read one workspace file's preview description, for the tool's own `open` validation.
|
|
296
|
+
* @param request - the workspace and the file.
|
|
297
|
+
* @param signal - cancellation for the reads.
|
|
298
|
+
* @returns the description, or a classified failure.
|
|
299
|
+
*/
|
|
300
|
+
describeFile(request: PreviewFileInfoRequest, signal?: AbortSignal): Promise<PreviewFileInfoResult>;
|
|
209
301
|
}
|
|
210
302
|
export default AdvancedSidebarService;
|