@ponythewhite/base-context 1.0.2 → 1.0.5

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 (70) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/base-context-runtime/pyproject.toml +1 -1
  3. package/dist/base-context-runtime/src/rlm/mcp.py +39 -17
  4. package/dist/base-context-runtime/test/test_mcp.py +87 -1
  5. package/dist/base-context-runtime/uv.lock +1 -1
  6. package/dist/build-info.json +1 -1
  7. package/dist/bundle/amazon-bedrock.js +2 -2
  8. package/dist/bundle/{bundled-modules-PWOGKUQQ.js → bundled-modules-UVCJPNFC.js} +4 -4
  9. package/dist/bundle/{chunk-IADCPVEI.js → chunk-6FZM46AU.js} +27 -12
  10. package/dist/bundle/{chunk-HKINIBP4.js → chunk-LFPWHI42.js} +1 -1
  11. package/dist/bundle/{chunk-27QCJ2AZ.js → chunk-UPVDERMD.js} +0 -12
  12. package/dist/bundle/{chunk-44PEHPOG.js → chunk-WFJRFQGG.js} +402 -277
  13. package/dist/bundle/{cli-main-4DS7Y3PI.js → cli-main-OYVMMJUO.js} +3 -3
  14. package/dist/bundle/cli.js +1 -1
  15. package/dist/bundle/{main-SV7JLVEB.js → main-AVMYOTHF.js} +4 -4
  16. package/dist/cli/daemon-ps.d.ts.map +1 -1
  17. package/dist/cli/daemon-ps.js +1 -0
  18. package/dist/cli/daemon-ps.js.map +1 -1
  19. package/dist/core/auth-storage.d.ts +4 -0
  20. package/dist/core/auth-storage.d.ts.map +1 -1
  21. package/dist/core/auth-storage.js +77 -19
  22. package/dist/core/auth-storage.js.map +1 -1
  23. package/dist/core/kernel/bootstrap.d.ts.map +1 -1
  24. package/dist/core/kernel/bootstrap.js +5 -2
  25. package/dist/core/kernel/bootstrap.js.map +1 -1
  26. package/dist/core/mcp/mcp-manager.d.ts.map +1 -1
  27. package/dist/core/mcp/mcp-manager.js +2 -2
  28. package/dist/core/mcp/mcp-manager.js.map +1 -1
  29. package/dist/installer.mjs +5 -2
  30. package/dist/modes/daemon/daemon-supervisor-ownership.d.ts.map +1 -1
  31. package/dist/modes/daemon/daemon-supervisor-ownership.js +16 -16
  32. package/dist/modes/daemon/daemon-supervisor-ownership.js.map +1 -1
  33. package/dist/modes/interactive/auth-flows.d.ts.map +1 -1
  34. package/dist/modes/interactive/auth-flows.js +7 -6
  35. package/dist/modes/interactive/auth-flows.js.map +1 -1
  36. package/dist/modes/interactive/components/brand-announcement.d.ts +5 -0
  37. package/dist/modes/interactive/components/brand-announcement.d.ts.map +1 -0
  38. package/dist/modes/interactive/components/brand-announcement.js +14 -0
  39. package/dist/modes/interactive/components/brand-announcement.js.map +1 -0
  40. package/dist/modes/interactive/components/login-dialog.d.ts +3 -1
  41. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  42. package/dist/modes/interactive/components/login-dialog.js +3 -1
  43. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  44. package/dist/modes/interactive/components/menu-panel.d.ts +1 -0
  45. package/dist/modes/interactive/components/menu-panel.d.ts.map +1 -1
  46. package/dist/modes/interactive/components/menu-panel.js +3 -0
  47. package/dist/modes/interactive/components/menu-panel.js.map +1 -1
  48. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  49. package/dist/modes/interactive/components/settings-selector.js +9 -6
  50. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  51. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  52. package/dist/modes/interactive/interactive-mode.js +11 -9
  53. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  54. package/dist/modes/shared/startup-notices.d.ts.map +1 -1
  55. package/dist/modes/shared/startup-notices.js +1 -1
  56. package/dist/modes/shared/startup-notices.js.map +1 -1
  57. package/dist/themes/synerise-logo.d.ts +3 -0
  58. package/dist/themes/synerise-logo.d.ts.map +1 -0
  59. package/dist/themes/synerise-logo.js +9 -0
  60. package/dist/themes/synerise-logo.js.map +1 -0
  61. package/package.json +6 -6
  62. package/dist/modes/interactive/assets/clankolas.png +0 -0
  63. package/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
  64. package/dist/modes/interactive/components/earendil-announcement.d.ts.map +0 -1
  65. package/dist/modes/interactive/components/earendil-announcement.js +0 -40
  66. package/dist/modes/interactive/components/earendil-announcement.js.map +0 -1
  67. package/dist/themes/prime-logo.d.ts +0 -9
  68. package/dist/themes/prime-logo.d.ts.map +0 -1
  69. package/dist/themes/prime-logo.js +0 -18
  70. package/dist/themes/prime-logo.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.0.5] - 2026-09-18
