jeopi-cli 16.4.1 → 16.4.3

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.
Files changed (125) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/dist/cli.js +3179 -3140
  3. package/dist/types/advisor/config.d.ts +4 -3
  4. package/dist/types/cli/args.d.ts +2 -0
  5. package/dist/types/cli/update-cli.d.ts +4 -1
  6. package/dist/types/cli/usage-error.d.ts +4 -0
  7. package/dist/types/commit/agentic/agent.d.ts +1 -0
  8. package/dist/types/config/model-resolver.d.ts +7 -1
  9. package/dist/types/config/settings-schema.d.ts +3 -3
  10. package/dist/types/eval/py/tool-bridge.d.ts +1 -0
  11. package/dist/types/extensibility/custom-tools/types.d.ts +3 -0
  12. package/dist/types/extensibility/extensions/runner.d.ts +3 -1
  13. package/dist/types/extensibility/extensions/types.d.ts +3 -0
  14. package/dist/types/internal-urls/memory-protocol.d.ts +6 -6
  15. package/dist/types/internal-urls/types.d.ts +7 -0
  16. package/dist/types/irc/bus.d.ts +4 -0
  17. package/dist/types/lsp/deferred-diagnostics.d.ts +11 -0
  18. package/dist/types/modes/components/move-overlay.d.ts +1 -1
  19. package/dist/types/modes/components/plan-review-overlay.d.ts +2 -0
  20. package/dist/types/modes/components/welcome.d.ts +4 -0
  21. package/dist/types/modes/magic-keyword-boundary.d.ts +9 -0
  22. package/dist/types/modes/orchestrate.d.ts +1 -1
  23. package/dist/types/modes/ultrathink.d.ts +1 -1
  24. package/dist/types/modes/workflow.d.ts +1 -1
  25. package/dist/types/session/agent-session.d.ts +5 -0
  26. package/dist/types/session/auth-broker-config.d.ts +2 -2
  27. package/dist/types/tools/bash-skill-urls.d.ts +3 -2
  28. package/dist/types/tools/browser/cmux/cmux-tab.d.ts +3 -1
  29. package/dist/types/tools/browser/cmux/rpc.d.ts +20 -0
  30. package/dist/types/tools/browser/launch.d.ts +1 -0
  31. package/dist/types/tools/browser/run-cancellation.d.ts +17 -2
  32. package/dist/types/tools/browser/run-output.d.ts +25 -0
  33. package/dist/types/tools/browser/tab-worker.d.ts +22 -0
  34. package/dist/types/utils/changelog.d.ts +35 -1
  35. package/package.json +12 -12
  36. package/src/advisor/__tests__/advisor.test.ts +13 -0
  37. package/src/advisor/__tests__/config.test.ts +36 -0
  38. package/src/advisor/config.ts +11 -8
  39. package/src/autolearn/controller.ts +14 -2
  40. package/src/cli/args.ts +12 -0
  41. package/src/cli/flag-tables.ts +21 -7
  42. package/src/cli/update-cli.ts +63 -13
  43. package/src/cli/usage-error.ts +7 -0
  44. package/src/commands/acp.ts +11 -2
  45. package/src/commands/launch.ts +12 -3
  46. package/src/commit/agentic/agent.ts +4 -0
  47. package/src/commit/agentic/index.ts +46 -21
  48. package/src/config/model-resolver.ts +24 -6
  49. package/src/config/settings-schema.ts +3 -3
  50. package/src/edit/index.ts +10 -76
  51. package/src/edit/renderer.ts +13 -10
  52. package/src/eval/__tests__/agent-bridge.test.ts +19 -14
  53. package/src/eval/__tests__/bridge-timeout.test.ts +60 -0
  54. package/src/eval/executor-base.ts +84 -7
  55. package/src/eval/js/shared/rewrite-imports.ts +31 -13
  56. package/src/eval/py/tool-bridge.ts +13 -14
  57. package/src/exec/non-interactive-env.ts +0 -1
  58. package/src/export/ttsr.ts +0 -3
  59. package/src/extensibility/custom-tools/loader.ts +70 -37
  60. package/src/extensibility/custom-tools/types.ts +3 -0
  61. package/src/extensibility/extensions/runner.ts +3 -0
  62. package/src/extensibility/extensions/types.ts +3 -0
  63. package/src/extensibility/plugins/manager.ts +21 -0
  64. package/src/internal-urls/docs-index.generated.txt +1 -1
  65. package/src/internal-urls/memory-protocol.ts +13 -8
  66. package/src/internal-urls/skill-protocol.ts +1 -1
  67. package/src/internal-urls/types.ts +7 -0
  68. package/src/irc/bus.ts +48 -18
  69. package/src/lsp/client.ts +7 -1
  70. package/src/lsp/deferred-diagnostics.ts +66 -0
  71. package/src/main.ts +13 -13
  72. package/src/mcp/tool-bridge.ts +57 -6
  73. package/src/mcp/transports/stdio.test.ts +45 -1
  74. package/src/mcp/transports/stdio.ts +6 -3
  75. package/src/modes/acp/acp-agent.ts +73 -2
  76. package/src/modes/acp/acp-event-mapper.ts +5 -0
  77. package/src/modes/acp/acp-mode.ts +11 -0
  78. package/src/modes/components/__tests__/move-overlay.test.ts +16 -1
  79. package/src/modes/components/advisor-config.ts +15 -7
  80. package/src/modes/components/move-overlay.ts +2 -3
  81. package/src/modes/components/plan-review-overlay.ts +7 -0
  82. package/src/modes/components/tips.txt +1 -1
  83. package/src/modes/components/welcome.ts +13 -14
  84. package/src/modes/controllers/command-controller.ts +8 -10
  85. package/src/modes/controllers/event-controller.ts +17 -30
  86. package/src/modes/controllers/input-controller.ts +9 -6
  87. package/src/modes/controllers/selector-controller.ts +3 -2
  88. package/src/modes/controllers/tan-command-controller.ts +40 -1
  89. package/src/modes/interactive-mode.ts +13 -0
  90. package/src/modes/magic-keyword-boundary.ts +23 -0
  91. package/src/modes/orchestrate.ts +6 -5
  92. package/src/modes/print-mode.ts +9 -0
  93. package/src/modes/ultrathink.ts +6 -5
  94. package/src/modes/workflow.ts +5 -4
  95. package/src/prompts/system/eager-task.md +2 -2
  96. package/src/prompts/system/tan-context-switch.md +17 -0
  97. package/src/prompts/tools/browser.md +5 -5
  98. package/src/sdk.ts +3 -0
  99. package/src/session/agent-session.ts +237 -50
  100. package/src/session/auth-broker-config.ts +4 -4
  101. package/src/session/snapcompact-inline.ts +3 -19
  102. package/src/session/streaming-output.ts +40 -12
  103. package/src/slash-commands/builtin-registry.ts +8 -8
  104. package/src/task/executor.ts +8 -0
  105. package/src/tools/bash-skill-urls.ts +7 -4
  106. package/src/tools/bash.ts +30 -22
  107. package/src/tools/browser/cmux/cmux-tab.ts +49 -50
  108. package/src/tools/browser/cmux/rpc.ts +50 -0
  109. package/src/tools/browser/launch.ts +8 -4
  110. package/src/tools/browser/run-cancellation.ts +44 -5
  111. package/src/tools/browser/run-output.ts +76 -0
  112. package/src/tools/browser/tab-worker.ts +280 -133
  113. package/src/tools/eval-render.ts +16 -14
  114. package/src/tools/glob.ts +20 -6
  115. package/src/tools/grep.ts +1 -0
  116. package/src/tools/image-gen.ts +3 -4
  117. package/src/tools/irc.ts +27 -13
  118. package/src/tools/read.ts +14 -7
  119. package/src/tools/write.ts +22 -5
  120. package/src/tools/yield.ts +29 -1
  121. package/src/utils/changelog.ts +106 -9
  122. package/src/utils/git.ts +0 -1
  123. package/src/utils/title-generator.ts +68 -7
  124. package/src/web/search/index.ts +14 -6
  125. package/src/web/search/providers/perplexity.ts +18 -2
