@stigmer/ink 0.5.1 → 1.0.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.
@@ -11,6 +11,16 @@ export interface SessionAppProps {
11
11
  readonly apiKey?: string;
12
12
  /** Dynamic token provider for authentication. */
13
13
  readonly getAccessToken?: TokenProvider;
14
+ /**
15
+ * Default interaction mode for follow-up executions.
16
+ *
17
+ * - `"agent"` (default): full tool access.
18
+ * - `"plan"`: read-only analysis, no file mutations.
19
+ *
20
+ * When set, all follow-up executions in this session use this mode
21
+ * unless overridden by the user.
22
+ */
23
+ readonly mode?: "agent" | "plan";
14
24
  }
15
25
  /**
16
26
  * Self-contained top-level Ink application for viewing and
@@ -38,5 +48,5 @@ export interface SessionAppProps {
38
48
  * );
39
49
  * ```
40
50
  */
41
- export declare function SessionApp({ sessionId, org, baseUrl, apiKey, getAccessToken, }: SessionAppProps): import("react/jsx-runtime").JSX.Element;
51
+ export declare function SessionApp({ sessionId, org, baseUrl, apiKey, getAccessToken, mode, }: SessionAppProps): import("react/jsx-runtime").JSX.Element;
42
52
  //# sourceMappingURL=SessionApp.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SessionApp.d.ts","sourceRoot":"","sources":["../../src/app/SessionApp.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAKlD,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC;CACzC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,GAAG,EACH,OAAO,EACP,MAAM,EACN,cAAc,GACf,EAAE,eAAe,2CAoBjB"}
1
+ {"version":3,"file":"SessionApp.d.ts","sourceRoot":"","sources":["../../src/app/SessionApp.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAKlD,oCAAoC;AACpC,MAAM,WAAW,eAAe;IAC9B,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,8BAA8B;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,yCAAyC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,cAAc,CAAC,EAAE,aAAa,CAAC;IACxC;;;;;;;;OAQG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,GAAG,EACH,OAAO,EACP,MAAM,EACN,cAAc,EACd,IAAI,GACL,EAAE,eAAe,2CAoBjB"}
package/app/SessionApp.js CHANGED
@@ -30,9 +30,9 @@ import { SessionView } from "./SessionView.js";
30
30
  * );
31
31
  * ```
32
32
  */
33
- export function SessionApp({ sessionId, org, baseUrl, apiKey, getAccessToken, }) {
33
+ export function SessionApp({ sessionId, org, baseUrl, apiKey, getAccessToken, mode, }) {
34
34
  const clientConfig = { baseUrl, apiKey, getAccessToken };
35
35
  const client = React.useMemo(() => createNodeClient(clientConfig), [baseUrl, apiKey, getAccessToken]);
36
- return (_jsx(InkStigmerProvider, { client: client, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { paddingLeft: 1, paddingBottom: 1, children: _jsxs(Text, { dimColor: true, children: ["Session ", sessionId, " \u00B7 ", org] }) }), _jsx(SessionView, { sessionId: sessionId, org: org })] }) }));
36
+ return (_jsx(InkStigmerProvider, { client: client, children: _jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { paddingLeft: 1, paddingBottom: 1, children: _jsxs(Text, { dimColor: true, children: ["Session ", sessionId, " \u00B7 ", org] }) }), _jsx(SessionView, { sessionId: sessionId, org: org, mode: mode })] }) }));
37
37
  }
38
38
  //# sourceMappingURL=SessionApp.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SessionApp.js","sourceRoot":"","sources":["../../src/app/SessionApp.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAyB,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAgB/C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,SAAS,EACT,GAAG,EACH,OAAO,EACP,MAAM,EACN,cAAc,GACE;IAChB,MAAM,YAAY,GAAqB,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAE3E,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAC1B,GAAG,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,EACpC,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,CAClC,CAAC;IAEF,OAAO,CACL,KAAC,kBAAkB,IAAC,MAAM,EAAE,MAAM,YAChC,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,KAAC,GAAG,IAAC,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,YACnC,MAAC,IAAI,IAAC,QAAQ,+BACH,SAAS,cAAK,GAAG,IACrB,GACH,EACN,KAAC,WAAW,IAAC,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,GAAI,IAC3C,GACa,CACtB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"SessionApp.js","sourceRoot":"","sources":["../../src/app/SessionApp.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAyB,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AA0B/C;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,SAAS,EACT,GAAG,EACH,OAAO,EACP,MAAM,EACN,cAAc,EACd,IAAI,GACY;IAChB,MAAM,YAAY,GAAqB,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;IAE3E,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAC1B,GAAG,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,EACpC,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,CAAC,CAClC,CAAC;IAEF,OAAO,CACL,KAAC,kBAAkB,IAAC,MAAM,EAAE,MAAM,YAChC,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,aACzB,KAAC,GAAG,IAAC,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,CAAC,YACnC,MAAC,IAAI,IAAC,QAAQ,+BACH,SAAS,cAAK,GAAG,IACrB,GACH,EACN,KAAC,WAAW,IAAC,SAAS,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,GAAI,IACvD,GACa,CACtB,CAAC;AACJ,CAAC"}
@@ -1,9 +1,22 @@
1
+ /** Interaction mode type used for follow-up executions. */
2
+ export type InteractionMode = "agent" | "plan";
1
3
  /** Props for {@link SessionView}. */
2
4
  export interface SessionViewProps {
3
5
  /** Session ID to display and converse in. */
4
6
  readonly sessionId: string;
5
7
  /** Organization slug for creating follow-up executions. */
6
8
  readonly org: string;
9
+ /**
10
+ * Initial interaction mode for follow-up executions.
11
+ *
12
+ * - `"agent"` (default): full tool access.
13
+ * - `"plan"`: read-only analysis, no file mutations.
14
+ *
15
+ * The user can toggle between modes with Ctrl+T during the session.
16
+ * This prop sets the initial value; subsequent toggles are managed
17
+ * as local state.
18
+ */
19
+ readonly mode?: InteractionMode;
7
20
  }
8
21
  /**
9
22
  * Full-featured session conversation view for the terminal.
@@ -28,5 +41,5 @@ export interface SessionViewProps {
28
41
  * );
29
42
  * ```
30
43
  */
31
- export declare function SessionView({ sessionId, org }: SessionViewProps): import("react/jsx-runtime").JSX.Element;
44
+ export declare function SessionView({ sessionId, org, mode }: SessionViewProps): import("react/jsx-runtime").JSX.Element;
32
45
  //# sourceMappingURL=SessionView.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SessionView.d.ts","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"AAUA,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,gBAAgB,2CA0H/D"}