4
+
5
+ - Displayed the built-in theme as Synerise without changing saved theme IDs, and branded the tmux startup notice as base-context.
6
+ - Replaced the upstream startup artwork with a Synerise ASCII wordmark and base-context label.
7
+
8
+ ## [1.0.4] - 2026-09-17
9
+
10
+ - Fixed first-time Python setup failing to find its newly installed uv when XDG data paths are configured.
11
+
12
+ ## [1.0.3] - 2026-09-17
13
+
14
+ - Fixed late OAuth and API-key logins overwriting a newer login or undoing logout.
15
+ - Fixed configured MCP environment-token authentication falling back to stored credentials.
16
+ - Fixed MCP tool discovery to retrieve paginated inventories without partial results and protect cached schemas from caller edits.
17
+ - Masked API-key prompts and pasted sign-in codes and callback values while keeping browser sign-in links readable.
18
+ - Fixed provider logout reporting success when saved credentials could not be removed.
19
+ - Fixed shutdown admission loss after slow process scans or transient registry errors while the shutdown process still owns its record.
20
+ - Fixed source builds including the development Python virtual environment in release packages.
21
+
3
22
  ## [1.0.2] - 2026-09-17
4
23
 
5
24
  - Fixed RPC requests waiting for a timeout after the agent process exits, and removed the shutdown delay for an already-exited process.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "base-context-runtime"
3
- version = "1.0.2"
3
+ version = "1.0.5"
4
4
  description = "Kernel-side runtime shim for Base Context recursion"
5
5
  license = "MIT"
6
6
  license-files = ["LICENSE", "NOTICE"]
@@ -10,6 +10,7 @@ import re
10
10
  import threading
11
11
  import time
12
12
  from contextlib import AsyncExitStack
13
+ from copy import deepcopy
13
14
  from collections.abc import Awaitable, Callable
14
15
  from typing import Any, TypeVar
15
16
 
@@ -20,6 +21,7 @@ __all__ = ["McpStartupError", "call_tool", "close", "list_tools", "reload"]
20
21
 
21
22
  _DEFAULT_STARTUP_TIMEOUT = 20.0
22
23
  _DEFAULT_CALL_TIMEOUT = 60.0
24
+ _MAX_TOOL_LIST_PAGES = 100
23
25
  # Must stay strictly below the host's KERNEL_SHUTDOWN_TIMEOUT_MS (5s) kill deadline.
24
26
  _SHUTDOWN_TIMEOUT = 2.5
25
27
  _T = TypeVar("_T")
@@ -259,21 +261,41 @@ class _Generation:
259
261
  return await self.stack.enter_async_context(stdio_client(params, errlog=self._stderr))
260
262
 
261
263
  async def discover(self) -> None:
262
- response = await self.session.list_tools()
264
+ from mcp.types import PaginatedRequestParams
265
+
263
266
  tools: dict[str, dict[str, Any]] = {}
