arisa 5.2.17 → 5.2.19

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 (33) hide show
  1. package/README.md +4 -2
  2. package/package.json +10 -9
  3. package/pnpm-workspace.yaml +7 -5
  4. package/src/core/agent/agent-manager.js +13 -14
  5. package/src/core/agent/auth-flow.js +6 -6
  6. package/src/core/agent/model-speed.js +3 -1
  7. package/src/core/agent/pi-auth-login.js +28 -28
  8. package/src/core/agent/pi-capability-tools.js +1 -0
  9. package/src/core/agent/pi-runtime.js +14 -21
  10. package/src/core/capabilities/capability-service.js +25 -0
  11. package/src/core/tasks/task-store.js +2 -1
  12. package/src/official-tools.lock.json +25 -18
  13. package/src/runtime/bootstrap-cli.js +3 -3
  14. package/src/runtime/bootstrap-telegram.js +7 -7
  15. package/src/runtime/slave-cli.js +20 -10
  16. package/src/runtime/slave-service.js +299 -7
  17. package/src/runtime/tui.js +5 -6
  18. package/src/transport/telegram/bot.js +9 -5
  19. package/src/transport/telegram/model-controls.js +1 -1
  20. package/src/transport/telegram/task-dispatcher.js +50 -23
  21. package/src/transport/telegram/telegram-auth-controller.js +7 -7
  22. package/src/transport/telegram/telegram-session-bridge.js +2 -1
  23. package/test/agent-turn-coordinator.test.js +5 -2
  24. package/test/auth-flow.test.js +2 -2
  25. package/test/capabilities-security.test.js +36 -0
  26. package/test/model-selection.test.js +3 -2
  27. package/test/official-tool-installer.test.js +13 -0
  28. package/test/pi-auth-login.test.js +78 -0
  29. package/test/pi-capability-tools.test.js +3 -0
  30. package/test/pi-speed-integration.test.js +176 -0
  31. package/test/slave-cli.test.js +221 -5
  32. package/test/task-store.test.js +3 -1
  33. package/test/telegram-task-dispatcher.test.js +57 -2
package/README.md CHANGED
@@ -127,8 +127,10 @@ Slave runs only the IPC host, daemon supervisor and installed tools. Connections
127
127
  are authenticated, encrypted, initiated by Slave and restricted by per-Slave
128
128
  roots and capability grants.
129
129
 
130
- Linux with systemd is the first supported Slave target. Bootstrap uses a
131
- single-use URL issued by Master:
130
+ Arisa Slave supports Linux with systemd, macOS with launchd, and Windows with
131
+ Task Scheduler. On desktop systems, run bootstrap as the normal user so the
132
+ persistent background task retains access to that user's browser profile.
133
+ Bootstrap uses a single-use URL issued by Master:
132
134
 
