@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.
- package/CHANGELOG.md +19 -0
- package/dist/base-context-runtime/pyproject.toml +1 -1
- package/dist/base-context-runtime/src/rlm/mcp.py +39 -17
- package/dist/base-context-runtime/test/test_mcp.py +87 -1
- package/dist/base-context-runtime/uv.lock +1 -1
- package/dist/build-info.json +1 -1
- package/dist/bundle/amazon-bedrock.js +2 -2
- package/dist/bundle/{bundled-modules-PWOGKUQQ.js → bundled-modules-UVCJPNFC.js} +4 -4
- package/dist/bundle/{chunk-IADCPVEI.js → chunk-6FZM46AU.js} +27 -12
- package/dist/bundle/{chunk-HKINIBP4.js → chunk-LFPWHI42.js} +1 -1
- package/dist/bundle/{chunk-27QCJ2AZ.js → chunk-UPVDERMD.js} +0 -12
- package/dist/bundle/{chunk-44PEHPOG.js → chunk-WFJRFQGG.js} +402 -277
- package/dist/bundle/{cli-main-4DS7Y3PI.js → cli-main-OYVMMJUO.js} +3 -3
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/{main-SV7JLVEB.js → main-AVMYOTHF.js} +4 -4
- package/dist/cli/daemon-ps.d.ts.map +1 -1
- package/dist/cli/daemon-ps.js +1 -0
- package/dist/cli/daemon-ps.js.map +1 -1
- package/dist/core/auth-storage.d.ts +4 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +77 -19
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/kernel/bootstrap.d.ts.map +1 -1
- package/dist/core/kernel/bootstrap.js +5 -2
- package/dist/core/kernel/bootstrap.js.map +1 -1
- package/dist/core/mcp/mcp-manager.d.ts.map +1 -1
- package/dist/core/mcp/mcp-manager.js +2 -2
- package/dist/core/mcp/mcp-manager.js.map +1 -1
- package/dist/installer.mjs +5 -2
- package/dist/modes/daemon/daemon-supervisor-ownership.d.ts.map +1 -1
- package/dist/modes/daemon/daemon-supervisor-ownership.js +16 -16
- package/dist/modes/daemon/daemon-supervisor-ownership.js.map +1 -1
- package/dist/modes/interactive/auth-flows.d.ts.map +1 -1
- package/dist/modes/interactive/auth-flows.js +7 -6
- package/dist/modes/interactive/auth-flows.js.map +1 -1
- package/dist/modes/interactive/components/brand-announcement.d.ts +5 -0
- package/dist/modes/interactive/components/brand-announcement.d.ts.map +1 -0
- package/dist/modes/interactive/components/brand-announcement.js +14 -0
- package/dist/modes/interactive/components/brand-announcement.js.map +1 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +3 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +3 -1
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/menu-panel.d.ts +1 -0
- package/dist/modes/interactive/components/menu-panel.d.ts.map +1 -1
- package/dist/modes/interactive/components/menu-panel.js +3 -0
- package/dist/modes/interactive/components/menu-panel.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +9 -6
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +11 -9
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/shared/startup-notices.d.ts.map +1 -1
- package/dist/modes/shared/startup-notices.js +1 -1
- package/dist/modes/shared/startup-notices.js.map +1 -1
- package/dist/themes/synerise-logo.d.ts +3 -0
- package/dist/themes/synerise-logo.d.ts.map +1 -0
- package/dist/themes/synerise-logo.js +9 -0
- package/dist/themes/synerise-logo.js.map +1 -0
- package/package.json +6 -6
- package/dist/modes/interactive/assets/clankolas.png +0 -0
- package/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +0 -1
- package/dist/modes/interactive/components/earendil-announcement.js +0 -40
- package/dist/modes/interactive/components/earendil-announcement.js.map +0 -1
- package/dist/themes/prime-logo.d.ts +0 -9
- package/dist/themes/prime-logo.d.ts.map +0 -1
- package/dist/themes/prime-logo.js +0 -18
- 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.
|
|
@@ -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
|
-
|
|
264
|
+
from mcp.types import PaginatedRequestParams
|
|
265
|
+
|
|
263
266
|
tools: dict[str, dict[str, Any]] = {}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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 [
|
|
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
|
|
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
|
|
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"}
|
package/dist/build-info.json
CHANGED
|
@@ -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-
|
|
5
|
-
import "./chunk-
|
|
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-
|
|
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-
|
|
146
|
+
} from "./chunk-6FZM46AU.js";
|
|
147
147
|
import "./chunk-CFNASUYO.js";
|
|
148
|
-
import "./chunk-
|
|
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-
|
|
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-
|
|
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 =
|
|
22505
|
-
const totalWidth = visibleWidth(
|
|
22516
|
+
let cursorDisplay = display.cursor;
|
|
22517
|
+
const totalWidth = visibleWidth(display.value);
|
|
22506
22518
|
if (totalWidth < availableWidth) {
|
|
22507
|
-
visibleText =
|
|
22519
|
+
visibleText = display.value;
|
|
22508
22520
|
} else {
|
|
22509
|
-
const scrollWidth =
|
|
22510
|
-
const cursorCol = visibleWidth(
|
|
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(
|
|
22522
|
-
const beforeCursor2 = sliceByColumn(
|
|
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-
|
|
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], {
|
|
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.
|
|
69000
|
+
return false ? void 0 : "v1.0.5";
|
|
68986
69001
|
}
|
|
68987
69002
|
function getDaemonRuntimeIdentity(environment = process.env) {
|
|
68988
69003
|
const entrypoint = process.argv[1];
|
|
@@ -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,
|