@wrongstack/webui 0.273.1 → 0.274.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.
@@ -13,8 +13,23 @@ interface WSClientMessage {
13
13
  payload?: unknown | undefined;
14
14
  }
15
15
  interface WebUIOptions {
16
+ /** HTTP frontend port. Prefer `httpPort`; `port` is kept for compatibility. */
16
17
  port?: number | undefined;
18
+ /** HTTP frontend port. */
19
+ httpPort?: number | undefined;
17
20
  webuiPort?: number | undefined;
21
+ /** WebSocket backend port. */
22
+ wsPort?: number | undefined;
23
+ /** Host/interface to bind. */
24
+ wsHost?: string | undefined;
25
+ /** Fixed access token/password. Defaults to WEBUI_TOKEN or random per process. */
26
+ accessToken?: string | undefined;
27
+ /** Browser-facing HTTP URL, used in startup output and instance registry. */
28
+ publicUrl?: string | undefined;
29
+ /** Browser-facing WebSocket URL, injected into the frontend for tunnels/proxies. */
30
+ publicWsUrl?: string | undefined;
31
+ /** Force token/password protection even on loopback binds. */
32
+ requireToken?: boolean | undefined;
18
33
  /**
19
34
  * Pre-built backend services. When provided, `startWebUI` skips its
20
35
  * default agent/event-bus/session/store construction and wires the
@@ -103,6 +118,11 @@ interface CreateHttpServerOptions {
103
118
  * is allowed to open a WebSocket back to the local server.
104
119
  */
105
120
  wsPort: number;
121
+ /**
122
+ * Public WebSocket URL injected into the frontend. Use this behind tunnels or
123
+ * reverse proxies where the browser-facing WS URL differs from host:wsPort.
124
+ */
125
+ publicWsUrl?: string | undefined;
106
126
  /**
107
127
  * Path to the global WrongStack root (~/.wrongstack). Used by the
108
128
  * /api/sessions and /api/sessions/:id/agents endpoints to read the
@@ -110,11 +130,13 @@ interface CreateHttpServerOptions {
110
130
  */
111
131
  globalRoot?: string | undefined;
112
132
  /**
113
- * Shared auth token for `/api/*` endpoints. Required for non-loopback
114
- * binds (LAN exposure). Loopback binds accept any local origin without
133
+ * Shared auth token for HTTP and WS access. Required for non-loopback
134
+ * binds (LAN exposure). Loopback binds accept local browser access without
115
135
  * a token (the WS path's loopback-bootstrap policy — see ws-auth.ts).
116
136
  */
117
137
  apiToken?: string | undefined;
138
+ /** Force HTTP token auth even on loopback binds, useful behind public tunnels. */
139
+ requireToken?: boolean | undefined;
118
140
  /**
119
141
  * If true, the `/ws-auth` endpoint exchanges a `?token=` query param (or
120
142
  * `X-WS-Token` header) for an `HttpOnly` auth cookie. The cookie is then
@@ -149,7 +171,7 @@ interface CreateHttpServerOptions {
149
171
  */
150
172
  declare function injectWsPort(html: string, wsPort: number): string;
151
173
  /** Build the Content-Security-Policy value for the given WS port. */
152
- declare function buildCspHeader(wsPort: number): string;
174
+ declare function buildCspHeader(wsPort: number, requestHost?: string | undefined, publicWsUrl?: string | undefined): string;
153
175
  /**
154
176
  * Create the static-file HTTP server. Returns the `http.Server` (not
155
177
  * listening yet) so the caller can attach to a `shutdown()` hook and
@@ -277,7 +299,7 @@ declare function messagePreview(content: unknown): string;
277
299
  /**
278
300
  * Running-instance registry for the standalone WebUI server.
279
301
  *
280
- * Every live `webui` process records itself in a single JSON file under the
302
+ * Every live `wstackui` process records itself in a single JSON file under the
281
303
  * wstack home dir (`~/.wrongstack/webui-instances.json`) so a user running
282
304
  * several instances (one per project, or several per project on different
283
305
  * ports) can see at a glance which ports are open for which path.
@@ -327,7 +349,7 @@ declare function registerInstance(record: WebUIInstanceRecord, baseDir?: string)
327
349
  declare function unregisterInstance(pid: number, baseDir?: string): Promise<void>;
328
350
  /** List live instances, pruning any dead entries encountered. */
329
351
  declare function listInstances(baseDir?: string): Promise<WebUIInstanceRecord[]>;
330
- /** Human-readable table of running instances for `webui --list`. */
352
+ /** Human-readable table of running instances for `wstackui --list`. */
331
353
  declare function formatInstances(instances: WebUIInstanceRecord[]): string;
332
354
 
333
355
  type EternalSubscribe = (fn: (entry: JournalEntry) => void) => () => void;
@@ -374,6 +396,16 @@ declare function errMessage(err: unknown): string;
374
396
  * Shared between standalone and CLI-embedded WebUI servers.
375
397
  */
376
398
  declare function generateAuthToken(): string;
399
+ declare function resolveAuthToken(explicit?: string | undefined): string;
400
+ declare function hostForBrowserUrl(bindHost: string): string;
401
+ declare function buildWebUIAccessUrl(opts: {
402
+ host: string;
403
+ port: number;
404
+ token?: string | undefined;
405
+ protocol?: 'http' | 'https' | undefined;
406
+ publicUrl?: string | undefined;
407
+ }): string;
408
+ declare function envFlag(name: string): boolean;
377
409
 
378
410
  /**
379
411
  * Shared file-operation WebSocket handlers for both the standalone WebUI
@@ -525,7 +557,7 @@ declare function handleMemoryForget(ws: WebSocket, msg: unknown, memoryStore: Me
525
557
 
526
558
  /**
527
559
  * MCP management handlers for the WebUI server (both the standalone
528
- * `wrongstack webui` server and the CLI's embedded `--webui` server).
560
+ * `wstackui` server and the CLI's embedded `--webui` server).
529
561
  *
530
562
  * These are thin WebSocket translators over the shared, surface-agnostic
531
563
  * management core in `@wrongstack/mcp` (`manage.ts`) — the SAME core the REPL
@@ -620,6 +652,7 @@ declare function extractToken(url: string): string | undefined;
620
652
  declare function hostHeaderOk(input: {
621
653
  hostHeader: string | undefined;
622
654
  wsHost: string;
655
+ allowedHostnames?: readonly string[] | undefined;
623
656
  }): boolean;
624
657
  interface VerifyClientInput {
625
658
  /** Browser `Origin` header, or undefined for non-browser clients. */
@@ -637,6 +670,12 @@ interface VerifyClientInput {
637
670
  wsHost: string;
638
671
  /** The server's generated auth token. */
639
672
  expectedToken: string;
673
+ /** Force token auth even for loopback binds, useful behind public tunnels. */
674
+ requireToken?: boolean | undefined;
675
+ /** Extra Host header names allowed on loopback binds, e.g. a tunnel hostname. */
676
+ allowedHostnames?: readonly string[] | undefined;
677
+ /** Allow browser WS URL tokens for explicit public WS URLs where cookies cannot cross hostnames. */
678
+ allowBrowserUrlToken?: boolean | undefined;
640
679
  }
641
680
  /**
642
681
  * Decide whether to accept an incoming WebSocket handshake. Pure mirror of the
@@ -759,19 +798,49 @@ declare class AutoPhaseWebSocketHandler {
759
798
  private store;
760
799
  private clients;
761
800
  private broadcastInterval;
762
- /** Aborts in-flight task agents when the run is stopped. */
801
+ /** Aborts in-flight task agents AND the planning turn when the run is stopped. */
763
802
  private abort;
803
+ /** Set the instant a stop/clear/revert is requested, so a planning turn that
804
+ * resolves afterwards never launches the orchestrator (the abort alone can't
805
+ * cover the window between the LLM call resolving and the orchestrator start). */
806
+ private stopping;
764
807
  /** Optional per-phase git-worktree isolation (lazily created at start). */
765
808
  private worktrees;
809
+ /** Base branch + tip SHA captured at run start so a revert can git-revert the
810
+ * run's squash commits (history-preserving) instead of a destructive reset. */
811
+ private runBase;
766
812
  /** Per-run worker identities so the board can show "who is on what". */
767
813
  private usedNicknames;
768
814
  constructor(agent: Agent, context: Context, logger: Logger, storeDir: string, events?: EventBus | undefined, projectRoot?: string | undefined);
769
815
  addClient(ws: WebSocket): void;
770
816
  handleMessage(msg: AutoPhaseWSMessage): Promise<void>;
771
817
  private handleStart;
818
+ /**
819
+ * Halt the run NOW — at any phase. Sets `stopping` (so a planning turn that
820
+ * resolves afterwards bails), aborts in-flight agents, stops the orchestrator
821
+ * tick, and ends the live broadcast. The board is kept for review; use
822
+ * `autophase.clear` to reset or `autophase.revert` to undo the changes.
823
+ */
824
+ private handleStop;
825
+ /**
826
+ * Stop + wipe: tear down phase worktrees and reset to an empty board so the UI
827
+ * returns to the start screen ("new one"). Does NOT touch already-merged commits
828
+ * on the base branch — that is `autophase.revert`.
829
+ */
830
+ private handleClear;
831
+ /**
832
+ * Stop + undo: remove phase worktrees, then history-preservingly `git revert`
833
+ * every commit this run landed on the base branch (captured `runBase`..HEAD),
834
+ * then reset to an empty board. Refuses (reports a reason) on a dirty tree or a
835
+ * conflicting revert rather than leaving the tree half-reverted.
836
+ */
837
+ private handleRevert;
772
838
  /** Generic fallback phases when the LLM planner produces nothing usable. */
773
839
  private defaultPhases;
774
- /** Plan phases+todos for the goal via the LLM; fall back to defaults on failure. */
840
+ /** Plan phases+todos for the goal via the LLM; fall back to defaults on failure.
841
+ * The caller passes the run's abort signal so a stop during planning cancels
842
+ * the LLM turn (the previous fresh, never-aborted controller made planning
843
+ * uninterruptible). */
775
844
  private planPhases;
776
845
  private executeTaskWithAgent;
777
846
  /** Persist + broadcast after an interactive board mutation. */
@@ -883,6 +952,8 @@ interface SddWizardDeps {
883
952
  defaultModel?: string | undefined;
884
953
  defaultProvider?: string | undefined;
885
954
  fallbackModels?: string[] | undefined;
955
+ /** Per-run worktree-isolation override; undefined → env default. */
956
+ worktrees?: boolean | undefined;
886
957
  }) => Promise<{
887
958
  runId: string;
888
959
  }>;
