taskuary 0.3.7.1__tar.gz → 0.3.7.2__tar.gz
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.
- {taskuary-0.3.7.1/taskuary.egg-info → taskuary-0.3.7.2}/PKG-INFO +30 -27
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/README.md +29 -26
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/pyproject.toml +1 -1
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/chatformat.py +17 -1
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/concierge.py +3 -1
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/doorway_browse.py +72 -9
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/lookups.py +12 -4
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/remote_assistant.py +53 -9
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/server.py +21 -3
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/settings_schema.json +2 -2
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/store.py +12 -6
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/terminal.py +2 -1
- taskuary-0.3.7.1/taskuary/web/assets/AssistantGame-0C4EbdNP.js → taskuary-0.3.7.2/taskuary/web/assets/AssistantGame-BZJj3XwN.js +3 -3
- taskuary-0.3.7.1/taskuary/web/assets/GameScene-VFVGUUWW.js → taskuary-0.3.7.2/taskuary/web/assets/GameScene-ATV2SyYO.js +1 -1
- taskuary-0.3.7.1/taskuary/web/assets/HubView-C3RE4gI3.js → taskuary-0.3.7.2/taskuary/web/assets/HubView-DtpvsbeL.js +1 -1
- taskuary-0.3.7.1/taskuary/web/assets/StudioScene-DbbMffmv.js → taskuary-0.3.7.2/taskuary/web/assets/StudioScene-D4IlNRXi.js +1 -1
- taskuary-0.3.7.1/taskuary/web/assets/TasksView-BE0ORh6n.js → taskuary-0.3.7.2/taskuary/web/assets/TasksView-B7m8zBYu.js +1 -1
- taskuary-0.3.7.1/taskuary/web/assets/index-BYDpTV3Z.js → taskuary-0.3.7.2/taskuary/web/assets/index-BKrB4ObA.js +14 -14
- taskuary-0.3.7.1/taskuary/web/assets/index-DzyUgP3W.css → taskuary-0.3.7.2/taskuary/web/assets/index-DUxLnhhx.css +1 -1
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/index.html +2 -2
- {taskuary-0.3.7.1 → taskuary-0.3.7.2/taskuary.egg-info}/PKG-INFO +30 -27
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary.egg-info/SOURCES.txt +8 -7
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_coder_session_continuity.py +16 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_continue_session.py +16 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_morning_line.py +2 -2
- taskuary-0.3.7.2/tests/test_phone_browse_pass.py +144 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/LICENSE +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/setup.cfg +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/__init__.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/acp.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/agents.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/aidefaults.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/aisetup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/alchemy.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/appfacts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/artifacts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/assistant.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/assistantblocks.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/autoreply.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/aws.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/azure.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/blackboard.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/brief.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/browserview.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/calendar.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/categories.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/chains.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/channels.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/chatservers.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/ci.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/cli.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/cli_connections.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/cli_install_terminal.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/cliinstall.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/climodels.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/clipool.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/clis.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/clisetup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/coder.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/compose.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/config.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/connectorcatalog.json +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/connectorcatalog.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/context.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/continuity.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/counsel.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/databases.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/db.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/demo.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/deps.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/desktop.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/devtools.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/digest.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/docsync.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/evalset.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/evening.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/files.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/funnel.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/funnel_presentation.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/funnel_selection.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/general.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/ghcloseout.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/github.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/guard.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/handbook.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/handraise.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/histgen.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/hooks.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/hub.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/images.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/imapmail.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/imessage.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/ingest.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/intacct.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/interview.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/invoice_workflow.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/jev.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/knowledge.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/lanes.json +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/learn.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/learnedgraph.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/linkedin.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/live.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/llm.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/logs.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/markets.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/mcp.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/messengers.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/msauth.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/mssql.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/operations.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/outbound.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/outbox.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/ownwork.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/playbooks.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/pm.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/policy.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/problems.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_all.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_inventory.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_membership.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_navigation.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_order.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_projection.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_rail.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_reads.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_startup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/processing_unread.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/projects.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/promptmap.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/proof.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/proposals.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/quickbooks.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/rank.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/redact.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/remind.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/reports.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/research.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/reshape.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/responder.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/retention.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/robinhood.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/routing.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/routingmemory.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/scopes.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/selfclose.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/semantic.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/senders.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/session_artifacts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/sessionfiles.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/settings_defaults.json +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/settings_schema.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/setup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/sharepoint.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/sheets.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/simplefin.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/skillimport.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/skills/soul-interview/SKILL.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/skills/taskuary-setup/SKILL.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/social.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/spawn.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/taskstate.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/teller.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/agent.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/analyst.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/coder.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/coordinator.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/counsel.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/digest.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.3.5.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.6.8.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.6.9-examples.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.6.9-remind.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.6.9.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/how-it-works.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/learned.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/marketer.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/playbook.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/profile.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/researcher.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/soul.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/style.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/trader.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/templates/triage.md +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/testing.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/toil.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/toolcatalog.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/treg.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/triage.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/triage_kind_rules.json +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/update.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/verdicts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/voice.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/wabridge.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/waitroom.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/walk.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/assets/RoundedBoxGeometry-BE4rf3sD.js +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/favicon.ico +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/favicon.png +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/walk/assistant.png +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/walk/board.png +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/walk/connections.png +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/walk/docs.png +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/walk/hub.png +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/walk/reports.png +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/walk/settings.png +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/web/walk/tasks.png +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/webguard.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/whatsapp/bridge.mjs +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/whatsapp/package.json +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/whatsapp/policy.mjs +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/whatsapp/poll.mjs +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/whatsapp/roster.mjs +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/whoami.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/witness.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/workerstate.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/workflows.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary/zoho.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary.egg-info/dependency_links.txt +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary.egg-info/entry_points.txt +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary.egg-info/requires.txt +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/taskuary.egg-info/top_level.txt +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_acp.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_advisor_idea_words.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_answer_route.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_answers_and_reminders.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_asking.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_environment.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_identity.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_profiles.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_reply.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_sentence.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_source.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_agent_wall.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_ai_defaults.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_aisetup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_alchemy.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_an_inbox_is_not_a_destination.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_answered_yourself.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_answers.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_api.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_api_worker_signals.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_app_uptime.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_appfacts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_approval_interrupt.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant_acts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant_blocks.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant_can_look_things_up.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant_doorways.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant_ideas.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant_notifications.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant_presentation.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant_reactions.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_assistant_verdicts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_async_triage.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_audit_chain.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_audit_fixes.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_auto_start.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_autoreply.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_aws_region.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_azure_discovery.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_banner_is_one_rule.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_blackboard.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_brain_layer.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_brain_reaches_the_session.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_browser_session.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_browser_workflow.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_browserview.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_button_promises.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_calendar.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_calendar_today.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_canvas_relay.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_canvas_sections.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_card_story_phone.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_categories.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cc.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cc_triage.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chat_doors.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chat_echo_mail.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chat_freshness.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chat_is_not_one_task.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chat_proposals.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chat_queue.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chat_relationship.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chat_retention.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chat_setup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chatformat.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chatservers.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_chinese_clis.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_clean_context.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cli_connections.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cli_failure.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cli_help.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cli_install.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cli_install_terminal.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cli_on_fresh_path.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cli_setup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cli_update.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_climodels.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_clipool.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_clis.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_closeout.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cloud.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cloud_sources.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_completion_freshness.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_compose.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_compose_sources.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_compose_workflows.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_concierge.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_concierge_counsel.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_config.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_context.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_context_refresh_freshness.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_coordination.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_core.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_correction_doors.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_counsel.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_counsel_consumers.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_counsel_migration.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_counsel_sections.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_current_restore.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_cwlogs_paging.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_databases.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_demo.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_deps.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_desktop.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_devin.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_devtools.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_diff_review.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_digest_brief.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_dispatch_retries.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_docs_and_llm.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_docs_flow.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_duplicate_connectors.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_email_chains.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_email_identity_routing.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_ending_a_run_writes_the_answer.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_evening_brief.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_every_card_is_reachable.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_every_cli_startable.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_explicit_completion.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_factory.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_failed_acts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_feed_working.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_files.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_final_answer_capture.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_finished_chat_stays_finished.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_floating_assistant.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_follow_up_verdict.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_fresh_evaluation.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_freshness.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_freshness_walk.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_funnel.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_general.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_github_auto.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_github_images.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_guard.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_handbook.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_handbook_topics.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_handoff_channels.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_handraise.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_harvest.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_histgen.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_home_is_never_yours.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_hooks_events.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_hooks_version.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_ideas_triage.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_ignore_sender.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_ignore_sender_quiets_its_work.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_images.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_imap_catchup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_imap_history.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_imapmail.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_imessage.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_inline_pictures.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_intacct.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_interrupted_work.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_invite_is_not_work.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_invoice_workflow.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_jev.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_judge_reads_the_conclusion.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_kind_dispatch.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_knowledge.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_lane_vocabulary.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_learnedgraph.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_lifecycle.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_lifespan_loops_are_guarded.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_linkedin.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_linkedin_signin.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_live.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_local_file.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_lookups.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_mail_catchup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_mail_fetch_cost.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_mail_folders.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_mark_read.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_markets.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_mcp.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_meeting_prep.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_message_thread.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_messengers.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_msauth.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_mssql.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_multi_question.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_muse.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_no_pydantic_v1.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_noop_ending.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_not_coding.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_note_retrieval.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_onboarding_walk.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_one_app_one_reason.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_one_pty_one_geometry.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_only_your_own_thread.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_openai_compatible_brains.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_operations.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_outbound_reports.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_outbox.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_own_rows_no_reply.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_person_name.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_phone_picks.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_phone_walk_ux.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_playbook_setup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_playbooks.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_pm.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_poll_lanes.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_poll_overlap.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_poll_parallel.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_poll_sources.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_pr_comments.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_problems.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_problems_dismiss.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_procedure_selection.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_processing_demo_replay.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_processing_ledger.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_profile_is_a_role.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_projects.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_prompt_images.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_prompt_sources.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_promptmap_and_catalog.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_proof_ci_proposals.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_pypi_downloads.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_quickbooks.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_qwen.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_rail_decisions.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_rank.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_rate_limit.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_read_text.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_recent_closures.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_reclassify.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_redact.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_redact_doors.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_remind.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_remote_assistant.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_remote_sections.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_reply_always_drafts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_reply_attachments.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_reply_channels.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_reply_envelope.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_reply_needs_a_correspondent.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_reply_sources.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_reply_voice.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_repo_choice_triage.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_report_alerts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_report_deliver.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_report_headline.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_report_one_road.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_report_order_and_research.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_report_prompt_isolation.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_report_refusal.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_report_routing.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_report_triage.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_research.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_research_more.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_review_task.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_reviews.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_robinhood.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_routing_memory.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_s3_poll_paging.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_scopes.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_seed_fits_a_tty.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_seeded_reports.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_selector_vocabulary.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_semantic.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_send_outcomes.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_send_targets.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_sender_trust.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_sender_words.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_session_artifacts.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_session_continuity.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_session_endings.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_session_files.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_settings_defaults_json.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_settings_schema.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_setup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_setup_skill.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_setup_walk.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_sheets_sharepoint.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_simplefin.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_skillimport.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_social.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_someone_else_replied.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_soul_interview.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_startup_contract.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_stay_open.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_stay_open_doors.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_store_app_cli.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_store_hotpaths.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_store_pokes.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_sync_clock.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_task_ask.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_task_checklist.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_task_controls_operations.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_task_identity.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_task_refs.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_task_tools.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_taskstate.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_telegram_buttons.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_teller.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_terminal.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_the_exe_ships_what_the_wheel_ships.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_the_split_holds.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_toil.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_tracker_revisions.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_treg.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_triage_cleanup.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_triage_dataset.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_triage_errors.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_triage_images.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_triage_joins.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_triage_pr_rule.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_triage_retry_sweep.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_triage_urgent.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_update.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_update_refused.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_urgent_and_handoff.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_verdict_paths.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_verdict_shape.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_verdict_sticks.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_vision.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_voice.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_wabridge.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_wabridge_log_trim.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_waitroom.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_walk_order.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_watermark.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_web_entrypoint.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_webguard.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_whatsapp_documents.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_whatsapp_images.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_whoami.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_why_not_started.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_withdrawn.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_witness.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_worker_brief.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_worker_events.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_worker_resumes.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_worker_scenarios.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_worker_surfaces.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_workerstate_said.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_workflows.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_zz_chipverbs.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_zz_lastword.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_zz_setupchat.py +0 -0
- {taskuary-0.3.7.1 → taskuary-0.3.7.2}/tests/test_zz_toolcatalog.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: taskuary
|
|
3
|
-
Version: 0.3.7.
|
|
3
|
+
Version: 0.3.7.2
|
|
4
4
|
Summary: Automate your job - the local-first operating system for your work: AI triage in, coding agents out.
|
|
5
5
|
License: MIT
|
|
6
6
|
Project-URL: Homepage, https://github.com/ldbumble/taskuary
|
|
@@ -69,7 +69,7 @@ Dynamic: license-file
|
|
|
69
69
|
|
|
70
70
|
[](https://github.com/ldbumble/taskuary/actions/workflows/ci.yml)
|
|
71
71
|
[](https://scorecard.dev/viewer/?uri=github.com/ldbumble/taskuary)
|
|
72
|
-
[](https://pypi.org/project/taskuary/)
|
|
73
73
|
[](https://github.com/ldbumble/taskuary)
|
|
74
74
|
[](LICENSE)
|
|
75
75
|
[](https://github.com/ldbumble/taskuary/stargazers)
|
|
@@ -83,7 +83,7 @@ your agents, and brings decisions back to you. Nothing sends or ships without yo
|
|
|
83
83
|
|
|
84
84
|

|
|
85
85
|
|
|
86
|
-
Taskuary is early—currently **v0.3.7.
|
|
86
|
+
Taskuary is early—currently **v0.3.7.2**—so breaking changes are still possible before 1.0.
|
|
87
87
|
|
|
88
88
|
<p align="center">
|
|
89
89
|
<a href="https://taskuary.com/demo/"><img
|
|
@@ -100,47 +100,50 @@ Taskuary is early—currently **v0.3.7.1**—so breaking changes are still possi
|
|
|
100
100
|
One request, from arrival to your approval. Follow Ruth's request for the latest vendor spend
|
|
101
101
|
numbers through the real app, using fictional demo data.
|
|
102
102
|
|
|
103
|
-
### 1.
|
|
103
|
+
### 1. Everything lands in one place
|
|
104
104
|
|
|
105
|
-
Mail, chats, issue trackers, alerts, and reports
|
|
106
|
-
|
|
105
|
+
Mail, chats, issue trackers, alerts, and reports arrive on one rail, sorted by what they need:
|
|
106
|
+
**Urgent**, **On you**, **For later**, the Advisor's ideas, and **FYI**. Beside it, the Assistant
|
|
107
|
+
says what came in and who is waiting, so you never open each system in turn.
|
|
107
108
|
|
|
108
|
-

|
|
109
110
|
|
|
110
|
-
### 2.
|
|
111
|
+
### 2. Let the Assistant walk you through it
|
|
111
112
|
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
Choose **Walk me through my tasks**. The Assistant puts one item on the table at a time, as the
|
|
114
|
+
same task card you would open yourself, with the next actions under it: **Next**, **Write reply**,
|
|
115
|
+
**Start an agent**. The buttons always do the same thing; the chat line is for everything else,
|
|
116
|
+
and the Assistant already has the message, the thread, and your past decisions to answer from.
|
|
114
117
|
|
|
115
|
-

|
|
116
119
|
|
|
117
|
-
### 3.
|
|
120
|
+
### 3. Every request becomes a task with its whole story
|
|
118
121
|
|
|
119
|
-
Open
|
|
120
|
-
|
|
122
|
+
Open any item to see how it got here: the message, what triage decided and why, which agent
|
|
123
|
+
has it, and where the reply stands.
|
|
121
124
|
|
|
122
|
-

|
|
123
126
|
|
|
124
|
-
### 4.
|
|
127
|
+
### 4. The agent works inside the chat
|
|
125
128
|
|
|
126
|
-
|
|
127
|
-
|
|
129
|
+
**Start an agent** and it works in the same card. Here the analyst prepares the numbers, checks
|
|
130
|
+
that the categories add up, names its source, and drafts the reply. Nothing is sent.
|
|
128
131
|
|
|
129
|
-

|
|
130
133
|
|
|
131
|
-
### 5.
|
|
134
|
+
### 5. The last word is yours
|
|
132
135
|
|
|
133
|
-
|
|
134
|
-
|
|
136
|
+
The prepared reply waits on the task, beside the request that started it. Read it, edit it,
|
|
137
|
+
and choose **Approve & send** when it is ready.
|
|
135
138
|
|
|
136
|
-

|
|
137
140
|
|
|
138
|
-
### 6. Start your day
|
|
141
|
+
### 6. Start your day before it gets busy
|
|
139
142
|
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
Each morning the Assistant opens with today's meetings on a timeline and who needs a word from you.
|
|
144
|
+
Ruth's request has a clear deadline: the 11:30 operations review.
|
|
142
145
|
|
|
143
|
-

|
|
144
147
|
|
|
145
148
|
## Key features
|
|
146
149
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
[](https://github.com/ldbumble/taskuary/actions/workflows/ci.yml)
|
|
6
6
|
[](https://scorecard.dev/viewer/?uri=github.com/ldbumble/taskuary)
|
|
7
|
-
[](https://pypi.org/project/taskuary/)
|
|
8
8
|
[](https://github.com/ldbumble/taskuary)
|
|
9
9
|
[](LICENSE)
|
|
10
10
|
[](https://github.com/ldbumble/taskuary/stargazers)
|
|
@@ -18,7 +18,7 @@ your agents, and brings decisions back to you. Nothing sends or ships without yo
|
|
|
18
18
|
|
|
19
19
|

|
|
20
20
|
|
|
21
|
-
Taskuary is early—currently **v0.3.7.
|
|
21
|
+
Taskuary is early—currently **v0.3.7.2**—so breaking changes are still possible before 1.0.
|
|
22
22
|
|
|
23
23
|
<p align="center">
|
|
24
24
|
<a href="https://taskuary.com/demo/"><img
|
|
@@ -35,47 +35,50 @@ Taskuary is early—currently **v0.3.7.1**—so breaking changes are still possi
|
|
|
35
35
|
One request, from arrival to your approval. Follow Ruth's request for the latest vendor spend
|
|
36
36
|
numbers through the real app, using fictional demo data.
|
|
37
37
|
|
|
38
|
-
### 1.
|
|
38
|
+
### 1. Everything lands in one place
|
|
39
39
|
|
|
40
|
-
Mail, chats, issue trackers, alerts, and reports
|
|
41
|
-
|
|
40
|
+
Mail, chats, issue trackers, alerts, and reports arrive on one rail, sorted by what they need:
|
|
41
|
+
**Urgent**, **On you**, **For later**, the Advisor's ideas, and **FYI**. Beside it, the Assistant
|
|
42
|
+
says what came in and who is waiting, so you never open each system in turn.
|
|
42
43
|
|
|
43
|
-

|
|
44
45
|
|
|
45
|
-
### 2.
|
|
46
|
+
### 2. Let the Assistant walk you through it
|
|
46
47
|
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
Choose **Walk me through my tasks**. The Assistant puts one item on the table at a time, as the
|
|
49
|
+
same task card you would open yourself, with the next actions under it: **Next**, **Write reply**,
|
|
50
|
+
**Start an agent**. The buttons always do the same thing; the chat line is for everything else,
|
|
51
|
+
and the Assistant already has the message, the thread, and your past decisions to answer from.
|
|
49
52
|
|
|
50
|
-

|
|
51
54
|
|
|
52
|
-
### 3.
|
|
55
|
+
### 3. Every request becomes a task with its whole story
|
|
53
56
|
|
|
54
|
-
Open
|
|
55
|
-
|
|
57
|
+
Open any item to see how it got here: the message, what triage decided and why, which agent
|
|
58
|
+
has it, and where the reply stands.
|
|
56
59
|
|
|
57
|
-

|
|
58
61
|
|
|
59
|
-
### 4.
|
|
62
|
+
### 4. The agent works inside the chat
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
**Start an agent** and it works in the same card. Here the analyst prepares the numbers, checks
|
|
65
|
+
that the categories add up, names its source, and drafts the reply. Nothing is sent.
|
|
63
66
|
|
|
64
|
-

|
|
65
68
|
|
|
66
|
-
### 5.
|
|
69
|
+
### 5. The last word is yours
|
|
67
70
|
|
|
68
|
-
|
|
69
|
-
|
|
71
|
+
The prepared reply waits on the task, beside the request that started it. Read it, edit it,
|
|
72
|
+
and choose **Approve & send** when it is ready.
|
|
70
73
|
|
|
71
|
-

|
|
72
75
|
|
|
73
|
-
### 6. Start your day
|
|
76
|
+
### 6. Start your day before it gets busy
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
Each morning the Assistant opens with today's meetings on a timeline and who needs a word from you.
|
|
79
|
+
Ruth's request has a clear deadline: the 11:30 operations review.
|
|
77
80
|
|
|
78
|
-

|
|
79
82
|
|
|
80
83
|
## Key features
|
|
81
84
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "taskuary"
|
|
7
|
-
version = "0.3.7.
|
|
7
|
+
version = "0.3.7.2"
|
|
8
8
|
description = "Automate your job - the local-first operating system for your work: AI triage in, coding agents out."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -188,6 +188,22 @@ def split(text: str, limit: int = HARD) -> list:
|
|
|
188
188
|
return out
|
|
189
189
|
|
|
190
190
|
|
|
191
|
+
def json_rows(text: str) -> str:
|
|
192
|
+
"""Rows that arrived as one JSON object per line - a report whose summary never came, the demo's - as a markdown table,
|
|
193
|
+
so the door lays them out like any other table ({"site": "Lakeview", "headcount": 112} went to the phone as that, braces
|
|
194
|
+
and quotes, 2026-09-30 phone test). Anything that is not ALL flat objects is left exactly as it was."""
|
|
195
|
+
import json
|
|
196
|
+
lines = [l.strip() for l in str(text or '').splitlines() if l.strip()]
|
|
197
|
+
if len(lines) < 2: return text
|
|
198
|
+
try: rows = [json.loads(l) for l in lines]
|
|
199
|
+
except ValueError: return text
|
|
200
|
+
if not all(isinstance(r, dict) and r and all(not isinstance(v, (dict, list)) for v in r.values()) for r in rows): return text
|
|
201
|
+
cols = list(dict.fromkeys(k for r in rows for k in r))
|
|
202
|
+
cell = lambda v: '' if v is None else str(v).replace('|', '/')
|
|
203
|
+
return '\n'.join(['| ' + ' | '.join(cols) + ' |', '|' + '---|' * len(cols)]
|
|
204
|
+
+ ['| ' + ' | '.join(cell(r.get(c)) for c in cols) + ' |' for r in rows])
|
|
205
|
+
|
|
206
|
+
|
|
191
207
|
def blocks(body, limit: int = HARD) -> list:
|
|
192
208
|
"""A report as the messages a chat should receive: one per section, in order.
|
|
193
209
|
|
|
@@ -200,7 +216,7 @@ def blocks(body, limit: int = HARD) -> list:
|
|
|
200
216
|
out = []
|
|
201
217
|
for title, text in sections(strip_raw(body)):
|
|
202
218
|
head = f'## {title}' if title else ''
|
|
203
|
-
text = text.strip()
|
|
219
|
+
text = json_rows(text.strip()).strip()
|
|
204
220
|
if not text: continue
|
|
205
221
|
for piece in split(text, max(200, limit - len(head) - 2)):
|
|
206
222
|
out.append(f'{head}\n{piece}'.strip() if head else piece)
|
|
@@ -1879,7 +1879,9 @@ def surface(store, key: str = None, llm=None, actor: str = 'owner', only: str =
|
|
|
1879
1879
|
f"I'll bring {'it' if n == 1 else 'them'} round again in a while - or open {'it' if n == 1 else 'one'} now.")
|
|
1880
1880
|
# ...and the way to them NOW, by name: a Next under this line only said it again (2026-09-23, six days running).
|
|
1881
1881
|
# What waits on the owner first - a close-out, an agent's question - then the rest.
|
|
1882
|
-
|
|
1882
|
+
# ...each saying WHAT it is, not a bare number (the owner, 2026-09-30: "have to write what they are about a little")
|
|
1883
|
+
opens = [{'verb': 'open', 'key': i['key'], 'label': ' · '.join(x for x in (
|
|
1884
|
+
f"Open {i.get('ref') or ''}".strip(), _title_cut(' '.join(str(i.get('title') or 'it').split()), 50)) if x)}
|
|
1883
1885
|
for i in sorted(waiting, key=lambda i: not funnel.on_you(i))[:3]]
|
|
1884
1886
|
elif only and left:
|
|
1885
1887
|
# the filtered set is done; what remains is the rest of the pipe - offer it rather than call the day over
|
|
@@ -62,14 +62,31 @@ def _connected(store) -> dict:
|
|
|
62
62
|
return out
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
POLL_MAX, PAGE = 12, 10 # WhatsApp's poll holds twelve (whatsapp/poll.mjs cuts the rest SILENTLY); a page leaves room
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def paged(rows: list, up: list, act: dict, page: int = 0) -> list:
|
|
69
|
+
"""The picks for one page: ten rows, More when there are more, then the way back - never past twelve. The Connections
|
|
70
|
+
menu offered seventeen and a list of cards twelve plus Back, so the last five sections and Back could not be tapped
|
|
71
|
+
(2026-09-30 phone test)."""
|
|
72
|
+
if len(rows) + len(up) <= POLL_MAX: return rows + up
|
|
73
|
+
page = max(0, int(page or 0))
|
|
74
|
+
here = rows[page * PAGE:(page + 1) * PAGE]
|
|
75
|
+
more = [(f'More ({len(rows) - (page + 1) * PAGE} left)', {**act, 'page': page + 1})] if (page + 1) * PAGE < len(rows) else \
|
|
76
|
+
[('From the top', {**act, 'page': 0})]
|
|
77
|
+
return here + more + up[:POLL_MAX - len(here) - 1]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def browse(store, area: str, section: str = None, open_: str = None, page: int = 0) -> tuple[str, list]:
|
|
66
81
|
"""(what to say, the picks under it) for one browse step. Back is always a pick; so is the way up."""
|
|
67
|
-
if area == 'connections': return _connections(store, section, open_)
|
|
68
|
-
if area == 'settings': return _settings(store, section, open_)
|
|
82
|
+
if area == 'connections': return _connections(store, section, open_, page)
|
|
83
|
+
if area == 'settings': return _settings(store, section, open_, page)
|
|
84
|
+
if area == 'reports': return _reports(store, open_, page)
|
|
85
|
+
if area == 'hub': return _hub(store, open_, page)
|
|
69
86
|
return f'I cannot browse {area} here yet - it is on the desktop.', []
|
|
70
87
|
|
|
71
88
|
|
|
72
|
-
def _connections(store, section, open_):
|
|
89
|
+
def _connections(store, section, open_, page=0):
|
|
73
90
|
from . import connectorcatalog
|
|
74
91
|
cards = [c for c in connectorcatalog.cards() if c.get('group')]
|
|
75
92
|
state = _connected(store)
|
|
@@ -87,18 +104,62 @@ def _connections(store, section, open_):
|
|
|
87
104
|
rows = [c for c in cards if c['group'] == section]
|
|
88
105
|
lines = [f"· {c['title']} - {state.get(c['type']) or ('planned' if c.get('planned') else 'not connected')}" for c in rows]
|
|
89
106
|
picks = [(c['title'], {'t': 'browse', 'area': 'connections', 'section': section, 'open': c['type']}) for c in rows if not c.get('planned')]
|
|
90
|
-
return f"CONNECTIONS · {section.upper()} · {len(rows)}\n" + '\n'.join(lines),
|
|
107
|
+
return (f"CONNECTIONS · {section.upper()} · {len(rows)}\n" + '\n'.join(lines),
|
|
108
|
+
paged(picks, up, {'t': 'browse', 'area': 'connections', 'section': section}, page))
|
|
91
109
|
on = sum(1 for v in state.values() if v == 'connected')
|
|
92
110
|
lines = [f"{g} · {sum(1 for c in cards if c['group'] == g)}" for g in groups]
|
|
93
111
|
return (f'Connections - {on} connected. Pick a section:\n' + '\n'.join(f'· {x}' for x in lines),
|
|
94
|
-
[(g, {'t': 'browse', 'area': 'connections', 'section': g}) for g in groups])
|
|
112
|
+
paged([(g, {'t': 'browse', 'area': 'connections', 'section': g}) for g in groups], [], {'t': 'browse', 'area': 'connections'}, page))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def _reports(store, open_, page=0):
|
|
116
|
+
"""REPORTS, the desktop sidebar's list as picks (the owner, 2026-09-30): each one's clock and how its last run went, then
|
|
117
|
+
one opened - what it is, where it goes, what the last run said. Running or changing one is words: the model proposes it."""
|
|
118
|
+
from . import appfacts
|
|
119
|
+
rows = appfacts.reports(store)
|
|
120
|
+
up = [('Back to Reports', {'t': 'browse', 'area': 'reports'})]
|
|
121
|
+
def last(r): return 'never ran' if r['last_ok'] is None else 'last run FAILED' if r['last_ok'] is False else f"ran {r['last_at'][:16]}"
|
|
122
|
+
if open_:
|
|
123
|
+
r = next((x for x in rows if str(x['source_id']) == str(open_)), None)
|
|
124
|
+
if not r: return 'That report is not there any more.', up
|
|
125
|
+
said = str(r['last_said'] or '').strip()
|
|
126
|
+
text = (f"{'WORKFLOW' if r['workflow'] else 'REPORT'} · {r['title']}{'' if r['active'] else ' (off)'}\n"
|
|
127
|
+
f"When: {r['schedule'] or 'no clock - it runs when asked'}\nReaches you: {r['reach']}\nGoes: {r['goes']}\n{last(r).capitalize()}"
|
|
128
|
+
+ (f"\n> {said}" if said else '')
|
|
129
|
+
+ '\n\nSay "run it now", or what to change, and I propose it for your yes.')
|
|
130
|
+
return text, up
|
|
131
|
+
if not rows: return 'No reports or workflows are set up yet. Say "set up a report" and I walk you through one.', []
|
|
132
|
+
lines = [f"· {r['title']}{'' if r['active'] else ' (off)'} - {r['schedule'] or 'no clock'}; {last(r)}" for r in rows]
|
|
133
|
+
return (f'REPORTS · {len(rows)}\n' + '\n'.join(lines),
|
|
134
|
+
paged([(r['title'], {'t': 'browse', 'area': 'reports', 'open': r['source_id']}) for r in rows], [], {'t': 'browse', 'area': 'reports'}, page))
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def _hub(store, open_, page=0):
|
|
138
|
+
"""THE HUB, newest first as the desktop lists it (the owner, 2026-09-30): what the agents worked out, each one openable."""
|
|
139
|
+
up = [('Back to the Hub', {'t': 'browse', 'area': 'hub'})]
|
|
140
|
+
if open_:
|
|
141
|
+
e = store.lore_get(int(open_))
|
|
142
|
+
if not e: return 'That entry is not on the Hub any more.', up
|
|
143
|
+
body = str(e.get('Body') or '').strip()
|
|
144
|
+
text = (f"HUB · {e.get('Topic') or 'general'}\n*{e.get('Title') or ''}*\n"
|
|
145
|
+
f"by {e.get('Author') or 'an agent'} · score {e.get('Score') or 0} · {len(store.lore_comments(int(open_)) or [])} comments\n\n"
|
|
146
|
+
+ (body[:1500] + ('…' if len(body) > 1500 else '')))
|
|
147
|
+
return text, up
|
|
148
|
+
posts = store.lore_posts(None, None, 40, 'new', 'live', None)
|
|
149
|
+
if not posts: return 'Nothing on the Hub yet - agents post what they work out as they go.', []
|
|
150
|
+
lines = [f"· {p.get('Title') or ''} ({p.get('Topic') or 'general'}, {p.get('Score') or 0})" for p in posts[:20]]
|
|
151
|
+
n = store.lore_count()
|
|
152
|
+
n = n.get('posts', len(posts)) if isinstance(n, dict) else n
|
|
153
|
+
return (f"HUB · {n} entries, newest first\n" + '\n'.join(lines),
|
|
154
|
+
paged([((p.get('Title') or '')[:90], {'t': 'browse', 'area': 'hub', 'open': p['LoreId']}) for p in posts[:20]], [],
|
|
155
|
+
{'t': 'browse', 'area': 'hub'}, page))
|
|
95
156
|
|
|
96
157
|
|
|
97
158
|
def _schema() -> dict:
|
|
98
159
|
return json.loads((Path(__file__).with_name('settings_schema.json')).read_text(encoding='utf-8'))
|
|
99
160
|
|
|
100
161
|
|
|
101
|
-
def _settings(store, section, open_):
|
|
162
|
+
def _settings(store, section, open_, page=0):
|
|
102
163
|
schema, st = _schema(), store.get_settings()
|
|
103
164
|
knobs = schema.get('knobs') or {}
|
|
104
165
|
up = [('Back to Settings', {'t': 'browse', 'area': 'settings'})]
|
|
@@ -106,6 +167,7 @@ def _settings(store, section, open_):
|
|
|
106
167
|
v = st.get(k)
|
|
107
168
|
kind = (knobs.get(k) or {}).get('type')
|
|
108
169
|
if kind == 'switch': return 'on' if str(v if v is not None else '1').strip() not in ('0', 'false', 'off', '') else 'off'
|
|
170
|
+
if str(v).strip() == '*': return 'every other one set up, in order' # backup_brains' own wildcard, said in words
|
|
109
171
|
return str(v) if v not in (None, '') else '(not set)'
|
|
110
172
|
if open_:
|
|
111
173
|
m = knobs.get(open_) or {'label': open_}
|
|
@@ -116,7 +178,8 @@ def _settings(store, section, open_):
|
|
|
116
178
|
rows = [(k, m) for k, m in knobs.items() if m.get('group') == section]
|
|
117
179
|
lines = [f"· {m.get('label') or k}: {value(k)}" for k, m in rows]
|
|
118
180
|
return (f"SETTINGS · {section.upper()}\n" + ('\n'.join(lines) or 'Its controls are on the desktop.'),
|
|
119
|
-
[(m.get('label') or k, {'t': 'browse', 'area': 'settings', 'section': section, 'open': k}) for k, m in rows]
|
|
181
|
+
paged([(m.get('label') or k, {'t': 'browse', 'area': 'settings', 'section': section, 'open': k}) for k, m in rows], up,
|
|
182
|
+
{'t': 'browse', 'area': 'settings', 'section': section}, page))
|
|
120
183
|
groups = [g for g in schema.get('groups') or [] if any(m.get('group') == g for m in knobs.values())]
|
|
121
184
|
return ('Settings - pick a section:\n' + '\n'.join(f'· {g}' for g in groups),
|
|
122
|
-
[(g, {'t': 'browse', 'area': 'settings', 'section': g}) for g in groups])
|
|
185
|
+
paged([(g, {'t': 'browse', 'area': 'settings', 'section': g}) for g in groups], [], {'t': 'browse', 'area': 'settings'}, page))
|
|
@@ -139,12 +139,20 @@ def pipe_list(store, p: dict) -> str:
|
|
|
139
139
|
from . import funnel
|
|
140
140
|
items = [i for i in (funnel.pile(store).get('items') or []) if not i.get('settling')]
|
|
141
141
|
if not items: return 'The pipe is empty - nothing is waiting on you.'
|
|
142
|
+
# BY THE RAIL'S OWN SECTIONS, the headings the owner sees (funnel.level_of) - each row still says its lane. Grouped by
|
|
143
|
+
# lane, "For later" never appeared: it is a section, not a lane, and "what is waiting in later" was answered "nothing is
|
|
144
|
+
# parked in Later" over four rows sitting under that heading (the owner, 2026-09-30)
|
|
145
|
+
from .remote_assistant import _back_in
|
|
142
146
|
out = []
|
|
143
|
-
for
|
|
144
|
-
xs = [i for i in items if i
|
|
147
|
+
for sec in ('urgent', 'task', 'agents', 'later', 'reports', 'ideas', 'fyi'):
|
|
148
|
+
xs = [i for i in items if funnel.level_of(i) == sec]
|
|
145
149
|
if not xs: continue
|
|
146
|
-
out.append(f"{funnel.
|
|
147
|
-
|
|
150
|
+
out.append(f"{funnel.SECTION_WORDS[sec].upper()} ({len(xs)}):")
|
|
151
|
+
def row(i):
|
|
152
|
+
back = _back_in(i.get('back_at') or i.get('defer_until')) if sec == 'later' else ''
|
|
153
|
+
return (f" {task_ref(i['tid']) + ' ' if i.get('tid') else ''}{i['who'] + ' - ' if i.get('who') else ''}{_cut(i.get('title'), 100)}"
|
|
154
|
+
f" [{funnel.LANE_WORDS.get(i['lane'], (i['lane'],))[0]}{', back in ' + back if back else ''}]")
|
|
155
|
+
out += [row(i) for i in xs[:15]]
|
|
148
156
|
if len(xs) > 15: out.append(f' ...and {len(xs) - 15} more')
|
|
149
157
|
return NL.join(out)
|
|
150
158
|
|
|
@@ -531,7 +531,8 @@ MORNING_KEY, MORNING_AT = 'phone_morning_line', 'phone_morning_line_at'
|
|
|
531
531
|
SCRIPT_LINES = [('Walk me through my tasks', {'t': 'walk'}), ('Set up Taskuary', {'t': 'script', 'script': 'set up Taskuary'}),
|
|
532
532
|
('Set up a report', {'t': 'script', 'script': 'set up a report'}),
|
|
533
533
|
# the sidebar's browse buttons, as picks (doorway_browse): sections, then the list, then one
|
|
534
|
-
('Connections', {'t': 'browse', 'area': 'connections'}), ('
|
|
534
|
+
('Connections', {'t': 'browse', 'area': 'connections'}), ('Reports', {'t': 'browse', 'area': 'reports'}),
|
|
535
|
+
('Hub', {'t': 'browse', 'area': 'hub'}), ('Settings', {'t': 'browse', 'area': 'settings'})]
|
|
535
536
|
|
|
536
537
|
|
|
537
538
|
def greeting(now=None) -> str:
|
|
@@ -771,8 +772,7 @@ def carry_out(store, out: dict, item: dict | None, actor: str = 'owner', lead: s
|
|
|
771
772
|
said.append('I could not write that draft here - it is waiting on the task page.')
|
|
772
773
|
if walk_on:
|
|
773
774
|
here = (item or {}).get('key') if verb == 'next' else None # Next leaves the table as the desktop's does
|
|
774
|
-
|
|
775
|
-
return '\n\n'.join(said + [turn_text(nxt, store=store)])
|
|
775
|
+
return _on(store, actor, said, leaving=here, exclude=here, done_with=(item or {}).get('key'))
|
|
776
776
|
return '\n\n'.join(x for x in said if x)
|
|
777
777
|
|
|
778
778
|
|
|
@@ -857,6 +857,29 @@ def receipt_text(store, done: dict, actor: str = 'owner') -> str:
|
|
|
857
857
|
return turn_text({'say': turn['say'], 'item': None}, store=store, extra=list(recovery_rows(store, turn['chips'], actor)))
|
|
858
858
|
|
|
859
859
|
|
|
860
|
+
def _move_on(store, actor: str, leaving: str = None, exclude: str = None, done_with: str = None) -> tuple[dict, str]:
|
|
861
|
+
"""What comes after the table - (the next surface, a lead line). WHILE A SECTION IS BEING WALKED the next row of that
|
|
862
|
+
section, whatever put the last one down: Next did, but an act (Make a task, Send to agent, Remind me) fell back to the
|
|
863
|
+
whole walk and put TQ-0001 up in the middle of Walk Reports (2026-09-30 phone test). `done_with` is the key the act settled."""
|
|
864
|
+
from . import concierge, doorway_browse, funnel
|
|
865
|
+
walking = doorway_browse.held(store, asking())
|
|
866
|
+
if walking:
|
|
867
|
+
seen = [*walking.get('seen', []), *[k for k in (leaving, done_with) if k]]
|
|
868
|
+
nxt = doorway_browse.next_in(store, walking['section'], seen)
|
|
869
|
+
if nxt:
|
|
870
|
+
doorway_browse.hold(store, asking(), walking['section'], [*seen, nxt['key']])
|
|
871
|
+
return concierge.surface(store, nxt['key'], actor=actor, leaving=leaving), ''
|
|
872
|
+
doorway_browse.hold(store, asking(), None) # the section ran out: say so, and the walk goes on as normal
|
|
873
|
+
return concierge.surface(store, actor=actor, leaving=leaving, exclude=exclude), funnel.section_done(walking['section'])
|
|
874
|
+
return concierge.surface(store, actor=actor, leaving=leaving, exclude=exclude), ''
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
def _on(store, actor: str, said: list, extra=None, **kw) -> str:
|
|
878
|
+
"""The receipt lines, then what comes next (_move_on) - with the section's own end said when it ran out."""
|
|
879
|
+
nxt, lead = _move_on(store, actor, **kw)
|
|
880
|
+
return '\n\n'.join([x for x in said if x] + [turn_text(nxt, lead=lead, store=store, extra=extra)])
|
|
881
|
+
|
|
882
|
+
|
|
860
883
|
def _ran(store, prop: dict, done: dict, item: dict | None, actor: str) -> str:
|
|
861
884
|
"""After the run: the receipt, an Undo when it offered one, and the next item when the table was settled."""
|
|
862
885
|
from . import concierge
|
|
@@ -864,7 +887,7 @@ def _ran(store, prop: dict, done: dict, item: dict | None, actor: str) -> str:
|
|
|
864
887
|
said = concierge.receipt(store, done, actor)
|
|
865
888
|
undo = [('Undo', {'t': 'undo'})] if ' Undo: ' in said else []
|
|
866
889
|
if done.get('status') == 'done' and _settled_the_table(prop, item):
|
|
867
|
-
return
|
|
890
|
+
return _on(store, actor, [said], extra=undo, done_with=prop.get('key') or (item or {}).get('key'))
|
|
868
891
|
if undo: return '\n\n'.join([said, turn_text({}, store=store, extra=undo)])
|
|
869
892
|
return said
|
|
870
893
|
|
|
@@ -897,7 +920,7 @@ def run_act(store, act: dict, item: dict | None, actor: str = 'owner') -> str:
|
|
|
897
920
|
# a new walk, or one item by name, is not the section being walked
|
|
898
921
|
if t in ('walk', 'open'): doorway_browse.hold(store, asking(), None)
|
|
899
922
|
if t == 'browse':
|
|
900
|
-
text, rows = doorway_browse.browse(store, act.get('area') or '', act.get('section'), act.get('open'))
|
|
923
|
+
text, rows = doorway_browse.browse(store, act.get('area') or '', act.get('section'), act.get('open'), act.get('page') or 0)
|
|
901
924
|
return turn_text({'say': text, 'item': None}, store=store, extra=rows)
|
|
902
925
|
if t == 'next' and doorway_browse.held(store, asking()):
|
|
903
926
|
here, walking = (item or {}).get('key'), doorway_browse.held(store, asking())
|
|
@@ -1008,6 +1031,13 @@ def stuck(store, text: str) -> str:
|
|
|
1008
1031
|
return turn_text({'say': text, 'item': None}, store=store, extra=[(concierge.CHIP_WORDS['next'], {'t': 'next'})])
|
|
1009
1032
|
|
|
1010
1033
|
|
|
1034
|
+
def asking_key(store) -> str:
|
|
1035
|
+
"""The key on the table for this chat's walk - what a Remind me just put away."""
|
|
1036
|
+
from . import concierge, general
|
|
1037
|
+
try: return (concierge.restore_current(store, general.dock_task(store, 'owner')[0]['TaskId']) or {}).get('key') or ''
|
|
1038
|
+
except Exception: return ''
|
|
1039
|
+
|
|
1040
|
+
|
|
1011
1041
|
REMIND_DAYS = (('Tomorrow', 'tomorrow'), ('Next week', '1 week'), ('In 2 weeks', '2 weeks'), ('In a month', '1 month')) # RemindMe.jsx's QUICK
|
|
1012
1042
|
|
|
1013
1043
|
|
|
@@ -1017,13 +1047,13 @@ def _remind(store, act: dict, actor: str) -> str:
|
|
|
1017
1047
|
if act.get('idea'):
|
|
1018
1048
|
from . import assistant
|
|
1019
1049
|
out = assistant.act(store, int(act['idea']), 'snooze', actor, until=act['until'])
|
|
1020
|
-
return
|
|
1050
|
+
return _on(store, actor, [f"Put away until {out['when']} - it comes back that morning."], done_with=(asking_key(store) or None))
|
|
1021
1051
|
out = remind.set_reminder(store, int(act['tid']), act['until'], actor)
|
|
1022
1052
|
operations.record_direct(store, 'task.defer', int(act['tid']), {'until': act['until']}, actor, out)
|
|
1023
1053
|
if not out.get('remindAt'): return 'It is back on your rail now.'
|
|
1024
1054
|
said = f"Away until {out['when']} - it is under Upcoming in Tasks, and back on your rail that morning."
|
|
1025
1055
|
back = [('Bring it back now', {'t': 'remind', 'tid': act['tid'], 'until': 'none'})]
|
|
1026
|
-
return
|
|
1056
|
+
return _on(store, actor, [said], extra=back, done_with=(asking_key(store) or None))
|
|
1027
1057
|
|
|
1028
1058
|
|
|
1029
1059
|
def _draft(store, item: dict, verb: str, instruction: str):
|
|
@@ -1454,6 +1484,19 @@ def summary_rest(store, item: dict | None) -> str:
|
|
|
1454
1484
|
return ' '.join(re.split(r'(?<=[.!?])\s+', summary)[1:]).strip()
|
|
1455
1485
|
|
|
1456
1486
|
|
|
1487
|
+
def _repeats(line: str, shown: list) -> bool:
|
|
1488
|
+
"""A line that only says again what is already on the card: its opening is in a shown line, or a shown line's opening is
|
|
1489
|
+
in it. A task written from one pasted paragraph has that paragraph as its title, its message's subject AND its summary,
|
|
1490
|
+
and the card printed it three times (the owner, 2026-09-30, TQ-0887) - the desktop row keeps one (fyiRow.gistFor)."""
|
|
1491
|
+
norm = lambda s: ' '.join(str(s or '').split()).lower().rstrip('…').strip()
|
|
1492
|
+
a = norm(line)
|
|
1493
|
+
if not a: return True
|
|
1494
|
+
for s in shown:
|
|
1495
|
+
b = norm(s)
|
|
1496
|
+
if b and (a[:48] in b or b[:48] in a): return True
|
|
1497
|
+
return False
|
|
1498
|
+
|
|
1499
|
+
|
|
1457
1500
|
def story_block(store, item: dict | None, draft: str = '', say: str = '', full: bool = False) -> str:
|
|
1458
1501
|
"""The quiet part: a header (state · ref), who asked and what they want, then the agent and its evidence.
|
|
1459
1502
|
`full`: the owner opened this one to READ it - the whole message, not its opening (full_body)."""
|
|
@@ -1483,9 +1526,10 @@ def story_block(store, item: dict | None, draft: str = '', say: str = '', full:
|
|
|
1483
1526
|
# what the thing IS, in its own words - a pull request's title and number, an email's subject - and the rest of the
|
|
1484
1527
|
# summary: the first sentence says who wants what, never what it is (the owner, 2026-09-28: "at least the title")
|
|
1485
1528
|
subj = subject_of(store, it)
|
|
1486
|
-
if subj and re.sub(r'^(PR |Issue )?#\d+( ·)?\s*', '', subj).lower() not in (said or '').lower()
|
|
1529
|
+
if subj and re.sub(r'^(PR |Issue )?#\d+( ·)?\s*', '', subj).lower() not in (said or '').lower() and not _repeats(subj, [said]):
|
|
1530
|
+
lines.append(_cut(subj, 280))
|
|
1487
1531
|
rest = summary_rest(store, it)
|
|
1488
|
-
if rest: lines.append(_cut(rest, 280))
|
|
1532
|
+
if rest and not _repeats(rest, [said, subj]): lines.append(_cut(rest, 280))
|
|
1489
1533
|
if not it.get('tid') and say and kind != 'agentdone' and (not said or said.lower() not in say.lower()): lines.append(say)
|
|
1490
1534
|
# their own words, when nothing of yours answers them yet (a draft puts them behind More)
|
|
1491
1535
|
whole = full_body(store, it) if full else ''
|
|
@@ -280,6 +280,7 @@ class DecideBody(BaseModel):
|
|
|
280
280
|
class CodeBody(BaseModel):
|
|
281
281
|
repo: str | None = None; agent: str | None = None
|
|
282
282
|
model: str | None = None; instruction: str | None = None
|
|
283
|
+
brain: str | None = None # WHICH CLI - continue_task read it, but nothing could ever send it
|
|
283
284
|
class DocBody(BaseModel): content: str
|
|
284
285
|
class SettingBody(BaseModel): name: str; value: str
|
|
285
286
|
class SourceBody(BaseModel):
|
|
@@ -1490,7 +1491,10 @@ def continue_session(task_id: int, body: CodeBody = None):
|
|
|
1490
1491
|
try:
|
|
1491
1492
|
session = hub_term.start_on_task(store, task_id, row['Agent'], (body.model if body else None),
|
|
1492
1493
|
(body.instruction if body else None), ACTOR,
|
|
1493
|
-
cwd=row['Cwd'], resume=row['ExtId']
|
|
1494
|
+
cwd=row['Cwd'], resume=row['ExtId'],
|
|
1495
|
+
# the id belongs to the CLI that made it: resuming a codex conversation on the default
|
|
1496
|
+
# brain ran `claude --resume <codex id>` - "No conversation found with session ID"
|
|
1497
|
+
brain=row.get('Brain') or None)
|
|
1494
1498
|
except (ValueError, RuntimeError, FileNotFoundError) as e:
|
|
1495
1499
|
raise HTTPException(422, str(e))
|
|
1496
1500
|
store.audit('task', task_id, 'continue-session', ACTOR, detail={'agent': row['Agent'], 'fromSid': row['Sid']})
|
|
@@ -1525,8 +1529,22 @@ def continue_work(task_id: int, body: ContinueBody = None):
|
|
|
1525
1529
|
return {'continued': True, 'taskId': task_id, 'kind': 'general'}
|
|
1526
1530
|
note = with_images(note, imgs).strip()
|
|
1527
1531
|
row, _why = _resumable(task_id)
|
|
1528
|
-
|
|
1529
|
-
else
|
|
1532
|
+
# CONTINUE IS THE SAME CLI (the owner, 2026-09-30: "it should start as codex if i hit continue of course"): the one that made
|
|
1533
|
+
# the conversation, else the one that last worked the task - never whatever the default happens to be today
|
|
1534
|
+
last = row or store.last_transcript(task_id) or {}
|
|
1535
|
+
brain = (last.get('Brain') or None) if isinstance(last, dict) else None
|
|
1536
|
+
fresh = lambda: continue_task(task_id, CodeBody(brain=brain, instruction=(f'FROM THE OWNER: {note}\n\n' if note else '') + continuity.RESUME_PROMPT)) # their words lead
|
|
1537
|
+
if row:
|
|
1538
|
+
# the conversation belongs to the CLI that made it; when THAT CLI cannot open now (out of sessions, signed out), a fresh
|
|
1539
|
+
# session seeded with the handover is the way on - not an error (the owner, 2026-09-30, TQ-0887: codex made it, codex was
|
|
1540
|
+
# unavailable, and every Continue failed)
|
|
1541
|
+
try: out = continue_session(task_id, CodeBody(instruction=note or None))
|
|
1542
|
+
except HTTPException as e:
|
|
1543
|
+
if e.status_code != 422: raise
|
|
1544
|
+
store.add_comment(task_id, 'router', 'agent', f"{brain or row['Agent']} could not reopen its conversation ({e.detail}); "
|
|
1545
|
+
f"starting a fresh {brain or 'agent'} session with the handover instead.")
|
|
1546
|
+
row, out = None, fresh()
|
|
1547
|
+
else: out = fresh()
|
|
1530
1548
|
store.audit('task', task_id, 'continue-work', ACTOR, detail={'kind': 'coding', 'resumed': bool(row), 'note': bool(note)})
|
|
1531
1549
|
return {'continued': True, 'taskId': task_id, 'kind': 'coding', 'resumed': bool(row), **(out if isinstance(out, dict) else {})}
|
|
1532
1550
|
|