1
+ {"version":3,"file":"SessionView.d.ts","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"AAWA,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,MAAM,CAAC;AAE/C,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,2DAA2D;IAC3D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;;;;OASG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,WAAW,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAuIrE"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState } from "react";
2
+ import { useState, useEffect } from "react";
3
3
  import { Box, Text, useInput } from "ink";
4
4
  import Spinner from "ink-spinner";
5
5
  import { useSessionConversation, resolvedSubject, PENDING_SUBJECT } from "@stigmer/react";
@@ -7,6 +7,7 @@ import { MessageThread } from "../components/MessageThread.js";
7
7
  import { TodoList } from "../components/TodoList.js";
8
8
  import { FollowUpInput } from "../components/FollowUpInput.js";
9
9
  import { UsageWidget } from "../components/UsageWidget.js";
10
+ import { ContextGauge } from "../components/ContextGauge.js";
10
11
  import { ExecutionProgress } from "../components/ExecutionProgress.js";
11
12
  /**
12
13
  * Full-featured session conversation view for the terminal.
@@ -31,13 +32,21 @@ import { ExecutionProgress } from "../components/ExecutionProgress.js";
31
32
  * );
32
33
  * ```
33
34
  */
34
- export function SessionView({ sessionId, org }) {
35
+ export function SessionView({ sessionId, org, mode }) {
35
36
  const conv = useSessionConversation(sessionId, org);
36
37
  const [expandTools, setExpandTools] = useState(false);
38
+ const [activeMode, setActiveMode] = useState(mode ?? "agent");
39
+ useEffect(() => {
40
+ if (mode)
41
+ setActiveMode(mode);
42
+ }, [mode]);
37
43
  useInput((input, key) => {
38
44
  if (key.ctrl && input === "o") {
39
45
  setExpandTools((e) => !e);
40
46
  }
47
+ if (key.ctrl && input === "t") {
48
+ setActiveMode((m) => (m === "plan" ? "agent" : "plan"));
49
+ }
41
50
  });
42
51
  if (conv.isLoading) {
43
52
  return (_jsxs(Box, { gap: 1, paddingLeft: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { children: "Loading session..." })] }));
@@ -50,9 +59,9 @@ export function SessionView({ sessionId, org }) {
50
59
  ...(conv.activeStreamExecution ? [conv.activeStreamExecution] : []),
51
60
  ];
52
61
  const activeTodos = conv.activeStreamExecution?.status?.todos;
53
- const contextInfo = conv.activeStreamExecution?.status?.contextInfo;
54
- const summarizationCount = contextInfo?.summarizationEvents?.length ?? 0;
55
62
  const subject = resolvedSubject(conv.session?.spec?.subject);
56
- return (_jsxs(Box, { flexDirection: "column", children: [subject && subject !== PENDING_SUBJECT && (_jsx(Box, { paddingLeft: 1, marginBottom: 1, children: _jsx(Text, { dimColor: true, bold: true, children: subject }) })), conv.isConnecting && (_jsxs(Box, { gap: 1, paddingLeft: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { dimColor: true, children: "Connecting to stream..." })] })), conv.streamError && (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, marginBottom: 1, children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: "yellow", bold: true, children: "Stream disconnected" }), _jsx(Text, { dimColor: true, children: "\u2014 reconnecting..." })] }), _jsx(Text, { color: "red", dimColor: true, children: conv.streamError.message })] })), conv.activePhase != null && conv.activePhase !== 0 && (_jsx(ExecutionProgress, { phase: conv.activePhase })), _jsx(MessageThread, { executions: conv.completedExecutions, activeStreamExecution: conv.activeStreamExecution, pendingUserMessage: conv.pendingUserMessage, onApprovalSubmit: conv.submitApproval, submittingApprovalIds: conv.submittingApprovalIds, expandToolCalls: expandTools }), summarizationCount > 0 && (_jsx(Box, { paddingLeft: 1, marginTop: 1, children: _jsxs(Text, { dimColor: true, children: ["Context compacted (", summarizationCount, " ", summarizationCount === 1 ? "event" : "events", ", ", Math.round(contextInfo.utilizationPercent), "% utilization)"] }) })), activeTodos && Object.keys(activeTodos).length > 0 && (_jsx(Box, { marginTop: 1, paddingLeft: 1, children: _jsx(TodoList, { todos: activeTodos }) })), conv.approvalError && (_jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { color: "red", children: ["Approval error: ", conv.approvalError.message] }) })), conv.sendError && (_jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { color: "red", children: ["Send error: ", conv.sendError.message] }) })), _jsx(UsageWidget, { executions: allExecutions }), _jsx(FollowUpInput, { onSubmit: (message) => conv.sendFollowUp(message), isSubmitting: conv.isSending, disabled: !conv.canSendFollowUp })] }));
63
+ return (_jsxs(Box, { flexDirection: "column", children: [subject && subject !== PENDING_SUBJECT && (_jsx(Box, { paddingLeft: 1, marginBottom: 1, children: _jsx(Text, { dimColor: true, bold: true, children: subject }) })), conv.isConnecting && (_jsxs(Box, { gap: 1, paddingLeft: 1, children: [_jsx(Text, { color: "cyan", children: _jsx(Spinner, { type: "dots" }) }), _jsx(Text, { dimColor: true, children: "Connecting to stream..." })] })), conv.streamError && (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, marginBottom: 1, children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: "yellow", bold: true, children: "Stream disconnected" }), _jsx(Text, { dimColor: true, children: "\u2014 reconnecting..." })] }), _jsx(Text, { color: "red", dimColor: true, children: conv.streamError.message })] })), conv.activePhase != null && conv.activePhase !== 0 && (_jsx(ExecutionProgress, { phase: conv.activePhase })), _jsx(MessageThread, { executions: conv.completedExecutions, activeStreamExecution: conv.activeStreamExecution, pendingUserMessage: conv.pendingUserMessage, onApprovalSubmit: conv.submitApproval, submittingApprovalIds: conv.submittingApprovalIds, expandToolCalls: expandTools }), activeTodos && Object.keys(activeTodos).length > 0 && (_jsx(Box, { marginTop: 1, paddingLeft: 1, children: _jsx(TodoList, { todos: activeTodos }) })), conv.approvalError && (_jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { color: "red", children: ["Approval error: ", conv.approvalError.message] }) })), conv.sendError && (_jsx(Box, { paddingLeft: 1, children: _jsxs(Text, { color: "red", children: ["Send error: ", conv.sendError.message] }) })), _jsx(UsageWidget, { executions: allExecutions }), _jsx(ContextGauge, { execution: conv.activeStreamExecution ?? null }), conv.canSendFollowUp && (_jsx(Box, { paddingLeft: 1, children: _jsx(Text, { color: activeMode === "plan" ? "yellow" : "cyan", dimColor: true, children: activeMode === "plan"
64
+ ? "Plan mode — read-only analysis, no file mutations"
65
+ : "Agent mode — full tool access" }) })), _jsx(FollowUpInput, { onSubmit: (message) => conv.sendFollowUp(message, { interactionMode: activeMode }), isSubmitting: conv.isSending, disabled: !conv.canSendFollowUp, mode: activeMode })] }));
57
66
  }
