@quanta-intellect/vessel-browser 0.1.32 → 0.1.35

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.
@@ -137,7 +137,7 @@ const api = {
137
137
  return () => electron.ipcRenderer.removeListener(Channels.AI_STREAM_CHUNK, handler);
138
138
  },
139
139
  onStreamEnd: (cb) => {
140
- const handler = () => cb();
140
+ const handler = (_, status = "completed") => cb(status);
141
141
  electron.ipcRenderer.on(Channels.AI_STREAM_END, handler);
142
142
  return () => electron.ipcRenderer.removeListener(Channels.AI_STREAM_END, handler);
143
143
  },
@@ -1546,7 +1546,9 @@ const DEFAULT_RUNTIME_STATE = {
1546
1546
  actions: [],
1547
1547
  checkpoints: [],
1548
1548
  transcript: [],
1549
- mcpStatus: "stopped"
1549
+ mcpStatus: "stopped",
1550
+ flowState: null,
1551
+ taskTracker: null
1550
1552
  };
1551
1553
  const [runtimeState, setRuntimeState] = createSignal(
1552
1554
  DEFAULT_RUNTIME_STATE
@@ -2324,11 +2326,14 @@ const [hasFirstChunk, setHasFirstChunk] = createSignal(false);
2324
2326
  const [streamStartedAt, setStreamStartedAt] = createSignal(null);
2325
2327
  const [recentQueries, setRecentQueries] = createSignal([]);
2326
2328
  const [pendingQueries, setPendingQueries] = createSignal([]);
2329
+ const [pendingQueryActivities, setPendingQueryActivities] = createSignal([]);
2327
2330
  const [queueNotice, setQueueNotice] = createSignal(null);
2328
2331
  const [automationActivities, setAutomationActivities] = createSignal([]);
2329
2332
  let initialized$1 = false;
2330
2333
  let pendingDrainScheduled = false;
2331
2334
  let listenerCleanups = [];
2335
+ let pendingAutomationActivity = null;
2336
+ let activeAutomationActivityId = null;
2332
2337
  function trimMessages(next) {
2333
2338
  return next.length > MAX_MESSAGE_HISTORY ? next.slice(-MAX_MESSAGE_HISTORY) : next;
2334
2339
  }
@@ -2348,17 +2353,23 @@ async function dispatchQuery(prompt) {
2348
2353
  const result = await window.vessel.ai.query(prompt, buildHistory());
2349
2354
  return result.accepted;
2350
2355
  }
2351
- async function dispatchQueuedPrompt(prompt) {
2356
+ async function dispatchQueuedPrompt(prompt, activity) {
2357
+ pendingAutomationActivity = activity;
2352
2358
  const accepted = await dispatchQuery(prompt);
2353
2359
  if (!accepted) {
2360
+ pendingAutomationActivity = null;
2354
2361
  const queued = enqueuePendingPrompt(pendingQueries(), prompt, { atFront: true });
2355
2362
  setPendingQueries(queued.queue);
2356
2363
  setQueueNotice(queued.notice);
2364
+ if (queued.status === "queued") {
2365
+ setPendingQueryActivities((prev) => [activity, ...prev]);
2366
+ }
2357
2367
  }
2358
2368
  }
2359
2369
  function schedulePendingDrain() {
2360
2370
  if (pendingDrainScheduled || isStreaming()) return;
2361
2371
  if (pendingQueries().length === 0) {
2372
+ setPendingQueryActivities([]);
2362
2373
  setQueueNotice(null);
2363
2374
  return;
2364
2375
  }
@@ -2367,10 +2378,12 @@ function schedulePendingDrain() {
2367
2378
  pendingDrainScheduled = false;
2368
2379
  if (isStreaming()) return;
2369
2380
  const next = dequeuePendingPrompt(pendingQueries());
2381
+ const [nextActivity = null, ...remainingActivities] = pendingQueryActivities();
2370
2382
  setPendingQueries(next.queue);
2383
+ setPendingQueryActivities(remainingActivities);
2371
2384
  setQueueNotice(next.notice);
2372
2385
  if (next.nextPrompt) {
2373
- void dispatchQueuedPrompt(next.nextPrompt);
2386
+ void dispatchQueuedPrompt(next.nextPrompt, nextActivity);
2374
2387
  }
2375
2388
  });
2376
2389
  }
@@ -2386,14 +2399,35 @@ function init$1() {
2386
2399
  setIsStreaming(true);
2387
2400
  setHasFirstChunk(false);
2388
2401
  setStreamStartedAt(Date.now());
2402
+ if (pendingAutomationActivity) {
2403
+ const activity = pendingAutomationActivity;
2404
+ activeAutomationActivityId = activity.id;
2405
+ setAutomationActivities(
2406
+ (prev) => startAutomationActivity(prev, {
2407
+ id: activity.id,
2408
+ source: "scheduled",
2409
+ title: activity.title,
2410
+ icon: activity.icon,
2411
+ status: "running",
2412
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
2413
+ })
2414
+ );
2415
+ pendingAutomationActivity = null;
2416
+ }
2389
2417
  }));
