storyboard-bridge 0.9.13 → 0.9.14

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 (2) hide show
  1. package/cdp_flow.py +28 -2
  2. package/package.json +1 -1
package/cdp_flow.py CHANGED
@@ -348,6 +348,10 @@ def load_flow(path, cli_vars):
348
348
  steps.append(("waitfor", sub(raw["xpath"])))
349
349
  elif do == "goto":
350
350
  steps.append(("goto", sub(raw["url"])))
351
+ elif do == "read":
352
+ steps.append(("read", sub(raw["xpath"]), raw.get("var", "")))
353
+ elif do == "ask":
354
+ steps.append(("ask", sub(raw["prompt"]), raw.get("var", "")))
351
355
  else:
352
356
  raise RuntimeError(f"flow step {i}: unknown 'do': {do!r}")
353
357
 
@@ -470,15 +474,19 @@ def main():
470
474
  json.dump({"tab_id": target_id, "context_id": ctx_id}, f)
471
475
  print(f"emitted tab/context ids to {args.emit}")
472
476
 
477
+ step_vars = {}
473
478
  for i, (kind, val) in enumerate(steps, 1):
474
479
  if kind == "type":
475
480
  shown = "***" if (len(val) > 2 and val[2]) else val[1]
476
481
  label = f"{val[0]} -> {shown}"
477
482
  else:
478
- label = val if isinstance(val, str) else " -> ".join(val)
483
+ label = val if isinstance(val, str) else " -> ".join(val[:1] if isinstance(val, tuple) else val)
479
484
  print(f"[{i}/{len(steps)}] {kind}: {label}")
480
485
  if kind == "type":
481
- step_type(page, val[0], val[1])
486
+ text_to_type = val[1]
487
+ for vname, vval in step_vars.items():
488
+ text_to_type = text_to_type.replace("{" + vname + "}", vval)
489
+ step_type(page, val[0], text_to_type)
482
490
  elif kind == "click":
483
491
  note = step_click(page, val)
484
492
  print(f" {note}")
@@ -490,6 +498,24 @@ def main():
490
498
  step_waitfor(page, val, timeout)
491
499
  elif kind == "goto":
492
500
  step_goto(page, val, timeout)
501
+ elif kind == "read":
502
+ xpath, var = val[0], val[1]
503
+ result = page.eval_js(f"document.evaluate({json.dumps(xpath)}, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue?.textContent || ''")
504
+ step_vars[var] = result
505
+ print(f" {var} = '{result[:50]}'")
506
+ elif kind == "ask":
507
+ prompt, var = val[0], val[1]
508
+ # Substitute variables in the prompt
509
+ ask_prompt = prompt
510
+ for vname, vval in step_vars.items():
511
+ ask_prompt = ask_prompt.replace("{" + vname + "}", vval)
512
+ try:
513
+ result = subprocess.run(["claude", "-p", ask_prompt], capture_output=True, text=True, timeout=30).stdout.strip()
514
+ step_vars[var] = result
515
+ print(f" {var} = '{result[:50]}'")
516
+ except Exception as e:
517
+ print(f" (ask failed: {e})", file=sys.stderr)
518
+ step_vars[var] = ""
493
519
  time.sleep(delay)
494
520
  print("flow complete")
495
521
  if spawned_ctx and temp.get("dispose"):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "storyboard-bridge",
3
- "version": "0.9.13",
3
+ "version": "0.9.14",
4
4
  "description": "Desktop bridge that powers a hosted Storyboard AI webapp with your own local Claude Code / Gemini CLI login (no API key).",
5
5
  "type": "module",
6
6
  "bin": {