58
67
  //# sourceMappingURL=SessionView.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SessionView.js","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SessionView.js","sourceRoot":"","sources":["../../src/app/SessionView.tsx"],"names":[],"mappings":"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"}
@@ -24,6 +24,16 @@ function parseArgs(argv) {
24
24
  case "-k":
25
25
  config.apiKey = args[++i];
26
26
  break;
27
+ case "--mode":
28
+ case "-M": {
29
+ const value = args[++i];
30
+ if (value !== "agent" && value !== "plan") {
31
+ console.error(`Invalid --mode value "${value}": must be "agent" or "plan"`);
32
+ process.exit(1);
33
+ }
34
+ config.mode = value;
35
+ break;
36
+ }
27
37
  case "--help":
28
38
  case "-h":
29
39
  printUsage();
@@ -80,6 +90,7 @@ Options:
80
90
  -o, --org <slug> Organization slug (required)
81
91
  -u, --base-url <url> Stigmer API URL (or STIGMER_BASE_URL env)
82
92
  -k, --api-key <key> API key (or STIGMER_API_KEY env)
93
+ -M, --mode <mode> Interaction mode for follow-ups: "agent" or "plan"
83
94
  -h, --help Show this help message
84
95
 
85
96
  Environment:
@@ -101,7 +112,7 @@ async function main() {
101
112
  const stdin = isTTY
102
113
  ? process.stdin
103
114
  : new Readable({ read() { } });
104
- const instance = render(_jsx(SessionApp, { sessionId: config.sessionId, org: config.org, baseUrl: config.baseUrl, apiKey: config.apiKey }), { stdin, exitOnCtrlC: isTTY, debug: !isTTY });
115
+ const instance = render(_jsx(SessionApp, { sessionId: config.sessionId, org: config.org, baseUrl: config.baseUrl, apiKey: config.apiKey, mode: config.mode }), { stdin, exitOnCtrlC: isTTY, debug: !isTTY });
105
116
  const cleanup = () => {
106
117
  instance.unmount();
107
118
  process.exit(0);
@@ -1 +1 @@
1
- {"version":3,"file":"stigmer-ink.js","sourceRoot":"","sources":["../../src/cli/stigmer-ink.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"stigmer-ink.js","sourceRoot":"","sources":["../../src/cli/stigmer-ink.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
2
+ /** Props for {@link ContextGauge}. */
3
+ export interface ContextGaugeProps {
4
+ /**
5
+ * The execution snapshot from the active stream, or `null`.
6
+ * The gauge extracts `context_info` from the execution status.
7
+ */
8
+ readonly execution: AgentExecution | null;
9
+ }
10
+ /**
11
+ * Terminal-native context window utilization gauge.
12
+ *
13
+ * Renders an ASCII progress bar with health-based coloring, token counts,
14
+ * and summarization event details. Uses the headless
15
+ * {@link useContextWindow} hook from `@stigmer/react`.
16
+ *
17
+ * Returns `null` when `ContextInfo` is absent (e.g., Cursor harness
18
+ * where context is managed externally).
19
+ *
20
+ * @example
21
+ * ```tsx
22
+ * <ContextGauge execution={activeStreamExecution} />
23
+ * ```
24
+ */
25
+ export declare function ContextGauge({ execution }: ContextGaugeProps): import("react/jsx-runtime").JSX.Element | null;
26
+ //# sourceMappingURL=ContextGauge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContextGauge.d.ts","sourceRoot":"","sources":["../../src/components/ContextGauge.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,6DAA6D,CAAC;AAOlG,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,cAAc,GAAG,IAAI,CAAC;CAC3C;AA0BD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,YAAY,CAAC,EAAE,SAAS,EAAE,EAAE,iBAAiB,kDA4C5D"}
@@ -0,0 +1,59 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { useContextWindow, } from "@stigmer/react";
4
+ const BAR_WIDTH = 20;
5
+ const HEALTH_COLORS = {
6
+ healthy: "green",
7
+ warning: "yellow",
8
+ critical: "red",
9
+ };
10
+ const HEALTH_LABELS = {
11
+ warning: "Approaching limit",
12
+ critical: "Near limit",
13
+ };
14
+ function formatCompactTokens(count) {
15
+ if (count >= 1_000_000)
16
+ return `${(count / 1_000_000).toFixed(1)}M`;
17
+ if (count >= 1_000)
18
+ return `${Math.round(count / 1_000)}K`;
19
+ return String(count);
20
+ }
21
+ function formatDuration(ms) {
22
+ if (ms < 1000)
23
+ return `${ms}ms`;
24
+ return `${(ms / 1000).toFixed(1)}s`;
25
+ }
26
+ /**
27
+ * Terminal-native context window utilization gauge.
28
+ *
29
+ * Renders an ASCII progress bar with health-based coloring, token counts,
30
+ * and summarization event details. Uses the headless
31
+ * {@link useContextWindow} hook from `@stigmer/react`.
32
+ *
33
+ * Returns `null` when `ContextInfo` is absent (e.g., Cursor harness
34
+ * where context is managed externally).
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * <ContextGauge execution={activeStreamExecution} />
39
+ * ```
40
+ */
41
+ export function ContextGauge({ execution }) {
42
+ const ctx = useContextWindow(execution);
43
+ if (!ctx.hasContextInfo)
44
+ return null;
45
+ const filled = Math.round((Math.min(ctx.utilizationPercent, 100) / 100) * BAR_WIDTH);
46
+ const empty = BAR_WIDTH - filled;
47
+ const bar = "█".repeat(filled) + "░".repeat(empty);
48
+ const color = HEALTH_COLORS[ctx.health];
49
+ const healthLabel = HEALTH_LABELS[ctx.health];
50
+ const eventCount = ctx.summarizationEvents.length;
51
+ return (_jsxs(Box, { flexDirection: "column", paddingLeft: 1, children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { dimColor: true, children: "Context" }), _jsx(Text, { color: color, children: bar }), _jsxs(Text, { color: color, children: [Math.round(ctx.utilizationPercent), "%"] }), _jsx(Text, { dimColor: true, children: "\u00B7" }), _jsxs(Text, { dimColor: true, children: [formatCompactTokens(ctx.currentTokenCount), " /", " ", formatCompactTokens(ctx.contextWindowLimit), " tokens"] }), healthLabel && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: "\u00B7" }), _jsx(Text, { color: color, children: healthLabel })] })), eventCount > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { dimColor: true, children: "\u00B7" }), _jsxs(Text, { dimColor: true, children: [eventCount, " ", eventCount === 1 ? "compaction" : "compactions"] })] }))] }), eventCount > 0 && (_jsx(LatestEvent, { event: ctx.summarizationEvents[eventCount - 1] }))] }));
52
+ }
53
+ function LatestEvent({ event }) {
54
+ const reduction = Math.round(event.compressionRatio * 100);
55
+ return (_jsx(Box, { paddingLeft: 2, children: _jsxs(Text, { dimColor: true, children: [formatCompactTokens(event.tokensBefore), " \u2192", " ", formatCompactTokens(event.tokensAfter), " tokens (", reduction, "% reduction)", event.model ? ` · ${event.model}` : "", event.durationMs > 0 ? ` · ${formatDuration(event.durationMs)}` : "", event.costUsd > 0
56
+ ? ` · $${event.costUsd < 0.01 ? event.costUsd.toFixed(4) : event.costUsd.toFixed(2)}`
57
+ : ""] }) }));
58
+ }
59
+ //# sourceMappingURL=ContextGauge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContextGauge.js","sourceRoot":"","sources":["../../src/components/ContextGauge.tsx"],"names":[],"mappings":"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"}
@@ -8,6 +8,8 @@ export interface FollowUpInputProps {
8
8
  readonly disabled?: boolean;
9
9
  /** Placeholder text. Default: "Reply..." */
10
10
  readonly placeholder?: string;
11
+ /** Current interaction mode. Shown in the shortcut hint line. */
12
+ readonly mode?: "agent" | "plan";
11
13
  }
