项目文件夹

文件
Saurav Panda 16c3729506 tasksquad domain skill: rename dir, replace fictional helper, fix compose snippet
- Move from top-level domain-skills/tasksquad.ai/ to the canonical
  agent-workspace/domain-skills/tasksquad-ai/ location, switching to
  kebab-case to match sibling dirs (booking-com, dev-to, archive-org).
- Replace find_text_coords(...) with self-contained inline Python
  helpers (_coords_by_text, _coords_by_selector) that wrap querySelector
  + getBoundingClientRect. find_text_coords does not exist in the
  harness or agent_helpers — every call site was a NameError waiting to
  happen.
- Fix the compose-task snippet: drop the dead subject_input = js(...)
  line, focus the subject input via _coords_by_selector before typing,
  and add a placeholder click for the agent dropdown item.
- Fix the polling-interval contradiction: the inbox section now defers
  to the gotchas, and the gotchas list the Free (5s) / Pro (2s) cadence
  in one place.
2026-05-04 11:32:28 -07:00

6.3 KiB

TaskSquad — Task Inbox

Field-tested against tasksquad.ai on 2026-05-03 using a logged-in Chrome session.

URL

https://tasksquad.ai/dashboard              # Inbox (default view)
https://tasksquad.ai/dashboard/<taskId>     # Task thread (individual task)

Inbox view

The inbox is the default view after sign-in. It shows a list of tasks assigned to agents in the currently selected project.

Task list

Tasks are rendered as rows. Each row shows:

  • Subject line
  • Agent name
  • Status badge
  • Relative timestamp

Status values

Status Meaning
pending Queued for the agent daemon
queued Agent is busy — task is waiting in line
running Agent is actively working
waiting_input Agent needs a reply from the user
done Completed successfully
failed Ended with an error
scheduled Will start at a future scheduled_at time
wrapping_up Running post-completion close steps

Filters

Two dropdowns appear above the task list:

Status (left): All / Pending / Queued / Running / Waiting / Done / Failed / Scheduled

Origin (right): All / System / Mine / From Note / Critique / Scheduled

  • "System" = tasks created by automated conveyors
  • "Mine" = tasks you composed yourself
  • "From Note" = tasks spawned from Notes
  • "Critique" = tasks that are note critiques

Both dropdowns use shadcn <Select>. Click the trigger to open, then click the item by text.

Refresh

A RefreshCw icon button sits next to the "Inbox" heading. Click it to reload the task list without full navigation. Alternatively, wait_for_load() after any state change — the app auto-polls when active tasks exist (interval depends on plan; see Gotchas).

Composing a new task

Click the "New message" button (top-right of Inbox). A dialog opens.

Dialog fields

Field Type Notes
Agent <Select> Required. Dropdown of agents in the current project.
Subject <input> Required. Short description of the task.
Message <textarea> Optional. Task body / detailed instructions.

Optional advanced toggles (revealed via UI controls):

  • Schedule: set a future delivery time
  • Auto-close: task closes automatically when the agent finishes
  • Save tokens: compress the task context (lite / full / ultra)
  • Close steps: newline-separated post-completion steps

Submit with the "Send" button inside the dialog.

import json

def _coords_by_text(label, tag="button"):
    """Find an element by exact innerText and return click coords, or raise."""
    sel = json.dumps(tag)
    txt = json.dumps(label)
    result = js(f"""
      var el = Array.from(document.querySelectorAll({sel}))
                .find(e => (e.innerText || "").trim() === {txt});
      if (!el) return null;
      var r = el.getBoundingClientRect();
      return JSON.stringify({{x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)}});
    """)
    if result is None:
        raise RuntimeError(f"{tag!r} with text {label!r} not found")
    p = json.loads(result)
    return p["x"], p["y"]

def _coords_by_selector(selector):
    """Find an element by CSS selector and return click coords, or raise."""
    sel = json.dumps(selector)
    result = js(f"""
      var el = document.querySelector({sel});
      if (!el) return null;
      var r = el.getBoundingClientRect();
      return JSON.stringify({{x: Math.round(r.x + r.width/2), y: Math.round(r.y + r.height/2)}});
    """)
    if result is None:
        raise RuntimeError(f"selector not found: {selector!r}")
    p = json.loads(result)
    return p["x"], p["y"]

# Open the compose dialog
click_at_xy(*_coords_by_text("New message"))
wait(1.0)  # let the dialog mount; agents may still be loading

# Open the agent <Select> trigger and pick an agent.
# The trigger renders the placeholder "Select agent…" until an agent is chosen.
click_at_xy(*_coords_by_text("Select agent…"))
wait(0.5)
# Then click the agent name from the opened dropdown:
click_at_xy(*_coords_by_text("YOUR_AGENT_NAME"))

# Focus the subject input, then type
click_at_xy(*_coords_by_selector('input[id="subject"]'))
type_text("Check the build status")

# (Optional) focus the message textarea and type the body
# click_at_xy(*_coords_by_selector('textarea'))
# type_text("Detailed instructions go here.")

# Submit
click_at_xy(*_coords_by_text("Send"))

Task thread

Clicking a task row opens the thread at /dashboard/<taskId>.

The thread is an email-style conversation. Messages alternate between:

  • User messages (right-aligned or labeled with sender name)
  • Agent messages (left-aligned)

Replying

When a task is in waiting_input status, a reply box appears at the bottom. Type your reply and press Enter or click the send button.

A scheduled reply pending delivery blocks the reply box — a cancel option appears.

Task actions

Actions available from the thread view (usually via icon buttons or a menu):

  • Close — mark the task done manually
  • Delete — permanently remove the task
  • Forward — reassign to a different agent (appears as "Forward to agent" with agent selector and optional instructions)

Gotchas

  • Inbox auto-polls while active tasks exist (pending / running / waiting_input). Free plan polls every 5 s, Pro every 2 s. For scraping, add a wait_for_load() between reads if statuses are changing.
  • queued is a derived client-side status — the server returns pending, but the UI shows queued when the target agent is itself running or waiting_input. Filter accordingly.
  • Task list is per-project. Switching projects (teams) reloads the list. The active project is stored in localStorage as tsq_team_id.
  • Dialog does not open until agents are loaded. If "Select agent…" placeholder is missing after clicking "New message", the agents list is still fetching — retry after a short wait.
  • Free plan project limit: free accounts have a project limit (currently 1).