taskuary 0.3.7.0__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.0/taskuary.egg-info → taskuary-0.3.7.2}/PKG-INFO +30 -27
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/README.md +29 -26
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/pyproject.toml +1 -1
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/aidefaults.py +21 -4
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/chatformat.py +17 -1
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/cli.py +1 -1
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/concierge.py +28 -9
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/demo.py +1 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/doorway_browse.py +72 -9
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/evalset.py +49 -1
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/funnel.py +10 -2
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/funnel_selection.py +3 -2
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/jev.py +34 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/llm.py +27 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/lookups.py +12 -4
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/remote_assistant.py +54 -10
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/server.py +98 -15
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/settings_schema.json +2 -2
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/store.py +12 -6
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/terminal.py +12 -2
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/toolcatalog.py +8 -3
- taskuary-0.3.7.0/taskuary/web/assets/AssistantGame-CgEOViMV.js → taskuary-0.3.7.2/taskuary/web/assets/AssistantGame-BZJj3XwN.js +3 -3
- taskuary-0.3.7.0/taskuary/web/assets/GameScene-ME4FVYZZ.js → taskuary-0.3.7.2/taskuary/web/assets/GameScene-ATV2SyYO.js +1 -1
- taskuary-0.3.7.0/taskuary/web/assets/HubView-BANr9hv3.js → taskuary-0.3.7.2/taskuary/web/assets/HubView-DtpvsbeL.js +1 -1
- taskuary-0.3.7.0/taskuary/web/assets/StudioScene-D19mVoMT.js → taskuary-0.3.7.2/taskuary/web/assets/StudioScene-D4IlNRXi.js +1 -1
- taskuary-0.3.7.0/taskuary/web/assets/TasksView-Cy_KQBIk.js → taskuary-0.3.7.2/taskuary/web/assets/TasksView-B7m8zBYu.js +1 -1
- taskuary-0.3.7.2/taskuary/web/assets/index-BKrB4ObA.js +602 -0
- taskuary-0.3.7.2/taskuary/web/assets/index-DUxLnhhx.css +32 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/index.html +2 -2
- {taskuary-0.3.7.0 → taskuary-0.3.7.2/taskuary.egg-info}/PKG-INFO +30 -27
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary.egg-info/SOURCES.txt +10 -7
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_ai_defaults.py +16 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_api.py +20 -0
- taskuary-0.3.7.2/tests/test_button_promises.py +32 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_coder_session_continuity.py +16 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_continue_session.py +16 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_funnel.py +3 -3
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_morning_line.py +8 -5
- taskuary-0.3.7.2/tests/test_phone_browse_pass.py +144 -0
- taskuary-0.3.7.2/tests/test_prompt_images.py +38 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_task_tools.py +12 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_terminal.py +26 -0
- taskuary-0.3.7.0/taskuary/web/assets/index-B-MVokO_.css +0 -32
- taskuary-0.3.7.0/taskuary/web/assets/index-Bn3FS1dn.js +0 -598
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/LICENSE +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/setup.cfg +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/__init__.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/acp.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/agents.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/aisetup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/alchemy.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/appfacts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/artifacts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/assistant.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/assistantblocks.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/autoreply.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/aws.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/azure.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/blackboard.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/brief.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/browserview.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/calendar.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/categories.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/chains.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/channels.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/chatservers.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/ci.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/cli_connections.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/cli_install_terminal.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/cliinstall.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/climodels.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/clipool.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/clis.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/clisetup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/coder.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/compose.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/config.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/connectorcatalog.json +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/connectorcatalog.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/context.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/continuity.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/counsel.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/databases.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/db.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/deps.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/desktop.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/devtools.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/digest.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/docsync.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/evening.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/files.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/funnel_presentation.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/general.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/ghcloseout.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/github.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/guard.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/handbook.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/handraise.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/histgen.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/hooks.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/hub.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/images.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/imapmail.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/imessage.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/ingest.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/intacct.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/interview.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/invoice_workflow.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/knowledge.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/lanes.json +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/learn.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/learnedgraph.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/linkedin.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/live.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/logs.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/markets.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/mcp.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/messengers.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/msauth.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/mssql.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/operations.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/outbound.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/outbox.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/ownwork.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/playbooks.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/pm.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/policy.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/problems.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_all.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_inventory.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_membership.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_navigation.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_order.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_projection.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_rail.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_reads.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_startup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/processing_unread.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/projects.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/promptmap.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/proof.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/proposals.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/quickbooks.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/rank.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/redact.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/remind.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/reports.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/research.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/reshape.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/responder.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/retention.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/robinhood.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/routing.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/routingmemory.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/scopes.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/selfclose.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/semantic.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/senders.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/session_artifacts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/sessionfiles.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/settings_defaults.json +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/settings_schema.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/setup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/sharepoint.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/sheets.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/simplefin.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/skillimport.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/skills/soul-interview/SKILL.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/skills/taskuary-setup/SKILL.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/social.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/spawn.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/taskstate.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/teller.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/agent.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/analyst.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/coder.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/coordinator.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/counsel.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/digest.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.3.5.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.6.8.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.6.9-examples.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.6.9-remind.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/history/counsel-0.3.6.9.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/how-it-works.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/learned.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/marketer.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/playbook.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/profile.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/researcher.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/soul.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/style.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/trader.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/templates/triage.md +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/testing.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/toil.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/treg.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/triage.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/triage_kind_rules.json +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/update.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/verdicts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/voice.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/wabridge.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/waitroom.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/walk.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/assets/RoundedBoxGeometry-BE4rf3sD.js +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/favicon.ico +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/favicon.png +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/walk/assistant.png +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/walk/board.png +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/walk/connections.png +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/walk/docs.png +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/walk/hub.png +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/walk/reports.png +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/walk/settings.png +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/web/walk/tasks.png +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/webguard.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/whatsapp/bridge.mjs +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/whatsapp/package.json +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/whatsapp/policy.mjs +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/whatsapp/poll.mjs +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/whatsapp/roster.mjs +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/whoami.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/witness.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/workerstate.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/workflows.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary/zoho.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary.egg-info/dependency_links.txt +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary.egg-info/entry_points.txt +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary.egg-info/requires.txt +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/taskuary.egg-info/top_level.txt +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_acp.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_advisor_idea_words.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_answer_route.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_answers_and_reminders.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_asking.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_environment.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_identity.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_profiles.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_reply.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_sentence.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_source.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_agent_wall.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_aisetup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_alchemy.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_an_inbox_is_not_a_destination.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_answered_yourself.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_answers.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_api_worker_signals.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_app_uptime.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_appfacts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_approval_interrupt.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant_acts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant_blocks.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant_can_look_things_up.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant_doorways.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant_ideas.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant_notifications.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant_presentation.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant_reactions.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_assistant_verdicts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_async_triage.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_audit_chain.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_audit_fixes.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_auto_start.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_autoreply.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_aws_region.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_azure_discovery.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_banner_is_one_rule.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_blackboard.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_brain_layer.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_brain_reaches_the_session.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_browser_session.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_browser_workflow.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_browserview.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_calendar.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_calendar_today.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_canvas_relay.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_canvas_sections.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_card_story_phone.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_categories.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cc.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cc_triage.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chat_doors.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chat_echo_mail.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chat_freshness.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chat_is_not_one_task.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chat_proposals.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chat_queue.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chat_relationship.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chat_retention.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chat_setup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chatformat.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chatservers.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_chinese_clis.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_clean_context.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cli_connections.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cli_failure.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cli_help.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cli_install.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cli_install_terminal.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cli_on_fresh_path.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cli_setup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cli_update.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_climodels.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_clipool.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_clis.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_closeout.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cloud.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cloud_sources.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_completion_freshness.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_compose.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_compose_sources.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_compose_workflows.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_concierge.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_concierge_counsel.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_config.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_context.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_context_refresh_freshness.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_coordination.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_core.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_correction_doors.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_counsel.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_counsel_consumers.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_counsel_migration.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_counsel_sections.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_current_restore.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_cwlogs_paging.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_databases.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_demo.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_deps.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_desktop.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_devin.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_devtools.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_diff_review.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_digest_brief.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_dispatch_retries.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_docs_and_llm.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_docs_flow.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_duplicate_connectors.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_email_chains.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_email_identity_routing.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_ending_a_run_writes_the_answer.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_evening_brief.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_every_card_is_reachable.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_every_cli_startable.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_explicit_completion.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_factory.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_failed_acts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_feed_working.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_files.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_final_answer_capture.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_finished_chat_stays_finished.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_floating_assistant.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_follow_up_verdict.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_fresh_evaluation.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_freshness.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_freshness_walk.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_general.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_github_auto.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_github_images.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_guard.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_handbook.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_handbook_topics.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_handoff_channels.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_handraise.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_harvest.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_histgen.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_home_is_never_yours.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_hooks_events.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_hooks_version.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_ideas_triage.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_ignore_sender.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_ignore_sender_quiets_its_work.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_images.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_imap_catchup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_imap_history.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_imapmail.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_imessage.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_inline_pictures.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_intacct.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_interrupted_work.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_invite_is_not_work.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_invoice_workflow.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_jev.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_judge_reads_the_conclusion.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_kind_dispatch.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_knowledge.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_lane_vocabulary.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_learnedgraph.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_lifecycle.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_lifespan_loops_are_guarded.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_linkedin.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_linkedin_signin.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_live.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_local_file.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_lookups.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_mail_catchup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_mail_fetch_cost.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_mail_folders.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_mark_read.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_markets.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_mcp.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_meeting_prep.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_message_thread.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_messengers.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_msauth.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_mssql.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_multi_question.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_muse.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_no_pydantic_v1.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_noop_ending.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_not_coding.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_note_retrieval.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_onboarding_walk.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_one_app_one_reason.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_one_pty_one_geometry.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_only_your_own_thread.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_openai_compatible_brains.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_operations.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_outbound_reports.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_outbox.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_own_rows_no_reply.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_person_name.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_phone_picks.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_phone_walk_ux.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_playbook_setup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_playbooks.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_pm.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_poll_lanes.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_poll_overlap.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_poll_parallel.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_poll_sources.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_pr_comments.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_problems.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_problems_dismiss.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_procedure_selection.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_processing_demo_replay.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_processing_ledger.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_profile_is_a_role.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_projects.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_prompt_sources.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_promptmap_and_catalog.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_proof_ci_proposals.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_pypi_downloads.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_quickbooks.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_qwen.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_rail_decisions.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_rank.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_rate_limit.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_read_text.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_recent_closures.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_reclassify.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_redact.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_redact_doors.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_remind.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_remote_assistant.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_remote_sections.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_reply_always_drafts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_reply_attachments.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_reply_channels.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_reply_envelope.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_reply_needs_a_correspondent.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_reply_sources.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_reply_voice.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_repo_choice_triage.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_report_alerts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_report_deliver.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_report_headline.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_report_one_road.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_report_order_and_research.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_report_prompt_isolation.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_report_refusal.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_report_routing.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_report_triage.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_research.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_research_more.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_review_task.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_reviews.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_robinhood.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_routing_memory.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_s3_poll_paging.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_scopes.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_seed_fits_a_tty.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_seeded_reports.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_selector_vocabulary.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_semantic.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_send_outcomes.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_send_targets.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_sender_trust.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_sender_words.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_session_artifacts.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_session_continuity.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_session_endings.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_session_files.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_settings_defaults_json.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_settings_schema.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_setup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_setup_skill.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_setup_walk.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_sheets_sharepoint.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_simplefin.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_skillimport.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_social.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_someone_else_replied.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_soul_interview.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_startup_contract.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_stay_open.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_stay_open_doors.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_store_app_cli.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_store_hotpaths.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_store_pokes.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_sync_clock.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_task_ask.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_task_checklist.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_task_controls_operations.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_task_identity.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_task_refs.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_taskstate.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_telegram_buttons.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_teller.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_the_exe_ships_what_the_wheel_ships.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_the_split_holds.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_toil.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_tracker_revisions.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_treg.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_triage_cleanup.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_triage_dataset.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_triage_errors.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_triage_images.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_triage_joins.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_triage_pr_rule.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_triage_retry_sweep.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_triage_urgent.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_update.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_update_refused.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_urgent_and_handoff.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_verdict_paths.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_verdict_shape.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_verdict_sticks.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_vision.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_voice.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_wabridge.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_wabridge_log_trim.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_waitroom.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_walk_order.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_watermark.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_web_entrypoint.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_webguard.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_whatsapp_documents.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_whatsapp_images.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_whoami.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_why_not_started.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_withdrawn.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_witness.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_worker_brief.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_worker_events.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_worker_resumes.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_worker_scenarios.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_worker_surfaces.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_workerstate_said.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_workflows.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_zz_chipverbs.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_zz_lastword.py +0 -0
- {taskuary-0.3.7.0 → taskuary-0.3.7.2}/tests/test_zz_setupchat.py +0 -0
- {taskuary-0.3.7.0 → 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.0**—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.0**—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" }
|
|
@@ -18,7 +18,7 @@ model for coding sessions and a LIGHT model for the one-message jobs - triage, d
|
|
|
18
18
|
summaries, the digest (llm.make_cli_llm). Naming the same CLI as both the coder and the triage
|
|
19
19
|
brain is normal and cheap; it is the light gear that keeps it cheap.
|
|
20
20
|
"""
|
|
21
|
-
import json
|
|
21
|
+
import json, re
|
|
22
22
|
|
|
23
23
|
from . import climodels
|
|
24
24
|
|
|
@@ -106,7 +106,7 @@ def resolve(store, cfg, slot_key: str) -> dict:
|
|
|
106
106
|
cli = _cli_of(cfg, store, name) if name else ''
|
|
107
107
|
cat = climodels.catalog(cli)
|
|
108
108
|
model, effort = climodels.split_pick(_gears(cfg, store, name).get('model') or '')
|
|
109
|
-
out.update(model=model, effort=effort, choices=cat['choices'], efforts=_efforts(cat, model),
|
|
109
|
+
out.update(model=model, effort=effort, choices=cat['choices'], efforts=_efforts(cat, model), resolved=_resolved(cat, model),
|
|
110
110
|
owner=f'the {cli} coding profile' if cli else '', owner_link='agents', cli=cli,
|
|
111
111
|
display=cli,
|
|
112
112
|
ready=bool(name))
|
|
@@ -159,7 +159,9 @@ def resolve(store, cfg, slot_key: str) -> dict:
|
|
|
159
159
|
from .llm import ASSISTANT_EFFORT
|
|
160
160
|
effort = ASSISTANT_EFFORT.get(cli, '') # what concierge.brain runs when the pick names no effort
|
|
161
161
|
said = (f"{dflt[7:]} effort" if dflt.startswith('effort:') else dflt) if dflt else f'the {cli} default'
|
|
162
|
-
|
|
162
|
+
# a blank box runs the gear's default model, so its efforts and version are that model's
|
|
163
|
+
seen = model or ('' if dflt.startswith('effort:') else dflt)
|
|
164
|
+
out.update(model=model, effort=effort, choices=cat['choices'], efforts=_efforts(cat, seen), resolved=_resolved(cat, seen),
|
|
163
165
|
default_hint=f"{said} - the {'Assistant' if slot_key == 'concierge_ai' else 'light'} default",
|
|
164
166
|
owner=owner, owner_link='' if slot_key == 'concierge_ai' else 'agents', cli=cli)
|
|
165
167
|
if not light and not dflt: out['note'] = f'no light model set - this runs on the {cli} coding model, which is the expensive gear'
|
|
@@ -184,10 +186,25 @@ def resolve(store, cfg, slot_key: str) -> dict:
|
|
|
184
186
|
return out
|
|
185
187
|
|
|
186
188
|
|
|
189
|
+
def _entry(cat: dict, model: str) -> dict:
|
|
190
|
+
"""The catalogue row a model names: the exact id, else an alias (`sonnet`) read as the NEWEST id of that family, which is
|
|
191
|
+
what the CLI itself runs - so an alias pick shows its efforts and the version it lands on."""
|
|
192
|
+
ms = cat.get('models') or []
|
|
193
|
+
if (hit := next((m for m in ms if m.get('id') == model), None)): return hit
|
|
194
|
+
fam = [m for m in ms if model and re.fullmatch(rf'claude-{re.escape(model)}-\d[\w-]*', str(m.get('id')))]
|
|
195
|
+
return max(fam, key=lambda m: [int(n) for n in re.findall(r'\d+', m['id'])], default={})
|
|
196
|
+
|
|
197
|
+
|
|
187
198
|
def _efforts(cat: dict, model: str) -> list:
|
|
188
199
|
"""The reasoning levels THIS model offers, per the CLI's own catalogue. Empty for every CLI
|
|
189
200
|
whose effort flag we cannot spell - climodels documents why muse is deliberately empty."""
|
|
190
|
-
return
|
|
201
|
+
return _entry(cat, model).get('efforts') or []
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _resolved(cat: dict, model: str) -> str:
|
|
205
|
+
"""The id an alias lands on ('' when the pick already is an id, or nothing is known)."""
|
|
206
|
+
i = _entry(cat, model).get('id') or ''
|
|
207
|
+
return i if i != model else ''
|
|
191
208
|
|
|
192
209
|
|
|
193
210
|
# What a blank model box actually means per provider, copied from llm.make_llm so the UI can
|
|
@@ -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)
|
|
@@ -80,7 +80,7 @@ def main():
|
|
|
80
80
|
'email. Prints what it WOULD change and writes nothing unless --apply.')
|
|
81
81
|
ap.add_argument('--apply', action='store_true', help='with --backfill-asks: actually write the changes')
|
|
82
82
|
ap.add_argument('--include-closed', action='store_true', help='with --backfill-asks: closed tasks too')
|
|
83
|
-
ap.add_argument('--evalset', choices=['build', 'share', 'evaluate', 'ablate'], metavar='ACTION',
|
|
83
|
+
ap.add_argument('--evalset', choices=['build', 'share', 'evaluate', 'ablate', 'jev'], metavar='ACTION',
|
|
84
84
|
help='triage dataset: build (labelled cases from your verdicts -> ~/.taskuary/eval), '
|
|
85
85
|
'evaluate (score the configured AI over them), ablate (score with and without memory), '
|
|
86
86
|
'share (anonymised copy for tests/data)')
|
|
@@ -76,7 +76,11 @@ CHIP_HINTS = {'not_ours': 'File it - the card asks whether just this once, from
|
|
|
76
76
|
'regular_agent': 'An agent takes it - triage picks a coding or a non-coding one, and you can change it on the card',
|
|
77
77
|
'mine': "A task on your own list - no agent starts", 'next': 'Read it and move on',
|
|
78
78
|
'defer': 'Put the task away until a day - it is Upcoming in Tasks and back on your rail that morning',
|
|
79
|
-
'continue': 'Pick the agent up where it left off - say what to tell it, or continue as is'
|
|
79
|
+
'continue': 'Pick the agent up where it left off - say what to tell it, or continue as is',
|
|
80
|
+
# the words that said nothing on hover: each line is what the handler does (TaskPage's own titles are the same sentences)
|
|
81
|
+
'stop_agent': "Writes up what the session did, ends it, and drafts the reply to whoever asked (with nothing to write up it just stops it) - the task stays open",
|
|
82
|
+
'close': 'Closes the task - it stops coming back to Work',
|
|
83
|
+
'rerun': 'Runs the report again in the background - it comes back here when it is done'}
|
|
80
84
|
# per kind, in the order they are offered. `next` is last on every one of them: moving on is always available,
|
|
81
85
|
# and it is the one word that is never a decision about the thing itself.
|
|
82
86
|
# THE SHORT LIST (the owner, 2026-09-25, word by word): eight buttons. Tomorrow and Later are gone - Next on
|
|
@@ -848,7 +852,12 @@ def _ask(store, llm, tid: int, item: dict | None, instruction: str, pile_items:
|
|
|
848
852
|
return say, options, (decision or {}).get('verb') or ''
|
|
849
853
|
|
|
850
854
|
|
|
851
|
-
|
|
855
|
+
# A line said to the PHONE only (the day's opener): kept in the conversation so the model and the desk know it was said,
|
|
856
|
+
# but never drawn by the desktop chat, whose own welcome already shows the day (the owner, 2026-09-30: "that's only for the phone")
|
|
857
|
+
PHONE_ACTOR = 'assistant-phone'
|
|
858
|
+
|
|
859
|
+
|
|
860
|
+
def record(store, tid: int, role: str, text: str, card: dict = None, phone: bool = False):
|
|
852
861
|
# A presentation revision is transport freshness, not conversation meaning. Persisting it
|
|
853
862
|
# made the same adjacent card into a second durable turn when surfacing changed only its read
|
|
854
863
|
# state. Keep every semantic field, including nested FYI cards, and let the current HTTP
|
|
@@ -863,7 +872,7 @@ def record(store, tid: int, role: str, text: str, card: dict = None):
|
|
|
863
872
|
return out
|
|
864
873
|
saved_card = durable(card) if card else None
|
|
865
874
|
body = redact(text).strip() + (f"\n\n{MARK}{json.dumps(saved_card, default=str)} -->" if saved_card else '')
|
|
866
|
-
actor = 'owner' if role == 'user' else 'assistant'
|
|
875
|
+
actor = 'owner' if role == 'user' else PHONE_ACTOR if phone else 'assistant'
|
|
867
876
|
actor_type = general.USER_TYPE if role == 'user' else general.ASSISTANT_TYPE
|
|
868
877
|
# A double click must not duplicate the owner's words: those two calls may reach the backend
|
|
869
878
|
# before React disables the button. The same guard also makes empty-pipe auto-advance
|
|
@@ -911,6 +920,7 @@ def record_related(store, dock_tid: int, item: dict | None, role: str, text: str
|
|
|
911
920
|
def history(store, tid: int) -> list:
|
|
912
921
|
out = []
|
|
913
922
|
for c in general.chat_rows(store, tid):
|
|
923
|
+
if c.get('Actor') == PHONE_ACTOR: continue # said to the phone; the model still reads it through chat_rows
|
|
914
924
|
body = c.get('Body') or ''
|
|
915
925
|
m = _MARK.search(body)
|
|
916
926
|
card = None
|
|
@@ -1518,7 +1528,11 @@ def call_turn(store, tid: int, call: dict, item: dict | None, text: str, actor:
|
|
|
1518
1528
|
# ...but an AGENT is never put on an old task by default: a new ask typed while something sits on the table
|
|
1519
1529
|
# became a run on that task (the owner, 2026-09-29: "if i ask for task it should not merge with old one or agent
|
|
1520
1530
|
# run unless i ask"). These two must NAME the task; a new job is task.create_from_text, which the miss says.
|
|
1521
|
-
|
|
1531
|
+
# ...but CONTINUING is not attaching: it reopens the task's OWN saved session (the owner, 2026-09-30: "continue session
|
|
1532
|
+
# and tell the coding agent to merge it in" on a close-out card was refused for want of a ref, and the retry
|
|
1533
|
+
# fell to the close-out itself). On the table, with a session to reopen, the table's task is what they mean.
|
|
1534
|
+
resumes = kind == 'agent.continue' and not ref and it.get('tid') and store.resumable_session(it['tid'])
|
|
1535
|
+
if kind in toolcatalog.ATTACH_AGENT and not ref and not resumes:
|
|
1522
1536
|
raise CallMiss(f"{kind} puts an agent on a task that already exists - name it (its TQ ref, the one on the table "
|
|
1523
1537
|
"included). A new job is task.create_from_text. Nothing was started.")
|
|
1524
1538
|
t = int(ref.group(1)) if ref else it.get('tid')
|
|
@@ -1865,7 +1879,9 @@ def surface(store, key: str = None, llm=None, actor: str = 'owner', only: str =
|
|
|
1865
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.")
|
|
1866
1880
|
# ...and the way to them NOW, by name: a Next under this line only said it again (2026-09-23, six days running).
|
|
1867
1881
|
# What waits on the owner first - a close-out, an agent's question - then the rest.
|
|
1868
|
-
|
|
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)}
|
|
1869
1885
|
for i in sorted(waiting, key=lambda i: not funnel.on_you(i))[:3]]
|
|
1870
1886
|
elif only and left:
|
|
1871
1887
|
# the filtered set is done; what remains is the rest of the pipe - offer it rather than call the day over
|
|
@@ -1896,7 +1912,7 @@ def surface(store, key: str = None, llm=None, actor: str = 'owner', only: str =
|
|
|
1896
1912
|
return surface(store, None, llm, actor, only, trace, cancel, include_surfaced, exclude) if not key else {'item': None, 'say': say, 'options': [], 'chips': walk_chips(len(p['items'])), 'left': len(p['items'])}
|
|
1897
1913
|
# FYIs have no action to take, so the normal walk brings four together. A row explicitly
|
|
1898
1914
|
# clicked on the Timeline still opens by itself (`key` is set); only Next/Walk batches them.
|
|
1899
|
-
if not key and item
|
|
1915
|
+
if not key and funnel.batchable(item):
|
|
1900
1916
|
# a batch already assembled (funnel_selection._batch, which next_item returns on a processing store)
|
|
1901
1917
|
# IS the batch: passed to fyi_batch as `first` it became its own member, "someone - 4 fyi" (2026-09-18)
|
|
1902
1918
|
batch = item.get('items') if item.get('kind') == 'fyis' else funnel.fyi_batch(store, item)
|
|
@@ -2721,7 +2737,7 @@ def _chat_proposed(store, dock_tid: int, oid: str) -> bool:
|
|
|
2721
2737
|
|
|
2722
2738
|
|
|
2723
2739
|
def say(store, text: str, key: str = None, llm=None, actor: str = 'owner', trace=None, cancel=None, item: dict | None = None,
|
|
2724
|
-
open_card: str | None = None) -> dict:
|
|
2740
|
+
open_card: str | None = None, images: list | None = None) -> dict:
|
|
2725
2741
|
"""The owner's words, answered briefly - about the item on the table when there is one. The MODEL interprets
|
|
2726
2742
|
them (PW-121): a question is answered, a subject named is pulled in, and a decision becomes a PROPOSAL the
|
|
2727
2743
|
owner confirms (PW-123/124) - except Next, which moves the walk and marks nothing, and a reply request, which
|
|
@@ -2765,10 +2781,13 @@ def say(store, text: str, key: str = None, llm=None, actor: str = 'owner', trace
|
|
|
2765
2781
|
# THE CARD BROWSED OPEN in the canvas (the canvas redesign, 2026-09-29): "this", "it", "set it up"
|
|
2766
2782
|
# mean that card - a connector, a settings group, a report - when no item is on the table
|
|
2767
2783
|
+ (f"ON SCREEN NOW: {_cut(open_card, 300)} - 'this' means that card; its own operations set it up\n\n" if open_card and not item else '')
|
|
2768
|
-
+ f"The owner says: {text}\
|
|
2784
|
+
+ f"The owner says: {text}\n"
|
|
2785
|
+
# A PICTURE WITH THE LINE (the owner, 2026-09-30): an API brain sees it, a CLI brain reads the file it names
|
|
2786
|
+
+ ("ATTACHED IMAGES (read these files - they are what the owner is showing you)\n" + "\n".join(images) + "\n" if images else '')
|
|
2787
|
+
+ f"Answer them, briefly. If a look-up would answer it, CALL it now instead of saying you will. "
|
|
2769
2788
|
+ ('If this is a decision about the item on the table, CALL it (bucket table).' if item else
|
|
2770
2789
|
'If they ask for something to be done, CALL it now - the card is their confirmation.'),
|
|
2771
|
-
max_tokens=MAX_TOKENS) or '').strip()
|
|
2790
|
+
max_tokens=MAX_TOKENS, **({'images': general._images(images)} if images else {})) or '').strip()
|
|
2772
2791
|
raw, call = parse_call(raw)
|
|
2773
2792
|
# A LOOK-UP runs at once and comes straight back, because it changes nothing and waits for
|
|
2774
2793
|
# nobody. The model then answers with what it read - one round only, so a question can never
|
|
@@ -47,6 +47,7 @@ ALLOWED_WRITES = (
|
|
|
47
47
|
r'^/api/tasks$', # make a task
|
|
48
48
|
r'^/api/tasks/\d+$', # ...and change it
|
|
49
49
|
r'^/api/tasks/\d+/(comments|waitroom|not-a-task|assistant/(session|messages|stream|cancel))$',
|
|
50
|
+
r'^/api/prompt-image$', # a picture for a prompt: saved in the demo's own home
|
|
50
51
|
r'^/api/messages/\d+/(file|promote|read)$', # the triage verdicts: the whole funnel
|
|
51
52
|
r'^/api/reviews?/\d+/(hold|drop|edit)$', # ...but never /send
|
|
52
53
|
r'^/api/board/notes', # the wall
|
|
@@ -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))
|