netizen-cli 0.14.0__tar.gz → 0.14.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.14.0/netizen_cli.egg-info → netizen_cli-0.14.2}/PKG-INFO +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/__init__.py +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/admin.css +3 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/admin.js +45 -20
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/index.html +36 -0
- netizen_cli-0.14.2/netizen_cli/admin/static/progress-card.js +118 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/web.py +53 -3
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/bindings.py +11 -7
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/controls.py +15 -10
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/scheduled.py +23 -5
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel_app.py +48 -12
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/codex_runtime.py +19 -7
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/database_migrations.py +4 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/domain.py +1 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/main.py +6 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/management/service.py +25 -0
- netizen_cli-0.14.2/netizen_cli/migrations/v19.py +94 -0
- netizen_cli-0.14.2/netizen_cli/migrations/v20.py +96 -0
- netizen_cli-0.14.2/netizen_cli/progress_card_config.py +45 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/schedules/mcp.py +7 -4
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/schedules/models.py +1 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/schedules/service.py +16 -6
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/schedules/store.py +25 -10
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/session_settings.py +10 -6
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/sessions/policy.py +12 -14
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/settings.py +8 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/worktrees/service.py +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/worktrees/settings.py +16 -16
- {netizen_cli-0.14.0 → netizen_cli-0.14.2/netizen_cli.egg-info}/PKG-INFO +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli.egg-info/SOURCES.txt +9 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/pyproject.toml +1 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/admin.md +19 -3
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/feedback-and-files.md +11 -4
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/scheduled-tasks.md +21 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/sessions.md +5 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_binding_scheduled_channel.py +6 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cards.py +2 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_channel_app.py +6 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cli_data.py +6 -6
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_codex_runtime.py +170 -3
- netizen_cli-0.14.2/tests/test_configuration_publication.py +132 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cron_chat_targets.py +10 -3
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_database_migrations.py +4 -4
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_defaults_cards.py +5 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_migration_schema_validation.py +1 -1
- netizen_cli-0.14.2/tests/test_optional_progress_card_settings_migration.py +142 -0
- netizen_cli-0.14.2/tests/test_progress_card_config.py +107 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_progress_card_entrypoints.py +33 -2
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_progress_card_settings_migration.py +5 -5
- netizen_cli-0.14.2/tests/test_schedule_auto_archive_migration.py +110 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_card_retry.py +3 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_cards.py +49 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_mcp.py +25 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_service.py +54 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_workspace_migration.py +2 -2
- netizen_cli-0.14.2/tests/test_scheduled_auto_archive.py +270 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_scheduled_runtime.py +12 -3
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedules_storage.py +30 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_session_defaults_migration.py +3 -3
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_session_external_runtime.py +13 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_session_settings.py +8 -1
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_worktree_service.py +25 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_worktree_tools_integration.py +6 -4
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/MANIFEST.in +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/README.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/_build.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/config.example.yaml +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/__main__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/account_rate_limits.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/auth.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/credentials.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/errors.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/feishu.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/login.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/port_config.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/presentation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/queries.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/chat-picker.css +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/chat-picker.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/identity.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/login.html +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/login.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/session-access.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/static/worktrees.js +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/transport.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/admin/users.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/builtin_skills.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/callbacks.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/chat_target.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/defaults.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/fork.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/model_info.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/pagination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/questions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/reply.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/session_ids.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/status.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/usage.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cards/workspace.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/completion_mentions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/input_preparation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/messages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/ports.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/question_inputs.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/reactions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/reply_presenter.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/session_pages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/channel/topics.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/chat_avatars.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/chat_targets.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cli.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cli_data.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cli_packages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cli_services.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cli_setup.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cli_update.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cli_update_restore.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/cli_update_worker.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/completion_mention.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/defaults/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/defaults/models.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/defaults/service.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/defaults/store.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/deployment/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/deployment/restart_worker.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/deployment/update_executor.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/deployment/update_protocol.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/error_messages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/experience.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/feishu_app_onboarding.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/feishu_app_permissions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/feishu_links.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/git_status.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/image_inputs.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/instance.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/lark_app.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/management/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/management/blocking_io.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/management/chat_directory.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/management/chat_labels.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/management/coordination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/management/updates.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/markdown_images.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/mcp_transport.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/message_content.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/message_history.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/message_preparation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/message_projection.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/migrations/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/migrations/schema.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/migrations/v14.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/migrations/v15.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/migrations/v16.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/migrations/v17.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/migrations/v18.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/model_settings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/package_resources.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/pagination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/partial_answers.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/progress_card_settings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/projects.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/prompt_projection.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/quoted_context.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/result_images.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/runtime/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/runtime/contracts.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/runtime/name_writes.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/runtime/thread_naming.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/schedules/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/schedules/scheduler.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/sdk_gap_adapter.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/service_launcher.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/session_inventory.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/sessions/__init__.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/sessions/delegation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/sessions/errors.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/sessions/mcp.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/sessions/presentation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/sessions/schema.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/sessions/service.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/skill_references.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/task_text.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/terminal_cleanup.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/thread_history.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/turn_activity.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/turn_files.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/turn_patch_children.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/turn_plan_observer.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/user_questions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/worktrees/errors.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/worktrees/git.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/worktrees/models.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/worktrees/policy.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli/worktrees/store.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli.egg-info/dependency_links.txt +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli.egg-info/entry_points.txt +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli.egg-info/requires.txt +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/netizen_cli.egg-info/top_level.txt +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/setup.cfg +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-lark/SKILL.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/SKILL.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/commands.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/concepts.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/faq.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/fork-side-goal.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/messages.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/native-capabilities.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/session-collaboration.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/status-and-control.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/skills/netizen-user-guide/references/user-guide.md +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_account_rate_limits.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_admin_update_executor_probe.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_bindings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_channel_fixtures.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_channel_input_preparation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_chat_avatars.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_chat_target_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_check_sdk.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cli.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cli_distribution.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cli_integration.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cli_packages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cli_packaging.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cli_services.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cli_setup.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_cli_update.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_codex_sdk_capabilities.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_codex_sdk_upgrade_0161.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_codex_sdk_upgrade_0163.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_completion_mention_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_completion_mentions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_completion_topic_delivery.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_defaults_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_defaults_runtime.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_defaults_worktree_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_deployment.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_documentation_links.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_domain_experience.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_error_messages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_feishu_app_onboarding.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_feishu_app_permissions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_file_pagination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_fork_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_git_status.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_goal_reply_separation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_image_inputs.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_lark_app.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_lark_sdk_contract.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_main.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_markdown_images.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_message_content.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_message_history.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_message_material_inputs.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_message_preparation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_model_info_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_model_settings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_name_writes.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_pagination.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_partial_answer_delivery.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_partial_answers.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_persistent_fork_bindings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_persistent_fork_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_persistent_fork_runtime.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_child_files.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_feishu_completion_mention.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_feishu_partial_answers.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_feishu_turn_file_card.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_persistent_fork.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_python_sdk.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_scheduled_tasks.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_sdk_completion_race.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_sdk_response_recovery.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_skill_execution.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_probe_thread_naming.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_progress_card_presentation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_project_delete_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_project_delete_runtime.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_project_deletion_storage.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_prompt_projection.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_question_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_question_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_question_target_parity.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_quoted_context.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_release_script.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_repository_hygiene.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_result_images.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_resume_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_retired_deployment.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_runtime_resume_activation.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_runtime_thread_naming.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_run_now.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_scope_matrix.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_workspace_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_workspace_service.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_schedule_workspace_storage.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_scheduled_channel.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_scheduled_worktrees.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_scheduler.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_scheduler_presenter.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_sdk_gap_adapter.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_service_launcher.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_session_card_pages.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_session_collaboration_app.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_session_defaults.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_session_id_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_session_policy.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_session_tools.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_settings_projects.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_status_cards.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_status_commands.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_task_text.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_terminal_cleanup.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_thread_history.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_thread_naming.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_turn_activity.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_turn_files.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_turn_patch_children.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_turn_patch_statistics.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_turn_plan_observer.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_update_executor.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_usage_card.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_usage_control.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_user_guide_skill.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_user_questions.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_worktree_channel_cwd.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_worktree_git.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_worktree_new.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_worktree_runtime_cwd.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_worktree_settings.py +0 -0
- {netizen_cli-0.14.0 → netizen_cli-0.14.2}/tests/test_worktree_storage.py +0 -0
|
@@ -429,8 +429,9 @@ body.schedule-detail-open { overflow: hidden; }
|
|
|
429
429
|
.tab-unsaved[hidden] { display: none; }
|
|
430
430
|
.admin-users { padding: 0; margin: 0; list-style: none; }
|
|
431
431
|
.admin-users > li { display: flex; justify-content: space-between; align-items: center; gap: 16px; border-top: 1px solid var(--line); padding: 16px 0; }
|
|
432
|
-
.session-access-form { border: 0; padding: 0; }
|
|
433
|
-
|
|
432
|
+
.session-access-form, .global-card-form { border: 0; padding: 0; }
|
|
433
|
+
.global-card-form { max-width: 800px; }
|
|
434
|
+
#session-access-fields, #global-card-fields { min-width: 0; margin: 0; border: 0; padding: 0; }
|
|
434
435
|
.session-access-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); align-items: start; gap: 16px; }
|
|
435
436
|
.session-access-rule { min-width: 0; border: 1px solid var(--line); border-radius: 10px; padding: 20px; }
|
|
436
437
|
.session-access-rule h4 { margin: 0; font-size: 16px; }
|
|
@@ -70,6 +70,7 @@ function expireAdminSession() {
|
|
|
70
70
|
if (notice) notice.hidden = false;
|
|
71
71
|
window.NetizenIdentity?.expire();
|
|
72
72
|
window.NetizenSessionAccess?.expire();
|
|
73
|
+
window.NetizenProgressCard?.expire();
|
|
73
74
|
window.NetizenWorktrees?.expire();
|
|
74
75
|
setStatus("登录已过期,请重新登录。", true);
|
|
75
76
|
}
|
|
@@ -2349,6 +2350,7 @@ async function loadSessionSettingsOptions() {
|
|
|
2349
2350
|
const serial = ++editor.optionsSerial;
|
|
2350
2351
|
editor.loading = true;
|
|
2351
2352
|
renderSessionSettingsEditor();
|
|
2353
|
+
const progressRead = editor.settings.progress_card_settings === null ? window.NetizenProgressCard.read() : null;
|
|
2352
2354
|
try {
|
|
2353
2355
|
const data = await api("/api/v1/sessions/options");
|
|
2354
2356
|
if (sessionSettingsEditor !== editor || serial !== editor.optionsSerial) return;
|
|
@@ -2359,6 +2361,7 @@ async function loadSessionSettingsOptions() {
|
|
|
2359
2361
|
editor.models = [];
|
|
2360
2362
|
editor.catalogError = `${error.message} 模型目录暂未读取,原选择保持不变。`;
|
|
2361
2363
|
} finally {
|
|
2364
|
+
await progressRead;
|
|
2362
2365
|
if (sessionSettingsEditor === editor && serial === editor.optionsSerial) {
|
|
2363
2366
|
editor.loading = false;
|
|
2364
2367
|
renderSessionSettingsEditor();
|
|
@@ -2768,6 +2771,7 @@ async function loadDefaultOptions(resolveChat = false) {
|
|
|
2768
2771
|
editor.workspaceOptions = null;
|
|
2769
2772
|
editor.workspaceError = "";
|
|
2770
2773
|
renderDefaultSettings();
|
|
2774
|
+
let progressRead = editor.settings.progress_card_settings === null ? window.NetizenProgressCard.read() : null;
|
|
2771
2775
|
try {
|
|
2772
2776
|
let view = null;
|
|
2773
2777
|
if (resolveChat && chatId) {
|
|
@@ -2810,6 +2814,11 @@ async function loadDefaultOptions(resolveChat = false) {
|
|
|
2810
2814
|
editor.error = `${error.message} 请重新打开表单后操作。`;
|
|
2811
2815
|
if (resolveChat) editor.action = null;
|
|
2812
2816
|
} finally {
|
|
2817
|
+
if (defaultsEditor === editor && serial === editor.serial
|
|
2818
|
+
&& editor.settings.progress_card_settings === null && !progressRead) {
|
|
2819
|
+
progressRead = window.NetizenProgressCard.read();
|
|
2820
|
+
}
|
|
2821
|
+
await progressRead;
|
|
2813
2822
|
if (defaultsEditor === editor && serial === editor.serial) {
|
|
2814
2823
|
// Initial catalog/defaults hydration is not a user edit. Later target
|
|
2815
2824
|
// resolution must not erase the original values used for discard checks.
|
|
@@ -3088,7 +3097,8 @@ function sessionSettingsFingerprint(settings) {
|
|
|
3088
3097
|
return JSON.stringify([turn ? [turn.model_id, turn.effort_id, turn.service_tier_id] : null,
|
|
3089
3098
|
settings.message_context_mode, settings.reaction_pulse_enabled,
|
|
3090
3099
|
settings.progress_card_enabled, settings.completion_mention_enabled,
|
|
3091
|
-
|
|
3100
|
+
settings.progress_card_settings === null ? null
|
|
3101
|
+
: progressCardFields.map((field) => settings.progress_card_settings[field.replaceAll("-", "_")])]);
|
|
3092
3102
|
}
|
|
3093
3103
|
|
|
3094
3104
|
function confirmDiscardChanges(changed) {
|
|
@@ -3098,6 +3108,7 @@ function confirmDiscardChanges(changed) {
|
|
|
3098
3108
|
function hasUnsavedEditors() {
|
|
3099
3109
|
return projectEditorHasChanges() || sessionSettingsHasChanges() || defaultEditorHasChanges() || scheduleEditorHasChanges()
|
|
3100
3110
|
|| Boolean(pendingScheduleDraft?.dirty) || Boolean(window.NetizenSessionAccess?.dirty())
|
|
3111
|
+
|| Boolean(window.NetizenProgressCard?.dirty())
|
|
3101
3112
|
|| Boolean(window.NetizenWorktrees?.dirty());
|
|
3102
3113
|
}
|
|
3103
3114
|
|
|
@@ -3105,7 +3116,8 @@ function hasUnsavedEditors() {
|
|
|
3105
3116
|
// existing fail-closed boundary; this helper never cancels or repeats a POST.
|
|
3106
3117
|
function confirmDiscardEditors() {
|
|
3107
3118
|
if (projectEditor?.saving || sessionSettingsEditor?.saving || defaultsBusy || (scheduleEditor && scheduleInput("fields").disabled)
|
|
3108
|
-
|| window.NetizenSessionAccess?.busy() || window.
|
|
3119
|
+
|| window.NetizenSessionAccess?.busy() || window.NetizenProgressCard?.busy()
|
|
3120
|
+
|| window.NetizenWorktrees?.busy()) return false;
|
|
3109
3121
|
if (!confirmDiscardChanges(hasUnsavedEditors())) return false;
|
|
3110
3122
|
closeProjectEditor({ confirmed: true });
|
|
3111
3123
|
closeSessionSettingsEditor({ confirmed: true });
|
|
@@ -3113,6 +3125,7 @@ function confirmDiscardEditors() {
|
|
|
3113
3125
|
if (scheduleEditor) closeScheduleEditor({ confirmed: true });
|
|
3114
3126
|
cancelScheduleSelection({ confirmed: true });
|
|
3115
3127
|
window.NetizenSessionAccess?.discard();
|
|
3128
|
+
window.NetizenProgressCard?.discard();
|
|
3116
3129
|
window.NetizenWorktrees?.discard();
|
|
3117
3130
|
return true;
|
|
3118
3131
|
}
|
|
@@ -3379,6 +3392,8 @@ function renderScheduleTarget() {
|
|
|
3379
3392
|
scheduleInput("chat-target").hidden = binding;
|
|
3380
3393
|
if (binding) { scheduleInput("chat").required = false; chatTarget("schedule").close(); }
|
|
3381
3394
|
scheduleInput("session-settings").hidden = binding;
|
|
3395
|
+
scheduleInput("auto-archive-field").hidden = binding;
|
|
3396
|
+
scheduleInput("auto-archive").disabled = binding;
|
|
3382
3397
|
renderScheduleWorkspace();
|
|
3383
3398
|
const target = editor.targetSession;
|
|
3384
3399
|
const selected = editor.plan?.target_binding_id || target?.bindingId || "";
|
|
@@ -3432,6 +3447,7 @@ function scheduleEditorValues() {
|
|
|
3432
3447
|
.filter((input) => input.checked).map((input) => input.value);
|
|
3433
3448
|
return { name: scheduleInput("name").value, instructions: scheduleInput("instructions").value,
|
|
3434
3449
|
enabled: scheduleInput("enabled").checked, targetKind: scheduleTargetKind(),
|
|
3450
|
+
autoArchive: binding ? null : scheduleInput("auto-archive").checked,
|
|
3435
3451
|
binding: binding ? scheduleInput("binding").value : "",
|
|
3436
3452
|
project: binding ? "" : scheduleInput("project").value,
|
|
3437
3453
|
chat: binding ? "" : scheduleInput("chat").value, rule,
|
|
@@ -3445,7 +3461,7 @@ function scheduleEditorHasChanges() {
|
|
|
3445
3461
|
}
|
|
3446
3462
|
|
|
3447
3463
|
function captureScheduleDraft() {
|
|
3448
|
-
const fields = ["name", "instructions", "enabled", "kind", "timezone", "time", "at", "offset", "end-at", "end-offset", "every"];
|
|
3464
|
+
const fields = ["name", "instructions", "enabled", "auto-archive", "kind", "timezone", "time", "at", "offset", "end-at", "end-offset", "every"];
|
|
3449
3465
|
return {
|
|
3450
3466
|
discardBase: structuredClone(scheduleEditor.discardBase), dirty: scheduleEditorHasChanges(),
|
|
3451
3467
|
fields: fields.map((id) => ({ id, value: scheduleInput(id).value, checked: scheduleInput(id).checked })),
|
|
@@ -3550,22 +3566,19 @@ function resetScheduleEndOffset() {
|
|
|
3550
3566
|
|
|
3551
3567
|
function defaultScheduleSessionSettings() {
|
|
3552
3568
|
return { turn_settings: null, reaction_pulse_enabled: false, progress_card_enabled: true, completion_mention_enabled: true,
|
|
3553
|
-
message_context_mode: "current-only", progress_card_settings:
|
|
3554
|
-
show_commentary: true, show_operations: true, show_plan: true,
|
|
3555
|
-
commentary_limit: 4, operation_limit: 8, commentary_max_chars: 160, operation_max_chars: 120,
|
|
3556
|
-
organization: "content",
|
|
3557
|
-
} };
|
|
3569
|
+
message_context_mode: "current-only", progress_card_settings: null };
|
|
3558
3570
|
}
|
|
3559
3571
|
|
|
3560
3572
|
const progressCardFields = ["show-commentary", "show-operations", "show-plan", "commentary-limit",
|
|
3561
3573
|
"operation-limit", "commentary-max-chars", "operation-max-chars", "organization"];
|
|
3562
3574
|
|
|
3563
3575
|
function progressCardSettings(settings) {
|
|
3564
|
-
return settings.progress_card_settings ||
|
|
3576
|
+
return settings.progress_card_settings || window.NetizenProgressCard?.current();
|
|
3565
3577
|
}
|
|
3566
3578
|
|
|
3567
3579
|
function progressCardSettingsError(settings) {
|
|
3568
3580
|
const progress = progressCardSettings(settings);
|
|
3581
|
+
if (!progress) return "";
|
|
3569
3582
|
for (const [key, label, maximum] of [
|
|
3570
3583
|
["commentary_limit", "进展条数", 8], ["operation_limit", "操作条数", 16],
|
|
3571
3584
|
["commentary_max_chars", "进展摘要长度", 320], ["operation_max_chars", "操作摘要长度", 240],
|
|
@@ -3582,19 +3595,21 @@ function renderProgressCardSettings(input, settings) {
|
|
|
3582
3595
|
if (!container) return;
|
|
3583
3596
|
const progress = progressCardSettings(settings);
|
|
3584
3597
|
container.hidden = !settings.progress_card_enabled;
|
|
3598
|
+
const source = input("progress-source");
|
|
3599
|
+
if (source) source.hidden = settings.progress_card_settings !== null;
|
|
3585
3600
|
for (const node of container.querySelectorAll("input, select")) {
|
|
3586
3601
|
const field = node.id.split("-progress-").at(-1);
|
|
3587
3602
|
const key = field.replaceAll("-", "_");
|
|
3588
|
-
if (field.startsWith("show-")) node.checked = progress[key];
|
|
3589
|
-
else node.value = progress[key];
|
|
3590
|
-
node.disabled = !settings.progress_card_enabled
|
|
3603
|
+
if (field.startsWith("show-")) node.checked = progress?.[key] || false;
|
|
3604
|
+
else node.value = progress?.[key] ?? "";
|
|
3605
|
+
node.disabled = !progress || !settings.progress_card_enabled
|
|
3591
3606
|
|| (field.startsWith("commentary-") && !progress.show_commentary)
|
|
3592
3607
|
|| (field.startsWith("operation-") && !progress.show_operations);
|
|
3593
3608
|
}
|
|
3594
|
-
for (const [kind, shown] of [["commentary", progress
|
|
3609
|
+
for (const [kind, shown] of [["commentary", progress?.show_commentary], ["operation", progress?.show_operations]]) {
|
|
3595
3610
|
input(`progress-${kind}-capacity`).hidden = !shown;
|
|
3596
3611
|
}
|
|
3597
|
-
const error = progressCardSettingsError(settings);
|
|
3612
|
+
const error = progress ? progressCardSettingsError(settings) : "读取全局配置后可编辑过程卡细项。";
|
|
3598
3613
|
const note = input("progress-error");
|
|
3599
3614
|
note.textContent = error;
|
|
3600
3615
|
note.hidden = !error;
|
|
@@ -3662,11 +3677,13 @@ function changeSessionSettingsField(input, settings, models, field, baseTurn = n
|
|
|
3662
3677
|
else if (field === "progress") settings.progress_card_enabled = input("progress").checked;
|
|
3663
3678
|
else if (field === "completion-mention") settings.completion_mention_enabled = input("completion-mention").checked;
|
|
3664
3679
|
else if (field.startsWith("progress-") && progressCardFields.includes(field.slice(9))) {
|
|
3680
|
+
const progress = progressCardSettings(settings);
|
|
3681
|
+
if (!progress) return;
|
|
3665
3682
|
const key = field.slice(9).replaceAll("-", "_");
|
|
3666
3683
|
const node = input(field);
|
|
3667
3684
|
const value = key.startsWith("show_") ? node.checked
|
|
3668
3685
|
: key === "organization" || node.value === "" ? node.value : Number(node.value);
|
|
3669
|
-
settings.progress_card_settings = { ...
|
|
3686
|
+
settings.progress_card_settings = { ...progress, [key]: value };
|
|
3670
3687
|
}
|
|
3671
3688
|
}
|
|
3672
3689
|
|
|
@@ -3949,6 +3966,7 @@ function openScheduleEditor(plan = null, source = {}) {
|
|
|
3949
3966
|
chatTarget("schedule", changeScheduleChat).set({ chatId: plan?.chat_id, chat: plan?.chat });
|
|
3950
3967
|
scheduleInput("instructions").value = plan?.instructions || "";
|
|
3951
3968
|
scheduleInput("enabled").checked = plan?.enabled ?? true;
|
|
3969
|
+
scheduleInput("auto-archive").checked = plan?.auto_archive ?? false;
|
|
3952
3970
|
scheduleInput("timezone").value = rule.timezone;
|
|
3953
3971
|
scheduleInput("kind").value = rule.kind;
|
|
3954
3972
|
scheduleInput("time").value = ["daily", "weekly"].includes(rule.kind) ? rule.at : "09:00";
|
|
@@ -4037,6 +4055,7 @@ async function saveSchedule(event) {
|
|
|
4037
4055
|
} else {
|
|
4038
4056
|
definition.project = scheduleInput("project").value.trim();
|
|
4039
4057
|
definition.chat_id = scheduleInput("chat").value.trim();
|
|
4058
|
+
definition.auto_archive = scheduleInput("auto-archive").checked;
|
|
4040
4059
|
if (scheduleWorkspaceChanged()) {
|
|
4041
4060
|
definition.workspace = structuredClone(editor.workspace);
|
|
4042
4061
|
if (editor.workspaceOptions?.projectAlias === definition.project) {
|
|
@@ -4310,6 +4329,9 @@ async function showSchedule(planId, returnFocus = document.activeElement) {
|
|
|
4310
4329
|
: scheduleSessionSummary(data.plan.session_settings || defaultScheduleSessionSettings());
|
|
4311
4330
|
scheduleInput("detail-settings").textContent += ` · ${data.plan.target_kind === "binding"
|
|
4312
4331
|
? scheduleInheritedWorkspace(data.plan) : workspacePolicySummary(data.plan.workspace, { scheduled: true })}`;
|
|
4332
|
+
if (data.plan.target_kind !== "binding") {
|
|
4333
|
+
scheduleInput("detail-settings").textContent += ` · 成功后自动归档:${data.plan.auto_archive ? "开启" : "关闭"}`;
|
|
4334
|
+
}
|
|
4313
4335
|
scheduleInput("detail-rule").textContent = scheduleRuleLabel(data.plan.schedule);
|
|
4314
4336
|
renderSchedulePreview("#schedule-detail-preview", data.preview);
|
|
4315
4337
|
scheduleInput("detail-note").textContent = "";
|
|
@@ -4604,8 +4626,9 @@ async function refresh(tab, cursor = undefined) {
|
|
|
4604
4626
|
if (tab === "schedules" && await loadSchedules(cursor) === false) return false;
|
|
4605
4627
|
if (tab === "defaults") await loadDefaults();
|
|
4606
4628
|
if (tab === "system") {
|
|
4607
|
-
const results = await Promise.all([window.NetizenIdentity.loadUsers(), window.NetizenSessionAccess?.load()
|
|
4608
|
-
|
|
4629
|
+
const results = await Promise.all([window.NetizenIdentity.loadUsers(), window.NetizenSessionAccess?.load(),
|
|
4630
|
+
window.NetizenProgressCard?.load()]);
|
|
4631
|
+
if (results.includes(false)) return false;
|
|
4609
4632
|
}
|
|
4610
4633
|
if (state.authExpired) return false;
|
|
4611
4634
|
if (isCurrentView()) setStatus("已更新。");
|
|
@@ -4643,7 +4666,7 @@ function selectSystemTab(name) {
|
|
|
4643
4666
|
if (state.authExpired || state.systemTab === name) return;
|
|
4644
4667
|
window.NetizenSelect?.close();
|
|
4645
4668
|
if (state.systemTab === "admins") window.NetizenIdentity?.suspendSelector();
|
|
4646
|
-
else window.NetizenSessionAccess?.closePickers();
|
|
4669
|
+
else if (state.systemTab === "access") window.NetizenSessionAccess?.closePickers();
|
|
4647
4670
|
state.systemTab = name;
|
|
4648
4671
|
for (const button of document.querySelectorAll("[data-system-tab]")) {
|
|
4649
4672
|
const selected = button.dataset.systemTab === name;
|
|
@@ -4710,8 +4733,10 @@ for (const tab of document.querySelectorAll("[data-system-tab]")) {
|
|
|
4710
4733
|
tab.addEventListener("keydown", (event) => {
|
|
4711
4734
|
if (!["ArrowLeft", "ArrowRight", "Home", "End"].includes(event.key)) return;
|
|
4712
4735
|
event.preventDefault();
|
|
4713
|
-
const
|
|
4714
|
-
|
|
4736
|
+
const names = [...document.querySelectorAll("[data-system-tab]")].map((button) => button.dataset.systemTab);
|
|
4737
|
+
const index = names.indexOf(tab.dataset.systemTab);
|
|
4738
|
+
const name = event.key === "Home" ? names[0] : event.key === "End" ? names.at(-1)
|
|
4739
|
+
: names[(index + (event.key === "ArrowRight" ? 1 : names.length - 1)) % names.length];
|
|
4715
4740
|
selectSystemTab(name);
|
|
4716
4741
|
document.querySelector(`#system-tab-${name}`).focus();
|
|
4717
4742
|
});
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
<script src="/static/chat-picker.js" defer></script>
|
|
10
10
|
<script src="/static/identity.js" defer></script>
|
|
11
11
|
<script src="/static/session-access.js" defer></script>
|
|
12
|
+
<script src="/static/progress-card.js" defer></script>
|
|
12
13
|
<script src="/static/worktrees.js" defer></script>
|
|
13
14
|
<script src="/static/admin.js" defer></script>
|
|
14
15
|
</head>
|
|
@@ -222,6 +223,7 @@
|
|
|
222
223
|
<label><input id="session-settings-completion-mention" type="checkbox">结束时 @ 提醒</label>
|
|
223
224
|
</div>
|
|
224
225
|
<div id="session-settings-progress-settings" class="progress-settings" hidden>
|
|
226
|
+
<p id="session-settings-progress-source" class="session-settings-help" hidden>当前未单独配置,显示全局过程卡配置。修改细项后将保存为独立配置。</p>
|
|
225
227
|
<label>过程卡组织方式<select id="session-settings-progress-organization"><option value="content">按内容</option><option value="time">按时间</option></select></label>
|
|
226
228
|
<p class="session-settings-help">按时间交错显示进展与操作,任务清单固定在底部。执行状态和异常提示始终保留。</p>
|
|
227
229
|
<div class="defaults-feedback"><label><input id="session-settings-progress-show-commentary" type="checkbox">最近进展</label></div>
|
|
@@ -305,6 +307,7 @@
|
|
|
305
307
|
<label><input id="defaults-completion-mention" type="checkbox">结束时 @ 提醒</label>
|
|
306
308
|
</div>
|
|
307
309
|
<div id="defaults-progress-settings" class="progress-settings" hidden>
|
|
310
|
+
<p id="defaults-progress-source" class="session-settings-help" hidden>当前未单独配置,显示全局过程卡配置。修改细项后将保存为独立配置。</p>
|
|
308
311
|
<label>过程卡组织方式<select id="defaults-progress-organization"><option value="content">按内容</option><option value="time">按时间</option></select></label>
|
|
309
312
|
<p class="session-settings-help">按时间交错显示进展与操作,任务清单固定在底部。执行状态和异常提示始终保留。</p>
|
|
310
313
|
<div class="defaults-feedback"><label><input id="defaults-progress-show-commentary" type="checkbox">最近进展</label></div>
|
|
@@ -463,6 +466,10 @@
|
|
|
463
466
|
</div>
|
|
464
467
|
</div>
|
|
465
468
|
</section>
|
|
469
|
+
<section id="schedule-auto-archive-field" class="schedule-editor-section">
|
|
470
|
+
<label class="schedule-checkbox"><input id="schedule-auto-archive" type="checkbox" aria-describedby="schedule-auto-archive-help">成功后自动归档</label>
|
|
471
|
+
<p id="schedule-auto-archive-help" class="schedule-field-help">首轮正常结束且结果送达后归档,恢复使用 /sessions archived。</p>
|
|
472
|
+
</section>
|
|
466
473
|
<details id="schedule-session-settings" class="schedule-editor-section schedule-session-settings" open>
|
|
467
474
|
<summary>会话配置<span id="schedule-session-summary">继承 Codex · 当前消息</span></summary>
|
|
468
475
|
<div class="schedule-section-fields">
|
|
@@ -488,6 +495,7 @@
|
|
|
488
495
|
<div class="session-tabs system-tabs" role="tablist" aria-label="系统管理">
|
|
489
496
|
<button id="system-tab-admins" class="session-tab" role="tab" data-system-tab="admins" aria-selected="true" aria-controls="system-admins" tabindex="0">管理员</button>
|
|
490
497
|
<button id="system-tab-access" class="session-tab" role="tab" data-system-tab="access" aria-selected="false" aria-controls="system-access" tabindex="-1">跨会话工具权限<span id="session-access-unsaved" class="tab-unsaved" hidden>未保存</span></button>
|
|
498
|
+
<button id="system-tab-progress" class="session-tab" role="tab" data-system-tab="progress" aria-selected="false" aria-controls="system-progress" tabindex="-1">过程卡<span id="global-card-unsaved" class="tab-unsaved" hidden>未保存</span></button>
|
|
491
499
|
</div>
|
|
492
500
|
<div id="system-admins" class="system-tab-panel" role="tabpanel" aria-labelledby="system-tab-admins">
|
|
493
501
|
<div class="section-head"><h3>管理员</h3><button id="admin-user-add" class="action" aria-expanded="false" aria-controls="admin-user-panel" disabled>添加管理员</button></div>
|
|
@@ -541,6 +549,34 @@
|
|
|
541
549
|
</div>
|
|
542
550
|
</form>
|
|
543
551
|
</div>
|
|
552
|
+
<div id="system-progress" class="system-tab-panel" role="tabpanel" aria-labelledby="system-tab-progress" hidden>
|
|
553
|
+
<h3>全局过程卡配置</h3>
|
|
554
|
+
<p class="defaults-help">仅在本实例的会话未单独配置过程卡时使用,不覆盖会话及聊天默认配置中已有的过程卡设置。</p>
|
|
555
|
+
<form id="global-card-form" class="card-form global-card-form">
|
|
556
|
+
<fieldset id="global-card-fields" disabled>
|
|
557
|
+
<div id="global-card-progress-settings" class="progress-settings" hidden>
|
|
558
|
+
<label>过程卡组织方式<select id="global-card-progress-organization"><option value="content">按内容</option><option value="time">按时间</option></select></label>
|
|
559
|
+
<p class="session-settings-help">按时间交错显示进展与操作,任务清单固定在底部。执行状态和异常提示始终保留。</p>
|
|
560
|
+
<div class="defaults-feedback"><label><input id="global-card-progress-show-commentary" type="checkbox">最近进展</label></div>
|
|
561
|
+
<div id="global-card-progress-commentary-capacity" class="schedule-form-grid">
|
|
562
|
+
<label>进展条数(1–8)<input id="global-card-progress-commentary-limit" type="number" min="1" max="8" step="1" required></label>
|
|
563
|
+
<label>进展摘要长度(1–320 字符)<input id="global-card-progress-commentary-max-chars" type="number" min="1" max="320" step="1" required></label>
|
|
564
|
+
</div>
|
|
565
|
+
<div class="defaults-feedback"><label><input id="global-card-progress-show-operations" type="checkbox">最近操作</label></div>
|
|
566
|
+
<div id="global-card-progress-operation-capacity" class="schedule-form-grid">
|
|
567
|
+
<label>操作条数(1–16)<input id="global-card-progress-operation-limit" type="number" min="1" max="16" step="1" required></label>
|
|
568
|
+
<label>操作摘要长度(1–240 字符)<input id="global-card-progress-operation-max-chars" type="number" min="1" max="240" step="1" required></label>
|
|
569
|
+
</div>
|
|
570
|
+
<div class="defaults-feedback"><label><input id="global-card-progress-show-plan" type="checkbox">任务清单</label></div>
|
|
571
|
+
</div>
|
|
572
|
+
<p id="global-card-progress-error" class="progress-settings-error" role="status" hidden></p>
|
|
573
|
+
</fieldset>
|
|
574
|
+
<div class="session-access-footer">
|
|
575
|
+
<p id="global-card-note" class="defaults-field-help" role="status"></p>
|
|
576
|
+
<div class="actions"><button id="global-card-cancel" class="refresh" type="button" disabled>放弃修改</button><button id="global-card-save" class="action" type="submit" disabled>保存配置</button></div>
|
|
577
|
+
</div>
|
|
578
|
+
</form>
|
|
579
|
+
</div>
|
|
544
580
|
</section>
|
|
545
581
|
<section id="updates" class="panel" aria-labelledby="updates-heading" hidden>
|
|
546
582
|
<div class="section-head">
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
window.NetizenProgressCard = (() => {
|
|
4
|
+
const node = (name) => document.querySelector(`#global-card-${name}`);
|
|
5
|
+
let snapshot = null;
|
|
6
|
+
let draft = null;
|
|
7
|
+
let preview = null;
|
|
8
|
+
let loading = false;
|
|
9
|
+
let pending = false;
|
|
10
|
+
let expired = false;
|
|
11
|
+
let generation = 0;
|
|
12
|
+
let previewGeneration = 0;
|
|
13
|
+
|
|
14
|
+
const wrapper = () => ({ progress_card_enabled: true, progress_card_settings: draft });
|
|
15
|
+
const dirty = () => Boolean(snapshot) && JSON.stringify(draft) !== JSON.stringify(snapshot.settings);
|
|
16
|
+
|
|
17
|
+
function render() {
|
|
18
|
+
if (draft) renderProgressCardSettings(node, wrapper());
|
|
19
|
+
node("fields").disabled = expired || loading || pending || !snapshot?.editable;
|
|
20
|
+
node("save").disabled = expired || loading || pending || !snapshot?.actions.save || !dirty()
|
|
21
|
+
|| Boolean(progressCardSettingsError(wrapper()));
|
|
22
|
+
node("cancel").disabled = expired || loading || pending || !dirty();
|
|
23
|
+
node("unsaved").hidden = !dirty();
|
|
24
|
+
node("save").textContent = pending ? "保存中…" : "保存配置";
|
|
25
|
+
node("form").setAttribute("aria-busy", String(loading || pending));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function discard() {
|
|
29
|
+
generation += 1;
|
|
30
|
+
loading = false;
|
|
31
|
+
draft = snapshot ? structuredClone(snapshot.settings) : null;
|
|
32
|
+
render();
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function read() {
|
|
36
|
+
const version = ++previewGeneration;
|
|
37
|
+
preview = null;
|
|
38
|
+
try {
|
|
39
|
+
const value = await api("/api/v1/progress-card/settings");
|
|
40
|
+
if (!expired && version === previewGeneration) preview = value.settings;
|
|
41
|
+
return value.settings;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
if (!expired && version === previewGeneration) setStatus(`全局过程卡配置读取失败:${error.message}`, true);
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function load() {
|
|
49
|
+
if (expired || pending || !confirmDiscardChanges(dirty())) return false;
|
|
50
|
+
const version = ++generation;
|
|
51
|
+
loading = true;
|
|
52
|
+
render();
|
|
53
|
+
try {
|
|
54
|
+
const value = await api("/api/v1/progress-card/settings");
|
|
55
|
+
if (expired || version !== generation) return false;
|
|
56
|
+
snapshot = value;
|
|
57
|
+
previewGeneration += 1;
|
|
58
|
+
preview = value.settings;
|
|
59
|
+
draft = structuredClone(value.settings);
|
|
60
|
+
node("note").textContent = value.editable
|
|
61
|
+
? "保存后,从后续任务开始使用;正在执行的卡片保持不变。" : "实例配置不可编辑。";
|
|
62
|
+
return true;
|
|
63
|
+
} catch (error) {
|
|
64
|
+
if (!expired && version === generation) {
|
|
65
|
+
if (snapshot) snapshot.actions.save = null;
|
|
66
|
+
node("note").textContent = "读取失败,请刷新后重试。";
|
|
67
|
+
}
|
|
68
|
+
throw error;
|
|
69
|
+
} finally {
|
|
70
|
+
if (version === generation) { loading = false; render(); }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function save(event) {
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
if (expired || loading || pending || !snapshot?.actions.save || !dirty()
|
|
77
|
+
|| progressCardSettingsError(wrapper())) return;
|
|
78
|
+
const body = actionPayload(snapshot.actions.save, { settings: draft });
|
|
79
|
+
snapshot.actions.save = null;
|
|
80
|
+
pending = true;
|
|
81
|
+
generation += 1;
|
|
82
|
+
render();
|
|
83
|
+
try {
|
|
84
|
+
const value = await api("/api/v1/progress-card/settings", {
|
|
85
|
+
method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body),
|
|
86
|
+
});
|
|
87
|
+
if (expired) return;
|
|
88
|
+
snapshot = value;
|
|
89
|
+
previewGeneration += 1;
|
|
90
|
+
preview = value.settings;
|
|
91
|
+
draft = structuredClone(value.settings);
|
|
92
|
+
node("note").textContent = "全局过程卡配置已保存,从后续任务开始使用。";
|
|
93
|
+
setStatus("全局过程卡配置已保存。");
|
|
94
|
+
} catch (error) {
|
|
95
|
+
if (!expired) {
|
|
96
|
+
node("note").textContent = "请刷新核对当前配置后再保存;本次修改未自动重试。";
|
|
97
|
+
setStatus(error.message, true);
|
|
98
|
+
}
|
|
99
|
+
} finally {
|
|
100
|
+
pending = false;
|
|
101
|
+
render();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
for (const field of node("fields").querySelectorAll("input, select")) {
|
|
106
|
+
field.addEventListener("change", () => {
|
|
107
|
+
if (expired || loading || pending || !snapshot?.editable) return;
|
|
108
|
+
const settings = wrapper();
|
|
109
|
+
changeSessionSettingsField(node, settings, [], field.id.slice("global-card-".length));
|
|
110
|
+
draft = settings.progress_card_settings;
|
|
111
|
+
render();
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
node("form").addEventListener("submit", save);
|
|
115
|
+
node("cancel").addEventListener("click", discard);
|
|
116
|
+
return { load, read, current: () => preview, dirty, discard, busy: () => pending,
|
|
117
|
+
expire() { expired = true; generation += 1; render(); } };
|
|
118
|
+
})();
|
|
@@ -167,6 +167,8 @@ from ..sessions.policy import (
|
|
|
167
167
|
SessionAccessPolicy, SessionPolicyConflict, SessionPolicyError, SessionPolicyService,
|
|
168
168
|
)
|
|
169
169
|
from ..worktrees.errors import WorktreeError
|
|
170
|
+
from ..progress_card_config import ProgressCardConfigConflict, ProgressCardConfigError
|
|
171
|
+
from ..progress_card_settings import ProgressCardSettings
|
|
170
172
|
|
|
171
173
|
|
|
172
174
|
logger = logging.getLogger(__name__)
|
|
@@ -255,6 +257,7 @@ class AdminActionPreconditions:
|
|
|
255
257
|
session_policy_revision: ExpectedValue[str] = ExpectedValue.dont_check()
|
|
256
258
|
cascade_delete: ExpectedValue[bool] = ExpectedValue.dont_check()
|
|
257
259
|
worktree_settings_revision: ExpectedValue[str] = ExpectedValue.dont_check()
|
|
260
|
+
progress_card_settings_revision: ExpectedValue[str] = ExpectedValue.dont_check()
|
|
258
261
|
|
|
259
262
|
|
|
260
263
|
@dataclass(frozen=True, slots=True)
|
|
@@ -577,6 +580,8 @@ class AdminWebApplication:
|
|
|
577
580
|
return Response(200, ((b"Content-Type", b"text/javascript; charset=utf-8"),), self._assets["session-access.js"])
|
|
578
581
|
if route == ("GET", "/static/worktrees.js"):
|
|
579
582
|
return Response(200, ((b"Content-Type", b"text/javascript; charset=utf-8"),), self._assets["worktrees.js"])
|
|
583
|
+
if route == ("GET", "/static/progress-card.js"):
|
|
584
|
+
return Response(200, ((b"Content-Type", b"text/javascript; charset=utf-8"),), self._assets["progress-card.js"])
|
|
580
585
|
if route == ("GET", "/api/v1/identity"):
|
|
581
586
|
_require_query_keys(context.query, set())
|
|
582
587
|
session = self._authenticate(context)
|
|
@@ -608,6 +613,8 @@ class AdminWebApplication:
|
|
|
608
613
|
return await self._worktree_branches(context)
|
|
609
614
|
if route == ("GET", "/api/v1/worktrees/settings"):
|
|
610
615
|
return self._worktree_settings(context)
|
|
616
|
+
if route == ("GET", "/api/v1/progress-card/settings"):
|
|
617
|
+
return self._progress_card_settings(context)
|
|
611
618
|
if route == ("GET", "/api/v1/chats"):
|
|
612
619
|
return await self._chats(context)
|
|
613
620
|
if route == ("GET", "/api/v1/chat-labels"):
|
|
@@ -656,6 +663,7 @@ class AdminWebApplication:
|
|
|
656
663
|
mutations: dict[str, Callable[[_RequestContext], Awaitable[Response]]] = {
|
|
657
664
|
"/api/v1/worktrees/create": self._worktree_create,
|
|
658
665
|
"/api/v1/worktrees/settings": self._worktree_save_settings,
|
|
666
|
+
"/api/v1/progress-card/settings": self._progress_card_save_settings,
|
|
659
667
|
"/api/v1/worktrees/delete-preview": self._worktree_delete_preview,
|
|
660
668
|
"/api/v1/worktrees/delete": self._worktree_delete,
|
|
661
669
|
"/api/v1/session-tool-access/save": self._save_session_tool_access,
|
|
@@ -978,7 +986,7 @@ class AdminWebApplication:
|
|
|
978
986
|
)
|
|
979
987
|
definition = payload.get("definition", {})
|
|
980
988
|
if not isinstance(definition, dict) or set(definition) - {
|
|
981
|
-
"name", "instructions", "project", "expected_project_revision", "chat_id", "schedule", "enabled", "session_settings", "workspace", "target_kind", "target_binding_id",
|
|
989
|
+
"name", "instructions", "project", "expected_project_revision", "chat_id", "schedule", "enabled", "session_settings", "workspace", "target_kind", "target_binding_id", "auto_archive",
|
|
982
990
|
}:
|
|
983
991
|
raise AdminWebError(400, "invalid_input", "定时任务定义字段无效。")
|
|
984
992
|
request: dict[str, object] = {
|
|
@@ -1104,6 +1112,46 @@ class AdminWebApplication:
|
|
|
1104
1112
|
)
|
|
1105
1113
|
return _json_response(200, {**result, "requestId": context.request.request_id})
|
|
1106
1114
|
|
|
1115
|
+
def _progress_card_settings(self, context: _RequestContext) -> Response:
|
|
1116
|
+
_require_query_keys(context.query, set())
|
|
1117
|
+
view = self._management.progress_card_settings()
|
|
1118
|
+
actions = {}
|
|
1119
|
+
if view["editable"]:
|
|
1120
|
+
actions["save"] = self._grant(
|
|
1121
|
+
context, "progress-card.settings", AdminActionTarget("progress-card-settings", "instance"),
|
|
1122
|
+
_empty_preconditions(progress_card_settings_revision=ExpectedValue.expect(view["revision"])),
|
|
1123
|
+
)
|
|
1124
|
+
return _json_response(200, {**view, "actions": actions, "requestId": context.request.request_id})
|
|
1125
|
+
|
|
1126
|
+
async def _progress_card_save_settings(self, context: _RequestContext) -> Response:
|
|
1127
|
+
_require_query_keys(context.query, set())
|
|
1128
|
+
payload, grant = self._redeem(
|
|
1129
|
+
context, "progress-card.settings", expected_resource="progress-card-settings",
|
|
1130
|
+
allowed_extra={"settings"},
|
|
1131
|
+
)
|
|
1132
|
+
if grant.target.target_id != "instance":
|
|
1133
|
+
raise StaleActionGrant()
|
|
1134
|
+
try:
|
|
1135
|
+
settings = ProgressCardSettings.from_dict(payload["settings"])
|
|
1136
|
+
except ValueError as error:
|
|
1137
|
+
raise AdminWebError(400, "invalid_progress_card_settings", str(error)) from None
|
|
1138
|
+
revision = _expected_value(
|
|
1139
|
+
_grant_preconditions(grant).progress_card_settings_revision, "progress card settings revision",
|
|
1140
|
+
)
|
|
1141
|
+
|
|
1142
|
+
async def apply() -> dict[str, Any]:
|
|
1143
|
+
try:
|
|
1144
|
+
return await self._management.update_progress_card_settings(settings, expected_revision=revision)
|
|
1145
|
+
except ProgressCardConfigConflict:
|
|
1146
|
+
raise AdminWebError(409, "stale_progress_card_settings", "过程卡配置已被修改,请刷新后再保存。") from None
|
|
1147
|
+
except AdminPortConfigurationError:
|
|
1148
|
+
raise AdminWebError(409, "configuration_changed", "实例配置文件已变化;请重启实例加载配置后再保存。") from None
|
|
1149
|
+
except (ProgressCardConfigError, OSError):
|
|
1150
|
+
raise AdminWebError(503, "configuration_unavailable", "无法保存过程卡配置,当前配置未更新。") from None
|
|
1151
|
+
|
|
1152
|
+
await self._mutation(context, "progress-card.settings", "instance", apply())
|
|
1153
|
+
return self._progress_card_settings(context)
|
|
1154
|
+
|
|
1107
1155
|
async def _worktree_delete_preview(self, context: _RequestContext) -> Response:
|
|
1108
1156
|
_require_query_keys(context.query, set())
|
|
1109
1157
|
payload, grant = self._redeem(
|
|
@@ -2164,7 +2212,7 @@ class AdminWebApplication:
|
|
|
2164
2212
|
|
|
2165
2213
|
async def apply() -> None:
|
|
2166
2214
|
try:
|
|
2167
|
-
|
|
2215
|
+
await self._management.update_session_tool_access(service, policy, expected_revision=revision)
|
|
2168
2216
|
except SessionPolicyConflict:
|
|
2169
2217
|
raise AdminWebError(409, "stale_session_tool_access", "权限已被修改,请刷新后再保存。") from None
|
|
2170
2218
|
except AdminPortConfigurationError:
|
|
@@ -2713,7 +2761,7 @@ def admin_access_urls(
|
|
|
2713
2761
|
def _load_assets() -> dict[str, bytes]:
|
|
2714
2762
|
root = importlib.resources.files("netizen_cli.admin").joinpath("static")
|
|
2715
2763
|
assets: dict[str, bytes] = {}
|
|
2716
|
-
for name in ("index.html", "admin.css", "admin.js", "chat-picker.js", "chat-picker.css", "login.html", "login.js", "identity.js", "session-access.js", "worktrees.js"):
|
|
2764
|
+
for name in ("index.html", "admin.css", "admin.js", "chat-picker.js", "chat-picker.css", "login.html", "login.js", "identity.js", "session-access.js", "worktrees.js", "progress-card.js"):
|
|
2717
2765
|
assets[name] = root.joinpath(name).read_bytes()
|
|
2718
2766
|
return assets
|
|
2719
2767
|
|
|
@@ -3015,6 +3063,7 @@ def _empty_preconditions(
|
|
|
3015
3063
|
session_policy_revision: ExpectedValue[str] | None = None,
|
|
3016
3064
|
cascade_delete: ExpectedValue[bool] | None = None,
|
|
3017
3065
|
worktree_settings_revision: ExpectedValue[str] | None = None,
|
|
3066
|
+
progress_card_settings_revision: ExpectedValue[str] | None = None,
|
|
3018
3067
|
) -> AdminActionPreconditions:
|
|
3019
3068
|
return AdminActionPreconditions(
|
|
3020
3069
|
active_binding_id or ExpectedValue.dont_check(),
|
|
@@ -3037,6 +3086,7 @@ def _empty_preconditions(
|
|
|
3037
3086
|
session_policy_revision or ExpectedValue.dont_check(),
|
|
3038
3087
|
cascade_delete or ExpectedValue.dont_check(),
|
|
3039
3088
|
worktree_settings_revision or ExpectedValue.dont_check(),
|
|
3089
|
+
progress_card_settings_revision or ExpectedValue.dont_check(),
|
|
3040
3090
|
)
|
|
3041
3091
|
|
|
3042
3092
|
|
|
@@ -40,7 +40,7 @@ from .worktrees.models import WorktreeRecord
|
|
|
40
40
|
from .worktrees.store import WorktreeStore, create_schema as create_worktree_schema
|
|
41
41
|
|
|
42
42
|
|
|
43
|
-
SCHEMA_VERSION =
|
|
43
|
+
SCHEMA_VERSION = 20
|
|
44
44
|
|
|
45
45
|
# Includes the running query and all submitted queries waiting for the reader.
|
|
46
46
|
_ADMIN_QUERY_CAPACITY = 32
|
|
@@ -467,7 +467,7 @@ def _require_current_schema(connection: sqlite3.Connection) -> None:
|
|
|
467
467
|
_require_project_metadata_schema(connection)
|
|
468
468
|
require_schema(connection)
|
|
469
469
|
require_defaults_schema(connection)
|
|
470
|
-
from .migrations.
|
|
470
|
+
from .migrations.v20 import validate
|
|
471
471
|
validate(connection)
|
|
472
472
|
|
|
473
473
|
|
|
@@ -1334,10 +1334,10 @@ class BindingStore:
|
|
|
1334
1334
|
row["task_reactions_enabled"],
|
|
1335
1335
|
row["progress_card_enabled"],
|
|
1336
1336
|
row["completion_mention_enabled"],
|
|
1337
|
-
_progress_card_settings(row["progress_card_settings_json"])
|
|
1337
|
+
_progress_card_settings(row["progress_card_settings_json"]),
|
|
1338
1338
|
)
|
|
1339
1339
|
feedback_changed = current_feedback != (
|
|
1340
|
-
*feedback_values[:3], task_feedback.progress_card_settings
|
|
1340
|
+
*feedback_values[:3], task_feedback.progress_card_settings,
|
|
1341
1341
|
)
|
|
1342
1342
|
if (
|
|
1343
1343
|
not settings_changed
|
|
@@ -3008,13 +3008,17 @@ def _feedback_values(
|
|
|
3008
3008
|
int(feedback.reaction_pulse_enabled),
|
|
3009
3009
|
int(feedback.progress_card_enabled),
|
|
3010
3010
|
int(feedback.completion_mention_enabled),
|
|
3011
|
-
json.dumps(
|
|
3011
|
+
json.dumps(
|
|
3012
|
+
feedback.progress_card_settings.to_dict() if feedback.progress_card_settings is not None else None,
|
|
3013
|
+
separators=(",", ":"),
|
|
3014
|
+
),
|
|
3012
3015
|
)
|
|
3013
3016
|
|
|
3014
3017
|
|
|
3015
|
-
def _progress_card_settings(raw: str) -> ProgressCardSettings:
|
|
3018
|
+
def _progress_card_settings(raw: str) -> ProgressCardSettings | None:
|
|
3016
3019
|
try:
|
|
3017
|
-
|
|
3020
|
+
value = json.loads(raw)
|
|
3021
|
+
return ProgressCardSettings.from_dict(value) if value is not None else None
|
|
3018
3022
|
except (TypeError, ValueError) as error:
|
|
3019
3023
|
raise RuntimeError("Binding contains invalid progress card settings") from error
|
|
3020
3024
|
|