netizen-cli 0.12.1__tar.gz → 0.12.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.
- {netizen_cli-0.12.1/netizen_cli.egg-info → netizen_cli-0.12.2}/PKG-INFO +2 -2
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/__init__.py +1 -1
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/queries.py +42 -37
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/static/admin.js +114 -40
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/static/index.html +11 -4
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/web.py +25 -16
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/bindings.py +89 -9
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/callbacks.py +1 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/controls.py +144 -85
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/reply.py +10 -4
- netizen_cli-0.12.2/netizen_cli/channel/reply_presenter.py +867 -0
- netizen_cli-0.12.2/netizen_cli/channel/session_pages.py +102 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/channel_app.py +458 -1383
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/codex_runtime.py +497 -100
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/domain.py +2 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/main.py +2 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/management/__init__.py +2 -2
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/management/service.py +125 -364
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/runtime/contracts.py +16 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/sdk_gap_adapter.py +58 -5
- netizen_cli-0.12.2/netizen_cli/session_inventory.py +142 -0
- netizen_cli-0.12.2/netizen_cli/sessions/delegation.py +29 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/sessions/presentation.py +27 -9
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/sessions/schema.py +3 -3
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/sessions/service.py +152 -76
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/terminal_cleanup.py +2 -2
- netizen_cli-0.12.2/netizen_cli/thread_history.py +142 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/turn_plan_observer.py +2 -2
- {netizen_cli-0.12.1 → netizen_cli-0.12.2/netizen_cli.egg-info}/PKG-INFO +2 -2
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli.egg-info/SOURCES.txt +9 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli.egg-info/requires.txt +1 -1
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/pyproject.toml +2 -2
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/admin.md +18 -12
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/faq.md +2 -2
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/feedback-and-files.md +13 -14
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/fork-side-goal.md +18 -14
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/messages.md +2 -1
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/sessions.md +15 -6
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_bindings.py +152 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cards.py +32 -43
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_channel_app.py +184 -2040
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_codex_runtime.py +1299 -54
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_codex_sdk_capabilities.py +1 -1
- netizen_cli-0.12.2/tests/test_codex_sdk_upgrade_0163.py +78 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_completion_mention_cards.py +43 -70
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_completion_mentions.py +149 -196
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_deployment.py +1 -1
- netizen_cli-0.12.2/tests/test_goal_reply_separation.py +268 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_main.py +3 -0
- netizen_cli-0.12.2/tests/test_partial_answer_delivery.py +716 -0
- netizen_cli-0.12.2/tests/test_probe_sdk_response_recovery.py +75 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_question_channel.py +5 -7
- netizen_cli-0.12.2/tests/test_resume_channel.py +177 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_scheduled_channel.py +60 -4
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_scheduler_presenter.py +46 -15
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_sdk_gap_adapter.py +73 -1
- netizen_cli-0.12.2/tests/test_session_card_pages.py +182 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_session_collaboration_app.py +35 -10
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_session_id_cards.py +87 -6
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_session_tools.py +213 -15
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_terminal_cleanup.py +2 -2
- netizen_cli-0.12.2/tests/test_thread_history.py +186 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_turn_plan_observer.py +1 -1
- netizen_cli-0.12.1/netizen_cli/channel/reply_presenter.py +0 -1655
- netizen_cli-0.12.1/tests/test_partial_answer_delivery.py +0 -487
- netizen_cli-0.12.1/tests/test_resume_channel.py +0 -91
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/MANIFEST.in +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/README.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/_build.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/config.example.yaml +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/__main__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/account_rate_limits.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/__init__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/auth.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/credentials.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/errors.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/feishu.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/login.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/port_config.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/presentation.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/static/admin.css +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/static/chat-picker.css +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/static/chat-picker.js +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/static/identity.js +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/static/login.html +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/static/login.js +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/static/session-access.js +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/transport.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/admin/users.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/builtin_skills.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/__init__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/chat_target.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/defaults.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/fork.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/model_info.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/pagination.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/questions.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/scheduled.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/session_ids.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/status.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cards/usage.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/channel/__init__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/channel/completion_mentions.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/channel/input_preparation.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/channel/messages.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/channel/ports.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/channel/question_inputs.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/channel/reactions.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/channel/topics.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/chat_avatars.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/chat_targets.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cli.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cli_data.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cli_packages.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cli_services.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cli_setup.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cli_update.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cli_update_restore.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/cli_update_worker.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/completion_mention.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/database_migrations.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/defaults/__init__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/defaults/models.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/defaults/service.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/defaults/store.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/deployment/__init__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/deployment/restart_worker.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/deployment/update_executor.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/deployment/update_protocol.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/error_messages.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/experience.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/feishu_app_onboarding.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/feishu_app_permissions.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/feishu_links.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/git_status.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/image_inputs.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/instance.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/lark_app.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/management/blocking_io.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/management/chat_directory.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/management/chat_labels.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/management/coordination.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/management/updates.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/markdown_images.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/mcp_transport.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/message_content.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/message_history.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/message_preparation.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/message_projection.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/migrations/__init__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/migrations/schema.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/migrations/v14.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/model_settings.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/package_resources.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/pagination.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/partial_answers.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/projects.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/prompt_projection.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/quoted_context.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/result_images.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/runtime/__init__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/runtime/name_writes.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/runtime/thread_naming.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/schedules/__init__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/schedules/mcp.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/schedules/models.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/schedules/scheduler.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/schedules/service.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/schedules/store.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/service_launcher.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/session_settings.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/sessions/__init__.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/sessions/errors.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/sessions/mcp.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/sessions/policy.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/settings.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/skill_references.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/task_text.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/turn_activity.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/turn_files.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/turn_patch_children.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli/user_questions.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli.egg-info/dependency_links.txt +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli.egg-info/entry_points.txt +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/netizen_cli.egg-info/top_level.txt +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/setup.cfg +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-lark/SKILL.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/SKILL.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/commands.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/concepts.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/native-capabilities.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/scheduled-tasks.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/session-collaboration.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/status-and-control.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/skills/netizen-user-guide/references/user-guide.md +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_account_rate_limits.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_admin_update_executor_probe.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_binding_scheduled_channel.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_channel_fixtures.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_channel_input_preparation.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_chat_avatars.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_chat_target_cards.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_check_sdk.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cli.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cli_data.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cli_distribution.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cli_integration.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cli_packages.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cli_packaging.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cli_services.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cli_setup.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cli_update.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_codex_sdk_upgrade_0161.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_completion_topic_delivery.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_cron_chat_targets.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_database_migrations.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_defaults_cards.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_defaults_channel.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_defaults_runtime.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_documentation_links.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_domain_experience.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_error_messages.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_feishu_app_onboarding.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_feishu_app_permissions.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_file_pagination.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_fork_cards.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_git_status.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_image_inputs.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_lark_app.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_lark_sdk_contract.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_markdown_images.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_message_content.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_message_history.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_message_material_inputs.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_message_preparation.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_migration_schema_validation.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_model_info_cards.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_model_settings.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_name_writes.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_pagination.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_partial_answers.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_persistent_fork_bindings.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_persistent_fork_channel.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_persistent_fork_runtime.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_child_files.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_feishu_completion_mention.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_feishu_partial_answers.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_feishu_turn_file_card.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_persistent_fork.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_python_sdk.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_scheduled_tasks.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_sdk_completion_race.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_skill_execution.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_probe_thread_naming.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_project_delete_channel.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_project_delete_runtime.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_project_deletion_storage.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_prompt_projection.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_question_cards.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_question_target_parity.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_quoted_context.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_release_script.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_repository_hygiene.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_result_images.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_retired_deployment.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_runtime_resume_activation.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_runtime_thread_naming.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_schedule_card_retry.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_schedule_cards.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_schedule_mcp.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_schedule_run_now.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_schedule_scope_matrix.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_schedule_service.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_scheduled_runtime.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_scheduler.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_schedules_storage.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_service_launcher.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_session_defaults.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_session_external_runtime.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_session_policy.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_session_settings.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_settings_projects.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_status_cards.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_status_commands.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_task_text.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_thread_naming.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_turn_activity.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_turn_files.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_turn_patch_children.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_turn_patch_statistics.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_update_executor.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_usage_card.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_usage_control.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_user_guide_skill.py +0 -0
- {netizen_cli-0.12.1 → netizen_cli-0.12.2}/tests/test_user_questions.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: netizen-cli
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.2
|
|
4
4
|
Summary: Use native Codex threads through a Feishu Channel.
|
|
5
5
|
Requires-Python: <3.15,>=3.11
|
|
6
6
|
Requires-Dist: h11==0.16.0
|
|
@@ -11,7 +11,7 @@ Requires-Dist: markdown-it-py==4.0.0
|
|
|
11
11
|
Requires-Dist: mdformat==1.0.0
|
|
12
12
|
Requires-Dist: mdformat-gfm==1.0.0
|
|
13
13
|
Requires-Dist: mcp==2.2.0
|
|
14
|
-
Requires-Dist: openai-codex==0.
|
|
14
|
+
Requires-Dist: openai-codex==0.163.0
|
|
15
15
|
Requires-Dist: pydantic==2.13.4
|
|
16
16
|
Requires-Dist: PyYAML==6.0.3
|
|
17
17
|
Requires-Dist: qrcode==8.2
|
|
@@ -12,7 +12,7 @@ from datetime import UTC, datetime
|
|
|
12
12
|
from .errors import AdminWebError
|
|
13
13
|
from ..bindings import BindingCursor, SideTopicCursor
|
|
14
14
|
from ..domain import ScopeKind
|
|
15
|
-
from ..management import SessionInventoryState,
|
|
15
|
+
from ..management import SessionInventoryState, SessionNativeCursor
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
_MAX_TEXT_BYTES = 4_096
|
|
@@ -113,22 +113,34 @@ def _text_set_query(
|
|
|
113
113
|
def _created_range_query(
|
|
114
114
|
values: Mapping[str, list[str]],
|
|
115
115
|
) -> tuple[str | None, str | None]:
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
return _time_range_query(values, "created", "创建")
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def _updated_range_query(
|
|
120
|
+
values: Mapping[str, list[str]],
|
|
121
|
+
) -> tuple[str | None, str | None]:
|
|
122
|
+
return _time_range_query(values, "updated", "更新")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def _time_range_query(
|
|
126
|
+
values: Mapping[str, list[str]], prefix: str, label: str,
|
|
127
|
+
) -> tuple[str | None, str | None]:
|
|
128
|
+
lower = _optional_time_query(values, f"{prefix}From")
|
|
129
|
+
upper = _optional_time_query(values, f"{prefix}Before")
|
|
118
130
|
if (
|
|
119
|
-
|
|
120
|
-
and
|
|
121
|
-
and
|
|
131
|
+
lower is not None
|
|
132
|
+
and upper is not None
|
|
133
|
+
and lower >= upper
|
|
122
134
|
):
|
|
123
135
|
raise AdminWebError(
|
|
124
136
|
400,
|
|
125
137
|
"invalid_time_range",
|
|
126
|
-
"
|
|
138
|
+
f"{label}时间的开始时间必须早于结束时间。",
|
|
127
139
|
)
|
|
128
|
-
return
|
|
140
|
+
return lower, upper
|
|
129
141
|
|
|
130
142
|
|
|
131
|
-
def
|
|
143
|
+
def _optional_time_query(
|
|
132
144
|
values: Mapping[str, list[str]],
|
|
133
145
|
name: str,
|
|
134
146
|
) -> str | None:
|
|
@@ -190,27 +202,17 @@ def _current_query(values: Mapping[str, list[str]]) -> bool | None:
|
|
|
190
202
|
return raw[0] == "true" if len(raw) == 1 else None
|
|
191
203
|
|
|
192
204
|
|
|
193
|
-
def
|
|
205
|
+
def _session_inventory_state(
|
|
194
206
|
values: Mapping[str, list[str]],
|
|
195
|
-
) ->
|
|
196
|
-
raw =
|
|
197
|
-
if raw
|
|
198
|
-
return (
|
|
199
|
-
SessionInventoryState.ACTIVE,
|
|
200
|
-
SessionInventoryState.LAZY,
|
|
201
|
-
SessionInventoryState.UNKNOWN,
|
|
202
|
-
)
|
|
203
|
-
if raw == ("all",):
|
|
204
|
-
return None
|
|
205
|
-
try:
|
|
206
|
-
states = tuple(SessionInventoryState(value) for value in raw)
|
|
207
|
-
except ValueError:
|
|
207
|
+
) -> SessionInventoryState:
|
|
208
|
+
raw = _optional_one(values, "inventoryState") or "active"
|
|
209
|
+
if raw not in {"active", "archived", "lazy"}:
|
|
208
210
|
raise AdminWebError(
|
|
209
211
|
400,
|
|
210
212
|
"invalid_inventory_state",
|
|
211
213
|
"会话状态无效。",
|
|
212
|
-
)
|
|
213
|
-
return
|
|
214
|
+
)
|
|
215
|
+
return SessionInventoryState(raw)
|
|
214
216
|
|
|
215
217
|
|
|
216
218
|
def _id_query(values: Mapping[str, list[str]], name: str) -> tuple[str, ...]:
|
|
@@ -308,13 +310,14 @@ def _decode_binding_cursor(
|
|
|
308
310
|
|
|
309
311
|
|
|
310
312
|
def _encode_session_cursor(
|
|
311
|
-
cursor: BindingCursor |
|
|
313
|
+
cursor: BindingCursor | SessionNativeCursor | None,
|
|
312
314
|
fingerprint: str,
|
|
313
315
|
) -> str | None:
|
|
314
|
-
if not isinstance(cursor,
|
|
316
|
+
if not isinstance(cursor, SessionNativeCursor):
|
|
315
317
|
return _encode_binding_cursor(cursor, fingerprint)
|
|
318
|
+
marker = "start" if cursor.cursor is None else "next"
|
|
316
319
|
return _encode_cursor(
|
|
317
|
-
"session-
|
|
320
|
+
"session-native", (marker, cursor.cursor if cursor.cursor is not None else "start", str(cursor.offset)), fingerprint,
|
|
318
321
|
)
|
|
319
322
|
|
|
320
323
|
|
|
@@ -322,19 +325,21 @@ def _decode_session_cursor(
|
|
|
322
325
|
encoded: str | None,
|
|
323
326
|
fingerprint: str,
|
|
324
327
|
*,
|
|
325
|
-
|
|
326
|
-
) -> BindingCursor |
|
|
327
|
-
if
|
|
328
|
+
inventory_state: SessionInventoryState,
|
|
329
|
+
) -> BindingCursor | SessionNativeCursor | None:
|
|
330
|
+
if inventory_state is SessionInventoryState.LAZY:
|
|
328
331
|
return _decode_binding_cursor(encoded, fingerprint)
|
|
329
|
-
values = _decode_cursor(encoded, kind="session-
|
|
332
|
+
values = _decode_cursor(encoded, kind="session-native", length=3, fingerprint=fingerprint)
|
|
330
333
|
if values is None:
|
|
331
334
|
return None
|
|
332
|
-
|
|
333
|
-
if
|
|
334
|
-
|
|
335
|
-
|
|
335
|
+
marker, raw_cursor, raw_offset = values
|
|
336
|
+
if (
|
|
337
|
+
marker not in {"start", "next"}
|
|
338
|
+
or marker == "start" and raw_cursor != "start"
|
|
339
|
+
or re.fullmatch(r"0|[1-9][0-9]?", raw_offset) is None
|
|
340
|
+
):
|
|
336
341
|
raise AdminWebError(400, "invalid_cursor", "分页游标无效。")
|
|
337
|
-
return
|
|
342
|
+
return SessionNativeCursor(None if marker == "start" else raw_cursor, int(raw_offset))
|
|
338
343
|
|
|
339
344
|
|
|
340
345
|
def _encode_side_cursor(
|
|
@@ -541,11 +541,6 @@ async function loadProjects(cursor = undefined) {
|
|
|
541
541
|
));
|
|
542
542
|
row.append(status);
|
|
543
543
|
cell(row, `${project.bindingCount}(Lazy ${project.lazyBindingCount})`);
|
|
544
|
-
cell(row, project.archivedBindingCount == null
|
|
545
|
-
? "未确认"
|
|
546
|
-
: project.unconfirmedBindingCount > 0
|
|
547
|
-
? `已确认 ${project.archivedBindingCount};另有 ${project.unconfirmedBindingCount} 个会话状态未确认`
|
|
548
|
-
: project.archivedBindingCount);
|
|
549
544
|
cell(row, project.lastActivatedAt);
|
|
550
545
|
const actions = actionsCell(row);
|
|
551
546
|
if (project.actions.setEnabled) {
|
|
@@ -578,7 +573,6 @@ let openFilter = null;
|
|
|
578
573
|
const filterOptions = {
|
|
579
574
|
project: [],
|
|
580
575
|
scopeKind: [["direct", "单聊"], ["group", "群聊"], ["topic", "话题"]],
|
|
581
|
-
inventoryState: [["active", "Active"], ["lazy", "Lazy"], ["unknown", "状态未确认"], ["archived", "Archived"], ["missing", "Missing"]],
|
|
582
576
|
current: [["true", "当前"], ["false", "非当前"]],
|
|
583
577
|
state: [["creating", "创建中"], ["open", "存活"], ["closed", "已结束"], ["expired", "已失效"], ["failed", "失败"]],
|
|
584
578
|
enabled: [["true", "已启用"], ["false", "已暂停"]],
|
|
@@ -796,8 +790,7 @@ function initializeFilter(root) {
|
|
|
796
790
|
const single = Boolean(root.dataset.scheduleFilter);
|
|
797
791
|
const prefix = single ? "schedule" : root.dataset.sideMulti ? "side" : "session";
|
|
798
792
|
const valueField = single ? document.querySelector(`#schedule-filter-${name}`) : null;
|
|
799
|
-
const defaults = name === "
|
|
800
|
-
: name === "state" ? ["creating", "open"] : name === "ended" ? ["false"] : [];
|
|
793
|
+
const defaults = name === "state" ? ["creating", "open"] : name === "ended" ? ["false"] : [];
|
|
801
794
|
const legend = root.querySelector("legend");
|
|
802
795
|
legend.id = `${prefix}-${name}-label`;
|
|
803
796
|
const trigger = document.createElement("button");
|
|
@@ -1034,7 +1027,17 @@ function formQuery(form, defaultPageSize = "25", refreshRelativeTime = true) {
|
|
|
1034
1027
|
const filters = root.dataset.sideMulti ? sideMultiFilters : sessionMultiFilters;
|
|
1035
1028
|
const values = filters.get(name).values();
|
|
1036
1029
|
for (const value of values) query.append(name, value);
|
|
1037
|
-
if (
|
|
1030
|
+
if (name === "state" && values.length === 0) query.set(name, "all");
|
|
1031
|
+
}
|
|
1032
|
+
if (form.id === "session-filter") {
|
|
1033
|
+
// Exact links remain targeted while the user changes state or date filters.
|
|
1034
|
+
const identity = new URLSearchParams(state.sessionPage?.query || "").get("identity");
|
|
1035
|
+
if (identity) query.set("identity", identity);
|
|
1036
|
+
if (query.get("inventoryState") === "lazy") {
|
|
1037
|
+
for (const key of ["createdFrom", "createdBefore", "updatedFrom", "updatedBefore"]) query.delete(key);
|
|
1038
|
+
} else if (!query.has("updatedFrom") && !query.has("updatedBefore")) {
|
|
1039
|
+
query.set("updatedRange", "all"); // URL intent only; never sent to the API.
|
|
1040
|
+
}
|
|
1038
1041
|
}
|
|
1039
1042
|
if (!query.has("pageSize")) query.set("pageSize", defaultPageSize);
|
|
1040
1043
|
return query;
|
|
@@ -1054,6 +1057,7 @@ const timeRangePresetLabels = {
|
|
|
1054
1057
|
"last-24-hours": "最近 24 小时",
|
|
1055
1058
|
"last-7-days": "最近 7 天",
|
|
1056
1059
|
"last-30-days": "最近 30 天",
|
|
1060
|
+
"last-3-months": "最近 3 个月",
|
|
1057
1061
|
};
|
|
1058
1062
|
|
|
1059
1063
|
function twoDigits(value) {
|
|
@@ -1178,7 +1182,7 @@ function allTimeRange() {
|
|
|
1178
1182
|
};
|
|
1179
1183
|
}
|
|
1180
1184
|
|
|
1181
|
-
function presetTimeRange(kind, now = new Date()) {
|
|
1185
|
+
function presetTimeRange(kind, now = new Date(), openEnded = false) {
|
|
1182
1186
|
if (kind === "all") return allTimeRange();
|
|
1183
1187
|
let from;
|
|
1184
1188
|
let before;
|
|
@@ -1188,6 +1192,14 @@ function presetTimeRange(kind, now = new Date()) {
|
|
|
1188
1192
|
} else if (kind === "yesterday") {
|
|
1189
1193
|
from = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1);
|
|
1190
1194
|
before = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
|
1195
|
+
} else if (kind === "last-3-months") {
|
|
1196
|
+
before = new Date(now.getTime());
|
|
1197
|
+
from = new Date(now.getTime());
|
|
1198
|
+
const day = from.getDate();
|
|
1199
|
+
from.setDate(1);
|
|
1200
|
+
from.setMonth(from.getMonth() - 3);
|
|
1201
|
+
const lastDay = new Date(from.getFullYear(), from.getMonth() + 1, 0).getDate();
|
|
1202
|
+
from.setDate(Math.min(day, lastDay));
|
|
1191
1203
|
} else {
|
|
1192
1204
|
const durationDays = {
|
|
1193
1205
|
"last-24-hours": 1,
|
|
@@ -1199,13 +1211,14 @@ function presetTimeRange(kind, now = new Date()) {
|
|
|
1199
1211
|
from = new Date(now.getTime() - durationDays * 24 * 60 * 60 * 1000);
|
|
1200
1212
|
}
|
|
1201
1213
|
const label = timeRangePresetLabels[kind];
|
|
1202
|
-
const
|
|
1214
|
+
const rolling = kind.startsWith("last-");
|
|
1215
|
+
const summary = rolling && !openEnded
|
|
1203
1216
|
? `${label} · 至 ${compactLocalMinute(before)} · ${utcOffsetLabel(before)}`
|
|
1204
1217
|
: `${label} · ${utcOffsetLabel(from)}`;
|
|
1205
1218
|
return {
|
|
1206
1219
|
kind,
|
|
1207
1220
|
from: canonicalUtc(from),
|
|
1208
|
-
before: canonicalUtc(before),
|
|
1221
|
+
before: openEnded && rolling ? "" : canonicalUtc(before),
|
|
1209
1222
|
startValue: localMinuteValue(from),
|
|
1210
1223
|
endValue: localMinuteValue(new Date(before.getTime() - 60 * 1000)),
|
|
1211
1224
|
summary,
|
|
@@ -1252,6 +1265,11 @@ function initializeTimeRangeFilter(root) {
|
|
|
1252
1265
|
}
|
|
1253
1266
|
root.append(timeRangeTemplate.content.cloneNode(true));
|
|
1254
1267
|
const identity = root.dataset.timeRangeId;
|
|
1268
|
+
const field = root.dataset.timeRangeField || "created";
|
|
1269
|
+
const label = root.querySelector("legend").textContent;
|
|
1270
|
+
const defaultKind = root.dataset.timeRangeDefault || "all";
|
|
1271
|
+
// Rolling update filters include later updates when this applied page is refreshed.
|
|
1272
|
+
const preset = (kind) => presetTimeRange(kind, new Date(), field === "updated");
|
|
1255
1273
|
const fromNode = root.querySelector("[data-time-range-from]");
|
|
1256
1274
|
const beforeNode = root.querySelector("[data-time-range-before]");
|
|
1257
1275
|
const trigger = root.querySelector("[data-time-range-trigger]");
|
|
@@ -1270,6 +1288,11 @@ function initializeTimeRangeFilter(root) {
|
|
|
1270
1288
|
const clear = root.querySelector("[data-time-range-clear]");
|
|
1271
1289
|
const presetButtons = [...root.querySelectorAll("[data-time-range-preset]")];
|
|
1272
1290
|
|
|
1291
|
+
fromNode.name = `${field}From`;
|
|
1292
|
+
beforeNode.name = `${field}Before`;
|
|
1293
|
+
title.textContent = label;
|
|
1294
|
+
quickClear.setAttribute("aria-label", `清除${label}筛选`);
|
|
1295
|
+
quickClear.title = `清除${label}筛选`;
|
|
1273
1296
|
popover.id = `${identity}-popover`;
|
|
1274
1297
|
title.id = `${identity}-title`;
|
|
1275
1298
|
help.id = `${identity}-help`;
|
|
@@ -1282,8 +1305,8 @@ function initializeTimeRangeFilter(root) {
|
|
|
1282
1305
|
start.setAttribute("aria-describedby", `${help.id} ${zone.id} ${error.id}`);
|
|
1283
1306
|
end.setAttribute("aria-describedby", `${help.id} ${zone.id} ${error.id}`);
|
|
1284
1307
|
|
|
1285
|
-
let applied =
|
|
1286
|
-
let draft =
|
|
1308
|
+
let applied = preset(defaultKind);
|
|
1309
|
+
let draft = { ...applied };
|
|
1287
1310
|
|
|
1288
1311
|
function setInputValidity(invalid) {
|
|
1289
1312
|
for (const [node, name] of [[start, "start"], [end, "end"]]) {
|
|
@@ -1297,7 +1320,7 @@ function initializeTimeRangeFilter(root) {
|
|
|
1297
1320
|
beforeNode.value = applied.before;
|
|
1298
1321
|
summary.textContent = applied.summary;
|
|
1299
1322
|
trigger.classList.toggle("has-value", applied.kind !== "all");
|
|
1300
|
-
trigger.setAttribute("aria-label",
|
|
1323
|
+
trigger.setAttribute("aria-label", `${label}:${applied.summary}`);
|
|
1301
1324
|
quickClear.hidden = applied.kind === "all";
|
|
1302
1325
|
}
|
|
1303
1326
|
|
|
@@ -1383,7 +1406,7 @@ function initializeTimeRangeFilter(root) {
|
|
|
1383
1406
|
|
|
1384
1407
|
function prepareQuery() {
|
|
1385
1408
|
if (applied.kind === "all" || applied.kind === "custom") return;
|
|
1386
|
-
applied =
|
|
1409
|
+
applied = preset(applied.kind);
|
|
1387
1410
|
renderApplied();
|
|
1388
1411
|
}
|
|
1389
1412
|
|
|
@@ -1408,7 +1431,7 @@ function initializeTimeRangeFilter(root) {
|
|
|
1408
1431
|
cancel: cancelDraft,
|
|
1409
1432
|
prepareQuery,
|
|
1410
1433
|
setBounds(from, before) {
|
|
1411
|
-
if (!from && !before) { this.reset(); return; }
|
|
1434
|
+
if (!from && !before) { this.reset("all"); return; }
|
|
1412
1435
|
const startDate = new Date(from);
|
|
1413
1436
|
const beforeDate = new Date(before);
|
|
1414
1437
|
const endDate = new Date(beforeDate.getTime() - 60000);
|
|
@@ -1420,9 +1443,9 @@ function initializeTimeRangeFilter(root) {
|
|
|
1420
1443
|
closePopover({ restoreFocus: false });
|
|
1421
1444
|
renderApplied();
|
|
1422
1445
|
},
|
|
1423
|
-
reset() {
|
|
1424
|
-
applied =
|
|
1425
|
-
draft =
|
|
1446
|
+
reset(kind = defaultKind) {
|
|
1447
|
+
applied = preset(kind);
|
|
1448
|
+
draft = { ...applied };
|
|
1426
1449
|
closePopover({ restoreFocus: false });
|
|
1427
1450
|
renderApplied();
|
|
1428
1451
|
},
|
|
@@ -1441,7 +1464,7 @@ function initializeTimeRangeFilter(root) {
|
|
|
1441
1464
|
});
|
|
1442
1465
|
for (const button of presetButtons) {
|
|
1443
1466
|
button.addEventListener("click", () => {
|
|
1444
|
-
draft =
|
|
1467
|
+
draft = preset(button.dataset.timeRangePreset);
|
|
1445
1468
|
renderDraft();
|
|
1446
1469
|
});
|
|
1447
1470
|
}
|
|
@@ -1453,7 +1476,10 @@ function initializeTimeRangeFilter(root) {
|
|
|
1453
1476
|
});
|
|
1454
1477
|
cancel.addEventListener("click", () => cancelDraft());
|
|
1455
1478
|
done.addEventListener("click", () => {
|
|
1456
|
-
|
|
1479
|
+
// A restored URL may have only one bound. Confirming it unchanged must
|
|
1480
|
+
// preserve that valid range; edited custom input still requires both dates.
|
|
1481
|
+
const unchanged = start.value === applied.startValue && end.value === applied.endValue;
|
|
1482
|
+
if (draft.kind === "custom" && !unchanged && !validateDraft()) {
|
|
1457
1483
|
(start.getAttribute("aria-invalid") === "true" ? start : end).focus();
|
|
1458
1484
|
return;
|
|
1459
1485
|
}
|
|
@@ -1645,13 +1671,16 @@ function sessionIdentityCell(row, session) {
|
|
|
1645
1671
|
row.append(td);
|
|
1646
1672
|
}
|
|
1647
1673
|
|
|
1648
|
-
function
|
|
1649
|
-
if (
|
|
1650
|
-
|
|
1651
|
-
const date = new Date(session.updatedAt * 1000);
|
|
1674
|
+
function nativeSessionDateLabel(value) {
|
|
1675
|
+
if (!Number.isSafeInteger(value) || value < 0) return "—";
|
|
1676
|
+
const date = new Date(value * 1000);
|
|
1652
1677
|
return Number.isNaN(date.getTime()) ? "—" : date.toLocaleString("zh-CN", { hour12: false });
|
|
1653
1678
|
}
|
|
1654
1679
|
|
|
1680
|
+
function sessionUpdatedAtLabel(session) {
|
|
1681
|
+
return session.catalogState === "lazy" ? "尚未开始" : nativeSessionDateLabel(session.updatedAt);
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1655
1684
|
function sessionDateLabel(value) {
|
|
1656
1685
|
if (typeof value !== "string" || !value) return "—";
|
|
1657
1686
|
const date = new Date(value);
|
|
@@ -1706,18 +1735,26 @@ function sessionSort(kind) {
|
|
|
1706
1735
|
function sessionFilterPage(kind = "session", { resetSort = false } = {}) {
|
|
1707
1736
|
const query = formQuery(document.querySelector(`#${kind}-filter`), "20");
|
|
1708
1737
|
const sort = resetSort ? { by: "updatedAt", direction: "desc" } : sessionSort(kind);
|
|
1709
|
-
query.set("sortBy", sort.by);
|
|
1738
|
+
query.set("sortBy", kind === "session" && query.get("inventoryState") === "lazy" ? "createdAt" : sort.by);
|
|
1710
1739
|
query.set("sortDirection", sort.direction);
|
|
1711
1740
|
return firstSessionPage(query.toString());
|
|
1712
1741
|
}
|
|
1713
1742
|
|
|
1714
1743
|
function renderSessionSort(kind) {
|
|
1715
1744
|
const sort = sessionSort(kind);
|
|
1745
|
+
const applied = new URLSearchParams(state[`${kind}Page`]?.query || "");
|
|
1746
|
+
const lazy = kind === "session" && applied.get("inventoryState") === "lazy";
|
|
1716
1747
|
for (const button of document.querySelectorAll("[data-session-sort]")) {
|
|
1717
1748
|
if (button.dataset.sessionSort !== kind) continue;
|
|
1718
1749
|
const selected = button.dataset.sortBy === sort.by;
|
|
1719
1750
|
const descending = selected && sort.direction === "desc";
|
|
1720
|
-
const label = button.dataset.sortBy === "createdAt" ? "创建时间" : "最近更新";
|
|
1751
|
+
const label = button.dataset.sortBy === "createdAt" ? lazy ? "登记时间" : "创建时间" : "最近更新";
|
|
1752
|
+
button.disabled = lazy && button.dataset.sortBy === "updatedAt";
|
|
1753
|
+
const labelNode = button.querySelector(".sort-label");
|
|
1754
|
+
if (labelNode) {
|
|
1755
|
+
labelNode.textContent = label;
|
|
1756
|
+
button.title = lazy ? "Netizen 登记时间;此时尚无 Codex 创建时间" : "Codex 原生会话创建时间,与创建时间筛选口径一致;按浏览器本地时区显示";
|
|
1757
|
+
}
|
|
1721
1758
|
button.parentElement.setAttribute("aria-sort", selected ? descending ? "descending" : "ascending" : "none");
|
|
1722
1759
|
button.setAttribute("aria-label", `按${label}${descending ? "由远及近" : "由近及远"}排序`
|
|
1723
1760
|
+ (selected ? `(当前${descending ? "由近及远" : "由远及近"})` : ""));
|
|
@@ -1725,6 +1762,14 @@ function renderSessionSort(kind) {
|
|
|
1725
1762
|
}
|
|
1726
1763
|
}
|
|
1727
1764
|
|
|
1765
|
+
function updateSessionDateFilters() {
|
|
1766
|
+
const lazy = document.querySelector("#session-inventory-state").value === "lazy";
|
|
1767
|
+
for (const root of document.querySelector("#session-filter").querySelectorAll("[data-time-range]")) {
|
|
1768
|
+
if (lazy) timeRangeControllers.get(root)?.cancel({ restoreFocus: false });
|
|
1769
|
+
root.disabled = lazy;
|
|
1770
|
+
}
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1728
1773
|
function renderSessionFreshness() {
|
|
1729
1774
|
const kind = state.sessionTab === "temporary" ? "side" : "session";
|
|
1730
1775
|
const updatedAt = state[`${kind}RefreshedAt`];
|
|
@@ -1741,6 +1786,7 @@ async function sortSessionPage(kind, by) {
|
|
|
1741
1786
|
const page = state[`${kind}Page`];
|
|
1742
1787
|
// Sorting operates on the displayed result, not unsubmitted filter drafts.
|
|
1743
1788
|
const query = new URLSearchParams(page.query ?? sessionFilterPage(kind).query);
|
|
1789
|
+
if (kind === "session" && query.get("inventoryState") === "lazy" && by === "updatedAt") return false;
|
|
1744
1790
|
const previous = sessionSort(kind);
|
|
1745
1791
|
query.set("sortBy", by);
|
|
1746
1792
|
query.set("sortDirection", previous.by === by && previous.direction === "desc" ? "asc" : "desc");
|
|
@@ -1758,13 +1804,18 @@ function renderSessionPagination(kind = "session") {
|
|
|
1758
1804
|
function resetSessionFilters(kind = "session") {
|
|
1759
1805
|
const form = document.querySelector(`#${kind}-filter`);
|
|
1760
1806
|
form.reset();
|
|
1807
|
+
if (kind === "session") updateSessionDateFilters();
|
|
1761
1808
|
(kind === "side" ? sideChatPicker : sessionChatPicker)?.reset();
|
|
1762
1809
|
const filters = kind === "side" ? sideMultiFilters : sessionMultiFilters;
|
|
1763
1810
|
for (const controller of filters.values()) controller.reset();
|
|
1764
1811
|
for (const root of form.querySelectorAll("[data-time-range]")) {
|
|
1765
1812
|
timeRangeControllers.get(root)?.reset();
|
|
1766
1813
|
}
|
|
1767
|
-
|
|
1814
|
+
const page = sessionFilterPage(kind, { resetSort: true });
|
|
1815
|
+
const query = new URLSearchParams(page.query);
|
|
1816
|
+
query.delete("identity");
|
|
1817
|
+
page.query = query.toString();
|
|
1818
|
+
return refresh("sessions", page);
|
|
1768
1819
|
}
|
|
1769
1820
|
|
|
1770
1821
|
function invalidateSessionListRequest() {
|
|
@@ -1780,11 +1831,12 @@ async function loadSessionPage(kind, page, render) {
|
|
|
1780
1831
|
const query = page.query == null
|
|
1781
1832
|
? formQuery(document.querySelector(`#${kind}-filter`), "20")
|
|
1782
1833
|
: new URLSearchParams(page.query);
|
|
1783
|
-
if (!query.has("sortBy")) query.set("sortBy", "updatedAt");
|
|
1834
|
+
if (!query.has("sortBy")) query.set("sortBy", kind === "session" && query.get("inventoryState") === "lazy" ? "createdAt" : "updatedAt");
|
|
1784
1835
|
if (!query.has("sortDirection")) query.set("sortDirection", "desc");
|
|
1785
1836
|
const candidate = { ...page, query: query.toString(), previousCursors: [...page.previousCursors] };
|
|
1786
1837
|
await loadSessionProjectOptions(kind === "side" ? sideMultiFilters : sessionMultiFilters, isCurrent);
|
|
1787
1838
|
if (!isCurrent()) return false;
|
|
1839
|
+
query.delete("updatedRange");
|
|
1788
1840
|
if (page.cursor) query.set("cursor", page.cursor);
|
|
1789
1841
|
const data = await api(`/api/v1/${kind === "side" ? "side-topics" : "sessions"}?${query}`);
|
|
1790
1842
|
if (!isCurrent()) return false;
|
|
@@ -1812,8 +1864,9 @@ async function loadSessions(page = state.sessionPage) {
|
|
|
1812
1864
|
}
|
|
1813
1865
|
|
|
1814
1866
|
function renderSessions(data) {
|
|
1815
|
-
|
|
1816
|
-
|
|
1867
|
+
const query = new URLSearchParams(state.sessionPage.query || "");
|
|
1868
|
+
document.querySelector("#sessions-lazy-notice").hidden = query.get("inventoryState") !== "lazy";
|
|
1869
|
+
document.querySelector("#sessions-identity-notice").hidden = !query.has("identity");
|
|
1817
1870
|
const body = document.querySelector("#sessions-body");
|
|
1818
1871
|
body.replaceChildren();
|
|
1819
1872
|
for (const session of data.items) {
|
|
@@ -1844,7 +1897,7 @@ function renderSessions(data) {
|
|
|
1844
1897
|
const turnSettings = settings.turn_settings;
|
|
1845
1898
|
const model = turnSettings ? `${turnSettings.model_id} / ${turnSettings.effort_id} / ${turnSettings.service_tier_id}` : "继承 Codex";
|
|
1846
1899
|
cell(row, `${settings.message_context_mode} · ${model}`);
|
|
1847
|
-
cell(row, sessionDateLabel(session.createdAt), "session-time");
|
|
1900
|
+
cell(row, session.catalogState === "lazy" ? sessionDateLabel(session.registeredAt) : nativeSessionDateLabel(session.createdAt), "session-time");
|
|
1848
1901
|
cell(row, sessionUpdatedAtLabel(session), "session-time");
|
|
1849
1902
|
const actions = actionsCell(row);
|
|
1850
1903
|
wireSessionActions(actions, session);
|
|
@@ -1931,7 +1984,7 @@ function renderSides(data) {
|
|
|
1931
1984
|
const link = document.createElement("a");
|
|
1932
1985
|
link.className = "action";
|
|
1933
1986
|
link.textContent = "查看来源会话";
|
|
1934
|
-
link.href = `/sessions/ordinary?identity=${encodeURIComponent(parent.bindingId)}&
|
|
1987
|
+
link.href = `/sessions/ordinary?identity=${encodeURIComponent(parent.bindingId)}&updatedRange=all`;
|
|
1935
1988
|
link.target = "_blank";
|
|
1936
1989
|
link.rel = "noopener noreferrer";
|
|
1937
1990
|
actions.append(link);
|
|
@@ -3708,7 +3761,7 @@ async function loadScheduleRuns(page = scheduleRunsPage) {
|
|
|
3708
3761
|
}
|
|
3709
3762
|
if (run.binding_id && !run.binding_removed) {
|
|
3710
3763
|
const link = document.createElement("a");
|
|
3711
|
-
link.href = `/sessions/ordinary?${new URLSearchParams({ identity: run.binding_id,
|
|
3764
|
+
link.href = `/sessions/ordinary?${new URLSearchParams({ identity: run.binding_id, updatedRange: "all" })}`;
|
|
3712
3765
|
link.textContent = "打开 Session";
|
|
3713
3766
|
links.append(link);
|
|
3714
3767
|
}
|
|
@@ -3751,7 +3804,7 @@ async function moveScheduleRunsPage(direction) {
|
|
|
3751
3804
|
const adminPagePaths = { projects: "/projects", schedules: "/schedules", defaults: "/defaults",
|
|
3752
3805
|
updates: "/maintenance", system: "/system" };
|
|
3753
3806
|
const sessionUrlKeys = ["project", "scopeKind", "inventoryState", "current", "chatId", "topicId", "identity",
|
|
3754
|
-
"createdFrom", "createdBefore", "pageSize", "sortBy", "sortDirection"];
|
|
3807
|
+
"createdFrom", "createdBefore", "updatedFrom", "updatedBefore", "updatedRange", "pageSize", "sortBy", "sortDirection"];
|
|
3755
3808
|
const sideUrlKeys = ["project", "state", "chatId", "createdFrom", "createdBefore", "pageSize", "sortBy", "sortDirection"];
|
|
3756
3809
|
let navigationReady = false;
|
|
3757
3810
|
let navigationIndex = 0;
|
|
@@ -3768,7 +3821,19 @@ function pageQuery(tab, sessionTab, raw = "") {
|
|
|
3768
3821
|
}
|
|
3769
3822
|
if (tab === "sessions") {
|
|
3770
3823
|
const field = sessionTab === "temporary" ? "state" : "inventoryState";
|
|
3771
|
-
if (!query.has(field)) for (const value of sessionTab === "temporary" ? ["creating", "open"] : ["active"
|
|
3824
|
+
if (!query.has(field)) for (const value of sessionTab === "temporary" ? ["creating", "open"] : ["active"]) query.append(field, value);
|
|
3825
|
+
if (sessionTab === "ordinary") {
|
|
3826
|
+
if (!["active", "archived", "lazy"].includes(query.get(field))) query.set(field, "active");
|
|
3827
|
+
else query.set(field, query.get(field));
|
|
3828
|
+
if (query.get(field) === "lazy") {
|
|
3829
|
+
for (const key of ["createdFrom", "createdBefore", "updatedFrom", "updatedBefore", "updatedRange"]) query.delete(key);
|
|
3830
|
+
query.set("sortBy", "createdAt");
|
|
3831
|
+
} else if (!query.has("updatedFrom") && !query.has("updatedBefore") && query.get("updatedRange") !== "all") {
|
|
3832
|
+
const range = presetTimeRange("last-3-months", new Date(), true);
|
|
3833
|
+
query.set("updatedFrom", range.from);
|
|
3834
|
+
}
|
|
3835
|
+
if (query.has("updatedFrom") || query.has("updatedBefore")) query.delete("updatedRange");
|
|
3836
|
+
}
|
|
3772
3837
|
if (!query.has("pageSize")) query.set("pageSize", "20");
|
|
3773
3838
|
if (!query.has("sortBy")) query.set("sortBy", "updatedAt");
|
|
3774
3839
|
if (!query.has("sortDirection")) query.set("sortDirection", "desc");
|
|
@@ -3779,13 +3844,15 @@ function pageQuery(tab, sessionTab, raw = "") {
|
|
|
3779
3844
|
|
|
3780
3845
|
function pageUrl(tab, sessionTab = state.sessionTab, raw = "") {
|
|
3781
3846
|
const path = tab === "sessions" ? `/sessions/${sessionTab}` : adminPagePaths[tab];
|
|
3782
|
-
const
|
|
3847
|
+
const intent = new URLSearchParams(raw);
|
|
3848
|
+
if (tab === "sessions" && sessionTab === "ordinary" && raw && !intent.has("updatedFrom") && !intent.has("updatedBefore")) intent.set("updatedRange", "all");
|
|
3849
|
+
const query = pageQuery(tab, sessionTab, intent);
|
|
3783
3850
|
if (tab === "sessions") {
|
|
3784
3851
|
for (const [key, value] of [["pageSize", "20"], ["sortBy", "updatedAt"], ["sortDirection", "desc"]]) {
|
|
3785
3852
|
if (query.getAll(key).length === 1 && query.get(key) === value) query.delete(key);
|
|
3786
3853
|
}
|
|
3787
3854
|
const key = sessionTab === "temporary" ? "state" : "inventoryState";
|
|
3788
|
-
const defaults = sessionTab === "temporary" ? "creating,open" : "active
|
|
3855
|
+
const defaults = sessionTab === "temporary" ? "creating,open" : "active";
|
|
3789
3856
|
if (query.getAll(key).sort().join(",") === defaults) query.delete(key);
|
|
3790
3857
|
}
|
|
3791
3858
|
if (tab === "schedules" && query.get("ended") === "false") query.delete("ended");
|
|
@@ -3829,6 +3896,7 @@ function readPageLocation() {
|
|
|
3829
3896
|
if (path === "/" && query.get("binding_id")) {
|
|
3830
3897
|
tab = "sessions";
|
|
3831
3898
|
query.set("identity", query.get("binding_id"));
|
|
3899
|
+
if (!query.has("updatedFrom") && !query.has("updatedBefore")) query.set("updatedRange", "all");
|
|
3832
3900
|
}
|
|
3833
3901
|
return { tab, sessionTab, query: pageQuery(tab, sessionTab, query) };
|
|
3834
3902
|
}
|
|
@@ -3846,7 +3914,12 @@ function restorePageFilters(route) {
|
|
|
3846
3914
|
document.querySelector(`#${kind}-chat-filter`).value = chatId || "";
|
|
3847
3915
|
document.querySelector(`#${kind}-page-size`).value = query.get("pageSize");
|
|
3848
3916
|
for (const root of document.querySelector(`#${kind}-filter`).querySelectorAll("[data-time-range]")) {
|
|
3849
|
-
|
|
3917
|
+
const field = root.dataset.timeRangeField || "created";
|
|
3918
|
+
timeRangeControllers.get(root).setBounds(query.get(`${field}From`) || "", query.get(`${field}Before`) || "");
|
|
3919
|
+
}
|
|
3920
|
+
if (kind === "session") {
|
|
3921
|
+
document.querySelector("#session-inventory-state").value = query.get("inventoryState");
|
|
3922
|
+
updateSessionDateFilters();
|
|
3850
3923
|
}
|
|
3851
3924
|
state[`${kind}Page`] = firstSessionPage(query.toString());
|
|
3852
3925
|
const name = kind === "side" ? "sides" : "sessions";
|
|
@@ -4035,6 +4108,7 @@ document.querySelector("#create-project").addEventListener("submit", async (even
|
|
|
4035
4108
|
formElement.reset();
|
|
4036
4109
|
});
|
|
4037
4110
|
|
|
4111
|
+
document.querySelector("#session-inventory-state").addEventListener("change", updateSessionDateFilters);
|
|
4038
4112
|
document.querySelector("#session-filter").addEventListener("submit", (event) => {
|
|
4039
4113
|
event.preventDefault();
|
|
4040
4114
|
refresh("sessions", sessionFilterPage());
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
<ul id="project-delete-remaining"></ul>
|
|
59
59
|
</section>
|
|
60
60
|
<div class="table-wrap"><table><thead><tr>
|
|
61
|
-
<th>Project</th><th>路径</th><th>状态</th><th>会话</th><th
|
|
61
|
+
<th>Project</th><th>路径</th><th>状态</th><th>会话</th><th>最近激活</th><th>操作</th>
|
|
62
62
|
</tr></thead><tbody id="projects-body"></tbody></table></div>
|
|
63
63
|
<nav class="pagination" aria-label="Projects 分页">
|
|
64
64
|
<button id="projects-previous" class="next" disabled>上一页</button>
|
|
@@ -82,18 +82,24 @@
|
|
|
82
82
|
<div id="session-chat-picker"></div>
|
|
83
83
|
<input id="session-chat-filter" name="chatId" type="hidden">
|
|
84
84
|
<fieldset class="multi-filter" data-session-multi="scopeKind"><legend>Scope</legend></fieldset>
|
|
85
|
-
<
|
|
85
|
+
<label>会话状态
|
|
86
|
+
<select id="session-inventory-state" name="inventoryState"><option value="active" selected>未归档</option><option value="archived">已归档</option><option value="lazy">Lazy(尚未开始)</option></select>
|
|
87
|
+
</label>
|
|
86
88
|
<fieldset class="multi-filter" data-session-multi="current"><legend>当前指针</legend></fieldset>
|
|
87
89
|
<fieldset class="time-range-filter" data-time-range data-time-range-id="session-created">
|
|
88
90
|
<legend>创建时间</legend>
|
|
89
91
|
</fieldset>
|
|
92
|
+
<fieldset class="time-range-filter" data-time-range data-time-range-id="session-updated" data-time-range-field="updated" data-time-range-default="last-3-months">
|
|
93
|
+
<legend>更新时间</legend>
|
|
94
|
+
</fieldset>
|
|
90
95
|
<label>每页
|
|
91
96
|
<select id="session-page-size" name="pageSize"><option value="10">10</option><option value="20" selected>20</option><option value="50">50</option><option value="100">100</option></select>
|
|
92
97
|
</label>
|
|
93
98
|
<button type="submit">筛选</button>
|
|
94
99
|
<button type="button" id="session-filter-reset" class="refresh">重置</button>
|
|
95
100
|
</form>
|
|
96
|
-
<p id="sessions-
|
|
101
|
+
<p id="sessions-lazy-notice" class="hint" hidden>Lazy 会话尚未在 Codex 创建,按 Netizen 登记时间排序;创建时间和更新时间筛选不适用。</p>
|
|
102
|
+
<p id="sessions-identity-notice" class="hint" hidden>按指定会话 ID 筛选;未找到时可切换会话状态。</p>
|
|
97
103
|
<div id="session-schedule-selection" class="selection-notice" hidden>
|
|
98
104
|
<p>请选择执行此定时任务的会话。已填写的内容暂存在当前页面,刷新页面将丢失。</p>
|
|
99
105
|
<button id="session-schedule-cancel" class="refresh" type="button">取消选择</button>
|
|
@@ -103,7 +109,7 @@
|
|
|
103
109
|
</div>
|
|
104
110
|
<div class="table-wrap"><table><thead><tr>
|
|
105
111
|
<th>飞书位置</th><th>类型</th><th>Session</th><th>会话状态</th><th>运行态</th><th>Project</th><th>配置</th>
|
|
106
|
-
<th aria-sort="none"><button type="button" class="session-sort" data-session-sort="session" data-sort-by="createdAt" aria-label="按创建时间由近及远排序" title="
|
|
112
|
+
<th aria-sort="none"><button type="button" class="session-sort" data-session-sort="session" data-sort-by="createdAt" aria-label="按创建时间由近及远排序" title="Codex 原生会话创建时间,与创建时间筛选口径一致;按浏览器本地时区显示"><span class="sort-label">创建时间</span><span class="sort-indicator" aria-hidden="true">↕</span></button></th>
|
|
107
113
|
<th aria-sort="descending"><button type="button" class="session-sort" data-session-sort="session" data-sort-by="updatedAt" aria-label="按最近更新由远及近排序(当前由近及远)" title="Codex 原生会话最近更新时间;按浏览器本地时区显示">最近更新<span class="sort-indicator" aria-hidden="true">↓</span></button></th><th>操作</th>
|
|
108
114
|
</tr></thead><tbody id="sessions-body"></tbody></table></div>
|
|
109
115
|
<nav class="pagination" aria-label="Sessions 分页">
|
|
@@ -489,6 +495,7 @@
|
|
|
489
495
|
<button type="button" data-time-range-preset="last-24-hours">最近 24 小时</button>
|
|
490
496
|
<button type="button" data-time-range-preset="last-7-days">最近 7 天</button>
|
|
491
497
|
<button type="button" data-time-range-preset="last-30-days">最近 30 天</button>
|
|
498
|
+
<button type="button" data-time-range-preset="last-3-months">最近 3 个月</button>
|
|
492
499
|
</div>
|
|
493
500
|
</div>
|
|
494
501
|
<div class="time-range-custom">
|