taskuary 0.3.6.2__tar.gz → 0.3.6.4__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.6.2/taskuary.egg-info → taskuary-0.3.6.4}/PKG-INFO +5 -5
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/README.md +4 -4
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/pyproject.toml +5 -4
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/assistant.py +29 -12
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/channels.py +9 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/cli.py +28 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/coder.py +65 -1
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/concierge.py +94 -52
- taskuary-0.3.6.4/taskuary/connectorcatalog.json +2397 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/demo.py +71 -40
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/funnel.py +24 -6
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/funnel_selection.py +3 -9
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/general.py +6 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/ingest.py +75 -2
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_all.py +1 -1
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_order.py +2 -2
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_unread.py +72 -6
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/remote_assistant.py +196 -60
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/reports.py +79 -5
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/routing.py +5 -4
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/scopes.py +3 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/selfclose.py +19 -2
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/server.py +69 -11
- taskuary-0.3.6.4/taskuary/settings_schema.json +483 -0
- taskuary-0.3.6.4/taskuary/social.py +241 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/store.py +90 -28
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/agent.md +2 -1
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/coder.md +4 -3
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/triage.md +5 -5
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/toolcatalog.py +9 -2
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/triage.py +37 -13
- taskuary-0.3.6.4/taskuary/triage_kind_rules.json +18 -0
- taskuary-0.3.6.4/taskuary/web/assets/AssistantGame-COau3nxm.js +4 -0
- taskuary-0.3.6.4/taskuary/web/assets/GameScene-CcQhDNj4.js +1 -0
- taskuary-0.3.6.2/taskuary/web/assets/HubView-BjL1r12I.js → taskuary-0.3.6.4/taskuary/web/assets/HubView-DUp1o1rB.js +1 -1
- taskuary-0.3.6.4/taskuary/web/assets/RoundedBoxGeometry-BE4rf3sD.js +3840 -0
- taskuary-0.3.6.4/taskuary/web/assets/StudioScene-BTJBGMHD.js +1 -0
- taskuary-0.3.6.2/taskuary/web/assets/index-Bsld__8Y.css → taskuary-0.3.6.4/taskuary/web/assets/index-CKQunODG.css +1 -1
- taskuary-0.3.6.4/taskuary/web/assets/index-DbbLj0HN.js +597 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/index.html +2 -2
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/workerstate.py +5 -1
- {taskuary-0.3.6.2 → taskuary-0.3.6.4/taskuary.egg-info}/PKG-INFO +5 -5
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/SOURCES.txt +18 -4
- taskuary-0.3.6.4/tests/test_agent_reply.py +111 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_an_inbox_is_not_a_destination.py +28 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_api.py +2 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant.py +21 -3
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_blocks.py +17 -10
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_presentation.py +24 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_reactions.py +10 -8
- taskuary-0.3.6.4/tests/test_banner_is_one_rule.py +32 -0
- taskuary-0.3.6.4/tests/test_chat_echo_mail.py +73 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chatformat.py +2 -1
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_concierge.py +10 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_core.py +3 -3
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_demo.py +19 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_digest_brief.py +4 -4
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_docs_and_llm.py +9 -6
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_every_card_is_reachable.py +22 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_funnel.py +137 -4
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ideas_triage.py +21 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_kind_dispatch.py +29 -3
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_lane_vocabulary.py +8 -2
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_morning_line.py +3 -1
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_not_coding.py +8 -8
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_onboarding_walk.py +1 -1
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_phone_walk_ux.py +58 -4
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_pypi_downloads.py +31 -2
- taskuary-0.3.6.4/tests/test_read_text.py +36 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_remote_assistant.py +7 -9
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_always_drafts.py +5 -5
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_order_and_research.py +1 -1
- taskuary-0.3.6.4/tests/test_same_failure_is_quiet.py +30 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_seeded_reports.py +41 -9
- taskuary-0.3.6.4/tests/test_social.py +263 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_the_exe_ships_what_the_wheel_ships.py +11 -5
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_urgent_and_handoff.py +1 -1
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_verdict_shape.py +14 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_walk_order.py +13 -7
- taskuary-0.3.6.4/tests/test_workerstate_said.py +19 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_zz_toolcatalog.py +18 -0
- taskuary-0.3.6.2/taskuary/web/assets/StudioScene-DXPO8NCz.js +0 -3840
- taskuary-0.3.6.2/taskuary/web/assets/index-D5A7qNvG.js +0 -498
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/LICENSE +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/setup.cfg +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/__init__.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/acp.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/agents.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/aidefaults.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/aisetup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/alchemy.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/appfacts.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/artifacts.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/assistantblocks.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/aws.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/azure.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/blackboard.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/brief.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/browserview.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/calendar.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/categories.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/chains.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/chatformat.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/chatservers.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/ci.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/cli_connections.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/cli_install_terminal.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/cliinstall.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/climodels.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/clis.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/clisetup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/compose.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/config.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/connectorcatalog.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/context.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/continuity.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/counsel.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/databases.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/db.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/deps.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/desktop.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/devtools.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/digest.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/docsync.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/evalset.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/evening.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/files.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/funnel_presentation.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/github.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/guard.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/handbook.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/handraise.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/histgen.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/hooks.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/hub.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/images.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/imapmail.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/imessage.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/intacct.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/interview.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/invoice_workflow.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/jev.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/knowledge.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/lanes.json +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/learn.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/learnedgraph.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/linkedin.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/live.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/llm.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/logs.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/markets.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/mcp.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/messengers.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/msauth.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/mssql.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/operations.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/outbound.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/outbox.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/ownwork.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/phone.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/playbooks.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/pm.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/policy.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/problems.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_inventory.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_membership.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_navigation.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_projection.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_rail.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_reads.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/processing_startup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/projects.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/promptmap.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/proof.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/proposals.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/quickbooks.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/rank.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/redact.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/research.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/reshape.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/responder.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/retention.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/robinhood.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/routingmemory.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/semantic.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/senders.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/session_artifacts.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/sessionfiles.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/settings_schema.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/setup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/sharepoint.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/sheets.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/simplefin.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/skillimport.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/skills/soul-interview/SKILL.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/skills/taskuary-setup/SKILL.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/spawn.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/teller.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/analyst.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/coordinator.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/counsel.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/digest.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/history/counsel-0.3.3.5.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/how-it-works.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/learned.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/marketer.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/playbook.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/profile.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/researcher.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/soul.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/style.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/templates/trader.md +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/terminal.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/testing.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/toil.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/treg.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/update.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/verdicts.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/voice.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/wabridge.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/waitroom.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/walk.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/favicon.ico +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/favicon.png +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/assistant.png +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/board.png +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/connections.png +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/docs.png +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/hub.png +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/reports.png +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/settings.png +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/web/walk/tasks.png +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/webguard.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/bridge.mjs +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/package.json +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/policy.mjs +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/policy.test.mjs +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/roster.mjs +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whatsapp/roster.test.mjs +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/whoami.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/witness.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/workflows.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary/zoho.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/dependency_links.txt +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/entry_points.txt +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/requires.txt +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/taskuary.egg-info/top_level.txt +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_acp.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_answer_route.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_environment.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_identity.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_profiles.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_sentence.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_source.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_agent_wall.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ai_defaults.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_aisetup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_alchemy.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_answered_yourself.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_answers.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_api_worker_signals.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_app_uptime.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_appfacts.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_approval_interrupt.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_acts.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_can_look_things_up.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_doorways.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_ideas.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_notifications.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_opens.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_assistant_verdicts.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_async_triage.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_audit_chain.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_audit_fixes.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_auto_start.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_aws_region.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_blackboard.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_brain_layer.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_brain_reaches_the_session.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_browser_session.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_browser_workflow.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_browserview.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_calendar.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_calendar_today.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_categories.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cc.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cc_triage.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_doors.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_freshness.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_is_not_one_task.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_proposals.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_queue.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_relationship.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_retention.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chat_setup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chatservers.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_chinese_clis.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_clean_context.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_connections.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_failure.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_install.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_install_terminal.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_on_fresh_path.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_setup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cli_update.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_climodels.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_clis.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cloud.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cloud_sources.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_coder_session_continuity.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_completion_freshness.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_compose.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_compose_sources.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_compose_workflows.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_concierge_counsel.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_config.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_context.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_context_refresh_freshness.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_coordination.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_correction_doors.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_counsel.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_counsel_consumers.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_counsel_migration.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_counsel_sections.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_current_restore.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_cwlogs_paging.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_databases.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_deps.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_desktop.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_devin.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_devtools.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_diff_review.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_dispatch_retries.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_docs_flow.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_duplicate_connectors.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_email_chains.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_email_identity_routing.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ending_a_run_writes_the_answer.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_evening_brief.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_every_cli_startable.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_explicit_completion.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_factory.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_feed_working.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_files.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_final_answer_capture.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_finished_chat_stays_finished.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_floating_assistant.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_follow_up_verdict.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_fresh_evaluation.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_freshness.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_freshness_walk.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_general.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_github_auto.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_github_images.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_guard.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_handbook.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_handbook_topics.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_handoff_channels.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_handraise.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_harvest.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_histgen.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_home_is_never_yours.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_hooks_events.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_hooks_version.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ignore_sender.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_ignore_sender_quiets_its_work.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_images.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_imap_catchup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_imap_history.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_imapmail.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_imessage.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_intacct.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_interrupted_work.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_invite_is_not_work.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_invoice_workflow.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_jev.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_judge_reads_the_conclusion.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_knowledge.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_learnedgraph.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_lifecycle.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_lifespan_loops_are_guarded.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_linkedin.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_linkedin_signin.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_live.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_local_file.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mail_catchup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mail_fetch_cost.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mail_folders.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mark_read.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_markets.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mcp.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_meeting_prep.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_message_thread.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_messengers.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_msauth.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_mssql.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_muse.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_noop_ending.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_note_retrieval.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_one_app_one_reason.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_one_pty_one_geometry.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_only_your_own_thread.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_openai_compatible_brains.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_operations.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_outbound_reports.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_outbox.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_own_rows_no_reply.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_playbook_setup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_playbooks.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_pm.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_poll_lanes.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_poll_overlap.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_poll_parallel.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_poll_sources.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_pr_comments.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_problems.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_problems_dismiss.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_procedure_selection.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_processing_demo_replay.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_processing_ledger.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_profile_is_a_role.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_projects.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_prompt_sources.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_promptmap_and_catalog.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_proof_ci_proposals.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_quickbooks.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_qwen.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_rank.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_rate_limit.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_recent_closures.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reclassify.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_redact.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_redact_doors.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_attachments.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_channels.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_envelope.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_needs_a_correspondent.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_sources.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reply_voice.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_repo_choice_triage.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_alerts.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_deliver.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_headline.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_prompt_isolation.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_reach.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_refusal.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_routing.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_report_triage.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_research.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_research_more.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_review_task.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_reviews.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_robinhood.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_routing_memory.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_s3_poll_paging.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_scopes.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_seed_fits_a_tty.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_selector_vocabulary.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_semantic.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_send_outcomes.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_send_targets.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_sender_trust.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_sender_words.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_session_artifacts.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_session_continuity.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_session_files.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_settings_schema.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_setup.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_setup_skill.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_setup_walk.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_sheets_sharepoint.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_simplefin.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_skillimport.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_someone_else_replied.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_soul_interview.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_startup_contract.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_stay_open.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_stay_open_doors.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_store_app_cli.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_store_hotpaths.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_store_pokes.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_sync_clock.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_task_ask.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_task_checklist.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_task_controls_operations.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_task_identity.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_teller.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_terminal.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_the_split_holds.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_toil.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_tracker_revisions.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_treg.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_dataset.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_errors.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_images.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_pr_rule.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_triage_retry_sweep.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_update.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_update_refused.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_verdict_paths.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_verdict_sticks.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_vision.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_voice.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_wabridge.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_wabridge_log_trim.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_waitroom.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_watermark.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_web_entrypoint.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_webguard.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_whatsapp_documents.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_whatsapp_images.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_whoami.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_why_not_started.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_withdrawn.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_witness.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_brief.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_events.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_resumes.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_scenarios.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_worker_surfaces.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_workflows.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_zz_chipverbs.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_zz_lastword.py +0 -0
- {taskuary-0.3.6.2 → taskuary-0.3.6.4}/tests/test_zz_setupchat.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: taskuary
|
|
3
|
-
Version: 0.3.6.
|
|
3
|
+
Version: 0.3.6.4
|
|
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.6.
|
|
86
|
+
Taskuary is early—currently **v0.3.6.4**—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
|
|
@@ -270,10 +270,10 @@ outside systems, send messages, run tools, or start agents. Its changes reset wh
|
|
|
270
270
|
|
|
271
271
|
## Installs
|
|
272
272
|
|
|
273
|
-