264
- for tool in response.tools:
265
- name = getattr(tool, "name", None)
266
- if not isinstance(name, str):
267
- continue
268
- schema = getattr(tool, "input_schema", None)
269
- if schema is None:
270
- schema = getattr(tool, "inputSchema", None)
271
- tools[name] = {
272
- "name": name,
273
- "description": getattr(tool, "description", "") or "",
274
- "inputSchema": schema if isinstance(schema, dict) else {},
275
- }
276
- self.tools = tools
267
+ cursor: str | None = None
268
+ seen_cursors: set[str] = set()
269
+ for _ in range(_MAX_TOOL_LIST_PAGES):
270
+ response = (
271
+ await self.session.list_tools()
272
+ if cursor is None
273
+ else await self.session.list_tools(params=PaginatedRequestParams(cursor=cursor))
274
+ )
275
+ for tool in response.tools:
276
+ name = getattr(tool, "name", None)
277
+ if not isinstance(name, str):
278
+ continue
279
+ schema = getattr(tool, "input_schema", None)
280
+ if schema is None:
281
+ schema = getattr(tool, "inputSchema", None)
282
+ tools[name] = {
283
+ "name": name,
284
+ "description": getattr(tool, "description", "") or "",
285
+ "inputSchema": schema if isinstance(schema, dict) else {},
286
+ }
287
+ cursor = getattr(response, "next_cursor", None)
288
+ if cursor is None:
289
+ cursor = getattr(response, "nextCursor", None)
290
+ if cursor is None:
291
+ self.tools = tools
292
+ return
293
+ if not isinstance(cursor, str):
294
+ raise RuntimeError(f"MCP server '{self.server}' returned an invalid tools/list cursor")
295
+ if cursor in seen_cursors:
296
+ raise RuntimeError(f"MCP server '{self.server}' repeated a tools/list cursor")
297
+ seen_cursors.add(cursor)
298
+ raise RuntimeError(f"MCP server '{self.server}' exceeded the tools/list page limit")
277
299
 
278
300
  def allows(self, tool: str) -> bool:
279
301
  enabled = self.config.get("enabledTools")
@@ -379,7 +401,7 @@ class _Registry:
379
401
  async def tools(self, server: str) -> list[dict[str, Any]]:
380
402
  async def operation() -> list[dict[str, Any]]:
381
403
  generation = await self._get(server)
382
- return [dict(tool) for name, tool in generation.tools.items() if generation.allows(name)]
404
+ return [deepcopy(tool) for name, tool in generation.tools.items() if generation.allows(name)]
383
405
 
384
406
  return await self._tracked(operation)
385
407
 
@@ -529,7 +551,7 @@ def _bound_auth(provider: str, config: dict[str, Any]) -> dict[str, Any] | None:
529
551
  async def _auth_identity(server: str, config: dict[str, Any]) -> str:
530
552
  env_name = config.get("bearerTokenEnvVar")
531
553
  token = os.environ.get(env_name, "").strip() if isinstance(env_name, str) else ""
532
- if config.get("oauth") is True and not token:
554
+ if config.get("oauth") is True and not env_name:
533
555
  provider = f"mcp:{server}"
534
556
  cred = _bound_auth(provider, config)
535
557
  expires = (cred or {}).get("expires")
@@ -556,7 +578,7 @@ async def _headers(server: str, config: dict[str, Any]) -> dict[str, str]:
556
578
  return headers
557
579
  env_name = config.get("bearerTokenEnvVar")
558
580
  token = os.environ.get(env_name, "").strip() if isinstance(env_name, str) else ""
559
- if config.get("oauth") is True and not token:
581
+ if config.get("oauth") is True and not env_name:
560
582
  cred = _bound_auth(f"mcp:{server}", config)
561
583
  token = _resolve_config_value(str((cred or {}).get("access") or (cred or {}).get("key") or ""))
562
584
  if token:
@@ -15,7 +15,7 @@ from pathlib import Path
15
15
  from types import SimpleNamespace
16
16
  from unittest import mock
17
17
 
18
- from mcp.types import CallToolResult, TextContent
18
+ from mcp.types import CallToolResult, PaginatedRequestParams, TextContent
19
19
  from rlm import McpToolError, mcp
20
20
  from rlm.mcp_base import _parse_result
21
21
 
@@ -104,6 +104,55 @@ class McpRegistryTest(unittest.TestCase):
104
104
  generation = self.generation({"type": "http"}, [tool])
105
105
  self.assertEqual(generation.tools["raw.tool/name"]["inputSchema"], schema)
106
106
 