@@ -3,9 +3,10 @@
3
3
  * with an optional `:level` thinking suffix (e.g. `x-ai/grok-code-fast:high`),
4
4
  * resolved exactly like any other model override; `tools` is a subset of
5
5
  * `BUILTIN_TOOL_NAMES` — any built-in name, including mutating tools such as
6
- * `edit`/`write`/`bash` (the advisor is a full agent). Omitted or empty falls
7
- * back to the default `read`/`grep`/`glob` subset. `instructions` is the
8
- * advisor's specialization, appended to the shared baseline.
6
+ * `edit`/`write`/`bash` (the advisor is a full agent). Omitted falls back to
7
+ * the default `read`/`grep`/`glob` subset; an explicit empty list grants no
8
+ * tools. `instructions` is the advisor's specialization, appended to the shared
9
+ * baseline.
9
10
  */
10
11
  export interface AdvisorConfig {
11
12
  name: string;
@@ -76,5 +76,7 @@ export declare function parseArgs(inputArgs: string[], extensionFlags?: Map<stri
76
76
  * process (issue #2459).
77
77
  */
78
78
  export declare function reportUnrecognizedFlags(args: Pick<Args, "unrecognizedFlags">, write?: (text: string) => void): boolean;
79
+ /** Emit a clean CLI usage error without an internal stack trace. */
80
+ export declare function reportCliUsageError(error: unknown, write?: (text: string) => void): boolean;
79
81
  export declare function getExtraHelpText(): string;
80
82
  export declare function printHelp(): void;
@@ -42,11 +42,12 @@ export declare function parseUpdateArgs(args: string[]): {
42
42
  force: boolean;
43
43
  check: boolean;
44
44
  } | undefined;
45
- type UpdateMethod = "brew" | "mise" | "bun" | "binary";
45
+ type UpdateMethod = "brew" | "mise" | "bun" | "npm" | "binary";
46
46
  interface UpdateMethodResolutionOptions {
47
47
  homebrewPrefix?: string;
48
48
  miseBinDirs?: readonly string[];
49
49
  miseDataDir?: string;
50
+ npmBinDir?: string;
50
51
  }
51
52
  export declare function resolveUpdateMethodForTest(jeopiPath: string, bunBinDir: string | undefined, options?: UpdateMethodResolutionOptions): UpdateMethod;
52
53
  /**
@@ -162,6 +163,8 @@ export declare function replaceBinaryForUpdate(options: BinaryReplacementOptions
162
163
  * See #1824.
163
164
  */
164
165
  export declare function buildBunInstallArgs(expectedVersion: string, nativeTag?: string): string[];
166
+ /** Build the npm argv used to update npm-managed global installs. */
167
+ export declare function buildNpmInstallArgs(expectedVersion: string, nativeTag?: string): string[];
165
168
  export declare function buildHomebrewUpdateArgs(force: boolean): string[];
166
169
  export declare function buildMiseUpgradeArgs(): string[];
167
170
  export declare function buildMiseForceInstallArgs(expectedVersion: string): string[];
@@ -0,0 +1,4 @@
1
+ /** Command-line input error that should be rendered without a stack trace. */
2
+ export declare class CliUsageError extends Error {
3
+ constructor(message: string);
4
+ }
@@ -20,6 +20,7 @@ export interface CommitAgentInput {
20
20
  requireChangelog: boolean;
21
21
  diffText?: string;
22
22
  existingChangelogEntries?: ExistingChangelogEntries[];
23
+ onComplete?: (state: CommitAgentState) => Promise<void> | void;
23
24
  }
24
25
  export interface ExistingChangelogEntries {
25
26
  path: string;
@@ -144,6 +144,7 @@ export declare function resolveModelOverride(modelPatterns: string[], modelRegis
144
144
  model?: Model<Api>;
145
145
  thinkingLevel?: ConfiguredThinkingLevel;
146
146
  explicitThinkingLevel: boolean;
147
+ warning?: string;
147
148
  };
148
149
  /**
149
150
  * Resolve a list of override patterns to the first matching model, with an
@@ -156,6 +157,10 @@ export declare function resolveModelOverride(modelPatterns: string[], modelRegis
156
157
  * `modelRoles.task` pointing at an unqualified id whose only available
157
158
  * provider variant has no configured credentials — see #985).
158
159
  *
160
+ * `sessionId` is forwarded to `getApiKey` so that session-sticky OAuth
161
+ * credentials resolve correctly during the pre-flight auth check. Without it,
162
+ * providers with multiple OAuth accounts may return `undefined` even though
163
+ * the credential is usable once the subagent session starts — see #5325.
159
164
  * Keyless-by-design providers (llama.cpp, ollama, lm-studio) advertise the
160
165
  * `kNoAuth` sentinel from `getApiKey` to signal that they do not require
161
166
  * credentials. Those are treated as authenticated here so an explicitly
@@ -166,11 +171,12 @@ export declare function resolveModelOverride(modelPatterns: string[], modelRegis
166
171
  * primary resolution unchanged so the existing error path still surfaces
167
172
  * a meaningful failure downstream.
168
173
  */
169
- export declare function resolveModelOverrideWithAuthFallback(modelPatterns: string[], parentActiveModelPattern: string | undefined, modelRegistry: ModelLookupRegistry & Pick<ModelRegistry, "getApiKey">, settings?: Settings): Promise<{
174
+ export declare function resolveModelOverrideWithAuthFallback(modelPatterns: string[], parentActiveModelPattern: string | undefined, modelRegistry: ModelLookupRegistry & Pick<ModelRegistry, "getApiKey">, settings?: Settings, sessionId?: string): Promise<{
170
175
  model?: Model<Api>;
171
176
  thinkingLevel?: ConfiguredThinkingLevel;
172
177
  explicitThinkingLevel: boolean;
173
178
  authFallbackUsed: boolean;
179
+ warning?: string;
174
180
  }>;
175
181
  /**
176
182
  * Resolve a list of role patterns to the first matching model.
@@ -1262,7 +1262,7 @@ export declare const SETTINGS_SCHEMA: {
1262
1262
  readonly textVerbosity: {
1263
1263
  readonly type: "enum";
1264
1264
  readonly values: readonly ["low", "medium", "high"];
1265
- readonly default: "high";
1265
+ readonly default: "medium";
1266
1266
  readonly ui: {
1267
1267
  readonly tab: "model";
1268
1268
  readonly group: "Sampling";
@@ -1275,11 +1275,11 @@ export declare const SETTINGS_SCHEMA: {
1275
1275
  }, {
1276
1276
  readonly value: "medium";
1277
1277
  readonly label: "Medium";
1278
- readonly description: "Balance brevity and detail";
1278
+ readonly description: "Balance brevity and detail (default)";
1279
1279
  }, {
1280
1280
  readonly value: "high";
1281
1281
  readonly label: "High";
1282
- readonly description: "Prefer detailed responses (default)";
1282
+ readonly description: "Prefer detailed responses";
1283
1283
  }];
1284
1284
  };
1285
1285
  };
@@ -4,6 +4,7 @@ export interface PyToolBridgeEntry {
4
4
  toolSession: ToolSession;
5
5
  signal?: AbortSignal;
6
6
  emitStatus?: (event: JsStatusEvent) => void;
7
+ abortRequested?: () => boolean;
7
8
  }
8
9
  export interface PyToolBridgeInfo {
9
10
  url: string;
@@ -17,6 +17,7 @@ import type { Settings } from "../../config/settings";
17
17
  import type { ExecOptions, ExecResult } from "../../exec/exec";
18
18
  import type { HookUIContext } from "../../extensibility/hooks/types";
19
19
  import type * as PiCodingAgent from "../../index";
20
+ import type { LocalProtocolOptions } from "../../internal-urls/local-protocol";
20
21
  import type { Theme } from "../../modes/theme/theme";
21
22
  import type { ReadonlySessionManager } from "../../session/session-manager";
22
23
  import type { TodoItem } from "../../tools/todo";
@@ -83,6 +84,8 @@ export interface CustomToolContext {
83
84
  settings?: Settings;
84
85
  /** Fetch implementation for outbound HTTP; defaults to global fetch when omitted. */
85
86
  fetch?: FetchImpl;
87
+ /** Calling session's `local://` root mapping for tools that bridge out of the OMP process. */
88
+ localProtocolOptions?: LocalProtocolOptions;
86
89
  /** Whether to auto-approve all destructive tool operations (--auto-approve CLI flag) */
87
90
  autoApprove?: boolean;
88
91
  }
@@ -6,6 +6,7 @@ import type { CredentialDisabledEvent, ImageContent, Model, ProviderResponseMeta
6
6
  import type { KeyId } from "jeopi-tui";
7
7
  import type { ModelRegistry } from "../../config/model-registry";
8
8
  import type { Settings } from "../../config/settings";
9
+ import type { LocalProtocolOptions } from "../../internal-urls/local-protocol";
9
10
  import type { MemoryRuntimeContext } from "../../memory-backend";
10
11
  import type { SessionManager } from "../../session/session-manager";
11
12
  import type { BranchHandler, NavigateTreeHandler, NewSessionHandler } from "../session-handler-types";
@@ -65,7 +66,8 @@ export declare class ExtensionRunner {
65
66
  private readonly sessionManager;
66
67
  private readonly modelRegistry;
67
68
  private readonly settings?;
68
- constructor(extensions: Extension[], runtime: ExtensionRuntime, cwd: string, sessionManager: SessionManager, modelRegistry: ModelRegistry, getMemory?: () => MemoryRuntimeContext | undefined, settings?: Settings | undefined);
69
+ private readonly localProtocolOptions?;
70
+ constructor(extensions: Extension[], runtime: ExtensionRuntime, cwd: string, sessionManager: SessionManager, modelRegistry: ModelRegistry, getMemory?: () => MemoryRuntimeContext | undefined, settings?: Settings | undefined, localProtocolOptions?: LocalProtocolOptions | undefined);
69
71
  initialize(actions: ExtensionActions, contextActions: ExtensionContextActions, commandContextActions?: ExtensionCommandContextActions, uiContext?: ExtensionUIContext): void;
70
72
  /**
71
73
  * Forward a `credential_disabled` event from `AuthStorage` to extension handlers.
@@ -22,6 +22,7 @@ import type { PythonResult } from "../../eval/py/executor";
22
22
  import type { BashResult } from "../../exec/bash-executor";
23
23
  import type { ExecOptions, ExecResult } from "../../exec/exec";
24
24
  import type * as PiCodingAgent from "../../index";
25
+ import type { LocalProtocolOptions } from "../../internal-urls/local-protocol";
25
26
  import type { MemoryRuntimeContext } from "../../memory-backend";
26
27
  import type { CustomEditor } from "../../modes/components/custom-editor";
27
28
  import type { Theme } from "../../modes/theme/theme";
@@ -222,6 +223,8 @@ export interface ExtensionContext {
222
223
  sessionManager: ReadonlySessionManager;
223
224
  /** Model registry for API key resolution */
224
225
  modelRegistry: ModelRegistry;
226
+ /** Calling session's `local://` root mapping for external tool bridges. */
227
+ localProtocolOptions?: LocalProtocolOptions;
225
228
  /** Current model (may be undefined) */
226
229
  model: Model | undefined;
227
230
  /** Read-only model query facade: list / current / resolve / family. */
@@ -1,4 +1,4 @@
1
- import type { InternalResource, InternalUrl, ProtocolHandler, UrlCompletion } from "./types";
1
+ import type { InternalResource, InternalUrl, ProtocolHandler, ResolveContext, UrlCompletion } from "./types";
2
2
  /**
3
3
  * Snapshot of memory roots for every registered session, deduped.
4
4
  * Each session has its own cwd (possibly a worktree), so subagents and main
@@ -12,13 +12,13 @@ export declare function resolveMemoryUrlToPath(url: InternalUrl, memoryRoot: str
12
12
  /**
13
13
  * Protocol handler for memory:// URLs.
14
14
  *
15
- * Walks every active session's memory root. Worktree-based subagents have
16
- * their own root; first one containing the file wins. Parent and subagent
17
- * sharing a cwd see the same file regardless of order.
15
+ * Resolves file-backed roots against the calling session cwd when provided.
16
+ * Contextless callers fall back to the live-session registry for legacy
17
+ * cross-session lookups.
18
18
  */
19
19
  export declare class MemoryProtocolHandler implements ProtocolHandler {
20
20
  readonly scheme = "memory";
21
21
  readonly immutable = true;
22
- resolve(url: InternalUrl): Promise<InternalResource>;
23
- complete(): Promise<UrlCompletion[]>;
22
+ resolve(url: InternalUrl, context?: ResolveContext): Promise<InternalResource>;
23
+ complete(_query?: string, context?: ResolveContext): Promise<UrlCompletion[]>;
24
24
  }
@@ -102,6 +102,13 @@ export interface ResolveContext {
102
102
  * reject directory resources, so they never need the listing.
103
103
  */
104
104
  skipDirectoryListing?: boolean;
105
+ /**
106
+ * When set, handlers that support both a "document" and a "directory" form
107
+ * for the same bare URL (e.g. `skill://name` vs `skill://name/SKILL.md`)
108
+ * resolve to the directory instead of the document. Used by `glob`'s
109
+ * internal-URL find path, which needs a directory to walk.
110
+ */
111
+ pathOnly?: boolean;
105
112
  }
106
113
  /**
107
114
  * Caller context for write operations dispatched to host-owned URI handlers.
@@ -76,6 +76,10 @@ export declare class IrcBus {
76
76
  from?: string;
77
77
  }, timeoutMs: number, signal?: AbortSignal, options?: {
78
78
  drainPending?: boolean;
79
+ liveness?: {
80
+ registry: AgentRegistry;
81
+ senderId: string;
82
+ };
79
83
  }): Promise<IrcMessage | null>;
80
84
  /** Drain (or peek) pending messages for `agentId`. */
81
85
  inbox(agentId: string, opts?: {
@@ -0,0 +1,11 @@
1
+ import type { ToolSession } from "../tools";
2
+ import type { WritethroughDeferredHandle } from "./index";
3
+ /** Coordinates late LSP diagnostics for one mutation tool instance. */
4
+ export declare class DeferredDiagnostics {
5
+ #private;
6
+ private readonly session;
7
+ private readonly deduplicate;
8
+ constructor(session: ToolSession, deduplicate: boolean);
9
+ /** Begin a file mutation and return the handle consumed by LSP writethrough. */
10
+ begin(path: string): WritethroughDeferredHandle;
11
+ }
@@ -18,6 +18,6 @@ export declare class MoveOverlay implements Component, Focusable {
18
18
  get focused(): boolean;
19
19
  set focused(value: boolean);
20
20
  handleInput(data: string): void;
21
- render(_width: number): readonly string[];
21
+ render(width: number): readonly string[];
22
22
  invalidate(): void;
23
23
  }
@@ -25,6 +25,8 @@ export interface PlanReviewOverlayCallbacks {
25
25
  onCancel: () => void;
26
26
  /** Invoked when the external-editor key is pressed (overlay stays open). */
27
27
  onExternalEditor?: () => void;
28
+ /** Invoked with the current full plan text when the copy hotkey is pressed. */
29
+ onCopyPlan?: (content: string) => void | Promise<void>;
28
30
  /** Invoked when the external-editor key edits the active annotation draft. */
29
31
  onAnnotationExternalEditor?: (draft: string, commit: (text: string | null) => void) => void;
30
32
  /** Invoked with the new full plan text after an in-overlay delete/undo. */
@@ -9,6 +9,10 @@ export declare const WELCOME_SESSION_SLOTS = 4;
9
9
  * the box height is constant regardless of how many servers a project has.
10
10
  */
11
11
  export declare const WELCOME_LSP_SLOTS = 4;
12
+ /** Pick a tip from `tips`, biased toward "[NEW]" tips by {@link NEW_TIP_WEIGHT};
13
+ * `r` is a uniform sample in [0, 1). Returns "" when `tips` is empty.
14
+ * Exported for tests. */
15
+ export declare function pickWeightedTip(tips: readonly string[], r: number): string;
12
16
  export declare function renderWelcomeTip(tip: string, boxWidth: number, phase?: number): string[];
13
17
  export interface RecentSession {
14
18
  name: string;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Build a case-sensitive magic-keyword matcher for prose punctuation boundaries.
3
+ *
4
+ * Sentence punctuation and quotes may touch the keyword, but letters, digits,
5
+ * underscores, slashes, backslashes, hyphens, file-extension dots, symbol
6
+ * references (`foo::keyword`), and immediate call parentheses (`keyword()`)
7
+ * keep the occurrence embedded in code rather than prose.
8
+ */
9
+ export declare function magicKeywordRegex(keyword: string, flags?: string): RegExp;
@@ -3,7 +3,7 @@ import { type KeywordHighlighter } from "./gradient-highlight";
3
3
  export declare const ORCHESTRATE_NOTICE: string;
4
4
  /**
5
5
  * Whether `text` contains the standalone keyword "orchestrate" (lowercase,
6
- * whitespace-delimited) in prose — never inside a code block, inline code span,
6
+ * prose-delimited) in prose — never inside a code block, inline code span,
7
7
  * or XML/HTML section.
8
8
  */
9
9
  export declare function containsOrchestrate(text: string): boolean;
@@ -3,7 +3,7 @@ import { type KeywordHighlighter } from "./gradient-highlight";
3
3
  export declare const ULTRATHINK_NOTICE: string;
4
4
  /**
5
5
  * Whether `text` contains the standalone keyword "ultrathink" (lowercase,
6
- * whitespace-delimited) in prose — never inside a code block, inline code span,
6
+ * prose-delimited) in prose — never inside a code block, inline code span,
7
7
  * or XML/HTML section.
8
8
  */
9
9
  export declare function containsUltrathink(text: string): boolean;
@@ -3,7 +3,7 @@ import { type KeywordHighlighter } from "./gradient-highlight";
3
3
  export declare const WORKFLOW_NOTICE: string;
4
4
  /**
5
5
  * Whether `text` contains the standalone keyword "workflowz"
6
- * (lowercase, whitespace-delimited) in prose — never inside a code block, inline
6
+ * (lowercase, prose-delimited) in prose — never inside a code block, inline
7
7
  * code span, or XML/HTML section.
8
8
  */
9
9
  export declare function containsWorkflow(text: string): boolean;
@@ -754,6 +754,11 @@ export declare class AgentSession {
754
754
  * from role configuration (e.g., "anthropic/claude-sonnet-4-5:xhigh").
755
755
  */
756
756
  resolveRoleModelWithThinking(role: string): ResolvedModelRoleValue;
757
+ /**
758
+ * Resolve the explicit thinking suffix that should apply when a temporary
759
+ * picker selects a model already assigned to a configured role.
760
+ */
761
+ resolveTemporaryModelThinkingLevel(model: Model): ConfiguredThinkingLevel | undefined;
757
762
  get promptTemplates(): ReadonlyArray<PromptTemplate>;
758
763
  /** Replace file-based slash commands used for prompt expansion. */
759
764
  setSlashCommands(slashCommands: FileSlashCommand[]): void;
@@ -9,13 +9,13 @@
9
9
  * Precedence (highest first):
10
10
  * 1. `JEOPI_AUTH_BROKER_URL` / `JEOPI_AUTH_BROKER_TOKEN` env vars.
11
11
  * 2. `auth.broker.url` / `auth.broker.token` in `~/.jeopi/agent/config.yml`
12
- * (hidden from the settings UI; `!command` resolution supported).
12
+ * or `~/.jeopi/agent/config.yaml` (hidden from the settings UI; `!command` resolution supported).
13
13
  * 3. Token file `~/.jeopi/auth-broker.token` (paired with URL from env or config).
14
14
  *
15
15
  * Returns null when no broker URL is configured — caller falls back to the
16
16
  * local SQLite store.
17
17
  *
18
- * Reads config.yml directly (instead of going through `Settings.init`) because
18
+ * Reads config YAML directly (instead of going through `Settings.init`) because
19
19
  * `discoverAuthStorage` runs before the settings singleton is initialized in
20
20
  * `runRootCommand`, and we want hand-edited config entries to be honoured at
21
21
  * boot without forcing a startup reorder.
@@ -1,15 +1,16 @@
1
1
  import type { Skill } from "../extensibility/skills";
2
2
  import { type LocalProtocolOptions } from "../internal-urls";
3
- import type { InternalResource } from "../internal-urls/types";
3
+ import type { InternalResource, ResolveContext } from "../internal-urls/types";
4
4
  interface InternalUrlResolver {
5
5
  canHandle(input: string): boolean;
6
- resolve(input: string): Promise<InternalResource>;
6
+ resolve(input: string, context?: ResolveContext): Promise<InternalResource>;
7
7
  }
8
8
  export interface InternalUrlExpansionOptions {
9
9
  skills: readonly Skill[];
10
10
  noEscape?: boolean;
11
11
  internalRouter?: InternalUrlResolver;
12
12
  localOptions?: LocalProtocolOptions;
13
+ cwd?: string;
13
14
  ensureLocalParentDirs?: boolean;
14
15
  }
15
16
  /**
@@ -2,6 +2,7 @@ import { JsRuntime } from "../../../eval/js/shared/runtime";
2
2
  import type { ToolSession } from "../../index";
3
3
  import { type AriaSnapshotOptions } from "../aria/aria-snapshot";
4
4
  import { type ReadableFormat } from "../readable";
5
+ import { RunOutput } from "../run-output";
5
6
  import type { Observation, ReadyInfo, RunResultOk, ScreenshotResult, SessionSnapshot } from "../tab-protocol";
6
7
  import type { CmuxSocketClient } from "./socket-client";
7
8
  interface ScreenshotOptions {
@@ -17,7 +18,7 @@ interface ObserveOptions {
17
18
  }
18
19
  interface RunContext {
19
20
  session: SessionSnapshot;
20
- displays: RunResultOk["displays"];
21
+ output: RunOutput;
21
22
  screenshots: ScreenshotResult[];
22
23
  signal: AbortSignal;
23
24
  timeoutMs: number;
@@ -142,6 +143,7 @@ declare class CmuxElementHandle {
142
143
  click(): Promise<void>;
143
144
  type(text: string): Promise<void>;
144
145
  fill(value: string): Promise<void>;
146
+ press(key: string): Promise<void>;
145
147
  focus(): Promise<void>;
146
148
  hover(): Promise<void>;
147
149
  evaluate<TResult, TArgs extends unknown[]>(fn: (element: unknown, ...args: TArgs) => TResult | Promise<TResult>, ...args: TArgs): Promise<TResult>;
@@ -62,6 +62,26 @@ export interface CmuxGeometry {
62
62
  export declare const GEOMETRY_SCRIPT = "(() => ({ innerWidth: window.innerWidth, innerHeight: window.innerHeight, dpr: window.devicePixelRatio||1, scrollX: window.scrollX, scrollY: window.scrollY, scrollWidth: document.documentElement.scrollWidth, scrollHeight: document.documentElement.scrollHeight }))()";
63
63
  export declare function cmuxSnapshotToObservation(result: CmuxSnapshotResult, viewport: Observation["viewport"], geometry: CmuxGeometry): Observation;
64
64
  export declare function serializeEval(fn: string | ((...args: unknown[]) => unknown), args: unknown[]): string;
65
+ /**
66
+ * Like {@link serializeEval}, but wraps the expression in a page-side
67
+ * try/catch envelope so a throwing script surfaces its message + stack
68
+ * instead of the daemon's opaque `js_error: A JavaScript exception occurred`,
69
+ * and a Promise return (which the daemon cannot serialize) is flagged
70
+ * explicitly rather than failing as "unsupported type".
71
+ *
72
+ * String scripts run through indirect eval to keep global-scope semantics;
73
+ * function sources are already expressions and are invoked directly.
74
+ * `undefined` results come back as `null` (JSON cannot carry `undefined`).
75
+ * Decode with {@link unwrapEvalEnvelope}.
76
+ */
77
+ export declare function serializeEvalWithEnvelope(fn: string | ((...args: unknown[]) => unknown), args: unknown[]): string;
78
+ /**
79
+ * Decode a {@link serializeEvalWithEnvelope} result: rethrow page-side
80
+ * exceptions as rich {@link ToolError}s, reject unserializable Promise
81
+ * returns with an actionable message, and pass through values from daemons
82
+ * that did not run the wrapper.
83
+ */
84
+ export declare function unwrapEvalEnvelope<TResult>(value: unknown, label: string): TResult;
65
85
  export declare function mapWaitUntil(waitUntil: string | undefined): "interactive" | "complete";
66
86
  export interface ResolveCmuxKindOptions {
67
87
  surface?: string;
@@ -13,6 +13,7 @@ export declare const DEFAULT_VIEWPORT: {
13
13
  export declare const BROWSER_PROTOCOL_TIMEOUT_MS = 60000;
14
14
  export declare function loadPuppeteer(): Promise<typeof Puppeteer>;
15
15
  export declare function loadPuppeteerInWorker(safeDir: string): Promise<typeof Puppeteer>;
16
+ export declare function ensureChromiumExecutable(): Promise<string | undefined>;
16
17
  export interface LaunchHeadlessOptions {
17
18
  headless: boolean;
18
19
  viewport?: {
@@ -1,4 +1,19 @@
1
- /** Sleeps inside evaluated browser code while honoring the owning run's cancellation signal. */
2
- export declare function waitForBrowserRun(ms: number, signal: AbortSignal): Promise<void>;
1
+ /** Options for the predicate form of the run-scoped `wait()` helper. */
2
+ export interface WaitPredicateOptions {
3
+ /** Max time to poll before failing, in ms (default 30_000). */
4
+ timeout?: number;
5
+ /** Poll interval in ms (default 100, floor 10). */
6
+ interval?: number;
7
+ }
8
+ /**
9
+ * Run-scoped `wait()` helper for evaluated browser code, honoring the owning run's
10
+ * cancellation signal.
11
+ *
12
+ * - `wait(ms)` sleeps for `ms` milliseconds.
13
+ * - `wait(fn, { timeout?, interval? })` polls `fn` (sync or async) until it returns a
14
+ * truthy value and resolves with that value; throws a named `ToolError` on timeout
15
+ * instead of stalling into the whole-cell deadline. Predicate errors propagate.
16
+ */
17
+ export declare function waitForBrowserRun(msOrPredicate: number | (() => unknown), signal: AbortSignal, opts?: WaitPredicateOptions): Promise<unknown>;
3
18
  /** Binds a long-lived browser facade to one evaluated run's abort signal. */
4
19
  export declare function bindBrowserRunFacade<T extends object>(target: T, signal: AbortSignal): T;
@@ -0,0 +1,25 @@
1
+ import type { ImageContent, TextContent } from "jeopi-ai";
2
+ import type { JsDisplayOutput } from "../../eval/js/shared/types";
3
+ /**
4
+ * Accumulates a browser run's result entries: explicit `display()` payloads,
5
+ * screenshot captions/images, and buffered stream text (`console.*`, `print`,
6
+ * `display()` of strings/primitives — `JsRuntime.displayValue` emits those via
7
+ * `onText`). Stream text is buffered and flushed as one entry before the next
8
+ * display/screenshot (and on `finish()`) so it reaches the tool result in
9
+ * order instead of vanishing into the debug log.
10
+ */
11
+ export declare class RunOutput {
12
+ #private;
13
+ /** Buffer a stream-text chunk; it joins the entries at the next push or on finish(). */
14
+ pushText(chunk: string): void;
15
+ /** Append a `display()` payload (image/json/status), flushing buffered text first. */
16
+ pushDisplay(output: JsDisplayOutput): void;
17
+ /** Append a pre-built entry (e.g. a screenshot caption/image), flushing buffered text first. */
18
+ push(entry: TextContent | ImageContent): void;
19
+ /** Flush any remaining stream text and return the ordered entries. */
20
+ finish(): Array<TextContent | ImageContent>;
21
+ }
22
+ /** JSON.stringify that never throws (cycles/BigInt → String(value)). */
23
+ export declare function safeJsonStringify(value: unknown): string;
24
+ /** Pass a return value across the run boundary: structured-cloneable as-is, else JSON round-trip, else String. */
25
+ export declare function cloneSafe(value: unknown): unknown;
@@ -1,6 +1,12 @@
1
1
  import type { HTMLElement } from "linkedom";
2
2
  import type { ElementHandle, ImageFormat } from "puppeteer-core";
3
3
  import type { Transport } from "./tab-protocol";
4
+ declare module "puppeteer-core" {
5
+ interface Frame {
6
+ /** Puppeteer's main JavaScript realm, retained by our pinned runtime patch. */
7
+ mainRealm(): Realm;
8
+ }
9
+ }
4
10
  declare global {
5
11
  interface Element extends HTMLElement {
6
12
  }
@@ -37,6 +43,22 @@ interface ScreenshotOptions {
37
43
  silent?: boolean;
38
44
  }
39
45
  export declare function normalizeSelector(selector: string): string;
46
+ /** ElementHandle enriched with the `fill()` the tool docs promise on handles from `tab.id()`/`tab.ref()`/`tab.waitFor()`. */
47
+ export type ActionableHandle = ElementHandle & {
48
+ fill(value: string): Promise<void>;
49
+ };
50
+ /**
51
+ * Attach `fill()` to a puppeteer ElementHandle before handing it to user code.
52
+ * Puppeteer handles expose `type()` but no `fill()`; the semantics mirror the
53
+ * selector-based `tab.fill()`: focus, clear any existing value, then type.
54
+ */
55
+ export declare function toActionableHandle(handle: ElementHandle): ActionableHandle;
56
+ /**
57
+ * Hint appended to a selector op's fail-fast timeout, given the selector's current
58
+ * match count: a missing element (consent wall, wrong page) reads differently from
59
+ * a present-but-unactionable one.
60
+ */
61
+ export declare function formatSelectorMatchHint(count: number): string;
40
62
  export interface InflightOp {
41
63
  label: string;
42
64
  startedAt: number;
@@ -4,6 +4,24 @@ export interface ChangelogEntry {
4
4
  patch: number;
5
5
  content: string;
6
6
  }
7
+ /** Number of changelog releases shown by automatic and default recent views. */
8
+ export declare const RECENT_CHANGELOG_ENTRY_LIMIT = 3;
9
+ /** Maximum Markdown source bytes allowed in automatic startup release notes. */
10
+ export declare const STARTUP_CHANGELOG_MAX_BYTES: number;
11
+ /** Hint appended when automatic startup release notes are truncated. */
12
+ export declare const STARTUP_CHANGELOG_FULL_HINT = "Use `/changelog full` to view the complete changelog.";
13
+ /** Markdown generated from selected changelog entries and whether it hit a size cap. */
14
+ export interface RenderedChangelog {
15
+ markdown: string;
16
+ truncated: boolean;
17
+ }
18
+ /** Automatic startup changelog decision, including whether the marker should advance. */
19
+ export interface StartupChangelogSelection {
20
+ markdown: string | undefined;
21
+ persistCurrentVersion: boolean;
22
+ truncated: boolean;
23
+ selectedEntries: number;
24
+ }
7
25
  /**
8
26
  * Parse changelog entries from the file at `changelogPath`. Scans for `## [x.y.z]`
9
27
  * headings and collects each block until the next heading or EOF.
@@ -19,9 +37,25 @@ export declare function parseChangelog(changelogPath: string | undefined): Promi
19
37
  */
20
38
  export declare function compareVersions(v1: ChangelogEntry, v2: ChangelogEntry): number;
21
39
  /**
22
- * Get entries newer than lastVersion
40
+ * Parse an omp changelog marker version into comparable parts.
41
+ */
42
+ export declare function parseChangelogVersion(version: string | undefined): ChangelogEntry | undefined;
43
+ /**
44
+ * Get entries newer than lastVersion.
23
45
  */
24
46
  export declare function getNewEntries(entries: ChangelogEntry[], lastVersion: string): ChangelogEntry[];
47
+ /**
48
+ * Render changelog entries oldest-first by default and optionally cap the Markdown source size.
49
+ */
50
+ export declare function renderChangelogEntries(entries: ChangelogEntry[], options?: {
51
+ maxBytes?: number;
52
+ truncationHint?: string;
53
+ oldestFirst?: boolean;
54
+ }): RenderedChangelog;
55
+ /**
56
+ * Select bounded release notes for interactive startup.
57
+ */
58
+ export declare function selectStartupChangelog(entries: ChangelogEntry[], lastVersion: string | undefined, currentVersion: string): StartupChangelogSelection;
25
59
  export { getChangelogPath } from "../config";
26
60
  /**
27
61
  * Last jeopi version whose changelog the user has seen. Stored as a plain-text
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "jeopi-cli",
4
- "version": "16.4.1",
4
+ "version": "16.4.3",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://github.com/akillness/jeopi",
7
7
  "author": "Can Boluk",
@@ -57,17 +57,17 @@
57
57
  "@agentclientprotocol/sdk": "0.25.0",
58
58
  "@babel/parser": "^7.29.7",
59
59
  "@mozilla/readability": "^0.6.0",
60
- "jeopi-hashline": "16.4.1",
61
- "jeopi-stats": "16.4.1",
62
- "jeopi-agent-core": "16.4.1",
63
- "jeopi-ai": "16.4.1",
64
- "jeopi-catalog": "16.4.1",
65
- "jeopi-mnemopi": "16.4.1",
66
- "jeopi-natives": "16.4.1",
67
- "jeopi-tui": "16.4.1",
68
- "jeopi-utils": "16.4.1",
69
- "jeopi-wire": "16.4.1",
70
- "jeopi-snapcompact": "16.4.1",
60
+ "jeopi-hashline": "16.4.3",
61
+ "jeopi-stats": "16.4.3",
62
+ "jeopi-agent-core": "16.4.3",
63
+ "jeopi-ai": "16.4.3",
64
+ "jeopi-catalog": "16.4.3",
65
+ "jeopi-mnemopi": "16.4.3",
66
+ "jeopi-natives": "16.4.3",
67
+ "jeopi-tui": "16.4.3",
68
+ "jeopi-utils": "16.4.3",
69
+ "jeopi-wire": "16.4.3",
70
+ "jeopi-snapcompact": "16.4.3",
71
71
  "@opentelemetry/api": "^1.9.1",
72
72
  "@opentelemetry/context-async-hooks": "^2.7.1",
73
73
  "@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
@@ -1839,6 +1839,19 @@ describe("advisor", () => {
1839
1839
  expect(text).toContain("read, grep, glob (default)");
1840
1840
  });
1841
1841
 
1842
+ it("renders an explicit no-tools advisor distinctly from the omitted default", async () => {
1843
+ const uiTheme = await getThemeByName("dark");
1844
+ if (!uiTheme) throw new Error("theme unavailable");
1845
+ setThemeInstance(uiTheme);
1846
+ const overlay = make({
1847
+ advisors: [{ name: "Blank", tools: [] }],
1848
+ });
1849
+
1850
+ const text = strip(overlay.render(200));
1851
+ expect(text.toLowerCase()).toContain("no tools");
1852
+ expect(text).not.toContain("read, grep, glob (default)");
1853
+ });
1854
+
1842
1855
  it("moves the preview with keyboard selection and preserves an explicit tool set", async () => {
1843
1856
  const uiTheme = await getThemeByName("dark");
1844
1857
  if (!uiTheme) throw new Error("theme unavailable");