|
|
274
274
|
|
|
275
275
|
Updated daily from PyPI with mirror traffic excluded. The raw series is
|
|
276
|
-
[
|
|
276
|
+
[downloads.csv on the `stats` branch](https://github.com/ldbumble/taskuary/blob/stats/downloads.csv).
|
|
277
277
|
|
|
278
278
|
## Documentation
|
|
279
279
|
|
|
@@ -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.6.
|
|
21
|
+
Taskuary is early—currently **v0.3.6.4**—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
|
|
@@ -205,10 +205,10 @@ outside systems, send messages, run tools, or start agents. Its changes reset wh
|
|
|
205
205
|
|
|
206
206
|
## Installs
|
|
207
207
|
|
|
208
|
-

|
|
209
209
|
|
|
210
210
|
Updated daily from PyPI with mirror traffic excluded. The raw series is
|
|
211
|
-
[
|
|
211
|
+
[downloads.csv on the `stats` branch](https://github.com/ldbumble/taskuary/blob/stats/downloads.csv).
|
|
212
212
|
|
|
213
213
|
## Documentation
|
|
214
214
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "taskuary"
|
|
7
|
-
version = "0.3.6.
|
|
7
|
+
version = "0.3.6.4"
|
|
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" }
|
|
@@ -71,10 +71,11 @@ include = ["taskuary*"]
|
|
|
71
71
|
[tool.setuptools.package-data]
|
|
72
72
|
# whatsapp/ too: the bridge error tells you to run `node bridge.mjs` out of the package, and
|
|
73
73
|
# a pip install without it is an instruction pointing at a directory that does not exist.
|
|
74
|
-
#
|
|
75
|
-
#
|
|
74
|
+
# *.json: every data file at the package root is read at runtime - lanes.json is the ONE lane
|
|
75
|
+
# vocabulary, and triage_kind_rules.json, settings_schema.json and connectorcatalog.json were all
|
|
76
|
+
# missing from the wheel once (the container died on the first; 2026-09-23). Name them by glob.
|
|
76
77
|
# A GLOB HERE DOES NOT CROSS A DIRECTORY SEPARATOR: `web/*` matches nothing inside `web/assets/`,
|
|
77
78
|
# which is why that line exists - and `web/walk/*` had to be added after the setup walk's nine
|
|
78
79
|
# screenshots shipped broken. Every new subdirectory under web/ needs its own line, or its files
|
|
79
80
|
# are simply absent from the wheel while the repo tree looks right.
|
|
80
|
-
taskuary = ["
|
|
81
|
+
taskuary = ["*.json", "web/*", "web/assets/*", "web/walk/*", "templates/*.md", "templates/history/*.md", "skills/*/*.md", "whatsapp/*"]
|
|
@@ -25,7 +25,7 @@ it brings in until it says something useful and surprising"). Handed only subjec
|
|
|
25
25
|
wrote 'no content given' in its own notes; so the check now reads WHAT PEOPLE SAID (the words of every
|
|
26
26
|
human thread of the last two days, the owner's lines marked), who is OUT OF OFFICE (from auto-replies -
|
|
27
27
|
a chase to someone away is worse than silence), the CALENDAR, and the actual words in every rolled-up
|
|
28
|
-
arrival (including machine mail), with each report's schedule and each failure's cause beside the count. That is where "Yittie said exporting freezes the
|
|
28
|
+
arrival (including machine mail), with each report's schedule, when it last ran and what that run did, and each failure's cause beside the count. That is where "Yittie said exporting freezes the
|
|
29
29
|
app - and she is in Monday's meeting" comes from.
|
|
30
30
|
|
|
31
31
|
It also leaves itself a NOTE: each check ends with what it looked at and found nothing in, when
|
|
@@ -503,7 +503,7 @@ def blk_label(bid: str) -> str:
|
|
|
503
503
|
# ── the model's pass: its own read, given what it already said ───────────────────────────────
|
|
504
504
|
CONTRACT = ('\n\nYou are writing your POST on the owner\'s Timeline - the short list of things worth saying right now. You get '
|
|
505
505
|
'CANDIDATES the hub found itself (each with a key), WHAT PEOPLE SAID (the words, by thread), who is OUT OF OFFICE, the '
|
|
506
|
-
'CALENDAR, what arrived (with each report\'s schedule and each failure\'s cause), what got done, what is open, and WHAT '
|
|
506
|
+
'CALENDAR, what arrived (with each report\'s schedule, when it last ran and what that run did, and each failure\'s cause), what got done, what is open, and WHAT '
|
|
507
507
|
'YOU ALREADY SAID. Answer JSON only: {"say": [{"key": "<a candidate key, or idea:<short-slug> for a thought of your own>", '
|
|
508
508
|
'"text": "<one line, under 30 words, first person: the fact and what I would do - quote the phrase or name the cause when there is one>", '
|
|
509
509
|
'"section": "<people|loose|ideas|systems - which part of the post this belongs under: people = what somebody said '
|
|
@@ -536,14 +536,26 @@ def _schedules(store) -> dict:
|
|
|
536
536
|
nothing without its clock: 25 digests in two days on an on_startup report is 25 launches, not a
|
|
537
537
|
scheduler bug, and two seeded reports at one timestamp is one launch, not a restart to explain."""
|
|
538
538
|
from . import reports
|
|
539
|
-
out = {}
|
|
539
|
+
out, st = {}, store.get_settings()
|
|
540
540
|
for src in store.list_sources(active_only=False):
|
|
541
541
|
if src.get('Channel') != 'report': continue
|
|
542
542
|
try: c = json.loads(src.get('ConfigJson') or '{}')
|
|
543
543
|
except ValueError: continue
|
|
544
|
-
out[c.get('title') or src.get('Address')] = reports.schedule_words(c)
|
|
544
|
+
out[c.get('title') or src.get('Address')] = reports.schedule_words(c) + _last_run(st, src)
|
|
545
545
|
return out
|
|
546
546
|
|
|
547
|
+
def _last_run(settings: dict, src: dict) -> str:
|
|
548
|
+
"""'; last ran Tue 22 Sep 20:37, nothing to report so nothing was filed' - or ''. The clock alone
|
|
549
|
+
misled: a routed report whose judge holds a run back files NO message, so the newest mid read as
|
|
550
|
+
the last firing and a 140-minute timer looked stalled two runs after it fired on time (TQ-0685).
|
|
551
|
+
The run record on the source (reports.LAST_RUN) is the receipt the arrivals cannot carry."""
|
|
552
|
+
from .reports import LAST_RUN
|
|
553
|
+
try: rec = json.loads(settings.get(f"{LAST_RUN}{src['SourceId']}") or '{}')
|
|
554
|
+
except (ValueError, TypeError): rec = {}
|
|
555
|
+
if not rec.get('at'): return ''
|
|
556
|
+
what = 'failed' if rec.get('failed') else f"posted mid {rec['message_id']}" if rec.get('message_id') else 'nothing to report so nothing was filed'
|
|
557
|
+
return f"; last ran {_when(rec['at'])}, {what}"
|
|
558
|
+
|
|
547
559
|
_FAILS = re.compile(r'fail|error|denied|timeout|could not|unable', re.I)
|
|
548
560
|
_GH_FAILED = re.compile(r'^(.+?) Failed in ', re.M) # the job lines of GitHub's "Run failed" mail
|
|
549
561
|
def _cause(r: dict) -> str:
|
|
@@ -852,7 +864,7 @@ def system_checks(store, source_ids=None, inline=None) -> str:
|
|
|
852
864
|
ids = saved if source_ids is None else _ids(source_ids)
|
|
853
865
|
subs = own if inline is None else _inline(inline)
|
|
854
866
|
if not ids and not subs:
|
|
855
|
-
return '(none selected - add a data source, or choose saved data views, on Reports ->
|
|
867
|
+
return '(none selected - add a data source, or choose saved data views, on Reports -> Advisor)'
|
|
856
868
|
from . import reports
|
|
857
869
|
found = {s['SourceId']: s for s in store.list_sources(active_only=False) if s.get('Channel') == 'report'}
|
|
858
870
|
jobs = [] # (title, cfg to render, or a note to print instead)
|
|
@@ -862,7 +874,7 @@ def system_checks(store, source_ids=None, inline=None) -> str:
|
|
|
862
874
|
try: cfg_ = json.loads(src.get('ConfigJson') or '{}')
|
|
863
875
|
except ValueError: cfg_ = {}
|
|
864
876
|
title = str(cfg_.get('title') or src.get('Address') or f'report {sid}')
|
|
865
|
-
if cfg_.get('type') == 'assistant': jobs.append((title, None, 'Skipped: an
|
|
877
|
+
if cfg_.get('type') == 'assistant': jobs.append((title, None, 'Skipped: an Advisor cannot watch itself.'))
|
|
866
878
|
else: jobs.append((title, cfg_, None))
|
|
867
879
|
for i, sub in enumerate(subs, 1):
|
|
868
880
|
jobs.append((str(sub.get('label') or sub.get('title') or '').strip() or f"{sub.get('type')} #{i}", sub, None))
|
|
@@ -1166,10 +1178,10 @@ def _idea_message(store, i: dict, a: dict, report_title=None) -> tuple:
|
|
|
1166
1178
|
active = bool(task and task.get('Status') in ('open', 'in_progress', 'waiting'))
|
|
1167
1179
|
working = bool(active and any(r.get('Status') == 'running' for r in store.list_runs(tid)))
|
|
1168
1180
|
stamp = i.get('LastSaid') or i.get('FirstSeen') or datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
|
1169
|
-
who = report_title or '
|
|
1181
|
+
who = report_title or 'Advisor'
|
|
1170
1182
|
# one arrival per idea: the stamp in the id made every re-say a fresh message, and a fresh task once the first closed
|
|
1171
1183
|
msg = {'external_id': f"idea:{i['IdeaId']}", 'channel': CHANNEL, 'from_name': who, 'source_name': who,
|
|
1172
|
-
'conversation_id': str(i.get('Key') or f"idea:{i['IdeaId']}"), 'subject': f"
|
|
1184
|
+
'conversation_id': str(i.get('Key') or f"idea:{i['IdeaId']}"), 'subject': f"Advisor idea: {_cut(i.get('Text'), 100)}",
|
|
1173
1185
|
'sent_at': stamp, 'body': str(i.get('Text') or '') + (f"\n\nwhy: {a.get('why')}" if a.get('why') else ''),
|
|
1174
1186
|
'idea_context': {'report': report_title, 'kind': i.get('Kind'),
|
|
1175
1187
|
'linked_task': f"{task_ref(tid)} [{task.get('Status')}] {_short(task.get('Title'), 80)}" if task else None,
|
|
@@ -1448,7 +1460,7 @@ def _run(store, llm, instruction, watch_source_ids, watch_sources, systems_only=
|
|
|
1448
1460
|
if systems_only and not (_ids(watch_source_ids) or _inline(watch_sources)):
|
|
1449
1461
|
why = ('this report reads nothing: no Taskuary block is ticked and no data source is chosen '
|
|
1450
1462
|
'- tick a block, or choose a source, on the report')
|
|
1451
|
-
logger.warning(f"assistant: {report_title or '
|
|
1463
|
+
logger.warning(f"assistant: {report_title or 'Advisor'} ran and read nothing - {why}")
|
|
1452
1464
|
return {'ran': True, 'said': 0, 'reads_nothing': True, 'summary': why, 'inputs': '',
|
|
1453
1465
|
'reviewed': {'notes': '', 'scope': 'nothing', 'systems': 0, 'why': why}}
|
|
1454
1466
|
state = {i['Key']: i for i in store.list_ideas()}
|
|
@@ -1522,7 +1534,7 @@ def _run(store, llm, instruction, watch_source_ids, watch_sources, systems_only=
|
|
|
1522
1534
|
# chose "every run", in which case the check still says it ran, in one line, with what it
|
|
1523
1535
|
# read behind it. A setting that promises every run and then shows nothing is a lie.
|
|
1524
1536
|
if not always_post: return {'ran': True, 'said': 0, 'reviewed': rv, 'inputs': read}
|
|
1525
|
-
who = (report_title or '
|
|
1537
|
+
who = (report_title or 'Advisor') if own_post else 'Advisor'
|
|
1526
1538
|
me = f'assistant:{report_id}' if own_post else 'assistant'
|
|
1527
1539
|
mid = store.add_message({'TaskId': None, 'ExternalId': f'{me}:{stamp}', 'ConversationId': me, 'Channel': CHANNEL,
|
|
1528
1540
|
'SourceName': who, 'Subject': f'{who} - nothing to report', 'FromName': who,
|
|
@@ -1551,7 +1563,7 @@ def _run(store, llm, instruction, watch_source_ids, watch_sources, systems_only=
|
|
|
1551
1563
|
head = rows[0]['Text'] if len(rows[0]['Text']) <= 90 else rows[0]['Text'][:90].rsplit(' ', 1)[0] + '…'
|
|
1552
1564
|
subj = head + (f' (+{len(rows) - 1} more)' if len(rows) > 1 else '')
|
|
1553
1565
|
identity = f'assistant:{report_id}' if own_post else 'assistant'
|
|
1554
|
-
name = (report_title or '
|
|
1566
|
+
name = (report_title or 'Advisor') if own_post else 'Advisor'
|
|
1555
1567
|
mid = store.add_message({'TaskId': None, 'ExternalId': f'{identity}:{stamp}', 'ConversationId': identity, 'Channel': CHANNEL,
|
|
1556
1568
|
'SourceName': name, 'Subject': subj, 'FromName': name, 'SentAt': stamp,
|
|
1557
1569
|
'BodyText': body, 'Status': 'feed'})
|
|
@@ -1623,7 +1635,7 @@ def act(store, idea_id: int, verb: str, actor: str = 'owner', llm=None, days: in
|
|
|
1623
1635
|
# This is NEW work noticed after an earlier task was completed. A message can point
|
|
1624
1636
|
# at only one task, so do not steal it from history or rename/reopen the completed
|
|
1625
1637
|
# task. Carry the evidence into a fresh assistant-owned task instead.
|
|
1626
|
-
title = str(a.get('title') or i.get('Text') or '
|
|
1638
|
+
title = str(a.get('title') or i.get('Text') or 'Advisor follow-up').strip()[:200]
|
|
1627
1639
|
source_text = str(message.get('BodyText') or '').strip()
|
|
1628
1640
|
summary = str(i.get('Text') or '').strip()
|
|
1629
1641
|
if source_text and source_text not in summary: summary += f'\n\nSource message: {source_text}'
|
|
@@ -1640,6 +1652,11 @@ def act(store, idea_id: int, verb: str, actor: str = 'owner', llm=None, days: in
|
|
|
1640
1652
|
brief = str(a.get('title') or i.get('Text') or task.get('Title') or '').strip()
|
|
1641
1653
|
why = str(a.get('why') or '').strip()
|
|
1642
1654
|
if why: brief += f'\n\nWhy the assistant raised it: {why}'
|
|
1655
|
+
# ...and the report it points at, or the agent can only ask for it to be pasted (2026-09-23)
|
|
1656
|
+
src = store.get_message(int(a['mid'])) if str(a.get('mid') or '').isdigit() else None
|
|
1657
|
+
if src and src.get('Channel') != 'assistant' and src.get('BodyText'):
|
|
1658
|
+
brief += (f"\n\nThe source - {src.get('Subject') or 'the message'}:\n"
|
|
1659
|
+
+ src['BodyText'].split('\n--- raw data ---')[0].strip()[:6000])
|
|
1643
1660
|
if kind == 'general':
|
|
1644
1661
|
ingest._spawn(_auto_general, store, tid, brief)
|
|
1645
1662
|
elif store.get_settings().get('coder_auto_enabled') == '1':
|
|
@@ -336,6 +336,15 @@ def test_connector(store, cid: int) -> dict:
|
|
|
336
336
|
elif c['Type'] == 'robinhood':
|
|
337
337
|
from . import robinhood
|
|
338
338
|
detail = robinhood.test(store, c)
|
|
339
|
+
elif c['Type'] in ('bluesky', 'mastodon'):
|
|
340
|
+
# whoami, like LinkedIn: the one call that proves the credential AND comes back
|
|
341
|
+
# with something the owner recognises. Posting would be a strange thing for Test.
|
|
342
|
+
from .reports import REGISTRY, resolve_cfg
|
|
343
|
+
rtype = f"{c['Type']}_me"
|
|
344
|
+
out = REGISTRY[rtype](resolve_cfg(store, {'type': rtype}))
|
|
345
|
+
row = (out.get('rows') or [{}])[0]
|
|
346
|
+
detail = (f"signed in as {row.get('handle') or '?'}"
|
|
347
|
+
f" - {row.get('followers')} followers, {row.get('posts')} posts")
|
|
339
348
|
elif c['Type'] == 'linkedin':
|
|
340
349
|
# whoami, which is the one call that proves the token AND returns something the
|
|
341
350
|
# owner recognises - a post would be a strange thing for a Test button to do
|
|
@@ -122,6 +122,11 @@ def main():
|
|
|
122
122
|
'this transcript, and draft the reply the sender gets (you are not '
|
|
123
123
|
'sending it - the owner approves it). Give one sentence on what you did '
|
|
124
124
|
'or found. Do not run this while waiting on the owner.')
|
|
125
|
+
ap.add_argument('--reply', metavar='TEXT',
|
|
126
|
+
help="write the reply the person who asked will get, in your own words - it becomes this "
|
|
127
|
+
"task's pending reply for the owner to approve (you are not sending it), and "
|
|
128
|
+
"finishing keeps it instead of redrafting. Use - to read it from stdin.")
|
|
129
|
+
ap.add_argument('--reply-file', metavar='PATH', help='--reply, read from a file (for a long or multi-line reply)')
|
|
125
130
|
args = ap.parse_args()
|
|
126
131
|
if args.demo:
|
|
127
132
|
import os, tempfile
|
|
@@ -133,6 +138,29 @@ def main():
|
|
|
133
138
|
# --done goes over HTTP, unlike --note. A note is a database row and any process can write
|
|
134
139
|
# one; ENDING a task needs the live session's scrollback, which exists only inside the
|
|
135
140
|
# running server - this process would find no transcript and wrap an empty one.
|
|
141
|
+
if args.reply is not None or args.reply_file:
|
|
142
|
+
import os, sys, requests
|
|
143
|
+
try: sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
144
|
+
except (AttributeError, OSError): pass
|
|
145
|
+
tid = os.environ.get('TASKUARY_TASK')
|
|
146
|
+
if not str(tid).isdigit():
|
|
147
|
+
print('not in a Taskuary session - TASKUARY_TASK is not set, so there is no task to reply on')
|
|
148
|
+
return
|
|
149
|
+
if args.reply_file: text = open(args.reply_file, encoding='utf-8').read()
|
|
150
|
+
else: text = sys.stdin.read() if args.reply == '-' else args.reply
|
|
151
|
+
srv = config.load()['server']
|
|
152
|
+
host = '127.0.0.1' if srv.get('host') in ('0.0.0.0', '::', '', None) else srv['host']
|
|
153
|
+
base = f"http://{host}:{srv.get('port') or 7787}"
|
|
154
|
+
hdr = {'X-Taskuary-Token': srv['token']} if srv.get('token') else {}
|
|
155
|
+
try:
|
|
156
|
+
r = requests.post(f'{base}/api/agent/reply', timeout=60, headers=hdr,
|
|
157
|
+
json={'task_id': int(tid), 'text': text, 'agent': os.environ.get('TASKUARY_AGENT') or 'agent'})
|
|
158
|
+
out = r.json() if r.headers.get('content-type', '').startswith('application/json') else {}
|
|
159
|
+
except Exception as e:
|
|
160
|
+
print(f'could not reach Taskuary at {base}: {e}'); return
|
|
161
|
+
print('reply saved on the task, waiting on the owner to approve and send it.' if out.get('ok')
|
|
162
|
+
else f"not saved: {out.get('why') or out.get('detail') or r.text[:200]}")
|
|
163
|
+
return
|
|
136
164
|
if args.done is not None:
|
|
137
165
|
import os, sys, requests
|
|
138
166
|
try: sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
@@ -105,6 +105,54 @@ def reply_target(store, task_id: int):
|
|
|
105
105
|
return next((m['MessageId'] for m in reversed(store.list_messages(task_id)) if m.get('Status') != 'context'), None)
|
|
106
106
|
|
|
107
107
|
|
|
108
|
+
# ── the agent's own words ───────────────────────────────────────────────────────────────
|
|
109
|
+
# The agent that did the work often writes the better answer: it knows what it found, and a second
|
|
110
|
+
# model redrafting from its transcript loses the nuance (the owner, 2026-09-23: "sometimes the agent
|
|
111
|
+
# that did the work is better for response than another ai generating it based off of transcript").
|
|
112
|
+
# It used to have no way to hand that answer over - it asked "should I draft the reply?", wrote it
|
|
113
|
+
# on its own screen, and the task's reply stayed empty until the responder wrote a different one.
|
|
114
|
+
# Now it says so: `taskuary --reply` (a shell) or a [[TASKUARY-REPLY]] block (the general chat), the
|
|
115
|
+
# text becomes the task's pending reply as written, and the end of the run keeps it.
|
|
116
|
+
AGENT_DRAFT = 'agent:'
|
|
117
|
+
|
|
118
|
+
def agent_drafted(rv) -> bool:
|
|
119
|
+
return bool(rv) and str(rv.get('DraftBy') or '').startswith(AGENT_DRAFT) and bool(str(rv.get('DraftText') or '').strip())
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def own_draft(store, task_id: int):
|
|
123
|
+
"""The pending reply the agent wrote itself, if there is one."""
|
|
124
|
+
return next((r for r in (store.pending_review(task_id, 'draft_reply', live_only=False),
|
|
125
|
+
store.pending_review(task_id, 'draft', live_only=False)) if agent_drafted(r)), None)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def agent_reply(store, task_id: int, text: str, agent: str = 'agent', run_id: int = None) -> dict:
|
|
129
|
+
"""Put the agent's reply on the task as the pending draft - the same review the responder would
|
|
130
|
+
write into (held, live or new; one per answer, PW-236), marked as the agent's. Nothing is sent:
|
|
131
|
+
the owner approves it like every other reply."""
|
|
132
|
+
text = str(text or '').strip()
|
|
133
|
+
if not text: return {'ok': False, 'why': 'no reply text'}
|
|
134
|
+
held = store.held_review(task_id) or {}
|
|
135
|
+
mid = reply_target(store, task_id) or held.get('MessageId')
|
|
136
|
+
if not mid: return {'ok': False, 'why': 'nobody is waiting on a reply on this task - there is no one to draft it to'}
|
|
137
|
+
# work the owner started here (a brief typed in the chat) has only their own words behind it: the agent's
|
|
138
|
+
# answer IS the result, and filing it as a reply "waiting on your approval" addressed it to them (2026-09-23)
|
|
139
|
+
if not held and no_one_behind((store.get_message(mid) or {}).get('Channel')):
|
|
140
|
+
return {'ok': False, 'why': 'nobody sent this task - its result stays on the task, there is no one to reply to'}
|
|
141
|
+
live = None if held else (store.pending_review(task_id, 'draft_reply', live_only=False) or store.pending_review(task_id, 'draft', live_only=False))
|
|
142
|
+
why = f'{agent} wrote this reply in its session - approve to send'
|
|
143
|
+
if held:
|
|
144
|
+
rid = held['ReviewId']; store.unhold_review(rid, why)
|
|
145
|
+
elif live:
|
|
146
|
+
rid = live['ReviewId']; store.update_review_reason(rid, why, run_id)
|
|
147
|
+
else:
|
|
148
|
+
rid = store.add_review({'TaskId': task_id, 'MessageId': mid, 'RunId': run_id, 'Kind': 'draft_reply', 'Status': 'pending', 'Reason': why})
|
|
149
|
+
rv = store.get_review(rid) or {}
|
|
150
|
+
if rv.get('MessageId') != mid: store.update_review_message(rid, mid)
|
|
151
|
+
store.update_review_draft(rid, text, run_id or rv.get('RunId'), by=AGENT_DRAFT + agent)
|
|
152
|
+
store.add_comment(task_id, agent, 'agent', f'{agent} drafted the reply itself - it is on the task, waiting on your approval.')
|
|
153
|
+
return {'ok': True, 'review_id': rid, 'message_id': mid}
|
|
154
|
+
|
|
155
|
+
|
|
108
156
|
# ── the cheap ending ────────────────────────────────────────────────────────────────────
|
|
109
157
|
# Almost everything a keyboard can do goes to the coding agent (the owner's rule), and the
|
|
110
158
|
# whole bargain is that an agent with nothing to do says "nothing to do here" and stops CHEAPLY.
|
|
@@ -213,7 +261,7 @@ def finish(store, task_id: int, rep: dict, run_id: int = None, actor: str = 'cod
|
|
|
213
261
|
# nobody can send does not hold a task the owner just closed
|
|
214
262
|
if owner_done and mid and not can_send: mid = None
|
|
215
263
|
# a held draft is proof somebody IS waiting on an answer, so it is never quietly dropped here
|
|
216
|
-
if mid and not held and nobody_waiting(store, mid, rep):
|
|
264
|
+
if mid and not held and not own_draft(store, task_id) and nobody_waiting(store, mid, rep):
|
|
217
265
|
store.add_comment(task_id, actor, 'agent', 'Nothing needed doing here and the sender is not waiting on an '
|
|
218
266
|
'answer - filed with the report, no reply drafted.')
|
|
219
267
|
mid = None
|
|
@@ -432,6 +480,16 @@ def raise_reply(store, task_id: int, mid: int, run_id: int, rep: dict,
|
|
|
432
480
|
rid = store.add_review({'TaskId': task_id, 'MessageId': mid, 'RunId': run_id, 'Kind': 'draft_reply', 'Status': 'pending',
|
|
433
481
|
'Reason': why if fresh.get('state') in ('changed', 'unresolved') else 'coder finished the work - reply awaiting approval'})
|
|
434
482
|
if (held or live) and (held or live).get('MessageId') != mid: store.update_review_message(rid, mid)
|
|
483
|
+
rv = store.get_review(rid) or {}
|
|
484
|
+
if agent_drafted(rv):
|
|
485
|
+
# the agent that did the work wrote this reply itself (agent_reply): its words stand and no second
|
|
486
|
+
# model rewrites them - only a thread that moved on (or could not be checked) is flagged for a reread
|
|
487
|
+
who = str(rv.get('DraftBy'))[len(AGENT_DRAFT):] or 'the agent'
|
|
488
|
+
store.update_review_reason(rid, f"{who}'s own reply from the session - approve to send"
|
|
489
|
+
+ (' (the thread moved on after it was written - reread it)' if fresh.get('state') == 'changed' else ''), run_id)
|
|
490
|
+
if fresh.get('state') in ('changed', 'unresolved'): store.mark_review_stale(rid)
|
|
491
|
+
_notify_done(store, task_id, rid)
|
|
492
|
+
return
|
|
435
493
|
src = complete_result or resolution_text(rep)
|
|
436
494
|
if fresh.get('state') == 'changed' and fresh.get('latest'):
|
|
437
495
|
l = fresh['latest']
|
|
@@ -450,6 +508,10 @@ def raise_reply(store, task_id: int, mid: int, run_id: int, rep: dict,
|
|
|
450
508
|
except Exception as e: logger.warning(f'reply draft failed for task {task_id}: {e}')
|
|
451
509
|
# a refresh that failed is an unresolved freshness state the owner sees: the draft waits, stale, for one that succeeds
|
|
452
510
|
if fresh.get('state') == 'unresolved': store.mark_review_stale(rid)
|
|
511
|
+
_notify_done(store, task_id, rid)
|
|
512
|
+
|
|
513
|
+
|
|
514
|
+
def _notify_done(store, task_id: int, rid: int) -> None:
|
|
453
515
|
# the ping that matters most: work FINISHED and its reply is sitting on the task on you
|
|
454
516
|
if (store.get_settings().get('notify_level') or 'needs_me') != 'off':
|
|
455
517
|
from .outbound import notify
|
|
@@ -463,3 +525,5 @@ def raise_reply(store, task_id: int, mid: int, run_id: int, rep: dict,
|
|
|
463
525
|
try: notify(store, f'{task_ref(task_id)} is done - the reply is drafted and waiting on '
|
|
464
526
|
f'your approval on the task.\n{head}{tail}')
|
|
465
527
|
except Exception as e: logger.warning(f'notify failed for task {task_id}: {e}')
|
|
528
|
+
|
|
529
|
+
|