107
+ def test_listing_detaches_nested_cached_schemas(self):
108
+ schema = {"type": "object", "properties": {"x": {"enum": ["original"]}}}
109
+ generation = self.generation({"type": "http"}, [SimpleNamespace(name="tool", inputSchema=schema)])
110
+
111
+ async def scenario():
112
+ with mock.patch.object(mcp._registry, "_get_locked", mock.AsyncMock(return_value=generation)):
113
+ first = await mcp.list_tools("svc")
114
+ first[0]["inputSchema"]["properties"]["x"]["enum"].append("caller mutation")
115
+ second = await mcp.list_tools("svc")
116
+ self.assertEqual(second[0]["inputSchema"], schema)
117
+ self.assertEqual(schema["properties"]["x"]["enum"], ["original"])
118
+
119
+ run(scenario())
120
+
121
+ def test_discovers_all_pages_with_sdk_params_and_cursor_aliases(self):
122
+ generation = mcp._Generation("svc", {"type": "http"})
123
+ generation.session = SimpleNamespace(list_tools=mock.AsyncMock(side_effect=[
124
+ SimpleNamespace(tools=[SimpleNamespace(name="first")], next_cursor=""),
125
+ SimpleNamespace(tools=[SimpleNamespace(name="second")], nextCursor="page-3"),
126
+ SimpleNamespace(tools=[SimpleNamespace(name="third")], next_cursor=None),
127
+ ]))
128
+ run(generation.discover())
129
+ self.assertEqual(list(generation.tools), ["first", "second", "third"])
130
+ self.assertEqual(generation.session.list_tools.call_args_list, [
131
+ mock.call(),
132
+ mock.call(params=PaginatedRequestParams(cursor="")),
133
+ mock.call(params=PaginatedRequestParams(cursor="page-3")),
134
+ ])
135
+
136
+ def test_failed_pagination_never_publishes_partial_inventory(self):
137
+ for case, cursors, message in (
138
+ ("cycle", ["repeat", "repeat"], "repeated"),
139
+ ("malformed", [17], "invalid"),
140
+ ("excessive", ["page-2", "page-3"], "page limit"),
141
+ ):
142
+ with self.subTest(case=case):
143
+ generation = self.generation({"type": "http"}, [SimpleNamespace(name="previous")])
144
+ previous = generation.tools
145
+ generation.session = SimpleNamespace(list_tools=mock.AsyncMock(side_effect=[
146
+ SimpleNamespace(tools=[SimpleNamespace(name="partial")], next_cursor=cursor)
147
+ for cursor in cursors
148
+ ]))
149
+ with mock.patch.object(mcp, "_MAX_TOOL_LIST_PAGES", 2):
150
+ with self.assertRaisesRegex(RuntimeError, message):
151
+ run(generation.discover())
152
+ self.assertIs(generation.tools, previous)
153
+ self.assertNotIn("partial", generation.tools)
154
+ self.assertLessEqual(generation.session.list_tools.call_count, 2)
155
+
107
156
  def test_sdk_result_aliases_preserve_structured_output_and_errors(self):
108
157
  structured = CallToolResult(content=[], structuredContent={})
109
158
  self.assertEqual(_parse_result(structured), {})
@@ -317,6 +366,43 @@ class McpRegistryTest(unittest.TestCase):
317
366
  env = mcp._stdio_env({"credentialSource": "acp", "env": {"TOKEN": "task-secret"}})
318
367
  self.assertEqual(env, {"PATH": "/bin", "TOKEN": "task-secret"})
319
368
 