133
135
  ```bash
134
136
  npm i -g arisa && arisa slave tcp://198.51.100.12:4719/arisa_secret_v1_<secret>
package/package.json CHANGED
@@ -1,12 +1,17 @@
1
1
  {
2
2
  "name": "arisa",
3
- "version": "5.2.17",
3
+ "version": "5.2.19",
4
4
  "description": "Telegram + Pi Agent modular assistant",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
7
7
  "bin": {
8
8
  "arisa": "bin/arisa.js"
9
9
  },
10
+ "scripts": {
11
+ "start": "node src/index.js",
12
+ "bootstrap": "node src/index.js --bootstrap",
13
+ "test": "node --test"
14
+ },
10
15
  "keywords": [
11
16
  "telegram",
12
17
  "pi-agent",
@@ -29,7 +34,7 @@
29
34
  "author": "Martin Clasen",
30
35
  "license": "MIT",
31
36
  "engines": {
32
- "node": ">=22.8.0"
37
+ "node": ">=22.19.0"
33
38
  },
34
39
  "repository": {
35
40
  "type": "git",
@@ -39,14 +44,10 @@
39
44
  "url": "https://github.com/clasen/Arisa/issues"
40
45
  },
41
46
  "homepage": "https://arisa.sh",
47
+ "packageManager": "pnpm@11.3.0+sha512.2c403d6594527287672b1f7056343a1f7c3634036a67ffabfcc2b3d7595d843768f8787148d1b57cf7956c90606bbd192857c363af19e96d2d0ec9ec5741d215",
42
48
  "dependencies": {
43
- "@earendil-works/pi-coding-agent": "0.80.6",
49
+ "@earendil-works/pi-coding-agent": "0.85.1",
44
50
  "@sinclair/typebox": "^0.34.41",
45
51
  "grammy": "^1.42.0"
46
- },
47
- "scripts": {
48
- "start": "node src/index.js",
49
- "bootstrap": "node src/index.js --bootstrap",
50
- "test": "node --test"
51
52
  }
52
- }
53
+ }
@@ -1,11 +1,13 @@
1
1
  allowBuilds:
2
2
  '@google/genai': false
3
+ esbuild: true
3
4
 
4
5
  minimumReleaseAgeExclude:
5
- - '@earendil-works/pi-agent-core@0.80.6'
6
- - '@earendil-works/pi-ai@0.80.6'
7
- - '@earendil-works/pi-coding-agent@0.80.6'
8
- - '@earendil-works/pi-tui@0.80.6'
6
+ - '@earendil-works/pi-agent-core@0.85.1'
7
+ - '@earendil-works/pi-ai@0.85.1'
8
+ - '@earendil-works/pi-coding-agent@0.85.1'
9
+ - '@earendil-works/pi-tui@0.85.1'
10
+ - '@earendil-works/chord@0.85.1'
9
11
 
10
12
  overrides:
11
13
  'node-fetch@2.7.0>whatwg-url': '13.0.0'
@@ -14,7 +16,7 @@ overrides:
14
16
  basic-ftp@<=5.2.2: '>=5.3.0'
15
17
  basic-ftp@<=5.3.0: '>=5.3.1'
16
18
  basic-ftp@=5.2.0: '>=5.2.1'
17
- brace-expansion@>=5.0.0 <5.0.6: '>=5.0.6'
19
+ brace-expansion@>=4.0.0 <5.0.9: '5.0.9'
18
20
  ip-address@<=10.1.0: '>=10.1.1'
19
21
  protobufjs@<7.5.5: '>=7.5.5'
20
22
  protobufjs@<=7.5.5: '>=7.5.6'
@@ -323,22 +323,21 @@ export class AgentManager {
323
323
 
324
324
  async validatePiAgent(config = this.config) {
325
325
  this.logger?.log("agent", "validating Pi session");
326
- const { authStorage, modelRegistry } = createPiRuntime({
326
+ const modelRuntime = await createPiRuntime({
327
327
  provider: config.pi.provider,
328
328
  apiKey: config.pi.apiKey
329
329
  });
330
- const model = modelRegistry.find(config.pi.provider, config.pi.model);
330
+ const model = modelRuntime.getModel(config.pi.provider, config.pi.model);
331
331
  if (!model) {
332
332
  throw new Error(`Model not found: ${config.pi.provider}/${config.pi.model}`);
333
333
  }
334
- if (requiresProviderAuth(model) && !config.pi.apiKey && !hasProviderAuth(config.pi.provider, { authStorage, modelRegistry })) {
334
+ if (requiresProviderAuth(model) && !config.pi.apiKey && !hasProviderAuth(config.pi.provider, modelRuntime)) {
335
335
  throw new Error(`No auth found for ${config.pi.provider}. Provide a Pi API key in bootstrap, or authenticate with Pi login for this provider during bootstrap.`);
336
336
  }
337
337
 
338
338
  const settingsManager = createPiSettingsManager(config);
339
339
  const { session } = await createAgentSession({
340
- authStorage,
341
- modelRegistry,
340
+ modelRuntime,
342
341
  model,
343
342
  settingsManager,
344
343
  sessionManager: SessionManager.inMemory()
@@ -386,13 +385,13 @@ export class AgentManager {
386
385
  this.pendingNewSessions.add(sessionKey);
387
386
  }
388
387
 
389
- const { authStorage, modelRegistry } = createPiRuntime({
388
+ const modelRuntime = await createPiRuntime({
390
389
  provider: this.config.pi.provider,
391
390
  apiKey: this.config.pi.apiKey
392
391
  });
393
- const model = modelRegistry.find(this.config.pi.provider, effectiveModelId);
392
+ const model = modelRuntime.getModel(this.config.pi.provider, effectiveModelId);
394
393
  if (!model) throw new Error(`Model not found: ${this.config.pi.provider}/${effectiveModelId}`);
395
- if (requiresProviderAuth(model) && !this.config.pi.apiKey && !hasProviderAuth(this.config.pi.provider, { authStorage, modelRegistry })) {
394
+ if (requiresProviderAuth(model) && !this.config.pi.apiKey && !hasProviderAuth(this.config.pi.provider, modelRuntime)) {
396
395
  throw new Error(`No auth found for ${this.config.pi.provider}. Re-run bootstrap and complete login for this provider before Telegram starts.`);
397
396
  }
398
397
  const thinkingLevel = clampModelThinkingLevel(model, modelSelection.thinkingLevel);
@@ -418,7 +417,8 @@ export class AgentManager {
418
417
  initializeForumTopic: (...args) => telegramTarget.current.initializeForumTopic(...args),
419
418
  prepareRestartReceipt: (...args) => telegramTarget.current.prepareRestartReceipt(...args),
420
419
  cancelRestartReceipt: (...args) => telegramTarget.current.cancelRestartReceipt(...args),
421
- getTaskContext: (...args) => telegramTarget.current.getTaskContext?.(...args) || null
420
+ getTaskContext: (...args) => telegramTarget.current.getTaskContext?.(...args) || null,
421
+ getAgentTaskExecution: (...args) => telegramTarget.current.getAgentTaskExecution?.(...args) || null
422
422
  };
423
423
  const assertAccess = () => accessGuardTarget.current();
424
424
  const customTools = guardTools([
@@ -440,8 +440,7 @@ export class AgentManager {
440
440
  cwd: policy.workspaceDir,
441
441
  agentDir: arisaHomeDir,
442
442
  resourceLoader,
443
- authStorage,
444
- modelRegistry,
443
+ modelRuntime,
445
444
  model,
446
445
  thinkingLevel,
447
446
  tools: policy.tools,
@@ -450,8 +449,8 @@ export class AgentManager {
450
449
  settingsManager,
451
450
  sessionManager
452
451
  });
453
- const speedController = createModelSpeedController(session.agent.streamFn, speed);
454
- session.agent.streamFn = speedController.streamFn;
452
+ const speedController = createModelSpeedController(session.agent.streamFunction, speed);
453
+ session.agent.streamFunction = speedController.streamFn;
455
454
 
456
455
  if (!hasExistingSession) {
457
456
  this.logger?.log("agent", `created new session for chat ${sessionKey}`);
@@ -479,7 +478,7 @@ export class AgentManager {
479
478
 
480
479
  async getAvailableModels(chatId) {
481
480
  const { listProviderModels } = await import("./pi-runtime.js");
482
- const runtime = createPiRuntime({ provider: this.config.pi.provider, apiKey: this.config.pi.apiKey });
481
+ const runtime = await createPiRuntime({ provider: this.config.pi.provider, apiKey: this.config.pi.apiKey });
483
482
  return listProviderModels(this.config.pi.provider, runtime);
484
483
  }
485
484
 
@@ -33,8 +33,8 @@ export function getPiAuthIssue(error) {
33
33
  return null;
34
34
  }
35
35
 
36
- export function getPiAuthStatus(config, chatId = null) {
37
- const runtime = createPiRuntime({
36
+ export async function getPiAuthStatus(config, chatId = null) {
37
+ const runtime = await createPiRuntime({
38
38
  provider: config.pi.provider,
39
39
  apiKey: config.pi.apiKey
40
40
  });
@@ -51,8 +51,8 @@ export function getPiAuthStatus(config, chatId = null) {
51
51
  };
52
52
  }
53
53
 
54
- export function buildPiAuthTelegramMessage({ config, chatId = null, issue = null, verified = false }) {
55
- const status = getPiAuthStatus(config, chatId);
54
+ export async function buildPiAuthTelegramMessage({ config, chatId = null, issue = null, verified = false }) {
55
+ const status = await getPiAuthStatus(config, chatId);
56
56
  let title = `Pi authentication status for ${status.provider}/${status.model}.`;
57
57
  if (issue) {
58
58
  title = `Pi authentication needs attention for ${status.provider}/${status.model}.`;
@@ -95,8 +95,8 @@ export function buildPiAuthTelegramMessage({ config, chatId = null, issue = null
95
95
  return lines.join("\n");
96
96
  }
97
97
 
98
- export function buildPiAuthRecoveryBlockedMessage({ config, chatId = null, issue = null, renewalActive = false }) {
99
- const status = getPiAuthStatus(config, chatId);
98
+ export async function buildPiAuthRecoveryBlockedMessage({ config, chatId = null, issue = null, renewalActive = false }) {
99
+ const status = await getPiAuthStatus(config, chatId);
100
100
  const lines = [
101
101
  `Pi authentication is not ready for ${status.provider}/${status.model}.`,
102
102
  "I did not send your message to the agent."
@@ -1,4 +1,4 @@
1
- export const MODEL_SPEEDS = Object.freeze([1, 1.5]);
1
+ export const MODEL_SPEEDS = Object.freeze([1, 1.5]);
2
2
 
3
3
  export function normalizeModelSpeed(speed) {
4
4
  const value = Number(speed);
@@ -17,6 +17,7 @@ export function modelSupportsSpeed(model) {
17
17
  || model.id === "gpt-5.5"
18
18
  || model.id === "gpt-5.6"
19
19
  || model.id.startsWith("gpt-5.6-")
20
+ || model.id === "gpt-6-astra"
20
21
  );
21
22
  }
22
23
 
@@ -40,6 +41,7 @@ export function createModelSpeedController(streamFn, initialSpeed) {
40
41
  speed = normalizeModelSpeed(nextSpeed);
41
42
  },
42
43
  streamFn(model, context, options) {
44
+ if (!modelSupportsSpeed(model)) return streamFn(model, context, options);
43
45
  const serviceTier = speedToServiceTier(speed);
44
46
  const onPayload = options?.onPayload;
45
47
  return streamFn(model, context, {
@@ -1,13 +1,6 @@
1
- import { AuthStorage } from "@earendil-works/pi-coding-agent";
2
- import { piAuthFile } from "../../platform/paths.js";
1
+ import { createPiRuntime, supportsProviderOAuth } from "./pi-runtime.js";
3
2
 
4
3
  export function createPiOAuthLogin({ provider, onAuth, onDeviceCode, onPrompt, onProgress, onSelect } = {}) {
5
- const authStorage = AuthStorage.create(piAuthFile);
6
- const oauthProvider = authStorage.getOAuthProviders().find((item) => item.id === provider);
7
- if (!oauthProvider) {
8
- throw new Error(`No internal OAuth login flow is available for ${provider}.`);
9
- }
10
-
11
4
  let resolveManualCode;
12
5
  const manualCodePromise = new Promise((resolve) => {
13
6
  resolveManualCode = resolve;
@@ -15,7 +8,6 @@ export function createPiOAuthLogin({ provider, onAuth, onDeviceCode, onPrompt, o
15
8
 
16
9
  const controller = {
17
10
  provider,
18
- oauthProvider,
19
11
  manualInputRequested: false,
20
12
  submitManualCode(value) {
21
13
  if (!resolveManualCode) return false;
@@ -31,25 +23,33 @@ export function createPiOAuthLogin({ provider, onAuth, onDeviceCode, onPrompt, o
31
23
  promise: null
32
24
  };
33
25
 
34
- controller.promise = authStorage.login(provider, {
35
- onAuth: async (params) => {
36
- await onAuth?.({ ...params, controller });
37
- },
38
- onDeviceCode: async (params) => {
39
- await onDeviceCode?.({ ...params, controller });
40
- },
41
- onPrompt: async (params) => {
42
- if (!onPrompt) return "";
43
- return onPrompt({ ...params, controller });
44
- },
45
- onProgress: (message) => {
46
- onProgress?.(message);
47
- },
48
- onSelect: async (params) => {
49
- if (!onSelect) return params.options?.[0]?.id;
50
- return onSelect({ ...params, controller });
51
- },
52
- onManualCodeInput: () => controller.waitForManualCode()
26
+ controller.promise = createPiRuntime().then(async (runtime) => {
27
+ if (!supportsProviderOAuth(provider, runtime)) {
28
+ throw new Error(`No internal OAuth login flow is available for ${provider}.`);
29
+ }
30
+ let notifications = Promise.resolve();
31
+ let notificationError;
32
+ const credential = await runtime.login(provider, "oauth", {
33
+ notify(event) {
34
+ notifications = notifications.then(async () => {
35
+ if (event.type === "auth_url") await onAuth?.({ ...event, controller });
36
+ else if (event.type === "device_code") await onDeviceCode?.({ ...event, controller });
37
+ else await onProgress?.(event.message);
38
+ }).catch((error) => { notificationError = error; });
39
+ },
40
+ async prompt(params) {
41
+ await notifications;
42
+ if (notificationError) throw notificationError;
43
+ if (params.type === "select") {
44
+ return onSelect ? onSelect({ ...params, controller }) : params.options?.[0]?.id;
45
+ }
46
+ if (params.type === "manual_code") return controller.waitForManualCode();
47
+ return onPrompt ? onPrompt({ ...params, controller }) : "";
48
+ }
49
+ });
50
+ await notifications;
51
+ if (notificationError) throw notificationError;
52
+ return credential;
53
53
  }).finally(() => {
54
54
  controller.submitManualCode("");
55
55
  });
@@ -47,6 +47,7 @@ export function createPiCapabilityTools({ capabilityService, telegram, chatId, p
47
47
  context: {
48
48
  ...baseContext,
49
49
  taskContext: telegram.getTaskContext(),
50
+ agentTaskExecution: telegram.getAgentTaskExecution?.() || null,
50
51
  ...context
51
52
  }
52
53
  });
@@ -1,34 +1,29 @@
1
- import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
1
+ import { ModelRuntime } from "@earendil-works/pi-coding-agent";
2
2
  import { piAuthFile } from "../../platform/paths.js";
3
3
 
4
4
  function compareText(a, b) {
5
5
  return a.localeCompare(b, undefined, { sensitivity: "base", numeric: true });
6
6
  }
7
7
 
8
- export function createPiRuntime({ provider, apiKey } = {}) {
9
- const authStorage = AuthStorage.create(piAuthFile);
8
+ export async function createPiRuntime({ provider, apiKey } = {}) {
9
+ const runtime = await ModelRuntime.create({ authPath: piAuthFile });
10
10
  if (provider && apiKey) {
11
- authStorage.setRuntimeApiKey(provider, apiKey);
11
+ await runtime.setRuntimeApiKey(provider, apiKey);
12
12
  }
13
- const modelRegistry = ModelRegistry.create(authStorage);
14
- const oauthProviders = authStorage.getOAuthProviders();
15
- return { authStorage, modelRegistry, oauthProviders };
13
+ return runtime;
16
14
  }
17
15
 
18
- export function hasProviderAuth(provider, { authStorage, modelRegistry }) {
19
- return modelRegistry.hasConfiguredAuth(provider) || authStorage.hasAuth(provider);
16
+ export function hasProviderAuth(provider, runtime) {
17
+ return runtime.getProviderAuthStatus(provider).configured;
20
18
  }
21
19
 
22
- export function supportsProviderOAuth(provider, { oauthProviders }) {
23
- return oauthProviders.some((item) => item.id === provider);
20
+ export function supportsProviderOAuth(provider, runtime) {
21
+ return Boolean(runtime.getProvider(provider)?.auth.oauth);
24
22
  }
25
23
 
26
- export function listPiProviders(runtime = createPiRuntime()) {
27
- const { modelRegistry, oauthProviders } = runtime;
28
- const allModels = modelRegistry.getAll();
29
- const oauthIds = new Set(oauthProviders.map((item) => item.id));
24
+ export function listPiProviders(runtime) {
30
25
  const counts = new Map();
31
- for (const model of allModels) {
26
+ for (const model of runtime.getModels()) {
32
27
  counts.set(model.provider, (counts.get(model.provider) || 0) + 1);
33
28
  }
34
29
 
@@ -36,7 +31,7 @@ export function listPiProviders(runtime = createPiRuntime()) {
36
31
  .map((provider) => ({
37
32
  provider,
38
33
  authConfigured: hasProviderAuth(provider, runtime),
39
- supportsOAuth: oauthIds.has(provider),
34
+ supportsOAuth: supportsProviderOAuth(provider, runtime),
40
35
  modelCount: counts.get(provider) || 0
41
36
  }))
42
37
  .sort((a, b) => {
@@ -46,10 +41,8 @@ export function listPiProviders(runtime = createPiRuntime()) {
46
41
  });
47
42
  }
48
43
 
49
- export function listProviderModels(provider, runtime = createPiRuntime()) {
50
- return runtime.modelRegistry
51
- .getAll()
52
- .filter((model) => model.provider === provider)
44
+ export function listProviderModels(provider, runtime) {
45
+ return [...runtime.getModels(provider)]
53
46
  .sort((a, b) => compareText(a.name || a.id, b.name || b.id));
54
47
  }
55
48
 
@@ -48,6 +48,17 @@ function normalizeAcknowledgement(value) {
48
48
  return acknowledgement;
49
49
  }
50
50
 
51
+ function recordAgentTaskAuthBlock(execution, toolName, result) {
52
+ if (!execution || execution.blockedAuth || result?.ok !== false || result?.status !== "blocked_auth") return;
53
+ execution.blockedAuth = {
54
+ toolName,
55
+ error: String(result.error || `${toolName} authentication is required`).slice(0, 1_000),
56
+ resolution: result.resolution && typeof result.resolution === "object"
57
+ ? structuredClone(result.resolution)
58
+ : {}
59
+ };
60
+ }
61
+
51
62
  function inferDeliveryMethod(artifact) {
52
63
  if (artifact.kind === "audio" || (artifact.mimeType || "").startsWith("audio/")) return "audio";
53
64
  if (artifact.kind === "image" || (artifact.mimeType || "").startsWith("image/")) return "photo";
@@ -178,6 +189,19 @@ export function createCapabilityService({
178
189
  if (!toolExecutor?.runTool) throw new Error("tools.run requires toolExecutor");
179
190
  const scopedChatId = requireChatId(chatId, method);
180
191
  const targetToolName = requireString(params.name, "name");
192
+ const blocked = context.agentTaskExecution?.blockedAuth;
193
+ if (blocked) {
194
+ return {
195
+ ok: false,
196
+ status: "blocked_prerequisite",
197
+ error: `Authentication for ${blocked.toolName} is blocking this scheduled task.`,
198
+ resolution: {
199
+ type: "blocked_prerequisite",
200
+ prerequisiteStatus: "blocked_auth",
201
+ toolName: blocked.toolName
202
+ }
203
+ };
204
+ }
181
205
  const chatArtifactStore = artifactStore.forChat(scopedChatId);
182
206
  const artifact = params.artifactId
183
207
  ? await chatArtifactStore.get(requireString(params.artifactId, "artifactId"))
@@ -197,6 +221,7 @@ export function createCapabilityService({
197
221
  chatId: scopedChatId,
198
222
  taskContext: context.taskContext || null
199
223
  });
224
+ recordAgentTaskAuthBlock(context.agentTaskExecution, targetToolName, result);
200
225
  if (params.deliver && result.output?.artifactId) {
201
226
  const generated = await chatArtifactStore.get(result.output.artifactId);
202
227
  if (generated?.path) {
@@ -177,7 +177,8 @@ function normalizeAuthResolution(resolution = {}) {
177
177
  ? structuredClone(value.probeArgs)
178
178
  : {};
179
179
  if (JSON.stringify(probeArgs).length > 4_096) throw new Error("Authentication probe arguments are too large");
180
- return { retryAfterSeconds, probeArgs };
180
+ const toolName = typeof value.toolName === "string" ? value.toolName.trim().slice(0, 128) : "";
181
+ return { retryAfterSeconds, probeArgs, ...(toolName ? { toolName } : {}) };
181
182
  }
182
183
 
183
184
  function failTask(task, error) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 1,
3
3
  "repository": "https://github.com/clasen/Arisa.git",
4
- "commit": "84b8728dea97871bccc5f9f3c96bbdd876e3766e",
4
+ "commit": "2256f9e19f26f23826b9a9062d3a9643b511bb3c",
5
5
  "tools": {
6
6
  "audio-extractor": {
7
7
  "version": null,
@@ -13,10 +13,11 @@
13
13
  }
14
14
  },
15
15
  "browser-session-bridge": {
16
- "version": "0.2.3",
16
+ "version": "0.2.5",
17
17
  "files": {
18
- "bridge-server.js": "7fb628cba4d68fad99ae4dfdc5fab1afa904656a15f336878611ce504e0b89bf",
19
- "chrome-web-store.js": "f7a58df8c3a68335e78f965ebbd6d64ed60d7c78dab255cc9200735b9a2722e7",
18
+ "README.md": "79cb347ead539309429eca19ba6e9c472e4790ec1ab39a20bba71a4149f61f15",
19
+ "bridge-server.js": "03722a2657ba74bf34de9cae683b8f23242657da87c05771dd413a38fb446eca",
20
+ "chrome-web-store.js": "4b588d1288dee754c5d8afd609b8c1f67f73d23de7dda247b7a2ff8b68f7ef60",
20
21
  "config.js": "45c8e9e9a159b9125d6ea3458c616926c2ba2b5327fdfd750aa05316d3ce5af8",
21
22
  "extension/icons/icon-128.png": "a55af49bb570bd5471fc0a2e15a6bcaf3f76a2c5e7439f16bb1829682b343380",
22
23
  "extension/icons/icon-16.png": "a4aedb49e2227222a68dc56455812a9e17938fd197b1f30268f02d6c9f7bf95e",
@@ -31,24 +32,26 @@
31
32
  "extension/site-permissions.js": "83f9aa4d0295318fc730bd561c2db9d1aacf36152319090e99d12f62deea11ad",
32
33
  "index.js": "c01a6b825da4587a550ecec560a558cc6736200e73b6831f5919000c7b81679d",
33
34
  "lightpanda-session.js": "57c713dafac531617d7285122b2098c1e0b2f334e43144632f2b1fc79405f789",
34
- "package-lock.json": "db39f00e7849631f93050d93670c47797e5d0732330cc0f496c3014c426a94ed",
35
- "package.json": "7ea065a7ace16cc51ffd18a07924e42d4cf92be01e43c37f1620bff756f43283",
36
- "README.md": "79cb347ead539309429eca19ba6e9c472e4790ec1ab39a20bba71a4149f61f15",
35
+ "package-lock.json": "b97f5a333df234fecde788d0f90b620d39e02fee6079c1b4347baaabd8010b1b",
36
+ "package.json": "5c9edd6155b6b4868cc87d474e808dfc23567bc312e0d1e0230d8f9f0a1cc081",
37
37
  "session-browser.js": "7af716a1c0d6793b82ebbaaf64ec3e8f73dfc52b3c9aceef2179d2d859e32a9c",
38
38
  "session-redaction.js": "c2393023c1d3b7634432606ad82a96d79c1f093d9b0a6440d955d0ae419c8393",
39
39
  "session-selection.js": "da5a4f55ccc8ba22791840943288e7aecacd730425c03f05c2bc10fd6a14341f",
40
- "session-store.js": "82562ab625f2e72d1b33ea6e59f0e71f3de10fbfedb42b7099e9b1f2e23086be",
41
- "test/device-enrollment.test.js": "53f9da425e506de265199a467ff16834fce9441b5482a0c99c7a5170cfd3e91d",
40
+ "session-store.js": "ee85e5b9696e542bb535a996743ddbbd2093fc66e18873a2f1c7a27707a83994",
41
+ "test/device-enrollment.test.js": "a4246f4cb19e959ef4b8a83f60664887b624526b0e5646e5ec1fdb93750082b0",
42
42
  "test/lightpanda-session.test.js": "1fa6c1693a5008c173ec6c5c97effe001b68c535c7a3d4530500c0c4b691c532",
43
43
  "test/onboarding-state.test.js": "889f7746bbdb51320e68447560459d2a5d812e4b135de08a7b6e94ef5a142250",
44
44
  "test/session-redaction.test.js": "e45b5cbd19eea7996d57141b5185c3a6e4c79989e4cb7253272fc66cd2cbd719",
45
- "test/session-refresh.test.js": "c619a3790d0f1ba9c6fcbd4509d96c43ee0d8c5a292382ffaf744defdc9c5cac",
45
+ "test/session-refresh.test.js": "ffa688433185c08696761f189df244ed9ac212731b012a3eb9a91da05b43dd56",
46
46
  "test/session-selection.test.js": "ee1a15d42b156403d46d789a3ecf0a9c8f0019a00ab908276297d031243a89f5",
47
47
  "test/session-send-state.test.js": "c8ccbdf0863c5de85f784e7e32436591fe2db16a2ef4c554f671c6352736d5b6",
48
48
  "test/site-permissions.test.js": "27c297475c38ee1cbe7c7df210c767c157e03ecd379cde99a1b502268bda56ab",
49
- "tool.manifest.json": "286bfce2e0770bf1f51decedcf974664cd184e1c146c4fdeb40500e346aa7856",
49
+ "tool.manifest.json": "820f6060f077b95c286168f175e5521bc67b043425cae69c5be40834d5016454",
50
50
  "web-store/listing.md": "3e6d7aab1f60142984c3f8c18d92bf23646dc901644c6b71bdb979802bcf320c",
51
- "web-store/privacy-policy.md": "3e92198fbf80196a044c1d58d83577d959e91136302f994e3ffe1327013ebda8"
51
+ "web-store/privacy-policy.md": "eaaaa6066b36ef56896321d62b6ac4596d62104a0591d4edceb8c6040c47fd5c"
52
+ },
53
+ "toolDependencies": {
54
+ "lightpanda-browser": "^0.11.5"
52
55
  }
53
56
  },
54
57
  "campaign-draft-runner": {
@@ -115,6 +118,7 @@
115
118
  "creator-scout": {
116
119
  "version": "1.4.0",
117
120
  "files": {
121
+ "README.md": "6895b2c0cc3a230ddf3f59f1c4670b12070464f8e742bfdf40a04120a7fefaea",
118
122
  "config.js": "bab728665650b986c0eaef8e1be1c259ec42b1f83df4217c9780f5468d3c7666",
119
123
  "index.js": "a544e5dbac9cb92e996c2b07690a18481a20b8b10c13c397412581ec9ac6bb04",
120
124
  "outcome-contract.js": "5685bd8fbe4fcb608ee43a0148201206283013c1a60855c974a928c1d312480a",
@@ -122,13 +126,16 @@
122
126
  "package.json": "19c61d77ec90fce64d1a3baa1acc5b29af23f7c0574964504bc69b19e38aa34f",
123
127
  "panda-results.js": "24a31263b4a03e2c2719d9c54be7b5c022b17fb7dcb249eed33b93882518145b",
124
128
  "panda-session.js": "69878ff01bfbf26afe4db0e2e6489b211e3aca100ba5353befefaea009636bb5",
125
- "README.md": "6895b2c0cc3a230ddf3f59f1c4670b12070464f8e742bfdf40a04120a7fefaea",
126
129
  "reference-match.js": "5ceb71bfe57763258d89c60936bb7e5b3166b6aa7127f9d2f8da49f01298f46b",
127
130
  "test/outcome-contract.test.js": "dda85d1f56880b30d7fad3e8a27aacbb0808d91fc0addac6e0c38f9f0c4849bf",
128
131
  "test/panda-results.test.js": "b918d6341251822292fe3e375ab66694a0f71f3c7a24e91be263ee36e5f3e92c",
129
132
  "test/panda-session.test.js": "6cfa4e0543fab77c502c1103c60d8cb7d16040770e7aa5c034a47e0292de8521",
130
133
  "test/reference-match.test.js": "38572ee3756f4ff0b0c61942dda0a19c9d06697826051cf0924dd3c47fc99b67",
131
134
  "tool.manifest.json": "5368082b6808dc9b5966a46afcc6042cc82aabef0cd55ed65b4e783a4cb2579e"
135
+ },
136
+ "toolDependencies": {
137
+ "lightpanda-browser": "^0.11.4",
138
+ "browser-session-bridge": "^0.1.3"
132
139
  }
133
140
  },
134
141
  "file-document": {
@@ -177,27 +184,27 @@
177
184
  "lightpanda-browser": {
178
185
  "version": "0.11.5",
179
186
  "files": {
187
+ "BENCHMARK.md": "9c732c65f6d8bceb4e73c1a03d298d5140d919f50269f982bd0ec6c1b21fa8b6",
188
+ "COMPATIBILITY-MIGRATION.md": "230e12e8ddac837b7772519693e530c43d2158b69c671036bf246fb3a9e35561",
189
+ "LIMITS.md": "6c0ec9624c76de8ddf09b82a4da1dba1b89a48a1f0e71a083ffbcf7a3d5401fb",
190
+ "README.md": "c79a9a24d2fe804a7ce3e160e8308b1ac0039461cbfd012347aaa61f841f5fed",
180
191
  "action-policy.js": "66c6ad39f65378ccf8ed54177f5a3665e23ef82818c30fb05d28cd58cba9b2ab",
181
192
  "authenticated-profile.js": "2bbb96c4d25a108c44256514c1c9b4e61e1f125e470ab35c5e02515216cd1b33",
182
193
  "benchmark-latest.json": "c5524e6d42479578579fd7db0e50857ff0831ca219e611b821ad1e0a4fade303",
183
194
  "benchmark-policy.js": "2c3763d7f327293c9d54ca24da9e65b94dc304af44908c1e196a4af45ed49a89",
184
- "BENCHMARK.md": "9c732c65f6d8bceb4e73c1a03d298d5140d919f50269f982bd0ec6c1b21fa8b6",
185
195
  "binary.js": "accd3f1f536ae7ceee4dbfcee2de9ac56fc1ae343656238d62003233417257f1",
186
196
  "browser-operation.js": "51384d146d45fda8c672d3d6672fa223b715ad40c3c5b5878719e9df38151592",
187
197
  "capture.js": "b68b198d494c762822c6da079a556dd3463e681557f2abef1387d9cd41abaf4c",
188
- "COMPATIBILITY-MIGRATION.md": "230e12e8ddac837b7772519693e530c43d2158b69c671036bf246fb3a9e35561",
189
198
  "config.js": "d08eb436df15540a53b02cf72e117c7fc8ead80195dbd53764a17598c9e565c5",
190
199
  "daemon-service.js": "10e70ed64f1fe8c7660044f6ce24e78d01da75a50322bfc08f42248c14ad5226",
191
200
  "index.js": "5fc54aec13fb27c6b55e20aed132853b79c44041f45ea4b0f4b47b00c205da16",
192
201
  "limit-suite-latest.json": "3d30f958d2d6c1e9dfcaf53e40a401ae288bf264a97ba6c3b64a25a08031feb0",
193
202
  "limit-suite-policy.js": "61440ee2e7f557ab2f3c74f8ef4ec2ec85fd2fb7fc53a4121e1f0d066670ea17",
194
- "LIMITS.md": "6c0ec9624c76de8ddf09b82a4da1dba1b89a48a1f0e71a083ffbcf7a3d5401fb",
195
203
  "mcp-session.js": "cd4a1e6d3c9d80c399fda8f313d69e38fa22a9b24789d7919832a56df7dc90c2",
196
204
  "output-bounds.js": "08ab730d0d8722c5e0e761911a509653dd23d8eb4d8c2abf2d9c5e8432870bdd",
197
205
  "package-lock.json": "815dfdb89ce94b543e520955480e322438abd2b71fad4c4ddd699838b8622b65",
198
206
  "package.json": "934ae0f55d1baea305c28f12c0c9faccdd864244d899663c96f9083d96442841",
199
207
  "process-metrics.js": "e39d2980abb581ca0b917d0d33a1d71922ce49b679a7e96cf16a6a66b81d879a",
200
- "README.md": "c79a9a24d2fe804a7ce3e160e8308b1ac0039461cbfd012347aaa61f841f5fed",
201
208
  "recipe-store.js": "358ac391ae86e0bfb82fc5b55bd08cfe3fd4fa56ac12a5ad4ad5abfa43c9a6c6",
202
209
  "scripts/benchmark.js": "f1bb939984460d84118317f9b4f811e0df80f590b0a441cd62a56eb97bb69b37",
203
210
  "scripts/install-lightpanda.js": "ba4a2f9e5ffae80b9375578731d68eff25997333cb9e3e443b155f7834948205",
@@ -255,6 +262,7 @@
255
262
  "master-slave": {
256
263
  "version": "0.1.9",
257
264
  "files": {
265
+ "README.md": "a75f87df7906fe143d2ecaddfe9263561db17436df7ec2c4a8d985e1e3e8996e",
258
266
  "batch-cancellation.js": "b9ca57dfcca4f1a672d5435536b7eb83547dba98ed3fd09f34376f1d995bb97f",
259
267
  "batch-runner.js": "97756a03b36278cd0315cc16da0c34a7821c322149c51ba6666f1c5081dbecbc",
260
268
  "chat-state-store.js": "50de39aa33432733bb688eb01968e314a32b169324a66d0f0089b2a19ed9c880",
@@ -271,7 +279,6 @@
271
279
  "master-domain.js": "10b7dfb43eb9939eb5baec54f742076cc73a2add6589a0ff57c51bc79c236faf",
272
280
  "network-session.js": "6ef332ef9694ff211f4aed1e8b6ff4df3614a1d4c63affe6fdd00409329ec431",
273
281
  "package.json": "774af304ec05a24461318172882a28373e568b5240d8eee9a31a286997b9a403",
274
- "README.md": "a75f87df7906fe143d2ecaddfe9263561db17436df7ec2c4a8d985e1e3e8996e",
275
282
  "remote-runtime.js": "d38b7a28f36e8f1be1d4826a056a03d0ebc2b9b17be277e010be25048797a562",
276
283
  "slave-operations.js": "5a8967e2006f3f30ee221614d25fbf7863ffd9c717fd7eeeb0ba981c8c8c367a",
277
284
  "state-store.js": "c56849a3f1b9c990128276e17963034a7836abacedc44f2e500d5732ebf9e451",
@@ -66,7 +66,7 @@ async function runInternalPiLogin(provider, { rl = null } = {}) {
66
66
 
67
67
  export async function collectCliBootstrapChoices({ telegramApiKey, rl, ask }) {
68
68
  const telegramMaxChatIds = Number(await ask("Maximum authorized chat IDs", "1"));
69
- const runtime = createPiRuntime();
69
+ const runtime = await createPiRuntime();
70
70
  const providers = sortBootstrapProviders(listPiProviders(runtime));
71
71
  console.log("\nAvailable Pi providers:");
72
72
  providers.forEach((item, index) => console.log(`${index + 1}. ${formatProviderOption(item)}`));
@@ -89,7 +89,7 @@ export async function collectCliBootstrapChoices({ telegramApiKey, rl, ask }) {
89
89
  while (true) {
90
90
  piApiKey = (await rl.question(`Pi API key for ${selectedProvider.provider} (optional): `)).trim();
91
91
  if (piApiKey) break;
92
- if (hasProviderAuth(selectedProvider.provider, createPiRuntime())) break;
92
+ if (hasProviderAuth(selectedProvider.provider, await createPiRuntime())) break;
93
93
  if (!providerSupportsOAuth) {
94
94
  console.log(`No existing Pi auth found for ${selectedProvider.provider}. This provider requires an API key.`);
95
95
  continue;
@@ -100,7 +100,7 @@ export async function collectCliBootstrapChoices({ telegramApiKey, rl, ask }) {
100
100
  } catch (error) {
101
101
  console.log(`Internal Pi login failed: ${error instanceof Error ? error.message : String(error)}`);
102
102
  }
103
- if (hasProviderAuth(selectedProvider.provider, createPiRuntime())) {
103
+ if (hasProviderAuth(selectedProvider.provider, await createPiRuntime())) {
104
104
  console.log(`Detected Pi auth for ${selectedProvider.provider}. Continuing bootstrap.`);
105
105
  break;
106
106
  }