2390
2418
  listenerCleanups.push(window.vessel.ai.onStreamChunk((chunk) => {
2391
2419
  if (!hasFirstChunk()) {
2392
2420
  setHasFirstChunk(true);
2393
2421
  }
2394
2422
  setStreamingText((prev) => prev + chunk);
2423
+ if (activeAutomationActivityId) {
2424
+ const activityId = activeAutomationActivityId;
2425
+ setAutomationActivities(
2426
+ (prev) => appendAutomationActivityChunk(prev, activityId, chunk)
2427
+ );
2428
+ }
2395
2429
  }));
2396
- listenerCleanups.push(window.vessel.ai.onStreamEnd(() => {
2430
+ listenerCleanups.push(window.vessel.ai.onStreamEnd((status) => {
2397
2431
  const finalText = streamingText();
2398
2432
  if (finalText) {
2399
2433
  setMessages((prev) => {
@@ -2401,6 +2435,19 @@ function init$1() {
2401
2435
  return trimMessages(next);
2402
2436
  });
2403
2437
  }
2438
+ if (activeAutomationActivityId) {
2439
+ const activityId = activeAutomationActivityId;
2440
+ setAutomationActivities(
2441
+ (prev) => finishAutomationActivity(
2442
+ prev,
2443
+ activityId,
2444
+ status,
2445
+ (/* @__PURE__ */ new Date()).toISOString()
2446
+ )
2447
+ );
2448
+ activeAutomationActivityId = null;
2449
+ }
2450
+ pendingAutomationActivity = null;
2404
2451
  setStreamingText("");
2405
2452
  setIsStreaming(false);
2406
2453
  setHasFirstChunk(false);
@@ -2426,6 +2473,32 @@ function init$1() {
2426
2473
  }
2427
2474
  function useAI() {
2428
2475
  init$1();
2476
+ const query = async (prompt, activity = null) => {
2477
+ recordRecentQuery(prompt);
2478
+ if (isStreaming()) {
2479
+ const queued = enqueuePendingPrompt(pendingQueries(), prompt);
2480
+ setPendingQueries(queued.queue);
2481
+ setQueueNotice(queued.notice);
2482
+ if (queued.status === "queued") {
2483
+ setPendingQueryActivities((prev) => [...prev, activity]);
2484
+ }
2485
+ return queued.status;
2486
+ }
2487
+ setQueueNotice(null);
2488
+ pendingAutomationActivity = activity;
2489
+ const accepted = await dispatchQuery(prompt);
2490
+ if (!accepted) {
2491
+ pendingAutomationActivity = null;
2492
+ const queued = enqueuePendingPrompt(pendingQueries(), prompt, { atFront: true });
2493
+ setPendingQueries(queued.queue);
2494
+ setQueueNotice(queued.notice);
2495
+ if (queued.status === "queued") {
2496
+ setPendingQueryActivities((prev) => [activity, ...prev]);
2497
+ }
2498
+ return queued.status;
2499
+ }
2500
+ return "started";
2501
+ };
2429
2502
  return {
2430
2503
  messages,
2431
2504
  streamingText,
@@ -2438,39 +2511,28 @@ function useAI() {
2438
2511
  pendingQueryCount: () => pendingQueries().length,
2439
2512
  pendingQueryLimit: MAX_PENDING_QUERIES,
2440
2513
  queueNotice,
2441
- query: async (prompt) => {
2442
- recordRecentQuery(prompt);
2443
- if (isStreaming()) {
2444
- const queued = enqueuePendingPrompt(pendingQueries(), prompt);
2445
- setPendingQueries(queued.queue);
2446
- setQueueNotice(queued.notice);
2447
- return queued.status;
2448
- }
2449
- setQueueNotice(null);
2450
- const accepted = await dispatchQuery(prompt);
2451
- if (!accepted) {
2452
- const queued = enqueuePendingPrompt(pendingQueries(), prompt, { atFront: true });
2453
- setPendingQueries(queued.queue);
2454
- setQueueNotice(queued.notice);
2455
- return queued.status;
2456
- }
2457
- return "started";
2458
- },
2514
+ query,
2515
+ runAutomationPrompt: async (prompt, activity) => query(prompt, activity),
2459
2516
  cancel: () => window.vessel.ai.cancel(),
2460
2517
  removePendingQuery: (index) => {
2461
2518
  const next = removePendingPrompt(pendingQueries(), index);
2462
2519
  setPendingQueries(next.queue);
2520
+ setPendingQueryActivities(
2521
+ (prev) => prev.filter((_, itemIndex) => itemIndex !== index)
2522
+ );
2463
2523
  setQueueNotice(next.notice);
2464
2524
  },
2465
2525
  clearPendingQueries: () => {
2466
2526
  const next = clearPendingPromptQueue();
2467
2527
  setPendingQueries(next.queue);
2528
+ setPendingQueryActivities([]);
2468
2529
  setQueueNotice(next.notice);
2469
2530
  },
2470
2531
  clearHistory: () => {
2471
2532
  setMessages([]);
2472
2533
  const next = clearPendingPromptQueue();
2473
2534
  setPendingQueries(next.queue);
2535
+ setPendingQueryActivities([]);
2474
2536
  setQueueNotice(next.notice);
2475
2537
  }
2476
2538
  };
@@ -4440,6 +4502,11 @@ var Zap = (props) => createComponent(Icon_default, mergeProps(props, {
4440
4502
  name: "zap"
4441
4503
  }));
4442
4504
  var zap_default = Zap;
4505
+ const BUNDLED_KIT_IDS = /* @__PURE__ */ new Set([
4506
+ "research-collect",
4507
+ "price-scout",
4508
+ "form-filler"
4509
+ ]);
4443
4510
  const BUNDLED_KITS = [
4444
4511
  {
4445
4512
  id: "research-collect",
@@ -4571,6 +4638,13 @@ Steps:
4571
4638
  }
4572
4639
  ];
4573
4640
  function renderKitPrompt(kit, values) {
4641
+ for (const input of kit.inputs) {
4642
+ if (input.required && !values[input.key]?.trim()) {
4643
+ console.warn(
4644
+ `[automation-kits] Required field "${input.key}" is empty for kit "${kit.id}".`
4645
+ );
4646
+ }
4647
+ }
4574
4648
  return kit.promptTemplate.replace(
4575
4649
  /\{\{(\w+)\}\}/g,
4576
4650
  (_, key) => values[key] ?? ""
@@ -4599,7 +4673,6 @@ const KitIcon = (props) => {
4599
4673
  }
4600
4674
  });
4601
4675
  };
4602
- const BUNDLED_KIT_IDS = new Set(BUNDLED_KITS.map((k) => k.id));
4603
4676
  const DAY_NAMES = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
4604
4677
  function formatScheduleLabel(job) {
4605
4678
  const {
@@ -4650,7 +4723,7 @@ function toLocalDateTimeInput(iso) {
4650
4723
  }
4651
4724
  const AutomationTab = (props) => {
4652
4725
  const {
4653
- query,
4726
+ runAutomationPrompt,
4654
4727
  isStreaming: isStreaming2,
4655
4728
  automationActivities: automationActivities2
4656
4729
  } = useAI();
@@ -4739,9 +4812,15 @@ const AutomationTab = (props) => {
4739
4812
  const kit = selectedKit();
4740
4813
  if (!kit || !canRun()) return;
4741
4814
  const prompt = renderKitPrompt(kit, fieldValues());
4815
+ const activityId = `adhoc:${kit.id}:${Date.now()}`;
4816
+ const result = await runAutomationPrompt(prompt, {
4817
+ id: activityId,
4818
+ title: kit.name,
4819
+ icon: kit.icon
4820
+ });
4821
+ if (result === "rejected") return;
4742
4822
  setSelectedKit(null);
4743
4823
  props.onRun();
4744
- await query(prompt);
4745
4824
  };
4746
4825
  const handleSchedule = async () => {
4747
4826
  const kit = selectedKit();
@@ -5,7 +5,7 @@
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; font-src 'self' data:;" />
7
7
  <title>Vessel</title>
8
- <script type="module" crossorigin src="./assets/index-DVD9XuhC.js"></script>
8
+ <script type="module" crossorigin src="./assets/index-IYqP5OYH.js"></script>
9
9
  <link rel="stylesheet" crossorigin href="./assets/index-eS3ccAls.css">
10
10
  </head>
11
11
  <body>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@quanta-intellect/vessel-browser",
3
3
  "mcpName": "io.github.unmodeled-tyler/vessel-browser",
4
- "version": "0.1.32",
4
+ "version": "0.1.35",
5
5
  "description": "AI-native web browser runtime for autonomous agents with human supervision",
6
6
  "main": "./out/main/index.js",
7
7
  "bin": {