369
+ def test_selected_environment_token_refuses_missing_values_before_connection(self):
370
+ config = {
371
+ "type": "http", "url": "https://srv.example/mcp", "oauth": True,
372
+ "bearerTokenEnvVar": "SELECTED_MCP_TOKEN",
373
+ "headers": {"Authorization": "Bearer configured-header"},
374
+ }
375
+ for token in (None, "", " "):
376
+ with self.subTest(token=token), mock.patch.dict(
377
+ os.environ, {} if token is None else {"SELECTED_MCP_TOKEN": token}, clear=True
378
+ ), mock.patch.object(mcp, "host_request", new=mock.AsyncMock(return_value=config)) as request, mock.patch.object(
379
+ mcp, "_read_auth", side_effect=AssertionError("must not read stored OAuth")
380
+ ), mock.patch.object(mcp._Generation, "_open_http", new=mock.AsyncMock()) as connect:
381
+ with self.assertRaisesRegex(RuntimeError, "credentials.*not available"):
382
+ run(mcp.list_tools("remote"))
383
+ with self.assertRaisesRegex(RuntimeError, "credentials.*not available"):
384
+ run(mcp._headers("remote", config))
385
+ request.assert_awaited_once_with("mcp.config", {"server": "remote"})
386
+ connect.assert_not_called()
387
+ self.assertEqual(mcp._registry._generations, {})
388
+ mcp._registry = mcp._Registry()
389
+
390
+ def test_selected_environment_token_is_the_only_auth_source(self):
391
+ config = {
392
+ "oauth": True, "url": "https://srv.example/mcp", "bearerTokenEnvVar": "SELECTED_MCP_TOKEN",
393
+ "headers": {"Authorization": "Bearer configured-header", "X-Other": "keep"},
394
+ }
395
+ with mock.patch.dict(os.environ, {"SELECTED_MCP_TOKEN": " selected-token "}), mock.patch.object(
396
+ mcp, "_read_auth", side_effect=AssertionError("must not read stored OAuth")
397
+ ), mock.patch.object(mcp, "host_request", new=mock.AsyncMock()) as request:
398
+ identity = run(mcp._auth_identity("remote", config))
399
+ self.assertNotEqual(identity, "anonymous")
400
+ self.assertNotIn("selected-token", identity)
401
+ self.assertEqual(run(mcp._headers("remote", config)), {
402
+ "Authorization": "Bearer selected-token", "X-Other": "keep",
403
+ })
404
+ request.assert_not_called()
405
+
320
406
  def test_endpoint_bound_credential_never_attaches_to_another_url(self):
321
407
  cred = {"access": "old-token", "endpoint": "https://old.example/mcp"}
322
408
  config = {"oauth": True, "url": "https://new.example/mcp"}