12
14
  /**
13
15
  * Terminal text input for sending follow-up messages in a session.
@@ -15,5 +17,5 @@ export interface FollowUpInputProps {
15
17
  * Renders a single-line text input with a submit hint. Press Enter
16
18
  * to submit, Ctrl+C to exit the application.
17
19
  */
18
- export declare function FollowUpInput({ onSubmit, isSubmitting, disabled, placeholder, }: FollowUpInputProps): import("react/jsx-runtime").JSX.Element;
20
+ export declare function FollowUpInput({ onSubmit, isSubmitting, disabled, placeholder, mode, }: FollowUpInputProps): import("react/jsx-runtime").JSX.Element;
19
21
  //# sourceMappingURL=FollowUpInput.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FollowUpInput.d.ts","sourceRoot":"","sources":["../../src/components/FollowUpInput.tsx"],"names":[],"mappings":"AAIA,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,sDAAsD;IACtD,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,4CAA4C;IAC5C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAoB,EACpB,QAAgB,EAChB,WAAwB,GACzB,EAAE,kBAAkB,2CA0CpB"}
1
+ {"version":3,"file":"FollowUpInput.d.ts","sourceRoot":"","sources":["../../src/components/FollowUpInput.tsx"],"names":[],"mappings":"AAIA,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,QAAQ,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,sDAAsD;IACtD,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAChC,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,4CAA4C;IAC5C,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,iEAAiE;IACjE,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAClC;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAoB,EACpB,QAAgB,EAChB,WAAwB,EACxB,IAAI,GACL,EAAE,kBAAkB,2CA0CpB"}
@@ -8,7 +8,7 @@ import TextInput from "ink-text-input";
8
8
  * Renders a single-line text input with a submit hint. Press Enter
9
9
  * to submit, Ctrl+C to exit the application.
10
10
  */
11
- export function FollowUpInput({ onSubmit, isSubmitting = false, disabled = false, placeholder = "Reply...", }) {
11
+ export function FollowUpInput({ onSubmit, isSubmitting = false, disabled = false, placeholder = "Reply...", mode, }) {
12
12
  const [value, setValue] = useState("");
13
13
  const { isRawModeSupported } = useStdin();
14
14
  const isDisabled = disabled || isSubmitting || !isRawModeSupported;
@@ -22,6 +22,6 @@ export function FollowUpInput({ onSubmit, isSubmitting = false, disabled = false
22
22
  if (isDisabled) {
23
23
  return (_jsx(Box, { paddingLeft: 1, paddingTop: 1, children: _jsx(Text, { dimColor: true, children: isSubmitting ? "Sending..." : placeholder }) }));
24
24
  }
25
- return (_jsxs(Box, { paddingLeft: 1, paddingTop: 1, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "\u276F" }), _jsx(TextInput, { value: value, onChange: setValue, onSubmit: handleSubmit, placeholder: placeholder })] }), _jsx(Box, { paddingLeft: 2, children: _jsx(Text, { dimColor: true, children: "Enter to send \u00B7 Ctrl+C to exit" }) })] }));
25
+ return (_jsxs(Box, { paddingLeft: 1, paddingTop: 1, flexDirection: "column", children: [_jsxs(Box, { gap: 1, children: [_jsx(Text, { color: "cyan", bold: true, children: "\u276F" }), _jsx(TextInput, { value: value, onChange: setValue, onSubmit: handleSubmit, placeholder: placeholder })] }), _jsx(Box, { paddingLeft: 2, children: _jsxs(Text, { dimColor: true, children: ["Enter to send \u00B7 Ctrl+T ", mode === "plan" ? "agent" : "plan", " mode \u00B7 Ctrl+C exit"] }) })] }));
26
26
  }
27
27
  //# sourceMappingURL=FollowUpInput.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FollowUpInput.js","sourceRoot":"","sources":["../../src/components/FollowUpInput.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAcvC;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAY,GAAG,KAAK,EACpB,QAAQ,GAAG,KAAK,EAChB,WAAW,GAAG,UAAU,GACL;IACnB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,EAAE,kBAAkB,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAG,QAAQ,IAAI,YAAY,IAAI,CAAC,kBAAkB,CAAC;IAEnE,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClB,QAAQ,CAAC,EAAE,CAAC,CAAC;IACf,CAAC,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CACL,KAAC,GAAG,IAAC,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,YAChC,KAAC,IAAI,IAAC,QAAQ,kBACX,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,GACrC,GACH,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,MAAC,GAAG,IAAC,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,aACxD,MAAC,GAAG,IAAC,GAAG,EAAE,CAAC,aACT,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,IAAI,6BAEhB,EACP,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,YAAY,EACtB,WAAW,EAAE,WAAW,GACxB,IACE,EACN,KAAC,GAAG,IAAC,WAAW,EAAE,CAAC,YACjB,KAAC,IAAI,IAAC,QAAQ,0DAEP,GACH,IACF,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"FollowUpInput.js","sourceRoot":"","sources":["../../src/components/FollowUpInput.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC1C,OAAO,SAAS,MAAM,gBAAgB,CAAC;AAgBvC;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,QAAQ,EACR,YAAY,GAAG,KAAK,EACpB,QAAQ,GAAG,KAAK,EAChB,WAAW,GAAG,UAAU,EACxB,IAAI,GACe;IACnB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,EAAE,kBAAkB,EAAE,GAAG,QAAQ,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAG,QAAQ,IAAI,YAAY,IAAI,CAAC,kBAAkB,CAAC;IAEnE,MAAM,YAAY,GAAG,CAAC,KAAa,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,OAAO;QACrB,QAAQ,CAAC,OAAO,CAAC,CAAC;QAClB,QAAQ,CAAC,EAAE,CAAC,CAAC;IACf,CAAC,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,CACL,KAAC,GAAG,IAAC,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,YAChC,KAAC,IAAI,IAAC,QAAQ,kBACX,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,GACrC,GACH,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,MAAC,GAAG,IAAC,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,aACxD,MAAC,GAAG,IAAC,GAAG,EAAE,CAAC,aACT,KAAC,IAAI,IAAC,KAAK,EAAC,MAAM,EAAC,IAAI,6BAEhB,EACP,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,YAAY,EACtB,WAAW,EAAE,WAAW,GACxB,IACE,EACN,KAAC,GAAG,IAAC,WAAW,EAAE,CAAC,YACjB,MAAC,IAAI,IAAC,QAAQ,mDACY,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,gCACrD,GACH,IACF,CACP,CAAC;AACJ,CAAC"}