@@ -937,12 +1008,6 @@ interface SddWizardWiringOptions {
937
1008
  projectDir: string;
938
1009
  };
939
1010
  }
940
- /**
941
- * Build the {@link SddWizardDeps} shared by both webui servers from a single
942
- * per-task `subagentFactory`. The factory drives BOTH the interview agent (an
943
- * isolated turn off the main chat bus) and the real multi-agent run, so each
944
- * server only has to supply the right factory for its process.
945
- */
946
1011
  declare function buildSddWizardDeps(opts: SddWizardWiringOptions): SddWizardDeps;
947
1012
 
948
1013
  /**
@@ -1013,7 +1078,12 @@ declare function handleSkillsExport(ws: WebSocket, ctx: SkillsContext): Promise<
1013
1078
  declare function startWebUI(opts?: WebUIOptions & {
1014
1079
  wsPort?: number | undefined;
1015
1080
  wsHost?: string | undefined;
1081
+ httpPort?: number | undefined;
1082
+ accessToken?: string | undefined;
1083
+ publicUrl?: string | undefined;
1084
+ publicWsUrl?: string | undefined;
1085
+ requireToken?: boolean | undefined;
1016
1086
  open?: boolean | undefined;
1017
1087
  }): Promise<void>;
1018
1088
 
1019
- export { AutoPhaseWebSocketHandler, type BackendServices, type CompletionHandlerOptions, type CompletionItemKind, type CompletionSuggestion, type ConnectedClient, type ContextBreakdown, type CreateHttpServerOptions, type CustomContextMode, type CustomModeStore, type EternalBroadcast, type EternalSubscribe, type EternalSubscription, type KeyOpResult, type LspCompletionSource, type LspCompletionSourceRequest, type MessageTokenEntry, type ProvidersRecord, SddBoardWebSocketHandler, type SddWizardDeps, SddWizardWebSocketHandler, type SddWizardWiringOptions, type ShellOpenRequest, type ShellOpenResult, type ShellOpenTarget, type SkillsContext, SpecsWebSocketHandler, type ToolTokenEntry, type VerifyClientInput, type WSClientMessage, type WSServerMessage, type WebUIInstanceRecord, type WebUIOptions, WorktreeWebSocketHandler, addProvider, broadcast, browserOpenCommand, buildCspHeader, buildSddWizardDeps, createCustomModeStore, createEternalSubscription, createHttpServer, createProviderConfigIO, createToolLspCompletionSource, defaultBaseDir, deleteKey, errMessage, estimateTokens, extractToken, findFreePort, formatInstances, generateAuthToken, handleCompletionRequest, handleFilesList, handleFilesRead, handleFilesTree, handleFilesWrite, handleGitChanges, handleGitDiff, handleGitInfo, handleMcpAdd, handleMcpDisable, handleMcpDiscover, handleMcpEnable, handleMcpList, handleMcpRemove, handleMcpRestart, handleMcpSleep, handleMcpUpdate, handleMcpWake, handleMemoryForget, handleMemoryList, handleMemoryRemember, handleShellOpen, handleSkillsContent, handleSkillsCreate, handleSkillsEdit, handleSkillsExport, handleSkillsInstall, handleSkillsUninstall, handleSkillsUpdate, hostHeaderOk, injectWsPort, isLoopbackBind, isLoopbackHostname, isPortFree, listInstances, loadSavedProviders, maskedKey, messagePreview, messageTokens, normalizeKeys, openBrowser, registerInstance, registryPath, removeProvider, saveProviders, send, sendResult, setActiveKey, startWebUI, stringifyContent, tokenMatches, unregisterInstance, upsertKey, verifyClient, writeKeysBack };
1089
+ export { AutoPhaseWebSocketHandler, type BackendServices, type CompletionHandlerOptions, type CompletionItemKind, type CompletionSuggestion, type ConnectedClient, type ContextBreakdown, type CreateHttpServerOptions, type CustomContextMode, type CustomModeStore, type EternalBroadcast, type EternalSubscribe, type EternalSubscription, type KeyOpResult, type LspCompletionSource, type LspCompletionSourceRequest, type MessageTokenEntry, type ProvidersRecord, SddBoardWebSocketHandler, type SddWizardDeps, SddWizardWebSocketHandler, type SddWizardWiringOptions, type ShellOpenRequest, type ShellOpenResult, type ShellOpenTarget, type SkillsContext, SpecsWebSocketHandler, type ToolTokenEntry, type VerifyClientInput, type WSClientMessage, type WSServerMessage, type WebUIInstanceRecord, type WebUIOptions, WorktreeWebSocketHandler, addProvider, broadcast, browserOpenCommand, buildCspHeader, buildSddWizardDeps, buildWebUIAccessUrl, createCustomModeStore, createEternalSubscription, createHttpServer, createProviderConfigIO, createToolLspCompletionSource, defaultBaseDir, deleteKey, envFlag, errMessage, estimateTokens, extractToken, findFreePort, formatInstances, generateAuthToken, handleCompletionRequest, handleFilesList, handleFilesRead, handleFilesTree, handleFilesWrite, handleGitChanges, handleGitDiff, handleGitInfo, handleMcpAdd, handleMcpDisable, handleMcpDiscover, handleMcpEnable, handleMcpList, handleMcpRemove, handleMcpRestart, handleMcpSleep, handleMcpUpdate, handleMcpWake, handleMemoryForget, handleMemoryList, handleMemoryRemember, handleShellOpen, handleSkillsContent, handleSkillsCreate, handleSkillsEdit, handleSkillsExport, handleSkillsInstall, handleSkillsUninstall, handleSkillsUpdate, hostForBrowserUrl, hostHeaderOk, injectWsPort, isLoopbackBind, isLoopbackHostname, isPortFree, listInstances, loadSavedProviders, maskedKey, messagePreview, messageTokens, normalizeKeys, openBrowser, registerInstance, registryPath, removeProvider, resolveAuthToken, saveProviders, send, sendResult, setActiveKey, startWebUI, stringifyContent, tokenMatches, unregisterInstance, upsertKey, verifyClient, writeKeysBack };