@@ -367,7 +367,7 @@ wheels = [
367
367
 
368
368
  [[package]]
369
369
  name = "base-context-runtime"
370
- version = "1.0.2"
370
+ version = "1.0.5"
371
371
  source = { editable = "." }
372
372
  dependencies = [
373
373
  { name = "mcp" },
@@ -1,5 +1,5 @@
1
1
  {
2
- "sourceCommit": "4192025d919683d61a402b666b4790e26118df53",
2
+ "sourceCommit": "79e825d437ae8d67768558cf2a51976cd4434616",
3
3
  "sourceDirty": false,
4
4
  "buildHost": {
5
5
  "platform": "linux",
@@ -1,8 +1,8 @@
1
1
  import { createRequire as __piBundleCreateRequire } from 'node:module'; const require = __piBundleCreateRequire(import.meta.url);
2
2
  import {
3
3
  writeFileLogEntry
4
- } from "./chunk-HKINIBP4.js";
5
- import "./chunk-27QCJ2AZ.js";
4
+ } from "./chunk-LFPWHI42.js";
5
+ import "./chunk-UPVDERMD.js";
6
6
  import "./chunk-5QCJ5DQU.js";
7
7
  import "./chunk-CRBVRZBV.js";
8
8
  import "./chunk-GRJFXLBM.js";
@@ -51,7 +51,7 @@ import {
51
51
  oauth_exports,
52
52
  runPrintMode,
53
53
  runRpcMode
54
- } from "./chunk-44PEHPOG.js";
54
+ } from "./chunk-WFJRFQGG.js";
55
55
  import {
56
56
  AgentSession,
57
57
  CURRENT_SESSION_VERSION,
@@ -143,15 +143,15 @@ import {
143
143
  withFileMutationQueue,
144
144
  wrapRegisteredTool,
145
145
  wrapRegisteredTools
146
- } from "./chunk-IADCPVEI.js";
146
+ } from "./chunk-6FZM46AU.js";
147
147
  import "./chunk-CFNASUYO.js";
148
- import "./chunk-HKINIBP4.js";
148
+ import "./chunk-LFPWHI42.js";
149
149
  import {
150
150
  VERSION,
151
151
  build_exports,
152
152
  getAgentDir,
153
153
  src_exports
154
- } from "./chunk-27QCJ2AZ.js";
154
+ } from "./chunk-UPVDERMD.js";
155
155
  import "./chunk-5QCJ5DQU.js";
156
156
  import {
157
157
  compile_exports,
@@ -32,7 +32,7 @@ import {
32
32
  typebox_exports,
33
33
  validateToolArguments,
34
34
  waitForChildProcess
35
- } from "./chunk-27QCJ2AZ.js";
35
+ } from "./chunk-UPVDERMD.js";
36
36
  import {
37
37
  cleanupSessionResources,
38
38
  registerSessionResourceCleanup
@@ -22195,6 +22195,8 @@ var Input = class {
22195
22195
  constructor() {
22196
22196
  this.value = "";
22197
22197
  this.cursor = 0;
22198
+ // Cursor position in the value
22199
+ this.masked = false;
22198
22200
  this.focused = false;
22199
22201
  this.pasteBuffer = "";
22200
22202
  this.isInPaste = false;
@@ -22202,6 +22204,9 @@ var Input = class {
22202
22204
  this.lastAction = null;
22203
22205
  this.undoStack = new UndoStack();
22204
22206
  }
22207
+ setMasked(masked) {
22208
+ this.masked = masked;
22209
+ }
22205
22210
  getValue() {
22206
22211
  return this.value;
22207
22212
  }
@@ -22494,20 +22499,27 @@ var Input = class {
22494
22499
  }
22495
22500
  invalidate() {
22496
22501
  }
22502
+ displayState() {
22503
+ if (!this.masked) return { value: this.value, cursor: this.cursor };
22504
+ const graphemes = [...segmenter2.segment(this.value)];
22505
+ const beforeCursor = [...segmenter2.segment(this.value.slice(0, this.cursor))];
22506
+ return { value: "\u2022".repeat(graphemes.length), cursor: beforeCursor.length };
22507
+ }
22497
22508
  render(width) {
22498
22509
  const prompt = "> ";
22499
22510
  const availableWidth = width - prompt.length;
22500
22511
  if (availableWidth <= 0) {
22501
22512
  return [prompt];
22502
22513
  }
22514
+ const display = this.displayState();
22503
22515
  let visibleText = "";
22504
- let cursorDisplay = this.cursor;
22505
- const totalWidth = visibleWidth(this.value);
22516
+ let cursorDisplay = display.cursor;
22517
+ const totalWidth = visibleWidth(display.value);
22506
22518
  if (totalWidth < availableWidth) {
22507
- visibleText = this.value;
22519
+ visibleText = display.value;
22508
22520
  } else {
22509
- const scrollWidth = this.cursor === this.value.length ? availableWidth - 1 : availableWidth;
22510
- const cursorCol = visibleWidth(this.value.slice(0, this.cursor));
22521
+ const scrollWidth = display.cursor === display.value.length ? availableWidth - 1 : availableWidth;
22522
+ const cursorCol = visibleWidth(display.value.slice(0, display.cursor));
22511
22523
  if (scrollWidth > 0) {
22512
22524
  const halfWidth = Math.floor(scrollWidth / 2);
22513
22525
  let startCol = 0;
@@ -22518,8 +22530,8 @@ var Input = class {
22518
22530
  } else {
22519
22531
  startCol = Math.max(0, cursorCol - halfWidth);
22520
22532
  }
22521
- visibleText = sliceByColumn(this.value, startCol, scrollWidth, true);
22522
- const beforeCursor2 = sliceByColumn(this.value, startCol, Math.max(0, cursorCol - startCol), true);
22533
+ visibleText = sliceByColumn(display.value, startCol, scrollWidth, true);
22534
+ const beforeCursor2 = sliceByColumn(display.value, startCol, Math.max(0, cursorCol - startCol), true);
22523
22535
  cursorDisplay = beforeCursor2.length;
22524
22536
  } else {
22525
22537
  visibleText = "";
@@ -44713,7 +44725,7 @@ async function loadExtensionModule(extensionPath) {
44713
44725
  // (file-path aliases would load a second, divergent copy of each package).
44714
44726
  // Also disable tryNative so jiti handles ALL imports (not just the entry point)
44715
44727
  // Node/dev must also share the native AI registry and implementation identities.
44716
- ...isBunBinary || isBundledCli ? { virtualModules: (await import("./bundled-modules-PWOGKUQQ.js")).VIRTUAL_MODULES, tryNative: false } : {
44728
+ ...isBunBinary || isBundledCli ? { virtualModules: (await import("./bundled-modules-UVCJPNFC.js")).VIRTUAL_MODULES, tryNative: false } : {
44717
44729
  alias: getAliases(),
44718
44730
  virtualModules: {
44719
44731
  "@ponythewhite/base-context-ai": src_exports,
@@ -47922,7 +47934,7 @@ async function resolveWritableKernelVenvDir() {
47922
47934
  function run(command, args, options = {}) {
47923
47935
  return new Promise((resolve17, reject) => {
47924
47936
  const child = spawn6(command, args, {
47925
- env: process.env,
47937
+ env: options.env ?? process.env,
47926
47938
  stdio: options.stdio ?? "ignore"
47927
47939
  });
47928
47940
  child.on("error", reject);
@@ -48056,7 +48068,10 @@ async function ensureUv(options) {
48056
48068
  }
48057
48069
  reportProgress(options, "\u203A installing uv (one-time)\u2026");
48058
48070
  try {
48059
- await run("sh", ["-c", UV_INSTALL_COMMAND], { stdio: options.onProgress ? "ignore" : "inherit" });
48071
+ await run("sh", ["-c", UV_INSTALL_COMMAND], {
48072
+ stdio: options.onProgress ? "ignore" : "inherit",
48073
+ env: { ...process.env, UV_INSTALL_DIR: path5.dirname(localUv) }
48074
+ });
48060
48075
  } catch (error) {
48061
48076
  throw new Error(`couldn't install uv from astral.sh; install it yourself: ${UV_INSTALL_COMMAND}, then re-run base-context. ${errorMessage2(error)}`);
48062
48077
  }
@@ -68982,7 +68997,7 @@ import { resolve as resolve15 } from "node:path";
68982
68997
  var BASE_CONTEXT_BUILD_ID_ENV = "BASE_CONTEXT_BUILD_ID";
68983
68998
  var BASE_CONTEXT_LAUNCHER_PATH_ENV = "BASE_CONTEXT_LAUNCHER_PATH";
68984
68999
  function bundledBuildId() {
68985
- return false ? void 0 : "v1.0.2";
69000
+ return false ? void 0 : "v1.0.5";
68986
69001
  }
68987
69002
  function getDaemonRuntimeIdentity(environment = process.env) {
68988
69003
  const entrypoint = process.argv[1];
@@ -2,7 +2,7 @@ import { createRequire as __piBundleCreateRequire } from 'node:module'; const re
2
2
  import {
3
3
  appendRotatingLog,
4
4
  getAgentLogPath
5
- } from "./chunk-27QCJ2AZ.js";
5
+ } from "./chunk-UPVDERMD.js";
6
6
  import {
7
7
  setLogSink,
8
8
  stringifyLogEntry
@@ -826,17 +826,6 @@ function getDocsPath() {
826
826
  function getChangelogPath() {
827
827
  return resolve3(join2(getPackageDir(), "CHANGELOG.md"));
828
828
  }
829
- function getInteractiveAssetsDir() {
830
- if (isBunBinary) {
831
- return join2(getPackageDir(), "assets");
832
- }
833
- const packageDir = getPackageDir();
834
- const srcOrDist = existsSync(join2(packageDir, "src")) ? "src" : "dist";
835
- return join2(packageDir, srcOrDist, "modes", "interactive", "assets");
836
- }
837
- function getBundledInteractiveAssetPath(name) {
838
- return join2(getInteractiveAssetsDir(), name);
839
- }
840
829
  function getBundledSkillsDir() {
841
830
  if (isBunBinary) {
842
831
  return join2(getPackageDir(), "skills");
@@ -2539,7 +2528,6 @@ export {
2539
2528
  getPackageJsonPath,
2540
2529
  getDocsPath,
2541
2530
  getChangelogPath,
2542
- getBundledInteractiveAssetPath,
2543
2531
  getBundledSkillsDir,
2544
2532
  PACKAGE_NAME,
2545
2533
  APP_NAME,