package/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export { ApprovalPrompt, type ApprovalPromptProps } from "./components/ApprovalP
11
11
  export { ExecutionProgress, type ExecutionProgressProps } from "./components/ExecutionProgress.js";
12
12
  export { FollowUpInput, type FollowUpInputProps } from "./components/FollowUpInput.js";
13
13
  export { UsageWidget, type UsageWidgetProps } from "./components/UsageWidget.js";
14
- export { SessionView, type SessionViewProps } from "./app/SessionView.js";
14
+ export { ContextGauge, type ContextGaugeProps } from "./components/ContextGauge.js";
15
+ export { SessionView, type SessionViewProps, type InteractionMode } from "./app/SessionView.js";
15
16
  export { SessionApp, type SessionAppProps } from "./app/SessionApp.js";
16
17
  //# sourceMappingURL=index.d.ts.map
package/index.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGjF,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAGjF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,KAAK,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAGjF,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,KAAK,gBAAgB,GACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,KAAK,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AAGpF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC"}
package/index.js CHANGED
@@ -15,6 +15,7 @@ export { ApprovalPrompt } from "./components/ApprovalPrompt.js";
15
15
  export { ExecutionProgress } from "./components/ExecutionProgress.js";
16
16
  export { FollowUpInput } from "./components/FollowUpInput.js";
17
17
  export { UsageWidget } from "./components/UsageWidget.js";
18
+ export { ContextGauge } from "./components/ContextGauge.js";
18
19
  // Composed views
19
20
  export { SessionView } from "./app/SessionView.js";
20
21
  export { SessionApp } from "./app/SessionApp.js";
package/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,kBAAkB,EAAgC,MAAM,eAAe,CAAC;AAEjF,iDAAiD;AACjD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAEpB,MAAM,mBAAmB,CAAC;AAE3B,WAAW;AACX,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,aAAa;AACb,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,cAAc,EAA4B,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AAEjF,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAAyB,MAAM,sBAAsB,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAwB,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,WAAW;AACX,OAAO,EAAE,kBAAkB,EAAgC,MAAM,eAAe,CAAC;AAEjF,iDAAiD;AACjD,OAAO,EACL,gBAAgB,EAChB,mBAAmB,GAEpB,MAAM,mBAAmB,CAAC;AAE3B,WAAW;AACX,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,aAAa;AACb,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,QAAQ,EAAsB,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,cAAc,EAA4B,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAA+B,MAAM,mCAAmC,CAAC;AACnG,OAAO,EAAE,aAAa,EAA2B,MAAM,+BAA+B,CAAC;AACvF,OAAO,EAAE,WAAW,EAAyB,MAAM,6BAA6B,CAAC;AACjF,OAAO,EAAE,YAAY,EAA0B,MAAM,8BAA8B,CAAC;AAEpF,iBAAiB;AACjB,OAAO,EAAE,WAAW,EAA+C,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,UAAU,EAAwB,MAAM,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/ink",
3
- "version": "0.5.1",
3
+ "version": "1.0.0",
4
4
  "description": "Ink (React for terminals) components for rendering Stigmer agent sessions in the terminal",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@connectrpc/connect-node": "^2.1.1",
35
- "@stigmer/react": "0.5.1",
35
+ "@stigmer/react": "1.0.0",
36
36
  "ink-spinner": "^5.0.0",
37
37
  "ink-text-input": "^6.0.0",
38
38
  "marked": "^15.0.7",
@@ -40,8 +40,8 @@
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@bufbuild/protobuf": "^2.0.0",
43
- "@stigmer/protos": "0.5.1",
44
- "@stigmer/sdk": "0.5.1",
43
+ "@stigmer/protos": "1.0.0",
44
+ "@stigmer/sdk": "1.0.0",
45
45
  "ink": "^7.0.0",
46
46
  "react": ">=19.0.0"
47
47
  }
@@ -0,0 +1,176 @@
1
+ import React from "react";
2
+ import { describe, it, expect } from "vitest";
3
+ import { render } from "ink-testing-library";
4
+ import { create } from "@bufbuild/protobuf";
5
+ import {
6
+ AgentExecutionSchema,
7
+ AgentExecutionStatusSchema,
8
+ type AgentExecution,
9
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
10
+ import {
11
+ ContextInfoSchema,
12
+ SummarizationEventSchema,
13
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/context_pb";
14
+ import { ContextGauge } from "../components/ContextGauge.js";
15
+
16
+ function makeExecution(overrides?: {
17
+ currentTokenCount?: number;
18
+ contextWindowLimit?: number;
19
+ utilizationPercent?: number;
20
+ }): AgentExecution {
21
+ const exec = create(AgentExecutionSchema);
22
+ const status = create(AgentExecutionStatusSchema);
23
+ const contextInfo = create(ContextInfoSchema);
24
+
25
+ contextInfo.currentTokenCount = overrides?.currentTokenCount ?? 10_000;
26
+ contextInfo.contextWindowLimit = overrides?.contextWindowLimit ?? 128_000;
27
+ contextInfo.summarizationTriggerThreshold = 115_200;
28
+ contextInfo.summarizationTargetTokens = 102_400;
29
+ contextInfo.summarizationEnabled = true;
30
+ contextInfo.utilizationPercent = overrides?.utilizationPercent ?? 5;
31
+
32
+ status.contextInfo = contextInfo;
33
+ exec.status = status;
34
+ return exec;
35
+ }
36
+
37
+ function addSummarizationEvent(
38
+ exec: AgentExecution,
39
+ overrides?: {
40
+ tokensBefore?: number;
41
+ tokensAfter?: number;
42
+ compressionRatio?: number;
43
+ durationMs?: number;
44
+ model?: string;
45
+ costUsd?: number;
46
+ },
47
+ ): void {
48
+ const event = create(SummarizationEventSchema);
49
+ event.timestamp = "2026-05-17T10:30:00.000Z";
50
+ event.tokensBefore = overrides?.tokensBefore ?? 120_000;
51
+ event.tokensAfter = overrides?.tokensAfter ?? 82_000;
52
+ event.compressionRatio = overrides?.compressionRatio ?? 0.32;
53
+ event.durationMs = overrides?.durationMs ?? 2100;
54
+ event.summarizationModel = overrides?.model ?? "claude-haiku-4";
55
+ event.messagesBefore = 30;
56
+ event.messagesAfter = 10;
57
+ event.summarizationCostUsd = overrides?.costUsd ?? 0.02;
58
+
59
+ exec.status!.contextInfo!.summarizationEvents.push(event);
60
+ }
61
+
62
+ describe("ContextGauge", () => {
63
+ it("renders nothing when execution is null", () => {
64
+ const { lastFrame } = render(<ContextGauge execution={null} />);
65
+ expect(lastFrame()).toBe("");
66
+ });
67
+
68
+ it("renders nothing when contextInfo is absent", () => {
69
+ const exec = create(AgentExecutionSchema);
70
+ exec.status = create(AgentExecutionStatusSchema);
71
+
72
+ const { lastFrame } = render(<ContextGauge execution={exec} />);
73
+ expect(lastFrame()).toBe("");
74
+ });
75
+
76
+ it("renders healthy gauge with green bar and no health label", () => {
77
+ const exec = makeExecution({
78
+ currentTokenCount: 51_200,
79
+ contextWindowLimit: 128_000,
80
+ utilizationPercent: 40,
81
+ });
82
+
83
+ const { lastFrame } = render(<ContextGauge execution={exec} />);
84
+ const output = lastFrame() ?? "";
85
+
86
+ expect(output).toContain("Context");
87
+ expect(output).toContain("40%");
88
+ expect(output).toContain("51K / 128K tokens");
89
+ expect(output).not.toContain("Approaching limit");
90
+ expect(output).not.toContain("Near limit");
91
+ });
92
+
93
+ it("renders warning gauge with health label", () => {
94
+ const exec = makeExecution({
95
+ currentTokenCount: 96_000,
96
+ contextWindowLimit: 128_000,
97
+ utilizationPercent: 75,
98
+ });
99
+
100
+ const { lastFrame } = render(<ContextGauge execution={exec} />);
101
+ const output = lastFrame() ?? "";
102
+
103
+ expect(output).toContain("75%");
104
+ expect(output).toContain("96K / 128K tokens");
105
+ expect(output).toContain("Approaching limit");
106
+ });
107
+
108
+ it("renders critical gauge with health label", () => {
109
+ const exec = makeExecution({
110
+ currentTokenCount: 118_000,
111
+ contextWindowLimit: 128_000,
112
+ utilizationPercent: 92,
113
+ });
114
+
115
+ const { lastFrame } = render(<ContextGauge execution={exec} />);
116
+ const output = lastFrame() ?? "";
117
+
118
+ expect(output).toContain("92%");
119
+ expect(output).toContain("118K / 128K tokens");
120
+ expect(output).toContain("Near limit");
121
+ });
122
+
123
+ it("shows correct token formatting for large counts", () => {
124
+ const exec = makeExecution({
125
+ currentTokenCount: 1_500_000,
126
+ contextWindowLimit: 2_000_000,
127
+ utilizationPercent: 75,
128
+ });
129
+
130
+ const { lastFrame } = render(<ContextGauge execution={exec} />);
131
+ const output = lastFrame() ?? "";
132
+
133
+ expect(output).toContain("1.5M / 2.0M tokens");
134
+ });
135
+
136
+ it("shows summarization count and latest event details", () => {
137
+ const exec = makeExecution({
138
+ currentTokenCount: 82_000,
139
+ contextWindowLimit: 128_000,
140
+ utilizationPercent: 64,
141
+ });
142
+ addSummarizationEvent(exec, {
143
+ tokensBefore: 120_000,
144
+ tokensAfter: 82_000,
145
+ compressionRatio: 0.32,
146
+ durationMs: 2100,
147
+ model: "claude-haiku-4",
148
+ costUsd: 0.02,
149
+ });
150
+
151
+ const { lastFrame } = render(<ContextGauge execution={exec} />);
152
+ const output = lastFrame() ?? "";
153
+
154
+ expect(output).toContain("1 compaction");
155
+ expect(output).toContain("120K → 82K tokens (32% reduction)");
156
+ expect(output).toContain("claude-haiku-4");
157
+ expect(output).toContain("2.1s");
158
+ expect(output).toContain("$0.02");
159
+ });
160
+
161
+ it("shows plural compaction count for multiple events", () => {
162
+ const exec = makeExecution({
163
+ currentTokenCount: 60_000,
164
+ contextWindowLimit: 128_000,
165
+ utilizationPercent: 47,
166
+ });
167
+ addSummarizationEvent(exec, { tokensBefore: 120_000, tokensAfter: 90_000 });
168
+ addSummarizationEvent(exec, { tokensBefore: 110_000, tokensAfter: 70_000 });
169
+ addSummarizationEvent(exec, { tokensBefore: 100_000, tokensAfter: 60_000 });
170
+
171
+ const { lastFrame } = render(<ContextGauge execution={exec} />);
172
+ const output = lastFrame() ?? "";
173
+
174
+ expect(output).toContain("3 compactions");
175
+ });
176
+ });
@@ -17,6 +17,16 @@ export interface SessionAppProps {
17
17
  readonly apiKey?: string;
18
18
  /** Dynamic token provider for authentication. */
19
19
  readonly getAccessToken?: TokenProvider;
20
+ /**
21
+ * Default interaction mode for follow-up executions.
22
+ *
23
+ * - `"agent"` (default): full tool access.
24
+ * - `"plan"`: read-only analysis, no file mutations.
25
+ *
26
+ * When set, all follow-up executions in this session use this mode
27
+ * unless overridden by the user.
28
+ */
29
+ readonly mode?: "agent" | "plan";
20
30
  }
21
31
 
22
32
  /**
@@ -51,6 +61,7 @@ export function SessionApp({
51
61
  baseUrl,
52
62
  apiKey,
53
63
  getAccessToken,
64
+ mode,
54
65
  }: SessionAppProps) {
55
66
  const clientConfig: NodeClientConfig = { baseUrl, apiKey, getAccessToken };
56
67
 
@@ -67,7 +78,7 @@ export function SessionApp({
67
78
  Session {sessionId} · {org}
68
79
  </Text>
69
80
  </Box>
70
- <SessionView sessionId={sessionId} org={org} />
81
+ <SessionView sessionId={sessionId} org={org} mode={mode} />
71
82
  </Box>
72
83
  </InkStigmerProvider>
73
84
  );
@@ -1,4 +1,4 @@
1
- import React, { useState } from "react";
1
+ import React, { useState, useEffect } from "react";
2
2
  import { Box, Text, useInput } from "ink";
3
3
  import Spinner from "ink-spinner";
4
4
  import { useSessionConversation, resolvedSubject, PENDING_SUBJECT } from "@stigmer/react";
@@ -6,14 +6,29 @@ import { MessageThread } from "../components/MessageThread.js";
6
6
  import { TodoList } from "../components/TodoList.js";
7
7
  import { FollowUpInput } from "../components/FollowUpInput.js";
8
8
  import { UsageWidget } from "../components/UsageWidget.js";
9
+ import { ContextGauge } from "../components/ContextGauge.js";
9
10
  import { ExecutionProgress } from "../components/ExecutionProgress.js";
10
11
 
12
+ /** Interaction mode type used for follow-up executions. */
13
+ export type InteractionMode = "agent" | "plan";
14
+
11
15
  /** Props for {@link SessionView}. */
12
16
  export interface SessionViewProps {
13
17
  /** Session ID to display and converse in. */
14
18
  readonly sessionId: string;
15
19
  /** Organization slug for creating follow-up executions. */
16
20
  readonly org: string;
21
+ /**
22
+ * Initial interaction mode for follow-up executions.
23
+ *
24
+ * - `"agent"` (default): full tool access.
25
+ * - `"plan"`: read-only analysis, no file mutations.
26
+ *
27
+ * The user can toggle between modes with Ctrl+T during the session.
28
+ * This prop sets the initial value; subsequent toggles are managed
29
+ * as local state.
30
+ */
31
+ readonly mode?: InteractionMode;
17
32
  }
18
33
 
19
34
  /**
@@ -39,14 +54,22 @@ export interface SessionViewProps {
39
54
  * );
40
55
  * ```
41
56
  */
42
- export function SessionView({ sessionId, org }: SessionViewProps) {
57
+ export function SessionView({ sessionId, org, mode }: SessionViewProps) {
43
58
  const conv = useSessionConversation(sessionId, org);
44
59
  const [expandTools, setExpandTools] = useState(false);
60
+ const [activeMode, setActiveMode] = useState<InteractionMode>(mode ?? "agent");
61
+
62
+ useEffect(() => {
63
+ if (mode) setActiveMode(mode);
64
+ }, [mode]);
45
65
 
46
66
  useInput((input, key) => {
47
67
  if (key.ctrl && input === "o") {
48
68
  setExpandTools((e) => !e);
49
69
  }
70
+ if (key.ctrl && input === "t") {
71
+ setActiveMode((m) => (m === "plan" ? "agent" : "plan"));
72
+ }
50
73
  });
51
74
 
52
75
  if (conv.isLoading) {
@@ -77,8 +100,6 @@ export function SessionView({ sessionId, org }: SessionViewProps) {
77
100
  ];
78
101
 
79
102
  const activeTodos = conv.activeStreamExecution?.status?.todos;
80
- const contextInfo = conv.activeStreamExecution?.status?.contextInfo;
81
- const summarizationCount = contextInfo?.summarizationEvents?.length ?? 0;
82
103
 
83
104
  const subject = resolvedSubject(conv.session?.spec?.subject);
84
105
 
@@ -122,14 +143,6 @@ export function SessionView({ sessionId, org }: SessionViewProps) {
122
143
  expandToolCalls={expandTools}
123
144
  />
124
145
 
125
- {summarizationCount > 0 && (
126
- <Box paddingLeft={1} marginTop={1}>
127
- <Text dimColor>
128
- Context compacted ({summarizationCount} {summarizationCount === 1 ? "event" : "events"}, {Math.round(contextInfo!.utilizationPercent)}% utilization)
129
- </Text>
130
- </Box>
131
- )}
132
-
133
146
  {activeTodos && Object.keys(activeTodos).length > 0 && (
134
147
  <Box marginTop={1} paddingLeft={1}>
135
148
  <TodoList todos={activeTodos} />
@@ -154,10 +167,25 @@ export function SessionView({ sessionId, org }: SessionViewProps) {
154
167
 
155
168
  <UsageWidget executions={allExecutions} />
156
169
 
170
+ <ContextGauge execution={conv.activeStreamExecution ?? null} />
171
+
172
+ {conv.canSendFollowUp && (
173
+ <Box paddingLeft={1}>
174
+ <Text color={activeMode === "plan" ? "yellow" : "cyan"} dimColor>
175
+ {activeMode === "plan"
176
+ ? "Plan mode — read-only analysis, no file mutations"
177
+ : "Agent mode — full tool access"}
178
+ </Text>
179
+ </Box>
180
+ )}
181
+
157
182
  <FollowUpInput
158
- onSubmit={(message) => conv.sendFollowUp(message)}
183
+ onSubmit={(message) =>
184
+ conv.sendFollowUp(message, { interactionMode: activeMode })
185
+ }
159
186
  isSubmitting={conv.isSending}
160
187
  disabled={!conv.canSendFollowUp}
188
+ mode={activeMode}
161
189
  />
162
190
  </Box>
163
191
  );
@@ -10,6 +10,7 @@ interface CliConfig {
10
10
  org: string;
11
11
  baseUrl: string;
12
12
  apiKey?: string;
13
+ mode?: "agent" | "plan";
13
14
  }
14
15
 
15
16
  function parseArgs(argv: string[]): CliConfig | null {
@@ -34,6 +35,16 @@ function parseArgs(argv: string[]): CliConfig | null {
34
35
  case "-k":
35
36
  config.apiKey = args[++i];
36
37
  break;
38
+ case "--mode":
39
+ case "-M": {
40
+ const value = args[++i];
41
+ if (value !== "agent" && value !== "plan") {
42
+ console.error(`Invalid --mode value "${value}": must be "agent" or "plan"`);
43
+ process.exit(1);
44
+ }
45
+ config.mode = value;
46
+ break;
47
+ }
37
48
  case "--help":
38
49
  case "-h":
39
50
  printUsage();
@@ -93,6 +104,7 @@ Options:
93
104
  -o, --org <slug> Organization slug (required)
94
105
  -u, --base-url <url> Stigmer API URL (or STIGMER_BASE_URL env)
95
106
  -k, --api-key <key> API key (or STIGMER_API_KEY env)
107
+ -M, --mode <mode> Interaction mode for follow-ups: "agent" or "plan"
96
108
  -h, --help Show this help message
97
109
 
98
110
  Environment:
@@ -127,6 +139,7 @@ async function main() {
127
139
  org={config.org}
128
140
  baseUrl={config.baseUrl}
129
141
  apiKey={config.apiKey}
142
+ mode={config.mode}
130
143
  />,
131
144
  { stdin, exitOnCtrlC: isTTY, debug: !isTTY },
132
145
  );
@@ -0,0 +1,120 @@
1
+ import React from "react";
2
+ import { Box, Text } from "ink";
3
+ import type { AgentExecution } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
4
+ import {
5
+ useContextWindow,
6
+ type ContextHealth,
7
+ type SummarizationEventView,
8
+ } from "@stigmer/react";
9
+
10
+ /** Props for {@link ContextGauge}. */
11
+ export interface ContextGaugeProps {
12
+ /**
13
+ * The execution snapshot from the active stream, or `null`.
14
+ * The gauge extracts `context_info` from the execution status.
15
+ */
16
+ readonly execution: AgentExecution | null;
17
+ }
18
+
19
+ const BAR_WIDTH = 20;
20
+
21
+ const HEALTH_COLORS: Record<ContextHealth, string> = {
22
+ healthy: "green",
23
+ warning: "yellow",
24
+ critical: "red",
25
+ };
26
+
27
+ const HEALTH_LABELS: Partial<Record<ContextHealth, string>> = {
28
+ warning: "Approaching limit",
29
+ critical: "Near limit",
30
+ };
31
+
32
+ function formatCompactTokens(count: number): string {
33
+ if (count >= 1_000_000) return `${(count / 1_000_000).toFixed(1)}M`;
34
+ if (count >= 1_000) return `${Math.round(count / 1_000)}K`;
35
+ return String(count);
36
+ }
37
+
38
+ function formatDuration(ms: number): string {
39
+ if (ms < 1000) return `${ms}ms`;
40
+ return `${(ms / 1000).toFixed(1)}s`;
41
+ }
42
+
43
+ /**
44
+ * Terminal-native context window utilization gauge.
45
+ *
46
+ * Renders an ASCII progress bar with health-based coloring, token counts,
47
+ * and summarization event details. Uses the headless
48
+ * {@link useContextWindow} hook from `@stigmer/react`.
49
+ *
50
+ * Returns `null` when `ContextInfo` is absent (e.g., Cursor harness
51
+ * where context is managed externally).
52
+ *
53
+ * @example
54
+ * ```tsx
55
+ * <ContextGauge execution={activeStreamExecution} />
56
+ * ```
57
+ */
58
+ export function ContextGauge({ execution }: ContextGaugeProps) {
59
+ const ctx = useContextWindow(execution);
60
+
61
+ if (!ctx.hasContextInfo) return null;
62
+
63
+ const filled = Math.round((Math.min(ctx.utilizationPercent, 100) / 100) * BAR_WIDTH);
64
+ const empty = BAR_WIDTH - filled;
65
+ const bar = "█".repeat(filled) + "░".repeat(empty);
66
+
67
+ const color = HEALTH_COLORS[ctx.health];
68
+ const healthLabel = HEALTH_LABELS[ctx.health];
69
+ const eventCount = ctx.summarizationEvents.length;
70
+
71
+ return (
72
+ <Box flexDirection="column" paddingLeft={1}>
73
+ <Box gap={1}>
74
+ <Text dimColor>Context</Text>
75
+ <Text color={color}>{bar}</Text>
76
+ <Text color={color}>{Math.round(ctx.utilizationPercent)}%</Text>
77
+ <Text dimColor>·</Text>
78
+ <Text dimColor>
79
+ {formatCompactTokens(ctx.currentTokenCount)} /{" "}
80
+ {formatCompactTokens(ctx.contextWindowLimit)} tokens
81
+ </Text>
82
+ {healthLabel && (
83
+ <>
84
+ <Text dimColor>·</Text>
85
+ <Text color={color}>{healthLabel}</Text>
86
+ </>
87
+ )}
88
+ {eventCount > 0 && (
89
+ <>
90
+ <Text dimColor>·</Text>
91
+ <Text dimColor>
92
+ {eventCount} {eventCount === 1 ? "compaction" : "compactions"}
93
+ </Text>
94
+ </>
95
+ )}
96
+ </Box>
97
+ {eventCount > 0 && (
98
+ <LatestEvent event={ctx.summarizationEvents[eventCount - 1]} />
99
+ )}
100
+ </Box>
101
+ );
102
+ }
103
+
104
+ function LatestEvent({ event }: { readonly event: SummarizationEventView }) {
105
+ const reduction = Math.round(event.compressionRatio * 100);
106
+
107
+ return (
108
+ <Box paddingLeft={2}>
109
+ <Text dimColor>
110
+ {formatCompactTokens(event.tokensBefore)} →{" "}
111
+ {formatCompactTokens(event.tokensAfter)} tokens ({reduction}% reduction)
112
+ {event.model ? ` · ${event.model}` : ""}
113
+ {event.durationMs > 0 ? ` · ${formatDuration(event.durationMs)}` : ""}
114
+ {event.costUsd > 0
115
+ ? ` · $${event.costUsd < 0.01 ? event.costUsd.toFixed(4) : event.costUsd.toFixed(2)}`
116
+ : ""}
117
+ </Text>
118
+ </Box>
119
+ );
120
+ }
@@ -12,6 +12,8 @@ export interface FollowUpInputProps {
12
12
  readonly disabled?: boolean;
13
13
  /** Placeholder text. Default: "Reply..." */
14
14
  readonly placeholder?: string;
15
+ /** Current interaction mode. Shown in the shortcut hint line. */
16
+ readonly mode?: "agent" | "plan";
15
17
  }
16
18
 
17
19
  /**
@@ -25,6 +27,7 @@ export function FollowUpInput({
25
27
  isSubmitting = false,
26
28
  disabled = false,
27
29
  placeholder = "Reply...",
30
+ mode,
28
31
  }: FollowUpInputProps) {
29
32
  const [value, setValue] = useState("");
30
33
  const { isRawModeSupported } = useStdin();
@@ -62,7 +65,7 @@ export function FollowUpInput({
62
65
  </Box>
63
66
  <Box paddingLeft={2}>
64
67
  <Text dimColor>
65
- Enter to send · Ctrl+C to exit
68
+ Enter to send · Ctrl+T {mode === "plan" ? "agent" : "plan"} mode · Ctrl+C exit
66
69
  </Text>
67
70
  </Box>
68
71
  </Box>
package/src/index.ts CHANGED
@@ -22,7 +22,8 @@ export { ApprovalPrompt, type ApprovalPromptProps } from "./components/ApprovalP
22
22
  export { ExecutionProgress, type ExecutionProgressProps } from "./components/ExecutionProgress.js";
23
23
  export { FollowUpInput, type FollowUpInputProps } from "./components/FollowUpInput.js";
24
24
  export { UsageWidget, type UsageWidgetProps } from "./components/UsageWidget.js";
25
+ export { ContextGauge, type ContextGaugeProps } from "./components/ContextGauge.js";
25
26
 
26
27
  // Composed views
27
- export { SessionView, type SessionViewProps } from "./app/SessionView.js";
28
+ export { SessionView, type SessionViewProps, type InteractionMode } from "./app/SessionView.js";
28
29
  export { SessionApp, type SessionAppProps } from "./app/SessionApp.js";